diff --git a/src/library_async.js b/src/library_async.js index 5faa91003ae8b..d2f3a683c28cf 100644 --- a/src/library_async.js +++ b/src/library_async.js @@ -456,7 +456,7 @@ mergeInto(LibraryManager.library, { return Asyncify.handleSleep((wakeUp) => { var _url = UTF8ToString(url); var _file = UTF8ToString(file); - _file = PATH_FS.resolve(FS.cwd(), _file); + _file = PATH_FS.resolve(_file); var destinationDirectory = PATH.dirname(_file); FS.createPreloadedFile( destinationDirectory, diff --git a/src/library_fs.js b/src/library_fs.js index 9e0e5b936bf95..7575f93a2d8a8 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -119,7 +119,7 @@ FS.staticInit();` + // paths // lookupPath: (path, opts = {}) => { - path = PATH_FS.resolve(FS.cwd(), path); + path = PATH_FS.resolve(path); if (!path) return { path: '', node: null }; @@ -133,8 +133,8 @@ FS.staticInit();` + throw new FS.ErrnoError({{{ cDefine('ELOOP') }}}); } - // split the path - var parts = PATH.normalizeArray(path.split('/').filter((p) => !!p), false); + // split the absolute path + var parts = path.split('/').filter((p) => !!p); // start at the root var current = FS.root; diff --git a/src/library_nodepath.js b/src/library_nodepath.js new file mode 100644 index 0000000000000..a995370bc3fbc --- /dev/null +++ b/src/library_nodepath.js @@ -0,0 +1,37 @@ +/** + * @license + * Copyright 2022 The Emscripten Authors + * SPDX-License-Identifier: MIT + */ + +// This implementation ensures that Windows-style paths are being +// used when running on a Windows operating system - see: +// https://nodejs.org/api/path.html#path_windows_vs_posix +// It's only used/needed when linking with `-sNODERAWFS`, as that +// will replace all normal filesystem access with direct Node.js +// operations. Hence, using `nodePath` should be safe here. + +mergeInto(LibraryManager.library, { + $PATH: { + isAbs: (path) => nodePath['isAbsolute'](path), + normalize: (path) => nodePath['normalize'](path), + dirname: (path) => nodePath['dirname'](path), + basename: (path) => nodePath['basename'](path), + join: function () { + return nodePath['join'].apply(null, arguments); + }, + join2: (l, r) => nodePath['join'](l, r), + }, + // The FS-using parts are split out into a separate object, so simple path + // usage does not require the FS. + $PATH_FS__deps: ['$FS'], + $PATH_FS__docs: '/** @type{{resolve: function(...*)}} */', + $PATH_FS: { + resolve: function () { + var paths = Array.prototype.slice.call(arguments, 0); + paths.unshift(FS.cwd()); + return nodePath['posix']['resolve'].apply(null, paths); + }, + relative: (from, to) => nodePath['posix']['relative'](from || FS.cwd(), to || FS.cwd()), + } +}); diff --git a/src/modules.js b/src/modules.js index 42e4203475a3e..5b869f533fe43 100644 --- a/src/modules.js +++ b/src/modules.js @@ -91,6 +91,8 @@ global.LibraryManager = { libraries.push('library_nodefs.js'); } libraries.push('library_noderawfs.js'); + // NODERAWFS overwrites library_path.js + libraries.push('library_nodepath.js'); } } else if (WASMFS) { libraries.push('library_wasmfs.js'); diff --git a/src/settings.js b/src/settings.js index 501d20d7f9610..d09c5f5816c50 100644 --- a/src/settings.js +++ b/src/settings.js @@ -944,8 +944,7 @@ var FORCE_FILESYSTEM = false; // Node.js to access the real local filesystem on your OS, the code will not // 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. This has -// mostly been tested on Linux so far. +// handles permissions and errors and so forth may be noticeable. // [link] var NODERAWFS = false; diff --git a/test/test_other.py b/test/test_other.py index 7b45c1a0f2f07..3e085aae8adb7 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -8457,6 +8457,17 @@ def test_noderawfs_disables_embedding(self): err = self.expect_fail(base + ['--embed-file', 'somefile']) self.assertContained(expected, err) + def test_noderawfs_access_abspath(self): + create_file('foo', 'bar') + create_file('access.c', r''' + #include + int main(int argc, char** argv) { + return access(argv[1], F_OK); + } + ''') + self.run_process([EMCC, 'access.c', '-sNODERAWFS']) + self.run_js('a.out.js', args=[os.path.abspath('foo')]) + @disabled('https://github.com/nodejs/node/issues/18265') def test_node_code_caching(self): self.run_process([EMCC, test_file('hello_world.c'),