Browse Source

Fix optional member call (#1233)

Marko Lahma 3 years ago
parent
commit
79fbf108a5

+ 17 - 0
Jint.Tests/Runtime/EngineTests.cs

@@ -2865,6 +2865,23 @@ x.test = {
             Assert.Equal("[\"02100\"]", engine.Evaluate("JSON.stringify(Object.getOwnPropertyNames(testObj));").AsString());
         }
 
+        [Fact]
+        public void ShouldAllowOptionalChainingForMemberCall()
+        {
+            var engine = new Engine();
+            const string Script = @"
+                const adventurer = {  name: 'Alice', cat: { name: 'Dinah' } };
+                const dogName = adventurer.dog?.name;
+                const methodResult = adventurer.someNonExistentMethod?.();
+                return [ dogName, methodResult ];
+            ";
+            var array = engine.Evaluate(Script).AsArray();
+
+            Assert.Equal(2L, array.Length);
+            Assert.True(array[0].IsUndefined());
+            Assert.True(array[1].IsUndefined());
+        }
+
         private class Wrapper
         {
             public Testificate Test { get; set; }

+ 8 - 3
Jint/Runtime/Interpreter/Expressions/JintCallExpression.cs

@@ -119,6 +119,11 @@ namespace Jint.Runtime.Interpreter.Expressions
             var engine = context.Engine;
             var func = engine.GetValue(reference, false);
 
+            if (func.IsNullOrUndefined() && _expression.IsOptional())
+            {
+                return Undefined.Instance;
+            }
+
             if (reference is Reference referenceRecord
                 && !referenceRecord.IsPropertyReference()
                 && referenceRecord.GetReferencedName() == CommonProperties.Eval
@@ -134,7 +139,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                 var evalArg = argList[0];
                 var strictCaller = StrictModeScope.IsStrictModeCode;
                 var evalRealm = evalFunctionInstance._realm;
-                var direct = !((CallExpression) _expression).Optional;
+                var direct = !_expression.IsOptional();
                 var value = evalFunctionInstance.PerformEval(evalArg, evalRealm, strictCaller, direct);
                 engine._referencePool.Return(referenceRecord);
                 return value;
@@ -172,7 +177,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                     else
                     {
                         var refEnv = (EnvironmentRecord) baseValue;
-                        thisValue = refEnv.WithBaseObject();   
+                        thisValue = refEnv.WithBaseObject();
                     }
                 }
             }
@@ -257,4 +262,4 @@ namespace Jint.Runtime.Interpreter.Expressions
             internal JsValue[] CachedArguments;
         }
     }
-}
+}