-
Notifications
You must be signed in to change notification settings - Fork 29.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
src: refactor embedded entrypoint loading
This patch: 1. Refactor the routines used to compile and run an embedder entrypoint. In JS land special handling for SEA is done directly in main/embedding.js instead of clobbering the CJS loader. Add warnings to remind users that currently the require() in SEA bundled scripts only supports loading builtins. 2. Don't use the bundled SEA code cache when compiling CJS loaded from disk, since in that case we are certainly not compiling the code bundled into the SEA. Use a is_sea_main flag in CompileFunctionForCJSLoader() (which replaces an unused argument) to pass this into the C++ land - the code cache is still read directly from C++ to avoid the overhead of ArrayBuffer creation. 3. Move SEA loading code into MaybeLoadSingleExecutableApplication() which calls LoadEnvironment() with its own StartExecutionCallback(). This avoids more hidden switches in StartExecution() and make them explicit. Also add some TODOs about how to support ESM in embedded applications. 4. Add more comments PR-URL: #53573 Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
- Loading branch information
1 parent
85e5359
commit 229c857
Showing
11 changed files
with
209 additions
and
134 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,116 @@ | ||
'use strict'; | ||
|
||
// This main script is currently only run when LoadEnvironment() | ||
// is run with a non-null StartExecutionCallback or a UTF8 | ||
// main script. Effectively there are two cases where this happens: | ||
// 1. It's a single-executable application *loading* a main script | ||
// bundled into the executable. This is currently done from | ||
// NodeMainInstance::Run(). | ||
// 2. It's an embedder application and LoadEnvironment() is invoked | ||
// as described above. | ||
|
||
const { | ||
prepareMainThreadExecution, | ||
} = require('internal/process/pre_execution'); | ||
const { isExperimentalSeaWarningNeeded } = internalBinding('sea'); | ||
const { isExperimentalSeaWarningNeeded, isSea } = internalBinding('sea'); | ||
const { emitExperimentalWarning } = require('internal/util'); | ||
const { embedderRequire, embedderRunCjs } = require('internal/util/embedding'); | ||
const { emitWarningSync } = require('internal/process/warning'); | ||
const { BuiltinModule: { normalizeRequirableId } } = require('internal/bootstrap/realm'); | ||
const { Module } = require('internal/modules/cjs/loader'); | ||
const { compileFunctionForCJSLoader } = internalBinding('contextify'); | ||
const { maybeCacheSourceMap } = require('internal/source_map/source_map_cache'); | ||
|
||
const { codes: { | ||
ERR_UNKNOWN_BUILTIN_MODULE, | ||
} } = require('internal/errors'); | ||
|
||
// Don't expand process.argv[1] because in a single-executable application or an | ||
// embedder application, the user main script isn't necessarily provided via the | ||
// command line (e.g. it could be provided via an API or bundled into the executable). | ||
prepareMainThreadExecution(false, true); | ||
|
||
const isLoadingSea = isSea(); | ||
if (isExperimentalSeaWarningNeeded()) { | ||
emitExperimentalWarning('Single executable application'); | ||
} | ||
|
||
// This is roughly the same as: | ||
// | ||
// const mod = new Module(filename); | ||
// mod._compile(content, filename); | ||
// | ||
// but the code has been duplicated because currently there is no way to set the | ||
// value of require.main to module. | ||
// | ||
// TODO(RaisinTen): Find a way to deduplicate this. | ||
function embedderRunCjs(content) { | ||
// The filename of the module (used for CJS module lookup) | ||
// is always the same as the location of the executable itself | ||
// at the time of the loading (which means it changes depending | ||
// on where the executable is in the file system). | ||
const filename = process.execPath; | ||
const customModule = new Module(filename, null); | ||
|
||
const { | ||
function: compiledWrapper, | ||
cachedDataRejected, | ||
sourceMapURL, | ||
} = compileFunctionForCJSLoader( | ||
content, | ||
filename, | ||
isLoadingSea, // is_sea_main | ||
false, // should_detect_module, ESM should be supported differently for embedded code | ||
); | ||
// Cache the source map for the module if present. | ||
if (sourceMapURL) { | ||
maybeCacheSourceMap( | ||
filename, | ||
content, | ||
customModule, | ||
false, // isGeneratedSource | ||
undefined, // sourceURL, TODO(joyeecheung): should be extracted by V8 | ||
sourceMapURL, | ||
); | ||
} | ||
|
||
// cachedDataRejected is only set if cache from SEA is used. | ||
if (cachedDataRejected !== false && isLoadingSea) { | ||
emitWarningSync('Code cache data rejected.'); | ||
} | ||
|
||
// Patch the module to make it look almost like a regular CJS module | ||
// instance. | ||
customModule.filename = process.execPath; | ||
customModule.paths = Module._nodeModulePaths(process.execPath); | ||
embedderRequire.main = customModule; | ||
|
||
return compiledWrapper( | ||
customModule.exports, // exports | ||
embedderRequire, // require | ||
customModule, // module | ||
process.execPath, // __filename | ||
customModule.path, // __dirname | ||
); | ||
} | ||
|
||
let warnedAboutBuiltins = false; | ||
|
||
function embedderRequire(id) { | ||
const normalizedId = normalizeRequirableId(id); | ||
if (!normalizedId) { | ||
if (isLoadingSea && !warnedAboutBuiltins) { | ||
emitWarningSync( | ||
'Currently the require() provided to the main script embedded into ' + | ||
'single-executable applications only supports loading built-in modules.\n' + | ||
'To load a module from disk after the single executable application is ' + | ||
'launched, use require("module").createRequire().\n' + | ||
'Support for bundled module loading or virtual file systems are under ' + | ||
'discussions in https://github.com/nodejs/single-executable'); | ||
warnedAboutBuiltins = true; | ||
} | ||
throw new ERR_UNKNOWN_BUILTIN_MODULE(id); | ||
} | ||
return require(normalizedId); | ||
} | ||
|
||
return [process, embedderRequire, embedderRunCjs]; |
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 was deleted.
Oops, something went wrong.
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
Oops, something went wrong.