diff --git a/sources/corepackUtils.ts b/sources/corepackUtils.ts index 5f44f72..48549e4 100644 --- a/sources/corepackUtils.ts +++ b/sources/corepackUtils.ts @@ -2,6 +2,7 @@ import {createHash} from 'crypto'; import {once} from 'events'; import fs from 'fs'; import type {Dir} from 'fs'; +import Module from 'module'; import path from 'path'; import semver from 'semver'; @@ -214,5 +215,10 @@ export async function runVersion(locator: Locator, installSpec: { location: stri ]; process.execArgv = []; - return nodeUtils.loadMainModule(binPath); + // Unset the mainModule and let Node.js set it when needed. + process.mainModule = undefined; + + // Use nextTick to unwind the stack, and consequently remove Corepack from + // the stack trace of the package manager. + process.nextTick(Module.runMain, binPath); } diff --git a/sources/module.d.ts b/sources/module.d.ts deleted file mode 100644 index d696c28..0000000 --- a/sources/module.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import 'module'; - -declare module 'module' { - const _cache: {[p: string]: NodeModule}; - - function _nodeModulePaths(from: string): Array; - function _resolveFilename(request: string, parent: NodeModule | null | undefined, isMain: boolean): string; -} - -declare global { - namespace NodeJS { - interface Module { - load(path: string): void; - } - } -} diff --git a/sources/nodeUtils.ts b/sources/nodeUtils.ts index 4c40cd6..14b7c82 100644 --- a/sources/nodeUtils.ts +++ b/sources/nodeUtils.ts @@ -1,30 +1,3 @@ -import Module from 'module'; -import path from 'path'; - -/** - * Loads a module as a main module, enabling the `require.main === module` pattern. - */ -export function loadMainModule(id: string): void { - const modulePath = Module._resolveFilename(id, null, true); - - const module = new Module(modulePath, undefined); - - module.filename = modulePath; - module.paths = Module._nodeModulePaths(path.dirname(modulePath)); - - Module._cache[modulePath] = module; - - process.mainModule = module; - module.id = `.`; - - try { - return module.load(modulePath); - } catch (error) { - delete Module._cache[modulePath]; - throw error; - } -} - export interface NodeError extends Error { code: string; } diff --git a/tests/main.test.ts b/tests/main.test.ts index 94a5c39..cfdf0cd 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -560,7 +560,10 @@ it(`should not override the package manager exit code`, async () => { }); }); -it(`should not override the package manager exit code when it throws`, async () => { +it(`should not preserve the process.exitCode when a package manager throws`, async () => { + // Node.js doesn't preserve process.exitCode when an exception is thrown + // so we need to make sure we don't break this behaviour. + await xfs.mktempPromise(async cwd => { await xfs.writeJsonPromise(ppath.join(cwd, `package.json` as Filename), { packageManager: `yarn@2.2.2`, @@ -575,9 +578,9 @@ it(`should not override the package manager exit code when it throws`, async () `); await expect(runCli(cwd, [`yarn`, `--version`])).resolves.toMatchObject({ - exitCode: 42, - stdout: expect.stringContaining(`foo`), - stderr: ``, + exitCode: 1, + stdout: ``, + stderr: expect.stringContaining(`foo`), }); }); }); @@ -606,3 +609,28 @@ it(`should not set the exit code after successfully launching the package manage }); }); }); + +it(`should support package managers in ESM format`, async () => { + await xfs.mktempPromise(async cwd => { + await xfs.writeJsonPromise(ppath.join(cwd, `package.json` as Filename), { + packageManager: `yarn@2.2.2`, + }); + + const yarnDir = ppath.join(npath.toPortablePath(process.env.COREPACK_HOME!), `yarn/2.2.2` as PortablePath); + + await xfs.mkdirPromise(yarnDir, {recursive: true}); + await xfs.writeFilePromise(ppath.join(yarnDir, `yarn.js` as PortablePath), ` + import 'fs'; + console.log(42); + `); + await xfs.writeJsonPromise(ppath.join(yarnDir, `package.json` as PortablePath), { + type: `module`, + }); + + await expect(runCli(cwd, [`yarn`, `--version`])).resolves.toMatchObject({ + exitCode: 0, + stdout: `42\n`, + stderr: ``, + }); + }); +}); diff --git a/tests/nock/6YlkCvzyrFlW9WizGIO9AA-1.dat b/tests/nock/6YlkCvzyrFlW9WizGIO9AA-1.dat new file mode 100644 index 0000000..5403d9e Binary files /dev/null and b/tests/nock/6YlkCvzyrFlW9WizGIO9AA-1.dat differ diff --git a/tests/nock/urO1i4GpxQt29UQLMf23wA-1.dat b/tests/nock/urO1i4GpxQt29UQLMf23wA-1.dat new file mode 100644 index 0000000..5403d9e Binary files /dev/null and b/tests/nock/urO1i4GpxQt29UQLMf23wA-1.dat differ