Browse Source

Provide engine instance when customizing options (#751)

Marko Lahma 5 years ago
parent
commit
69c525c56a
3 changed files with 49 additions and 19 deletions
  1. 21 1
      Jint.Tests/Runtime/EngineTests.cs
  2. 20 5
      Jint/Engine.cs
  3. 8 13
      Jint/Options.cs

+ 21 - 1
Jint.Tests/Runtime/EngineTests.cs

@@ -2834,6 +2834,19 @@ x.test = {
             _engine.Execute("equal(false, str.hasOwnProperty('foo'));");
         }
 
+        [Fact]
+        public void ShouldProvideEngineForOptionsAsOverload()
+        {
+            new Engine((e, options) =>
+                {
+                    Assert.IsType<Engine>(e);
+                    options
+                        .AddObjectConverter(new TestObjectConverter())
+                        .AddObjectConverter<TestObjectConverter>();
+                })
+                .SetValue("a", 1);
+        }
+
         private class Wrapper
         {
             public Testificate Test { get; set; }
@@ -2845,9 +2858,16 @@ x.test = {
             public Func<int, int, int> Init { get; set; }
         }
 
-        private class TestTypeConverter : Jint.Runtime.Interop.ITypeConverter
+        private class TestObjectConverter : Jint.Runtime.Interop.IObjectConverter
         {
+            public bool TryConvert(Engine engine, object value, out JsValue result)
+            {
+                throw new NotImplementedException();
+            }
+        }
 
+        private class TestTypeConverter : Jint.Runtime.Interop.ITypeConverter
+        {
             public object Convert(object value, Type type, IFormatProvider formatProvider)
             {
                 throw new NotImplementedException();

+ 20 - 5
Jint/Engine.cs

@@ -147,11 +147,26 @@ namespace Jint
 
         internal readonly JintCallStack CallStack = new JintCallStack();
 
-        public Engine() : this(null)
+        /// <summary>
+        /// Constructs a new engine instance.
+        /// </summary>
+        public Engine() : this((Action<Options>) null)
         {
         }
 
+        /// <summary>
+        /// Constructs a new engine instance and allows customizing options.
+        /// </summary>
         public Engine(Action<Options> options)
+            : this((engine, opts) => options?.Invoke(opts))
+        {
+        }
+
+        /// <summary>
+        /// Constructs a new engine instance and allows customizing options.
+        /// </summary>
+        /// <remarks>The provided engine instance in callback is not guaranteed to be fully configured</remarks>
+        public Engine(Action<Engine, Options> options)
         {
             _executionContexts = new ExecutionContextStack(2);
 
@@ -195,9 +210,12 @@ namespace Jint
             // create the global execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.1.1
             EnterExecutionContext(GlobalEnvironment, GlobalEnvironment);
 
+            Eval = new EvalFunctionInstance(this);
+            Global.SetProperty(CommonProperties.Eval, new PropertyDescriptor(Eval, PropertyFlag.Configurable | PropertyFlag.Writable));
+
             Options = new Options();
 
-            options?.Invoke(Options);
+            options?.Invoke(this, Options);
 
             // gather some options as fields for faster checks
             _isDebugMode = Options.IsDebugMode;
@@ -209,9 +227,6 @@ namespace Jint
             _argumentsInstancePool = new ArgumentsInstancePool(this);
             _jsValueArrayPool = new JsValueArrayPool();
 
-            Eval = new EvalFunctionInstance(this);
-            Global.SetProperty(CommonProperties.Eval, new PropertyDescriptor(Eval, PropertyFlag.Configurable | PropertyFlag.Writable));
-
             if (Options._IsClrAllowed)
             {
                 Global.SetProperty("System", new PropertyDescriptor(new NamespaceReference(this, "System"), PropertyFlag.AllForbidden));

+ 8 - 13
Jint/Options.cs

@@ -13,7 +13,6 @@ namespace Jint
     public sealed class Options
     {
         private readonly List<IConstraint> _constraints = new List<IConstraint>();
-        private bool _discardGlobal;
         private bool _strict;
         private bool _allowDebuggerStatement;
         private bool _allowClr;
@@ -28,16 +27,6 @@ namespace Jint
         private Predicate<Exception> _clrExceptionsHandler;
         private IReferenceResolver _referenceResolver = DefaultReferenceResolver.Instance;
 
-        /// <summary>
-        /// When called, doesn't initialize the global scope.
-        /// Can be useful in lightweight scripts for performance reason.
-        /// </summary>
-        public Options DiscardGlobal(bool discard = true)
-        {
-            _discardGlobal = discard;
-            return this;
-        }
-
         /// <summary>
         /// Run the script in strict mode.
         /// </summary>
@@ -69,6 +58,14 @@ namespace Jint
             return this;
         }
 
+        /// <summary>
+        /// Adds a <see cref="IObjectConverter"/> instance to convert CLR types to <see cref="JsValue"/>
+        /// </summary>
+        public Options AddObjectConverter<T>() where T : IObjectConverter, new()
+        {
+            return AddObjectConverter(new T());
+        }
+
         /// <summary>
          /// Adds a <see cref="IObjectConverter"/> instance to convert CLR types to <see cref="JsValue"/>
         /// </summary>
@@ -182,8 +179,6 @@ namespace Jint
             return this;
         }
 
-        internal bool _IsGlobalDiscarded => _discardGlobal;
-
         internal bool IsStrict => _strict;
 
         internal bool _IsDebuggerStatementAllowed => _allowDebuggerStatement;