Skip to content

fix: guard parent access in addTsEsmHook for ESM-to-CJS sub-dependency resolution#1087

Open
setthase wants to merge 1 commit intohapijs:masterfrom
setthase:fix-ts-esm-dep-resolve
Open

fix: guard parent access in addTsEsmHook for ESM-to-CJS sub-dependency resolution#1087
setthase wants to merge 1 commit intohapijs:masterfrom
setthase:fix-ts-esm-dep-resolve

Conversation

@setthase
Copy link

What: Adds a null guard for parent in internals.addTsEsmHook() (lib/cli.js).

Why: When running TypeScript tests (--typescript) in an ESM project that imports from an ESM package with CJS sub-dependencies, the crash path is: require.extensions['.ts']Module._compileloadESMFromCJS → ESM translators → CJS sub-dependency resolution → Module._resolveFilename with parent === undefined. The current code accesses parent.filename unconditionally, causing TypeError: Cannot read properties of undefined (reading 'filename').

Fix: Guard the parent access so that when parent is undefined (ESM-to-CJS transition context), the hook falls through to the original _resolveFilename, which handles the resolution natively.

Test: Added test/cli_typescript_esm_dep/ fixture — a TypeScript ESM test that imports from an ESM package which has a CJS sub-dependency (two-layer structure required to trigger the crash). Without the fix, this crashes. With the fix, it passes.

Ref: fixes #1086

@setthase setthase force-pushed the fix-ts-esm-dep-resolve branch from 4ee1b6d to d7a95fa Compare February 20, 2026 16:12
@kanongil kanongil added the bug Bug or defect label Feb 22, 2026
@setthase setthase force-pushed the fix-ts-esm-dep-resolve branch from d7a95fa to 94fead7 Compare February 23, 2026 10:29
@damusix
Copy link
Contributor

damusix commented Feb 24, 2026

@kanongil this related to ESM coverage by any chance?

Copy link
Contributor

@kanongil kanongil left a comment

Choose a reason for hiding this comment

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

Overall this looks good.

Module._resolveFilename = function (request, parent, ...rest) {

if (request.endsWith('.js') && (parent.filename.endsWith('.ts') || parent.filename.endsWith('.tsx'))) {
if (request.endsWith('.js') && parent && parent.filename && (parent.filename.endsWith('.ts') || parent.filename.endsWith('.tsx'))) {
Copy link
Contributor

Choose a reason for hiding this comment

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

There is no need to guard parent.filename access.

Copy link
Author

Choose a reason for hiding this comment

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

Ah, right... I went too much into defensive mode, it seems 😅

**/.idea

!test/cli_coverage/node_modules
!test/cli_typescript_esm_dep/node_modules
Copy link
Contributor

Choose a reason for hiding this comment

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

Please don't add random stuff here.

Copy link
Author

Choose a reason for hiding this comment

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

I'm a bit confused here... 🤔

If you mean it literally, then I need to explain that this is needed to reproduce the scenario in which the code breaks. Those node_modules are created manually, not installed from registry.

If you speak generally, for future usage, I agree that we shouldn't touch this file or drop anything into those node_modules.

Please clarify: can this stay as is or I need to remove it? If the later, do you have a suggestion how to add tests files that can reproduce this issue?

@kanongil
Copy link
Contributor

@kanongil this related to ESM coverage by any chance?

Not really. ESM coverage was/is? mainly blocked on experimental / unstable hooks into the import logic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Bug or defect

Projects

None yet

Development

Successfully merging this pull request may close these issues.

@hapi/lab crashes when TypeScript tests depend on ESM packages

3 participants