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

+13-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.yarn/versions/9630a917.yml

+27
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

+60-2
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

+1-1
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

+15-12
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy