1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 15:24:46 -05:00

fix(core): fix top-level-await error handling (#4911)

This commit is contained in:
Bartek Iwańczuk 2020-04-27 17:25:26 +02:00 committed by GitHub
parent dd0b25e313
commit 7a94ea08e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 4 deletions

View file

@ -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 {

View file

@ -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);
}