Repository: denoland/deno
Pull request: feat(ext/web): add `[[ErrorData]]` slot to `DOMException`

<!--
Before submitting a PR, please read https://docs.deno.com/runtime/manual/references/contributing

1. Give the PR a descriptive title.

  Examples of good title:
    - fix(std/http): Fix race condition in server
    - docs(console): Update docstrings
    - feat(doc): Handle nested reexports

  Examples of bad title:
    - fix #7123
    - update docs
    - fix bugs

2. Ensure there is a related issue and it is referenced in the PR text.
3. Ensure there are tests that cover the changes.
4. Ensure `cargo test` passes.
5. Ensure `./tools/format.js` passes without changing files.
6. Ensure `./tools/lint.js` passes.
7. Open as a draft PR if your work is still in progress. The CI won't run
   all steps, but you can add '[ci]' to a commit message to force it to.
8. If you would like to run the benchmarks on the CI, add the 'ci-bench' label.
-->

Preparing for Stage 3 [`Error.isError`](https://github.com/tc39/proposal-is-error) (https://github.com/whatwg/webidl/pull/1421)

Node.js `util.isError` already returns `true` for `DOMException`, ~~so this change should have no effect.~~


Changed files:
filename: ext/web/01_dom_exception.js
patch: @@ -9,14 +9,15 @@
 
 import { primordials } from "ext:core/mod.js";
 const {
+  Error,
   ErrorPrototype,
-  ErrorCaptureStackTrace,
   ObjectDefineProperty,
   ObjectCreate,
   ObjectEntries,
   ObjectHasOwn,
   ObjectPrototypeIsPrototypeOf,
   ObjectSetPrototypeOf,
+  ReflectConstruct,
   Symbol,
   SymbolFor,
 } = primordials;
@@ -107,12 +108,14 @@ class DOMException {
     );
     const code = nameToCodeMapping[name] ?? 0;
 
-    this[_message] = message;
-    this[_name] = name;
-    this[_code] = code;
-    this[webidl.brand] = webidl.brand;
+    // execute Error constructor to have stack property and [[ErrorData]] internal slot
+    const error = ReflectConstruct(Error, [], new.target);
+    error[_message] = message;
+    error[_name] = name;
+    error[_code] = code;
+    error[webidl.brand] = webidl.brand;
 
-    ErrorCaptureStackTrace(this, DOMException);
+    return error;
   }
 
   get message() {

filename: tests/unit_node/util_test.ts
patch: @@ -224,7 +224,7 @@ Deno.test({
   fn() {
     assert(util.types.isNativeError(new Error()));
     assert(util.types.isNativeError(new TypeError()));
-    assert(!util.types.isNativeError(new DOMException()));
+    assert(util.types.isNativeError(new DOMException()));
   },
 });
 

filename: tests/wpt/runner/expectation.json
patch: @@ -3594,16 +3594,13 @@
         "DOMException-constructor-behavior.any.html": true,
         "DOMException-constructor-behavior.any.worker.html": true,
         "DOMException-custom-bindings.any.html": true,
-        "DOMException-custom-bindings.any.worker.html": true
+        "DOMException-custom-bindings.any.worker.html": true,
+        "exceptions.html": false
       },
       "class-string-interface.any.html": true,
       "class-string-interface.any.worker.html": true,
-      "class-string-iterator-prototype-object.any.html": [
-        "Object.prototype.toString applied after deleting @@toStringTag"
-      ],
-      "class-string-iterator-prototype-object.any.worker.html": [
-        "Object.prototype.toString applied after deleting @@toStringTag"
-      ],
+      "class-string-iterator-prototype-object.any.html": true,
+      "class-string-iterator-prototype-object.any.worker.html": true,
       "class-string-named-properties-object.window.html": false,
       "global-immutable-prototype.any.html": [
         "Setting to a different prototype"
@@ -9754,16 +9751,14 @@
         "structured-cloning-error-stack-optional.sub.window.html": [
           "page-created Error (cross-site iframe)",
           "page-created Error (same-origin iframe)",
-          "page-created DOMException (structuredClone())",
           "page-created DOMException (cross-site iframe)",
           "page-created DOMException (same-origin iframe)",
           "JS-engine-created TypeError (cross-site iframe)",
           "JS-engine-created TypeError (same-origin iframe)",
           "web API-created TypeError (cross-site iframe)",
           "web API-created TypeError (same-origin iframe)",
           "web API-created DOMException (cross-site iframe)",
-          "web API-created DOMException (same-origin iframe)",
-          "page-created DOMException (worker)"
+          "web API-created DOMException (same-origin iframe)"
         ],
         "transfer-errors.window.html": false,
         "window-postmessage.window.html": false