Skip to content

Commit 80b3790

Browse files
Add JSException.stack property to retrieve the stack trace of the exception.
1 parent 6f93d50 commit 80b3790

File tree

2 files changed

+27
-2
lines changed

2 files changed

+27
-2
lines changed

Sources/JavaScriptKit/JSException.swift

+13-2
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,22 @@ public struct JSException: Error, Equatable, CustomStringConvertible {
2828
/// A description of the exception.
2929
public let description: String
3030

31+
/// The stack trace of the exception.
32+
public let stack: String?
33+
3134
/// Initializes a new JSException instance with a value thrown from JavaScript.
3235
///
33-
/// Only available within the package.
36+
/// Only available within the package. This must be called on the thread where the exception object created.
3437
package init(_ thrownValue: JSValue) {
3538
self._thrownValue = thrownValue
36-
self.description = "JSException(\(thrownValue))"
39+
// Capture the stringified representation on the object owner thread
40+
// to bring useful info to the catching thread even if they are different threads.
41+
if let errorObject = thrownValue.object, let stack = errorObject.stack.string {
42+
self.description = "JSException(\(stack))"
43+
self.stack = stack
44+
} else {
45+
self.description = "JSException(\(thrownValue))"
46+
self.stack = nil
47+
}
3748
}
3849
}

Tests/JavaScriptEventLoopTests/WebWorkerTaskExecutorTests.swift

+14
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,20 @@ final class WebWorkerTaskExecutorTests: XCTestCase {
620620
XCTAssertEqual(object["test"].string!, "Hello, World!")
621621
}
622622

623+
func testThrowJSExceptionAcrossThreads() async throws {
624+
let executor = try await WebWorkerTaskExecutor(numberOfThreads: 1)
625+
let task = Task(executorPreference: executor) {
626+
_ = try JSObject.global.eval.function!.throws("throw new Error()")
627+
}
628+
do {
629+
try await task.value
630+
XCTFail()
631+
} catch let error as JSException {
632+
// Stringify JSException coming from worker should be allowed
633+
_ = String(describing: error)
634+
}
635+
}
636+
623637
// func testDeinitJSObjectOnDifferentThread() async throws {
624638
// let executor = try await WebWorkerTaskExecutor(numberOfThreads: 1)
625639
//

0 commit comments

Comments
 (0)