Skip to content
Merged
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
4 changes: 4 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ See docs/process.md for more on how version tagging works.
use case. (#25645, #25440)
- The fetch library now supports streaming data requests when
`-sFETCH_STREAMING` is enabled.
- A new `NODE_HOST_ENV` setting was added which exposes the host environment
variables to the generated program, when running under Node. This setting is
enabled by default when `-sNODERAWFS` is used but can also be controlled
separately. (#18820)

4.0.20 - 11/18/25
-----------------
Expand Down
16 changes: 15 additions & 1 deletion site/source/docs/tools_reference/settings_reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1494,7 +1494,7 @@ Default value: false
NODERAWFS
=========

Enables support for the NODERAWFS filesystem backend. This is a special
Enables support for the ``NODERAWFS`` filesystem backend. This is a special
backend as it replaces all normal filesystem access with direct Node.js
operations, without the need to do ``FS.mount()``, and this backend only
works with Node.js. The initial working directory will be same as
Expand All @@ -1504,6 +1504,20 @@ necessarily be portable between OSes - it will be as portable as a Node.js
program would be, which means that differences in how the underlying OS
handles permissions and errors and so forth may be noticeable.

Enabling this setting will also enable :ref:`NODE_HOST_ENV` by default.

Default value: false

.. _node_host_env:

NODE_HOST_ENV
=============

When running under Node, expose the underlying OS environment variables.
This is similar to how ``NODERAWFS`` exposes the underlying FS.
This setting gets enabled by default when ``NODERAWFS`` is enabled, but can
also be controlled separately.

Default value: false

.. _node_code_caching:
Expand Down
6 changes: 6 additions & 0 deletions src/lib/libwasi.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ var WasiLibrary = {
'_': getExecutableName()
#endif
};
#if ENVIRONMENT_MAY_BE_NODE && NODE_HOST_ENV
if (ENVIRONMENT_IS_NODE) {
// When NODE_HOST_ENV is enabled we mirror then entire host environment.
env = process.env;
}
#endif
// Apply the user-provided values, if any.
for (var x in ENV) {
// x is a key in ENV; if ENV[x] is undefined, that means it was
Expand Down
10 changes: 9 additions & 1 deletion src/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -1023,7 +1023,7 @@ var FILESYSTEM = true;
// [link]
var FORCE_FILESYSTEM = false;

// Enables support for the NODERAWFS filesystem backend. This is a special
// Enables support for the ``NODERAWFS`` filesystem backend. This is a special
// backend as it replaces all normal filesystem access with direct Node.js
// operations, without the need to do ``FS.mount()``, and this backend only
// works with Node.js. The initial working directory will be same as
Expand All @@ -1032,9 +1032,17 @@ var FORCE_FILESYSTEM = false;
// necessarily be portable between OSes - it will be as portable as a Node.js
// program would be, which means that differences in how the underlying OS
// handles permissions and errors and so forth may be noticeable.
//
// Enabling this setting will also enable :ref:`NODE_HOST_ENV` by default.
// [link]
var NODERAWFS = false;

// When running under Node, expose the underlying OS environment variables.
// This is similar to how ``NODERAWFS`` exposes the underlying FS.
// This setting gets enabled by default when ``NODERAWFS`` is enabled, but can
// also be controlled separately.
var NODE_HOST_ENV = false;

// This saves the compiled wasm module in a file with name
// ``$WASM_BINARY_NAME.$V8_VERSION.cached``
// and loads it on subsequent runs. This caches the compiled wasm code from
Expand Down
27 changes: 27 additions & 0 deletions test/other/test_std_filesystem_tempdir.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <cassert>
#include <filesystem>
#include <fstream>
#include <iostream>

namespace fs = std::filesystem;

int main() {
// libc++'s temp_directory_path depends on one of these env vars
// being set, and falls back to /tmp as a default.
// Log these values in case this test ever fails:
const char* env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
for (int i = 0; i < sizeof(env_paths)/sizeof(char*); i++) {
const char* p = getenv(env_paths[i]);
std::cout << env_paths[i] << " -> " << (p ? p : "(NULL)") << "\n";
if (p) {
std::cout << env_paths[i] << " exists: " << fs::exists(env_paths[i]) << "\n";
}
}
std::cout << "default /tmp exists: " << fs::exists("/tmp") << "\n";

fs::path tmp{fs::temp_directory_path()};
std::cout << "temp_directory_path: " << tmp << "\n";
assert(fs::exists(tmp));
std::cout << "exists ok!" << "\n";
return 0;
}
1 change: 1 addition & 0 deletions test/other/test_std_filesystem_tempdir.out
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
exists ok!
26 changes: 26 additions & 0 deletions test/test_other.py
Original file line number Diff line number Diff line change
Expand Up @@ -7840,6 +7840,24 @@ def test_override_js_execution_environment(self):
seen = self.run_js('test.js', engine=engine, assert_returncode=NON_ZERO)
self.assertContained('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -sENVIRONMENT=web or -sENVIRONMENT=node', seen)

@requires_node
@with_env_modify({'FOO': 'bar'})
@parameterized({
'': ([], '|(null)|\n'),
'rawfs': (['-sNODERAWFS'], '|bar|\n'),
'rawfs_no_env': (['-sNODERAWFS', '-sNODE_HOST_ENV=0'], '|(null)|\n'),
'enabled': (['-sNODE_HOST_ENV'], '|bar|\n'),
})
def test_node_host_env(self, args, expected):
create_file('src.c', r'''
#include <stdlib.h>
#include <stdio.h>
int main() {
printf("|%s|\n", getenv("FOO"));
}
''')
self.do_runf('src.c', expected, cflags=args)

def test_override_c_environ(self):
create_file('pre.js', r'''
Module.preRun = () => { ENV.hello = '💩 world'; ENV.LANG = undefined; }
Expand Down Expand Up @@ -13644,12 +13662,20 @@ def test_fs_icase(self):
# c++20 for ends_with().
self.do_other_test('test_fs_icase.cpp', cflags=['-sCASE_INSENSITIVE_FS', '-std=c++20'])

@crossplatform
@with_all_fs
def test_std_filesystem(self):
if (WINDOWS or MACOS) and self.get_setting('NODERAWFS'):
self.skipTest('Rawfs directory removal works only on Linux')
self.do_other_test('test_std_filesystem.cpp')

@crossplatform
@with_all_fs
def test_std_filesystem_tempdir(self):
if (WINDOWS or MACOS) and self.get_setting('NODERAWFS') and self.get_setting('WASMFS'):
self.skipTest('NODERAWFS + WASMFS is does not allow access to arbitrary paths')
self.do_other_test('test_std_filesystem_tempdir.cpp', cflags=['-g'])

def test_strict_js_closure(self):
self.do_runf('hello_world.c', cflags=['-sSTRICT_JS', '-Werror=closure', '--closure=1', '-O3'])

Expand Down
15 changes: 14 additions & 1 deletion tools/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -1405,7 +1405,6 @@ def limit_incoming_module_api():
# see https://github.com/emscripten-core/emscripten/issues/18723#issuecomment-1429236996
if settings.MODULARIZE:
default_setting('NODEJS_CATCH_REJECTION', 0)
default_setting('NODEJS_CATCH_EXIT', 0)

if settings.POLYFILL:
# Emscripten requires certain ES6+ constructs by default in library code
Expand Down Expand Up @@ -1884,6 +1883,20 @@ def get_full_import_name(name):
if settings.PTHREADS:
settings.REQUIRED_EXPORTS.append('_emscripten_tls_init')

if settings.NODERAWFS:
default_setting('NODE_HOST_ENV', 1)

if not settings.ENVIRONMENT_MAY_BE_NODE:
# Node-specific settings only make sense if ENVIRONMENT_MAY_BE_NODE
if settings.NODERAWFS:
diagnostics.warning('unused-command-line-argument', 'NODERAWFS ignored since `node` not in `ENVIRONMENT`')
if settings.NODE_CODE_CACHING:
diagnostics.warning('unused-command-line-argument', 'NODE_CODE_CACHING ignored since `node` not in `ENVIRONMENT`')
if settings.NODEJS_CATCH_EXIT:
diagnostics.warning('unused-command-line-argument', 'NODEJS_CATCH_EXIT ignored since `node` not in `ENVIRONMENT`')
if settings.NODEJS_CATCH_REJECTION and 'NODEJS_CATCH_REJECTION' in user_settings:
diagnostics.warning('unused-command-line-argument', 'NODEJS_CATCH_REJECTION ignored since `node` not in `ENVIRONMENT`')

settings.PRE_JS_FILES = options.pre_js
settings.POST_JS_FILES = options.post_js

Expand Down