diff options
-rw-r--r-- | cli/tests/integration_tests.rs | 1 | ||||
-rw-r--r-- | core/es_isolate.rs | 32 |
2 files changed, 29 insertions, 4 deletions
diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs index 7ba296944..68b69c97f 100644 --- a/cli/tests/integration_tests.rs +++ b/cli/tests/integration_tests.rs @@ -1341,7 +1341,6 @@ itest!(error_013_missing_script { itest!(error_014_catch_dynamic_import_error { args: "run --reload --allow-read error_014_catch_dynamic_import_error.js", output: "error_014_catch_dynamic_import_error.js.out", - exit_code: 1, }); itest!(error_015_dynamic_import_permissions { diff --git a/core/es_isolate.rs b/core/es_isolate.rs index 4b5fd58ba..be5e2c0c6 100644 --- a/core/es_isolate.rs +++ b/core/es_isolate.rs @@ -18,6 +18,7 @@ use futures::task::AtomicWaker; use futures::Future; use libc::c_void; use std::collections::HashMap; +use std::convert::TryFrom; use std::ops::{Deref, DerefMut}; use std::option::Option; use std::pin::Pin; @@ -233,16 +234,41 @@ impl EsIsolate { let info = self.modules.get_info(id).expect("ModuleInfo not found"); let module = info.handle.get(scope).expect("Empty module handle"); let mut status = module.get_status(); - if status == v8::ModuleStatus::Instantiated { - let ok = module.evaluate(scope, context).is_some(); + // IMPORTANT: Top-level-await is enabled, which means that return value + // of module evaluation is a promise. + // + // Because that promise is created internally by V8, when error occurs during + // module evaluation the promise is rejected, and since the promise has no rejection + // handler it will result in call to `bindings::promise_reject_callback` adding + // the promise to pending promise rejection table - meaning Isolate will return + // error on next poll(). + // + // This situation is not desirable as we want to manually return error at the + // end of this function to handle it further. It means we need to manually + // remove this promise from pending promise rejection table. + // + // For more details see: + // https://github.com/denoland/deno/issues/4908 + // https://v8.dev/features/top-level-await#module-execution-order + let maybe_value = module.evaluate(scope, context); + // Update status after evaluating. status = module.get_status(); - if ok { + + if let Some(value) = maybe_value { assert!( status == v8::ModuleStatus::Evaluated || status == v8::ModuleStatus::Errored ); + let promise = v8::Local::<v8::Promise>::try_from(value) + .expect("Expected to get promise as module evaluation result"); + let promise_id = promise.get_identity_hash(); + if let Some(mut handle) = + core_isolate.pending_promise_exceptions.remove(&promise_id) + { + handle.reset(scope); + } } else { assert!(status == v8::ModuleStatus::Errored); } |