2024-01-01 14:58:21 -05:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2021-02-13 09:58:12 -05:00
|
|
|
|
|
|
|
// @ts-check
|
2021-07-03 15:32:28 -04:00
|
|
|
/// <reference path="../../core/internal.d.ts" />
|
2021-02-13 09:58:12 -05:00
|
|
|
/// <reference path="../../core/lib.deno_core.d.ts" />
|
chore: split web op crate (#9635)
This commit starts splitting out the deno_web op crate into multiple
smaller crates. This commit splits out WebIDL and URL API, but in the
future I want to split out each spec into its own crate. That means we
will have (in rough order of loading): `webidl`, `dom`, `streams`,
`console`, `encoding`, `url`, `file`, `fetch`, `websocket`, and
`webgpu` crates.
2021-03-12 10:17:18 -05:00
|
|
|
/// <reference path="../webidl/internal.d.ts" />
|
2021-02-13 09:58:12 -05:00
|
|
|
/// <reference path="../web/internal.d.ts" />
|
|
|
|
/// <reference path="../web/lib.deno_web.d.ts" />
|
|
|
|
|
2023-12-07 08:21:01 -05:00
|
|
|
import { primordials } from "ext:core/mod.js";
|
2023-02-07 14:22:46 -05:00
|
|
|
const {
|
|
|
|
ArrayPrototypeSlice,
|
|
|
|
Error,
|
|
|
|
ErrorPrototype,
|
|
|
|
ObjectDefineProperty,
|
|
|
|
ObjectCreate,
|
|
|
|
ObjectEntries,
|
|
|
|
ObjectPrototypeIsPrototypeOf,
|
|
|
|
ObjectSetPrototypeOf,
|
|
|
|
Symbol,
|
|
|
|
SymbolFor,
|
|
|
|
} = primordials;
|
2024-01-10 17:37:25 -05:00
|
|
|
|
2023-03-08 06:44:54 -05:00
|
|
|
import * as webidl from "ext:deno_webidl/00_webidl.js";
|
2023-04-30 05:11:37 -04:00
|
|
|
import { createFilteredInspectProxy } from "ext:deno_console/01_console.js";
|
2023-02-07 14:22:46 -05:00
|
|
|
|
|
|
|
const _name = Symbol("name");
|
|
|
|
const _message = Symbol("message");
|
|
|
|
const _code = Symbol("code");
|
perf(ext/web): optimize DOMException (#20715)
This PR optimizes `DOMException` constructor increasing performance of
all Web APIs that throw a `DOMException` (ie: `AbortSignal`)
**main**
```
cpu: 13th Gen Intel(R) Core(TM) i9-13900H
runtime: deno 1.37.1 (x86_64-unknown-linux-gnu)
new DOMException() 9.66 µs/iter 103,476.8 (8.47 µs … 942.71 µs) 9.62 µs 11.29 µs 14.04 µs
abort writeTextFileSync 16.45 µs/iter 60,775.5 (13.65 µs … 1.33 ms) 16.39 µs 20.59 µs 24.12 µs
abort readFile 16.25 µs/iter 61,542.2 (15.12 µs … 621.14 µs) 16.18 µs 19.59 µs 22.33 µs
```
**this PR**
```
cpu: 13th Gen Intel(R) Core(TM) i9-13900H
runtime: deno 1.37.1 (x86_64-unknown-linux-gnu)
benchmark time (avg) iter/s (min … max) p75 p99 p995
----------------------------------------------------------------------------- -----------------------------
new DOMException() 2.37 µs/iter 421,657.0 (2.33 µs … 2.58 µs) 2.37 µs 2.58 µs 2.58 µs
abort writeTextFileSync 7.1 µs/iter 140,760.1 (6.94 µs … 7.68 µs) 7.13 µs 7.68 µs 7.68 µs
abort readFile 5.48 µs/iter 182,648.2 (5.3 µs … 5.69 µs) 5.56 µs 5.69 µs 5.69 µ
```
```js
Deno.bench("new DOMException()", () => {
new DOMException();
});
Deno.bench("abort writeTextFileSync", () => {
const ac = new AbortController();
ac.abort();
try {
Deno.writeTextFileSync("/tmp/out", "x", { signal: ac.signal });
} catch {}
});
Deno.bench("abort readFile", async () => {
const ac = new AbortController();
ac.abort();
try {
await Deno.readFile("/tmp/out", { signal: ac.signal });
} catch {}
});
```
2023-10-01 20:18:34 -04:00
|
|
|
const _error = Symbol("error");
|
2023-02-07 14:22:46 -05:00
|
|
|
|
|
|
|
// Defined in WebIDL 4.3.
|
|
|
|
// https://webidl.spec.whatwg.org/#idl-DOMException
|
|
|
|
const INDEX_SIZE_ERR = 1;
|
|
|
|
const DOMSTRING_SIZE_ERR = 2;
|
|
|
|
const HIERARCHY_REQUEST_ERR = 3;
|
|
|
|
const WRONG_DOCUMENT_ERR = 4;
|
|
|
|
const INVALID_CHARACTER_ERR = 5;
|
|
|
|
const NO_DATA_ALLOWED_ERR = 6;
|
|
|
|
const NO_MODIFICATION_ALLOWED_ERR = 7;
|
|
|
|
const NOT_FOUND_ERR = 8;
|
|
|
|
const NOT_SUPPORTED_ERR = 9;
|
|
|
|
const INUSE_ATTRIBUTE_ERR = 10;
|
|
|
|
const INVALID_STATE_ERR = 11;
|
|
|
|
const SYNTAX_ERR = 12;
|
|
|
|
const INVALID_MODIFICATION_ERR = 13;
|
|
|
|
const NAMESPACE_ERR = 14;
|
|
|
|
const INVALID_ACCESS_ERR = 15;
|
|
|
|
const VALIDATION_ERR = 16;
|
|
|
|
const TYPE_MISMATCH_ERR = 17;
|
|
|
|
const SECURITY_ERR = 18;
|
|
|
|
const NETWORK_ERR = 19;
|
|
|
|
const ABORT_ERR = 20;
|
|
|
|
const URL_MISMATCH_ERR = 21;
|
|
|
|
const QUOTA_EXCEEDED_ERR = 22;
|
|
|
|
const TIMEOUT_ERR = 23;
|
|
|
|
const INVALID_NODE_TYPE_ERR = 24;
|
|
|
|
const DATA_CLONE_ERR = 25;
|
|
|
|
|
|
|
|
// Defined in WebIDL 2.8.1.
|
|
|
|
// https://webidl.spec.whatwg.org/#dfn-error-names-table
|
|
|
|
/** @type {Record<string, number>} */
|
|
|
|
// the prototype should be null, to prevent user code from looking
|
|
|
|
// up Object.prototype properties, such as "toString"
|
|
|
|
const nameToCodeMapping = ObjectCreate(null, {
|
|
|
|
IndexSizeError: { value: INDEX_SIZE_ERR },
|
|
|
|
HierarchyRequestError: { value: HIERARCHY_REQUEST_ERR },
|
|
|
|
WrongDocumentError: { value: WRONG_DOCUMENT_ERR },
|
|
|
|
InvalidCharacterError: { value: INVALID_CHARACTER_ERR },
|
|
|
|
NoModificationAllowedError: { value: NO_MODIFICATION_ALLOWED_ERR },
|
|
|
|
NotFoundError: { value: NOT_FOUND_ERR },
|
|
|
|
NotSupportedError: { value: NOT_SUPPORTED_ERR },
|
|
|
|
InUseAttributeError: { value: INUSE_ATTRIBUTE_ERR },
|
|
|
|
InvalidStateError: { value: INVALID_STATE_ERR },
|
|
|
|
SyntaxError: { value: SYNTAX_ERR },
|
|
|
|
InvalidModificationError: { value: INVALID_MODIFICATION_ERR },
|
|
|
|
NamespaceError: { value: NAMESPACE_ERR },
|
|
|
|
InvalidAccessError: { value: INVALID_ACCESS_ERR },
|
|
|
|
TypeMismatchError: { value: TYPE_MISMATCH_ERR },
|
|
|
|
SecurityError: { value: SECURITY_ERR },
|
|
|
|
NetworkError: { value: NETWORK_ERR },
|
|
|
|
AbortError: { value: ABORT_ERR },
|
|
|
|
URLMismatchError: { value: URL_MISMATCH_ERR },
|
|
|
|
QuotaExceededError: { value: QUOTA_EXCEEDED_ERR },
|
|
|
|
TimeoutError: { value: TIMEOUT_ERR },
|
|
|
|
InvalidNodeTypeError: { value: INVALID_NODE_TYPE_ERR },
|
|
|
|
DataCloneError: { value: DATA_CLONE_ERR },
|
|
|
|
});
|
|
|
|
|
|
|
|
// Defined in WebIDL 4.3.
|
|
|
|
// https://webidl.spec.whatwg.org/#idl-DOMException
|
|
|
|
class DOMException {
|
|
|
|
[_message];
|
|
|
|
[_name];
|
|
|
|
[_code];
|
|
|
|
|
|
|
|
// https://webidl.spec.whatwg.org/#dom-domexception-domexception
|
|
|
|
constructor(message = "", name = "Error") {
|
2023-05-01 06:47:13 -04:00
|
|
|
message = webidl.converters.DOMString(
|
|
|
|
message,
|
|
|
|
"Failed to construct 'DOMException'",
|
|
|
|
"Argument 1",
|
|
|
|
);
|
|
|
|
name = webidl.converters.DOMString(
|
|
|
|
name,
|
|
|
|
"Failed to construct 'DOMException'",
|
|
|
|
"Argument 2",
|
|
|
|
);
|
2023-02-07 14:22:46 -05:00
|
|
|
const code = nameToCodeMapping[name] ?? 0;
|
|
|
|
|
|
|
|
this[_message] = message;
|
|
|
|
this[_name] = name;
|
|
|
|
this[_code] = code;
|
|
|
|
this[webidl.brand] = webidl.brand;
|
|
|
|
|
perf(ext/web): optimize DOMException (#20715)
This PR optimizes `DOMException` constructor increasing performance of
all Web APIs that throw a `DOMException` (ie: `AbortSignal`)
**main**
```
cpu: 13th Gen Intel(R) Core(TM) i9-13900H
runtime: deno 1.37.1 (x86_64-unknown-linux-gnu)
new DOMException() 9.66 µs/iter 103,476.8 (8.47 µs … 942.71 µs) 9.62 µs 11.29 µs 14.04 µs
abort writeTextFileSync 16.45 µs/iter 60,775.5 (13.65 µs … 1.33 ms) 16.39 µs 20.59 µs 24.12 µs
abort readFile 16.25 µs/iter 61,542.2 (15.12 µs … 621.14 µs) 16.18 µs 19.59 µs 22.33 µs
```
**this PR**
```
cpu: 13th Gen Intel(R) Core(TM) i9-13900H
runtime: deno 1.37.1 (x86_64-unknown-linux-gnu)
benchmark time (avg) iter/s (min … max) p75 p99 p995
----------------------------------------------------------------------------- -----------------------------
new DOMException() 2.37 µs/iter 421,657.0 (2.33 µs … 2.58 µs) 2.37 µs 2.58 µs 2.58 µs
abort writeTextFileSync 7.1 µs/iter 140,760.1 (6.94 µs … 7.68 µs) 7.13 µs 7.68 µs 7.68 µs
abort readFile 5.48 µs/iter 182,648.2 (5.3 µs … 5.69 µs) 5.56 µs 5.69 µs 5.69 µ
```
```js
Deno.bench("new DOMException()", () => {
new DOMException();
});
Deno.bench("abort writeTextFileSync", () => {
const ac = new AbortController();
ac.abort();
try {
Deno.writeTextFileSync("/tmp/out", "x", { signal: ac.signal });
} catch {}
});
Deno.bench("abort readFile", async () => {
const ac = new AbortController();
ac.abort();
try {
await Deno.readFile("/tmp/out", { signal: ac.signal });
} catch {}
});
```
2023-10-01 20:18:34 -04:00
|
|
|
this[_error] = new Error(message);
|
|
|
|
this[_error].name = "DOMException";
|
2023-02-07 14:22:46 -05:00
|
|
|
}
|
2020-04-11 11:42:02 -04:00
|
|
|
|
2023-02-07 14:22:46 -05:00
|
|
|
get message() {
|
|
|
|
webidl.assertBranded(this, DOMExceptionPrototype);
|
|
|
|
return this[_message];
|
|
|
|
}
|
2021-01-14 08:08:49 -05:00
|
|
|
|
2023-02-07 14:22:46 -05:00
|
|
|
get name() {
|
|
|
|
webidl.assertBranded(this, DOMExceptionPrototype);
|
|
|
|
return this[_name];
|
2021-01-14 08:08:49 -05:00
|
|
|
}
|
|
|
|
|
2023-02-07 14:22:46 -05:00
|
|
|
get code() {
|
|
|
|
webidl.assertBranded(this, DOMExceptionPrototype);
|
|
|
|
return this[_code];
|
2020-04-11 11:42:02 -04:00
|
|
|
}
|
2021-01-09 01:27:46 -05:00
|
|
|
|
2023-11-19 03:13:38 -05:00
|
|
|
[SymbolFor("Deno.privateCustomInspect")](inspect, inspectOptions) {
|
2023-02-07 14:22:46 -05:00
|
|
|
if (ObjectPrototypeIsPrototypeOf(DOMExceptionPrototype, this)) {
|
2023-11-19 03:13:38 -05:00
|
|
|
return this[_error].stack;
|
2023-02-07 14:22:46 -05:00
|
|
|
} else {
|
2023-11-19 03:13:38 -05:00
|
|
|
return inspect(
|
|
|
|
createFilteredInspectProxy({
|
|
|
|
object: this,
|
|
|
|
evaluate: false,
|
|
|
|
keys: [
|
|
|
|
"message",
|
|
|
|
"name",
|
|
|
|
"code",
|
|
|
|
],
|
|
|
|
}),
|
|
|
|
inspectOptions,
|
|
|
|
);
|
2023-02-07 14:22:46 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
perf(ext/web): optimize DOMException (#20715)
This PR optimizes `DOMException` constructor increasing performance of
all Web APIs that throw a `DOMException` (ie: `AbortSignal`)
**main**
```
cpu: 13th Gen Intel(R) Core(TM) i9-13900H
runtime: deno 1.37.1 (x86_64-unknown-linux-gnu)
new DOMException() 9.66 µs/iter 103,476.8 (8.47 µs … 942.71 µs) 9.62 µs 11.29 µs 14.04 µs
abort writeTextFileSync 16.45 µs/iter 60,775.5 (13.65 µs … 1.33 ms) 16.39 µs 20.59 µs 24.12 µs
abort readFile 16.25 µs/iter 61,542.2 (15.12 µs … 621.14 µs) 16.18 µs 19.59 µs 22.33 µs
```
**this PR**
```
cpu: 13th Gen Intel(R) Core(TM) i9-13900H
runtime: deno 1.37.1 (x86_64-unknown-linux-gnu)
benchmark time (avg) iter/s (min … max) p75 p99 p995
----------------------------------------------------------------------------- -----------------------------
new DOMException() 2.37 µs/iter 421,657.0 (2.33 µs … 2.58 µs) 2.37 µs 2.58 µs 2.58 µs
abort writeTextFileSync 7.1 µs/iter 140,760.1 (6.94 µs … 7.68 µs) 7.13 µs 7.68 µs 7.68 µs
abort readFile 5.48 µs/iter 182,648.2 (5.3 µs … 5.69 µs) 5.56 µs 5.69 µs 5.69 µ
```
```js
Deno.bench("new DOMException()", () => {
new DOMException();
});
Deno.bench("abort writeTextFileSync", () => {
const ac = new AbortController();
ac.abort();
try {
Deno.writeTextFileSync("/tmp/out", "x", { signal: ac.signal });
} catch {}
});
Deno.bench("abort readFile", async () => {
const ac = new AbortController();
ac.abort();
try {
await Deno.readFile("/tmp/out", { signal: ac.signal });
} catch {}
});
```
2023-10-01 20:18:34 -04:00
|
|
|
ObjectDefineProperty(DOMException.prototype, "stack", {
|
|
|
|
get() {
|
|
|
|
return this[_error].stack;
|
|
|
|
},
|
|
|
|
set(value) {
|
|
|
|
this[_error].stack = value;
|
|
|
|
},
|
|
|
|
configurable: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
// `DOMException` isn't a native error, so `Error.prepareStackTrace()` is
|
|
|
|
// not called when accessing `.stack`, meaning our structured stack trace
|
|
|
|
// hack doesn't apply. This patches it in.
|
|
|
|
ObjectDefineProperty(DOMException.prototype, "__callSiteEvals", {
|
|
|
|
get() {
|
2024-05-07 17:02:29 -04:00
|
|
|
// Call the stack getter so `__callSiteEvals` get populated.
|
|
|
|
this[_error].stack;
|
|
|
|
// To be extra sure, use an empty array if `__callSiteEvals` is still not there,
|
|
|
|
// eg. if the user overrides `Error.prepareStackTrace`.
|
|
|
|
const callSiteEvals = this[_error].__callSiteEvals ?? [];
|
|
|
|
return ArrayPrototypeSlice(callSiteEvals, 1);
|
perf(ext/web): optimize DOMException (#20715)
This PR optimizes `DOMException` constructor increasing performance of
all Web APIs that throw a `DOMException` (ie: `AbortSignal`)
**main**
```
cpu: 13th Gen Intel(R) Core(TM) i9-13900H
runtime: deno 1.37.1 (x86_64-unknown-linux-gnu)
new DOMException() 9.66 µs/iter 103,476.8 (8.47 µs … 942.71 µs) 9.62 µs 11.29 µs 14.04 µs
abort writeTextFileSync 16.45 µs/iter 60,775.5 (13.65 µs … 1.33 ms) 16.39 µs 20.59 µs 24.12 µs
abort readFile 16.25 µs/iter 61,542.2 (15.12 µs … 621.14 µs) 16.18 µs 19.59 µs 22.33 µs
```
**this PR**
```
cpu: 13th Gen Intel(R) Core(TM) i9-13900H
runtime: deno 1.37.1 (x86_64-unknown-linux-gnu)
benchmark time (avg) iter/s (min … max) p75 p99 p995
----------------------------------------------------------------------------- -----------------------------
new DOMException() 2.37 µs/iter 421,657.0 (2.33 µs … 2.58 µs) 2.37 µs 2.58 µs 2.58 µs
abort writeTextFileSync 7.1 µs/iter 140,760.1 (6.94 µs … 7.68 µs) 7.13 µs 7.68 µs 7.68 µs
abort readFile 5.48 µs/iter 182,648.2 (5.3 µs … 5.69 µs) 5.56 µs 5.69 µs 5.69 µ
```
```js
Deno.bench("new DOMException()", () => {
new DOMException();
});
Deno.bench("abort writeTextFileSync", () => {
const ac = new AbortController();
ac.abort();
try {
Deno.writeTextFileSync("/tmp/out", "x", { signal: ac.signal });
} catch {}
});
Deno.bench("abort readFile", async () => {
const ac = new AbortController();
ac.abort();
try {
await Deno.readFile("/tmp/out", { signal: ac.signal });
} catch {}
});
```
2023-10-01 20:18:34 -04:00
|
|
|
},
|
|
|
|
configurable: true,
|
|
|
|
});
|
|
|
|
|
2023-02-07 14:22:46 -05:00
|
|
|
ObjectSetPrototypeOf(DOMException.prototype, ErrorPrototype);
|
|
|
|
|
2023-10-09 23:01:01 -04:00
|
|
|
webidl.configureInterface(DOMException);
|
2023-02-07 14:22:46 -05:00
|
|
|
const DOMExceptionPrototype = DOMException.prototype;
|
|
|
|
|
|
|
|
const entries = ObjectEntries({
|
|
|
|
INDEX_SIZE_ERR,
|
|
|
|
DOMSTRING_SIZE_ERR,
|
|
|
|
HIERARCHY_REQUEST_ERR,
|
|
|
|
WRONG_DOCUMENT_ERR,
|
|
|
|
INVALID_CHARACTER_ERR,
|
|
|
|
NO_DATA_ALLOWED_ERR,
|
|
|
|
NO_MODIFICATION_ALLOWED_ERR,
|
|
|
|
NOT_FOUND_ERR,
|
|
|
|
NOT_SUPPORTED_ERR,
|
|
|
|
INUSE_ATTRIBUTE_ERR,
|
|
|
|
INVALID_STATE_ERR,
|
|
|
|
SYNTAX_ERR,
|
|
|
|
INVALID_MODIFICATION_ERR,
|
|
|
|
NAMESPACE_ERR,
|
|
|
|
INVALID_ACCESS_ERR,
|
|
|
|
VALIDATION_ERR,
|
|
|
|
TYPE_MISMATCH_ERR,
|
|
|
|
SECURITY_ERR,
|
|
|
|
NETWORK_ERR,
|
|
|
|
ABORT_ERR,
|
|
|
|
URL_MISMATCH_ERR,
|
|
|
|
QUOTA_EXCEEDED_ERR,
|
|
|
|
TIMEOUT_ERR,
|
|
|
|
INVALID_NODE_TYPE_ERR,
|
|
|
|
DATA_CLONE_ERR,
|
|
|
|
});
|
|
|
|
for (let i = 0; i < entries.length; ++i) {
|
|
|
|
const { 0: key, 1: value } = entries[i];
|
|
|
|
const desc = { value, enumerable: true };
|
|
|
|
ObjectDefineProperty(DOMException, key, desc);
|
|
|
|
ObjectDefineProperty(DOMException.prototype, key, desc);
|
|
|
|
}
|
|
|
|
|
2024-01-03 23:12:38 -05:00
|
|
|
export { DOMException, DOMExceptionPrototype };
|