Skip to content
Open
Show file tree
Hide file tree
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
19 changes: 19 additions & 0 deletions doc/api/globals.md
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,24 @@ changes:

A browser-compatible implementation of [`WritableStreamDefaultWriter`][].

## `[Symbol.for('startupSnapshot')]`

<!-- YAML
added: REPLACEME
-->

An object exposing the `addDeserializeCallback`, `addSerializeCallback`, and `isBuildingSnapshot`
methods from [`v8.startupSnapshot`][] for usage in libraries that target both Node.js and other
runtimes and cannot directly rely on the `v8` module.

```js
const {
addDeserializeCallback,
addSerializeCallback,
isBuildingSnapshot,
} = globalThis[Symbol.for('startupSnapshot')];
```

[CommonJS module]: modules.md
[CommonJS modules]: modules.md
[ECMAScript module]: esm.md
Expand Down Expand Up @@ -1422,6 +1440,7 @@ A browser-compatible implementation of [`WritableStreamDefaultWriter`][].
[`setInterval`]: timers.md#setintervalcallback-delay-args
[`setTimeout`]: timers.md#settimeoutcallback-delay-args
[`structuredClone`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/structuredClone
[`v8.startupSnapshot`]: v8.md#startup-snapshot-api
[`window.navigator`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/navigator
[`worker_threads.locks`]: worker_threads.md#worker_threadslocks
[browser `LockManager`]: https://developer.mozilla.org/en-US/docs/Web/API/LockManager
Expand Down
12 changes: 12 additions & 0 deletions doc/api/v8.md
Original file line number Diff line number Diff line change
Expand Up @@ -1400,6 +1400,10 @@ into a form more suitable for serialization.

Callbacks are run in the order in which they are added.

This function is also available as
`globalThis[Symbol.for('startupSnapshot')].addSerializeCallback` for use
in libraries that cannot import the `v8` module.

### `v8.startupSnapshot.addDeserializeCallback(callback[, data])`

<!-- YAML
Expand All @@ -1421,6 +1425,10 @@ when the application is restarted from the snapshot.

Callbacks are run in the order in which they are added.

This function is also available as
`globalThis[Symbol.for('startupSnapshot')].addDeserializeCallback` for use
in libraries that cannot import the `v8` module.

### `v8.startupSnapshot.setDeserializeMainFunction(callback[, data])`

<!-- YAML
Expand Down Expand Up @@ -1453,6 +1461,10 @@ added:

Returns true if the Node.js instance is run to build a snapshot.

This function is also available as
`globalThis[Symbol.for('startupSnapshot')].isBuildingSnapshot` for use
in libraries that cannot import the `v8` module.

## Class: `v8.GCProfiler`

<!-- YAML
Expand Down
8 changes: 8 additions & 0 deletions lib/internal/process/pre_execution.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const {
ObjectDefineProperty,
ObjectFreeze,
String,
SymbolFor,
globalThis,
} = primordials;

Expand Down Expand Up @@ -123,6 +124,7 @@ function prepareExecution(options) {
setupEventsource();
setupCodeCoverage();
setupDebugEnv();
setupGlobalSnapshotHooks();
// Process initial diagnostic reporting configuration, if present.
initializeReport();

Expand Down Expand Up @@ -378,6 +380,12 @@ function setupNavigator() {
defineReplaceableLazyAttribute(globalThis, 'internal/navigator', ['navigator'], false);
}

function setupGlobalSnapshotHooks() {
exposeLazyInterfaces(globalThis, 'internal/v8/startup_snapshot', [
SymbolFor('startupSnapshot'),
]);
}

function setupFFI() {
if (!getOptionValue('--experimental-ffi')) {
return;
Expand Down
10 changes: 10 additions & 0 deletions lib/internal/v8/startup_snapshot.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
'use strict';

const {
SymbolFor,
} = primordials;

const {
validateFunction,
} = require('internal/validators');
Expand Down Expand Up @@ -122,6 +126,12 @@ initializeCallbacks();
module.exports = {
runDeserializeCallbacks,
throwIfBuildingSnapshot,
// Exposed to globalThis[Symbol.for('startupSnapshot')]
[SymbolFor('startupSnapshot')]: {
addDeserializeCallback,
addSerializeCallback,
isBuildingSnapshot,
},
// Exposed to require('v8').startupSnapshot
namespace: {
addDeserializeCallback,
Expand Down
4 changes: 2 additions & 2 deletions src/node_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -422,10 +422,10 @@ static void DefineLazyProperties(const FunctionCallbackInfo<Value>& args) {
// V8 will have scheduled an error to be thrown.
return;
}
CHECK(key->IsString());
CHECK(key->IsName());
if (target
->SetLazyDataProperty(context,
key.As<String>(),
key.As<Name>(),
DefineLazyPropertiesGetter,
id,
attribute)
Expand Down
8 changes: 8 additions & 0 deletions test/parallel/test-v8-startup-snapshot-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,11 @@ assert.throws(() => addDeserializeCallback(() => {}), {
assert.throws(() => setDeserializeMainFunction(() => {}), {
code: 'ERR_NOT_BUILDING_SNAPSHOT',
});

// globalThis[Symbol.for('startupSnapshot')] provides access to a subset
// of functions.
assert.deepStrictEqual(globalThis[Symbol.for('startupSnapshot')], {
addDeserializeCallback,
addSerializeCallback,
isBuildingSnapshot,
});
Loading