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>
This commit is contained in:
parent
5ab65cff8d
commit
08a9c4a996
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user