summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhosra <phosra@tutanota.com>2022-07-20 01:12:18 -0700
committerGitHub <noreply@github.com>2022-07-20 10:12:18 +0200
commitb8e1250500ba07971b2f05847fdcbbfe548caa44 (patch)
tree8eaac48eb6f14e279120cdd81cf58c510bf640f8
parent2b1f145c3e51cf9885c073b78bd5882e80d258e3 (diff)
fix(ext/web): align DOMException better with spec (#15097)
-rw-r--r--cli/tests/unit/dom_exception_test.ts16
-rw-r--r--ext/web/01_dom_exception.js93
2 files changed, 70 insertions, 39 deletions
diff --git a/cli/tests/unit/dom_exception_test.ts b/cli/tests/unit/dom_exception_test.ts
index 01f7b5db5..b6b6a4440 100644
--- a/cli/tests/unit/dom_exception_test.ts
+++ b/cli/tests/unit/dom_exception_test.ts
@@ -1,4 +1,8 @@
-import { assertEquals, assertStringIncludes } from "./test_util.ts";
+import {
+ assertEquals,
+ assertNotEquals,
+ assertStringIncludes,
+} from "./test_util.ts";
Deno.test(function customInspectFunction() {
const blob = new DOMException("test");
@@ -8,3 +12,13 @@ Deno.test(function customInspectFunction() {
);
assertStringIncludes(Deno.inspect(DOMException.prototype), "DOMException");
});
+
+Deno.test(function nameToCodeMappingPrototypeAccess() {
+ const newCode = 100;
+ const objectPrototype = Object.prototype as unknown as {
+ pollution: number;
+ };
+ objectPrototype.pollution = newCode;
+ assertNotEquals(newCode, new DOMException("test", "pollution").code);
+ Reflect.deleteProperty(objectPrototype, "pollution");
+});
diff --git a/ext/web/01_dom_exception.js b/ext/web/01_dom_exception.js
index a3beb3064..d04006204 100644
--- a/ext/web/01_dom_exception.js
+++ b/ext/web/01_dom_exception.js
@@ -15,16 +15,22 @@
Error,
ErrorPrototype,
ObjectDefineProperty,
+ ObjectCreate,
ObjectEntries,
ObjectPrototypeIsPrototypeOf,
ObjectSetPrototypeOf,
+ Symbol,
SymbolFor,
} = window.__bootstrap.primordials;
const webidl = window.__bootstrap.webidl;
const consoleInternal = window.__bootstrap.console;
+ const _name = Symbol("name");
+ const _message = Symbol("message");
+ const _code = Symbol("code");
+
// Defined in WebIDL 4.3.
- // https://heycam.github.io/webidl/#idl-DOMException
+ // https://webidl.spec.whatwg.org/#idl-DOMException
const INDEX_SIZE_ERR = 1;
const DOMSTRING_SIZE_ERR = 2;
const HIERARCHY_REQUEST_ERR = 3;
@@ -52,52 +58,60 @@
const DATA_CLONE_ERR = 25;
// Defined in WebIDL 2.8.1.
- // https://heycam.github.io/webidl/#dfn-error-names-table
+ // https://webidl.spec.whatwg.org/#dfn-error-names-table
/** @type {Record<string, number>} */
- const nameToCodeMapping = {
- IndexSizeError: INDEX_SIZE_ERR,
- HierarchyRequestError: HIERARCHY_REQUEST_ERR,
- WrongDocumentError: WRONG_DOCUMENT_ERR,
- InvalidCharacterError: INVALID_CHARACTER_ERR,
- NoModificationAllowedError: NO_MODIFICATION_ALLOWED_ERR,
- NotFoundError: NOT_FOUND_ERR,
- NotSupportedError: NOT_SUPPORTED_ERR,
- InUseAttributeError: INUSE_ATTRIBUTE_ERR,
- InvalidStateError: INVALID_STATE_ERR,
- SyntaxError: SYNTAX_ERR,
- InvalidModificationError: INVALID_MODIFICATION_ERR,
- NamespaceError: NAMESPACE_ERR,
- InvalidAccessError: INVALID_ACCESS_ERR,
- TypeMismatchError: TYPE_MISMATCH_ERR,
- SecurityError: SECURITY_ERR,
- NetworkError: NETWORK_ERR,
- AbortError: ABORT_ERR,
- URLMismatchError: URL_MISMATCH_ERR,
- QuotaExceededError: QUOTA_EXCEEDED_ERR,
- TimeoutError: TIMEOUT_ERR,
- InvalidNodeTypeError: INVALID_NODE_TYPE_ERR,
- DataCloneError: DATA_CLONE_ERR,
- };
+ // 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://heycam.github.io/webidl/#idl-DOMException
+ // https://webidl.spec.whatwg.org/#idl-DOMException
class DOMException {
- #message = "";
- #name = "";
- #code = 0;
+ [_message];
+ [_name];
+ [_code];
+ // https://webidl.spec.whatwg.org/#dom-domexception-domexception
constructor(message = "", name = "Error") {
- this.#message = webidl.converters.DOMString(message, {
+ message = webidl.converters.DOMString(message, {
prefix: "Failed to construct 'DOMException'",
context: "Argument 1",
});
- this.#name = webidl.converters.DOMString(name, {
+ name = webidl.converters.DOMString(name, {
prefix: "Failed to construct 'DOMException'",
context: "Argument 2",
});
- this.#code = nameToCodeMapping[this.#name] ?? 0;
+ const code = nameToCodeMapping[name] ?? 0;
+
+ this[_message] = message;
+ this[_name] = name;
+ this[_code] = code;
+ this[webidl.brand] = webidl.brand;
- const error = new Error(this.#message);
+ const error = new Error(message);
error.name = "DOMException";
ObjectDefineProperty(this, "stack", {
value: error.stack,
@@ -115,20 +129,23 @@
}
get message() {
- return this.#message;
+ webidl.assertBranded(this, DOMExceptionPrototype);
+ return this[_message];
}
get name() {
- return this.#name;
+ webidl.assertBranded(this, DOMExceptionPrototype);
+ return this[_name];
}
get code() {
- return this.#code;
+ webidl.assertBranded(this, DOMExceptionPrototype);
+ return this[_code];
}
[SymbolFor("Deno.customInspect")](inspect) {
if (ObjectPrototypeIsPrototypeOf(DOMExceptionPrototype, this)) {
- return `DOMException: ${this.#message}`;
+ return `DOMException: ${this[_message]}`;
} else {
return inspect(consoleInternal.createFilteredInspectProxy({
object: this,