瀏覽代碼

Ensure support for custom null and undefined (#1407)

Marko Lahma 2 年之前
父節點
當前提交
81cfbc0507
共有 4 個文件被更改,包括 85 次插入38 次删除
  1. 84 33
      Jint.Tests.PublicInterface/RavenApiUsageTests.cs
  2. 0 2
      Jint/Native/JsNull.cs
  3. 0 2
      Jint/Native/JsUndefined.cs
  4. 1 1
      Jint/Native/JsValue.cs

+ 84 - 33
Jint.Tests.PublicInterface/RavenApiUsageTests.cs

@@ -2,6 +2,7 @@ using Esprima.Ast;
 using Jint.Constraints;
 using Jint.Native;
 using Jint.Native.Function;
+using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
 
@@ -96,7 +97,7 @@ public class RavenApiUsageTests
 
         TestArrayAccess(engine, array1, "array1");
 
-        var array3 = new JsArray(engine, new []
+        var array3 = new JsArray(engine, new[]
         {
             new PropertyDescriptor(JsNumber.Create(1), true, true, true),
             new PropertyDescriptor(JsNumber.Create(2), true, true, true),
@@ -206,47 +207,97 @@ public class RavenApiUsageTests
         Assert.True(engine.Evaluate("empty.trimEnd() === ''").AsBoolean());
     }
 
-    private sealed class CustomString : JsString
+    [Fact]
+    public void CanDefineCustomNull()
     {
-        private readonly string _value;
+        var engine = new Engine();
+        engine.SetValue("value", new CustomNull());
+        Assert.Equal("foo", engine.Evaluate("value ? value + 'bar' : 'foo'"));
+    }
 
-        public CustomString(string value) : base(null)
-        {
-            _value = value;
-        }
+    [Fact]
+    public void CanDefineCustomUndefined()
+    {
+        var engine = new Engine();
+        engine.SetValue("value", new CustomUndefined());
+        Assert.Equal("foo", engine.Evaluate("value ? value + 'bar' : 'foo'"));
+    }
+}
 
-        public override string ToString()
-        {
-            // when called we know that we couldn't use fast paths
-            throw new InvalidOperationException("I don't want to be materialized!");
-        }
+file sealed class CustomString : JsString
+{
+    private readonly string _value;
 
-        public override char this[int index] => _value[index];
+    public CustomString(string value) : base(null)
+    {
+        _value = value;
+    }
 
-        public override int Length => _value.Length;
+    public override string ToString()
+    {
+        // when called we know that we couldn't use fast paths
+        throw new InvalidOperationException("I don't want to be materialized!");
+    }
 
-        public override bool Equals(JsString obj)
-        {
-            return obj switch
-            {
-                CustomString customString => _value == customString._value,
-                _ => _value == obj.ToString()
-            };
-        }
+    public override char this[int index] => _value[index];
+
+    public override int Length => _value.Length;
 
-        public override bool IsLooselyEqual(JsValue value)
+    public override bool Equals(JsString obj)
+    {
+        return obj switch
         {
-            return value switch
-            {
-                CustomString customString => _value == customString._value,
-                JsString jsString => _value == jsString.ToString(),
-                _ => base.IsLooselyEqual(value)
-            };
-        }
+            CustomString customString => _value == customString._value,
+            _ => _value == obj.ToString()
+        };
+    }
 
-        public override int GetHashCode()
+    public override bool IsLooselyEqual(JsValue value)
+    {
+        return value switch
         {
-            return _value.GetHashCode();
-        }
+            CustomString customString => _value == customString._value,
+            JsString jsString => _value == jsString.ToString(),
+            _ => base.IsLooselyEqual(value)
+        };
+    }
+
+    public override int GetHashCode()
+    {
+        return _value.GetHashCode();
+    }
+}
+
+file sealed class CustomNull : JsValue
+{
+    public CustomNull() : base(Types.Null)
+    {
+    }
+
+    public override object ToObject()
+    {
+        return null;
+    }
+
+    public override string ToString()
+    {
+        return "null";
+    }
+}
+
+file sealed class CustomUndefined : JsValue
+{
+    public CustomUndefined() : base(Types.Null)
+    {
+    }
+
+    public override object ToObject()
+    {
+        return null;
+    }
+
+    public override string ToString()
+    {
+        return "null";
     }
 }

+ 0 - 2
Jint/Native/JsNull.cs

@@ -10,8 +10,6 @@ public sealed class JsNull : JsValue, IEquatable<JsNull>
 
     public override object ToObject() => null!;
 
-    internal override bool ToBoolean() => false;
-
     public override string ToString() => "null";
 
     public override bool IsLooselyEqual(JsValue value)

+ 0 - 2
Jint/Native/JsUndefined.cs

@@ -10,8 +10,6 @@ public sealed class JsUndefined : JsValue, IEquatable<JsUndefined>
 
     public override object ToObject() => null!;
 
-    internal override bool ToBoolean() => false;
-
     public override string ToString() => "undefined";
 
     public override bool IsLooselyEqual(JsValue value)

+ 1 - 1
Jint/Native/JsValue.cs

@@ -149,7 +149,7 @@ namespace Jint.Native
         /// <summary>
         /// Coerces boolean value from <see cref="JsValue"/> instance.
         /// </summary>
-        internal virtual bool ToBoolean() => true;
+        internal virtual bool ToBoolean() => _type > InternalTypes.Null;
 
         /// <summary>
         /// Invoke the current value as function.