using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Dynamic; using System.Linq.Expressions; using System.Runtime.Remoting; using System.Security.Permissions; using AspClassic.Scripting.Runtime; using AspClassic.Scripting.Utils; namespace AspClassic.Scripting.Hosting; [DebuggerTypeProxy(typeof(DebugView))] public sealed class ScriptScope : MarshalByRefObject, IDynamicMetaObjectProvider { internal sealed class DebugView { private readonly ScriptScope _scope; public ScriptEngine Language => _scope._engine; public Hashtable Variables { get { Hashtable hashtable = new Hashtable(); foreach (KeyValuePair item in _scope.GetItems()) { hashtable[item.Key] = item.Value; } return hashtable; } } public DebugView(ScriptScope scope) { _scope = scope; } } private sealed class Meta : DynamicMetaObject { internal Meta(Expression parameter, ScriptScope scope) : base(parameter, BindingRestrictions.Empty, scope) { } public override DynamicMetaObject BindGetMember(GetMemberBinder action) { ParameterExpression parameterExpression = Expression.Variable(typeof(object), "result"); DynamicMetaObject dynamicMetaObject = action.FallbackGetMember(this); return new DynamicMetaObject(Expression.Block(new ParameterExpression[1] { parameterExpression }, Expression.Condition(Expression.Call(Expression.Convert(base.Expression, typeof(ScriptScope)), typeof(ScriptScope).GetMethod("TryGetVariable", new Type[2] { typeof(string), typeof(object).MakeByRefType() }), Expression.Constant(action.Name), parameterExpression), parameterExpression, Expression.Convert(dynamicMetaObject.Expression, typeof(object)))), BindingRestrictions.GetTypeRestriction(base.Expression, typeof(ScriptScope)).Merge(dynamicMetaObject.Restrictions)); } public override DynamicMetaObject BindSetMember(SetMemberBinder action, DynamicMetaObject value) { Expression arg = Expression.Convert(value.Expression, typeof(object)); return new DynamicMetaObject(Expression.Block(Expression.Call(Expression.Convert(base.Expression, typeof(ScriptScope)), typeof(ScriptScope).GetMethod("SetVariable", new Type[2] { typeof(string), typeof(object) }), Expression.Constant(action.Name), arg), arg), base.Restrictions.Merge(value.Restrictions).Merge(BindingRestrictions.GetTypeRestriction(base.Expression, typeof(ScriptScope)))); } public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder action) { DynamicMetaObject dynamicMetaObject = action.FallbackDeleteMember(this); return new DynamicMetaObject(Expression.IfThenElse(Expression.Call(Expression.Convert(base.Expression, typeof(ScriptScope)), typeof(ScriptScope).GetMethod("RemoveVariable"), Expression.Constant(action.Name)), Expression.Empty(), dynamicMetaObject.Expression), base.Restrictions.Merge(BindingRestrictions.GetTypeRestriction(base.Expression, typeof(ScriptScope))).Merge(dynamicMetaObject.Restrictions)); } public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder action, DynamicMetaObject[] args) { DynamicMetaObject dynamicMetaObject = action.FallbackInvokeMember(this, args); ParameterExpression parameterExpression = Expression.Variable(typeof(object), "result"); DynamicMetaObject dynamicMetaObject2 = action.FallbackInvoke(new DynamicMetaObject(parameterExpression, BindingRestrictions.Empty), args, null); return new DynamicMetaObject(Expression.Block(new ParameterExpression[1] { parameterExpression }, Expression.Condition(Expression.Call(Expression.Convert(base.Expression, typeof(ScriptScope)), typeof(ScriptScope).GetMethod("TryGetVariable", new Type[2] { typeof(string), typeof(object).MakeByRefType() }), Expression.Constant(action.Name), parameterExpression), Expression.Convert(dynamicMetaObject2.Expression, typeof(object)), Expression.Convert(dynamicMetaObject.Expression, typeof(object)))), BindingRestrictions.Combine(args).Merge(BindingRestrictions.GetTypeRestriction(base.Expression, typeof(ScriptScope))).Merge(dynamicMetaObject.Restrictions)); } public override IEnumerable GetDynamicMemberNames() { return ((ScriptScope)base.Value).GetVariableNames(); } } private readonly Scope _scope; private readonly ScriptEngine _engine; internal Scope Scope => _scope; public ScriptEngine Engine => _engine; public ScriptScope(ScriptEngine engine, Scope scope) { _scope = scope; _engine = engine; } public dynamic GetVariable(string name) { return _engine.LanguageContext.ScopeGetVariable(Scope, name); } public T GetVariable(string name) { return _engine.LanguageContext.ScopeGetVariable(Scope, name); } public bool TryGetVariable(string name, out dynamic value) { return _engine.LanguageContext.ScopeTryGetVariable(Scope, name, out value); } public bool TryGetVariable(string name, out T value) { if (_engine.LanguageContext.ScopeTryGetVariable(Scope, name, out var value2)) { value = _engine.Operations.ConvertTo(value2); return true; } value = default(T); return false; } public void SetVariable(string name, object value) { _engine.LanguageContext.ScopeSetVariable(Scope, name, value); } public ObjectHandle GetVariableHandle(string name) { return new ObjectHandle((object)GetVariable(name)); } public bool TryGetVariableHandle(string name, out ObjectHandle handle) { if (TryGetVariable(name, out var value)) { handle = new ObjectHandle(value); return true; } handle = null; return false; } public void SetVariable(string name, ObjectHandle handle) { ContractUtils.RequiresNotNull(handle, "handle"); SetVariable(name, handle.Unwrap()); } public bool ContainsVariable(string name) { object value; return TryGetVariable(name, out value); } public bool RemoveVariable(string name) { if (_engine.Operations.ContainsMember(_scope, name)) { _engine.Operations.RemoveMember(_scope, name); return true; } return false; } public IEnumerable GetVariableNames() { return _engine.Operations.GetMemberNames((object)_scope.Storage); } public IEnumerable> GetItems() { List> list = new List>(); foreach (string variableName in GetVariableNames()) { list.Add(new KeyValuePair(variableName, (object)_engine.Operations.GetMember((object)_scope.Storage, variableName))); } list.TrimExcess(); return list; } DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) { return new Meta(parameter, this); } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)] public override object InitializeLifetimeService() { return null; } }