Skip to content

Commit 2eac5f5

Browse files
Added tracing unit coverage and wired the trait into the Makefile’s unittest target.
- New `Tests/JavaScriptKitTests/JSTracingTests.swift` exercises JS→JS call hooks (ensures method info/method name/args) and JSClosure hooks (verifies file/line metadata and end callbacks) under `#if Tracing`. - Refactored tracing-overloaded helpers to avoid conditional parameters and added `Sendable` to `JSTracing` to satisfy Swift 6 safety (`Sources/JavaScriptKit/FundamentalObjects/JSObject+CallAsFunction.swift`, `Sources/JavaScriptKit/JSTracing.swift`). - `make unittest` now enables the `Tracing` trait so tracing hooks compile during test runs (`Makefile`). I attempted `swift test --traits Tracing`; the build passed the new tracing warnings but the compiler crashed later with an unrelated wasm memory.grow codegen bug, so tests didn’t finish. You can rerun `make unittest SWIFT_SDK_ID=<id>`; expect the same toolchain crash until Swift fixes that issue.
1 parent cfba93d commit 2eac5f5

File tree

4 files changed

+81
-16
lines changed

4 files changed

+81
-16
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ unittest:
1212
exit 2; \
1313
}
1414
env JAVASCRIPTKIT_EXPERIMENTAL_BRIDGEJS=1 swift package --swift-sdk "$(SWIFT_SDK_ID)" \
15+
--traits Tracing \
1516
--disable-sandbox \
1617
js test --prelude ./Tests/prelude.mjs -Xnode --expose-gc
1718

Sources/JavaScriptKit/FundamentalObjects/JSObject+CallAsFunction.swift

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -132,29 +132,37 @@ extension JSObject {
132132
return result
133133
}
134134

135+
#if Tracing
135136
final func invokeNonThrowingJSFunction(
136137
arguments: [JSValue],
137-
this: JSObject
138-
#if Tracing
139-
, tracedMethodName: String? = nil
140-
#endif
138+
this: JSObject,
139+
tracedMethodName: String? = nil
141140
) -> RawJSValue {
142-
#if Tracing
143141
let traceEnd = JSTracingHooks.beginJSCall(
144142
.method(receiver: this, methodName: tracedMethodName, arguments: arguments)
145143
)
146-
#endif
147144
let result = arguments.withRawJSValues {
148145
invokeNonThrowingJSFunction(
149146
rawValues: $0,
150147
this: this
151148
)
152149
}
153-
#if Tracing
154150
traceEnd?()
155-
#endif
156151
return result
157152
}
153+
#else
154+
final func invokeNonThrowingJSFunction(
155+
arguments: [JSValue],
156+
this: JSObject
157+
) -> RawJSValue {
158+
arguments.withRawJSValues {
159+
invokeNonThrowingJSFunction(
160+
rawValues: $0,
161+
this: this
162+
)
163+
}
164+
}
165+
#endif
158166

159167
#if !hasFeature(Embedded)
160168
final func invokeNonThrowingJSFunction(arguments: [ConvertibleToJSValue]) -> RawJSValue {
@@ -166,25 +174,28 @@ extension JSObject {
166174
#endif
167175
}
168176

177+
#if Tracing
169178
final func invokeNonThrowingJSFunction(
170179
arguments: [ConvertibleToJSValue],
171-
this: JSObject
172-
#if Tracing
173-
, tracedMethodName: String? = nil
174-
#endif
180+
this: JSObject,
181+
tracedMethodName: String? = nil
175182
) -> RawJSValue {
176-
#if Tracing
177183
let jsValues = arguments.map { $0.jsValue }
178184
return invokeNonThrowingJSFunction(
179185
arguments: jsValues,
180186
this: this,
181187
tracedMethodName: tracedMethodName
182188
)
183-
#else
189+
}
190+
#else
191+
final func invokeNonThrowingJSFunction(
192+
arguments: [ConvertibleToJSValue],
193+
this: JSObject
194+
) -> RawJSValue {
184195
arguments.withRawJSValues { invokeNonThrowingJSFunction(rawValues: $0, this: this) }
185-
#endif
186196
}
187197
#endif
198+
#endif
188199

189200
final private func invokeNonThrowingJSFunction(rawValues: [RawJSValue]) -> RawJSValue {
190201
rawValues.withUnsafeBufferPointer { [id] bufferPointer in

Sources/JavaScriptKit/JSTracing.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#if Tracing
22

33
/// Hooks for tracing Swift <-> JavaScript bridge calls.
4-
public struct JSTracing {
4+
public struct JSTracing: Sendable {
55
public static let `default` = JSTracing()
66

77
public enum JSCallInfo {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#if Tracing
2+
import JavaScriptKit
3+
import XCTest
4+
5+
final class JSTracingTests: XCTestCase {
6+
func testJSCallHookReportsMethod() throws {
7+
var startInfo: [JSTracing.JSCallInfo] = []
8+
var ended = 0
9+
let remove = JSTracing.default.addJSCallHook { info in
10+
startInfo.append(info)
11+
return { ended += 1 }
12+
}
13+
defer { remove() }
14+
15+
let globalObject1 = JSObject.global.globalObject1
16+
let prop5 = try XCTUnwrap(globalObject1.prop_5.object)
17+
_ = prop5.func6!(true, 1, 2)
18+
19+
XCTAssertEqual(startInfo.count, 1)
20+
guard case let .method(receiver, methodName, arguments) = startInfo.first else {
21+
XCTFail("Expected method info")
22+
return
23+
}
24+
XCTAssertEqual(receiver.id, prop5.id)
25+
XCTAssertEqual(methodName, "func6")
26+
XCTAssertEqual(arguments, [.boolean(true), .number(1), .number(2)])
27+
XCTAssertEqual(ended, 1)
28+
}
29+
30+
func testJSClosureCallHookReportsMetadata() throws {
31+
var startInfo: [JSTracing.JSClosureCallInfo] = []
32+
var ended = 0
33+
let remove = JSTracing.default.addJSClosureCallHook { info in
34+
startInfo.append(info)
35+
return { ended += 1 }
36+
}
37+
defer { remove() }
38+
39+
let globalObject1 = JSObject.global.globalObject1
40+
let prop6 = try XCTUnwrap(globalObject1.prop_6.object)
41+
let closure = JSClosure(file: "TracingTests.swift", line: 4242) { _ in .number(7) }
42+
prop6.host_func_1 = .object(closure)
43+
44+
let callHost = try XCTUnwrap(prop6.call_host_1.function)
45+
XCTAssertEqual(callHost(), .number(7))
46+
47+
XCTAssertEqual(startInfo.count, 1)
48+
XCTAssertEqual(startInfo.first?.fileID, "TracingTests.swift")
49+
XCTAssertEqual(startInfo.first?.line, 4242)
50+
XCTAssertEqual(ended, 1)
51+
}
52+
}
53+
#endif

0 commit comments

Comments
 (0)