Browse Source

Backport fix custom reference resolver argument (#1939)

Marko Lahma 1 year ago
parent
commit
8ce657ffb7
2 changed files with 78 additions and 5 deletions
  1. 62 0
      Jint.Tests.PublicInterface/RavenApiUsageTests.cs
  2. 16 5
      Jint/Engine.cs

+ 62 - 0
Jint.Tests.PublicInterface/RavenApiUsageTests.cs

@@ -202,6 +202,36 @@ public class RavenApiUsageTests
         var engine = new Engine();
         var engine = new Engine();
         engine.Advanced.ResetCallStack();
         engine.Advanced.ResetCallStack();
     }
     }
+
+    [Fact]
+    public void CanUseCustomReferenceResolver()
+    {
+        var engine = new Engine(options =>
+        {
+            options.ReferenceResolver = new MyReferenceResolver();
+        });
+
+        engine
+            .Execute("""
+                          function output(doc) {
+                         var rows123 = [{}];
+                     var test = null;
+                         return { 
+                             Rows : [{}].map(row=>({row:row, myRows:test.filter(x=>x)
+                             })).map(__rvn4=>({
+                                 Custom:__rvn4.myRows[0].Custom,
+                                 Custom2:__rvn4.myRows
+                                 }))
+                                 };
+                     }
+                     """);
+
+        var result = engine.Evaluate("output()");
+
+        var rows = result.AsObject()["Rows"];
+        var custom = rows.AsArray()[0].AsObject()["Custom"];
+        Assert.Equal(JsValue.Null, custom);
+    }
 }
 }
 
 
 file sealed class CustomString : JsString
 file sealed class CustomString : JsString
@@ -288,3 +318,35 @@ file sealed class CustomUndefined : JsValue
         return "null";
         return "null";
     }
     }
 }
 }
+
+file sealed class MyReferenceResolver : IReferenceResolver
+{
+    public bool TryUnresolvableReference(Engine engine, Reference reference, out JsValue value)
+    {
+        JsValue referencedName = reference.ReferencedName;
+
+        if (referencedName.IsString())
+        {
+            value = reference.IsPropertyReference ? JsValue.Undefined : JsValue.Null;
+            return true;
+        }
+
+        throw new InvalidOperationException();
+    }
+
+    public bool TryPropertyReference(Engine engine, Reference reference, ref JsValue value)
+    {
+        return value.IsNull() || value.IsUndefined();
+    }
+
+    public bool TryGetCallable(Engine engine, object callee, out JsValue value)
+    {
+        value = new ClrFunction(engine, "function", static (_, _) => JsValue.Undefined);
+        return true;
+    }
+
+    public bool CheckCoercible(JsValue value)
+    {
+        return true;
+    }
+}

+ 16 - 5
Jint/Engine.cs

@@ -49,7 +49,10 @@ namespace Jint
         internal readonly Constraint[] _constraints;
         internal readonly Constraint[] _constraints;
         internal readonly bool _isDebugMode;
         internal readonly bool _isDebugMode;
         internal readonly bool _isStrict;
         internal readonly bool _isStrict;
+
+        private bool _customResolver;
         internal readonly IReferenceResolver _referenceResolver;
         internal readonly IReferenceResolver _referenceResolver;
+
         internal readonly ReferencePool _referencePool;
         internal readonly ReferencePool _referencePool;
         internal readonly ArgumentsInstancePool _argumentsInstancePool;
         internal readonly ArgumentsInstancePool _argumentsInstancePool;
         internal readonly JsValueArrayPool _jsValueArrayPool;
         internal readonly JsValueArrayPool _jsValueArrayPool;
@@ -134,6 +137,7 @@ namespace Jint
 
 
             _constraints = Options.Constraints.Constraints.ToArray();
             _constraints = Options.Constraints.Constraints.ToArray();
             _referenceResolver = Options.ReferenceResolver;
             _referenceResolver = Options.ReferenceResolver;
+            _customResolver = !ReferenceEquals(_referenceResolver, DefaultReferenceResolver.Instance);
 
 
             _referencePool = new ReferencePool();
             _referencePool = new ReferencePool();
             _argumentsInstancePool = new ArgumentsInstancePool(this);
             _argumentsInstancePool = new ArgumentsInstancePool(this);
@@ -579,18 +583,25 @@ namespace Jint
 
 
             if (baseValue.IsUndefined())
             if (baseValue.IsUndefined())
             {
             {
-                if (_referenceResolver.TryUnresolvableReference(this, reference, out var val))
+                if (_customResolver)
                 {
                 {
-                    return val;
+                    reference.EvaluateAndCachePropertyKey();
+                    if (_referenceResolver.TryUnresolvableReference(this, reference, out var val))
+                    {
+                        return val;
+                    }
                 }
                 }
 
 
                 ExceptionHelper.ThrowReferenceError(Realm, reference);
                 ExceptionHelper.ThrowReferenceError(Realm, reference);
             }
             }
 
 
-            if ((baseValue._type & InternalTypes.ObjectEnvironmentRecord) == InternalTypes.Empty
-                && _referenceResolver.TryPropertyReference(this, reference, ref baseValue))
+            if ((baseValue._type & InternalTypes.ObjectEnvironmentRecord) == InternalTypes.Empty && _customResolver)
             {
             {
-                return baseValue;
+                reference.EvaluateAndCachePropertyKey();
+                if (_referenceResolver.TryPropertyReference(this, reference, ref baseValue))
+                {
+                    return baseValue;
+                }
             }
             }
 
 
             if (reference.IsPropertyReference)
             if (reference.IsPropertyReference)