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 { 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);