diff --git a/Jint/Engine.cs b/Jint/Engine.cs index 0b3604b621..456672cd79 100644 --- a/Jint/Engine.cs +++ b/Jint/Engine.cs @@ -1,4 +1,5 @@ -using System.Runtime.CompilerServices; +using System.Reflection; +using System.Runtime.CompilerServices; using Esprima; using Esprima.Ast; using Jint.Native; @@ -53,7 +54,7 @@ public sealed partial class Engine : IDisposable internal readonly Dictionary TypeCache = new(); // cache for already wrapped CLR objects to keep object identity - internal readonly ConditionalWeakTable _objectWrapperCache = new(); + internal ConditionalWeakTable? _objectWrapperCache; internal readonly JintCallStack CallStack; @@ -1426,7 +1427,18 @@ private ObjectInstance Construct( public void Dispose() { - // no-op for now + if (_objectWrapperCache is null) + { + return; + } + +#if NETSTANDARD2_1_OR_GREATER + _objectWrapperCache.Clear(); +#else + // we can expect that reflection is OK as we've been generating object wrappers already + var clearMethod = _objectWrapperCache.GetType().GetMethod("Clear", BindingFlags.Instance | BindingFlags.NonPublic); + clearMethod?.Invoke(_objectWrapperCache, Array.Empty()); +#endif } } } diff --git a/Jint/Runtime/Interop/DefaultObjectConverter.cs b/Jint/Runtime/Interop/DefaultObjectConverter.cs index fe7a2c8d69..81ba34cc5e 100644 --- a/Jint/Runtime/Interop/DefaultObjectConverter.cs +++ b/Jint/Runtime/Interop/DefaultObjectConverter.cs @@ -1,6 +1,8 @@ using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Threading; using Jint.Native; +using Jint.Native.Object; using Jint.Runtime; using Jint.Runtime.Interop; @@ -101,7 +103,7 @@ public static bool TryConvert(Engine engine, object value, [NotNullWhen(true)] o else { // check global cache, have we already wrapped the value? - if (engine._objectWrapperCache.TryGetValue(value, out var cached)) + if (engine._objectWrapperCache?.TryGetValue(value, out var cached) == true) { result = cached; } @@ -112,6 +114,7 @@ public static bool TryConvert(Engine engine, object value, [NotNullWhen(true)] o if (engine.Options.Interop.TrackObjectWrapperIdentity && wrapped is not null) { + engine._objectWrapperCache ??= new ConditionalWeakTable(); engine._objectWrapperCache.Add(value, wrapped); } }