Browse Source

Fix toPrimitive evaluating multiple times during "in" expression (#1319)

Gökhan Kurt 2 năm trước cách đây
mục cha
commit
aa3ad792d4

+ 23 - 0
Jint.Tests/Runtime/TypeConverterTests.cs

@@ -1,10 +1,21 @@
 using Jint.Native;
 using Jint.Runtime;
+using Xunit.Abstractions;
 
 namespace Jint.Tests.Runtime
 {
     public class TypeConverterTests
     {
+        private readonly Engine _engine;
+
+        public TypeConverterTests(ITestOutputHelper output)
+        {
+            _engine = new Engine()
+                .SetValue("log", new Action<object>(o => output.WriteLine(o.ToString())))
+                .SetValue("assert", new Action<bool>(Assert.True))
+                .SetValue("equal", new Action<object, object>(Assert.Equal))
+                ;
+        }
 
         public static readonly IEnumerable<object[]> ConvertNumberToInt32AndUint32TestData = new TheoryData<double, int>()
         {
@@ -68,6 +79,18 @@ namespace Jint.Tests.Runtime
             Assert.Equal((uint)expectedResult, TypeConverter.ToUint32(jsval));
         }
 
+        [Fact]
+        public void ToPrimitiveShouldEvaluateOnlyOnceDuringInExpression()
+        {
+            _engine.Execute(@"
+                var b = {};
+                var bval = 0;
+                b[Symbol.toPrimitive] = function(hint) { return bval++; };
+
+                b in {};
+                equal(1, bval);
+            ");
+        }
     }
 
 }

+ 3 - 3
Jint/Native/Object/ObjectConstructor.cs

@@ -496,7 +496,7 @@ namespace Jint.Native.Object
         {
             if (arguments.At(0) is not ObjectInstance o)
             {
-                return true;
+                return JsBoolean.True;
             }
 
             return TestIntegrityLevel(o, IntegrityLevel.Sealed);
@@ -509,7 +509,7 @@ namespace Jint.Native.Object
         {
             if (arguments.At(0) is not ObjectInstance o)
             {
-                return true;
+                return JsBoolean.True;
             }
 
             return TestIntegrityLevel(o, IntegrityLevel.Frozen);
@@ -555,7 +555,7 @@ namespace Jint.Native.Object
         {
             if (arguments.At(0) is not ObjectInstance o)
             {
-                return false;
+                return JsBoolean.False;
             }
 
             return o.Extensible;

+ 3 - 2
Jint/Native/Object/ObjectInstance.cs

@@ -584,7 +584,8 @@ namespace Jint.Native.Object
         /// </summary>
         public virtual bool HasProperty(JsValue property)
         {
-            var hasOwn = GetOwnProperty(property);
+            var key = TypeConverter.ToPropertyKey(property);
+            var hasOwn = GetOwnProperty(key);
             if (hasOwn != PropertyDescriptor.Undefined)
             {
                 return true;
@@ -593,7 +594,7 @@ namespace Jint.Native.Object
             var parent = GetPrototypeOf();
             if (parent != null)
             {
-                return parent.HasProperty(property);
+                return parent.HasProperty(key);
             }
 
             return false;