Skip to content

Commit 3a6d43d

Browse files
jlenon7alexfernandez
authored andcommitted
util: add getCwdSafe internal util fn
This function was first implemented in nodejs#46826, but at some point of the PR implementation this fn was no longer related to the PR. Refs: nodejs#46826 (comment) PR-URL: nodejs#48434 Reviewed-By: Jacob Smith <[email protected]> Reviewed-By: Yagiz Nizipli <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]>
1 parent cefe957 commit 3a6d43d

File tree

4 files changed

+37
-22
lines changed

4 files changed

+37
-22
lines changed

lib/internal/modules/esm/resolve.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const experimentalNetworkImports =
3737
getOptionValue('--experimental-network-imports');
3838
const typeFlag = getOptionValue('--input-type');
3939
const { URL, pathToFileURL, fileURLToPath, isURL } = require('internal/url');
40+
const { getCWDURL } = require('internal/util');
4041
const { canParse: URLCanParse } = internalBinding('url');
4142
const { legacyMainResolve: FSLegacyMainResolve } = internalBinding('fs');
4243
const {
@@ -1095,7 +1096,7 @@ function defaultResolve(specifier, context = {}) {
10951096

10961097
const isMain = parentURL === undefined;
10971098
if (isMain) {
1098-
parentURL = pathToFileURL(`${process.cwd()}/`).href;
1099+
parentURL = getCWDURL().href;
10991100

11001101
// This is the initial entry point to the program, and --input-type has
11011102
// been passed as an option; but --input-type can only be used with

lib/internal/modules/esm/utils.js

+2-11
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const {
2121
loadPreloadModules,
2222
initializeFrozenIntrinsics,
2323
} = require('internal/process/pre_execution');
24-
const { pathToFileURL } = require('internal/url');
24+
const { getCWDURL } = require('internal/util');
2525
const {
2626
setImportModuleDynamicallyCallback,
2727
setInitializeImportMetaObjectCallback,
@@ -195,15 +195,6 @@ function isLoaderWorker() {
195195
async function initializeHooks() {
196196
const customLoaderURLs = getOptionValue('--experimental-loader');
197197

198-
let cwd;
199-
try {
200-
// `process.cwd()` can fail if the parent directory is deleted while the process runs.
201-
cwd = process.cwd() + '/';
202-
} catch {
203-
cwd = '/';
204-
}
205-
206-
207198
const { Hooks } = require('internal/modules/esm/hooks');
208199
const esmLoader = require('internal/process/esm_loader').esmLoader;
209200

@@ -220,7 +211,7 @@ async function initializeHooks() {
220211
loadPreloadModules();
221212
initializeFrozenIntrinsics();
222213

223-
const parentURL = pathToFileURL(cwd).href;
214+
const parentURL = getCWDURL().href;
224215
for (let i = 0; i < customLoaderURLs.length; i++) {
225216
await hooks.register(
226217
customLoaderURLs[i],

lib/internal/process/esm_loader.js

+2-10
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ const { getOptionValue } = require('internal/options');
99
const {
1010
hasUncaughtExceptionCaptureCallback,
1111
} = require('internal/process/execution');
12-
const { pathToFileURL } = require('internal/url');
13-
const { kEmptyObject } = require('internal/util');
12+
const { kEmptyObject, getCWDURL } = require('internal/util');
1413

1514
let esmLoader;
1615

@@ -23,14 +22,7 @@ module.exports = {
2322
try {
2423
const userImports = getOptionValue('--import');
2524
if (userImports.length > 0) {
26-
let cwd;
27-
try {
28-
// `process.cwd()` can fail if the parent directory is deleted while the process runs.
29-
cwd = process.cwd() + '/';
30-
} catch {
31-
cwd = '/';
32-
}
33-
const parentURL = pathToFileURL(cwd).href;
25+
const parentURL = getCWDURL().href;
3426
await SafePromiseAllReturnVoid(userImports, (specifier) => esmLoader.import(
3527
specifier,
3628
parentURL,

lib/internal/util.js

+31
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,36 @@ function getConstructorOf(obj) {
358358
return null;
359359
}
360360

361+
let cachedURL;
362+
let cachedCWD;
363+
364+
/**
365+
* Get the current working directory while accounting for the possibility that it has been deleted.
366+
* `process.cwd()` can fail if the parent directory is deleted while the process runs.
367+
* @returns {URL} The current working directory or the volume root if it cannot be determined.
368+
*/
369+
function getCWDURL() {
370+
const { sep } = require('path');
371+
const { pathToFileURL } = require('internal/url');
372+
373+
let cwd;
374+
375+
try {
376+
// The implementation of `process.cwd()` already uses proper cache when it can.
377+
// It's a relatively cheap call performance-wise for the most common use case.
378+
cwd = process.cwd();
379+
} catch {
380+
cachedURL ??= pathToFileURL(sep);
381+
}
382+
383+
if (cwd != null && cwd !== cachedCWD) {
384+
cachedURL = pathToFileURL(cwd + sep);
385+
cachedCWD = cwd;
386+
}
387+
388+
return cachedURL;
389+
}
390+
361391
function getSystemErrorName(err) {
362392
const entry = uvErrmapGet(err);
363393
return entry ? entry[0] : `Unknown system error ${err}`;
@@ -853,6 +883,7 @@ module.exports = {
853883
filterDuplicateStrings,
854884
filterOwnProperties,
855885
getConstructorOf,
886+
getCWDURL,
856887
getInternalGlobal,
857888
getSystemErrorMap,
858889
getSystemErrorName,

0 commit comments

Comments
 (0)