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 = | ||||
| 							/** @type {InnerGraph} */ (parser.state.harmonyInnerGraph); | ||||
| 						if (!innerGraph) return; | ||||
| 						// flatten graph
 | ||||
| 						const unexpanded = new Set(innerGraph.keys()); | ||||
| 						const expand = key => { | ||||
| 							if (!unexpanded.has(key)) return; | ||||
| 							unexpanded.delete(key); | ||||
| 						// flatten graph to terminal nodes (string, undefined or true)
 | ||||
| 						const nonTerminal = new Set(innerGraph.keys()); | ||||
| 						while (nonTerminal.size > 0) { | ||||
| 							for (const key of nonTerminal) { | ||||
| 								/** @type {Set<string|TopLevelSymbol> | true} */ | ||||
| 								let newSet = new Set(); | ||||
| 								let isTerminal = true; | ||||
| 								const value = innerGraph.get(key); | ||||
| 								if (value !== true && value !== undefined) { | ||||
| 								const newSet = new Set(); | ||||
| 									for (const item of value) { | ||||
| 										if (typeof item === "string") { | ||||
| 											newSet.add(item); | ||||
| 										} else { | ||||
| 										expand(item); | ||||
| 											const itemValue = innerGraph.get(item); | ||||
| 											if (itemValue === true) { | ||||
| 											innerGraph.set(key, true); | ||||
| 											return; | ||||
| 												newSet = true; | ||||
| 												break; | ||||
| 											} | ||||
| 											if (itemValue !== undefined) { | ||||
| 												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.size === 0) { | ||||
| 									} | ||||
| 									if (newSet === true) { | ||||
| 										innerGraph.set(key, true); | ||||
| 									} else if (newSet.size === 0) { | ||||
| 										innerGraph.set(key, undefined); | ||||
| 									} else { | ||||
| 										innerGraph.set(key, newSet); | ||||
| 									} | ||||
| 								} | ||||
| 						}; | ||||
| 						for (const item of unexpanded) { | ||||
| 							expand(item); | ||||
| 								if (isTerminal) { | ||||
| 									nonTerminal.delete(key); | ||||
| 								} | ||||
| 							} | ||||
| 						} | ||||
| 
 | ||||
| 						for (const dep of parser.state | ||||
| 							.harmonyAllExportDependentDependencies) { | ||||
| 							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