Repository: denoland/deno
Pull request: fix(runtime): handle `options` parameter in `Deno.errors.*` constructors

`Deno.errors.*` are just errors. However, before, a `Deno.errors.*` constructor wouldn't use the `options` parameter in the call to the constructor call to the parent class (`super()`). Now it does.

In other words, the following code used to return `undefined` and pass a type check. Now, it returns `hello` and the error's runtime behaviour aligns with its type.

```ts
new Deno.errors.NotFound("not found", { cause: "hello" }).cause;
```

Changed files:
filename: runtime/js/01_errors.js
patch: @@ -5,155 +5,155 @@ const { BadResource, Interrupted, NotCapable } = core;
 const { Error } = primordials;
 
 class NotFound extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "NotFound";
   }
 }
 
 class ConnectionRefused extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "ConnectionRefused";
   }
 }
 
 class ConnectionReset extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "ConnectionReset";
   }
 }
 
 class ConnectionAborted extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "ConnectionAborted";
   }
 }
 
 class NotConnected extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "NotConnected";
   }
 }
 
 class AddrInUse extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "AddrInUse";
   }
 }
 
 class AddrNotAvailable extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "AddrNotAvailable";
   }
 }
 
 class BrokenPipe extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "BrokenPipe";
   }
 }
 
 class AlreadyExists extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "AlreadyExists";
   }
 }
 
 class InvalidData extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "InvalidData";
   }
 }
 
 class TimedOut extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "TimedOut";
   }
 }
 
 class WriteZero extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "WriteZero";
   }
 }
 
 class WouldBlock extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "WouldBlock";
   }
 }
 
 class UnexpectedEof extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "UnexpectedEof";
   }
 }
 
 class Http extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "Http";
   }
 }
 
 class Busy extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "Busy";
   }
 }
 
 class PermissionDenied extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "PermissionDenied";
   }
 }
 
 class NotSupported extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "NotSupported";
   }
 }
 
 class FilesystemLoop extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "FilesystemLoop";
   }
 }
 
 class IsADirectory extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "IsADirectory";
   }
 }
 
 class NetworkUnreachable extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "NetworkUnreachable";
   }
 }
 
 class NotADirectory extends Error {
-  constructor(msg) {
-    super(msg);
+  constructor(msg, opts) {
+    super(msg, opts);
     this.name = "NotADirectory";
   }
 }

filename: tests/unit/error_test.ts
patch: @@ -1,28 +1,49 @@
 // Copyright 2018-2026 the Deno authors. MIT license.
-import { assert, assertThrows, fail } from "./test_util.ts";
+import {
+  assertEquals,
+  assertInstanceOf,
+  assertThrows,
+  fail,
+} from "@std/assert";
+
+const errorConstructors = [
+  Deno.errors.NotFound,
+  Deno.errors.PermissionDenied,
+  Deno.errors.ConnectionRefused,
+  Deno.errors.ConnectionReset,
+  Deno.errors.ConnectionAborted,
+  Deno.errors.NotConnected,
+  Deno.errors.AddrInUse,
+  Deno.errors.AddrNotAvailable,
+  Deno.errors.BrokenPipe,
+  Deno.errors.AlreadyExists,
+  Deno.errors.InvalidData,
+  Deno.errors.TimedOut,
+  Deno.errors.Interrupted,
+  Deno.errors.WriteZero,
+  Deno.errors.WouldBlock,
+  Deno.errors.UnexpectedEof,
+  Deno.errors.BadResource,
+  Deno.errors.Http,
+  Deno.errors.Busy,
+  Deno.errors.NotSupported,
+  Deno.errors.FilesystemLoop,
+  Deno.errors.IsADirectory,
+  Deno.errors.NetworkUnreachable,
+  Deno.errors.NotADirectory,
+  Deno.errors.NotCapable,
+];
+
+function assertError(ErrorConstructor: typeof Deno.errors.NotFound) {
+  const error = new ErrorConstructor("msg", { cause: "cause" });
+  assertInstanceOf(error, Error);
+  assertEquals(error.cause, "cause");
+}
 
 Deno.test("Errors work", () => {
-  assert(new Deno.errors.NotFound("msg") instanceof Error);
-  assert(new Deno.errors.PermissionDenied("msg") instanceof Error);
-  assert(new Deno.errors.ConnectionRefused("msg") instanceof Error);
-  assert(new Deno.errors.ConnectionReset("msg") instanceof Error);
-  assert(new Deno.errors.ConnectionAborted("msg") instanceof Error);
-  assert(new Deno.errors.NotConnected("msg") instanceof Error);
-  assert(new Deno.errors.AddrInUse("msg") instanceof Error);
-  assert(new Deno.errors.AddrNotAvailable("msg") instanceof Error);
-  assert(new Deno.errors.BrokenPipe("msg") instanceof Error);
-  assert(new Deno.errors.AlreadyExists("msg") instanceof Error);
-  assert(new Deno.errors.InvalidData("msg") instanceof Error);
-  assert(new Deno.errors.TimedOut("msg") instanceof Error);
-  assert(new Deno.errors.Interrupted("msg") instanceof Error);
-  assert(new Deno.errors.WouldBlock("msg") instanceof Error);
-  assert(new Deno.errors.WriteZero("msg") instanceof Error);
-  assert(new Deno.errors.UnexpectedEof("msg") instanceof Error);
-  assert(new Deno.errors.BadResource("msg") instanceof Error);
-  assert(new Deno.errors.Http("msg") instanceof Error);
-  assert(new Deno.errors.Busy("msg") instanceof Error);
-  assert(new Deno.errors.NotSupported("msg") instanceof Error);
-  assert(new Deno.errors.NotCapable("msg") instanceof Error);
+  for (const errorConstructor of errorConstructors) {
+    assertError(errorConstructor);
+  }
 });
 
 Deno.test("Errors have some tamper resistance", () => {