Skip to content

[Bug?]: CJS loader error caught in PnP is different from expected #4016

@swandir

Description

@swandir

Self-service

  • I'd be willing to implement a fix

Describe the bug

Some packages implementing custom module loaders for Node.js rely on errors thrown by builtin CJS loader to detect if a module needs transpiling.

See this PR in esbuild-register and an issue in esm referenced there: egoist/esbuild-register#18

Though it fails when is running in PnP mode.

The reason is that the error caught is different for some reason: instead of an error with code ERR_REQUIRE_ESM it's a SyntaxError with message Cannot use import statement outside a module.

The issue manifests itself for external "type": "module" dependencies, e.g. node-fetch.
For workspace dependencies the error is the same as expected. Same with nodeLinker: node-modules.

To reproduce

const fs = require("fs/promises");

await fs.writeFile("package.json", `\
{
  "workspaces": ["dep"],
  "dependencies": {
    "dep": "workspace:*",
    "node-fetch": "^3.2.0"
  }
}
`)


await fs.writeFile("loader.js", `\
const { Module } = require("module");

const original = Module._extensions[".js"];
Module._extensions[".js"] = function (module, filename) {
  try {
    return original.call(this, module, filename);
  } catch (e) {
    console.log(e.code ?? "undefined");
    process.exit(0);
  }
};
`)

await fs.writeFile("dep.js", `\
require("./loader");
require("dep");
`)

await fs.writeFile("node-fetch.js", `\
require("./loader");
require("node-fetch");
`)

await fs.mkdir("dep");

await fs.writeFile("dep/package.json", `\
{
  "name": "dep",
  "type": "module"
}
`)

await fs.writeFile("dep/index.js", `\
import "fs";
`)


// The assertion below won't fail with node-modules linker
// await global.yarn("config", "set", "nodeLinker", "node-modules");

await global.yarn();

// This one works as expected
expect(
  (await global.yarn("node", "dep.js")).trim()
).toBe("ERR_REQUIRE_ESM");

// This one fails
expect(
  (await global.yarn("node", "node-fetch.js")).trim()
).toBe("ERR_REQUIRE_ESM");

Environment

System:
    OS: macOS 12.1
    CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
  Binaries:
    Node: 17.4.0 - /private/var/folders/4z/nlhtwc4s6psgn6y7t6zx4dpwlypf3b/T/xfs-38a985a1/node
    Yarn: 3.1.1 - /private/var/folders/4z/nlhtwc4s6psgn6y7t6zx4dpwlypf3b/T/xfs-38a985a1/yarn
    npm: 8.3.1 - /usr/local/bin/npm

Additional context

No response

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingesmreproducibleThis issue can be successfully reproduced

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions