Skip to content

Commit

Permalink
Track TypeReference registrations and use as prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
lahma committed Oct 28, 2023
1 parent 5ee35f1 commit e8a42d4
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 1 deletion.
5 changes: 5 additions & 0 deletions Jint.Tests/Runtime/InteropTests.TypeReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ public void CanRegisterToStringTag()

Assert.Equal("[object Dependency]", _engine.Evaluate("Object.prototype.toString.call(c);"));
Assert.Equal(123, _engine.Evaluate("c.abc"));

// engine uses registered type reference
_engine.SetValue("c2", new Dependency());
Assert.Equal("[object Dependency]", _engine.Evaluate("Object.prototype.toString.call(c2);"));
Assert.Equal(123, _engine.Evaluate("c2.abc"));
}

private class Injectable
Expand Down
9 changes: 9 additions & 0 deletions Jint/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ public sealed partial class Engine : IDisposable
// cache of types used when resolving CLR type names
internal readonly Dictionary<string, Type?> TypeCache = new();

// we use registered type reference as prototype if it's known
internal Dictionary<Type,TypeReference>? _typeReferences;

// cache for already wrapped CLR objects to keep object identity
internal ConditionalWeakTable<object, ObjectInstance>? _objectWrapperCache;

Expand Down Expand Up @@ -1562,6 +1565,12 @@ internal void SignalError(ErrorDispatchInfo error)
_error = error;
}

internal void RegisterTypeReference(TypeReference reference)
{
_typeReferences ??= new Dictionary<Type, TypeReference>();
_typeReferences[reference.ReferenceType] = reference;
}

public void Dispose()
{
if (_objectWrapperCache is null)
Expand Down
7 changes: 7 additions & 0 deletions Jint/Runtime/Interop/DefaultObjectConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,13 @@ public static bool TryConvert(Engine engine, object value, Type? type, [NotNullW
else
{
var wrapped = engine.Options.Interop.WrapObjectHandler.Invoke(engine, value, type);

if (ReferenceEquals(wrapped?.GetPrototypeOf(), engine.Realm.Intrinsics.Object.PrototypeObject)
&& engine._typeReferences?.TryGetValue(t, out var typeReference) == true)
{
wrapped.SetPrototypeOf(typeReference);
}

result = wrapped;

if (engine.Options.Interop.TrackObjectWrapperIdentity && wrapped is not null)
Expand Down
4 changes: 3 additions & 1 deletion Jint/Runtime/Interop/TypeReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ public static TypeReference CreateTypeReference<T>(Engine engine)

public static TypeReference CreateTypeReference(Engine engine, Type type)
{
return new TypeReference(engine, type);
var reference = new TypeReference(engine, type);
engine.RegisterTypeReference(reference);
return reference;
}

protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
Expand Down

0 comments on commit e8a42d4

Please sign in to comment.