Skip to content

fix(loader): preserve resolved format for extensionless entrypoints - #300

Open
pabloerhard wants to merge 5 commits into
nodejs:mainfrom
pabloerhard:pabloerhard/fix-extensionless-esm-entrypoints
Open

pabloerhard wants to merge 5 commits into
nodejs:mainfrom
pabloerhard:pabloerhard/fix-extensionless-esm-entrypoints

Conversation

@pabloerhard

@pabloerhard pabloerhard commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Problem

When IITM resolves an extensionless entrypoint, such as a CLI file in bin/, it always reports the format as commonjs.

Node 18.19+ and 20.10+ can now resolve extensionless entrypoints as ESM, but IITM still overrides that result. TypeScript 7's bin/tsc is in a "type": "module" package. With IITM active, Node loads it as CommonJS and fails with ERR_REQUIRE_CYCLE_MODULE.

Fix

Use commonjs only when the resolver before IITM didn't return a format:

return { ...result, format: result.format ?? 'commonjs' }

Resolves: DataDog/dd-trace-js#10533

Keep the CommonJS fallback only when the upstream resolver supplies no
format. This prevents extensionless ESM CLI launchers, such as TypeScript
7's tsc, from being loaded as CommonJS and triggering
ERR_REQUIRE_CYCLE_MODULE.

Add regression coverage for extensionless ESM and CommonJS entrypoints
with asynchronous and synchronous loader hooks.
Native extensionless ESM support starts in Node 18.19 and 20.10. Keep
that case on supported runtimes and exercise upstream-resolved ESM
formats on older runtimes instead.

Compose the asynchronous test loader directly to also cover Node 18.5,
which predates loader chaining. Retain CommonJS entrypoint coverage
across all supported runtimes.
Test the latest TypeScript in its own dependency tree so compiler-API
consumers can use supported peer versions. Separate Remix's TypeScript 5
peer from the TypeScript 6 peer shared by SvelteKit and typescript-estree.

Retain all 250 baseline and instrumented export comparisons. Replace
generated manifests on reruns and fail immediately if installation
fails, rather than testing an incomplete dependency tree.
Install every dependency group in sibling directories so no tree resolves
packages from another one's node_modules, and define the groups in a single
table. Pin the shared TypeScript peer to ~6.0.0 because typescript-estree
rejects 6.1, and drop stale lockfiles before reinstalling.
@pabloerhard
pabloerhard marked this pull request as ready for review October 5, 2026 17:32
Comment thread create-hook.mjs Outdated
Return only the URL and format for extensionless entrypoints, matching
the original result shape. The other resolve fields are not needed
once the upstream format is preserved.
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.

[FEATURE]: Support TypeScript 7

3 participants