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