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(string expression) { return Operations.ConvertTo((object)Execute(expression)); } public T Execute(string expression, ScriptScope scope) { return Operations.ConvertTo((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 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")] public T GetVariable(ScriptScope scope, string name) { ContractUtils.RequiresNotNull(scope, "scope"); ContractUtils.RequiresNotNull(name, "name"); return Operations.ConvertTo((object)GetVariable(scope, name)); } [Obsolete("Use ScriptScope.GetVariable 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")] public bool TryGetVariable(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(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(params object[] args) where TService : class { if (typeof(TService) == typeof(TokenCategorizer)) { TokenizerService service = _language.GetService(ArrayUtils.Insert(_language, args)); if (service == null) { return null; } return (TService)(object)new TokenCategorizer(service); } if (typeof(TService) == typeof(ExceptionOperations)) { ExceptionOperations service2 = _language.GetService(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(args); if (service3 == null) { return null; } return (TService)(object)new DocumentationOperations(service3); } return _language.GetService(args); } public CompilerOptions GetCompilerOptions() { return _language.GetCompilerOptions(); } public CompilerOptions GetCompilerOptions(ScriptScope scope) { return _language.GetCompilerOptions(scope.Scope); } public void SetSearchPaths(ICollection paths) { ContractUtils.RequiresNotNull(paths, "paths"); ContractUtils.RequiresNotNullItems(paths, "paths"); _language.SetSearchPaths(paths); } public ICollection GetSearchPaths() { return _language.GetSearchPaths(); } internal TRet Call(Func f, T arg) { return f(_language, arg); } [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)] public override object InitializeLifetimeService() { return null; } }