소스 검색

Handle Symbol.toPrimitive and valueOf calls better under interop (#1470)

Marko Lahma 2 년 전
부모
커밋
fa27dfa497
3개의 변경된 파일45개의 추가작업 그리고 13개의 파일을 삭제
  1. 20 1
      Jint.Tests/Runtime/InteropTests.cs
  2. 17 11
      Jint/Runtime/Interop/ObjectWrapper.cs
  3. 8 1
      Jint/Runtime/Interop/Reflection/IndexerAccessor.cs

+ 20 - 1
Jint.Tests/Runtime/InteropTests.cs

@@ -24,7 +24,7 @@ namespace Jint.Tests.Runtime
             _engine = new Engine(cfg => cfg.AllowClr(
                         typeof(Shape).GetTypeInfo().Assembly,
                         typeof(Console).GetTypeInfo().Assembly,
-                        typeof(System.IO.File).GetTypeInfo().Assembly))
+                        typeof(File).GetTypeInfo().Assembly))
                     .SetValue("log", new Action<object>(Console.WriteLine))
                     .SetValue("assert", new Action<bool>(Assert.True))
                     .SetValue("equal", new Action<object, object>(Assert.Equal))
@@ -3154,6 +3154,25 @@ try {
             }
         }
 
+        private class ClassWithIndexerAndProperty
+        {
+            public string MyProp { get; } = "from property";
+
+            public string this[string name] => name != nameof(MyProp) ? "from indexer" : null;
+        }
+
+        [Fact]
+        public void CanToStringObjectWithoutToPrimitiveSymbol()
+        {
+            var engine = new Engine();
+
+            engine.SetValue("obj", new ClassWithIndexerAndProperty());
+            Assert.Equal("Jint.Tests.Runtime.InteropTests+ClassWithIndexerAndProperty", engine.Evaluate("obj + ''").AsString());
+
+            engine.SetValue("obj", new Company("name"));
+            Assert.Equal("Jint.Tests.Runtime.Domain.Company", engine.Evaluate("obj + ''").AsString());
+        }
+
         [Fact]
         public void CanConstructOptionalRecordClass()
         {

+ 17 - 11
Jint/Runtime/Interop/ObjectWrapper.cs

@@ -187,18 +187,24 @@ namespace Jint.Runtime.Interop
             }
 
             // if we have array-like or dictionary or expando, we can provide iterator
-            if (property.IsSymbol() && property == GlobalSymbolRegistry.Iterator && _typeDescriptor.Iterable)
+            if (property.IsSymbol())
             {
-                var iteratorFunction = new ClrFunctionInstance(
-                    Engine,
-                    "iterator",
-                    Iterator,
-                    1,
-                    PropertyFlag.Configurable);
-
-                var iteratorProperty = new PropertyDescriptor(iteratorFunction, PropertyFlag.Configurable | PropertyFlag.Writable);
-                SetProperty(GlobalSymbolRegistry.Iterator, iteratorProperty);
-                return iteratorProperty;
+                if (property == GlobalSymbolRegistry.Iterator && _typeDescriptor.Iterable)
+                {
+                    var iteratorFunction = new ClrFunctionInstance(
+                        Engine,
+                        "iterator",
+                        Iterator,
+                        1,
+                        PropertyFlag.Configurable);
+
+                    var iteratorProperty = new PropertyDescriptor(iteratorFunction, PropertyFlag.Configurable | PropertyFlag.Writable);
+                    SetProperty(GlobalSymbolRegistry.Iterator, iteratorProperty);
+                    return iteratorProperty;
+                }
+
+                // not that safe
+                return PropertyDescriptor.Undefined;
             }
 
             var member = property.ToString();

+ 8 - 1
Jint/Runtime/Interop/Reflection/IndexerAccessor.cs

@@ -139,7 +139,14 @@ namespace Jint.Runtime.Interop.Reflection
                 }
             }
 
-            return _getter.Invoke(target, parameters);
+            try
+            {
+                return _getter.Invoke(target, parameters);
+            }
+            catch (TargetInvocationException tie) when (tie.InnerException is KeyNotFoundException)
+            {
+                return JsValue.Undefined;
+            }
         }
 
         protected override void DoSetValue(object target, object? value)