mirror of
https://github.com/nodejs/node.git
synced 2025-05-03 02:06:12 +00:00

This patch adds snapshot support to single executable applications. To build a snapshot from the main script when preparing the blob that will be injected into the single executable application, add `"useSnapshot": true` to the configuration passed to `--experimental-sea-config`. For example: ``` { "main": "snapshot.js", "output": "sea-prep.blob", "useSnapshot": true } ``` The main script used to build the snapshot must invoke `v8.startupSnapshot.setDeserializeMainFunction()` to configure the entry point. The generated startup snapshot would be part of the preparation blob and get injected into the final executable. When the single executable application is launched, instead of running the `main` script from scratch, Node.js would instead deserialize the snapshot to get to the state initialized during build-time directly. PR-URL: https://github.com/nodejs/node/pull/46824 Refs: https://github.com/nodejs/single-executable/discussions/57 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Darshan Sen <raisinten@gmail.com>
90 lines
2.1 KiB
JavaScript
90 lines
2.1 KiB
JavaScript
'use strict';
|
|
|
|
require('../common');
|
|
|
|
const {
|
|
injectAndCodeSign,
|
|
skipIfSingleExecutableIsNotSupported,
|
|
} = require('../common/sea');
|
|
|
|
skipIfSingleExecutableIsNotSupported();
|
|
|
|
// This tests the snapshot support in single executable applications.
|
|
|
|
const tmpdir = require('../common/tmpdir');
|
|
const { copyFileSync, writeFileSync, existsSync } = require('fs');
|
|
const { spawnSync } = require('child_process');
|
|
const { join } = require('path');
|
|
const assert = require('assert');
|
|
|
|
const configFile = join(tmpdir.path, 'sea-config.json');
|
|
const seaPrepBlob = join(tmpdir.path, 'sea-prep.blob');
|
|
const outputFile = join(tmpdir.path, process.platform === 'win32' ? 'sea.exe' : 'sea');
|
|
|
|
{
|
|
tmpdir.refresh();
|
|
|
|
writeFileSync(join(tmpdir.path, 'snapshot.js'), '', 'utf-8');
|
|
writeFileSync(configFile, `
|
|
{
|
|
"main": "snapshot.js",
|
|
"output": "sea-prep.blob",
|
|
"useSnapshot": true
|
|
}
|
|
`);
|
|
|
|
const child = spawnSync(
|
|
process.execPath,
|
|
['--experimental-sea-config', 'sea-config.json'],
|
|
{
|
|
cwd: tmpdir.path
|
|
});
|
|
|
|
assert.match(
|
|
child.stderr.toString(),
|
|
/snapshot\.js does not invoke v8\.startupSnapshot\.setDeserializeMainFunction\(\)/);
|
|
}
|
|
|
|
{
|
|
tmpdir.refresh();
|
|
const code = `
|
|
const {
|
|
setDeserializeMainFunction,
|
|
} = require('v8').startupSnapshot;
|
|
|
|
setDeserializeMainFunction(() => {
|
|
console.log('Hello from snapshot');
|
|
});
|
|
`;
|
|
|
|
writeFileSync(join(tmpdir.path, 'snapshot.js'), code, 'utf-8');
|
|
writeFileSync(configFile, `
|
|
{
|
|
"main": "snapshot.js",
|
|
"output": "sea-prep.blob",
|
|
"useSnapshot": true
|
|
}
|
|
`);
|
|
|
|
let child = spawnSync(
|
|
process.execPath,
|
|
['--experimental-sea-config', 'sea-config.json'],
|
|
{
|
|
cwd: tmpdir.path
|
|
});
|
|
assert.match(
|
|
child.stderr.toString(),
|
|
/Single executable application is an experimental feature/);
|
|
|
|
assert(existsSync(seaPrepBlob));
|
|
|
|
copyFileSync(process.execPath, outputFile);
|
|
injectAndCodeSign(outputFile, seaPrepBlob);
|
|
|
|
child = spawnSync(outputFile);
|
|
assert.strictEqual(child.stdout.toString().trim(), 'Hello from snapshot');
|
|
assert.doesNotMatch(
|
|
child.stderr.toString(),
|
|
/Single executable application is an experimental feature/);
|
|
}
|