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: https://github.com/nodejs/node/pull/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>
By default, Node.js enables trap-handler-based WebAssembly bound
checks. As a result, V8 does not need to insert inline bound checks
int the code compiled from WebAssembly which may speedup WebAssembly
execution significantly, but this optimization requires allocating
a big virtual memory cage (currently 10GB). If the Node.js process
does not have access to a large enough virtual memory address space
due to system configurations or hardware limitations, users won't
be able to run any WebAssembly that involves allocation in this
virtual memory cage and will see an out-of-memory error.
```console
$ ulimit -v 5000000
$ node -p "new WebAssembly.Memory({ initial: 10, maximum: 100 });"
[eval]:1
new WebAssembly.Memory({ initial: 10, maximum: 100 });
^
RangeError: WebAssembly.Memory(): could not allocate memory
at [eval]:1:1
at runScriptInThisContext (node:internal/vm:209:10)
at node:internal/process/execution:118:14
at [eval]-wrapper:6:24
at runScript (node:internal/process/execution:101:62)
at evalScript (node:internal/process/execution:136:3)
at node:internal/main/eval_string:49:3
```
`--disable-wasm-trap-handler` disables this optimization so that
users can at least run WebAssembly (with a less optimial performance)
when the virtual memory address space available to their Node.js
process is lower than what the V8 WebAssembly memory cage needs.
PR-URL: https://github.com/nodejs/node/pull/52766
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
The V8 WebAssembly trap handler setup for Windows was incorrectly
nested within a POSIX conditional compilation block in src/node.cc.
This caused the related functions to be effectively non-operational
on Windows. The changes involve removing the Windows-specific code from
the POSIX section and correctly placing it under the WIN32 check.
This fix will ensure that the intended exception handling is active
on Windows builds.
Fixes: https://github.com/nodejs/node/issues/52404
Refs: https://github.com/nodejs/node/pull/35033
PR-URL: https://github.com/nodejs/node/pull/52545
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This patch removes support for the `assert` keyword
for import attributes. It was an old variant of the
proposal that was only shipped in V8 and no other
engine, and that has then been replaced by the `with`
keyword.
Chrome is planning to remove support for `assert`
in version 126, which will be released in June.
Node.js already supports the `with` keyword for
import attributes, and this patch does not change that.
PR-URL: https://github.com/nodejs/node/pull/52104
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Previously it would not compile if the build is configured with
--disable-single-executable-application because we use directives
to exclude the definition of SEA-related code completely. This patch
changes them so that the SEA code are still compiled and internals
can still check whether the executable is an SEA. The executable would
not try to load the SEA blob at all if SEA is disabled. If future
modifications to the C++ code attempt to load the SEA blob when SEA
is disabled, UNREACHABLE() would be raised. If user attempt to
generate the SEA blob with --experimental-sea-config with an executable
that disables SEA, they would get an error.
PR-URL: https://github.com/nodejs/node/pull/51808
Fixes: https://github.com/nodejs/node/issues/51730
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
In many cases we can query the environment variable directly instead
of encoding it into UTF8 first and then decoding it again from
UTF8 via an intermediate V8 string.
Drive-by: pass per_process::system_environment explicitly when
the real environment variables are supposed to be used instead of
relying on fallback with defaults.
PR-URL: https://github.com/nodejs/node/pull/51829
Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Previously we wrapped the embedder entry point callback into a
binding and then invoke the binding from JS land which was a bit
convoluted. Now we just call it directly from C++.
The main scripts that needed to tail call the embedder callback now
return the arguments in an array so that the C++ land can extract
the arguments and pass them to the callback. We also set
`PauseOnNextJavascriptStatement()` for --inspect-brk and mark
the bootstrap complete milestone directly in C++ for these
execution modes.
PR-URL: https://github.com/nodejs/node/pull/51557
Reviewed-By: Daniel Lemire <daniel@lemire.me>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
- Add support for --build-snapshot-config which allows passing
snapshot configurations via a JSON configuration file.
- Add support for node::SnapshotConfig in the embedder API
The initial configurable options are:
- "builder" (SnapshotConfig::builder_script_path): path to the
builder script.
- "withoutCodeCache" (SnapshotFlags::kWithoutCodeCache): disable
code cache generation.
PR-URL: https://github.com/nodejs/node/pull/50453
Refs: https://github.com/nodejs/node/issues/42566
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
This patch implements a debugging flag that dumps the current
stack trace when a promise is created or resolved. To reduce
noise we ignore before and after events (as the execution is
less interesting) and use the per-isolate hook to avoid extra
JS frames. This flag can assist work in reducing unnecessary
promise overhead.
PR-URL: https://github.com/nodejs/node/pull/50899
Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Vinícius Lourenço Claro Cardoso <contact@viniciusl.com.br>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
To improve determinism of snapshot generation, add --predictable
to the V8 flags used to initialize a process launched to generate
snapshot. Also add a kGeneratePredictableSnapshot flag
to ProcessInitializationFlags for this and moves the configuration
of these flags into node::InitializeOncePerProcess() so that
it can be shared by embedders.
PR-URL: https://github.com/nodejs/node/pull/48749
Refs: https://github.com/nodejs/build/issues/3043
Reviewed-By: Richard Lau <rlau@redhat.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Previously when we fail to initialize ICU data, the error message is
```
could not initialize ICU (check NODE_ICU_DATA or --icu-data-dir
parameters)
```
This patch updates it to something similar to:
```
U_FILE_ACCESS_ERROR: Could not initialize ICU. Check the directory
specified by NODE_ICU_DATA or --icu-data-dir contains icudt73l.dat
and it's readable
```
Where the expected data file name is the same as U_ICUDATA_NAME.
PR-URL: https://github.com/nodejs/node/pull/49666
Reviewed-By: Richard Lau <rlau@redhat.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
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>
- Run the embedder entry point directly through
runEmbedderEntryPoint(), instead of going through another
JS -> C++ trip through the function returned by
getEmbedderEntryFunction()
- For --build-snapshot, read the snapshot script code directly in C++
and pass it to SnapshotBuilder::Generate(), this makes the entry point
more explicit instead of hiding it in JS land, and also makes it
possible to invoke SnapshotBuilder::Generate() internally to create
a custom snapshot.
- Previously we used process.execPath for the embedder to create
__filename and __dirname in the snapshot builder script while using
process.argv[1] for --build-snapshot (where it's always set) which
results in inconsistencies. We now require the embedder to also set
args[1] when creating the Environment if they intend to run snapshot
scripts with a context that contains __filename and __dirname, which
would be derived from args[1]. If they prefer not to include
build-time paths in the snapshot, we now provide
node::GetAnonymousMainPath() as an alternative.
PR-URL: https://github.com/nodejs/node/pull/48242
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
I recently discovered that the custom NodeJS specific OpenSSL
config section in openssl.cnf would not be respected, if the
environment variable `NODE_EXTRA_CA_CERTS` was set.
This happens even if it contains an invalid value, i.e no actual
certs are read.
Someone suggested moving the checking of extra ca certs to after
the OpenSSL config is read, and this seems to work.
PR-URL: https://github.com/nodejs/node/pull/48159
Reviewed-By: Richard Lau <rlau@redhat.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
Previously we modify the CLI options store to indicate whether the
isolate is created for building snapshot, which is a bit hacky and
makes it difficult to tell whether the snapshot is built from the
command line or through other APIs. This patch adds
is_building_snapshot to IsolateData and use this instead when we
need to know whether the isolate is created for building snapshot
(but do not care about where that request is coming from).
PR-URL: https://github.com/nodejs/node/pull/47887
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
The pattern of getting the address of the element at index 0 of a
container is generally used to materialize a pointer to the backing
data of a container, however `std::string` and `std::vector`
provide a `data()` accessor to retrieve the data pointer which
should be preferred.
This also ensures that in the case that the container is empty, the
data pointer access does not perform an errant memory access.
PR-URL: https://github.com/nodejs/node/pull/47750
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Daeyeon Jeong <daeyeon.dev@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
The only bad handler value we can inhert from before exec is SIG_IGN
(any actual function pointer is reset to SIG_DFL during exec).
If that's the case, we want to reset it back to SIG_DFL.
However, it's also possible that an embeder (or an LD_PRELOAD-ed
library) has set up own signal handler for own purposes
(e.g. profiling). If that's the case, keep it intact.
Fix#47013
PR-URL: https://github.com/nodejs/node/pull/47188
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Since SEA is very similar in principle to embedding functionality,
it makes sense to share code paths where possible. This commit does
so and addresses a `TODO` while doing so.
It also adds a utility to directly run CJS code to the embedder
startup callback, which comes in handy for this purpose.
Finally, this commit is breaking because it aligns the behavior
of `require()`ing internal modules; previously, embedders could
use the `require` function that they received to do so.
(If this is not considered breaking because accessing internals
is not covered by the API, then this would need ABI compatibility
patches for becoming fully non-breaking.)
PR-URL: https://github.com/nodejs/node/pull/46825
Reviewed-By: Darshan Sen <raisinten@gmail.com>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>