Skip to content

Commit d987c3e

Browse files
Refactor JSClosure to leverage FinalizationRegistry (#128)
* Refactor JSClosure to leverage FinalizationRegistry * Restore support for older runtimes using JSOneshotClosure + JSUnretainedClosure * Bump TS version * Fix build errors * Add escape hatch for old environments (#139) Co-authored-by: Yuta Saito <kateinoigakukun@gmail.com>
1 parent a08e46b commit d987c3e

File tree

12 files changed

+237
-150
lines changed

12 files changed

+237
-150
lines changed

IntegrationTests/Makefile

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
CONFIGURATION ?= debug
2+
SWIFT_BUILD_FLAGS ?=
23

34
FORCE:
45
TestSuites/.build/$(CONFIGURATION)/%.wasm: FORCE
56
swift build --package-path TestSuites \
67
--product $(basename $(notdir $@)) \
78
--triple wasm32-unknown-wasi \
8-
--configuration $(CONFIGURATION)
9+
--configuration $(CONFIGURATION) \
10+
$(SWIFT_BUILD_FLAGS)
911

1012
dist/%.wasm: TestSuites/.build/$(CONFIGURATION)/%.wasm
1113
mkdir -p dist

IntegrationTests/TestSuites/Sources/BenchmarkTests/Benchmark.swift

-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,5 @@ class Benchmark {
1515
return .undefined
1616
}
1717
runner("\(title)/\(name)", jsBody)
18-
jsBody.release()
1918
}
2019
}

IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift

+36-13
Original file line numberDiff line numberDiff line change
@@ -197,28 +197,39 @@ try test("Closure Lifetime") {
197197
return arguments[0]
198198
}
199199
try expectEqual(evalClosure(c1, JSValue.number(1.0)), .number(1.0))
200+
#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
200201
c1.release()
202+
#endif
201203
}
202204

203205
do {
204-
let c1 = JSClosure { arguments in
205-
return arguments[0]
206-
}
206+
let c1 = JSClosure { _ in .undefined }
207+
#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
207208
c1.release()
208-
// Call a released closure
209-
try expectCrashByCall(ofClosure: c1)
209+
#endif
210210
}
211211

212212
do {
213-
let c1 = JSClosure { _ in
214-
// JSClosure will be deallocated before `release()`
215-
_ = JSClosure { _ in .undefined }
216-
return .undefined
217-
}
218-
try expectCrashByCall(ofClosure: c1)
213+
let array = JSObject.global.Array.function!.new()
214+
let c1 = JSClosure { _ in .number(3) }
215+
_ = array.push!(c1)
216+
try expectEqual(array[0].function!().number, 3.0)
217+
#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
219218
c1.release()
219+
#endif
220220
}
221221

222+
// do {
223+
// let weakRef = { () -> JSObject in
224+
// let c1 = JSClosure { _ in .undefined }
225+
// return JSObject.global.WeakRef.function!.new(c1)
226+
// }()
227+
//
228+
// // unsure if this will actually work since GC may not run immediately
229+
// try expectEqual(weakRef.deref!(), .undefined)
230+
// }
231+
232+
#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
222233
do {
223234
let c1 = JSOneshotClosure { _ in
224235
return .boolean(true)
@@ -228,6 +239,7 @@ try test("Closure Lifetime") {
228239
try expectCrashByCall(ofClosure: c1)
229240
// OneshotClosure won't call fatalError even if it's deallocated before `release`
230241
}
242+
#endif
231243
}
232244

233245
try test("Host Function Registration") {
@@ -259,7 +271,9 @@ try test("Host Function Registration") {
259271
try expectEqual(call_host_1Func(), .number(1))
260272
try expectEqual(isHostFunc1Called, true)
261273

274+
#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
262275
hostFunc1.release()
276+
#endif
263277

264278
let hostFunc2 = JSClosure { (arguments) -> JSValue in
265279
do {
@@ -272,7 +286,10 @@ try test("Host Function Registration") {
272286

273287
try expectEqual(evalClosure(hostFunc2, 3), .number(6))
274288
_ = try expectString(evalClosure(hostFunc2, true))
289+
290+
#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
275291
hostFunc2.release()
292+
#endif
276293
}
277294

278295
try test("New Object Construction") {
@@ -386,9 +403,13 @@ try test("ObjectRef Lifetime") {
386403
let ref2 = evalClosure(identity, ref1).object!
387404
try expectEqual(ref1.prop_2, .number(2))
388405
try expectEqual(ref2.prop_2, .number(2))
406+
407+
#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
389408
identity.release()
409+
#endif
390410
}
391411

412+
#if JAVASCRIPTKIT_WITHOUT_WEAKREFS
392413
func closureScope() -> ObjectIdentifier {
393414
let closure = JSClosure { _ in .undefined }
394415
let result = ObjectIdentifier(closure)
@@ -401,6 +422,7 @@ try test("Closure Identifiers") {
401422
let oid2 = closureScope()
402423
try expectEqual(oid1, oid2)
403424
}
425+
#endif
404426

405427
func checkArray<T>(_ array: [T]) throws where T: TypedArrayElement {
406428
try expectEqual(toString(JSTypedArray(array).jsValue().object!), jsStringify(array))
@@ -519,7 +541,7 @@ try test("Timer") {
519541
interval = JSTimer(millisecondsDelay: 5, isRepeating: true) {
520542
// ensure that JSTimer is living
521543
try! expectNotNil(interval)
522-
// verify that at least `timeoutMilliseconds * count` passed since the `timeout`
544+
// verify that at least `timeoutMilliseconds * count` passed since the `timeout`
523545
// timer started
524546
try! expectEqual(start + timeoutMilliseconds * count <= JSDate().valueOf(), true)
525547

@@ -555,7 +577,8 @@ try test("Promise") {
555577
exp1.fulfill()
556578
return JSValue.undefined
557579
}
558-
.catch { _ -> JSValue in
580+
.catch { err -> JSValue in
581+
print(err.object!.stack.string!)
559582
fatalError("Not fired due to no throw")
560583
}
561584
.finally { exp1.fulfill() }

0 commit comments

Comments
 (0)