Ver código fonte

Clear interop identity tracking ConditionalWeakTable in Engine.Dispose (#1408)

Marko Lahma 2 anos atrás
pai
commit
57d142954e
2 arquivos alterados com 19 adições e 4 exclusões
  1. 15 3
      Jint/Engine.cs
  2. 4 1
      Jint/Runtime/Interop/DefaultObjectConverter.cs

+ 15 - 3
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 @@ namespace Jint
         internal readonly Dictionary<string, Type?> TypeCache = new();
 
         // cache for already wrapped CLR objects to keep object identity
-        internal readonly ConditionalWeakTable<object, ObjectInstance> _objectWrapperCache = new();
+        internal ConditionalWeakTable<object, ObjectInstance>? _objectWrapperCache;
 
         internal readonly JintCallStack CallStack;
 
@@ -1426,7 +1427,18 @@ namespace Jint
 
         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<object>());
+#endif
         }
     }
 }

+ 4 - 1
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 @@ namespace Jint
                     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 @@ namespace Jint
 
                             if (engine.Options.Interop.TrackObjectWrapperIdentity && wrapped is not null)
                             {
+                                engine._objectWrapperCache ??= new ConditionalWeakTable<object, ObjectInstance>();
                                 engine._objectWrapperCache.Add(value, wrapped);
                             }
                         }