summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/tests/integration/run_tests.rs11
-rw-r--r--cli/tests/testdata/queue_microtask_error.ts5
-rw-r--r--cli/tests/testdata/queue_microtask_error.ts.out6
-rw-r--r--cli/tests/testdata/queue_microtask_error_handled.ts21
-rw-r--r--cli/tests/testdata/queue_microtask_error_handled.ts.out15
-rw-r--r--core/01_core.js30
-rw-r--r--runtime/js/99_main.js3
-rw-r--r--tools/wpt/expectation.json4
8 files changed, 91 insertions, 4 deletions
diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs
index 9c60cc745..8998eecc9 100644
--- a/cli/tests/integration/run_tests.rs
+++ b/cli/tests/integration/run_tests.rs
@@ -2745,6 +2745,17 @@ itest!(report_error_end_of_program {
exit_code: 1,
});
+itest!(queue_microtask_error {
+ args: "run --quiet queue_microtask_error.ts",
+ output: "queue_microtask_error.ts.out",
+ exit_code: 1,
+});
+
+itest!(queue_microtask_error_handled {
+ args: "run --quiet queue_microtask_error_handled.ts",
+ output: "queue_microtask_error_handled.ts.out",
+});
+
itest!(spawn_stdout_inherit {
args: "run --quiet --unstable -A spawn_stdout_inherit.ts",
output: "spawn_stdout_inherit.ts.out",
diff --git a/cli/tests/testdata/queue_microtask_error.ts b/cli/tests/testdata/queue_microtask_error.ts
new file mode 100644
index 000000000..b2e9642c5
--- /dev/null
+++ b/cli/tests/testdata/queue_microtask_error.ts
@@ -0,0 +1,5 @@
+queueMicrotask(() => {
+ throw new Error("foo");
+});
+console.log(1);
+Promise.resolve().then(() => console.log(2));
diff --git a/cli/tests/testdata/queue_microtask_error.ts.out b/cli/tests/testdata/queue_microtask_error.ts.out
new file mode 100644
index 000000000..6c4d41936
--- /dev/null
+++ b/cli/tests/testdata/queue_microtask_error.ts.out
@@ -0,0 +1,6 @@
+1
+error: Uncaught Error: foo
+ throw new Error("foo");
+ ^
+ at [WILDCARD]/queue_microtask_error.ts:2:9
+ at deno:core/[WILDCARD]
diff --git a/cli/tests/testdata/queue_microtask_error_handled.ts b/cli/tests/testdata/queue_microtask_error_handled.ts
new file mode 100644
index 000000000..7d1440135
--- /dev/null
+++ b/cli/tests/testdata/queue_microtask_error_handled.ts
@@ -0,0 +1,21 @@
+addEventListener("error", (event) => {
+ console.log({
+ cancelable: event.cancelable,
+ message: event.message,
+ filename: event.filename,
+ lineno: event.lineno,
+ colno: event.colno,
+ error: event.error,
+ });
+ event.preventDefault();
+});
+
+onerror = (event) => {
+ console.log("onerror() called", event.error);
+};
+
+queueMicrotask(() => {
+ throw new Error("foo");
+});
+console.log(1);
+Promise.resolve().then(() => console.log(2));
diff --git a/cli/tests/testdata/queue_microtask_error_handled.ts.out b/cli/tests/testdata/queue_microtask_error_handled.ts.out
new file mode 100644
index 000000000..7f3f7f84a
--- /dev/null
+++ b/cli/tests/testdata/queue_microtask_error_handled.ts.out
@@ -0,0 +1,15 @@
+1
+{
+ cancelable: true,
+ message: "Uncaught Error: foo",
+ filename: "[WILDCARD]/queue_microtask_error_handled.ts",
+ lineno: 18,
+ colno: 9,
+ error: Error: foo
+ at [WILDCARD]/queue_microtask_error_handled.ts:18:9
+ at deno:core/[WILDCARD]
+}
+onerror() called Error: foo
+ at [WILDCARD]/queue_microtask_error_handled.ts:18:9
+ at deno:core/[WILDCARD]
+2
diff --git a/core/01_core.js b/core/01_core.js
index aaff59148..e1ac275eb 100644
--- a/core/01_core.js
+++ b/core/01_core.js
@@ -210,8 +210,35 @@
return aggregate;
}
+ let reportExceptionCallback = undefined;
+
+ // Used to report errors thrown from functions passed to `queueMicrotask()`.
+ // The callback will be passed the thrown error. For example, you can use this
+ // to dispatch an error event to the global scope.
+ // In other words, set the implementation for
+ // https://html.spec.whatwg.org/multipage/webappapis.html#report-the-exception
+ function setReportExceptionCallback(cb) {
+ if (typeof cb != "function") {
+ throw new TypeError("expected a function");
+ }
+ reportExceptionCallback = cb;
+ }
+
function queueMicrotask(cb) {
- return ops.op_queue_microtask(cb);
+ if (typeof cb != "function") {
+ throw new TypeError("expected a function");
+ }
+ return ops.op_queue_microtask(() => {
+ try {
+ cb();
+ } catch (error) {
+ if (reportExceptionCallback) {
+ reportExceptionCallback(error);
+ } else {
+ throw error;
+ }
+ }
+ });
}
// Some "extensions" rely on "BadResource" and "Interrupted" errors in the
@@ -252,6 +279,7 @@
opCallTraces,
refOp,
unrefOp,
+ setReportExceptionCallback,
close: (rid) => ops.op_close(rid),
tryClose: (rid) => ops.op_try_close(rid),
read: opAsync.bind(null, "op_read"),
diff --git a/runtime/js/99_main.js b/runtime/js/99_main.js
index cbc5c1b5b..b25022a08 100644
--- a/runtime/js/99_main.js
+++ b/runtime/js/99_main.js
@@ -76,7 +76,7 @@ delete Intl.v8BreakIterator;
const errors = window.__bootstrap.errors.errors;
const webidl = window.__bootstrap.webidl;
const domException = window.__bootstrap.domException;
- const { defineEventHandler } = window.__bootstrap.event;
+ const { defineEventHandler, reportException } = window.__bootstrap.event;
const { deserializeJsMessageData, serializeJsMessageData } =
window.__bootstrap.messagePort;
@@ -243,6 +243,7 @@ delete Intl.v8BreakIterator;
core.setMacrotaskCallback(timers.handleTimerMacrotask);
core.setMacrotaskCallback(promiseRejectMacrotaskCallback);
core.setWasmStreamingCallback(fetch.handleWasmStreaming);
+ core.setReportExceptionCallback(reportException);
ops.op_set_format_exception_callback(formatException);
version.setVersions(
runtimeOptions.denoVersion,
diff --git a/tools/wpt/expectation.json b/tools/wpt/expectation.json
index 813abbbba..39fe59515 100644
--- a/tools/wpt/expectation.json
+++ b/tools/wpt/expectation.json
@@ -3615,7 +3615,7 @@
"type-long-settimeout.any.worker.html": true
},
"microtask-queuing": {
- "queue-microtask-exceptions.any.html": false,
+ "queue-microtask-exceptions.any.html": true,
"queue-microtask.any.html": true,
"queue-microtask.any.worker.html": true
},
@@ -4610,4 +4610,4 @@
"idlharness.https.any.worker.html": true,
"idlharness-shadowrealm.window.html": false
}
-} \ No newline at end of file
+}