diff --git a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift index 60806e671..1672b5855 100644 --- a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift +++ b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift @@ -331,6 +331,22 @@ ObjectRef_Lifetime: do { let ref2 = identity(ref1).object! try expectEqual(ref1.prop_2, .number(2)) try expectEqual(ref2.prop_2, .number(2)) + identity.release() +} catch { + print(error) +} + +func closureScope() -> ObjectIdentifier { + let closure = JSClosure { _ in .undefined } + let result = ObjectIdentifier(closure) + closure.release() + return result +} + +Closure_Identifiers: do { + let oid1 = closureScope() + let oid2 = closureScope() + try expectEqual(oid1, oid2) } catch { print(error) } diff --git a/Sources/JavaScriptKit/JSFunction.swift b/Sources/JavaScriptKit/JSFunction.swift index 09586c6cb..8914fbd87 100644 --- a/Sources/JavaScriptKit/JSFunction.swift +++ b/Sources/JavaScriptKit/JSFunction.swift @@ -68,6 +68,8 @@ public class JSClosure: JSFunctionRef { private var hostFuncRef: JavaScriptHostFuncRef = 0 + private var isReleased = false + public init(_ body: @escaping ([JSValue]) -> JSValue) { super.init(id: 0) let objectId = ObjectIdentifier(self) @@ -83,6 +85,16 @@ public class JSClosure: JSFunctionRef { public func release() { Self.sharedFunctions[hostFuncRef] = nil + isReleased = true + } + + deinit { + guard isReleased else { + fatalError(""" + release() must be called on closures manually before deallocating. + This is caused by the lack of support for the `FinalizationRegistry` API in Safari. + """) + } } }