Browse Source

Create sample how to JSON.stringify CLR types (#1226)

Marko Lahma 3 years ago
parent
commit
cb4e73de96

+ 1 - 70
Jint.Tests/Runtime/InteropTests.Dynamic.cs

@@ -1,6 +1,5 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Dynamic;
 using System.Dynamic;
-using System.Linq;
 using Xunit;
 using Xunit;
 
 
 namespace Jint.Tests.Runtime
 namespace Jint.Tests.Runtime
@@ -32,34 +31,6 @@ namespace Jint.Tests.Runtime
             Assert.Equal("abc", _engine.Evaluate("parent.child.item.title"));
             Assert.Equal("abc", _engine.Evaluate("parent.child.item.title"));
         }
         }
 
 
-
-        [Fact]
-        public void EngineShouldStringifyAnExpandoObjectCorrectly()
-        {
-            var engine = new Engine();
-
-            dynamic expando = new ExpandoObject();
-            expando.foo = 5;
-            expando.bar = "A string";
-            engine.SetValue(nameof(expando), expando);
-
-            var result = engine.Evaluate($"JSON.stringify({nameof(expando)})").AsString();
-            Assert.Equal("{\"foo\":5,\"bar\":\"A string\"}", result);
-        }
-
-        [Fact]
-        public void EngineShouldStringifyAnExpandoObjectWithValuesCorrectly()
-        {
-            // https://github.com/sebastienros/jint/issues/995
-            var engine = new Engine();
-
-            dynamic expando = new ExpandoObject();
-            expando.Values = 1;
-            engine.SetValue("expando", expando);
-
-            Assert.Equal("{\"Values\":1}", engine.Evaluate($"JSON.stringify(expando)").AsString());
-        }
-
         [Fact]
         [Fact]
         public void ShouldForOfOnExpandoObject()
         public void ShouldForOfOnExpandoObject()
         {
         {
@@ -91,46 +62,6 @@ namespace Jint.Tests.Runtime
             Assert.Equal("foo", dic["b"]);
             Assert.Equal("foo", dic["b"]);
         }
         }
 
 
-        [Fact]
-        public void EngineShouldStringifyAnJObjectArrayWithValuesCorrectly()
-        {
-            //https://github.com/OrchardCMS/OrchardCore/issues/10648
-            var engine = new Engine();
-            var queryResults = new List<dynamic>();
-            queryResults.Add(new { Text = "Text1", Value = 1 });
-            queryResults.Add(new { Text = "Text2", Value = 2 });
-
-            engine.SetValue("testSubject", queryResults.ToArray());
-            var fromEngine2 = engine.Evaluate("return JSON.stringify(testSubject);");
-            var result2 = fromEngine2.ToString();
-            Assert.Equal("[{\"Text\":\"Text1\",\"Value\":1},{\"Text\":\"Text2\",\"Value\":2}]", result2);
-        }
-
-        [Fact]
-        public void EngineShouldStringifyDynamicObjectListWithValuesCorrectly()
-        {
-            var engine = new Engine();
-            var source = new dynamic[] { new { Text = "Text1", Value = 1 }, new { Text = "Text2", Value = 2 } };
-
-            var objects = source.ToList();
-            engine.SetValue("testSubject", objects);
-            var fromEngine = engine.Evaluate("return JSON.stringify(testSubject);");
-            var result = fromEngine.ToString();
-            Assert.Equal("[{\"Text\":\"Text1\",\"Value\":1},{\"Text\":\"Text2\",\"Value\":2}]", result);
-        }
-
-        [Fact]
-        public void EngineShouldStringifyDynamicObjectArrayWithValuesCorrectly()
-        {
-            var engine = new Engine();
-            var source = new dynamic[] { new { Text = "Text1", Value = 1 }, new { Text = "Text2", Value = 2 } };
-
-            engine.SetValue("testSubject", source.AsEnumerable());
-            var fromEngine = engine.Evaluate("return JSON.stringify(testSubject);");
-            var result = fromEngine.ToString();
-            Assert.Equal("[{\"Text\":\"Text1\",\"Value\":1},{\"Text\":\"Text2\",\"Value\":2}]", result);
-        }
-
         [Fact]
         [Fact]
         public void CanAccessDynamicObject()
         public void CanAccessDynamicObject()
         {
         {
@@ -182,4 +113,4 @@ namespace Jint.Tests.Runtime
             }
             }
         }
         }
     }
     }
-}
+}

+ 110 - 0
Jint.Tests/Runtime/InteropTests.Json.cs

@@ -0,0 +1,110 @@
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+using Jint.Native;
+using Jint.Runtime.Interop;
+using Xunit;
+
+namespace Jint.Tests.Runtime;
+
+public partial class InteropTests
+{
+    [Fact]
+    public void EngineShouldStringifyAnExpandoObjectCorrectly()
+    {
+        var engine = new Engine();
+
+        dynamic expando = new ExpandoObject();
+        expando.foo = 5;
+        expando.bar = "A string";
+        engine.SetValue(nameof(expando), expando);
+
+        var result = engine.Evaluate($"JSON.stringify({nameof(expando)})").AsString();
+        Assert.Equal("{\"foo\":5,\"bar\":\"A string\"}", result);
+    }
+
+    [Fact]
+    public void EngineShouldStringifyAnExpandoObjectWithValuesCorrectly()
+    {
+        // https://github.com/sebastienros/jint/issues/995
+        var engine = new Engine();
+
+        dynamic expando = new ExpandoObject();
+        expando.Values = 1;
+        engine.SetValue("expando", expando);
+
+        Assert.Equal("{\"Values\":1}", engine.Evaluate($"JSON.stringify(expando)").AsString());
+    }
+
+
+    [Fact]
+    public void EngineShouldStringifyAnJObjectArrayWithValuesCorrectly()
+    {
+        //https://github.com/OrchardCMS/OrchardCore/issues/10648
+        var engine = new Engine();
+        var queryResults = new List<dynamic>();
+        queryResults.Add(new { Text = "Text1", Value = 1 });
+        queryResults.Add(new { Text = "Text2", Value = 2 });
+
+        engine.SetValue("testSubject", queryResults.ToArray());
+        var fromEngine2 = engine.Evaluate("return JSON.stringify(testSubject);");
+        var result2 = fromEngine2.ToString();
+        Assert.Equal("[{\"Text\":\"Text1\",\"Value\":1},{\"Text\":\"Text2\",\"Value\":2}]", result2);
+    }
+
+    [Fact]
+    public void EngineShouldStringifyDynamicObjectListWithValuesCorrectly()
+    {
+        var engine = new Engine();
+        var source = new dynamic[] { new { Text = "Text1", Value = 1 }, new { Text = "Text2", Value = 2 } };
+
+        var objects = source.ToList();
+        engine.SetValue("testSubject", objects);
+        var fromEngine = engine.Evaluate("return JSON.stringify(testSubject);");
+        var result = fromEngine.ToString();
+        Assert.Equal("[{\"Text\":\"Text1\",\"Value\":1},{\"Text\":\"Text2\",\"Value\":2}]", result);
+    }
+
+    [Fact]
+    public void EngineShouldStringifyDynamicObjectArrayWithValuesCorrectly()
+    {
+        var engine = new Engine();
+        var source = new dynamic[] { new { Text = "Text1", Value = 1 }, new { Text = "Text2", Value = 2 } };
+
+        engine.SetValue("testSubject", source.AsEnumerable());
+        var fromEngine = engine.Evaluate("return JSON.stringify(testSubject);");
+        var result = fromEngine.ToString();
+        Assert.Equal("[{\"Text\":\"Text1\",\"Value\":1},{\"Text\":\"Text2\",\"Value\":2}]", result);
+    }
+
+    [Fact]
+    public void CanStringifyTimeSpanUsingCustomToJsonHook()
+    {
+        var engine = new Engine(options =>
+        {
+            options.Interop.MemberAccessor = (e, target, member) =>
+            {
+                // custom serializer hook for known object types
+                if (member == "toJSON" && target is TimeSpan)
+                {
+                    return new ClrFunctionInstance(e, "toJSON", (thisObject, _) =>
+                    {
+                        // here could check other types too
+                        var wrappedInstance = ((IObjectWrapper) thisObject).Target;
+                        return wrappedInstance.ToString();
+                    });
+                }
+
+                return null;
+            };
+        });
+
+        var expected = Newtonsoft.Json.JsonConvert.SerializeObject(TimeSpan.FromSeconds(3));
+
+        engine.SetValue("TimeSpan", TypeReference.CreateTypeReference<TimeSpan>(engine));
+        var value = engine.Evaluate("JSON.stringify(TimeSpan.FromSeconds(3));");
+
+        Assert.Equal(expected, value);
+    }
+}

+ 1 - 11
Jint/Runtime/Interop/ClrFunctionInstance.cs

@@ -35,17 +35,7 @@ namespace Jint.Runtime.Interop
 
 
         public override bool Equals(JsValue obj)
         public override bool Equals(JsValue obj)
         {
         {
-            if (ReferenceEquals(null, obj))
-            {
-                return false;
-            }
-
-            if (!(obj is ClrFunctionInstance s))
-            {
-                return false;
-            }
-
-            return Equals(s);
+            return Equals(obj as ClrFunctionInstance);
         }
         }
 
 
         public bool Equals(ClrFunctionInstance other)
         public bool Equals(ClrFunctionInstance other)