diff --git a/js/dispatch_json.ts b/js/dispatch_json.ts index bde2b7cb1d..8ec924f4c3 100644 --- a/js/dispatch_json.ts +++ b/js/dispatch_json.ts @@ -15,10 +15,10 @@ interface JsonError { interface JsonResponse { ok?: Ok; err?: JsonError; - promiseId?: number; // only present in async mesasges. + promiseId?: number; // Only present in async messages. } -const promiseTable = new Map>(); +const promiseTable = new Map>(); let _nextPromiseId = 1; function nextPromiseId(): number { @@ -35,25 +35,22 @@ function encode(args: object): Uint8Array { return new TextEncoder().encode(s); } -function toDenoError(err: JsonError): DenoError { - return new DenoError(err.kind, err.message); +function unwrapResponse(res: JsonResponse): Ok { + if (res.err != null) { + throw new DenoError(res.err!.kind, res.err!.message); + } + util.assert(res.ok != null); + return res.ok!; } -export function asyncMsgFromRust(opId: number, res: Uint8Array): void { - const { ok, err, promiseId } = decode(res); - const promise = promiseTable.get(promiseId!)!; - if (!promise) { - throw Error(`Async op ${opId} had bad promiseId`); - } - promiseTable.delete(promiseId!); +export function asyncMsgFromRust(opId: number, resUi8: Uint8Array): void { + const res = decode(resUi8); + util.assert(res.promiseId != null); - if (err) { - promise.reject(toDenoError(err)); - } else if (ok) { - promise.resolve(ok); - } else { - util.unreachable(); - } + const promise = promiseTable.get(res.promiseId!); + util.assert(promise != null); + promiseTable.delete(res.promiseId!); + promise!.resolve(res); } export function sendSync( @@ -62,29 +59,28 @@ export function sendSync( zeroCopy?: Uint8Array ): Ok { const argsUi8 = encode(args); - const res = core.dispatch(opId, argsUi8, zeroCopy); - if (!res) { - return; - } - const { ok, err, promiseId } = decode(res); - util.assert(!promiseId); - if (err) { - throw toDenoError(err); - } - return ok; + const resUi8 = core.dispatch(opId, argsUi8, zeroCopy); + util.assert(resUi8 != null); + + const res = decode(resUi8!); + util.assert(res.promiseId == null); + return unwrapResponse(res); } -export function sendAsync( +export async function sendAsync( opId: number, args: object = {}, zeroCopy?: Uint8Array ): Promise { const promiseId = nextPromiseId(); args = Object.assign(args, { promiseId }); - const argsUi8 = encode(args); const promise = util.createResolvable(); promiseTable.set(promiseId, promise); - const r = core.dispatch(opId, argsUi8, zeroCopy); - util.assert(!r); - return promise; + + const argsUi8 = encode(args); + const resUi8 = core.dispatch(opId, argsUi8, zeroCopy); + util.assert(resUi8 == null); + + const res = await promise; + return unwrapResponse(res); } diff --git a/js/dispatch_json_test.ts b/js/dispatch_json_test.ts new file mode 100644 index 0000000000..47e5cef2fa --- /dev/null +++ b/js/dispatch_json_test.ts @@ -0,0 +1,19 @@ +import { testPerm, assertMatch, unreachable } from "./test_util.ts"; + +const openErrorStackPattern = new RegExp( + `^.* + at unwrapResponse \\(js\\/dispatch_json\\.ts:.*\\) + at sendAsync.* \\(js\\/dispatch_json\\.ts:.*\\) + at async Object\\.open \\(js\\/files\\.ts:.*\\).*$`, + "ms" +); + +testPerm({ read: true }, async function sendAsyncStackTrace(): Promise { + await Deno.open("nonexistent.txt") + .then(unreachable) + .catch( + (error): void => { + assertMatch(error.stack, openErrorStackPattern); + } + ); +}); diff --git a/js/test_util.ts b/js/test_util.ts index 454f26ff21..bcbacf2812 100644 --- a/js/test_util.ts +++ b/js/test_util.ts @@ -15,9 +15,11 @@ import { export { assert, assertEquals, + assertMatch, assertNotEquals, assertStrictEq, - assertStrContains + assertStrContains, + unreachable } from "./deps/https/deno.land/std/testing/asserts.ts"; interface TestPermissions { diff --git a/js/unit_tests.ts b/js/unit_tests.ts index b55c1954aa..711a092fdb 100644 --- a/js/unit_tests.ts +++ b/js/unit_tests.ts @@ -13,6 +13,7 @@ import "./console_test.ts"; import "./copy_file_test.ts"; import "./custom_event_test.ts"; import "./dir_test.ts"; +import "./dispatch_json_test.ts"; import "./error_stack_test.ts"; import "./event_test.ts"; import "./event_target_test.ts"; diff --git a/tests/error_004_missing_module.ts.out b/tests/error_004_missing_module.ts.out index 261d0a97bc..a0ce342e94 100644 --- a/tests/error_004_missing_module.ts.out +++ b/tests/error_004_missing_module.ts.out @@ -1,7 +1,7 @@ [WILDCARD]error: Uncaught NotFound: Cannot resolve module "[WILDCARD]/bad-module.ts" [WILDCARD] js/dispatch_json.ts:[WILDCARD] at DenoError (js/errors.ts:[WILDCARD]) - at toDenoError (js/dispatch_json.ts:[WILDCARD]) + at unwrapResponse (js/dispatch_json.ts:[WILDCARD]) at sendSync[WILDCARD] (js/dispatch_json.ts:[WILDCARD]) at fetchSourceFile (js/compiler.ts:[WILDCARD]) at _resolveModule (js/compiler.ts:[WILDCARD]) diff --git a/tests/error_005_missing_dynamic_import.ts.out b/tests/error_005_missing_dynamic_import.ts.out index 6574705313..a580368bae 100644 --- a/tests/error_005_missing_dynamic_import.ts.out +++ b/tests/error_005_missing_dynamic_import.ts.out @@ -1,7 +1,7 @@ [WILDCARD]error: Uncaught NotFound: Cannot resolve module "[WILDCARD]/bad-module.ts" [WILDCARD] js/dispatch_json.ts:[WILDCARD] at DenoError (js/errors.ts:[WILDCARD]) - at toDenoError (js/dispatch_json.ts:[WILDCARD]) + at unwrapResponse (js/dispatch_json.ts:[WILDCARD]) at sendSync[WILDCARD] (js/dispatch_json.ts:[WILDCARD]) at fetchSourceFile (js/compiler.ts:[WILDCARD]) at _resolveModule (js/compiler.ts:[WILDCARD]) diff --git a/tests/error_006_import_ext_failure.ts.out b/tests/error_006_import_ext_failure.ts.out index 6ccee7e13b..442ef9c53d 100644 --- a/tests/error_006_import_ext_failure.ts.out +++ b/tests/error_006_import_ext_failure.ts.out @@ -1,7 +1,7 @@ [WILDCARD]error: Uncaught NotFound: Cannot resolve module "[WILDCARD]/non-existent" [WILDCARD] js/dispatch_json.ts:[WILDCARD] at DenoError (js/errors.ts:[WILDCARD]) - at toDenoError (js/dispatch_json.ts:[WILDCARD]) + at unwrapResponse (js/dispatch_json.ts:[WILDCARD]) at sendSync[WILDCARD] (js/dispatch_json.ts:[WILDCARD]) at fetchSourceFile (js/compiler.ts:[WILDCARD]) at _resolveModule (js/compiler.ts:[WILDCARD]) diff --git a/tests/error_011_bad_module_specifier.ts.out b/tests/error_011_bad_module_specifier.ts.out index 3b7baa2414..518ad08b3f 100644 --- a/tests/error_011_bad_module_specifier.ts.out +++ b/tests/error_011_bad_module_specifier.ts.out @@ -1,7 +1,7 @@ [WILDCARD]error: Uncaught ImportPrefixMissing: relative import path "bad-module.ts" not prefixed with / or ./ or ../ [WILDCARD] js/dispatch_json.ts:[WILDCARD] at DenoError (js/errors.ts:[WILDCARD]) - at toDenoError (js/dispatch_json.ts:[WILDCARD]) + at unwrapResponse (js/dispatch_json.ts:[WILDCARD]) at sendSync[WILDCARD] (js/dispatch_json.ts:[WILDCARD]) at fetchSourceFile (js/compiler.ts:[WILDCARD]) at _resolveModule (js/compiler.ts:[WILDCARD]) diff --git a/tests/error_012_bad_dynamic_import_specifier.ts.out b/tests/error_012_bad_dynamic_import_specifier.ts.out index 3b7baa2414..518ad08b3f 100644 --- a/tests/error_012_bad_dynamic_import_specifier.ts.out +++ b/tests/error_012_bad_dynamic_import_specifier.ts.out @@ -1,7 +1,7 @@ [WILDCARD]error: Uncaught ImportPrefixMissing: relative import path "bad-module.ts" not prefixed with / or ./ or ../ [WILDCARD] js/dispatch_json.ts:[WILDCARD] at DenoError (js/errors.ts:[WILDCARD]) - at toDenoError (js/dispatch_json.ts:[WILDCARD]) + at unwrapResponse (js/dispatch_json.ts:[WILDCARD]) at sendSync[WILDCARD] (js/dispatch_json.ts:[WILDCARD]) at fetchSourceFile (js/compiler.ts:[WILDCARD]) at _resolveModule (js/compiler.ts:[WILDCARD])