summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/tests/integration_tests.rs1
-rw-r--r--core/es_isolate.rs32
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);
}