Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions cli/tsc/dts/lib.deno_web.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,31 @@ declare var DOMException: {
readonly DATA_CLONE_ERR: 25;
};

/** @category Platform */
interface QuotaExceededErrorOptions {
quota?: number;
requested?: number;
}

/**
* Represents an error when a quota has been exceeded.
*
* @category Platform
*/
interface QuotaExceededError extends DOMException {
readonly quota: number | null;
readonly requested: number | null;
}

/** @category Platform */
declare var QuotaExceededError: {
readonly prototype: QuotaExceededError;
new (
message?: string,
options?: QuotaExceededErrorOptions,
): QuotaExceededError;
};

/** @category Events */
interface EventInit {
bubbles?: boolean;
Expand Down
2 changes: 2 additions & 0 deletions cli/tsc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1344,6 +1344,8 @@ pub static TYPES_NODE_IGNORABLE_NAMES: &[&str] = &[
"PerformanceMeasure",
"QueuingStrategy",
"QueuingStrategySize",
"QuotaExceededError",
"QuotaExceededErrorOptions",
"ReadableByteStreamController",
"ReadableStream",
"ReadableStreamBYOBReader",
Expand Down
71 changes: 70 additions & 1 deletion ext/web/01_dom_exception.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const {
ObjectSetPrototypeOf,
ReflectConstruct,
ReflectHas,
RangeError,
Symbol,
SymbolFor,
} = primordials;
Expand Down Expand Up @@ -243,4 +244,72 @@ core.registerCloneableResource("DOMException", (data) => {
return ex;
});

export { DOMException, DOMExceptionPrototype };
const _quota = Symbol("quota");
const _requested = Symbol("requested");

// Defined in WebIDL 4.3.1.
// https://webidl.spec.whatwg.org/#quotaexceedederror
class QuotaExceededError extends DOMException {
[_quota];
[_requested];

constructor(message = "", options = { __proto__: null }) {
super(message, "QuotaExceededError");

if (options !== null && typeof options === "object") {
if (ObjectHasOwn(options, "quota")) {
const quota = webidl.converters["unrestricted double"](
options.quota,
"Failed to construct 'QuotaExceededError'",
"'quota' member of QuotaExceededErrorOptions",
);
if (quota < 0) {
throw new RangeError(
"Failed to construct 'QuotaExceededError': quota must not be negative",
);
}
this[_quota] = quota;
} else {
this[_quota] = null;
}
if (ObjectHasOwn(options, "requested")) {
const requested = webidl.converters["unrestricted double"](
options.requested,
"Failed to construct 'QuotaExceededError'",
"'requested' member of QuotaExceededErrorOptions",
);
if (requested < 0) {
throw new RangeError(
"Failed to construct 'QuotaExceededError': requested must not be negative",
);
}
this[_requested] = requested;
} else {
this[_requested] = null;
}
} else {
this[_quota] = null;
this[_requested] = null;
}
}

get quota() {
webidl.assertBranded(this, QuotaExceededErrorPrototype);
return this[_quota];
}

get requested() {
webidl.assertBranded(this, QuotaExceededErrorPrototype);
return this[_requested];
}
}

webidl.configureInterface(QuotaExceededError);
const QuotaExceededErrorPrototype = QuotaExceededError.prototype;

export {
DOMException,
DOMExceptionPrototype,
QuotaExceededError,
QuotaExceededErrorPrototype,
};
1 change: 1 addition & 0 deletions ext/web/internal.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ declare module "ext:deno_web/00_infra.js" {

declare module "ext:deno_web/01_dom_exception.js" {
const DOMException: DOMException;
const QuotaExceededError: QuotaExceededError;
}

declare module "ext:deno_web/01_mimesniff.js" {
Expand Down
6 changes: 5 additions & 1 deletion runtime/js/98_global_scope_shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ import * as fetch from "ext:deno_fetch/26_fetch.js";
import * as eventSource from "ext:deno_fetch/27_eventsource.js";
import * as messagePort from "ext:deno_web/13_message_port.js";
import * as webidl from "ext:deno_webidl/00_webidl.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
import {
DOMException,
QuotaExceededError,
} from "ext:deno_web/01_dom_exception.js";
import * as abortSignal from "ext:deno_web/03_abort_signal.js";
import * as imageData from "ext:deno_web/16_image_data.js";
import process from "node:process";
Expand Down Expand Up @@ -66,6 +69,7 @@ const windowOrWorkerGlobalScope = {
CustomEvent: core.propNonEnumerable(event.CustomEvent),
DecompressionStream: core.propNonEnumerable(compression.DecompressionStream),
DOMException: core.propNonEnumerable(DOMException),
QuotaExceededError: core.propNonEnumerable(QuotaExceededError),
ErrorEvent: core.propNonEnumerable(event.ErrorEvent),
Event: core.propNonEnumerable(event.Event),
EventTarget: core.propNonEnumerable(event.EventTarget),
Expand Down
7 changes: 5 additions & 2 deletions runtime/js/99_main.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ import {
} from "ext:runtime/90_deno_ns.js";
import { errors } from "ext:runtime/01_errors.js";
import * as webidl from "ext:deno_webidl/00_webidl.js";
import { DOMException } from "ext:deno_web/01_dom_exception.js";
import {
DOMException,
QuotaExceededError,
} from "ext:deno_web/01_dom_exception.js";
import {
unstableForWindowOrWorkerGlobalScope,
windowOrWorkerGlobalScope,
Expand Down Expand Up @@ -351,7 +354,7 @@ core.registerErrorBuilder(
core.registerErrorBuilder(
"DOMExceptionQuotaExceededError",
function DOMExceptionQuotaExceededError(msg) {
return new DOMException(msg, "QuotaExceededError");
return new QuotaExceededError(msg);
},
);
core.registerErrorBuilder(
Expand Down
79 changes: 79 additions & 0 deletions tests/unit/dom_exception_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
assertEquals,
assertNotEquals,
assertStringIncludes,
assertThrows,
} from "./test_util.ts";

Deno.test(function customInspectFunction() {
Expand All @@ -30,3 +31,81 @@ Deno.test(function hasStackAccessor() {
assert(typeof desc.get === "function");
assert(typeof desc.set === "function");
});

// QuotaExceededError still maps to code 22 in the DOMException names table
Deno.test(function domExceptionQuotaExceededErrorCode() {
const e = new DOMException("test", "QuotaExceededError");
assertEquals(e.code, 22);
assertEquals(e.name, "QuotaExceededError");
});

// QuotaExceededError as a DOMException derived interface
Deno.test(function quotaExceededErrorBasic() {
const e = new QuotaExceededError("quota exceeded");
assert(e instanceof QuotaExceededError);
assert(e instanceof DOMException);
assert(e instanceof Error);
assertEquals(e.name, "QuotaExceededError");
assertEquals(e.message, "quota exceeded");
assertEquals(e.code, 22);
assertEquals(e.quota, null);
assertEquals(e.requested, null);
});

Deno.test(function quotaExceededErrorWithOptions() {
const e = new QuotaExceededError("too much", { quota: 100, requested: 200 });
assertEquals(e.name, "QuotaExceededError");
assertEquals(e.message, "too much");
assertEquals(e.code, 22);
assertEquals(e.quota, 100);
assertEquals(e.requested, 200);
});

Deno.test(function quotaExceededErrorDefaultMessage() {
const e = new QuotaExceededError();
assertEquals(e.message, "");
assertEquals(e.name, "QuotaExceededError");
assertEquals(e.code, 22);
assertEquals(e.quota, null);
assertEquals(e.requested, null);
});

Deno.test(function quotaExceededErrorPartialOptions() {
const e1 = new QuotaExceededError("msg", { quota: 50 });
assertEquals(e1.quota, 50);
assertEquals(e1.requested, null);

const e2 = new QuotaExceededError("msg", { requested: 75 });
assertEquals(e2.quota, null);
assertEquals(e2.requested, 75);
});

Deno.test(function quotaExceededErrorNegativeQuotaThrows() {
assertThrows(
() => new QuotaExceededError("msg", { quota: -1 }),
RangeError,
);
});

Deno.test(function quotaExceededErrorNegativeRequestedThrows() {
assertThrows(
() => new QuotaExceededError("msg", { requested: -1 }),
RangeError,
);
});

Deno.test(function quotaExceededErrorLegacyCodeConstant() {
assertEquals(DOMException.QUOTA_EXCEEDED_ERR, 22);
});

Deno.test(function quotaExceededErrorConstructorName() {
const e = new QuotaExceededError("test");
assertEquals(e.constructor, QuotaExceededError);
assertEquals(e.constructor.name, "QuotaExceededError");
});

Deno.test(function quotaExceededErrorHasStack() {
const e = new QuotaExceededError("test");
assert(typeof e.stack === "string");
assertStringIncludes(e.stack, "QuotaExceededError");
});
28 changes: 26 additions & 2 deletions tests/wpt/runner/expectations/WebCryptoAPI.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
{
"getRandomValues.any.html": true,
"getRandomValues.any.worker.html": true,
"getRandomValues.any.html": {
"expectedFailures": [
"Large length: Int8Array",
"Large length: Int16Array",
"Large length: Int32Array",
"Large length: BigInt64Array",
"Large length: Uint8Array",
"Large length: Uint8ClampedArray",
"Large length: Uint16Array",
"Large length: Uint32Array",
"Large length: BigUint64Array"
]
},
"getRandomValues.any.worker.html": {
"expectedFailures": [
"Large length: Int8Array",
"Large length: Int16Array",
"Large length: Int32Array",
"Large length: BigInt64Array",
"Large length: Uint8Array",
"Large length: Uint8ClampedArray",
"Large length: Uint16Array",
"Large length: Uint32Array",
"Large length: BigUint64Array"
]
},
"derive_bits_keys": {
"ecdh_bits.https.any.html": {
"expectedFailures": [
Expand Down
2 changes: 1 addition & 1 deletion tests/wpt/runner/expectations/fetch.json
Original file line number Diff line number Diff line change
Expand Up @@ -2589,11 +2589,11 @@
"<img id=\"dangling\" src=\"/images/green-1x1.png?img=&#10;&lt;b\">",
"<img id=\"dangling\" src=\"/images/green-1x1.png?img=&lt;&#10;b\">",
"\\n <img id=\"dangling\" src=\"/images/green-1x1.png?img=\\n &lt;\\n &#10;b\\n \">\\n ",
"Fetch: /images/gre\\ten-1x1.png?img=<",
"Fetch: /images/green-1x1.png?<\\n=block",
"Fetch: /images/gre\\nen-1x1.png?img=<",
"Fetch: /images/gre\\ren-1x1.png?img=<",
"Fetch: /images/green-1x1.png?<\\r=block",
"Fetch: /images/gre\\ten-1x1.png?img=<",
"Fetch: /images/green-1x1.png?<\\t=block"
]
},
Expand Down
4 changes: 2 additions & 2 deletions tests/wpt/runner/expectations/webstorage.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
"storage_key.window.html": true,
"storage_key_empty_string.window.html": true,
"storage_length.window.html": true,
"storage_local_setitem_quotaexceedederr.window.html": true,
"storage_local_setitem_quotaexceedederr.window.html": false,
"storage_removeitem.window.html": true,
"storage_session_setitem_quotaexceedederr.window.html": true,
"storage_session_setitem_quotaexceedederr.window.html": false,
"storage_set_value_enumerate.window.html": true,
"storage_setitem.window.html": {
"expectedFailures": [
Expand Down
1 change: 1 addition & 0 deletions tools/update_types_node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ function handleVarDecl(decl: VariableDeclaration) {
case "PerformanceEntry":
case "PerformanceMark":
case "PerformanceMeasure":
case "QuotaExceededError":
case "ReadableByteStreamController":
case "ReadableStream":
case "ReadableStreamBYOBReader":
Expand Down
Loading