Skip to content

Guard missing require.extensions in match path resolution#289

Open
wojtekmaj wants to merge 1 commit intojonaskello:masterfrom
wojtekmaj:fix-require-extensions-guard
Open

Guard missing require.extensions in match path resolution#289
wojtekmaj wants to merge 1 commit intojonaskello:masterfrom
wojtekmaj:fix-require-extensions-guard

Conversation

@wojtekmaj
Copy link
Copy Markdown

This makes match path resolution tolerate environments where require.extensions is unavailable.

In our case, this surfaced under Node.js 24.15.0 with Yarn 4.14.1 Plug'n'Play, where some CommonJS code paths executed through the ESM loader no longer expose require.extensions. tsconfig-paths then throws while building the default extension list, even though falling back to the standard Node extensions is sufficient.

This change:

  • falls back to [".js", ".json", ".node"] when require.extensions is missing or empty
  • adds regression coverage for both sync and async match-path resolution

I drafted this patch and PR with assistance from OpenAI Codex, then reviewed and validated the changes locally before opening the PR.

Copilot AI review requested due to automatic review settings April 24, 2026 22:48
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates tsconfig-paths match-path resolution to tolerate runtimes where require.extensions is unavailable (e.g., some Node + ESM-loader/PnP scenarios), by falling back to standard Node extensions and adding regression tests.

Changes:

  • Add a safe fallback extension list ([".js", ".json", ".node"]) when require.extensions is missing/empty in sync and async match-path resolution.
  • Add regression tests ensuring sync and async match-path creation/invocation does not throw/fail when require.extensions is unavailable.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
src/match-path-sync.ts Guard default extensions resolution with a fallback list when require.extensions is missing/empty.
src/match-path-async.ts Same fallback logic for async match-path resolution.
src/__tests__/match-path-sync.test.ts Add regression coverage for missing require.extensions in sync path resolution.
src/__tests__/match-path-async.test.ts Add regression coverage for missing require.extensions in async path resolution.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +35 to +46
const matchPath = createMatchPathAsync("/base", {});
matchPath(
"missing-module",
undefined,
undefined,
undefined,
(err, result) => {
expect(err).toBeUndefined();
expect(result).toBeUndefined();
done();
}
);
Comment thread src/match-path-sync.ts
Comment on lines +73 to +75
extensions: Array<string> = Object.keys(require.extensions || {}).length
? Object.keys(require.extensions || {})
: defaultExtensions,
Comment thread src/match-path-sync.ts
Comment on lines +6 to +7
const defaultExtensions = [".js", ".json", ".node"];

Comment thread src/match-path-async.ts
Comment on lines +67 to +70
extensions: ReadonlyArray<string> = Object.keys(require.extensions || {})
.length
? Object.keys(require.extensions || {})
: defaultExtensions,

try {
const matchPath = createMatchPath("/base", {});
expect(() => matchPath("missing-module")).not.toThrow();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants