From 4082c87f2608521a4c9621bfb71f487528449734 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Tue, 4 Aug 2020 23:01:14 +0100 Subject: [PATCH 1/4] Change `JSClosure.release` to `deinit` --- .../TestSuites/Sources/PrimaryTests/main.swift | 16 +++++++++++++--- Sources/JavaScriptKit/JSFunction.swift | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift index 60806e671..f42de6059 100644 --- a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift +++ b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift @@ -207,8 +207,6 @@ Host_Function_Registration: do { try expectEqual(call_host_1Func(), .number(1)) try expectEqual(isHostFunc1Called, true) - hostFunc1.release() - let hostFunc2 = JSClosure { (arguments) -> JSValue in do { let input = try expectNumber(arguments[0]) @@ -220,7 +218,6 @@ Host_Function_Registration: do { try expectEqual(hostFunc2(3), .number(6)) _ = try expectString(hostFunc2(true)) - hostFunc2.release() } catch { print(error) } @@ -334,3 +331,16 @@ ObjectRef_Lifetime: do { } catch { print(error) } + +func closureScope() -> ObjectIdentifier { + let closure = JSClosure { _ in .undefined } + return ObjectIdentifier(closure) +} + +Closure_References: do { + let oid1 = closureScope() + let oid2 = closureScope() + try expectEqual(oid1, oid2) +} catch { + print(error) +} \ No newline at end of file diff --git a/Sources/JavaScriptKit/JSFunction.swift b/Sources/JavaScriptKit/JSFunction.swift index 09586c6cb..b8c042dce 100644 --- a/Sources/JavaScriptKit/JSFunction.swift +++ b/Sources/JavaScriptKit/JSFunction.swift @@ -81,7 +81,7 @@ public class JSClosure: JSFunctionRef { id = objectRef } - public func release() { + deinit { Self.sharedFunctions[hostFuncRef] = nil } } From 498b6badfd06f7ef6353bc634b6ed3b9ad35e9e3 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Tue, 4 Aug 2020 23:01:41 +0100 Subject: [PATCH 2/4] Rename test case in PrimaryTests --- IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift index f42de6059..62a53fe46 100644 --- a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift +++ b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift @@ -337,7 +337,7 @@ func closureScope() -> ObjectIdentifier { return ObjectIdentifier(closure) } -Closure_References: do { +Closure_Identifiers: do { let oid1 = closureScope() let oid2 = closureScope() try expectEqual(oid1, oid2) From b4042fafca98763ccfce1972c84021148e50b8b5 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Tue, 4 Aug 2020 23:02:24 +0100 Subject: [PATCH 3/4] Add newline to `PrimaryTests/main.swift` --- IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift index 62a53fe46..c87e27946 100644 --- a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift +++ b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift @@ -343,4 +343,4 @@ Closure_Identifiers: do { try expectEqual(oid1, oid2) } catch { print(error) -} \ No newline at end of file +} From 3420079e48dca2f6da4e6828d4b7c945d6ed0312 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Mon, 10 Aug 2020 16:24:42 +0100 Subject: [PATCH 4/4] Add `isRelease` property to `JSClosure` --- .../TestSuites/Sources/PrimaryTests/main.swift | 8 +++++++- Sources/JavaScriptKit/JSFunction.swift | 14 +++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift index c87e27946..1672b5855 100644 --- a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift +++ b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift @@ -207,6 +207,8 @@ Host_Function_Registration: do { try expectEqual(call_host_1Func(), .number(1)) try expectEqual(isHostFunc1Called, true) + hostFunc1.release() + let hostFunc2 = JSClosure { (arguments) -> JSValue in do { let input = try expectNumber(arguments[0]) @@ -218,6 +220,7 @@ Host_Function_Registration: do { try expectEqual(hostFunc2(3), .number(6)) _ = try expectString(hostFunc2(true)) + hostFunc2.release() } catch { print(error) } @@ -328,13 +331,16 @@ 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 } - return ObjectIdentifier(closure) + let result = ObjectIdentifier(closure) + closure.release() + return result } Closure_Identifiers: do { diff --git a/Sources/JavaScriptKit/JSFunction.swift b/Sources/JavaScriptKit/JSFunction.swift index b8c042dce..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) @@ -81,8 +83,18 @@ public class JSClosure: JSFunctionRef { id = objectRef } - deinit { + 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. + """) + } } }