From 32e4d9e9a9575d8046e407486c575df4c5aead35 Mon Sep 17 00:00:00 2001 From: Jason Ginchereau Date: Mon, 22 Jul 2024 12:30:13 -0700 Subject: [PATCH 1/2] Fix weak reference handling in runtime object map --- src/NodeApi/Interop/JSRuntimeContext.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/NodeApi/Interop/JSRuntimeContext.cs b/src/NodeApi/Interop/JSRuntimeContext.cs index 1fe533a8..42732732 100644 --- a/src/NodeApi/Interop/JSRuntimeContext.cs +++ b/src/NodeApi/Interop/JSRuntimeContext.cs @@ -371,11 +371,10 @@ private JSValue GetOrCreateObjectWrapper(T obj, Func createWrapper) if (_objectMap.TryGetValue(obj, out JSReference? wrapperWeakRef) && !wrapperWeakRef.IsDisposed) { - JSValue? existingWrapper = wrapperWeakRef.GetValue(); - if (existingWrapper.HasValue) + if (wrapperWeakRef.TryGetValue(out JSValue existingWrapper)) { // Return the JS wrapper that was found in the map. - return existingWrapper.Value; + return existingWrapper; } else { From 2a48504af712f25e1cfbbcae080d54c5d354cfd7 Mon Sep 17 00:00:00 2001 From: Jason Ginchereau Date: Wed, 24 Jul 2024 10:48:50 -0700 Subject: [PATCH 2/2] Add object-map test case --- test/TestCases/napi-dotnet/object_map.js | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 test/TestCases/napi-dotnet/object_map.js diff --git a/test/TestCases/napi-dotnet/object_map.js b/test/TestCases/napi-dotnet/object_map.js new file mode 100644 index 00000000..226f0b9b --- /dev/null +++ b/test/TestCases/napi-dotnet/object_map.js @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +// Test the JSRuntimeContext "object map" which keeps track of JS wrapper objects +// for corresponding .NET objects. + +const assert = require('assert'); + +/** @type {import('./napi-dotnet')} */ +const binding = require('../common').binding; + +const ComplexTypes = binding.ComplexTypes; +assert.strictEqual(typeof ComplexTypes, 'object'); + +let obj1 = ComplexTypes.classObject; +assert(obj1); + +// The same JS wrapper instance should be returned every time. +let obj2 = ComplexTypes.classObject; +assert.strictEqual(obj1, obj2); + +// Force the JS wrapper object to be collected. +obj1 = obj2 = undefined; +global.gc(); + +// A new JS wrapper object should be created. +let obj3 = ComplexTypes.classObject; +assert(obj3);