summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/fmt_errors.rs5
-rw-r--r--cli/tests/integration/run_tests.rs11
-rw-r--r--cli/tests/testdata/report_error.ts3
-rw-r--r--cli/tests/testdata/report_error.ts.out5
-rw-r--r--cli/tests/testdata/report_error_handled.ts19
-rw-r--r--cli/tests/testdata/report_error_handled.ts.out13
-rw-r--r--ext/web/02_event.js15
-rw-r--r--ext/web/lib.deno_web.d.ts19
-rw-r--r--runtime/web_worker.rs3
-rw-r--r--tools/wpt/expectation.json17
10 files changed, 93 insertions, 17 deletions
diff --git a/cli/fmt_errors.rs b/cli/fmt_errors.rs
index 953dfec8b..3016e0ff4 100644
--- a/cli/fmt_errors.rs
+++ b/cli/fmt_errors.rs
@@ -48,8 +48,9 @@ pub fn format_location(frame: &JsStackFrame) -> String {
return cyan("native").to_string();
}
let mut result = String::new();
- if let Some(file_name) = &frame.file_name {
- result += &cyan(&format_file_name(file_name)).to_string();
+ let file_name = frame.file_name.clone().unwrap_or_default();
+ if !file_name.is_empty() {
+ result += &cyan(&format_file_name(&file_name)).to_string();
} else {
if frame.is_eval {
result +=
diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs
index b99ab2890..85363a27f 100644
--- a/cli/tests/integration/run_tests.rs
+++ b/cli/tests/integration/run_tests.rs
@@ -2753,3 +2753,14 @@ fn deno_no_prompt_environment_variable() {
.unwrap();
assert!(output.status.success());
}
+
+itest!(report_error {
+ args: "run --quiet report_error.ts",
+ output: "report_error.ts.out",
+ exit_code: 1,
+});
+
+itest!(report_error_handled {
+ args: "run --quiet report_error_handled.ts",
+ output: "report_error_handled.ts.out",
+});
diff --git a/cli/tests/testdata/report_error.ts b/cli/tests/testdata/report_error.ts
new file mode 100644
index 000000000..a6d4af1fd
--- /dev/null
+++ b/cli/tests/testdata/report_error.ts
@@ -0,0 +1,3 @@
+console.log(1);
+reportError(new Error("foo"));
+console.log(2);
diff --git a/cli/tests/testdata/report_error.ts.out b/cli/tests/testdata/report_error.ts.out
new file mode 100644
index 000000000..185db62a5
--- /dev/null
+++ b/cli/tests/testdata/report_error.ts.out
@@ -0,0 +1,5 @@
+1
+error: Uncaught Error: foo
+reportError(new Error("foo"));
+ ^
+ at [WILDCARD]/report_error.ts:2:13
diff --git a/cli/tests/testdata/report_error_handled.ts b/cli/tests/testdata/report_error_handled.ts
new file mode 100644
index 000000000..de58f0b8e
--- /dev/null
+++ b/cli/tests/testdata/report_error_handled.ts
@@ -0,0 +1,19 @@
+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);
+};
+
+console.log(1);
+reportError(new Error("foo"));
+console.log(2);
diff --git a/cli/tests/testdata/report_error_handled.ts.out b/cli/tests/testdata/report_error_handled.ts.out
new file mode 100644
index 000000000..89fa30314
--- /dev/null
+++ b/cli/tests/testdata/report_error_handled.ts.out
@@ -0,0 +1,13 @@
+1
+{
+ cancelable: true,
+ message: "Uncaught Error: foo",
+ filename: "[WILDCARD]/report_error_handled.ts",
+ lineno: 18,
+ colno: 13,
+ error: Error: foo
+ at [WILDCARD]/report_error_handled.ts:18:13
+}
+onerror() called Error: foo
+ at [WILDCARD]/report_error_handled.ts:18:13
+2
diff --git a/ext/web/02_event.js b/ext/web/02_event.js
index 677768ac9..06df6429c 100644
--- a/ext/web/02_event.js
+++ b/ext/web/02_event.js
@@ -1367,6 +1367,20 @@
reportExceptionStackedCalls--;
}
+ function checkThis(thisArg) {
+ if (thisArg !== null && thisArg !== undefined && thisArg !== globalThis) {
+ throw new TypeError("Illegal invocation");
+ }
+ }
+
+ // https://html.spec.whatwg.org/#dom-reporterror
+ function reportError(error) {
+ checkThis(this);
+ const prefix = "Failed to call 'reportError'";
+ webidl.requiredArguments(arguments.length, 1, { prefix });
+ reportException(error);
+ }
+
window.Event = Event;
window.EventTarget = EventTarget;
window.ErrorEvent = ErrorEvent;
@@ -1377,6 +1391,7 @@
window.dispatchEvent = EventTarget.prototype.dispatchEvent;
window.addEventListener = EventTarget.prototype.addEventListener;
window.removeEventListener = EventTarget.prototype.removeEventListener;
+ window.reportError = reportError;
window.__bootstrap.eventTarget = {
EventTarget,
setEventTargetData,
diff --git a/ext/web/lib.deno_web.d.ts b/ext/web/lib.deno_web.d.ts
index 77c502fac..8c845ced1 100644
--- a/ext/web/lib.deno_web.d.ts
+++ b/ext/web/lib.deno_web.d.ts
@@ -890,3 +890,22 @@ declare class DecompressionStream {
readonly readable: ReadableStream<Uint8Array>;
readonly writable: WritableStream<Uint8Array>;
}
+
+/** Dispatch an uncaught exception. Similar to a synchronous version of:
+ * ```ts
+ * setTimeout(() => { throw error; }, 0);
+ * ```
+ * The error can not be caught with a `try/catch` block. An error event will
+ * be dispatched to the global scope. You can prevent the error from being
+ * reported to the console with `Event.prototype.preventDefault()`:
+ * ```ts
+ * addEventListener("error", (event) => {
+ * event.preventDefault();
+ * });
+ * reportError(new Error("foo")); // Will not be reported.
+ * ```
+ * In Deno, this error will terminate the process if not intercepted like above.
+ */
+declare function reportError(
+ error: any,
+): void;
diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs
index 40b222417..f4c040aa4 100644
--- a/runtime/web_worker.rs
+++ b/runtime/web_worker.rs
@@ -638,7 +638,8 @@ impl WebWorker {
v8::Local::<v8::Value>::new(scope, poll_for_messages_fn);
let fn_ = v8::Local::<v8::Function>::try_from(poll_for_messages).unwrap();
let undefined = v8::undefined(scope);
- fn_.call(scope, undefined.into(), &[]).unwrap();
+ // This call may return `None` if worker is terminated.
+ fn_.call(scope, undefined.into(), &[]);
}
}
diff --git a/tools/wpt/expectation.json b/tools/wpt/expectation.json
index 38a1e3db5..67e256353 100644
--- a/tools/wpt/expectation.json
+++ b/tools/wpt/expectation.json
@@ -3646,18 +3646,8 @@
"queue-microtask.any.worker.html": true
},
"scripting": {
- "reporterror.any.html": [
- "self.reportError(1)",
- "self.reportError(TypeError)",
- "self.reportError(undefined)",
- "self.reportError() doesn't invoke getters"
- ],
- "reporterror.any.worker.html": [
- "self.reportError(1)",
- "self.reportError(TypeError)",
- "self.reportError(undefined)",
- "self.reportError() doesn't invoke getters"
- ]
+ "reporterror.any.html": false,
+ "reporterror.any.worker.html": false
},
"structured-clone": {
"structured-clone.any.html": [
@@ -4237,7 +4227,6 @@
"opening-handshake": {
"003-sets-origin.worker.html": false
},
- "Create-on-worker-shutdown.any.worker.html": false,
"Send-data.worker.html": true,
"Send-data.worker.html?wpt_flags=h2": false,
"Send-data.worker.html?wss": true,
@@ -4648,4 +4637,4 @@
"idlharness.https.any.worker.html": true,
"idlharness-shadowrealm.window.html": false
}
-} \ No newline at end of file
+}