fix(core): run macrotasks and next ticks after polling dynamic imports (#17173)

This commit fixes handling of rejected promises in dynamic imports
evaluation.

Previously we were running callbacks for next ticks and macrotasks
_before_ polling
dynamic imports and checked for unhandled rejections immediately after.
This is wrong,
as `unhandledrejection` event is dispatched and its callbacks are run as
macrotasks.

This commit changes order of actions performed by the event loop to
following:
- poll async ops
- poll dynamic imports
- run next tick callbacks
- run macrotask callbacks
- check for unhandled promise rejections
This commit is contained in:
Bartek Iwańczuk 2022-12-23 19:46:24 +01:00 committed by GitHub
parent 2a61b5fdd4
commit 208c91b68f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 58 additions and 8 deletions

View file

@ -2945,6 +2945,19 @@ mod run {
output: "run/unhandled_rejection_sync_error.ts.out",
});
// Regression test for https://github.com/denoland/deno/issues/15661
itest!(unhandled_rejection_dynamic_import {
args: "run --allow-read run/unhandled_rejection_dynamic_import/main.ts",
output: "run/unhandled_rejection_dynamic_import/main.ts.out",
exit_code: 1,
});
// Regression test for https://github.com/denoland/deno/issues/16909
itest!(unhandled_rejection_dynamic_import2 {
args: "run --allow-read run/unhandled_rejection_dynamic_import2/main.ts",
output: "run/unhandled_rejection_dynamic_import2/main.ts.out",
});
itest!(nested_error {
args: "run run/nested_error.ts",
output: "run/nested_error.ts.out",

View file

@ -0,0 +1,5 @@
globalThis.addEventListener("unhandledrejection", () => {
console.log("hey");
});
console.log("---");
Promise.reject();

View file

@ -0,0 +1 @@
await import("./import.ts");

View file

@ -0,0 +1,3 @@
---
hey
error: Uncaught (in promise) undefined

View file

@ -0,0 +1,3 @@
export default {
a: "a",
};

View file

@ -0,0 +1,21 @@
globalThis.addEventListener("unhandledrejection", (e) => {
console.log("unhandled rejection", e.reason);
e.preventDefault();
});
const dummyImport = (await import("./import.ts")).default;
let a = new Promise((resolve, reject) => {
throw "errA";
});
let i = 0;
while (true) {
await new Promise((resolve) => setTimeout(resolve, 100));
i++;
console.log("running...");
if (i > 3) {
break;
}
}

View file

@ -0,0 +1,5 @@
unhandled rejection errA
running...
running...
running...
running...