diff --git a/IntegrationTests/JavaScriptKitExec/Sources/JavaScriptKitExec/main.swift b/IntegrationTests/JavaScriptKitExec/Sources/JavaScriptKitExec/main.swift index 8bc2cd1c8..a5fca9a59 100644 --- a/IntegrationTests/JavaScriptKitExec/Sources/JavaScriptKitExec/main.swift +++ b/IntegrationTests/JavaScriptKitExec/Sources/JavaScriptKitExec/main.swift @@ -299,3 +299,27 @@ Object_Conversion: do { } catch { print(error) } + +ObjectRef_Lifetime: do { + // ```js + // global.globalObject1 = { + // "prop_1": { + // "nested_prop": 1, + // }, + // "prop_2": 2, + // "prop_3": true, + // "prop_4": [ + // 3, 4, "str_elm_1", 5, + // ], + // ... + // } + // ``` + + let identity = JSClosure { $0[0] } + let ref1 = getJSValue(this: .global, name: "globalObject1").object! + let ref2 = identity(ref1).object! + try expectEqual(ref1.prop_2, .number(2)) + try expectEqual(ref2.prop_2, .number(2)) +} catch { + print(error) +} \ No newline at end of file diff --git a/Runtime/src/index.ts b/Runtime/src/index.ts index 9084af7e0..b37756789 100644 --- a/Runtime/src/index.ts +++ b/Runtime/src/index.ts @@ -50,22 +50,29 @@ class SwiftRuntimeHeap { allocHeap(value: any) { const isObject = typeof value == "object" if (isObject && value.swjs_heap_id) { + value.swjs_heap_rc++; return value.swjs_heap_id } const id = this._heapNextKey++; this._heapValues.set(id, value) - if (isObject) + if (isObject) { Reflect.set(value, "swjs_heap_id", id); + Reflect.set(value, "swjs_heap_rc", 1); + } return id } freeHeap(ref: ref) { const value = this._heapValues.get(ref); const isObject = typeof value == "object" - if (isObject && value.swjs_heap_id) { + if (isObject) { + const rc = --value.swjs_heap_rc; + if (rc != 0) return; delete value.swjs_heap_id; + this._heapValues.delete(ref) + } else { + this._heapValues.delete(ref) } - this._heapValues.delete(ref) } referenceHeap(ref: ref) {