-
Notifications
You must be signed in to change notification settings - Fork 30k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
src: fixup Error.stackTraceLimit during snapshot building
When V8 creates a context for snapshot building, it does not install Error.stackTraceLimit. As a result, error.stack would be undefined in the snapshot builder script unless users explicitly initialize Error.stackTraceLimit, which may be surprising. This patch initializes Error.stackTraceLimit based on the value of --stack-trace-limit to prevent the surprise. If users have modified Error.stackTraceLimit in the builder script, the modified value would be restored during deserialization. Otherwise, the fixed up limit would be deleted since V8 expects to find it unset and re-initialize it during snapshot deserialization. PR-URL: #55121 Fixes: #55100 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
- Loading branch information
1 parent
b229083
commit 1af5ad6
Showing
6 changed files
with
219 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
|
||
const { | ||
setDeserializeMainFunction, | ||
} = require('v8').startupSnapshot; | ||
|
||
console.log(`During snapshot building, Error.stackTraceLimit =`, Error.stackTraceLimit); | ||
console.log(getError('During snapshot building', 30)); | ||
|
||
setDeserializeMainFunction(() => { | ||
console.log(`After snapshot deserialization, Error.stackTraceLimit =`, Error.stackTraceLimit); | ||
console.log(getError('After snapshot deserialization', 30)); | ||
}); | ||
|
||
function getError(message, depth) { | ||
let counter = 1; | ||
function recurse() { | ||
if (counter++ < depth) { | ||
return recurse(); | ||
} | ||
const error = new Error(message); | ||
return error.stack; | ||
} | ||
return recurse(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
|
||
const { | ||
addSerializeCallback, | ||
setDeserializeMainFunction, | ||
} = require('v8').startupSnapshot; | ||
const assert = require('assert'); | ||
|
||
if (process.env.TEST_IN_SERIALIZER) { | ||
addSerializeCallback(checkMutate); | ||
} else { | ||
checkMutate(); | ||
} | ||
|
||
function checkMutate() { | ||
// Check that mutation to Error.stackTraceLimit is effective in the snapshot | ||
// builder script. | ||
assert.strictEqual(typeof Error.stackTraceLimit, 'number'); | ||
Error.stackTraceLimit = 0; | ||
assert.strictEqual(getError('', 30), 'Error'); | ||
} | ||
|
||
setDeserializeMainFunction(() => { | ||
// Check that the mutation is preserved in the deserialized main function. | ||
assert.strictEqual(Error.stackTraceLimit, 0); | ||
assert.strictEqual(getError('', 30), 'Error'); | ||
|
||
// Check that it can still be mutated. | ||
Error.stackTraceLimit = 10; | ||
const error = getError('', 30); | ||
const matches = [...error.matchAll(/at recurse/g)]; | ||
assert.strictEqual(matches.length, 10); | ||
}); | ||
|
||
function getError(message, depth) { | ||
let counter = 1; | ||
function recurse() { | ||
if (counter++ < depth) { | ||
return recurse(); | ||
} | ||
const error = new Error(message); | ||
return error.stack; | ||
} | ||
return recurse(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
'use strict'; | ||
|
||
// This tests mutation to Error.stackTraceLimit in both the snapshot builder script | ||
// and the snapshot main script work. | ||
|
||
require('../common'); | ||
const assert = require('assert'); | ||
const tmpdir = require('../common/tmpdir'); | ||
const fixtures = require('../common/fixtures'); | ||
const { spawnSyncAndAssert, spawnSyncAndExitWithoutError } = require('../common/child_process'); | ||
|
||
const blobPath = tmpdir.resolve('snapshot.blob'); | ||
|
||
function test(additionalArguments = [], additionalEnv = {}) { | ||
tmpdir.refresh(); | ||
// Check the mutation works without --stack-trace-limit. | ||
spawnSyncAndAssert(process.execPath, [ | ||
...additionalArguments, | ||
'--snapshot-blob', | ||
blobPath, | ||
'--build-snapshot', | ||
fixtures.path('snapshot', 'mutate-error-stack-trace-limit.js'), | ||
], { | ||
cwd: tmpdir.path, | ||
env: { | ||
...process.env, | ||
...additionalEnv, | ||
} | ||
}, { | ||
stderr(output) { | ||
assert.match(output, /Error\.stackTraceLimit has been modified by the snapshot builder script/); | ||
assert.match(output, /It will be preserved after snapshot deserialization/); | ||
} | ||
}); | ||
spawnSyncAndExitWithoutError(process.execPath, [ | ||
'--snapshot-blob', | ||
blobPath, | ||
], { | ||
cwd: tmpdir.path | ||
}); | ||
} | ||
|
||
test(); | ||
test([], { TEST_IN_SERIALIZER: 1 }); | ||
test(['--stack-trace-limit=50']); | ||
test(['--stack-trace-limit=50'], { TEST_IN_SERIALIZER: 1 }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
'use strict'; | ||
|
||
// This tests Error.stackTraceLimit is fixed up for snapshot-building contexts, | ||
// and can be restored after deserialization. | ||
|
||
require('../common'); | ||
const assert = require('assert'); | ||
const tmpdir = require('../common/tmpdir'); | ||
const fixtures = require('../common/fixtures'); | ||
const { spawnSyncAndAssert } = require('../common/child_process'); | ||
|
||
tmpdir.refresh(); | ||
const blobPath = tmpdir.resolve('snapshot.blob'); | ||
{ | ||
spawnSyncAndAssert(process.execPath, [ | ||
'--stack-trace-limit=50', | ||
'--snapshot-blob', | ||
blobPath, | ||
'--build-snapshot', | ||
fixtures.path('snapshot', 'error-stack.js'), | ||
], { | ||
cwd: tmpdir.path | ||
}, { | ||
stdout(output) { | ||
assert.match(output, /During snapshot building, Error\.stackTraceLimit = 50/); | ||
const matches = [...output.matchAll(/at recurse/g)]; | ||
assert.strictEqual(matches.length, 30); | ||
} | ||
}); | ||
} | ||
|
||
{ | ||
spawnSyncAndAssert(process.execPath, [ | ||
'--stack-trace-limit=20', | ||
'--snapshot-blob', | ||
blobPath, | ||
], { | ||
cwd: tmpdir.path | ||
}, { | ||
stdout(output) { | ||
assert.match(output, /After snapshot deserialization, Error\.stackTraceLimit = 20/); | ||
const matches = [...output.matchAll(/at recurse/g)]; | ||
assert.strictEqual(matches.length, 20); | ||
} | ||
}); | ||
} |