mirror of https://github.com/webpack/webpack.git
improve resolving of build dependencies when `exports` field is used
This commit is contained in:
parent
cffa1ad189
commit
e2fb89eed1
|
|
@ -27,11 +27,12 @@ const RBDT_RESOLVE_CJS = 0;
|
||||||
const RBDT_RESOLVE_ESM = 1;
|
const RBDT_RESOLVE_ESM = 1;
|
||||||
const RBDT_RESOLVE_DIRECTORY = 2;
|
const RBDT_RESOLVE_DIRECTORY = 2;
|
||||||
const RBDT_RESOLVE_CJS_FILE = 3;
|
const RBDT_RESOLVE_CJS_FILE = 3;
|
||||||
const RBDT_RESOLVE_ESM_FILE = 4;
|
const RBDT_RESOLVE_CJS_FILE_AS_CHILD = 4;
|
||||||
const RBDT_DIRECTORY = 5;
|
const RBDT_RESOLVE_ESM_FILE = 5;
|
||||||
const RBDT_FILE = 6;
|
const RBDT_DIRECTORY = 6;
|
||||||
const RBDT_DIRECTORY_DEPENDENCIES = 7;
|
const RBDT_FILE = 7;
|
||||||
const RBDT_FILE_DEPENDENCIES = 8;
|
const RBDT_DIRECTORY_DEPENDENCIES = 8;
|
||||||
|
const RBDT_FILE_DEPENDENCIES = 9;
|
||||||
|
|
||||||
const INVALID = Symbol("invalid");
|
const INVALID = Symbol("invalid");
|
||||||
|
|
||||||
|
|
@ -1103,15 +1104,23 @@ class FileSystemInfo {
|
||||||
const resolveCjs = createResolver({
|
const resolveCjs = createResolver({
|
||||||
extensions: [".js", ".json", ".node"],
|
extensions: [".js", ".json", ".node"],
|
||||||
conditionNames: ["require", "node"],
|
conditionNames: ["require", "node"],
|
||||||
|
exportsFields: ["exports"],
|
||||||
|
fileSystem: this.fs
|
||||||
|
});
|
||||||
|
const resolveCjsAsChild = createResolver({
|
||||||
|
extensions: [".js", ".json", ".node"],
|
||||||
|
conditionNames: ["require", "node"],
|
||||||
|
exportsFields: [],
|
||||||
fileSystem: this.fs
|
fileSystem: this.fs
|
||||||
});
|
});
|
||||||
const resolveEsm = createResolver({
|
const resolveEsm = createResolver({
|
||||||
extensions: [".js", ".json", ".node"],
|
extensions: [".js", ".json", ".node"],
|
||||||
fullySpecified: true,
|
fullySpecified: true,
|
||||||
conditionNames: ["import", "node"],
|
conditionNames: ["import", "node"],
|
||||||
|
exportsFields: ["exports"],
|
||||||
fileSystem: this.fs
|
fileSystem: this.fs
|
||||||
});
|
});
|
||||||
return { resolveContext, resolveEsm, resolveCjs };
|
return { resolveContext, resolveEsm, resolveCjs, resolveCjsAsChild };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1124,7 +1133,8 @@ class FileSystemInfo {
|
||||||
const {
|
const {
|
||||||
resolveContext,
|
resolveContext,
|
||||||
resolveEsm,
|
resolveEsm,
|
||||||
resolveCjs
|
resolveCjs,
|
||||||
|
resolveCjsAsChild
|
||||||
} = this._createBuildDependenciesResolvers();
|
} = this._createBuildDependenciesResolvers();
|
||||||
|
|
||||||
/** @type {Set<string>} */
|
/** @type {Set<string>} */
|
||||||
|
|
@ -1242,7 +1252,7 @@ class FileSystemInfo {
|
||||||
resolveResults.set(key, result);
|
resolveResults.set(key, result);
|
||||||
} else {
|
} else {
|
||||||
invalidResolveResults.add(key);
|
invalidResolveResults.add(key);
|
||||||
this.logger.debug(
|
this.logger.warn(
|
||||||
`Resolving '${path}' in ${context} for build dependencies doesn't lead to expected result '${expected}', but to '${result}' instead. Resolving dependencies are ignored for this path.\n${pathToString(
|
`Resolving '${path}' in ${context} for build dependencies doesn't lead to expected result '${expected}', but to '${result}' instead. Resolving dependencies are ignored for this path.\n${pathToString(
|
||||||
job
|
job
|
||||||
)}`
|
)}`
|
||||||
|
|
@ -1299,6 +1309,10 @@ class FileSystemInfo {
|
||||||
resolveFile(path, "f", resolveCjs);
|
resolveFile(path, "f", resolveCjs);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case RBDT_RESOLVE_CJS_FILE_AS_CHILD: {
|
||||||
|
resolveFile(path, "c", resolveCjsAsChild);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case RBDT_RESOLVE_ESM_FILE: {
|
case RBDT_RESOLVE_ESM_FILE: {
|
||||||
resolveFile(path, "e", resolveEsm);
|
resolveFile(path, "e", resolveEsm);
|
||||||
break;
|
break;
|
||||||
|
|
@ -1378,11 +1392,29 @@ class FileSystemInfo {
|
||||||
const context = dirname(this.fs, path);
|
const context = dirname(this.fs, path);
|
||||||
for (const modulePath of module.paths) {
|
for (const modulePath of module.paths) {
|
||||||
if (childPath.startsWith(modulePath)) {
|
if (childPath.startsWith(modulePath)) {
|
||||||
let request = childPath.slice(modulePath.length + 1);
|
let subPath = childPath.slice(modulePath.length + 1);
|
||||||
|
const packageMatch = /^(@[^\\/]+[\\/])[^\\/]+/.exec(
|
||||||
|
subPath
|
||||||
|
);
|
||||||
|
if (packageMatch) {
|
||||||
|
push({
|
||||||
|
type: RBDT_FILE,
|
||||||
|
context: undefined,
|
||||||
|
path:
|
||||||
|
modulePath +
|
||||||
|
childPath[modulePath.length] +
|
||||||
|
packageMatch[0] +
|
||||||
|
childPath[modulePath.length] +
|
||||||
|
"package.json",
|
||||||
|
expected: false,
|
||||||
|
issuer: job
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let request = subPath.replace(/\\/g, "/");
|
||||||
if (request.endsWith(".js"))
|
if (request.endsWith(".js"))
|
||||||
request = request.slice(0, -3);
|
request = request.slice(0, -3);
|
||||||
push({
|
push({
|
||||||
type: RBDT_RESOLVE_CJS_FILE,
|
type: RBDT_RESOLVE_CJS_FILE_AS_CHILD,
|
||||||
context,
|
context,
|
||||||
path: request,
|
path: request,
|
||||||
expected: child.filename,
|
expected: child.filename,
|
||||||
|
|
@ -1573,6 +1605,7 @@ class FileSystemInfo {
|
||||||
checkResolveResultsValid(resolveResults, callback) {
|
checkResolveResultsValid(resolveResults, callback) {
|
||||||
const {
|
const {
|
||||||
resolveCjs,
|
resolveCjs,
|
||||||
|
resolveCjsAsChild,
|
||||||
resolveEsm,
|
resolveEsm,
|
||||||
resolveContext
|
resolveContext
|
||||||
} = this._createBuildDependenciesResolvers();
|
} = this._createBuildDependenciesResolvers();
|
||||||
|
|
@ -1600,6 +1633,15 @@ class FileSystemInfo {
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
case "c":
|
||||||
|
resolveCjsAsChild(context, path, {}, (err, result) => {
|
||||||
|
if (expectedResult === false)
|
||||||
|
return callback(err ? undefined : INVALID);
|
||||||
|
if (err) return callback(err);
|
||||||
|
if (result !== expectedResult) return callback(INVALID);
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
break;
|
||||||
case "e":
|
case "e":
|
||||||
resolveEsm(context, path, {}, (err, result) => {
|
resolveEsm(context, path, {}, (err, result) => {
|
||||||
if (expectedResult === false)
|
if (expectedResult === false)
|
||||||
|
|
|
||||||
|
|
@ -99,10 +99,14 @@ describe("BuildDependencies", () => {
|
||||||
const output2 = await exec("2");
|
const output2 = await exec("2");
|
||||||
expect(output2).toMatch(/but build dependencies have changed/);
|
expect(output2).toMatch(/but build dependencies have changed/);
|
||||||
expect(output2).toMatch(/Captured build dependencies/);
|
expect(output2).toMatch(/Captured build dependencies/);
|
||||||
|
expect(output2).not.toMatch(/Assuming/);
|
||||||
|
expect(output2).not.toMatch(/<w>/);
|
||||||
const output3 = await exec("3");
|
const output3 = await exec("3");
|
||||||
expect(output3).not.toMatch(/resolving of build dependencies is invalid/);
|
expect(output3).not.toMatch(/resolving of build dependencies is invalid/);
|
||||||
expect(output3).not.toMatch(/but build dependencies have changed/);
|
expect(output3).not.toMatch(/but build dependencies have changed/);
|
||||||
expect(output3).not.toMatch(/Captured build dependencies/);
|
expect(output3).not.toMatch(/Captured build dependencies/);
|
||||||
|
expect(output3).not.toMatch(/Assuming/);
|
||||||
|
expect(output3).not.toMatch(/<w>/);
|
||||||
fs.writeFileSync(
|
fs.writeFileSync(
|
||||||
path.resolve(inputDirectory, "package.json"),
|
path.resolve(inputDirectory, "package.json"),
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
|
|
|
||||||
0
test/fixtures/buildDependencies/node_modules/dep-with-exports/main-entry.js
generated
vendored
Normal file
0
test/fixtures/buildDependencies/node_modules/dep-with-exports/main-entry.js
generated
vendored
Normal file
8
test/fixtures/buildDependencies/node_modules/dep-with-exports/package.json
generated
vendored
Normal file
8
test/fixtures/buildDependencies/node_modules/dep-with-exports/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"exports": {
|
||||||
|
".": "./main-entry.js",
|
||||||
|
"./sub": {
|
||||||
|
"require": "./sub-entry.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
0
test/fixtures/buildDependencies/node_modules/dep-with-exports/sub-entry.js
generated
vendored
Normal file
0
test/fixtures/buildDependencies/node_modules/dep-with-exports/sub-entry.js
generated
vendored
Normal file
0
test/fixtures/buildDependencies/node_modules/dep-without-package.json/main-entry.js
generated
vendored
Normal file
0
test/fixtures/buildDependencies/node_modules/dep-without-package.json/main-entry.js
generated
vendored
Normal file
0
test/fixtures/buildDependencies/node_modules/dep-without-package.json/sub-entry.js
generated
vendored
Normal file
0
test/fixtures/buildDependencies/node_modules/dep-without-package.json/sub-entry.js
generated
vendored
Normal file
4
test/fixtures/buildDependencies/node_modules/dependency-with-exports/main.js
generated
vendored
Normal file
4
test/fixtures/buildDependencies/node_modules/dependency-with-exports/main.js
generated
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
require("dep-with-exports");
|
||||||
|
require("dep-with-exports/sub");
|
||||||
|
require("dep-without-package.json/main-entry");
|
||||||
|
require("dep-without-package.json/sub-entry");
|
||||||
3
test/fixtures/buildDependencies/node_modules/dependency-with-exports/package.json
generated
vendored
Normal file
3
test/fixtures/buildDependencies/node_modules/dependency-with-exports/package.json
generated
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"exports": "./main.js"
|
||||||
|
}
|
||||||
1
test/fixtures/buildDependencies/node_modules/require-dependency-with-exports/index.js
generated
vendored
Normal file
1
test/fixtures/buildDependencies/node_modules/require-dependency-with-exports/index.js
generated
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
require("dependency-with-exports");
|
||||||
|
|
@ -10,6 +10,7 @@ const options = JSON.parse(process.argv[3]);
|
||||||
const esm = +process.versions.modules >= 83;
|
const esm = +process.versions.modules >= 83;
|
||||||
|
|
||||||
if (esm) {
|
if (esm) {
|
||||||
|
require("require-dependency-with-exports");
|
||||||
import("./esm.mjs").then(module => {
|
import("./esm.mjs").then(module => {
|
||||||
run(module);
|
run(module);
|
||||||
});
|
});
|
||||||
|
|
@ -56,6 +57,7 @@ function run({ default: value2, asyncDep: value3 }) {
|
||||||
type: "filesystem",
|
type: "filesystem",
|
||||||
cacheDirectory: path.resolve(__dirname, "../../js/buildDepsCache"),
|
cacheDirectory: path.resolve(__dirname, "../../js/buildDepsCache"),
|
||||||
buildDependencies: {
|
buildDependencies: {
|
||||||
|
defaultWebpack: [],
|
||||||
config: [
|
config: [
|
||||||
__filename,
|
__filename,
|
||||||
path.resolve(__dirname, "../../../node_modules/.yarn-integrity")
|
path.resolve(__dirname, "../../../node_modules/.yarn-integrity")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue