progress
This commit is contained in:
parent
16e76d6b31
commit
484dbfc9d9
529 changed files with 113694 additions and 0 deletions
309
AspClassic.Scripting/Hosting/ScriptRuntime.cs
Normal file
309
AspClassic.Scripting/Hosting/ScriptRuntime.cs
Normal file
|
@ -0,0 +1,309 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Dynamic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Security.Permissions;
|
||||
using System.Threading;
|
||||
using AspClassic.Scripting.Runtime;
|
||||
using AspClassic.Scripting.Utils;
|
||||
|
||||
namespace AspClassic.Scripting.Hosting;
|
||||
|
||||
public sealed class ScriptRuntime : MarshalByRefObject
|
||||
{
|
||||
private readonly Dictionary<LanguageContext, ScriptEngine> _engines;
|
||||
|
||||
private readonly ScriptDomainManager _manager;
|
||||
|
||||
private readonly InvariantContext _invariantContext;
|
||||
|
||||
private readonly ScriptIO _io;
|
||||
|
||||
private readonly ScriptHost _host;
|
||||
|
||||
private readonly ScriptRuntimeSetup _setup;
|
||||
|
||||
private readonly object _lock = new object();
|
||||
|
||||
private ScriptScope _globals;
|
||||
|
||||
private Scope _scopeGlobals;
|
||||
|
||||
private ScriptEngine _invariantEngine;
|
||||
|
||||
internal ScriptDomainManager Manager => _manager;
|
||||
|
||||
public ScriptHost Host => _host;
|
||||
|
||||
public ScriptIO IO => _io;
|
||||
|
||||
public ScriptRuntimeSetup Setup => _setup;
|
||||
|
||||
public ScriptScope Globals
|
||||
{
|
||||
get
|
||||
{
|
||||
Scope globals = _manager.Globals;
|
||||
if (_scopeGlobals == globals)
|
||||
{
|
||||
return _globals;
|
||||
}
|
||||
lock (_lock)
|
||||
{
|
||||
if (_scopeGlobals != globals)
|
||||
{
|
||||
_globals = new ScriptScope(InvariantEngine, globals);
|
||||
_scopeGlobals = globals;
|
||||
}
|
||||
return _globals;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
ContractUtils.RequiresNotNull(value, "value");
|
||||
lock (_lock)
|
||||
{
|
||||
_globals = value;
|
||||
_manager.Globals = value.Scope;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ObjectOperations Operations => InvariantEngine.Operations;
|
||||
|
||||
internal ScriptEngine InvariantEngine
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_invariantEngine == null)
|
||||
{
|
||||
_invariantEngine = GetEngine(_invariantContext);
|
||||
}
|
||||
return _invariantEngine;
|
||||
}
|
||||
}
|
||||
|
||||
public ScriptRuntime(ScriptRuntimeSetup setup)
|
||||
{
|
||||
ContractUtils.RequiresNotNull(setup, "setup");
|
||||
DlrConfiguration configuration = setup.ToConfiguration();
|
||||
_setup = setup;
|
||||
try
|
||||
{
|
||||
_host = (ScriptHost)Activator.CreateInstance(setup.HostType, Utils.CollectionExtensions.ToArray(setup.HostArguments));
|
||||
}
|
||||
catch (TargetInvocationException ex)
|
||||
{
|
||||
throw new InvalidImplementationException(Strings.InvalidCtorImplementation(setup.HostType, ex.InnerException.Message), ex.InnerException);
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
throw new InvalidImplementationException(Strings.InvalidCtorImplementation(setup.HostType, ex2.Message), ex2);
|
||||
}
|
||||
ScriptHostProxy hostingProvider = new ScriptHostProxy(_host);
|
||||
_manager = new ScriptDomainManager(hostingProvider, configuration);
|
||||
_invariantContext = new InvariantContext(_manager);
|
||||
_io = new ScriptIO(_manager.SharedIO);
|
||||
_engines = new Dictionary<LanguageContext, ScriptEngine>();
|
||||
_globals = new ScriptScope(GetEngineNoLockNoNotification(_invariantContext, out var _), _manager.Globals);
|
||||
_host.SetRuntime(this);
|
||||
if (!setup.Options.TryGetValue("NoDefaultReferences", out var value) || !Convert.ToBoolean(value))
|
||||
{
|
||||
LoadAssembly(typeof(string).Assembly);
|
||||
LoadAssembly(typeof(Debug).Assembly);
|
||||
}
|
||||
}
|
||||
|
||||
public static ScriptRuntime CreateFromConfiguration()
|
||||
{
|
||||
return new ScriptRuntime(ScriptRuntimeSetup.ReadConfiguration());
|
||||
}
|
||||
|
||||
public static ScriptRuntime CreateRemote(AppDomain domain, ScriptRuntimeSetup setup)
|
||||
{
|
||||
ContractUtils.RequiresNotNull(domain, "domain");
|
||||
return (ScriptRuntime)domain.CreateInstanceAndUnwrap(typeof(ScriptRuntime).Assembly.FullName, typeof(ScriptRuntime).FullName, ignoreCase: false, BindingFlags.Default, null, new object[1] { setup }, null, null);
|
||||
}
|
||||
|
||||
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
|
||||
public override object InitializeLifetimeService()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public ScriptEngine GetEngine(string languageName)
|
||||
{
|
||||
ContractUtils.RequiresNotNull(languageName, "languageName");
|
||||
if (!TryGetEngine(languageName, out var engine))
|
||||
{
|
||||
throw new ArgumentException($"Unknown language name: '{languageName}'");
|
||||
}
|
||||
return engine;
|
||||
}
|
||||
|
||||
public ScriptEngine GetEngineByTypeName(string assemblyQualifiedTypeName)
|
||||
{
|
||||
ContractUtils.RequiresNotNull(assemblyQualifiedTypeName, "assemblyQualifiedTypeName");
|
||||
return GetEngine(_manager.GetLanguageByTypeName(assemblyQualifiedTypeName));
|
||||
}
|
||||
|
||||
public ScriptEngine GetEngineByFileExtension(string fileExtension)
|
||||
{
|
||||
ContractUtils.RequiresNotNull(fileExtension, "fileExtension");
|
||||
if (!TryGetEngineByFileExtension(fileExtension, out var engine))
|
||||
{
|
||||
throw new ArgumentException($"Unknown file extension: '{fileExtension}'");
|
||||
}
|
||||
return engine;
|
||||
}
|
||||
|
||||
public bool TryGetEngine(string languageName, out ScriptEngine engine)
|
||||
{
|
||||
if (!_manager.TryGetLanguage(languageName, out var language))
|
||||
{
|
||||
engine = null;
|
||||
return false;
|
||||
}
|
||||
engine = GetEngine(language);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryGetEngineByFileExtension(string fileExtension, out ScriptEngine engine)
|
||||
{
|
||||
if (!_manager.TryGetLanguageByFileExtension(fileExtension, out var language))
|
||||
{
|
||||
engine = null;
|
||||
return false;
|
||||
}
|
||||
engine = GetEngine(language);
|
||||
return true;
|
||||
}
|
||||
|
||||
internal ScriptEngine GetEngine(LanguageContext language)
|
||||
{
|
||||
ScriptEngine engineNoLockNoNotification;
|
||||
bool freshEngineCreated;
|
||||
lock (_engines)
|
||||
{
|
||||
engineNoLockNoNotification = GetEngineNoLockNoNotification(language, out freshEngineCreated);
|
||||
}
|
||||
if (freshEngineCreated && !object.ReferenceEquals(language, _invariantContext))
|
||||
{
|
||||
_host.EngineCreated(engineNoLockNoNotification);
|
||||
}
|
||||
return engineNoLockNoNotification;
|
||||
}
|
||||
|
||||
private ScriptEngine GetEngineNoLockNoNotification(LanguageContext language, out bool freshEngineCreated)
|
||||
{
|
||||
if (freshEngineCreated = !_engines.TryGetValue(language, out var value))
|
||||
{
|
||||
value = new ScriptEngine(this, language);
|
||||
Thread.MemoryBarrier();
|
||||
_engines.Add(language, value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public ScriptScope CreateScope()
|
||||
{
|
||||
return InvariantEngine.CreateScope();
|
||||
}
|
||||
|
||||
public ScriptScope CreateScope(string languageId)
|
||||
{
|
||||
return GetEngine(languageId).CreateScope();
|
||||
}
|
||||
|
||||
public ScriptScope CreateScope(IDynamicMetaObjectProvider storage)
|
||||
{
|
||||
return InvariantEngine.CreateScope(storage);
|
||||
}
|
||||
|
||||
public ScriptScope CreateScope(string languageId, IDynamicMetaObjectProvider storage)
|
||||
{
|
||||
return GetEngine(languageId).CreateScope(storage);
|
||||
}
|
||||
|
||||
[Obsolete("IAttributesCollection is obsolete, use CreateScope(IDynamicMetaObjectProvider) instead")]
|
||||
public ScriptScope CreateScope(IAttributesCollection dictionary)
|
||||
{
|
||||
return InvariantEngine.CreateScope(dictionary);
|
||||
}
|
||||
|
||||
[Obsolete("IAttributesCollection is obsolete, use CreateScope(string, IDynamicMetaObjectProvider) instead")]
|
||||
public ScriptScope CreateScope(string languageId, IAttributesCollection storage)
|
||||
{
|
||||
return GetEngine(languageId).CreateScope(storage);
|
||||
}
|
||||
|
||||
public ScriptScope ExecuteFile(string path)
|
||||
{
|
||||
ContractUtils.RequiresNotEmpty(path, "path");
|
||||
string extension = Path.GetExtension(path);
|
||||
if (!TryGetEngineByFileExtension(extension, out var engine))
|
||||
{
|
||||
throw new ArgumentException($"File extension '{extension}' is not associated with any language.");
|
||||
}
|
||||
return engine.ExecuteFile(path);
|
||||
}
|
||||
|
||||
public ScriptScope UseFile(string path)
|
||||
{
|
||||
ContractUtils.RequiresNotEmpty(path, "path");
|
||||
string extension = Path.GetExtension(path);
|
||||
if (!TryGetEngineByFileExtension(extension, out var engine))
|
||||
{
|
||||
throw new ArgumentException($"File extension '{extension}' is not associated with any language.");
|
||||
}
|
||||
ICollection<string> searchPaths = engine.GetSearchPaths();
|
||||
if (searchPaths.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException($"No search paths defined for language '{engine.Setup.DisplayName}'");
|
||||
}
|
||||
foreach (string item in searchPaths)
|
||||
{
|
||||
string path2 = Path.Combine(item, path);
|
||||
ScriptScope scope = engine.GetScope(path2);
|
||||
if (scope != null)
|
||||
{
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
foreach (string item2 in searchPaths)
|
||||
{
|
||||
string path3 = Path.Combine(item2, path);
|
||||
if (_manager.Platform.FileExists(path3))
|
||||
{
|
||||
return ExecuteFile(path3);
|
||||
}
|
||||
}
|
||||
string arg = Utils.CollectionExtensions.Aggregate(searchPaths ,(string x, string y) => x + ", " + y);
|
||||
throw new FileNotFoundException($"File '{path}' not found in language's search path: {arg}");
|
||||
}
|
||||
|
||||
public void LoadAssembly(Assembly assembly)
|
||||
{
|
||||
_manager.LoadAssembly(assembly);
|
||||
}
|
||||
|
||||
public ObjectOperations CreateOperations()
|
||||
{
|
||||
return InvariantEngine.CreateOperations();
|
||||
}
|
||||
|
||||
public void Shutdown()
|
||||
{
|
||||
List<LanguageContext> list;
|
||||
lock (_engines)
|
||||
{
|
||||
list = new List<LanguageContext>(_engines.Keys);
|
||||
}
|
||||
foreach (LanguageContext item in list)
|
||||
{
|
||||
item.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue