diff --git a/lib/internal/per_context/domexception.js b/lib/internal/per_context/domexception.js index 83b8d559952..3852567ac6b 100644 --- a/lib/internal/per_context/domexception.js +++ b/lib/internal/per_context/domexception.js @@ -15,12 +15,28 @@ class ERR_INVALID_THIS extends TypeError { get code() { return 'ERR_INVALID_THIS'; } } -const internalsMap = new SafeWeakMap(); +let internalsMap; +let nameToCodeMap; +let isInitialized = false; -const nameToCodeMap = new SafeMap(); +// We need to instantiate the maps lazily because they render +// the snapshot non-rehashable. +// https://bugs.chromium.org/p/v8/issues/detail?id=6593 +function ensureInitialized() { + if (isInitialized) { + return; + } + internalsMap = new SafeWeakMap(); + nameToCodeMap = new SafeMap(); + forEachCode((name, codeName, value) => { + nameToCodeMap.set(name, value); + }); + isInitialized = true; +} class DOMException extends Error { constructor(message = '', name = 'Error') { + ensureInitialized(); super(); internalsMap.set(this, { message: `${message}`, @@ -29,6 +45,7 @@ class DOMException extends Error { } get name() { + ensureInitialized(); const internals = internalsMap.get(this); if (internals === undefined) { throw new ERR_INVALID_THIS('DOMException'); @@ -37,6 +54,7 @@ class DOMException extends Error { } get message() { + ensureInitialized(); const internals = internalsMap.get(this); if (internals === undefined) { throw new ERR_INVALID_THIS('DOMException'); @@ -45,6 +63,7 @@ class DOMException extends Error { } get code() { + ensureInitialized(); const internals = internalsMap.get(this); if (internals === undefined) { throw new ERR_INVALID_THIS('DOMException'); @@ -61,39 +80,40 @@ Object.defineProperties(DOMException.prototype, { code: { enumerable: true, configurable: true } }); -for (const [name, codeName, 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] +function forEachCode(fn) { + fn('IndexSizeError', 'INDEX_SIZE_ERR', 1); + fn('DOMStringSizeError', 'DOMSTRING_SIZE_ERR', 2); + fn('HierarchyRequestError', 'HIERARCHY_REQUEST_ERR', 3); + fn('WrongDocumentError', 'WRONG_DOCUMENT_ERR', 4); + fn('InvalidCharacterError', 'INVALID_CHARACTER_ERR', 5); + fn('NoDataAllowedError', 'NO_DATA_ALLOWED_ERR', 6); + fn('NoModificationAllowedError', 'NO_MODIFICATION_ALLOWED_ERR', 7); + fn('NotFoundError', 'NOT_FOUND_ERR', 8); + fn('NotSupportedError', 'NOT_SUPPORTED_ERR', 9); + fn('InUseAttributeError', 'INUSE_ATTRIBUTE_ERR', 10); + fn('InvalidStateError', 'INVALID_STATE_ERR', 11); + fn('SyntaxError', 'SYNTAX_ERR', 12); + fn('InvalidModificationError', 'INVALID_MODIFICATION_ERR', 13); + fn('NamespaceError', 'NAMESPACE_ERR', 14); + fn('InvalidAccessError', 'INVALID_ACCESS_ERR', 15); + fn('ValidationError', 'VALIDATION_ERR', 16); + fn('TypeMismatchError', 'TYPE_MISMATCH_ERR', 17); + fn('SecurityError', 'SECURITY_ERR', 18); + fn('NetworkError', 'NETWORK_ERR', 19); + fn('AbortError', 'ABORT_ERR', 20); + fn('URLMismatchError', 'URL_MISMATCH_ERR', 21); + fn('QuotaExceededError', 'QUOTA_EXCEEDED_ERR', 22); + fn('TimeoutError', 'TIMEOUT_ERR', 23); + fn('InvalidNodeTypeError', 'INVALID_NODE_TYPE_ERR', 24); + fn('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. -]) { +} + +forEachCode((name, codeName, value) => { const desc = { enumerable: true, value }; Object.defineProperty(DOMException, codeName, desc); Object.defineProperty(DOMException.prototype, codeName, desc); - nameToCodeMap.set(name, value); -} +}); exports.DOMException = DOMException;