Skip to content

Commit

Permalink
lib: modify DOMException to pass WPT
Browse files Browse the repository at this point in the history
PR-URL: #41517
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
XadillaX authored and BethGriggs committed Jan 24, 2022
1 parent 9c73bd5 commit 8a99eed
Show file tree
Hide file tree
Showing 10 changed files with 468 additions and 4 deletions.
24 changes: 21 additions & 3 deletions lib/internal/per_context/domexception.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
'use strict';

const {
Error,
ErrorCaptureStackTrace,
ErrorPrototype,
ObjectDefineProperties,
ObjectDefineProperty,
ObjectSetPrototypeOf,
SafeWeakMap,
SafeMap,
SafeSet,
SymbolToStringTag,
TypeError,
} = primordials;
Expand Down Expand Up @@ -33,6 +36,7 @@ function throwInvalidThisError(Base, type) {
throw err;
}

let disusedNamesSet;
let internalsMap;
let nameToCodeMap;
let isInitialized = false;
Expand All @@ -49,13 +53,21 @@ function ensureInitialized() {
forEachCode((name, codeName, value) => {
nameToCodeMap.set(name, value);
});

// These were removed from the error names table.
// See https://github.com/heycam/webidl/pull/946.
disusedNamesSet = new SafeSet()
.add('DOMStringSizeError')
.add('NoDataAllowedError')
.add('ValidationError');

isInitialized = true;
}

class DOMException extends Error {
class DOMException {
constructor(message = '', name = 'Error') {
ensureInitialized();
super();
ErrorCaptureStackTrace(this);
internalsMap.set(this, {
message: `${message}`,
name: `${name}`
Expand Down Expand Up @@ -86,11 +98,17 @@ class DOMException extends Error {
if (internals === undefined) {
throwInvalidThisError(TypeError, 'DOMException');
}

if (disusedNamesSet.has(internals.name)) {
return 0;
}

const code = nameToCodeMap.get(internals.name);
return code === undefined ? 0 : code;
}
}

ObjectSetPrototypeOf(DOMException.prototype, ErrorPrototype);
ObjectDefineProperties(DOMException.prototype, {
[SymbolToStringTag]: { configurable: true, value: 'DOMException' },
name: { enumerable: true, configurable: true },
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/wpt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Last update:
- url: https://github.com/web-platform-tests/wpt/tree/77d54aa9e0/url
- user-timing: https://github.com/web-platform-tests/wpt/tree/df24fb604e/user-timing
- WebCryptoAPI: https://github.com/web-platform-tests/wpt/tree/cdd0f03df4/WebCryptoAPI
- webidl/ecmascript-binding/es-exceptions: https://github.com/web-platform-tests/wpt/tree/a370aad338/webidl/ecmascript-binding/es-exceptions

[Web Platform Tests]: https://github.com/web-platform-tests/wpt
[`git node wpt`]: https://github.com/nodejs/node-core-utils/blob/main/docs/git-node.md#git-node-wpt
6 changes: 5 additions & 1 deletion test/fixtures/wpt/versions.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,9 @@
"WebCryptoAPI": {
"commit": "cdd0f03df41b222aed098fbbb11c6a3cc500a86b",
"path": "WebCryptoAPI"
},
"webidl/ecmascript-binding/es-exceptions": {
"commit": "a370aad338d6ed743abb4d2c6ae84a7f1058558c",
"path": "webidl/ecmascript-binding/es-exceptions"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
'use strict';

test(function() {
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=27732
var constants = [
"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"
]
var objects = [
[DOMException, "DOMException constructor object"],
[DOMException.prototype, "DOMException prototype object"]
]
constants.forEach(function(name, i) {
objects.forEach(function(o) {
var object = o[0], description = o[1];
test(function() {
assert_equals(object[name], i + 1, name)
assert_own_property(object, name)
var pd = Object.getOwnPropertyDescriptor(object, name)
assert_false("get" in pd, "get")
assert_false("set" in pd, "set")
assert_false(pd.writable, "writable")
assert_true(pd.enumerable, "enumerable")
assert_false(pd.configurable, "configurable")
}, "Constant " + name + " on " + description)
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
test(function() {
assert_own_property(self, "DOMException", "property of global");

var desc = Object.getOwnPropertyDescriptor(self, "DOMException");
assert_false("get" in desc, "get");
assert_false("set" in desc, "set");
assert_true(desc.writable, "writable");
assert_false(desc.enumerable, "enumerable");
assert_true(desc.configurable, "configurable");
}, "existence and property descriptor of DOMException");

test(function() {
assert_own_property(self.DOMException, "prototype", "prototype property");

var desc = Object.getOwnPropertyDescriptor(self.DOMException, "prototype");
assert_false("get" in desc, "get");
assert_false("set" in desc, "set");
assert_false(desc.writable, "writable");
assert_false(desc.enumerable, "enumerable");
assert_false(desc.configurable, "configurable");
}, "existence and property descriptor of DOMException.prototype");

test(function() {
assert_own_property(self.DOMException.prototype, "constructor", "property of prototype");
var desc = Object.getOwnPropertyDescriptor(self.DOMException.prototype, "constructor");
assert_false("get" in desc, "get");
assert_false("set" in desc, "set");
assert_true(desc.writable, "writable");
assert_false(desc.enumerable, "enumerable");
assert_true(desc.configurable, "configurable");
assert_equals(self.DOMException.prototype.constructor, self.DOMException, "equality with actual constructor");
}, "existence and property descriptor of DOMException.prototype.constructor");
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
'use strict';

test(function() {
var ex = new DOMException();
assert_equals(ex.name, "Error",
"Not passing a name should end up with 'Error' as the name");
assert_equals(ex.message, "",
"Not passing a message should end up with empty string as the message");
}, 'new DOMException()');

test(function() {
var ex = new DOMException();
assert_false(ex.hasOwnProperty("name"),
"The name property should be inherited");
assert_false(ex.hasOwnProperty("message"),
"The message property should be inherited");
}, 'new DOMException(): inherited-ness');

test(function() {
var ex = new DOMException(null);
assert_equals(ex.name, "Error",
"Not passing a name should end up with 'Error' as the name");
assert_equals(ex.message, "null",
"Passing null as message should end up with stringified 'null' as the message");
}, 'new DOMException(null)');

test(function() {
var ex = new DOMException(undefined);
assert_equals(ex.name, "Error",
"Not passing a name should end up with 'Error' as the name");
assert_equals(ex.message, "",
"Not passing a message should end up with empty string as the message");
}, 'new DOMException(undefined)');

test(function() {
var ex = new DOMException(undefined);
assert_false(ex.hasOwnProperty("name"),
"The name property should be inherited");
assert_false(ex.hasOwnProperty("message"),
"The message property should be inherited");
}, 'new DOMException(undefined): inherited-ness');

test(function() {
var ex = new DOMException("foo");
assert_equals(ex.name, "Error",
"Not passing a name should still end up with 'Error' as the name");
assert_equals(ex.message, "foo", "Should be using passed-in message");
}, 'new DOMException("foo")');

test(function() {
var ex = new DOMException("foo");
assert_false(ex.hasOwnProperty("name"),
"The name property should be inherited");
assert_false(ex.hasOwnProperty("message"),
"The message property should be inherited");
}, 'new DOMException("foo"): inherited-ness');

test(function() {
var ex = new DOMException("bar", undefined);
assert_equals(ex.name, "Error",
"Passing undefined for name should end up with 'Error' as the name");
assert_equals(ex.message, "bar", "Should still be using passed-in message");
}, 'new DOMException("bar", undefined)');

test(function() {
var ex = new DOMException("bar", "NotSupportedError");
assert_equals(ex.name, "NotSupportedError", "Should be using the passed-in name");
assert_equals(ex.message, "bar", "Should still be using passed-in message");
assert_equals(ex.code, DOMException.NOT_SUPPORTED_ERR,
"Should have the right exception code");
}, 'new DOMException("bar", "NotSupportedError")');

test(function() {
var ex = new DOMException("bar", "NotSupportedError");
assert_false(ex.hasOwnProperty("name"),
"The name property should be inherited");
assert_false(ex.hasOwnProperty("message"),
"The message property should be inherited");
}, 'new DOMException("bar", "NotSupportedError"): inherited-ness');

test(function() {
var ex = new DOMException("bar", "foo");
assert_equals(ex.name, "foo", "Should be using the passed-in name");
assert_equals(ex.message, "bar", "Should still be using passed-in message");
assert_equals(ex.code, 0,
"Should have 0 for code for a name not in the exception names table");
}, 'new DOMException("bar", "foo")');

[
{name: "IndexSizeError", code: 1},
{name: "HierarchyRequestError", code: 3},
{name: "WrongDocumentError", code: 4},
{name: "InvalidCharacterError", code: 5},
{name: "NoModificationAllowedError", code: 7},
{name: "NotFoundError", code: 8},
{name: "NotSupportedError", code: 9},
{name: "InUseAttributeError", code: 10},
{name: "InvalidStateError", code: 11},
{name: "SyntaxError", code: 12},
{name: "InvalidModificationError", code: 13},
{name: "NamespaceError", code: 14},
{name: "InvalidAccessError", code: 15},
{name: "TypeMismatchError", code: 17},
{name: "SecurityError", code: 18},
{name: "NetworkError", code: 19},
{name: "AbortError", code: 20},
{name: "URLMismatchError", code: 21},
{name: "QuotaExceededError", code: 22},
{name: "TimeoutError", code: 23},
{name: "InvalidNodeTypeError", code: 24},
{name: "DataCloneError", code: 25},

// These were removed from the error names table.
// See https://github.com/heycam/webidl/pull/946.
{name: "DOMStringSizeError", code: 0},
{name: "NoDataAllowedError", code: 0},
{name: "ValidationError", code: 0},

// The error names which don't have legacy code values.
{name: "EncodingError", code: 0},
{name: "NotReadableError", code: 0},
{name: "UnknownError", code: 0},
{name: "ConstraintError", code: 0},
{name: "DataError", code: 0},
{name: "TransactionInactiveError", code: 0},
{name: "ReadOnlyError", code: 0},
{name: "VersionError", code: 0},
{name: "OperationError", code: 0},
{name: "NotAllowedError", code: 0}
].forEach(function(test_case) {
test(function() {
var ex = new DOMException("msg", test_case.name);
assert_equals(ex.name, test_case.name,
"Should be using the passed-in name");
assert_equals(ex.message, "msg",
"Should be using the passed-in message");
assert_equals(ex.code, test_case.code,
"Should have matching legacy code from error names table");
},'new DOMexception("msg", "' + test_case.name + '")');
});
Loading

0 comments on commit 8a99eed

Please sign in to comment.