diff --git a/cli/tests/error_005_missing_dynamic_import.ts.out b/cli/tests/error_005_missing_dynamic_import.ts.out index bffa907961..e21c7fffee 100644 --- a/cli/tests/error_005_missing_dynamic_import.ts.out +++ b/cli/tests/error_005_missing_dynamic_import.ts.out @@ -1 +1,4 @@ error: Uncaught (in promise) TypeError: Cannot resolve module "[WILDCARD]/cli/tests/bad-module.ts". + const badModule = await import("./bad-module.ts"); + ^ + at async file://[WILDCARD]/error_005_missing_dynamic_import.ts:3:21 diff --git a/cli/tests/error_012_bad_dynamic_import_specifier.ts.out b/cli/tests/error_012_bad_dynamic_import_specifier.ts.out index 8205470637..15658a6ebf 100644 --- a/cli/tests/error_012_bad_dynamic_import_specifier.ts.out +++ b/cli/tests/error_012_bad_dynamic_import_specifier.ts.out @@ -1,2 +1,5 @@ Check [WILDCARD]error_012_bad_dynamic_import_specifier.ts error: Uncaught (in promise) TypeError: relative import path "bad-module.ts" not prefixed with / or ./ or ../ Imported from "[WILDCARD]/error_012_bad_dynamic_import_specifier.ts" + const badModule = await import("bad-module.ts"); + ^ + at async file:///[WILDCARD]/error_012_bad_dynamic_import_specifier.ts:3:21 diff --git a/cli/tests/error_014_catch_dynamic_import_error.js.out b/cli/tests/error_014_catch_dynamic_import_error.js.out index 5ec98df021..4f133c834f 100644 --- a/cli/tests/error_014_catch_dynamic_import_error.js.out +++ b/cli/tests/error_014_catch_dynamic_import_error.js.out @@ -1,7 +1,9 @@ Caught direct dynamic import error. TypeError: relative import path "does not exist" not prefixed with / or ./ or ../ Imported from "[WILDCARD]/error_014_catch_dynamic_import_error.js" + at async file:///[WILDCARD]/error_014_catch_dynamic_import_error.js:3:5 Caught indirect direct dynamic import error. TypeError: relative import path "does not exist either" not prefixed with / or ./ or ../ Imported from "[WILDCARD]/indirect_import_error.js" + at async file:///[WILDCARD]/error_014_catch_dynamic_import_error.js:10:5 Caught error thrown by dynamically imported module. Error: An error at file:///[WILDCARD]tests/subdir/throws.js:6:7 diff --git a/cli/tests/error_015_dynamic_import_permissions.out b/cli/tests/error_015_dynamic_import_permissions.out index b3d6289908..d613066a4c 100644 --- a/cli/tests/error_015_dynamic_import_permissions.out +++ b/cli/tests/error_015_dynamic_import_permissions.out @@ -1 +1,4 @@ error: Uncaught (in promise) TypeError: network access to "localhost:4545", run again with the --allow-net flag + await import("http://localhost:4545/cli/tests/subdir/mod4.js"); + ^ + at async file:///[WILDCARD]/error_015_dynamic_import_permissions.js:2:3 diff --git a/core/bindings.rs b/core/bindings.rs index 1f6b85174b..bb5589080b 100644 --- a/core/bindings.rs +++ b/core/bindings.rs @@ -11,6 +11,7 @@ use futures::future::FutureExt; use rusty_v8 as v8; use std::cell::Cell; use std::convert::TryFrom; +use std::convert::TryInto; use std::io::{stdout, Write}; use std::option::Option; use url::Url; @@ -205,6 +206,32 @@ pub extern "C" fn host_import_module_dynamically_callback( state.dyn_import_cb(resolver_handle, &specifier_str, &referrer_name_str); } + // Map errors from module resolution (not JS errors from module execution) to + // ones rethrown from this scope, so they include the call stack of the + // dynamic import site. Error objects without any stack frames are assumed to + // be module resolution errors, other exception values are left as they are. + let map_err = |scope: &mut v8::HandleScope, + args: v8::FunctionCallbackArguments, + _rv: v8::ReturnValue| { + let arg = args.get(0); + if arg.is_native_error() { + let message = v8::Exception::create_message(scope, arg); + if message.get_stack_trace(scope).unwrap().get_frame_count() == 0 { + let arg: v8::Local = arg.clone().try_into().unwrap(); + let message_key = v8::String::new(scope, "message").unwrap(); + let message = arg.get(scope, message_key.into()).unwrap(); + let exception = + v8::Exception::type_error(scope, message.try_into().unwrap()); + scope.throw_exception(exception); + return; + } + } + scope.throw_exception(arg); + }; + let map_err = v8::FunctionTemplate::new(scope, map_err); + let map_err = map_err.get_function(scope).unwrap(); + let promise = promise.catch(scope, map_err).unwrap(); + &*promise as *const _ as *mut _ }