Skip to content

Commit d497994

Browse files
authored
Merge pull request #271 from webpack/bugfix/270
handle exports field when using PnP
2 parents b7dfc38 + 4232a91 commit d497994

File tree

5 files changed

+60
-31
lines changed

5 files changed

+60
-31
lines changed

lib/PnpPlugin.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,16 @@ module.exports = class PnpPlugin {
3939
// The trailing slash indicates to PnP that this value is a folder rather than a file
4040
const issuer = `${request.path}/`;
4141

42+
const packageMatch = /^(@[^/]+\/)?[^/]+/.exec(req);
43+
if (!packageMatch) return callback();
44+
45+
const packageName = packageMatch[0];
46+
const innerRequest = `.${req.slice(packageName.length)}`;
47+
4248
let resolution;
4349
let apiResolution;
4450
try {
45-
resolution = this.pnpApi.resolveToUnqualified(req, issuer, {
51+
resolution = this.pnpApi.resolveToUnqualified(packageName, issuer, {
4652
considerBuiltins: false
4753
});
4854
if (resolveContext.fileDependencies) {
@@ -67,7 +73,7 @@ module.exports = class PnpPlugin {
6773
return callback(error);
6874
}
6975

70-
if (resolution === req) return callback();
76+
if (resolution === packageName) return callback();
7177

7278
if (apiResolution && resolveContext.fileDependencies) {
7379
resolveContext.fileDependencies.add(apiResolution);
@@ -76,10 +82,9 @@ module.exports = class PnpPlugin {
7682
const obj = {
7783
...request,
7884
path: resolution,
79-
request: undefined,
85+
request: innerRequest,
8086
ignoreSymlinks: true,
81-
fullySpecified:
82-
request.fullySpecified && !/^(@[^/]+\/)?[^/]+$/.test(req)
87+
fullySpecified: request.fullySpecified && innerRequest !== "."
8388
};
8489
resolver.doResolve(
8590
target,

lib/ResolverFactory.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,9 @@ exports.createResolver = function (options) {
395395
new ModulesInHierachicDirectoriesPlugin("raw-module", item, "module")
396396
);
397397
if (item.includes("node_modules") && pnpApi) {
398-
plugins.push(new PnpPlugin("raw-module", pnpApi, "relative"));
398+
plugins.push(
399+
new PnpPlugin("raw-module", pnpApi, "undescribed-resolve-in-package")
400+
);
399401
}
400402
} else {
401403
plugins.push(new ModulesInRootPlugin("raw-module", item, "module"));

test/fixtures/pnp/pkg3/a.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = 1;

test/fixtures/pnp/pkg3/package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "@exports-field/core",
3+
"version": "1.0.0",
4+
"exports": {
5+
".": "./a.js",
6+
"./x": "./a.js"
7+
}
8+
}

test/pnp.js

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -72,28 +72,22 @@ describe("pnp", () => {
7272
});
7373
});
7474
it("should resolve by going through the pnp api", done => {
75-
pnpApi.mocks.set(
76-
"pkg/dir/index.js",
77-
path.resolve(fixture, "pkg/dir/index.js")
78-
);
75+
pnpApi.mocks.set("pkg", path.resolve(fixture, "pkg"));
7976
resolver.resolve({}, __dirname, "pkg/dir/index.js", {}, (err, result) => {
8077
if (err) return done(err);
8178
result.should.equal(path.resolve(fixture, "pkg/dir/index.js"));
8279
done();
8380
});
8481
});
8582
it("should not resolve a not fully specified request when fullySpecified is set", done => {
86-
pnpApi.mocks.set("pkg/dir/index", path.resolve(fixture, "pkg/dir/index"));
83+
pnpApi.mocks.set("pkg", path.resolve(fixture, "pkg"));
8784
resolver.resolve({}, __dirname, "pkg/dir/index", {}, (err, result) => {
8885
err.should.be.instanceof(Error);
8986
done();
9087
});
9188
});
9289
it("should track dependency to the pnp api", done => {
93-
pnpApi.mocks.set(
94-
"pkg/dir/index.js",
95-
path.resolve(fixture, "pkg/dir/index.js")
96-
);
90+
pnpApi.mocks.set("pkg", path.resolve(fixture, "pkg"));
9791
pnpApi.mocks.set("pnpapi", path.resolve(fixture, ".pnp.js"));
9892
const fileDependencies = new Set();
9993
resolver.resolve(
@@ -131,7 +125,7 @@ describe("pnp", () => {
131125
"should not resolve symlinks",
132126
isAdmin
133127
? done => {
134-
pnpApi.mocks.set("pkg/symlink", path.resolve(fixture, "pkg/symlink"));
128+
pnpApi.mocks.set("pkg", path.resolve(fixture, "pkg"));
135129
resolverFuzzy.resolve(
136130
{},
137131
__dirname,
@@ -149,10 +143,7 @@ describe("pnp", () => {
149143
: undefined
150144
);
151145
it("should properly deal with other extensions", done => {
152-
pnpApi.mocks.set(
153-
"@user/pkg/typescript",
154-
path.resolve(fixture, "pkg/typescript")
155-
);
146+
pnpApi.mocks.set("@user/pkg", path.resolve(fixture, "pkg"));
156147
resolverFuzzy.resolve(
157148
{},
158149
__dirname,
@@ -166,10 +157,7 @@ describe("pnp", () => {
166157
);
167158
});
168159
it("should properly deal package.json alias", done => {
169-
pnpApi.mocks.set(
170-
"pkg/package-alias",
171-
path.resolve(fixture, "pkg/package-alias")
172-
);
160+
pnpApi.mocks.set("pkg", path.resolve(fixture, "pkg"));
173161
resolverFuzzy.resolve(
174162
{},
175163
__dirname,
@@ -185,7 +173,7 @@ describe("pnp", () => {
185173
);
186174
});
187175
it("should prefer normal modules over pnp resolves", done => {
188-
pnpApi.mocks.set("m1/a.js", path.resolve(fixture, "pkg/a.js"));
176+
pnpApi.mocks.set("m1", path.resolve(fixture, "pkg"));
189177
resolver.resolve(
190178
{},
191179
path.resolve(__dirname, "fixtures"),
@@ -199,10 +187,7 @@ describe("pnp", () => {
199187
);
200188
});
201189
it("should prefer alias over pnp resolves", done => {
202-
pnpApi.mocks.set(
203-
"alias/index.js",
204-
path.resolve(fixture, "pkg/dir/index.js")
205-
);
190+
pnpApi.mocks.set("alias", path.resolve(fixture, "pkg/dir"));
206191
resolver.resolve(
207192
{},
208193
path.resolve(__dirname, "fixtures"),
@@ -216,11 +201,11 @@ describe("pnp", () => {
216201
);
217202
});
218203
it("should prefer pnp over modules after node_modules", done => {
219-
pnpApi.mocks.set("m2/a.js", path.resolve(fixture, "pkg/index.js"));
204+
pnpApi.mocks.set("m2", path.resolve(fixture, "pkg"));
220205
resolver.resolve(
221206
{},
222207
path.resolve(__dirname, "fixtures"),
223-
"m2/a.js",
208+
"m2/index.js",
224209
{},
225210
(err, result) => {
226211
if (err) return done(err);
@@ -242,4 +227,32 @@ describe("pnp", () => {
242227
}
243228
);
244229
});
230+
it("should handle the exports field when using PnP", done => {
231+
pnpApi.mocks.set("m1", path.resolve(fixture, "pkg3"));
232+
resolver.resolve(
233+
{},
234+
path.resolve(__dirname, "fixtures"),
235+
"m1",
236+
{},
237+
(err, result) => {
238+
if (err) return done(err);
239+
result.should.equal(path.resolve(fixture, "pkg3/a.js"));
240+
done();
241+
}
242+
);
243+
});
244+
it("should handle the exports field when using PnP (with sub path)", done => {
245+
pnpApi.mocks.set("@user/m1", path.resolve(fixture, "pkg3"));
246+
resolver.resolve(
247+
{},
248+
path.resolve(__dirname, "fixtures"),
249+
"@user/m1/x",
250+
{},
251+
(err, result) => {
252+
if (err) return done(err);
253+
result.should.equal(path.resolve(fixture, "pkg3/a.js"));
254+
done();
255+
}
256+
);
257+
});
245258
});

0 commit comments

Comments
 (0)