Bläddra i källkod

Backport add interop option ThrowOnUnresolvedMember (#1905)

Marko Lahma 1 år sedan
förälder
incheckning
a2bd5532fe

+ 23 - 1
Jint.Tests/Runtime/InteropTests.MemberAccess.cs

@@ -237,6 +237,8 @@ namespace Jint.Tests.Runtime
 
         public class ClassWithData
         {
+            public int Age => 42;
+
             public DataType Data { get; set; }
 
             public class DataType
@@ -251,10 +253,30 @@ namespace Jint.Tests.Runtime
             var engine = new Engine();
 
             engine.SetValue("obj", new ClassWithData());
-            engine.Execute(@"obj.Data = { Value: '123' };");
+            engine.Execute("obj.Data = { Value: '123' };");
             var obj = engine.Evaluate("obj").ToObject() as ClassWithData;
 
             Assert.Equal("123", obj?.Data.Value);
         }
+
+        [Fact]
+        public void CanConfigureStrictAccess()
+        {
+            var engine = new Engine();
+
+            engine.SetValue("obj", new ClassWithData());
+            engine.Evaluate("obj.Age").AsNumber().Should().Be(42);
+            engine.Evaluate("obj.AgeMissing").Should().Be(JsValue.Undefined);
+
+            engine = new Engine(options =>
+            {
+                options.Interop.ThrowOnUnresolvedMember = true;
+            });
+
+            engine.SetValue("obj", new ClassWithData());
+            engine.Evaluate("obj.Age").AsNumber().Should().Be(42);
+
+            engine.Invoking(e => e.Evaluate("obj.AgeMissing")).Should().Throw<MissingMemberException>();
+        }
     }
 }

+ 5 - 0
Jint/Options.cs

@@ -359,6 +359,11 @@ public class Options
         /// Should the Array prototype be attached instead of Object prototype to the wrapped interop objects when type looks suitable. Defaults to true.
         /// </summary>
         public bool AttachArrayPrototype { get; set; } = true;
+
+        /// <summary>
+        /// Whether the engine should throw an error when a member is not found on a CLR object. Defaults to false.
+        /// </summary>
+        public bool ThrowOnUnresolvedMember { get; set; }
     }
 
     public class ConstraintOptions

+ 5 - 0
Jint/Runtime/Interop/TypeResolver.cs

@@ -262,6 +262,11 @@ namespace Jint.Runtime.Interop
                 }
             }
 
+            if (engine.Options.Interop.ThrowOnUnresolvedMember)
+            {
+                throw new MissingMemberException($"Cannot access property '{memberName}' on type '{type.FullName}");
+            }
+
             return ConstantValueAccessor.NullAccessor;
         }