Skip to content

Commit

Permalink
fix(pnp): resolve virtual paths in process.dlopen
Browse files Browse the repository at this point in the history
  • Loading branch information
merceyz committed Jul 16, 2022
1 parent b8d2315 commit 841f6b3
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 11 deletions.
7 changes: 6 additions & 1 deletion .pnp.cjs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions .yarn/versions/c4427793.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
releases:
"@yarnpkg/cli": patch
"@yarnpkg/plugin-pnp": patch
"@yarnpkg/pnp": patch

declined:
- "@yarnpkg/esbuild-plugin-pnp"
- "@yarnpkg/plugin-compat"
- "@yarnpkg/plugin-constraints"
- "@yarnpkg/plugin-dlx"
- "@yarnpkg/plugin-essentials"
- "@yarnpkg/plugin-init"
- "@yarnpkg/plugin-interactive-tools"
- "@yarnpkg/plugin-nm"
- "@yarnpkg/plugin-npm-cli"
- "@yarnpkg/plugin-pack"
- "@yarnpkg/plugin-patch"
- "@yarnpkg/plugin-pnpm"
- "@yarnpkg/plugin-stage"
- "@yarnpkg/plugin-typescript"
- "@yarnpkg/plugin-version"
- "@yarnpkg/plugin-workspace-tools"
- "@yarnpkg/builder"
- "@yarnpkg/core"
- "@yarnpkg/doctor"
- "@yarnpkg/nm"
- "@yarnpkg/pnpify"
- "@yarnpkg/sdks"
31 changes: 30 additions & 1 deletion packages/acceptance-tests/pkg-tests-specs/sources/pnp.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const {npath, ppath, xfs} = require(`@yarnpkg/fslib`);
const {npath, ppath, xfs, Filename} = require(`@yarnpkg/fslib`);
const cp = require(`child_process`);
const {satisfies} = require(`semver`);

Expand Down Expand Up @@ -2095,4 +2095,33 @@ describe(`Plug'n'Play`, () => {
},
),
);

test(
`it should resolve virtual paths passed to process.dlopen`,
makeTemporaryEnv(
{
dependencies: {
pkg: `portal:./pkg`,
},
},
async ({path, run, source}) => {
await xfs.mkdirPromise(ppath.join(path, `pkg`));
await xfs.writeFilePromise(ppath.join(path, `pkg/test.node`), `invalid`);
await xfs.writeJsonPromise(ppath.join(path, `pkg`, Filename.manifest), {
name: `pkg`,
peerDependencies: {
'no-deps': `*`,
},
});

await expect(run(`install`)).resolves.toMatchObject({code: 0});

await expect(source(`require('pkg/test.node')`)).rejects.toMatchObject({
externalException: {
message: expect.not.stringMatching(/__virtual__|invalid mode/),
},
});
},
),
);
});
2 changes: 1 addition & 1 deletion packages/yarnpkg-pnp/sources/hook.js

Large diffs are not rendered by default.

35 changes: 27 additions & 8 deletions packages/yarnpkg-pnp/sources/loader/applyPatch.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import {FakeFS, PosixFS, npath, patchFs, PortablePath, NativePath} from '@yarnpkg/fslib';
import fs from 'fs';
import {Module} from 'module';
import {URL, fileURLToPath} from 'url';
import {FakeFS, PosixFS, npath, patchFs, PortablePath, NativePath, VirtualFS} from '@yarnpkg/fslib';
import fs from 'fs';
import {Module} from 'module';
import {URL, fileURLToPath} from 'url';

import {PnpApi} from '../types';
import {PnpApi} from '../types';

import {ErrorCode, makeError, getIssuerModule} from './internalTools';
import {Manager} from './makeManager';
import * as nodeUtils from './nodeUtils';
import {ErrorCode, makeError, getIssuerModule} from './internalTools';
import {Manager} from './makeManager';
import * as nodeUtils from './nodeUtils';

export type ApplyPatchOptions = {
fakeFs: FakeFS<PortablePath>;
Expand All @@ -19,6 +19,14 @@ type PatchedModule = Module & {
isLoading?: boolean;
};

declare global {
module NodeJS {
interface Process {
dlopen: (module: Object, filename: string, flags?: number) => void;
}
}
}

export function applyPatch(pnpapi: PnpApi, opts: ApplyPatchOptions) {
/**
* The cache that will be used for all accesses occurring outside of a PnP context.
Expand Down Expand Up @@ -411,6 +419,17 @@ export function applyPatch(pnpapi: PnpApi, opts: ApplyPatchOptions) {
originalExtensionJSFunction.call(this, module, filename);
};

const originalDlopen = process.dlopen;
process.dlopen = function (...args) {
const [module, filename, ...rest] = args;
return originalDlopen.call(
this,
module,
npath.fromPortablePath(VirtualFS.resolveVirtual(npath.toPortablePath(filename))),
...rest,
);
};

// When using the ESM loader Node.js prints either of the following warnings
//
// - ExperimentalWarning: --experimental-loader is an experimental feature. This feature could change at any time
Expand Down

0 comments on commit 841f6b3

Please sign in to comment.