From e223fc42444d6e948e25e927a4207e0d7b8c87a3 Mon Sep 17 00:00:00 2001 From: shirakaba <14055146+shirakaba@users.noreply.github.com> Date: Sun, 17 Mar 2024 22:28:57 +0900 Subject: [PATCH] as-is commit of DomException implementation from 10th March 2024 https://github.com/nodejs/node/blob/454d0806a1f2e2aa5c327cff57c1dff7c43fc21b/lib/internal/per_context/domexception.js#L51 --- LICENCE-abort-controller | 21 ++++++ src/dom-exception.js | 157 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 LICENCE-abort-controller create mode 100644 src/dom-exception.js diff --git a/LICENCE-abort-controller b/LICENCE-abort-controller new file mode 100644 index 0000000..c914149 --- /dev/null +++ b/LICENCE-abort-controller @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Toru Nagashima + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/dom-exception.js b/src/dom-exception.js new file mode 100644 index 0000000..951382c --- /dev/null +++ b/src/dom-exception.js @@ -0,0 +1,157 @@ +'use strict'; + +const { + ErrorCaptureStackTrace, + ErrorPrototype, + ObjectDefineProperties, + ObjectDefineProperty, + ObjectSetPrototypeOf, + SafeWeakMap, + SafeMap, + SafeSet, + SymbolToStringTag, + TypeError, +} = primordials; + +function throwInvalidThisError(Base, type) { + const err = new Base(); + const key = 'ERR_INVALID_THIS'; + ObjectDefineProperties(err, { + message: { + __proto__: null, + value: `Value of "this" must be of ${type}`, + enumerable: false, + writable: true, + configurable: true, + }, + toString: { + __proto__: null, + value() { + return `${this.name} [${key}]: ${this.message}`; + }, + enumerable: false, + writable: true, + configurable: true, + }, + }); + err.code = key; + throw err; +} + +const internalsMap = new SafeWeakMap(); +const nameToCodeMap = new SafeMap(); + +// These were removed from the error names table. +// See https://github.com/heycam/webidl/pull/946. +const disusedNamesSet = new SafeSet() + .add('DOMStringSizeError') + .add('NoDataAllowedError') + .add('ValidationError'); + +class DOMException { + constructor(message = '', options = 'Error') { + ErrorCaptureStackTrace(this); + + if (options && typeof options === 'object') { + const { name } = options; + internalsMap.set(this, { + message: `${message}`, + name: `${name}`, + }); + + if ('cause' in options) { + ObjectDefineProperty(this, 'cause', { + __proto__: null, + value: options.cause, + configurable: true, + writable: true, + enumerable: false, + }); + } + } else { + internalsMap.set(this, { + message: `${message}`, + name: `${options}`, + }); + } + } + + get name() { + const internals = internalsMap.get(this); + if (internals === undefined) { + throwInvalidThisError(TypeError, 'DOMException'); + } + return internals.name; + } + + get message() { + const internals = internalsMap.get(this); + if (internals === undefined) { + throwInvalidThisError(TypeError, 'DOMException'); + } + return internals.message; + } + + get code() { + const internals = internalsMap.get(this); + 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]: { + __proto__: null, + configurable: true, + value: 'DOMException', + }, + name: { __proto__: null, enumerable: true, configurable: true }, + message: { __proto__: null, enumerable: true, configurable: true }, + code: { __proto__: null, enumerable: true, configurable: true }, +}); + +for (const { 0: name, 1: codeName, 2: value } of [ + ['IndexSizeError', 'INDEX_SIZE_ERR', 1], + ['DOMStringSizeError', 'DOMSTRING_SIZE_ERR', 2], + ['HierarchyRequestError', 'HIERARCHY_REQUEST_ERR', 3], + ['WrongDocumentError', 'WRONG_DOCUMENT_ERR', 4], + ['InvalidCharacterError', 'INVALID_CHARACTER_ERR', 5], + ['NoDataAllowedError', 'NO_DATA_ALLOWED_ERR', 6], + ['NoModificationAllowedError', 'NO_MODIFICATION_ALLOWED_ERR', 7], + ['NotFoundError', 'NOT_FOUND_ERR', 8], + ['NotSupportedError', 'NOT_SUPPORTED_ERR', 9], + ['InUseAttributeError', 'INUSE_ATTRIBUTE_ERR', 10], + ['InvalidStateError', 'INVALID_STATE_ERR', 11], + ['SyntaxError', 'SYNTAX_ERR', 12], + ['InvalidModificationError', 'INVALID_MODIFICATION_ERR', 13], + ['NamespaceError', 'NAMESPACE_ERR', 14], + ['InvalidAccessError', 'INVALID_ACCESS_ERR', 15], + ['ValidationError', 'VALIDATION_ERR', 16], + ['TypeMismatchError', 'TYPE_MISMATCH_ERR', 17], + ['SecurityError', 'SECURITY_ERR', 18], + ['NetworkError', 'NETWORK_ERR', 19], + ['AbortError', 'ABORT_ERR', 20], + ['URLMismatchError', 'URL_MISMATCH_ERR', 21], + ['QuotaExceededError', 'QUOTA_EXCEEDED_ERR', 22], + ['TimeoutError', 'TIMEOUT_ERR', 23], + ['InvalidNodeTypeError', 'INVALID_NODE_TYPE_ERR', 24], + ['DataCloneError', 'DATA_CLONE_ERR', 25], + // There are some more error names, but since they don't have codes assigned, + // we don't need to care about them. +]) { + const desc = { enumerable: true, value }; + ObjectDefineProperty(DOMException, codeName, desc); + ObjectDefineProperty(DOMException.prototype, codeName, desc); + nameToCodeMap.set(name, value); +} + +exports.DOMException = DOMException;