mirror of
https://github.com/nodejs/node.git
synced 2025-05-20 20:44:49 +00:00

Previously, the `require()` function exposed to the embedded SEA code was calling the internal `require()` function if the module name belonged to the list of public core modules but the internal `require()` function does not support loading modules with the "node:" prefix, so this change forwards the calls to another `require()` function that supports this. Fixes: https://github.com/nodejs/single-executable/issues/69 Signed-off-by: Darshan Sen <raisinten@gmail.com> PR-URL: https://github.com/nodejs/node/pull/47779 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Michael Dawson <midawson@redhat.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
187 lines
4.4 KiB
JavaScript
187 lines
4.4 KiB
JavaScript
'use strict';
|
|
|
|
const {
|
|
Error,
|
|
ObjectDefineProperty,
|
|
ObjectGetOwnPropertyDescriptor,
|
|
ObjectSetPrototypeOf,
|
|
SafeArrayIterator,
|
|
SafeSet,
|
|
} = primordials;
|
|
|
|
const binding = internalBinding('mksnapshot');
|
|
const { BuiltinModule: { normalizeRequirableId } } = require('internal/bootstrap/realm');
|
|
const {
|
|
getEmbedderEntryFunction,
|
|
compileSerializeMain,
|
|
} = binding;
|
|
|
|
const {
|
|
getOptionValue,
|
|
} = require('internal/options');
|
|
|
|
const {
|
|
readFileSync,
|
|
} = require('fs');
|
|
|
|
const supportedModules = new SafeSet(new SafeArrayIterator([
|
|
// '_http_agent',
|
|
// '_http_client',
|
|
// '_http_common',
|
|
// '_http_incoming',
|
|
// '_http_outgoing',
|
|
// '_http_server',
|
|
'_stream_duplex',
|
|
'_stream_passthrough',
|
|
'_stream_readable',
|
|
'_stream_transform',
|
|
'_stream_wrap',
|
|
'_stream_writable',
|
|
// '_tls_common',
|
|
// '_tls_wrap',
|
|
'assert',
|
|
'assert/strict',
|
|
// 'async_hooks',
|
|
'buffer',
|
|
// 'child_process',
|
|
// 'cluster',
|
|
'console',
|
|
'constants',
|
|
'crypto',
|
|
// 'dgram',
|
|
'diagnostics_channel',
|
|
'dns',
|
|
// 'dns/promises',
|
|
// 'domain',
|
|
'events',
|
|
'fs',
|
|
'fs/promises',
|
|
// 'http',
|
|
// 'http2',
|
|
// 'https',
|
|
// 'inspector',
|
|
// 'module',
|
|
'net',
|
|
'os',
|
|
'path',
|
|
'path/posix',
|
|
'path/win32',
|
|
// 'perf_hooks',
|
|
'process',
|
|
'punycode',
|
|
'querystring',
|
|
// 'readline',
|
|
// 'repl',
|
|
'stream',
|
|
'stream/promises',
|
|
'string_decoder',
|
|
'sys',
|
|
'timers',
|
|
'timers/promises',
|
|
// 'tls',
|
|
// 'trace_events',
|
|
// 'tty',
|
|
'url',
|
|
'util',
|
|
'util/types',
|
|
'v8',
|
|
// 'vm',
|
|
// 'worker_threads',
|
|
'zlib',
|
|
]));
|
|
|
|
const warnedModules = new SafeSet();
|
|
function supportedInUserSnapshot(id) {
|
|
return supportedModules.has(id);
|
|
}
|
|
|
|
function requireForUserSnapshot(id) {
|
|
const normalizedId = normalizeRequirableId(id);
|
|
if (!normalizedId) {
|
|
// eslint-disable-next-line no-restricted-syntax
|
|
const err = new Error(
|
|
`Cannot find module '${id}'. `,
|
|
);
|
|
err.code = 'MODULE_NOT_FOUND';
|
|
throw err;
|
|
}
|
|
if (!supportedInUserSnapshot(normalizedId)) {
|
|
if (!warnedModules.has(normalizedId)) {
|
|
process.emitWarning(
|
|
`built-in module ${id} is not yet supported in user snapshots`);
|
|
warnedModules.add(normalizedId);
|
|
}
|
|
}
|
|
|
|
return require(normalizedId);
|
|
}
|
|
|
|
function main() {
|
|
const {
|
|
prepareMainThreadExecution,
|
|
} = require('internal/process/pre_execution');
|
|
const path = require('path');
|
|
|
|
let serializeMainFunction = getEmbedderEntryFunction();
|
|
const serializeMainArgs = [requireForUserSnapshot];
|
|
|
|
if (serializeMainFunction) { // embedded case
|
|
prepareMainThreadExecution(false, false);
|
|
// TODO(addaleax): Make this `embedderRunCjs` once require('module')
|
|
// is supported in snapshots.
|
|
const filename = process.execPath;
|
|
const dirname = path.dirname(filename);
|
|
function minimalRunCjs(source) {
|
|
const fn = compileSerializeMain(filename, source);
|
|
return fn(requireForUserSnapshot, filename, dirname);
|
|
}
|
|
serializeMainArgs.push(minimalRunCjs);
|
|
} else {
|
|
prepareMainThreadExecution(true, false);
|
|
const file = process.argv[1];
|
|
const filename = path.resolve(file);
|
|
const dirname = path.dirname(filename);
|
|
const source = readFileSync(file, 'utf-8');
|
|
serializeMainFunction = compileSerializeMain(filename, source);
|
|
serializeMainArgs.push(filename, dirname);
|
|
}
|
|
|
|
const {
|
|
initializeCallbacks,
|
|
namespace: {
|
|
addSerializeCallback,
|
|
addDeserializeCallback,
|
|
},
|
|
} = require('internal/v8/startup_snapshot');
|
|
initializeCallbacks();
|
|
|
|
let stackTraceLimitDesc;
|
|
addDeserializeCallback(() => {
|
|
if (stackTraceLimitDesc !== undefined) {
|
|
ObjectDefineProperty(Error, 'stackTraceLimit', stackTraceLimitDesc);
|
|
}
|
|
});
|
|
|
|
if (getOptionValue('--inspect-brk')) {
|
|
internalBinding('inspector').callAndPauseOnStart(
|
|
serializeMainFunction, undefined, ...serializeMainArgs);
|
|
} else {
|
|
serializeMainFunction(...serializeMainArgs);
|
|
}
|
|
|
|
addSerializeCallback(() => {
|
|
stackTraceLimitDesc = ObjectGetOwnPropertyDescriptor(Error, 'stackTraceLimit');
|
|
|
|
if (stackTraceLimitDesc !== undefined) {
|
|
// We want to use null-prototype objects to not rely on globally mutable
|
|
// %Object.prototype%.
|
|
ObjectSetPrototypeOf(stackTraceLimitDesc, null);
|
|
process._rawDebug('Deleting Error.stackTraceLimit from the snapshot. ' +
|
|
'It will be re-installed after deserialization');
|
|
delete Error.stackTraceLimit;
|
|
}
|
|
});
|
|
}
|
|
|
|
main();
|