Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
  • Loading branch information
joyeecheung committed Apr 23, 2019
commit 2d6665a94d3b2962eec668d7c4417099f4a49d2b
82 changes: 51 additions & 31 deletions lib/internal/per_context/domexception.js
Original file line number Diff line number Diff line change
Expand Up @@ -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}`,
Expand All @@ -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');
Expand All @@ -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');
Expand All @@ -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');
Expand All @@ -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;