aspclassic-core/AspClassic.Scripting/Hosting/ScriptEngine.cs
Jelle Luteijn 484dbfc9d9 progress
2022-05-15 11:19:49 +02:00

439 lines
13 KiB
C#

using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Diagnostics;
using System.Dynamic;
using System.Runtime.Remoting;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using AspClassic.Scripting.Runtime;
using AspClassic.Scripting.Utils;
namespace AspClassic.Scripting.Hosting;
[DebuggerDisplay("{Setup.DisplayName}")]
public sealed class ScriptEngine : MarshalByRefObject
{
private readonly LanguageContext _language;
private readonly ScriptRuntime _runtime;
private LanguageSetup _config;
private ObjectOperations _operations;
public ObjectOperations Operations
{
get
{
if (_operations == null)
{
Interlocked.CompareExchange(ref _operations, CreateOperations(), null);
}
return _operations;
}
}
public LanguageSetup Setup
{
get
{
if (_config == null)
{
LanguageConfiguration languageConfig = _runtime.Manager.Configuration.GetLanguageConfig(_language);
foreach (LanguageSetup languageSetup in _runtime.Setup.LanguageSetups)
{
if (languageConfig.ProviderName == new AssemblyQualifiedTypeName(languageSetup.TypeName))
{
return _config = languageSetup;
}
}
}
return _config;
}
}
public ScriptRuntime Runtime => _runtime;
public Version LanguageVersion => _language.LanguageVersion;
internal LanguageContext LanguageContext => _language;
internal ScriptEngine(ScriptRuntime runtime, LanguageContext context)
{
_runtime = runtime;
_language = context;
}
public ObjectOperations CreateOperations()
{
return new ObjectOperations(new DynamicOperations(_language), this);
}
public ObjectOperations CreateOperations(ScriptScope scope)
{
ContractUtils.RequiresNotNull(scope, "scope");
return new ObjectOperations(_language.Operations, this);
}
public dynamic Execute(string expression)
{
return CreateScriptSourceFromString(expression).Execute();
}
public dynamic Execute(string expression, ScriptScope scope)
{
return CreateScriptSourceFromString(expression).Execute(scope);
}
public T Execute<T>(string expression)
{
return Operations.ConvertTo<T>((object)Execute(expression));
}
public T Execute<T>(string expression, ScriptScope scope)
{
return Operations.ConvertTo<T>((object)Execute(expression, scope));
}
public ScriptScope ExecuteFile(string path)
{
return ExecuteFile(path, CreateScope());
}
public ScriptScope ExecuteFile(string path, ScriptScope scope)
{
CreateScriptSourceFromFile(path).Execute(scope);
return scope;
}
public ObjectHandle ExecuteAndWrap(string expression, ScriptScope scope)
{
return new ObjectHandle((object)Execute(expression, scope));
}
public ObjectHandle ExecuteAndWrap(string expression)
{
return new ObjectHandle((object)Execute(expression));
}
public ObjectHandle ExecuteAndWrap(string expression, ScriptScope scope, out ObjectHandle exception)
{
exception = null;
try
{
return new ObjectHandle((object)Execute(expression, scope));
}
catch (Exception o)
{
exception = new ObjectHandle(o);
return null;
}
}
public ObjectHandle ExecuteAndWrap(string expression, out ObjectHandle exception)
{
exception = null;
try
{
return new ObjectHandle((object)Execute(expression));
}
catch (Exception o)
{
exception = new ObjectHandle(o);
return null;
}
}
public ScriptScope CreateScope()
{
return new ScriptScope(this, new Scope());
}
[Obsolete("IAttributesCollection is obsolete, use CreateScope(IDynamicMetaObjectProvider) instead")]
public ScriptScope CreateScope(IAttributesCollection dictionary)
{
ContractUtils.RequiresNotNull(dictionary, "dictionary");
return new ScriptScope(this, new Scope(dictionary));
}
public ScriptScope CreateScope(IDynamicMetaObjectProvider storage)
{
ContractUtils.RequiresNotNull(storage, "storage");
return new ScriptScope(this, new Scope(storage));
}
public ScriptScope GetScope(string path)
{
ContractUtils.RequiresNotNull(path, "path");
Scope scope = _language.GetScope(path);
if (scope == null)
{
return null;
}
return new ScriptScope(this, scope);
}
public ScriptSource CreateScriptSourceFromString(string expression)
{
ContractUtils.RequiresNotNull(expression, "expression");
return CreateScriptSource(new SourceStringContentProvider(expression), null, SourceCodeKind.AutoDetect);
}
public ScriptSource CreateScriptSourceFromString(string code, SourceCodeKind kind)
{
ContractUtils.RequiresNotNull(code, "code");
ContractUtils.Requires(kind.IsValid(), "kind");
return CreateScriptSource(new SourceStringContentProvider(code), null, kind);
}
public ScriptSource CreateScriptSourceFromString(string expression, string path)
{
ContractUtils.RequiresNotNull(expression, "expression");
return CreateScriptSource(new SourceStringContentProvider(expression), path, SourceCodeKind.AutoDetect);
}
public ScriptSource CreateScriptSourceFromString(string code, string path, SourceCodeKind kind)
{
ContractUtils.RequiresNotNull(code, "code");
ContractUtils.Requires(kind.IsValid(), "kind");
return CreateScriptSource(new SourceStringContentProvider(code), path, kind);
}
public ScriptSource CreateScriptSourceFromFile(string path)
{
return CreateScriptSourceFromFile(path, StringUtils.DefaultEncoding, SourceCodeKind.File);
}
public ScriptSource CreateScriptSourceFromFile(string path, Encoding encoding)
{
return CreateScriptSourceFromFile(path, encoding, SourceCodeKind.File);
}
public ScriptSource CreateScriptSourceFromFile(string path, Encoding encoding, SourceCodeKind kind)
{
ContractUtils.RequiresNotNull(path, "path");
ContractUtils.RequiresNotNull(encoding, "encoding");
ContractUtils.Requires(kind.IsValid(), "kind");
if (!_language.CanCreateSourceCode)
{
throw new NotSupportedException("Invariant engine cannot create scripts");
}
return new ScriptSource(this, _language.CreateFileUnit(path, encoding, kind));
}
public ScriptSource CreateScriptSource(CodeObject content)
{
return CreateScriptSource(content, null, SourceCodeKind.File);
}
public ScriptSource CreateScriptSource(CodeObject content, string path)
{
return CreateScriptSource(content, path, SourceCodeKind.File);
}
public ScriptSource CreateScriptSource(CodeObject content, SourceCodeKind kind)
{
return CreateScriptSource(content, null, kind);
}
public ScriptSource CreateScriptSource(CodeObject content, string path, SourceCodeKind kind)
{
ContractUtils.RequiresNotNull(content, "content");
if (!_language.CanCreateSourceCode)
{
throw new NotSupportedException("Invariant engine cannot create scripts");
}
return new ScriptSource(this, _language.GenerateSourceCode(content, path, kind));
}
public ScriptSource CreateScriptSource(StreamContentProvider content, string path)
{
ContractUtils.RequiresNotNull(content, "content");
return CreateScriptSource(content, path, StringUtils.DefaultEncoding, SourceCodeKind.File);
}
public ScriptSource CreateScriptSource(StreamContentProvider content, string path, Encoding encoding)
{
ContractUtils.RequiresNotNull(content, "content");
ContractUtils.RequiresNotNull(encoding, "encoding");
return CreateScriptSource(content, path, encoding, SourceCodeKind.File);
}
public ScriptSource CreateScriptSource(StreamContentProvider content, string path, Encoding encoding, SourceCodeKind kind)
{
ContractUtils.RequiresNotNull(content, "content");
ContractUtils.RequiresNotNull(encoding, "encoding");
ContractUtils.Requires(kind.IsValid(), "kind");
return CreateScriptSource(new LanguageBoundTextContentProvider(_language, content, encoding, path), path, kind);
}
public ScriptSource CreateScriptSource(TextContentProvider contentProvider, string path, SourceCodeKind kind)
{
ContractUtils.RequiresNotNull(contentProvider, "contentProvider");
ContractUtils.Requires(kind.IsValid(), "kind");
if (!_language.CanCreateSourceCode)
{
throw new NotSupportedException("Invariant engine cannot create scripts");
}
return new ScriptSource(this, _language.CreateSourceUnit(contentProvider, path, kind));
}
[Obsolete("Use ScriptScope.GetVariable instead")]
public dynamic GetVariable(ScriptScope scope, string name)
{
ContractUtils.RequiresNotNull(scope, "scope");
ContractUtils.RequiresNotNull(name, "name");
return scope.GetVariable(name);
}
[Obsolete("Use ScriptScope.RemoveVariable instead")]
public bool RemoveVariable(ScriptScope scope, string name)
{
ContractUtils.RequiresNotNull(scope, "scope");
ContractUtils.RequiresNotNull(name, "name");
return scope.RemoveVariable(name);
}
[Obsolete("Use ScriptScope.SetVariable instead")]
public void SetVariable(ScriptScope scope, string name, object value)
{
ContractUtils.RequiresNotNull(scope, "scope");
ContractUtils.RequiresNotNull(name, "name");
scope.SetVariable(name, value);
}
[Obsolete("Use ScriptScope.TryGetVariable instead")]
public bool TryGetVariable(ScriptScope scope, string name, out object value)
{
ContractUtils.RequiresNotNull(scope, "scope");
ContractUtils.RequiresNotNull(name, "name");
return scope.TryGetVariable(name, out value);
}
[Obsolete("Use ScriptScope.GetVariable<T> instead. If the target scope is not bound to any language or you need control over the conversion use ScriptScope.GetVariable and ScriptEngine.Operations.ConvertTo<T>")]
public T GetVariable<T>(ScriptScope scope, string name)
{
ContractUtils.RequiresNotNull(scope, "scope");
ContractUtils.RequiresNotNull(name, "name");
return Operations.ConvertTo<T>((object)GetVariable(scope, name));
}
[Obsolete("Use ScriptScope.GetVariable<T> instead. If the target scope is not bound to any language or you need control over the conversion use ScriptScope.GetVariable and ScriptEngine.Operations.ConvertTo<T>")]
public bool TryGetVariable<T>(ScriptScope scope, string name, out T value)
{
ContractUtils.RequiresNotNull(scope, "scope");
ContractUtils.RequiresNotNull(name, "name");
if (TryGetVariable(scope, name, out var value2))
{
return Operations.TryConvertTo<T>(value2, out value);
}
value = default(T);
return false;
}
[Obsolete("Use ScriptScope.ContainsVariable instead")]
public bool ContainsVariable(ScriptScope scope, string name)
{
ContractUtils.RequiresNotNull(scope, "scope");
ContractUtils.RequiresNotNull(name, "name");
object value;
return TryGetVariable(scope, name, out value);
}
[Obsolete("Use ScriptScope.GetVariableHandle instead")]
public ObjectHandle GetVariableHandle(ScriptScope scope, string name)
{
ContractUtils.RequiresNotNull(scope, "scope");
ContractUtils.RequiresNotNull(name, "name");
return new ObjectHandle((object)GetVariable(scope, name));
}
[Obsolete("Use ScriptScope.SetVariable instead")]
public void SetVariable(ScriptScope scope, string name, ObjectHandle value)
{
ContractUtils.RequiresNotNull(scope, "scope");
ContractUtils.RequiresNotNull(name, "name");
SetVariable(scope, name, value.Unwrap());
}
[Obsolete("Use ScriptScope.TryGetVariableHandle instead")]
public bool TryGetVariableHandle(ScriptScope scope, string name, out ObjectHandle value)
{
ContractUtils.RequiresNotNull(scope, "scope");
ContractUtils.RequiresNotNull(name, "name");
if (TryGetVariable(scope, name, out var value2))
{
value = new ObjectHandle(value2);
return true;
}
value = null;
return false;
}
public TService GetService<TService>(params object[] args) where TService : class
{
if (typeof(TService) == typeof(TokenCategorizer))
{
TokenizerService service = _language.GetService<TokenizerService>(ArrayUtils.Insert(_language, args));
if (service == null)
{
return null;
}
return (TService)(object)new TokenCategorizer(service);
}
if (typeof(TService) == typeof(ExceptionOperations))
{
ExceptionOperations service2 = _language.GetService<ExceptionOperations>(new object[0]);
if (service2 == null)
{
return (TService)(object)new ExceptionOperations(_language);
}
return (TService)(object)service2;
}
if (typeof(TService) == typeof(DocumentationOperations))
{
DocumentationProvider service3 = _language.GetService<DocumentationProvider>(args);
if (service3 == null)
{
return null;
}
return (TService)(object)new DocumentationOperations(service3);
}
return _language.GetService<TService>(args);
}
public CompilerOptions GetCompilerOptions()
{
return _language.GetCompilerOptions();
}
public CompilerOptions GetCompilerOptions(ScriptScope scope)
{
return _language.GetCompilerOptions(scope.Scope);
}
public void SetSearchPaths(ICollection<string> paths)
{
ContractUtils.RequiresNotNull(paths, "paths");
ContractUtils.RequiresNotNullItems(paths, "paths");
_language.SetSearchPaths(paths);
}
public ICollection<string> GetSearchPaths()
{
return _language.GetSearchPaths();
}
internal TRet Call<T, TRet>(Func<LanguageContext, T, TRet> f, T arg)
{
return f(_language, arg);
}
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
public override object InitializeLifetimeService()
{
return null;
}
}