diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js index a320736d1b6fd7..9f719290c21149 100644 --- a/lib/internal/modules/cjs/loader.js +++ b/lib/internal/modules/cjs/loader.js @@ -534,7 +534,6 @@ function tryPackage(requestPath, exts, isMain, originalPath) { err.code = 'MODULE_NOT_FOUND'; err.path = pjsonPath; err.requestPath = originalPath; - // TODO(BridgeAR): Add the requireStack as well. throw err; } else { process.emitWarning( @@ -1406,6 +1405,14 @@ Module._resolveFilename = function(request, parent, isMain, options) { paths = Module._resolveLookupPaths(request, parent); } + const requireStack = []; + for (let cursor = parent; + cursor; + // TODO(joyeecheung): it makes more sense to use kLastModuleParent here. + cursor = cursor[kFirstModuleParent]) { + ArrayPrototypePush(requireStack, cursor.filename || cursor.id); + } + if (request[0] === '#' && (parent?.filename || parent?.id === '')) { const parentPath = parent?.filename ?? process.cwd() + path.sep; const pkg = packageJsonReader.getNearestParentPackageJSON(parentPath); @@ -1419,7 +1426,7 @@ Module._resolveFilename = function(request, parent, isMain, options) { ); } catch (e) { if (e.code === 'ERR_MODULE_NOT_FOUND') { - throw createEsmNotFoundErr(request); + throw createEsmNotFoundErr(request, undefined, requireStack); } throw e; } @@ -1428,7 +1435,15 @@ Module._resolveFilename = function(request, parent, isMain, options) { // Try module self resolution first const parentPath = trySelfParentPath(parent); - const selfResolved = trySelf(parentPath, request, conditions); + let selfResolved; + try { + selfResolved = trySelf(parentPath, request, conditions); + } catch (e) { + if (e.code === 'MODULE_NOT_FOUND' && e.requireStack === undefined) { + e.requireStack = requireStack; + } + throw e; + } if (selfResolved) { const cacheKey = request + '\x00' + (paths.length === 1 ? paths[0] : ArrayPrototypeJoin(paths, '\x00')); @@ -1437,15 +1452,16 @@ Module._resolveFilename = function(request, parent, isMain, options) { } // Look up the filename first, since that's the cache key. - const filename = Module._findPath(request, paths, isMain, conditions); - if (filename) { return filename; } - const requireStack = []; - for (let cursor = parent; - cursor; - // TODO(joyeecheung): it makes more sense to use kLastModuleParent here. - cursor = cursor[kFirstModuleParent]) { - ArrayPrototypePush(requireStack, cursor.filename || cursor.id); + let filename; + try { + filename = Module._findPath(request, paths, isMain, conditions); + } catch (e) { + if (e.code === 'MODULE_NOT_FOUND' && e.requireStack === undefined) { + e.requireStack = requireStack; + } + throw e; } + if (filename) { return filename; } let message = `Cannot find module '${request}'`; if (requireStack.length > 0) { message = message + '\nRequire stack:\n- ' + @@ -1485,16 +1501,19 @@ function finalizeEsmResolution(resolved, parentPath, pkgPath) { * Creates an error object for when a requested ES module cannot be found. * @param {string} request The name of the requested module * @param {string} [path] The path to the requested module + * @param {string[]} [requireStack] The require stack at the time of the error * @returns {Error} */ -function createEsmNotFoundErr(request, path) { +function createEsmNotFoundErr(request, path, requireStack) { // eslint-disable-next-line no-restricted-syntax const err = new Error(`Cannot find module '${request}'`); err.code = 'MODULE_NOT_FOUND'; if (path) { err.path = path; } - // TODO(BridgeAR): Add the requireStack as well. + if (requireStack) { + err.requireStack = requireStack; + } return err; } diff --git a/test/parallel/test-module-loading-error.js b/test/parallel/test-module-loading-error.js index 3496a4104df090..b26e395373e042 100644 --- a/test/parallel/test-module-loading-error.js +++ b/test/parallel/test-module-loading-error.js @@ -91,6 +91,7 @@ assert.throws( () => { require('../fixtures/packages/is-dir'); }, common.isAIX ? { code: 'ERR_INVALID_PACKAGE_CONFIG' } : { code: 'MODULE_NOT_FOUND', - message: /Cannot find module '\.\.\/fixtures\/packages\/is-dir'/ + message: /Cannot find module '\.\.\/fixtures\/packages\/is-dir'/, + requireStack: [__filename], } ); diff --git a/test/sequential/test-module-loading.js b/test/sequential/test-module-loading.js index 1e2efc6fd26a6b..118fcb1ff18d42 100644 --- a/test/sequential/test-module-loading.js +++ b/test/sequential/test-module-loading.js @@ -123,6 +123,7 @@ assert.throws( message: /packages[/\\]missing-main-no-index[/\\]doesnotexist\.js'\. Please.+package\.json.+valid "main"/, path: /fixtures[/\\]packages[/\\]missing-main-no-index[/\\]package\.json/, requestPath: /^\.\.[/\\]fixtures[/\\]packages[/\\]missing-main-no-index$/, + requireStack: [__filename], } );