Browse Source

Fix ExpandoObject serialization (#996)

Fixes #995
Sébastien Ros 3 năm trước cách đây
mục cha
commit
c110428c7c

+ 25 - 0
Jint.Tests/Runtime/InteropTests.cs

@@ -76,6 +76,31 @@ namespace Jint.Tests.Runtime
             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 EngineShouldStringifyADictionary()
+        {
+            var engine = new Engine();
+
+            var d = new Hashtable();
+            d["Values"] = 1;
+            engine.SetValue("d", d);
+
+            Assert.Equal("{\"Values\":1}", engine.Evaluate($"JSON.stringify(d)").AsString());
+        }
+
         [Fact]
         public void EngineShouldStringifyADictionaryOfStringAndObjectCorrectly()
         {

+ 4 - 4
Jint/Native/Json/JsonSerializer.cs

@@ -270,13 +270,13 @@ namespace Jint.Native.Json
             if (_gap == "")
             {
                 var separator = ",";
-                var properties = System.String.Join(separator, partial.ToArray());
+                var properties = string.Join(separator, partial.ToArray());
                 final = "[" + properties + "]";
             }
             else
             {
                 var separator = ",\n" + _indent;
-                var properties = System.String.Join(separator, partial.ToArray());
+                var properties = string.Join(separator, partial.ToArray());
                 final = "[\n" + _indent + properties + "\n" + stepback + "]";
             }
 
@@ -322,13 +322,13 @@ namespace Jint.Native.Json
                 if (_gap == "")
                 {
                     var separator = ",";
-                    var properties = System.String.Join(separator, partial.ToArray());
+                    var properties = string.Join(separator, partial.ToArray());
                     final = "{" + properties + "}";
                 }
                 else
                 {
                     var separator = ",\n" + _indent;
-                    var properties = System.String.Join(separator, partial.ToArray());
+                    var properties = string.Join(separator, partial.ToArray());
                     final = "{\n" + _indent + properties + "\n" + stepback + "}";
                 }
             }

+ 10 - 0
Jint/Runtime/Interop/ObjectWrapper.cs

@@ -101,6 +101,16 @@ namespace Jint.Runtime.Interop
             if (property is JsString stringKey)
             {
                 var member = stringKey.ToString();
+
+                // expando object for instance
+                if (Target is IDictionary<string, object> stringKeyedDictionary)
+                {
+                    if (stringKeyedDictionary.TryGetValue(member, out var value))
+                    {
+                        return FromObject(_engine, value);
+                    }
+                }
+
                 var result = Engine.Options.Interop.MemberAccessor?.Invoke(Engine, Target, member);
                 if (result is not null)
                 {

+ 1 - 1
Jint/Runtime/Interop/TypeDescriptor.cs

@@ -38,7 +38,7 @@ namespace Jint.Runtime.Interop
 
         private static bool DetermineIfObjectIsArrayLikeClrCollection(Type type)
         {
-            if (typeof(IDictionary).IsAssignableFrom(type))
+            if (typeof(IDictionary).IsAssignableFrom(type) || typeof(IDictionary<string, object>).IsAssignableFrom(type))
             {
                 // dictionaries are considered normal-object-like
                 return false;