Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backport fix custom reference resolver argument #1939

Merged
merged 1 commit into from
Aug 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions Jint.Tests.PublicInterface/RavenApiUsageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
}
21 changes: 16 additions & 5 deletions Jint/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -134,6 +137,7 @@ private Engine(Options? options, Action<Engine, Options>? configure)

_constraints = Options.Constraints.Constraints.ToArray();
_referenceResolver = Options.ReferenceResolver;
_customResolver = !ReferenceEquals(_referenceResolver, DefaultReferenceResolver.Instance);

_referencePool = new ReferencePool();
_argumentsInstancePool = new ArgumentsInstancePool(this);
Expand Down Expand Up @@ -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)
Expand Down