diff options
author | Joyee Cheung <joyeec9h3@gmail.com> | 2019-04-24 01:24:23 +0800 |
---|---|---|
committer | Daniel Bevenius <daniel.bevenius@gmail.com> | 2019-04-26 07:23:42 +0200 |
commit | 08a9c4a996964aca909cd75fa8ecafd652c54885 (patch) | |
tree | 41fdc49f11e9e293d26257b95be88a9cd04e84c3 | |
parent | 5ab65cff8d95faa6ebd91f20b77156a520dc3ac2 (diff) | |
download | android-node-v8-08a9c4a996964aca909cd75fa8ecafd652c54885.tar.gz android-node-v8-08a9c4a996964aca909cd75fa8ecafd652c54885.tar.bz2 android-node-v8-08a9c4a996964aca909cd75fa8ecafd652c54885.zip |
bootstrap: delay the instantiation of maps in per-context scripts
Instantiating maps renders the snapshot non-rehashable
(v8 currently fails silently during `CreateBlob()`).
Then the hash seed would always be the same and not
recomputed if custom V8 snapshot is enabled. This patch
delays the instantiation of the maps in domexception.js
and make it lazy.
PR-URL: https://github.com/nodejs/node/pull/27371
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
-rw-r--r-- | lib/internal/per_context/domexception.js | 82 |
1 files changed, 51 insertions, 31 deletions
diff --git a/lib/internal/per_context/domexception.js b/lib/internal/per_context/domexception.js index 83b8d55995..3852567ac6 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; |