Browse Source

Allowing to use nullable propagation on callables again. Fixed #1041 (#1042)

Ayende Rahien 3 years ago
parent
commit
ff6765bf1a

+ 31 - 2
Jint.Tests/Runtime/NullPropagation.cs

@@ -1,4 +1,5 @@
-using Esprima;
+using System;
+using Esprima;
 using Jint.Native;
 using Jint.Runtime;
 using Jint.Runtime.Interop;
@@ -22,8 +23,18 @@ namespace Jint.Tests.Runtime
                 return value.IsNull() || value.IsUndefined();
             }
 
-            public bool TryGetCallable(Engine engine, object reference, out JsValue value)
+            public bool TryGetCallable(Engine engine, object callee, out JsValue value)
             {
+                if (callee is Reference reference)
+                {
+                    var name = reference.GetReferencedName().AsString();
+                    if (name == "filter")
+                    {
+                        value = new ClrFunctionInstance(engine, "map", (thisObj, values) => engine.Realm.Intrinsics.Array.ConstructFast(0));
+                        return true;
+                    }
+                }
+
                 value = new ClrFunctionInstance(engine, "anonymous", (thisObj, values) => thisObj);
                 return true;
             }
@@ -34,6 +45,24 @@ namespace Jint.Tests.Runtime
             }
         }
 
+        [Fact]
+        public void CanCallFilterOnNull()
+        {
+            var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
+
+            const string Script = @"
+var input = {};
+
+var output = { Tags : input.Tags.filter(x=>x!=null) };
+";
+
+            engine.Execute(Script);
+
+            var output = engine.GetValue("output").AsObject();
+
+            Assert.True(output.Get("Tags").IsArray());
+        }
+
         [Fact]
         public void NullPropagationTest()
         {

+ 6 - 4
Jint/Runtime/Interpreter/Expressions/JintCallExpression.cs

@@ -167,11 +167,13 @@ namespace Jint.Runtime.Interpreter.Expressions
                     if (baseValue.IsNullOrUndefined()
                         && engine._referenceResolver.TryUnresolvableReference(engine, referenceRecord, out var value))
                     {
-                        return value;
+                        thisValue = value;
+                    }
+                    else
+                    {
+                        var refEnv = (EnvironmentRecord) baseValue;
+                        thisValue = refEnv.WithBaseObject();   
                     }
-
-                    var refEnv = (EnvironmentRecord) baseValue;
-                    thisValue = refEnv.WithBaseObject();
                 }
             }
             else