diff --git a/packages/pkg-tests/pkg-tests-specs/sources/pnp.js b/packages/pkg-tests/pkg-tests-specs/sources/pnp.js index 3c70197991..9afa12fe06 100644 --- a/packages/pkg-tests/pkg-tests-specs/sources/pnp.js +++ b/packages/pkg-tests/pkg-tests-specs/sources/pnp.js @@ -460,6 +460,108 @@ module.exports = makeTemporaryEnv => { ), ); + test( + `it should support the 'paths' option from require.resolve (same dependency tree)`, + makeTemporaryEnv( + { + private: true, + workspaces: [`workspace-*`], + }, + { + plugNPlay: true, + }, + async ({path, run, source}) => { + await writeJson(`${path}/workspace-a/package.json`, { + name: `workspace-a`, + version: `1.0.0`, + dependencies: {[`no-deps`]: `1.0.0`}, + }); + + await writeJson(`${path}/workspace-b/package.json`, { + name: `workspace-b`, + version: `1.0.0`, + dependencies: {[`no-deps`]: `2.0.0`, [`one-fixed-dep`]: `1.0.0`}, + }); + + await run(`install`); + + await expect( + source( + `require(require.resolve('no-deps', {paths: ${JSON.stringify([ + `${path}/workspace-a`, + `${path}/workspace-b`, + ])}}))`, + ), + ).resolves.toMatchObject({ + name: `no-deps`, + version: `1.0.0`, + }); + }, + ), + ); + + // Skipped because not supported (we can't require files from within other dependency trees, since we couldn't + // reconcile them together: dependency tree A could think that package X has deps Y@1 while dependency tree B + // could think that X has deps Y@2 instead. Since they would share the same location on the disk, PnP wouldn't + // be able to tell which one should be used) + test.skip( + `it should support the 'paths' option from require.resolve (different dependency trees)`, + makeTemporaryEnv( + { + dependencies: {}, + }, + { + plugNPlay: true, + }, + async ({path, run, source}) => { + await run(`install`); + + const tmpA = await createTemporaryFolder(); + const tmpB = await createTemporaryFolder(); + + await writeJson(`${tmpA}/package.json`, { + dependencies: {[`no-deps`]: `1.0.0`}, + }); + + await writeJson(`${tmpB}/package.json`, { + dependencies: {[`no-deps`]: `2.0.0`, [`one-fixed-dep`]: `1.0.0`}, + }); + + await run(`install`, { + cwd: tmpA, + }); + + await run(`install`, { + cwd: tmpB, + }); + + await expect( + source(`require(require.resolve('no-deps', {paths: ${JSON.stringify([tmpA, tmpB])}}))`), + ).resolves.toMatchObject({ + name: `no-deps`, + version: `1.0.0`, + }); + }, + ), + ); + + test( + `using require.resolve with unsupported options should throw`, + makeTemporaryEnv( + { + dependencies: {[`no-deps`]: `1.0.0`}, + }, + { + plugNPlay: true, + }, + async ({path, run, source}) => { + await run(`install`); + + await expect(source(`require.resolve('no-deps', {foobar: 42})`)).rejects.toBeTruthy(); + }, + ), + ); + test( `it should load the index.js file when loading from a folder`, makeTemporaryEnv({}, {plugNPlay: true}, async ({path, run, source}) => { diff --git a/src/util/generate-pnp-map-api.tpl.js b/src/util/generate-pnp-map-api.tpl.js index dca837e40b..693b82394a 100644 --- a/src/util/generate-pnp-map-api.tpl.js +++ b/src/util/generate-pnp-map-api.tpl.js @@ -646,15 +646,18 @@ exports.setup = function setup() { if (!enableNativeHooks) { return originalModuleResolveFilename.call(Module, request, parent, isMain, options); } - + let issuers; - + if (options) { - const optionNames = new Set(Object.keys(optionNames)); + const optionNames = new Set(Object.keys(options)); optionNames.delete('paths'); - - if (options.size > 0) { - throw makeError(`UNSUPPORTED`, `Some options passed to require() aren't supported by PnP yet (${Array.from(optionNames).join(', ')})`); + + if (optionNames.size > 0) { + throw makeError( + `UNSUPPORTED`, + `Some options passed to require() aren't supported by PnP yet (${Array.from(optionNames).join(', ')})`, + ); } if (options.paths) { @@ -665,15 +668,15 @@ exports.setup = function setup() { if (!issuers) { const issuerModule = getIssuerModule(parent); const issuer = issuerModule ? issuerModule.filename : `${process.cwd()}/`; - + issuers = [issuer]; } - + let firstError; for (const issuer of issuers) { let resolution; - + try { resolution = exports.resolveRequest(request, issuer); } catch (error) { @@ -683,7 +686,7 @@ exports.setup = function setup() { return resolution !== null ? resolution : request; } - + throw firstError; };