Skip to content

Commit 32929bb

Browse files
BridgeJS: Add lifetime tracking mode to BridgeJSLink
1 parent 28b97a9 commit 32929bb

File tree

1 file changed

+45
-2
lines changed

1 file changed

+45
-2
lines changed

Plugins/BridgeJS/Sources/BridgeJSLink/BridgeJSLink.swift

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@ import BridgeJSUtilities
1010
public struct BridgeJSLink {
1111
var skeletons: [BridgeJSSkeleton] = []
1212
let sharedMemory: Bool
13+
/// Whether to track the lifetime of Swift objects.
14+
///
15+
/// This is useful for debugging memory issues.
16+
let enableLifetimeTracking: Bool = false
1317
private let namespaceBuilder = NamespaceBuilder()
1418
private let intrinsicRegistry = JSIntrinsicRegistry()
1519

1620
public init(
1721
skeletons: [BridgeJSSkeleton] = [],
18-
sharedMemory: Bool
22+
sharedMemory: Bool = false
1923
) {
2024
self.skeletons = skeletons
2125
self.sharedMemory = sharedMemory
@@ -50,8 +54,33 @@ public struct BridgeJSLink {
5054
}
5155
"""
5256

53-
let swiftHeapObjectClassJs = """
57+
let lifetimeTrackingClassJs = """
58+
const TRACKING = {
59+
wrap: (pointer, deinit, prototype, state) => {
60+
console.log(JSON.stringify({ DEBUG: true, event: "WRP", class: prototype.constructor.name, state }));
61+
},
62+
release: (obj) => {
63+
console.log(JSON.stringify({ DEBUG: true, event: "REL", class: obj.constructor.name, state: obj.__swiftHeapObjectState }));
64+
},
65+
finalization: (state) => {
66+
console.log(JSON.stringify({ DEBUG: true, event: "FIN", state }));
67+
}
68+
};
69+
"""
70+
71+
var swiftHeapObjectClassJs: String {
72+
var output = ""
73+
if enableLifetimeTracking {
74+
output += lifetimeTrackingClassJs + "\n"
75+
}
76+
output += """
5477
const swiftHeapObjectFinalizationRegistry = (typeof FinalizationRegistry === "undefined") ? { register: () => {}, unregister: () => {} } : new FinalizationRegistry((state) => {
78+
79+
"""
80+
if enableLifetimeTracking {
81+
output += " TRACKING.finalization(state);\n"
82+
}
83+
output += """
5584
if (state.hasReleased) {
5685
return;
5786
}
@@ -64,13 +93,25 @@ public struct BridgeJSLink {
6493
static __wrap(pointer, deinit, prototype) {
6594
const obj = Object.create(prototype);
6695
const state = { pointer, deinit, hasReleased: false };
96+
97+
"""
98+
if enableLifetimeTracking {
99+
output += " TRACKING.wrap(pointer, deinit, prototype, state);\n"
100+
}
101+
output += """
67102
obj.pointer = pointer;
68103
obj.__swiftHeapObjectState = state;
69104
swiftHeapObjectFinalizationRegistry.register(obj, state, state);
70105
return obj;
71106
}
72107
73108
release() {
109+
110+
"""
111+
if enableLifetimeTracking {
112+
output += " TRACKING.release(this);\n"
113+
}
114+
output += """
74115
const state = this.__swiftHeapObjectState;
75116
if (state.hasReleased) {
76117
return;
@@ -81,6 +122,8 @@ public struct BridgeJSLink {
81122
}
82123
}
83124
"""
125+
return output
126+
}
84127

85128
fileprivate struct LinkData {
86129
var exportsLines: [String] = []

0 commit comments

Comments
 (0)