|
@@ -1,4 +1,6 @@
|
|
-using System;
|
|
|
|
|
|
+#nullable enable
|
|
|
|
+
|
|
|
|
+using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Generic;
|
|
using System.Dynamic;
|
|
using System.Dynamic;
|
|
using System.Globalization;
|
|
using System.Globalization;
|
|
@@ -10,94 +12,96 @@ using Jint.Runtime;
|
|
using Jint.Runtime.Interop;
|
|
using Jint.Runtime.Interop;
|
|
using Jint.Runtime.Debugger;
|
|
using Jint.Runtime.Debugger;
|
|
using Jint.Runtime.Descriptors;
|
|
using Jint.Runtime.Descriptors;
|
|
-using Jint.Runtime.Interop.Reflection;
|
|
|
|
-using Jint.Runtime.References;
|
|
|
|
|
|
|
|
namespace Jint
|
|
namespace Jint
|
|
{
|
|
{
|
|
- public delegate JsValue MemberAccessorDelegate(Engine engine, object target, string member);
|
|
|
|
|
|
+ public delegate JsValue? MemberAccessorDelegate(Engine engine, object target, string member);
|
|
|
|
+
|
|
|
|
+ public delegate ObjectInstance? WrapObjectDelegate(Engine engine, object target);
|
|
|
|
+
|
|
|
|
+ public delegate bool ExceptionHandlerDelegate(Exception exception);
|
|
|
|
|
|
- public sealed class Options
|
|
|
|
|
|
+ public class Options
|
|
{
|
|
{
|
|
- private readonly List<IConstraint> _constraints = new();
|
|
|
|
- private bool _strict;
|
|
|
|
- private DebuggerStatementHandling _debuggerStatementHandling;
|
|
|
|
- private bool _allowClr;
|
|
|
|
- private bool _allowClrWrite = true;
|
|
|
|
- private bool _allowOperatorOverloading;
|
|
|
|
- private readonly List<IObjectConverter> _objectConverters = new();
|
|
|
|
- private Func<Engine, object, ObjectInstance> _wrapObjectHandler;
|
|
|
|
- private MemberAccessorDelegate _memberAccessor;
|
|
|
|
- private int _maxRecursionDepth = -1;
|
|
|
|
- private TimeSpan _regexTimeoutInterval = TimeSpan.FromSeconds(10);
|
|
|
|
- private CultureInfo _culture = CultureInfo.CurrentCulture;
|
|
|
|
- private TimeZoneInfo _localTimeZone = TimeZoneInfo.Local;
|
|
|
|
- private List<Assembly> _lookupAssemblies = new();
|
|
|
|
- private Predicate<Exception> _clrExceptionsHandler;
|
|
|
|
- private IReferenceResolver _referenceResolver = DefaultReferenceResolver.Instance;
|
|
|
|
- private TypeResolver _typeResolver = TypeResolver.Default;
|
|
|
|
- private readonly List<Action<Engine>> _configurations = new();
|
|
|
|
-
|
|
|
|
- private readonly List<Type> _extensionMethodClassTypes = new();
|
|
|
|
- internal ExtensionMethodCache _extensionMethods = ExtensionMethodCache.Empty;
|
|
|
|
- internal Func<Engine, Host> _hostFactory = _ => new Host();
|
|
|
|
|
|
+ internal List<Action<Engine>> _configurations { get; } = new();
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// Run the script in strict mode.
|
|
|
|
|
|
+ /// Execution constraints for the engine.
|
|
/// </summary>
|
|
/// </summary>
|
|
- public Options Strict(bool strict = true)
|
|
|
|
- {
|
|
|
|
- _strict = strict;
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ public ConstraintOptions Constraints { get; } = new();
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// Selects the handling for script <code>debugger</code> statements.
|
|
|
|
|
|
+ /// CLR interop related options.
|
|
/// </summary>
|
|
/// </summary>
|
|
- /// <remarks>
|
|
|
|
- /// The <c>debugger</c> statement can either be ignored (default) trigger debugging at CLR level (e.g. Visual Studio),
|
|
|
|
- /// or trigger a break in Jint's DebugHandler.
|
|
|
|
- /// </remarks>
|
|
|
|
- public Options DebuggerStatementHandling(DebuggerStatementHandling debuggerStatementHandling)
|
|
|
|
- {
|
|
|
|
- _debuggerStatementHandling = debuggerStatementHandling;
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ public InteropOptions Interop { get; } = new();
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// Allow to run the script in debug mode.
|
|
|
|
|
|
+ /// Debugger configuration.
|
|
/// </summary>
|
|
/// </summary>
|
|
- public Options DebugMode(bool debugMode = true)
|
|
|
|
- {
|
|
|
|
- IsDebugMode = debugMode;
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ public DebuggerOptions Debugger { get; } = new();
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// Adds a <see cref="IObjectConverter"/> instance to convert CLR types to <see cref="JsValue"/>
|
|
|
|
|
|
+ /// Host options.
|
|
/// </summary>
|
|
/// </summary>
|
|
- public Options AddObjectConverter<T>() where T : IObjectConverter, new()
|
|
|
|
- {
|
|
|
|
- return AddObjectConverter(new T());
|
|
|
|
- }
|
|
|
|
|
|
+ internal HostOptions Host { get; } = new();
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// Adds a <see cref="IObjectConverter"/> instance to convert CLR types to <see cref="JsValue"/>
|
|
|
|
|
|
+ /// Whether the code should be always considered to be in strict mode. Can improve performance.
|
|
/// </summary>
|
|
/// </summary>
|
|
- public Options AddObjectConverter(IObjectConverter objectConverter)
|
|
|
|
- {
|
|
|
|
- _objectConverters.Add(objectConverter);
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ public bool Strict { get; set; }
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// The culture the engine runs on, defaults to current culture.
|
|
|
|
+ /// </summary>
|
|
|
|
+ public CultureInfo Culture { get; set; } = CultureInfo.CurrentCulture;
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// The time zone the engine runs on, defaults to local.
|
|
|
|
+ /// </summary>
|
|
|
|
+ public TimeZoneInfo TimeZone { get; set; } = TimeZoneInfo.Local;
|
|
|
|
|
|
- public Options AddExtensionMethods(params Type[] types)
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Reference resolver allows customizing behavior for reference resolving. This can be useful in cases where
|
|
|
|
+ /// you want to ignore long chain of property accesses that might throw if anything is null or undefined.
|
|
|
|
+ /// An example of such is <code>var a = obj.field.subField.value</code>. Custom resolver could accept chain to return
|
|
|
|
+ /// null/undefined on first occurrence.
|
|
|
|
+ /// </summary>
|
|
|
|
+ public IReferenceResolver ReferenceResolver { get; set; } = DefaultReferenceResolver.Instance;
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Called by the <see cref="Engine"/> instance that loads this <see cref="Options" />
|
|
|
|
+ /// once it is loaded.
|
|
|
|
+ /// </summary>
|
|
|
|
+ internal void Apply(Engine engine)
|
|
{
|
|
{
|
|
- _extensionMethodClassTypes.AddRange(types);
|
|
|
|
- _extensionMethods = ExtensionMethodCache.Build(_extensionMethodClassTypes);
|
|
|
|
- return this;
|
|
|
|
|
|
+ foreach (var configuration in _configurations)
|
|
|
|
+ {
|
|
|
|
+ configuration?.Invoke(engine);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // add missing bits if needed
|
|
|
|
+ if (Interop.Enabled)
|
|
|
|
+ {
|
|
|
|
+ engine.Realm.GlobalObject.SetProperty("System",
|
|
|
|
+ new PropertyDescriptor(new NamespaceReference(engine, "System"), PropertyFlag.AllForbidden));
|
|
|
|
+ engine.Realm.GlobalObject.SetProperty("importNamespace", new PropertyDescriptor(new ClrFunctionInstance(
|
|
|
|
+ engine,
|
|
|
|
+ "importNamespace",
|
|
|
|
+ (thisObj, arguments) =>
|
|
|
|
+ new NamespaceReference(engine, TypeConverter.ToString(arguments.At(0)))),
|
|
|
|
+ PropertyFlag.AllForbidden));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (Interop.ExtensionMethodTypes.Count > 0)
|
|
|
|
+ {
|
|
|
|
+ AttachExtensionMethodsToPrototypes(engine);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // ensure defaults
|
|
|
|
+ engine.ClrTypeConverter ??= new DefaultTypeConverter(engine);
|
|
}
|
|
}
|
|
|
|
|
|
- private void AttachExtensionMethodsToPrototypes(Engine engine)
|
|
|
|
|
|
+ private static void AttachExtensionMethodsToPrototypes(Engine engine)
|
|
{
|
|
{
|
|
AttachExtensionMethodsToPrototype(engine, engine.Realm.Intrinsics.Array.PrototypeObject, typeof(Array));
|
|
AttachExtensionMethodsToPrototype(engine, engine.Realm.Intrinsics.Array.PrototypeObject, typeof(Array));
|
|
AttachExtensionMethodsToPrototype(engine, engine.Realm.Intrinsics.Boolean.PrototypeObject, typeof(bool));
|
|
AttachExtensionMethodsToPrototype(engine, engine.Realm.Intrinsics.Boolean.PrototypeObject, typeof(bool));
|
|
@@ -108,30 +112,30 @@ namespace Jint
|
|
AttachExtensionMethodsToPrototype(engine, engine.Realm.Intrinsics.String.PrototypeObject, typeof(string));
|
|
AttachExtensionMethodsToPrototype(engine, engine.Realm.Intrinsics.String.PrototypeObject, typeof(string));
|
|
}
|
|
}
|
|
|
|
|
|
- private void AttachExtensionMethodsToPrototype(Engine engine, ObjectInstance prototype, Type objectType)
|
|
|
|
|
|
+ private static void AttachExtensionMethodsToPrototype(Engine engine, ObjectInstance prototype, Type objectType)
|
|
{
|
|
{
|
|
- if (!_extensionMethods.TryGetExtensionMethods(objectType, out var methods))
|
|
|
|
|
|
+ if (!engine._extensionMethods.TryGetExtensionMethods(objectType, out var methods))
|
|
{
|
|
{
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
foreach (var overloads in methods.GroupBy(x => x.Name))
|
|
foreach (var overloads in methods.GroupBy(x => x.Name))
|
|
{
|
|
{
|
|
-
|
|
|
|
- PropertyDescriptor CreateMethodInstancePropertyDescriptor(ClrFunctionInstance clrFunctionInstance)
|
|
|
|
|
|
+ PropertyDescriptor CreateMethodInstancePropertyDescriptor(ClrFunctionInstance? function)
|
|
{
|
|
{
|
|
- var instance = clrFunctionInstance == null
|
|
|
|
|
|
+ var instance = function is null
|
|
? new MethodInfoFunctionInstance(engine, MethodDescriptor.Build(overloads.ToList()))
|
|
? new MethodInfoFunctionInstance(engine, MethodDescriptor.Build(overloads.ToList()))
|
|
- : new MethodInfoFunctionInstance(engine, MethodDescriptor.Build(overloads.ToList()), clrFunctionInstance);
|
|
|
|
|
|
+ : new MethodInfoFunctionInstance(engine, MethodDescriptor.Build(overloads.ToList()), function);
|
|
|
|
|
|
return new PropertyDescriptor(instance, PropertyFlag.NonConfigurable);
|
|
return new PropertyDescriptor(instance, PropertyFlag.NonConfigurable);
|
|
}
|
|
}
|
|
|
|
|
|
JsValue key = overloads.Key;
|
|
JsValue key = overloads.Key;
|
|
- PropertyDescriptor descriptorWithFallback = null;
|
|
|
|
- PropertyDescriptor descriptorWithoutFallback = null;
|
|
|
|
|
|
+ PropertyDescriptor? descriptorWithFallback = null;
|
|
|
|
+ PropertyDescriptor? descriptorWithoutFallback = null;
|
|
|
|
|
|
- if (prototype.HasOwnProperty(key) && prototype.GetOwnProperty(key).Value is ClrFunctionInstance clrFunctionInstance)
|
|
|
|
|
|
+ if (prototype.HasOwnProperty(key) &&
|
|
|
|
+ prototype.GetOwnProperty(key).Value is ClrFunctionInstance clrFunctionInstance)
|
|
{
|
|
{
|
|
descriptorWithFallback = CreateMethodInstancePropertyDescriptor(clrFunctionInstance);
|
|
descriptorWithFallback = CreateMethodInstancePropertyDescriptor(clrFunctionInstance);
|
|
prototype.SetOwnProperty(key, descriptorWithFallback);
|
|
prototype.SetOwnProperty(key, descriptorWithFallback);
|
|
@@ -147,278 +151,125 @@ namespace Jint
|
|
{
|
|
{
|
|
key = char.ToLower(overloads.Key[0]) + overloads.Key.Substring(1);
|
|
key = char.ToLower(overloads.Key[0]) + overloads.Key.Substring(1);
|
|
|
|
|
|
- if (prototype.HasOwnProperty(key) && prototype.GetOwnProperty(key).Value is ClrFunctionInstance lowerclrFunctionInstance)
|
|
|
|
|
|
+ if (prototype.HasOwnProperty(key) &&
|
|
|
|
+ prototype.GetOwnProperty(key).Value is ClrFunctionInstance lowerclrFunctionInstance)
|
|
{
|
|
{
|
|
- descriptorWithFallback = descriptorWithFallback ?? CreateMethodInstancePropertyDescriptor(lowerclrFunctionInstance);
|
|
|
|
|
|
+ descriptorWithFallback ??= CreateMethodInstancePropertyDescriptor(lowerclrFunctionInstance);
|
|
prototype.SetOwnProperty(key, descriptorWithFallback);
|
|
prototype.SetOwnProperty(key, descriptorWithFallback);
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
- descriptorWithoutFallback = descriptorWithoutFallback ?? CreateMethodInstancePropertyDescriptor(null);
|
|
|
|
|
|
+ descriptorWithoutFallback ??= CreateMethodInstancePropertyDescriptor(null);
|
|
prototype.SetOwnProperty(key, descriptorWithoutFallback);
|
|
prototype.SetOwnProperty(key, descriptorWithoutFallback);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ public class DebuggerOptions
|
|
|
|
+ {
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// If no known type could be guessed, objects are normally wrapped as an
|
|
|
|
- /// ObjectInstance using class ObjectWrapper. This function can be used to
|
|
|
|
- /// register a handler for a customized handling.
|
|
|
|
|
|
+ /// Whether debugger functionality is enabled, defaults to false.
|
|
/// </summary>
|
|
/// </summary>
|
|
- public Options SetWrapObjectHandler(Func<Engine, object, ObjectInstance> wrapObjectHandler)
|
|
|
|
- {
|
|
|
|
- _wrapObjectHandler = wrapObjectHandler;
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ public bool Enabled { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// Sets the type converter to use.
|
|
|
|
|
|
+ /// Configures the statement handling strategy, defaults to Ignore.
|
|
/// </summary>
|
|
/// </summary>
|
|
- public Options SetTypeConverter(Func<Engine, ITypeConverter> typeConverterFactory)
|
|
|
|
- {
|
|
|
|
- _configurations.Add(engine => engine.ClrTypeConverter = typeConverterFactory(engine));
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ public DebuggerStatementHandling StatementHandling { get; set; } = DebuggerStatementHandling.Ignore;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ public class InteropOptions
|
|
|
|
+ {
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// Sets member name comparison strategy when finding CLR objects members.
|
|
|
|
- /// By default member's first character casing is ignored and rest of the name is compared with strict equality.
|
|
|
|
|
|
+ /// Whether accessing CLR and it's types and methods is allowed from JS code, defaults to false.
|
|
/// </summary>
|
|
/// </summary>
|
|
- public Options SetTypeResolver(TypeResolver resolver)
|
|
|
|
- {
|
|
|
|
- _typeResolver = resolver;
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ public bool Enabled { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// Registers a delegate that is called when CLR members are invoked. This allows
|
|
|
|
- /// to change what values are returned for specific CLR objects, or if any value
|
|
|
|
- /// is returned at all.
|
|
|
|
|
|
+ /// Whether writing to CLR objects is allowed (set properties), defaults to true.
|
|
/// </summary>
|
|
/// </summary>
|
|
- /// <param name="accessor">
|
|
|
|
- /// The delegate to invoke for each CLR member. If the delegate
|
|
|
|
- /// returns <c>null</c>, the standard evaluation is performed.
|
|
|
|
- /// </param>
|
|
|
|
- public Options SetMemberAccessor(MemberAccessorDelegate accessor)
|
|
|
|
- {
|
|
|
|
- _memberAccessor = accessor;
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ public bool AllowWrite { get; set; } = true;
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// Allows scripts to call CLR types directly like <example>System.IO.File</example>
|
|
|
|
|
|
+ /// Whether operator overloading resolution is allowed, defaults to false.
|
|
/// </summary>
|
|
/// </summary>
|
|
- public Options AllowClr(params Assembly[] assemblies)
|
|
|
|
- {
|
|
|
|
- _allowClr = true;
|
|
|
|
- _lookupAssemblies.AddRange(assemblies);
|
|
|
|
- _lookupAssemblies = _lookupAssemblies.Distinct().ToList();
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public Options AllowClrWrite(bool allow = true)
|
|
|
|
- {
|
|
|
|
- _allowClrWrite = allow;
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public Options AllowOperatorOverloading(bool allow = true)
|
|
|
|
- {
|
|
|
|
- _allowOperatorOverloading = allow;
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ public bool OperatorOverloadingAllowed { get; set; }
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// Exceptions thrown from CLR code are converted to JavaScript errors and
|
|
|
|
- /// can be used in at try/catch statement. By default these exceptions are bubbled
|
|
|
|
- /// to the CLR host and interrupt the script execution.
|
|
|
|
|
|
+ /// Types holding extension methods that should be considered when resolving methods.
|
|
/// </summary>
|
|
/// </summary>
|
|
- public Options CatchClrExceptions()
|
|
|
|
- {
|
|
|
|
- CatchClrExceptions(_ => true);
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ public List<Type> ExtensionMethodTypes { get; } = new();
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// Exceptions that thrown from CLR code are converted to JavaScript errors and
|
|
|
|
- /// can be used in at try/catch statement. By default these exceptions are bubbled
|
|
|
|
- /// to the CLR host and interrupt the script execution.
|
|
|
|
|
|
+ /// Object converters to try when build-in conversions.
|
|
/// </summary>
|
|
/// </summary>
|
|
- public Options CatchClrExceptions(Predicate<Exception> handler)
|
|
|
|
- {
|
|
|
|
- _clrExceptionsHandler = handler;
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public Options Constraint(IConstraint constraint)
|
|
|
|
- {
|
|
|
|
- if (constraint != null)
|
|
|
|
- {
|
|
|
|
- _constraints.Add(constraint);
|
|
|
|
- }
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public Options WithoutConstraint(Predicate<IConstraint> predicate)
|
|
|
|
- {
|
|
|
|
- _constraints.RemoveAll(predicate);
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public Options RegexTimeoutInterval(TimeSpan regexTimeoutInterval)
|
|
|
|
- {
|
|
|
|
- _regexTimeoutInterval = regexTimeoutInterval;
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ public List<IObjectConverter> ObjectConverters { get; } = new();
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// Sets maximum allowed depth of recursion.
|
|
|
|
|
|
+ /// If no known type could be guessed, objects are by default wrapped as an
|
|
|
|
+ /// ObjectInstance using class ObjectWrapper. This function can be used to
|
|
|
|
+ /// change the behavior.
|
|
/// </summary>
|
|
/// </summary>
|
|
- /// <param name="maxRecursionDepth">
|
|
|
|
- /// The allowed depth.
|
|
|
|
- /// a) In case max depth is zero no recursion is allowed.
|
|
|
|
- /// b) In case max depth is equal to n it means that in one scope function can be called no more than n times.
|
|
|
|
- /// </param>
|
|
|
|
- /// <returns>Options instance for fluent syntax</returns>
|
|
|
|
- public Options LimitRecursion(int maxRecursionDepth = 0)
|
|
|
|
- {
|
|
|
|
- _maxRecursionDepth = maxRecursionDepth;
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ public WrapObjectDelegate WrapObjectHandler { get; set; } = (engine, target) => new ObjectWrapper(engine, target);
|
|
|
|
|
|
- public Options Culture(CultureInfo cultureInfo)
|
|
|
|
- {
|
|
|
|
- _culture = cultureInfo;
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public Options LocalTimeZone(TimeZoneInfo timeZoneInfo)
|
|
|
|
- {
|
|
|
|
- _localTimeZone = timeZoneInfo;
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
+ ///
|
|
|
|
+ /// </summary>
|
|
|
|
+ public MemberAccessorDelegate MemberAccessor { get; set; } = (engine, target, member) => null;
|
|
|
|
|
|
- public Options SetReferencesResolver(IReferenceResolver resolver)
|
|
|
|
- {
|
|
|
|
- _referenceResolver = resolver;
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Exceptions that thrown from CLR code are converted to JavaScript errors and
|
|
|
|
+ /// can be used in at try/catch statement. By default these exceptions are bubbled
|
|
|
|
+ /// to the CLR host and interrupt the script execution. If handler returns true these exceptions are converted
|
|
|
|
+ /// to JS errors that can be caught by the script.
|
|
|
|
+ /// </summary>
|
|
|
|
+ public ExceptionHandlerDelegate ExceptionHandler { get; set; } = exception => false;
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// Registers some custom logic to apply on an <see cref="Engine"/> instance when the options
|
|
|
|
- /// are loaded.
|
|
|
|
|
|
+ /// Assemblies to allow scripts to call CLR types directly like <example>System.IO.File</example>.
|
|
/// </summary>
|
|
/// </summary>
|
|
- /// <param name="configuration">The action to register.</param>
|
|
|
|
- public Options Configure(Action<Engine> configuration)
|
|
|
|
- {
|
|
|
|
- _configurations.Add(configuration);
|
|
|
|
- return this;
|
|
|
|
- }
|
|
|
|
|
|
+ public List<Assembly> AllowedAssemblies { get; set; } = new();
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// Allows to configure how the host is constructed.
|
|
|
|
|
|
+ /// Type and member resolving strategy, which allows filtering allowed members and configuring member
|
|
|
|
+ /// name matching comparison.
|
|
/// </summary>
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <remarks>
|
|
- /// Passed Engine instance is still in construction and should not be used during call stage.
|
|
|
|
|
|
+ /// As this object holds caching state same instance should be shared between engines, if possible.
|
|
/// </remarks>
|
|
/// </remarks>
|
|
- public void UseHostFactory<T>(Func<Engine, T> factory) where T : Host
|
|
|
|
- {
|
|
|
|
- _hostFactory = factory;
|
|
|
|
- }
|
|
|
|
|
|
+ public TypeResolver TypeResolver { get; set; } = TypeResolver.Default;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ public class ConstraintOptions
|
|
|
|
+ {
|
|
/// <summary>
|
|
/// <summary>
|
|
- /// Called by the <see cref="Engine"/> instance that loads this <see cref="Options" />
|
|
|
|
- /// once it is loaded.
|
|
|
|
|
|
+ /// Registered constraints.
|
|
/// </summary>
|
|
/// </summary>
|
|
- internal void Apply(Engine engine)
|
|
|
|
- {
|
|
|
|
- foreach (var configuration in _configurations)
|
|
|
|
- {
|
|
|
|
- configuration?.Invoke(engine);
|
|
|
|
- }
|
|
|
|
|
|
+ public List<IConstraint> Constraints { get; } = new();
|
|
|
|
|
|
- // add missing bits if needed
|
|
|
|
- if (_allowClr)
|
|
|
|
- {
|
|
|
|
- engine.Realm.GlobalObject.SetProperty("System", new PropertyDescriptor(new NamespaceReference(engine, "System"), PropertyFlag.AllForbidden));
|
|
|
|
- engine.Realm.GlobalObject.SetProperty("importNamespace", new PropertyDescriptor(new ClrFunctionInstance(
|
|
|
|
- engine,
|
|
|
|
- "importNamespace",
|
|
|
|
- func: (thisObj, arguments) => new NamespaceReference(engine, TypeConverter.ToString(arguments.At(0)))), PropertyFlag.AllForbidden));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (_extensionMethodClassTypes.Count > 0)
|
|
|
|
- {
|
|
|
|
- AttachExtensionMethodsToPrototypes(engine);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // ensure defaults
|
|
|
|
- engine.ClrTypeConverter ??= new DefaultTypeConverter(engine);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- internal bool IsStrict => _strict;
|
|
|
|
-
|
|
|
|
- internal DebuggerStatementHandling _DebuggerStatementHandling => _debuggerStatementHandling;
|
|
|
|
-
|
|
|
|
- internal bool IsDebugMode { get; private set; }
|
|
|
|
-
|
|
|
|
- internal bool _IsClrWriteAllowed => _allowClrWrite;
|
|
|
|
-
|
|
|
|
- internal bool _IsOperatorOverloadingAllowed => _allowOperatorOverloading;
|
|
|
|
-
|
|
|
|
- internal Predicate<Exception> _ClrExceptionsHandler => _clrExceptionsHandler;
|
|
|
|
-
|
|
|
|
- internal List<Assembly> _LookupAssemblies => _lookupAssemblies;
|
|
|
|
-
|
|
|
|
- internal List<IObjectConverter> _ObjectConverters => _objectConverters;
|
|
|
|
-
|
|
|
|
- internal List<IConstraint> _Constraints => _constraints;
|
|
|
|
-
|
|
|
|
- internal Func<Engine, object, ObjectInstance> _WrapObjectHandler => _wrapObjectHandler;
|
|
|
|
-
|
|
|
|
- internal MemberAccessorDelegate _MemberAccessor => _memberAccessor;
|
|
|
|
- internal TypeResolver _TypeResolver => _typeResolver;
|
|
|
|
-
|
|
|
|
- internal int MaxRecursionDepth => _maxRecursionDepth;
|
|
|
|
-
|
|
|
|
- internal TimeSpan _RegexTimeoutInterval => _regexTimeoutInterval;
|
|
|
|
-
|
|
|
|
- internal CultureInfo _Culture => _culture;
|
|
|
|
-
|
|
|
|
- internal TimeZoneInfo _LocalTimeZone => _localTimeZone;
|
|
|
|
-
|
|
|
|
- internal IReferenceResolver ReferenceResolver => _referenceResolver;
|
|
|
|
-
|
|
|
|
- private sealed class DefaultReferenceResolver : IReferenceResolver
|
|
|
|
- {
|
|
|
|
- public static readonly DefaultReferenceResolver Instance = new();
|
|
|
|
-
|
|
|
|
- private DefaultReferenceResolver()
|
|
|
|
- {
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public bool TryUnresolvableReference(Engine engine, Reference reference, out JsValue value)
|
|
|
|
- {
|
|
|
|
- value = JsValue.Undefined;
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Maximum recursion depth allowed, defaults to -1 (no checks).
|
|
|
|
+ /// </summary>
|
|
|
|
+ public int MaxRecursionDepth { get; set; } = -1;
|
|
|
|
|
|
- public bool TryPropertyReference(Engine engine, Reference reference, ref JsValue value)
|
|
|
|
- {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Maximum time a Regex is allowed to run, defaults to 10 seconds.
|
|
|
|
+ /// </summary>
|
|
|
|
+ public TimeSpan RegexTimeout { get; set; } = TimeSpan.FromSeconds(10);
|
|
|
|
|
|
- public bool TryGetCallable(Engine engine, object callee, out JsValue value)
|
|
|
|
- {
|
|
|
|
- value = JsValue.Undefined;
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// The maximum size for JavaScript array, defaults to <see cref="uint.MaxValue"/>.
|
|
|
|
+ /// </summary>
|
|
|
|
+ public uint MaxArraySize { get; set; } = uint.MaxValue;
|
|
|
|
+ }
|
|
|
|
|
|
- public bool CheckCoercible(JsValue value)
|
|
|
|
- {
|
|
|
|
- return false;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// Host related customization, still work in progress.
|
|
|
|
+ /// </summary>
|
|
|
|
+ public class HostOptions
|
|
|
|
+ {
|
|
|
|
+ internal Func<Engine, Host> Factory { get; set; } = _ => new Host();
|
|
}
|
|
}
|
|
-}
|
|
|
|
|
|
+}
|