Skip to content

Commit 307c5ac

Browse files
committed
feat: upgrade QuotaExceededError to DOMException subclass
Implements Web IDL spec change (whatwg/webidl#1465) to upgrade QuotaExceededError from a DOMException name to a proper subclass. Changes: - Remove QuotaExceededError from DOMException names table - Create QuotaExceededError class extending DOMException - Add quota and requested properties (default to null) - Update error registration to use new QuotaExceededError class - Add comprehensive tests for QuotaExceededError subclass Fixes denoland#30028
1 parent ef3192d commit 307c5ac

File tree

3 files changed

+83
-11
lines changed

3 files changed

+83
-11
lines changed

ext/web/01_dom_exception.js

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ const nameToCodeMapping = ObjectCreate(null, {
8181
NetworkError: { value: NETWORK_ERR },
8282
AbortError: { value: ABORT_ERR },
8383
URLMismatchError: { value: URL_MISMATCH_ERR },
84-
QuotaExceededError: { value: QUOTA_EXCEEDED_ERR },
8584
TimeoutError: { value: TIMEOUT_ERR },
8685
InvalidNodeTypeError: { value: INVALID_NODE_TYPE_ERR },
8786
DataCloneError: { value: DATA_CLONE_ERR },
@@ -194,4 +193,42 @@ for (let i = 0; i < entries.length; ++i) {
194193
ObjectDefineProperty(DOMException.prototype, key, desc);
195194
}
196195

197-
export { DOMException, DOMExceptionPrototype };
196+
// Defined in WebIDL 4.3.
197+
// https://webidl.spec.whatwg.org/#quotaexceedederror
198+
class QuotaExceededError extends DOMException {
199+
#quota = null;
200+
#requested = null;
201+
202+
constructor(message = "", options = { __proto__: null }) {
203+
message = webidl.converters.DOMString(
204+
message,
205+
"Failed to construct 'QuotaExceededError'",
206+
"Argument 1",
207+
);
208+
super(message, "QuotaExceededError");
209+
210+
if (options !== null && options !== undefined) {
211+
if (ObjectHasOwn(options, "quota")) {
212+
this.#quota = options.quota ?? null;
213+
}
214+
if (ObjectHasOwn(options, "requested")) {
215+
this.#requested = options.requested ?? null;
216+
}
217+
}
218+
}
219+
220+
get quota() {
221+
webidl.assertBranded(this, QuotaExceededErrorPrototype);
222+
return this.#quota;
223+
}
224+
225+
get requested() {
226+
webidl.assertBranded(this, QuotaExceededErrorPrototype);
227+
return this.#requested;
228+
}
229+
}
230+
231+
webidl.configureInterface(QuotaExceededError);
232+
const QuotaExceededErrorPrototype = QuotaExceededError.prototype;
233+
234+
export { DOMException, DOMExceptionPrototype, QuotaExceededError };

runtime/js/99_main.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ import {
7676
} from "ext:runtime/90_deno_ns.js";
7777
import { errors } from "ext:runtime/01_errors.js";
7878
import * as webidl from "ext:deno_webidl/00_webidl.js";
79-
import { DOMException } from "ext:deno_web/01_dom_exception.js";
79+
import { DOMException, QuotaExceededError } from "ext:deno_web/01_dom_exception.js";
8080
import {
8181
unstableForWindowOrWorkerGlobalScope,
8282
windowOrWorkerGlobalScope,
@@ -309,11 +309,10 @@ function formatException(error) {
309309
) {
310310
return null;
311311
} else if (typeof error == "string") {
312-
return `Uncaught ${
313-
inspectArgs([quoteString(error, getDefaultInspectOptions())], {
314-
colors: !getStderrNoColor(),
315-
})
316-
}`;
312+
return `Uncaught ${inspectArgs([quoteString(error, getDefaultInspectOptions())], {
313+
colors: !getStderrNoColor(),
314+
})
315+
}`;
317316
} else {
318317
return `Uncaught ${inspectArgs([error], { colors: !getStderrNoColor() })}`;
319318
}
@@ -350,7 +349,7 @@ core.registerErrorBuilder(
350349
core.registerErrorBuilder(
351350
"DOMExceptionQuotaExceededError",
352351
function DOMExceptionQuotaExceededError(msg) {
353-
return new DOMException(msg, "QuotaExceededError");
352+
return new QuotaExceededError(msg);
354353
},
355354
);
356355
core.registerErrorBuilder(
@@ -566,8 +565,8 @@ const finalDenoNs = {
566565
// Deno.test, Deno.bench, Deno.lint are noops here, but kept for compatibility; so
567566
// that they don't cause errors when used outside of `deno test`/`deno bench`/`deno lint`
568567
// contexts.
569-
test: () => {},
570-
bench: () => {},
568+
test: () => { },
569+
bench: () => { },
571570
lint: {
572571
runPlugin: () => {
573572
throw new Error(

tests/unit/dom_exception_test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,39 @@ Deno.test(function hasStackAccessor() {
3030
assert(typeof desc.get === "function");
3131
assert(typeof desc.set === "function");
3232
});
33+
34+
Deno.test(function quotaExceededErrorIsSubclass() {
35+
const error = new QuotaExceededError("test message");
36+
assert(error instanceof QuotaExceededError);
37+
assert(error instanceof DOMException);
38+
assert(error instanceof Error);
39+
});
40+
41+
Deno.test(function quotaExceededErrorCodeIsZero() {
42+
// QuotaExceededError is now a subclass, not a DOMException name
43+
// So creating a DOMException with name "QuotaExceededError" should have code 0
44+
const error = new DOMException("test", "QuotaExceededError");
45+
assertEquals(error.code, 0);
46+
});
47+
48+
Deno.test(function quotaExceededErrorHasCorrectName() {
49+
const error = new QuotaExceededError("test message");
50+
assertEquals(error.name, "QuotaExceededError");
51+
});
52+
53+
Deno.test(function quotaExceededErrorHasQuotaAndRequestedProperties() {
54+
const error = new QuotaExceededError("test message");
55+
assertEquals(error.quota, null);
56+
assertEquals(error.requested, null);
57+
});
58+
59+
Deno.test(function quotaExceededErrorWithOptions() {
60+
const error = new QuotaExceededError("test message", {
61+
quota: 1000,
62+
requested: 1500,
63+
});
64+
assertEquals(error.quota, 1000);
65+
assertEquals(error.requested, 1500);
66+
assertEquals(error.message, "test message");
67+
assertEquals(error.name, "QuotaExceededError");
68+
});

0 commit comments

Comments
 (0)