203 lines
6.7 KiB
C#
203 lines
6.7 KiB
C#
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<string, object> 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<string> 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<T>(string name)
|
|
{
|
|
return _engine.LanguageContext.ScopeGetVariable<T>(Scope, name);
|
|
}
|
|
|
|
public bool TryGetVariable(string name, out dynamic value)
|
|
{
|
|
return _engine.LanguageContext.ScopeTryGetVariable(Scope, name, out value);
|
|
}
|
|
|
|
public bool TryGetVariable<T>(string name, out T value)
|
|
{
|
|
if (_engine.LanguageContext.ScopeTryGetVariable(Scope, name, out var value2))
|
|
{
|
|
value = _engine.Operations.ConvertTo<T>(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<string> GetVariableNames()
|
|
{
|
|
return _engine.Operations.GetMemberNames((object)_scope.Storage);
|
|
}
|
|
|
|
public IEnumerable<KeyValuePair<string, object>> GetItems()
|
|
{
|
|
List<KeyValuePair<string, object>> list = new List<KeyValuePair<string, object>>();
|
|
foreach (string variableName in GetVariableNames())
|
|
{
|
|
list.Add(new KeyValuePair<string, object>(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;
|
|
}
|
|
}
|