Skip to content

Commit 3978649

Browse files
authored
fix(pnp): support require(esm) (#6639)
**What's the problem this PR addresses?** Node.js supports `require(esm)` now so we can avoid throwing an error if support is enabled. Fixes #6336 Ref nodejs/citgm#1086 **How did you fix it?** Avoid throwing `ERR_REQUIRE_ESM` if `process.features.require_module` is truthy. **Checklist** - [x] I have read the [Contributing Guide](https://yarnpkg.com/advanced/contributing). - [x] I have set the packages that need to be released for my changes to be effective. - [x] I will check that all automated PR checks pass before the PR gets reviewed.
1 parent 8bfe2d5 commit 3978649

File tree

5 files changed

+116
-26
lines changed

5 files changed

+116
-26
lines changed

.pnp.cjs

Lines changed: 13 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.yarn/versions/9630a917.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
releases:
2+
"@yarnpkg/cli": patch
3+
"@yarnpkg/plugin-pnp": patch
4+
"@yarnpkg/pnp": patch
5+
6+
declined:
7+
- "@yarnpkg/plugin-compat"
8+
- "@yarnpkg/plugin-constraints"
9+
- "@yarnpkg/plugin-dlx"
10+
- "@yarnpkg/plugin-essentials"
11+
- "@yarnpkg/plugin-init"
12+
- "@yarnpkg/plugin-interactive-tools"
13+
- "@yarnpkg/plugin-nm"
14+
- "@yarnpkg/plugin-npm-cli"
15+
- "@yarnpkg/plugin-pack"
16+
- "@yarnpkg/plugin-patch"
17+
- "@yarnpkg/plugin-pnpm"
18+
- "@yarnpkg/plugin-stage"
19+
- "@yarnpkg/plugin-typescript"
20+
- "@yarnpkg/plugin-version"
21+
- "@yarnpkg/plugin-workspace-tools"
22+
- "@yarnpkg/builder"
23+
- "@yarnpkg/core"
24+
- "@yarnpkg/doctor"
25+
- "@yarnpkg/nm"
26+
- "@yarnpkg/pnpify"
27+
- "@yarnpkg/sdks"

packages/acceptance-tests/pkg-tests-specs/sources/pnp-esm.test.ts

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,8 @@ describe(`Plug'n'Play - ESM`, () => {
613613
),
614614
);
615615

616-
test(
616+
// @ts-expect-error - Missing types
617+
(process.features.require_module ? it.skip : it)(
617618
`it should throw ERR_REQUIRE_ESM when requiring a file with type=module`,
618619
makeTemporaryEnv(
619620
{
@@ -643,7 +644,36 @@ describe(`Plug'n'Play - ESM`, () => {
643644
),
644645
);
645646

646-
test(
647+
// @ts-expect-error - Missing types
648+
(process.features.require_module ? it : it.skip)(
649+
`it should not throw ERR_REQUIRE_ESM when requiring a file with type=module`,
650+
makeTemporaryEnv(
651+
{
652+
dependencies: {
653+
'no-deps-esm': `1.0.0`,
654+
},
655+
},
656+
{
657+
pnpEnableEsmLoader: true,
658+
},
659+
async ({path, run, source}) => {
660+
await run(`install`);
661+
662+
await xfs.writeFilePromise(ppath.join(path, `index.js`), `
663+
require('no-deps-esm')
664+
console.log('ESM required')
665+
`);
666+
667+
await expect(run(`node`, `index.js`)).resolves.toMatchObject({
668+
code: 0,
669+
stdout: `ESM required\n`,
670+
});
671+
},
672+
),
673+
);
674+
675+
// @ts-expect-error - Missing types
676+
(process.features.require_module ? it.skip : it)(
647677
`it should throw ERR_REQUIRE_ESM when requiring a .mjs file`,
648678
makeTemporaryEnv(
649679
{
@@ -673,6 +703,34 @@ describe(`Plug'n'Play - ESM`, () => {
673703
),
674704
);
675705

706+
// @ts-expect-error - Missing types
707+
(process.features.require_module ? it : it.skip)(
708+
`it should not throw ERR_REQUIRE_ESM when requiring a .mjs file`,
709+
makeTemporaryEnv(
710+
{
711+
dependencies: {
712+
'no-deps-mjs': `1.0.0`,
713+
},
714+
},
715+
{
716+
pnpEnableEsmLoader: true,
717+
},
718+
async ({path, run, source}) => {
719+
await run(`install`);
720+
721+
await xfs.writeFilePromise(ppath.join(path, `index.js`), `
722+
require('no-deps-mjs/index.mjs')
723+
console.log('ESM required')
724+
`);
725+
726+
await expect(run(`node`, `index.js`)).resolves.toMatchObject({
727+
code: 0,
728+
stdout: `ESM required\n`,
729+
});
730+
},
731+
),
732+
);
733+
676734
test(
677735
`it should throw ERR_MODULE_NOT_FOUND when statically importing a nonexistent file`,
678736
makeTemporaryEnv(

packages/yarnpkg-pnp/sources/hook.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/yarnpkg-pnp/sources/loader/applyPatch.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -275,20 +275,23 @@ export function applyPatch(pnpapi: PnpApi, opts: ApplyPatchOptions) {
275275
return false;
276276
};
277277

278-
// https://github.com/nodejs/node/blob/3743406b0a44e13de491c8590386a964dbe327bb/lib/internal/modules/cjs/loader.js#L1110-L1154
279-
const originalExtensionJSFunction = Module._extensions[`.js`] as (module: NodeModule, filename: string) => void;
280-
Module._extensions[`.js`] = function (module: NodeModule, filename: string) {
281-
if (filename.endsWith(`.js`)) {
282-
const pkg = nodeUtils.readPackageScope(filename);
283-
if (pkg && pkg.data?.type === `module`) {
284-
const err = nodeUtils.ERR_REQUIRE_ESM(filename, module.parent?.filename);
285-
Error.captureStackTrace(err);
286-
throw err;
278+
// @ts-expect-error - Missing types
279+
if (!process.features.require_module) {
280+
// https://github.com/nodejs/node/blob/3743406b0a44e13de491c8590386a964dbe327bb/lib/internal/modules/cjs/loader.js#L1110-L1154
281+
const originalExtensionJSFunction = Module._extensions[`.js`] as (module: NodeModule, filename: string) => void;
282+
Module._extensions[`.js`] = function (module: NodeModule, filename: string) {
283+
if (filename.endsWith(`.js`)) {
284+
const pkg = nodeUtils.readPackageScope(filename);
285+
if (pkg && pkg.data?.type === `module`) {
286+
const err = nodeUtils.ERR_REQUIRE_ESM(filename, module.parent?.filename);
287+
Error.captureStackTrace(err);
288+
throw err;
289+
}
287290
}
288-
}
289291

290-
originalExtensionJSFunction.call(this, module, filename);
291-
};
292+
originalExtensionJSFunction.call(this, module, filename);
293+
};
294+
}
292295

293296
const originalDlopen = process.dlopen;
294297
process.dlopen = function (...args) {

0 commit comments

Comments
 (0)