From ff490e9532ebb9a92772a2df72f4f0230f77485f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Go=CC=81mez?= Date: Wed, 30 Mar 2022 17:10:52 +0200 Subject: [PATCH 1/7] Remove a not neede try/catch when evaluating JSFunction values so we can improve error reporting by not hiding the information we get form the JS crash --- .../Sources/PrimaryTests/UnitTestUtils.swift | 6 +++ .../Sources/PrimaryTests/main.swift | 12 ++--- IntegrationTests/bin/primary-tests.js | 8 +++ Runtime/src/index.ts | 49 +++++++++++++++++++ Runtime/src/types.ts | 17 +++++++ .../FundamentalObjects/JSFunction.swift | 4 +- Sources/JavaScriptKit/XcodeSupport.swift | 15 ++++++ .../_CJavaScriptKit/include/_CJavaScriptKit.h | 33 +++++++++++++ 8 files changed, 133 insertions(+), 11 deletions(-) diff --git a/IntegrationTests/TestSuites/Sources/PrimaryTests/UnitTestUtils.swift b/IntegrationTests/TestSuites/Sources/PrimaryTests/UnitTestUtils.swift index 87ab72bc4..ab11bc017 100644 --- a/IntegrationTests/TestSuites/Sources/PrimaryTests/UnitTestUtils.swift +++ b/IntegrationTests/TestSuites/Sources/PrimaryTests/UnitTestUtils.swift @@ -103,6 +103,12 @@ func expectThrow(_ body: @autoclosure () throws -> T, file: StaticString = #f throw MessageError("Expect to throw an exception", file: file, line: line, column: column) } +func wrapUnsafeThrowableFunction(_ body: @escaping () -> Void, file: StaticString = #file, line: UInt = #line, column: UInt = #column) throws -> Error { + JSObject.global.callThrowingClosure.function!(JSClosure { _ in + body() + return .undefined + }) +} func expectNotNil(_ value: T?, file: StaticString = #file, line: UInt = #line, column: UInt = #column) throws { switch value { case .some: return diff --git a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift index e876b60e0..bce5e74f0 100644 --- a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift +++ b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift @@ -705,27 +705,21 @@ try test("Exception") { let prop_9: JSValue = globalObject1.prop_9 // MARK: Throwing method calls - let error1 = try expectThrow(try prop_9.object!.throwing.func1!()) + let error1 = try wrapUnsafeThrowableFunction { _ = prop_9.object!.func1!() } try expectEqual(error1 is JSValue, true) let errorObject = JSError(from: error1 as! JSValue) try expectNotNil(errorObject) - let error2 = try expectThrow(try prop_9.object!.throwing.func2!()) + let error2 = try wrapUnsafeThrowableFunction { _ = prop_9.object!.func2!() } try expectEqual(error2 is JSValue, true) let errorString = try expectString(error2 as! JSValue) try expectEqual(errorString, "String Error") - let error3 = try expectThrow(try prop_9.object!.throwing.func3!()) + let error3 = try wrapUnsafeThrowableFunction { _ = prop_9.object!.func3!() } try expectEqual(error3 is JSValue, true) let errorNumber = try expectNumber(error3 as! JSValue) try expectEqual(errorNumber, 3.0) - // MARK: Simple function calls - let error4 = try expectThrow(try prop_9.func1.function!.throws()) - try expectEqual(error4 is JSValue, true) - let errorObject2 = JSError(from: error4 as! JSValue) - try expectNotNil(errorObject2) - // MARK: Throwing constructor call let Animal = JSObject.global.Animal.function! _ = try Animal.throws.new("Tama", 3, true) diff --git a/IntegrationTests/bin/primary-tests.js b/IntegrationTests/bin/primary-tests.js index 79c62776a..597590bd4 100644 --- a/IntegrationTests/bin/primary-tests.js +++ b/IntegrationTests/bin/primary-tests.js @@ -82,6 +82,14 @@ global.Animal = function (name, age, isCat) { } }; +global.callThrowingClosure = (c) => { + try { + c() + } catch (error) { + return error + } +} + const { startWasiTask } = require("../lib"); startWasiTask("./dist/PrimaryTests.wasm").catch((err) => { diff --git a/Runtime/src/index.ts b/Runtime/src/index.ts index baf9ffd17..1d8378212 100644 --- a/Runtime/src/index.ts +++ b/Runtime/src/index.ts @@ -226,6 +226,29 @@ export class SwiftRuntime { this.memory ); }, + swjs_call_function_unsafe: ( + ref: ref, + argv: pointer, + argc: number, + kind_ptr: pointer, + payload1_ptr: pointer, + payload2_ptr: pointer + ) => { + const func = this.memory.getObject(ref); + const result = Reflect.apply( + func, + undefined, + JSValue.decodeArray(argv, argc, this.memory) + ); + JSValue.write( + result, + kind_ptr, + payload1_ptr, + payload2_ptr, + false, + this.memory + ); + }, swjs_call_function_with_this: ( obj_ref: ref, @@ -265,6 +288,32 @@ export class SwiftRuntime { this.memory ); }, + + swjs_call_function_with_this_unsafe: ( + obj_ref: ref, + func_ref: ref, + argv: pointer, + argc: number, + kind_ptr: pointer, + payload1_ptr: pointer, + payload2_ptr: pointer + ) => { + const obj = this.memory.getObject(obj_ref); + const func = this.memory.getObject(func_ref); + const result = Reflect.apply( + func, + obj, + JSValue.decodeArray(argv, argc, this.memory) + ); + JSValue.write( + result, + kind_ptr, + payload1_ptr, + payload2_ptr, + false, + this.memory + ); + }, swjs_call_new: (ref: ref, argv: pointer, argc: number) => { const constructor = this.memory.getObject(ref); const instance = Reflect.construct( diff --git a/Runtime/src/types.ts b/Runtime/src/types.ts index 4f613cc6a..c3ecdafda 100644 --- a/Runtime/src/types.ts +++ b/Runtime/src/types.ts @@ -58,6 +58,14 @@ export interface ImportedFunctions { payload1_ptr: pointer, payload2_ptr: pointer ): void; + swjs_call_function_unsafe( + ref: number, + argv: pointer, + argc: number, + kind_ptr: pointer, + payload1_ptr: pointer, + payload2_ptr: pointer + ): void; swjs_call_function_with_this( obj_ref: ref, func_ref: ref, @@ -67,6 +75,15 @@ export interface ImportedFunctions { payload1_ptr: pointer, payload2_ptr: pointer ): void; + swjs_call_function_with_this_unsafe( + obj_ref: ref, + func_ref: ref, + argv: pointer, + argc: number, + kind_ptr: pointer, + payload1_ptr: pointer, + payload2_ptr: pointer + ): void; swjs_call_new(ref: number, argv: pointer, argc: number): number; swjs_call_throwing_new( ref: number, diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift b/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift index d9d66ff94..e5fa645d3 100644 --- a/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift +++ b/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift @@ -93,11 +93,11 @@ internal func invokeJSFunction(_ jsFunc: JSFunction, arguments: [ConvertibleToJS var payload1 = JavaScriptPayload1() var payload2 = JavaScriptPayload2() if let thisId = this?.id { - _call_function_with_this(thisId, + _call_function_with_this_unsafe(thisId, jsFunc.id, argv, Int32(argc), &kindAndFlags, &payload1, &payload2) } else { - _call_function( + _call_function_unsafe( jsFunc.id, argv, Int32(argc), &kindAndFlags, &payload1, &payload2 ) diff --git a/Sources/JavaScriptKit/XcodeSupport.swift b/Sources/JavaScriptKit/XcodeSupport.swift index 5bb02e3a3..85d5b2fcb 100644 --- a/Sources/JavaScriptKit/XcodeSupport.swift +++ b/Sources/JavaScriptKit/XcodeSupport.swift @@ -53,6 +53,13 @@ import _CJavaScriptKit _: UnsafeMutablePointer!, _: UnsafeMutablePointer! ) { fatalError() } + func _call_function_unsafe( + _: JavaScriptObjectRef, + _: UnsafePointer!, _: Int32, + _: UnsafeMutablePointer!, + _: UnsafeMutablePointer!, + _: UnsafeMutablePointer! + ) { fatalError() } func _call_function_with_this( _: JavaScriptObjectRef, _: JavaScriptObjectRef, @@ -61,6 +68,14 @@ import _CJavaScriptKit _: UnsafeMutablePointer!, _: UnsafeMutablePointer! ) { fatalError() } + func _call_function_with_this_unsafe( + _: JavaScriptObjectRef, + _: JavaScriptObjectRef, + _: UnsafePointer!, _: Int32, + _: UnsafeMutablePointer!, + _: UnsafeMutablePointer!, + _: UnsafeMutablePointer! + ) { fatalError() } func _call_new( _: JavaScriptObjectRef, _: UnsafePointer!, _: Int32 diff --git a/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h b/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h index 8979cee56..da178d2c6 100644 --- a/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h +++ b/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h @@ -170,6 +170,21 @@ extern void _call_function(const JavaScriptObjectRef ref, const RawJSValue *argv JavaScriptPayload1 *result_payload1, JavaScriptPayload2 *result_payload2); +/// `_call_function` calls JavaScript function with given arguments list without capturing any exception +/// +/// @param ref The target JavaScript function to call. +/// @param argv A list of `RawJSValue` arguments to apply. +/// @param argc The length of `argv``. +/// @param result_kind A result pointer of JavaScript value kind of returned result or thrown exception. +/// @param result_payload1 A result pointer of first payload of JavaScript value of returned result or thrown exception. +/// @param result_payload2 A result pointer of second payload of JavaScript value of returned result or thrown exception. +__attribute__((__import_module__("javascript_kit"), + __import_name__("swjs_call_function_unsafe"))) +extern void _call_function_unsafe(const JavaScriptObjectRef ref, const RawJSValue *argv, + const int argc, JavaScriptValueKindAndFlags *result_kind, + JavaScriptPayload1 *result_payload1, + JavaScriptPayload2 *result_payload2); + /// `_call_function_with_this` calls JavaScript function with given arguments list and given `_this`. /// /// @param _this The value of `this` provided for the call to `func_ref`. @@ -188,6 +203,24 @@ extern void _call_function_with_this(const JavaScriptObjectRef _this, JavaScriptPayload1 *result_payload1, JavaScriptPayload2 *result_payload2); +/// `_call_function_with_this` calls JavaScript function with given arguments list and given `_this` without capturing any exception. +/// +/// @param _this The value of `this` provided for the call to `func_ref`. +/// @param func_ref The target JavaScript function to call. +/// @param argv A list of `RawJSValue` arguments to apply. +/// @param argc The length of `argv``. +/// @param result_kind A result pointer of JavaScript value kind of returned result or thrown exception. +/// @param result_payload1 A result pointer of first payload of JavaScript value of returned result or thrown exception. +/// @param result_payload2 A result pointer of second payload of JavaScript value of returned result or thrown exception. +__attribute__((__import_module__("javascript_kit"), + __import_name__("swjs_call_function_with_this_unsafe"))) +extern void _call_function_with_this_unsafe(const JavaScriptObjectRef _this, + const JavaScriptObjectRef func_ref, + const RawJSValue *argv, const int argc, + JavaScriptValueKindAndFlags *result_kind, + JavaScriptPayload1 *result_payload1, + JavaScriptPayload2 *result_payload2); + /// `_call_new` calls JavaScript object constructor with given arguments list. /// /// @param ref The target JavaScript constructor to call. From 35d4c92009412a34666d127b8bfeaa0c99b6d9ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Go=CC=81mez?= Date: Wed, 30 Mar 2022 17:44:34 +0200 Subject: [PATCH 2/7] Modify JSThrowingFunction to be based on the safe version of _call_function_with_this and _call_function instead of the unsafe version we created --- .../FundamentalObjects/JSFunction.swift | 5 ++-- .../JSThrowingFunction.swift | 28 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift b/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift index e5fa645d3..b86d743d7 100644 --- a/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift +++ b/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift @@ -19,7 +19,7 @@ public class JSFunction: JSObject { /// - Returns: The result of this call. @discardableResult public func callAsFunction(this: JSObject? = nil, arguments: [ConvertibleToJSValue]) -> JSValue { - try! invokeJSFunction(self, arguments: arguments, this: this) + try! invokeNonThrowingJSFunction(self, arguments: arguments, this: this) } /// A variadic arguments version of `callAsFunction`. @@ -84,7 +84,7 @@ public class JSFunction: JSObject { } } -internal func invokeJSFunction(_ jsFunc: JSFunction, arguments: [ConvertibleToJSValue], this: JSObject?) throws -> JSValue { +private func invokeNonThrowingJSFunction(_ jsFunc: JSFunction, arguments: [ConvertibleToJSValue], this: JSObject?) throws -> JSValue { let (result, isException) = arguments.withRawJSValues { rawValues in rawValues.withUnsafeBufferPointer { bufferPointer -> (JSValue, Bool) in let argv = bufferPointer.baseAddress @@ -102,6 +102,7 @@ internal func invokeJSFunction(_ jsFunc: JSFunction, arguments: [ConvertibleToJS &kindAndFlags, &payload1, &payload2 ) } + assert(!kindAndFlags.isException) let result = RawJSValue(kind: kindAndFlags.kind, payload1: payload1, payload2: payload2) return (result.jsValue(), kindAndFlags.isException) } diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift b/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift index 0fe96d318..adcd82a63 100644 --- a/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift +++ b/Sources/JavaScriptKit/FundamentalObjects/JSThrowingFunction.swift @@ -62,3 +62,31 @@ public class JSThrowingFunction { try new(arguments: arguments) } } + +private func invokeJSFunction(_ jsFunc: JSFunction, arguments: [ConvertibleToJSValue], this: JSObject?) throws -> JSValue { + let (result, isException) = arguments.withRawJSValues { rawValues in + rawValues.withUnsafeBufferPointer { bufferPointer -> (JSValue, Bool) in + let argv = bufferPointer.baseAddress + let argc = bufferPointer.count + var kindAndFlags = JavaScriptValueKindAndFlags() + var payload1 = JavaScriptPayload1() + var payload2 = JavaScriptPayload2() + if let thisId = this?.id { + _call_function_with_this(thisId, + jsFunc.id, argv, Int32(argc), + &kindAndFlags, &payload1, &payload2) + } else { + _call_function( + jsFunc.id, argv, Int32(argc), + &kindAndFlags, &payload1, &payload2 + ) + } + let result = RawJSValue(kind: kindAndFlags.kind, payload1: payload1, payload2: payload2) + return (result.jsValue(), kindAndFlags.isException) + } + } + if isException { + throw result + } + return result +} From f5072a5a2ccf59251ec367a1fd45a6f3c4fda93c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20G=C3=B3mez?= Date: Wed, 30 Mar 2022 17:47:46 +0200 Subject: [PATCH 3/7] Update swjs_call_function_unsafe to notify wasm when there is an exception Co-authored-by: Jed Fox --- Runtime/src/index.ts | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/Runtime/src/index.ts b/Runtime/src/index.ts index 1d8378212..65dca269d 100644 --- a/Runtime/src/index.ts +++ b/Runtime/src/index.ts @@ -235,19 +235,34 @@ export class SwiftRuntime { payload2_ptr: pointer ) => { const func = this.memory.getObject(ref); - const result = Reflect.apply( - func, - undefined, - JSValue.decodeArray(argv, argc, this.memory) - ); - JSValue.write( - result, - kind_ptr, - payload1_ptr, - payload2_ptr, - false, - this.memory - ); + let isException = true; + try { + const result = Reflect.apply( + func, + undefined, + JSValue.decodeArray(argv, argc, this.memory) + ); + JSValue.write( + result, + kind_ptr, + payload1_ptr, + payload2_ptr, + false, + this.memory + ); + isException = false; + } finally { + if (isException) { + JSValue.write( + undefined, + kind_ptr, + payload1_ptr, + payload2_ptr, + true, + this.memory + ); + } + } }, swjs_call_function_with_this: ( From 160acf7a07c33d893a8dcd077bcdae48c6e74eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Go=CC=81mez?= Date: Wed, 30 Mar 2022 17:50:10 +0200 Subject: [PATCH 4/7] Modify swjs_call_function_with_this_unsafe to notify WASM there was an exception as Jed suggested --- Runtime/src/index.ts | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/Runtime/src/index.ts b/Runtime/src/index.ts index 65dca269d..5c67edd65 100644 --- a/Runtime/src/index.ts +++ b/Runtime/src/index.ts @@ -315,19 +315,34 @@ export class SwiftRuntime { ) => { const obj = this.memory.getObject(obj_ref); const func = this.memory.getObject(func_ref); - const result = Reflect.apply( - func, - obj, - JSValue.decodeArray(argv, argc, this.memory) - ); - JSValue.write( - result, - kind_ptr, - payload1_ptr, - payload2_ptr, - false, - this.memory - ); + let isException = true; + try { + const result = Reflect.apply( + func, + obj, + JSValue.decodeArray(argv, argc, this.memory) + ); + JSValue.write( + result, + kind_ptr, + payload1_ptr, + payload2_ptr, + false, + this.memory + ); + isException = false + } finally { + if (isException) { + JSValue.write( + undefined, + kind_ptr, + payload1_ptr, + payload2_ptr, + true, + this.memory + ); + } + } }, swjs_call_new: (ref: ref, argv: pointer, argc: number) => { const constructor = this.memory.getObject(ref); From baa667842b4d04a65ffb3a30d35cde6f2240b6f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Go=CC=81mez?= Date: Wed, 30 Mar 2022 17:53:42 +0200 Subject: [PATCH 5/7] Recover the already written test cases for JSThrowingFunction and create a new test case for the new functionality --- .../Sources/PrimaryTests/main.swift | 53 +++++++++++++++++-- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift index bce5e74f0..8136f345e 100644 --- a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift +++ b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift @@ -700,26 +700,31 @@ try test("Exception") { // } // ``` // - let globalObject1 = JSObject.global.globalObject1 let prop_9: JSValue = globalObject1.prop_9 // MARK: Throwing method calls - let error1 = try wrapUnsafeThrowableFunction { _ = prop_9.object!.func1!() } + let error1 = try expectThrow(try prop_9.object!.throwing.func1!()) try expectEqual(error1 is JSValue, true) let errorObject = JSError(from: error1 as! JSValue) try expectNotNil(errorObject) - let error2 = try wrapUnsafeThrowableFunction { _ = prop_9.object!.func2!() } + let error2 = try expectThrow(try prop_9.object!.throwing.func2!()) try expectEqual(error2 is JSValue, true) let errorString = try expectString(error2 as! JSValue) try expectEqual(errorString, "String Error") - let error3 = try wrapUnsafeThrowableFunction { _ = prop_9.object!.func3!() } + let error3 = try expectThrow(try prop_9.object!.throwing.func3!()) try expectEqual(error3 is JSValue, true) let errorNumber = try expectNumber(error3 as! JSValue) try expectEqual(errorNumber, 3.0) + // MARK: Simple function calls + let error4 = try expectThrow(try prop_9.func1.function!.throws()) + try expectEqual(error4 is JSValue, true) + let errorObject2 = JSError(from: error4 as! JSValue) + try expectNotNil(errorObject2) + // MARK: Throwing constructor call let Animal = JSObject.global.Animal.function! _ = try Animal.throws.new("Tama", 3, true) @@ -729,6 +734,46 @@ try test("Exception") { try expectNotNil(errorObject3) } +try test("Unhandled Exception") { + // ```js + // global.globalObject1 = { + // ... + // prop_9: { + // func1: function () { + // throw new Error(); + // }, + // func2: function () { + // throw "String Error"; + // }, + // func3: function () { + // throw 3.0 + // }, + // }, + // ... + // } + // ``` + // + + let globalObject1 = JSObject.global.globalObject1 + let prop_9: JSValue = globalObject1.prop_9 + + // MARK: Throwing method calls + let error1 = try wrapUnsafeThrowableFunction { _ = prop_9.object!.func1!() } + try expectEqual(error1 is JSValue, true) + let errorObject = JSError(from: error1 as! JSValue) + try expectNotNil(errorObject) + + let error2 = try wrapUnsafeThrowableFunction { _ = prop_9.object!.func2!() } + try expectEqual(error2 is JSValue, true) + let errorString = try expectString(error2 as! JSValue) + try expectEqual(errorString, "String Error") + + let error3 = try wrapUnsafeThrowableFunction { _ = prop_9.object!.func3!() } + try expectEqual(error3 is JSValue, true) + let errorNumber = try expectNumber(error3 as! JSValue) + try expectEqual(errorNumber, 3.0) +} + /// If WebAssembly.Memory is not accessed correctly (i.e. creating a new view each time), /// this test will fail with `TypeError: Cannot perform Construct on a detached ArrayBuffer`, /// since asking to grow memory will detach the backing ArrayBuffer. From d7e8747b9da84e85094a49761895df1a4dff43bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Go=CC=81mez?= Date: Thu, 31 Mar 2022 08:57:10 +0200 Subject: [PATCH 6/7] Rename unsafe fuctions to no_catch and simplify invokeNonThrowingJSFunction implementation --- Runtime/src/index.ts | 4 ++-- Runtime/src/types.ts | 4 ++-- .../FundamentalObjects/JSFunction.swift | 18 +++++++----------- Sources/JavaScriptKit/XcodeSupport.swift | 4 ++-- .../_CJavaScriptKit/include/_CJavaScriptKit.h | 8 ++++---- 5 files changed, 17 insertions(+), 21 deletions(-) diff --git a/Runtime/src/index.ts b/Runtime/src/index.ts index 5c67edd65..a2c45a242 100644 --- a/Runtime/src/index.ts +++ b/Runtime/src/index.ts @@ -226,7 +226,7 @@ export class SwiftRuntime { this.memory ); }, - swjs_call_function_unsafe: ( + swjs_call_function_no_catch: ( ref: ref, argv: pointer, argc: number, @@ -304,7 +304,7 @@ export class SwiftRuntime { ); }, - swjs_call_function_with_this_unsafe: ( + swjs_call_function_with_this_no_catch: ( obj_ref: ref, func_ref: ref, argv: pointer, diff --git a/Runtime/src/types.ts b/Runtime/src/types.ts index c3ecdafda..b291cd913 100644 --- a/Runtime/src/types.ts +++ b/Runtime/src/types.ts @@ -58,7 +58,7 @@ export interface ImportedFunctions { payload1_ptr: pointer, payload2_ptr: pointer ): void; - swjs_call_function_unsafe( + swjs_call_function_no_catch( ref: number, argv: pointer, argc: number, @@ -75,7 +75,7 @@ export interface ImportedFunctions { payload1_ptr: pointer, payload2_ptr: pointer ): void; - swjs_call_function_with_this_unsafe( + swjs_call_function_with_this_no_catch( obj_ref: ref, func_ref: ref, argv: pointer, diff --git a/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift b/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift index b86d743d7..0d3a917c0 100644 --- a/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift +++ b/Sources/JavaScriptKit/FundamentalObjects/JSFunction.swift @@ -19,7 +19,7 @@ public class JSFunction: JSObject { /// - Returns: The result of this call. @discardableResult public func callAsFunction(this: JSObject? = nil, arguments: [ConvertibleToJSValue]) -> JSValue { - try! invokeNonThrowingJSFunction(self, arguments: arguments, this: this) + invokeNonThrowingJSFunction(self, arguments: arguments, this: this) } /// A variadic arguments version of `callAsFunction`. @@ -84,31 +84,27 @@ public class JSFunction: JSObject { } } -private func invokeNonThrowingJSFunction(_ jsFunc: JSFunction, arguments: [ConvertibleToJSValue], this: JSObject?) throws -> JSValue { - let (result, isException) = arguments.withRawJSValues { rawValues in - rawValues.withUnsafeBufferPointer { bufferPointer -> (JSValue, Bool) in +private func invokeNonThrowingJSFunction(_ jsFunc: JSFunction, arguments: [ConvertibleToJSValue], this: JSObject?) -> JSValue { + arguments.withRawJSValues { rawValues in + rawValues.withUnsafeBufferPointer { bufferPointer -> (JSValue) in let argv = bufferPointer.baseAddress let argc = bufferPointer.count var kindAndFlags = JavaScriptValueKindAndFlags() var payload1 = JavaScriptPayload1() var payload2 = JavaScriptPayload2() if let thisId = this?.id { - _call_function_with_this_unsafe(thisId, + _call_function_with_this_no_catch(thisId, jsFunc.id, argv, Int32(argc), &kindAndFlags, &payload1, &payload2) } else { - _call_function_unsafe( + _call_function_no_catch( jsFunc.id, argv, Int32(argc), &kindAndFlags, &payload1, &payload2 ) } assert(!kindAndFlags.isException) let result = RawJSValue(kind: kindAndFlags.kind, payload1: payload1, payload2: payload2) - return (result.jsValue(), kindAndFlags.isException) + return result.jsValue() } } - if isException { - throw result - } - return result } diff --git a/Sources/JavaScriptKit/XcodeSupport.swift b/Sources/JavaScriptKit/XcodeSupport.swift index 85d5b2fcb..013c49e2e 100644 --- a/Sources/JavaScriptKit/XcodeSupport.swift +++ b/Sources/JavaScriptKit/XcodeSupport.swift @@ -53,7 +53,7 @@ import _CJavaScriptKit _: UnsafeMutablePointer!, _: UnsafeMutablePointer! ) { fatalError() } - func _call_function_unsafe( + func _call_function_no_catch( _: JavaScriptObjectRef, _: UnsafePointer!, _: Int32, _: UnsafeMutablePointer!, @@ -68,7 +68,7 @@ import _CJavaScriptKit _: UnsafeMutablePointer!, _: UnsafeMutablePointer! ) { fatalError() } - func _call_function_with_this_unsafe( + func _call_function_with_this_no_catch( _: JavaScriptObjectRef, _: JavaScriptObjectRef, _: UnsafePointer!, _: Int32, diff --git a/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h b/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h index da178d2c6..ce0bf5862 100644 --- a/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h +++ b/Sources/_CJavaScriptKit/include/_CJavaScriptKit.h @@ -179,8 +179,8 @@ extern void _call_function(const JavaScriptObjectRef ref, const RawJSValue *argv /// @param result_payload1 A result pointer of first payload of JavaScript value of returned result or thrown exception. /// @param result_payload2 A result pointer of second payload of JavaScript value of returned result or thrown exception. __attribute__((__import_module__("javascript_kit"), - __import_name__("swjs_call_function_unsafe"))) -extern void _call_function_unsafe(const JavaScriptObjectRef ref, const RawJSValue *argv, + __import_name__("swjs_call_function_no_catch"))) +extern void _call_function_no_catch(const JavaScriptObjectRef ref, const RawJSValue *argv, const int argc, JavaScriptValueKindAndFlags *result_kind, JavaScriptPayload1 *result_payload1, JavaScriptPayload2 *result_payload2); @@ -213,8 +213,8 @@ extern void _call_function_with_this(const JavaScriptObjectRef _this, /// @param result_payload1 A result pointer of first payload of JavaScript value of returned result or thrown exception. /// @param result_payload2 A result pointer of second payload of JavaScript value of returned result or thrown exception. __attribute__((__import_module__("javascript_kit"), - __import_name__("swjs_call_function_with_this_unsafe"))) -extern void _call_function_with_this_unsafe(const JavaScriptObjectRef _this, + __import_name__("swjs_call_function_with_this_no_catch"))) +extern void _call_function_with_this_no_catch(const JavaScriptObjectRef _this, const JavaScriptObjectRef func_ref, const RawJSValue *argv, const int argc, JavaScriptValueKindAndFlags *result_kind, From 292b9db59309528055997fb1fc665558ca7b9b01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Go=CC=81mez?= Date: Thu, 31 Mar 2022 10:22:44 +0200 Subject: [PATCH 7/7] Bump swjs_library_version version --- Runtime/src/index.ts | 2 +- Sources/_CJavaScriptKit/_CJavaScriptKit.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Runtime/src/index.ts b/Runtime/src/index.ts index a2c45a242..06fecc286 100644 --- a/Runtime/src/index.ts +++ b/Runtime/src/index.ts @@ -14,7 +14,7 @@ export class SwiftRuntime { private _instance: WebAssembly.Instance | null; private _memory: Memory | null; private _closureDeallocator: SwiftClosureDeallocator | null; - private version: number = 705; + private version: number = 706; private textDecoder = new TextDecoder("utf-8"); private textEncoder = new TextEncoder(); // Only support utf-8 diff --git a/Sources/_CJavaScriptKit/_CJavaScriptKit.c b/Sources/_CJavaScriptKit/_CJavaScriptKit.c index 38329ff14..c263b8f71 100644 --- a/Sources/_CJavaScriptKit/_CJavaScriptKit.c +++ b/Sources/_CJavaScriptKit/_CJavaScriptKit.c @@ -36,7 +36,7 @@ void swjs_cleanup_host_function_call(void *argv_buffer) { /// this and `SwiftRuntime.version` in `./Runtime/src/index.ts`. __attribute__((export_name("swjs_library_version"))) int swjs_library_version(void) { - return 705; + return 706; } int _library_features(void);