From 8ce657ffb7e5d03b60017926ffc5b025b8f5c37b Mon Sep 17 00:00:00 2001 From: Marko Lahma Date: Sat, 10 Aug 2024 09:52:30 +0300 Subject: [PATCH] Backport fix custom reference resolver argument (#1939) --- .../RavenApiUsageTests.cs | 62 +++++++++++++++++++ Jint/Engine.cs | 21 +++++-- 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/Jint.Tests.PublicInterface/RavenApiUsageTests.cs b/Jint.Tests.PublicInterface/RavenApiUsageTests.cs index e0b5df9ce0..1cd0899405 100644 --- a/Jint.Tests.PublicInterface/RavenApiUsageTests.cs +++ b/Jint.Tests.PublicInterface/RavenApiUsageTests.cs @@ -202,6 +202,36 @@ public void CanResetCallStack() var engine = new Engine(); 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 @@ -288,3 +318,35 @@ public override string ToString() 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; + } +} diff --git a/Jint/Engine.cs b/Jint/Engine.cs index 1bee5f8eba..f846f65fc6 100644 --- a/Jint/Engine.cs +++ b/Jint/Engine.cs @@ -49,7 +49,10 @@ public sealed partial class Engine : IDisposable internal readonly Constraint[] _constraints; internal readonly bool _isDebugMode; internal readonly bool _isStrict; + + private bool _customResolver; internal readonly IReferenceResolver _referenceResolver; + internal readonly ReferencePool _referencePool; internal readonly ArgumentsInstancePool _argumentsInstancePool; internal readonly JsValueArrayPool _jsValueArrayPool; @@ -134,6 +137,7 @@ private Engine(Options? options, Action? configure) _constraints = Options.Constraints.Constraints.ToArray(); _referenceResolver = Options.ReferenceResolver; + _customResolver = !ReferenceEquals(_referenceResolver, DefaultReferenceResolver.Instance); _referencePool = new ReferencePool(); _argumentsInstancePool = new ArgumentsInstancePool(this); @@ -579,18 +583,25 @@ internal JsValue GetValue(Reference reference, bool returnReferenceToPool) 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); } - 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)