mirror of https://github.com/webpack/webpack.git
				
				
				
			fix handling of circular references in the inner graph
This commit is contained in:
		
							parent
							
								
									c47e1f8071
								
							
						
					
					
						commit
						f01e7d253b
					
				|  | @ -96,41 +96,49 @@ class InnerGraphPlugin { | ||||||
| 						const innerGraph = | 						const innerGraph = | ||||||
| 							/** @type {InnerGraph} */ (parser.state.harmonyInnerGraph); | 							/** @type {InnerGraph} */ (parser.state.harmonyInnerGraph); | ||||||
| 						if (!innerGraph) return; | 						if (!innerGraph) return; | ||||||
| 						// flatten graph
 | 						// flatten graph to terminal nodes (string, undefined or true)
 | ||||||
| 						const unexpanded = new Set(innerGraph.keys()); | 						const nonTerminal = new Set(innerGraph.keys()); | ||||||
| 						const expand = key => { | 						while (nonTerminal.size > 0) { | ||||||
| 							if (!unexpanded.has(key)) return; | 							for (const key of nonTerminal) { | ||||||
| 							unexpanded.delete(key); | 								/** @type {Set<string|TopLevelSymbol> | true} */ | ||||||
| 							const value = innerGraph.get(key); | 								let newSet = new Set(); | ||||||
| 							if (value !== true && value !== undefined) { | 								let isTerminal = true; | ||||||
| 								const newSet = new Set(); | 								const value = innerGraph.get(key); | ||||||
| 								for (const item of value) { | 								if (value !== true && value !== undefined) { | ||||||
| 									if (typeof item === "string") { | 									for (const item of value) { | ||||||
| 										newSet.add(item); | 										if (typeof item === "string") { | ||||||
| 									} else { | 											newSet.add(item); | ||||||
| 										expand(item); | 										} else { | ||||||
| 										const itemValue = innerGraph.get(item); | 											const itemValue = innerGraph.get(item); | ||||||
| 										if (itemValue === true) { | 											if (itemValue === true) { | ||||||
| 											innerGraph.set(key, true); | 												newSet = true; | ||||||
| 											return; | 												break; | ||||||
| 										} | 											} | ||||||
| 										if (itemValue !== undefined) { | 											if (itemValue !== undefined) { | ||||||
| 											for (const i of itemValue) { | 												for (const i of itemValue) { | ||||||
| 												if (typeof i === "string") newSet.add(i); | 													if (i === key) continue; | ||||||
|  | 													newSet.add(i); | ||||||
|  | 													if (typeof i !== "string") { | ||||||
|  | 														isTerminal = false; | ||||||
|  | 													} | ||||||
|  | 												} | ||||||
| 											} | 											} | ||||||
| 										} | 										} | ||||||
| 									} | 									} | ||||||
|  | 									if (newSet === true) { | ||||||
|  | 										innerGraph.set(key, true); | ||||||
|  | 									} else if (newSet.size === 0) { | ||||||
|  | 										innerGraph.set(key, undefined); | ||||||
|  | 									} else { | ||||||
|  | 										innerGraph.set(key, newSet); | ||||||
|  | 									} | ||||||
| 								} | 								} | ||||||
| 								if (newSet.size === 0) { | 								if (isTerminal) { | ||||||
| 									innerGraph.set(key, undefined); | 									nonTerminal.delete(key); | ||||||
| 								} else { |  | ||||||
| 									innerGraph.set(key, newSet); |  | ||||||
| 								} | 								} | ||||||
| 							} | 							} | ||||||
| 						}; |  | ||||||
| 						for (const item of unexpanded) { |  | ||||||
| 							expand(item); |  | ||||||
| 						} | 						} | ||||||
|  | 
 | ||||||
| 						for (const dep of parser.state | 						for (const dep of parser.state | ||||||
| 							.harmonyAllExportDependentDependencies) { | 							.harmonyAllExportDependentDependencies) { | ||||||
| 							const value = innerGraph.get(dep); | 							const value = innerGraph.get(dep); | ||||||
|  |  | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | import "./inner"; | ||||||
|  | @ -0,0 +1,12 @@ | ||||||
|  | import { exportAUsed, exportBUsed, exportCUsed } from "./inner"; | ||||||
|  | import { y } from "./module"; | ||||||
|  | 
 | ||||||
|  | it("export should be unused when only unused functions use it", () => { | ||||||
|  | 	expect(y("a")).toBe("okBAA"); | ||||||
|  | 	expect(exportAUsed).toBe(true); | ||||||
|  | 	expect(exportBUsed).toBe(true); | ||||||
|  | 	if (process.env.NODE_ENV === "production") { | ||||||
|  | 		expect(exportCUsed).toBe(false); | ||||||
|  | 	} | ||||||
|  | 	return import("./chunk"); | ||||||
|  | }); | ||||||
|  | @ -0,0 +1,13 @@ | ||||||
|  | export function A(s) { | ||||||
|  | 	return s + "A"; | ||||||
|  | } | ||||||
|  | export function B(s) { | ||||||
|  | 	return s + "B"; | ||||||
|  | } | ||||||
|  | export function C(s) { | ||||||
|  | 	return s + "C"; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const exportAUsed = __webpack_exports_info__.A.used; | ||||||
|  | export const exportBUsed = __webpack_exports_info__.B.used; | ||||||
|  | export const exportCUsed = __webpack_exports_info__.C.used; | ||||||
|  | @ -0,0 +1,36 @@ | ||||||
|  | import { A, B, C } from "./inner"; | ||||||
|  | 
 | ||||||
|  | function x(type) { | ||||||
|  | 	switch (type) { | ||||||
|  | 		case "a": | ||||||
|  | 			return withA("b"); | ||||||
|  | 		case "b": | ||||||
|  | 			return withB("c"); | ||||||
|  | 		case "c": | ||||||
|  | 			return "ok"; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function y(v) { | ||||||
|  | 	return withA(v); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function withA(v) { | ||||||
|  | 	const value = x(v); | ||||||
|  | 
 | ||||||
|  | 	return A(value); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function withB(v) { | ||||||
|  | 	const value = x(v); | ||||||
|  | 
 | ||||||
|  | 	return B(value); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function withC(v) { | ||||||
|  | 	const value = x(v); | ||||||
|  | 
 | ||||||
|  | 	return C(value); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export { x, y }; | ||||||
		Loading…
	
		Reference in New Issue