summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/tests/integration/run_tests.rs7
-rw-r--r--cli/tests/testdata/dom_exception_formatting.ts1
-rw-r--r--cli/tests/testdata/dom_exception_formatting.ts.out2
-rw-r--r--core/error.rs33
4 files changed, 42 insertions, 1 deletions
diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs
index 2c0a16582..4fd825507 100644
--- a/cli/tests/integration/run_tests.rs
+++ b/cli/tests/integration/run_tests.rs
@@ -1805,3 +1805,10 @@ itest!(byte_order_mark {
args: "run --no-check byte_order_mark.ts",
output: "byte_order_mark.out",
});
+
+// Regression test for https://github.com/denoland/deno/issues/11451.
+itest!(dom_exception_formatting {
+ args: "run dom_exception_formatting.ts",
+ output: "dom_exception_formatting.ts.out",
+ exit_code: 1,
+});
diff --git a/cli/tests/testdata/dom_exception_formatting.ts b/cli/tests/testdata/dom_exception_formatting.ts
new file mode 100644
index 000000000..0209ec81e
--- /dev/null
+++ b/cli/tests/testdata/dom_exception_formatting.ts
@@ -0,0 +1 @@
+throw new DOMException("foo", "SyntaxError");
diff --git a/cli/tests/testdata/dom_exception_formatting.ts.out b/cli/tests/testdata/dom_exception_formatting.ts.out
new file mode 100644
index 000000000..2a815eac1
--- /dev/null
+++ b/cli/tests/testdata/dom_exception_formatting.ts.out
@@ -0,0 +1,2 @@
+[WILDCARD]error: Uncaught SyntaxError: foo
+[WILDCARD]
diff --git a/core/error.rs b/core/error.rs
index abe707795..087b27c41 100644
--- a/core/error.rs
+++ b/core/error.rs
@@ -189,7 +189,7 @@ impl JsError {
let msg = v8::Exception::create_message(scope, exception);
- let (message, frames, stack) = if exception.is_native_error() {
+ let (message, frames, stack) = if is_instance_of_error(scope, exception) {
// The exception is a JS Error object.
let exception: v8::Local<v8::Object> = exception.try_into().unwrap();
@@ -296,6 +296,37 @@ pub(crate) fn attach_handle_to_error(
ErrWithV8Handle::new(scope, err, handle).into()
}
+/// Implements `value instanceof primordials.Error` in JS. Similar to
+/// `Value::is_native_error()` but more closely matches the semantics
+/// of `instanceof`. `Value::is_native_error()` also checks for static class
+/// inheritance rather than just scanning the prototype chain, which doesn't
+/// work with our WebIDL implementation of `DOMException`.
+fn is_instance_of_error<'s>(
+ scope: &mut v8::HandleScope<'s>,
+ value: v8::Local<v8::Value>,
+) -> bool {
+ if !value.is_object() {
+ return false;
+ }
+ let message = v8::String::empty(scope);
+ let error_prototype = v8::Exception::error(scope, message)
+ .to_object(scope)
+ .unwrap()
+ .get_prototype(scope)
+ .unwrap();
+ let mut maybe_prototype =
+ value.to_object(scope).unwrap().get_prototype(scope);
+ while let Some(prototype) = maybe_prototype {
+ if prototype.strict_equals(error_prototype) {
+ return true;
+ }
+ maybe_prototype = prototype
+ .to_object(scope)
+ .and_then(|o| o.get_prototype(scope));
+ }
+ false
+}
+
// TODO(piscisaureus): rusty_v8 should implement the Error trait on
// values of type v8::Global<T>.
pub(crate) struct ErrWithV8Handle {