fix: align DOMException API to the spec and add web platform testing of it. (#9106)

* fix: align DOMException API to the spec

* test: fix test case 070_location

* test(DOMException): disable "does not inherit from Error: class-side"
test of WPT

* test: remove test cases in deno codebase

* docs: add note about skipped test
This commit is contained in:
Yoshiya Hinosawa 2021-01-14 22:08:49 +09:00 committed by GitHub
parent 78c27e0923
commit c75f92c4e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 125 additions and 47 deletions

View file

@ -6,5 +6,5 @@ console.log(location);
try { try {
location.hostname = "bar"; location.hostname = "bar";
} catch (error) { } catch (error) {
console.log(error); console.log(error.toString());
} }

View file

@ -1,18 +0,0 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
import { assert, assertEquals, unitTest } from "./test_util.ts";
unitTest(function testDomError() {
const de = new DOMException("foo", "bar");
assert(de);
assertEquals(de.message, "foo");
assertEquals(de.name, "bar");
assertEquals(de.code, 0);
});
unitTest(function testKnownDomException() {
const de = new DOMException("foo", "SyntaxError");
assert(de);
assertEquals(de.message, "foo");
assertEquals(de.name, "SyntaxError");
assertEquals(de.code, 12);
});

View file

@ -17,7 +17,6 @@ import "./custom_event_test.ts";
import "./dir_test.ts"; import "./dir_test.ts";
import "./dispatch_minimal_test.ts"; import "./dispatch_minimal_test.ts";
import "./dispatch_json_test.ts"; import "./dispatch_json_test.ts";
import "./dom_exception_test.ts";
import "./error_stack_test.ts"; import "./error_stack_test.ts";
import "./event_test.ts"; import "./event_test.ts";
import "./event_target_test.ts"; import "./event_target_test.ts";

View file

@ -182,5 +182,21 @@
], ],
"WebCryptoApi": [ "WebCryptoApi": [
"getRandomValues" "getRandomValues"
],
"WebIDL": [
"ecmascript-binding/es-exceptions/DOMException-constants",
"ecmascript-binding/es-exceptions/DOMException-constructor-and-prototype",
"ecmascript-binding/es-exceptions/DOMException-constructor-behavior",
{
"name": "ecmascript-binding/es-exceptions/DOMException-custom-bindings",
"expectFail": [
// TODO(kt3k): Enable this test.
// We can pass this test by using Object.setPrototypeOf(...) instead of
// class...extends, but that causes a problem in printing of uncaught
// DOMException. We might need to modify how to print uncaught error in
// `//core/error.rs`.
"does not inherit from Error: class-side"
]
}
] ]
} }

View file

@ -1,42 +1,80 @@
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
((window) => { ((window) => {
const nameToCodeMapping = Object.create( const { defineProperty } = Object;
null, // Defined in WebIDL 4.3.
{ // https://heycam.github.io/webidl/#idl-DOMException
IndexSizeError: { value: 1 }, const INDEX_SIZE_ERR = 1;
HierarchyRequestError: { value: 3 }, const DOMSTRING_SIZE_ERR = 2;
WrongDocumentError: { value: 4 }, const HIERARCHY_REQUEST_ERR = 3;
InvalidCharacterError: { value: 5 }, const WRONG_DOCUMENT_ERR = 4;
NoModificationAllowedError: { value: 7 }, const INVALID_CHARACTER_ERR = 5;
NotFoundError: { value: 8 }, const NO_DATA_ALLOWED_ERR = 6;
NotSupportedError: { value: 9 }, const NO_MODIFICATION_ALLOWED_ERR = 7;
InvalidStateError: { value: 11 }, const NOT_FOUND_ERR = 8;
SyntaxError: { value: 12 }, const NOT_SUPPORTED_ERR = 9;
InvalidModificationError: { value: 13 }, const INUSE_ATTRIBUTE_ERR = 10;
NamespaceError: { value: 14 }, const INVALID_STATE_ERR = 11;
InvalidAccessError: { value: 15 }, const SYNTAX_ERR = 12;
TypeMismatchError: { value: 17 }, const INVALID_MODIFICATION_ERR = 13;
SecurityError: { value: 18 }, const NAMESPACE_ERR = 14;
NetworkError: { value: 19 }, const INVALID_ACCESS_ERR = 15;
AbortError: { value: 20 }, const VALIDATION_ERR = 16;
URLMismatchError: { value: 21 }, const TYPE_MISMATCH_ERR = 17;
QuotaExceededError: { value: 22 }, const SECURITY_ERR = 18;
TimeoutError: { value: 23 }, const NETWORK_ERR = 19;
InvalidNodeTypeError: { value: 24 }, const ABORT_ERR = 20;
DataCloneError: { value: 25 }, 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://heycam.github.io/webidl/#dfn-error-names-table
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,
};
// Defined in WebIDL 4.3.
// https://heycam.github.io/webidl/#idl-DOMException
class DOMException extends Error { class DOMException extends Error {
#message = "";
#name = ""; #name = "";
#code = 0; #code = 0;
constructor(message = "", name = "Error") { constructor(message = "", name = "Error") {
super(message); super();
this.#message = String(message);
this.#name = name; this.#name = name;
this.#code = nameToCodeMapping[name] ?? 0; this.#code = nameToCodeMapping[name] ?? 0;
} }
get message() {
return this.#message;
}
get name() { get name() {
return this.#name; return this.#name;
} }
@ -44,7 +82,50 @@
get code() { get code() {
return this.#code; return this.#code;
} }
get [Symbol.toStringTag]() {
return "DOMException";
}
}
defineProperty(DOMException.prototype, "message", { enumerable: true });
defineProperty(DOMException.prototype, "name", { enumerable: true });
defineProperty(DOMException.prototype, "code", { enumerable: true });
for (
const [key, value] of Object.entries({
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,
})
) {
const desc = { value, enumerable: true };
defineProperty(DOMException, key, desc);
defineProperty(DOMException.prototype, key, desc);
} }
window.DOMException = DOMException; window.DOMException = DOMException;
defineProperty(window, "DOMException", { enumerable: false });
})(this); })(this);