mirror of https://github.com/webpack/webpack.git
				
				
				
			Refactor to track nested exports
Harmony dependencies track access to nested properties Flag nested exports
This commit is contained in:
		
							parent
							
								
									db5a8a33d3
								
							
						
					
					
						commit
						43bc7a306e
					
				|  | @ -34,9 +34,16 @@ const DependencyReference = require("./dependencies/DependencyReference"); | ||||||
| 
 | 
 | ||||||
| /** @typedef {SynteticDependencyLocation|RealDependencyLocation} DependencyLocation */ | /** @typedef {SynteticDependencyLocation|RealDependencyLocation} DependencyLocation */ | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @typedef {Object} ExportSpec | ||||||
|  |  * @property {string} name the name of the export | ||||||
|  |  * @property {Module=} from  when reexported: from which module | ||||||
|  |  * @property {string[] | null=} export  when reexported: from which export | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * @typedef {Object} ExportsSpec |  * @typedef {Object} ExportsSpec | ||||||
|  * @property {string[] | true | null} exports exported names, true for unknown exports or null for no exports |  * @property {(string | ExportSpec)[] | true | null} exports exported names, true for unknown exports or null for no exports | ||||||
|  * @property {Module[]=} dependencies module on which the result depends on |  * @property {Module[]=} dependencies module on which the result depends on | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ const Queue = require("./util/Queue"); | ||||||
| /** @typedef {import("./DependenciesBlock")} DependenciesBlock */ | /** @typedef {import("./DependenciesBlock")} DependenciesBlock */ | ||||||
| /** @typedef {import("./Dependency")} Dependency */ | /** @typedef {import("./Dependency")} Dependency */ | ||||||
| /** @typedef {import("./Module")} Module */ | /** @typedef {import("./Module")} Module */ | ||||||
|  | /** @typedef {import("./ModuleGraph").ExportsInfo} ExportsInfo */ | ||||||
| 
 | 
 | ||||||
| const getCacheIdentifier = (compilation, module) => { | const getCacheIdentifier = (compilation, module) => { | ||||||
| 	return `${ | 	return `${ | ||||||
|  | @ -79,6 +80,7 @@ class FlagDependencyExportsPlugin { | ||||||
| 								/** @type {Module} */ | 								/** @type {Module} */ | ||||||
| 								let module; | 								let module; | ||||||
| 
 | 
 | ||||||
|  | 								/** @type {ExportsInfo} */ | ||||||
| 								let exportsInfo; | 								let exportsInfo; | ||||||
| 
 | 
 | ||||||
| 								let cacheable = true; | 								let cacheable = true; | ||||||
|  | @ -113,11 +115,35 @@ class FlagDependencyExportsPlugin { | ||||||
| 										} | 										} | ||||||
| 									} else if (Array.isArray(exports)) { | 									} else if (Array.isArray(exports)) { | ||||||
| 										// merge in new exports
 | 										// merge in new exports
 | ||||||
| 										for (const exportName of exports) { | 										for (const exportNameOrSpec of exports) { | ||||||
| 											const exportInfo = exportsInfo.getExportInfo(exportName); | 											if (typeof exportNameOrSpec === "string") { | ||||||
| 											if (exportInfo.provided === false) { | 												const exportInfo = exportsInfo.getExportInfo( | ||||||
| 												exportInfo.provided = true; | 													exportNameOrSpec | ||||||
| 												changed = true; | 												); | ||||||
|  | 												if (exportInfo.provided === false) { | ||||||
|  | 													exportInfo.provided = true; | ||||||
|  | 													changed = true; | ||||||
|  | 												} | ||||||
|  | 											} else { | ||||||
|  | 												const exportInfo = exportsInfo.getExportInfo( | ||||||
|  | 													exportNameOrSpec.name | ||||||
|  | 												); | ||||||
|  | 												if (exportInfo.provided === false) { | ||||||
|  | 													exportInfo.provided = true; | ||||||
|  | 													changed = true; | ||||||
|  | 												} | ||||||
|  | 												if (exportNameOrSpec.from) { | ||||||
|  | 													const fromExportsInfo = moduleGraph.getExportsInfo( | ||||||
|  | 														exportNameOrSpec.from | ||||||
|  | 													); | ||||||
|  | 													const nestedExportsInfo = fromExportsInfo.getNestedExportsInfo( | ||||||
|  | 														exportNameOrSpec.export | ||||||
|  | 													); | ||||||
|  | 													if (exportInfo.exportsInfo !== nestedExportsInfo) { | ||||||
|  | 														exportInfo.exportsInfo = nestedExportsInfo; | ||||||
|  | 														changed = true; | ||||||
|  | 													} | ||||||
|  | 												} | ||||||
| 											} | 											} | ||||||
| 										} | 										} | ||||||
| 									} | 									} | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ | ||||||
| 
 | 
 | ||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
|  | const { UsageState } = require("./ModuleGraph"); | ||||||
| const { STAGE_DEFAULT } = require("./OptimizationStages"); | const { STAGE_DEFAULT } = require("./OptimizationStages"); | ||||||
| const Queue = require("./util/Queue"); | const Queue = require("./util/Queue"); | ||||||
| 
 | 
 | ||||||
|  | @ -12,6 +13,10 @@ const Queue = require("./util/Queue"); | ||||||
| /** @typedef {import("./DependenciesBlock")} DependenciesBlock */ | /** @typedef {import("./DependenciesBlock")} DependenciesBlock */ | ||||||
| /** @typedef {import("./Dependency")} Dependency */ | /** @typedef {import("./Dependency")} Dependency */ | ||||||
| /** @typedef {import("./Module")} Module */ | /** @typedef {import("./Module")} Module */ | ||||||
|  | /** @typedef {import("./ModuleGraph").ExportsInfo} ExportsInfo */ | ||||||
|  | 
 | ||||||
|  | const NS_OBJ_USED = [[]]; | ||||||
|  | const NOTHING_USED = []; | ||||||
| 
 | 
 | ||||||
| class FlagDependencyUsagePlugin { | class FlagDependencyUsagePlugin { | ||||||
| 	/** | 	/** | ||||||
|  | @ -27,31 +32,60 @@ class FlagDependencyUsagePlugin { | ||||||
| 					stage: STAGE_DEFAULT | 					stage: STAGE_DEFAULT | ||||||
| 				}, | 				}, | ||||||
| 				modules => { | 				modules => { | ||||||
|  | 					/** @type {Map<ExportsInfo, Module>} */ | ||||||
|  | 					const exportInfoToModuleMap = new Map(); | ||||||
|  | 
 | ||||||
| 					/** | 					/** | ||||||
| 					 * | 					 * @typedef {string[]} StringArray | ||||||
| 					 * @param {Module} module module to process | 					 * @param {Module} module module to process | ||||||
| 					 * @param {boolean | string[]} usedExports list of used exports | 					 * @param {StringArray[]} usedExports list of used exports | ||||||
| 					 * @returns {void} | 					 * @returns {void} | ||||||
| 					 */ | 					 */ | ||||||
| 					const processModule = (module, usedExports) => { | 					const processModule = (module, usedExports) => { | ||||||
| 						const exportsInfo = moduleGraph.getExportsInfo(module); | 						const exportsInfo = moduleGraph.getExportsInfo(module); | ||||||
| 						let changed = false; | 						if (usedExports.length > 0) { | ||||||
| 						if (usedExports === true) { | 							for (const usedExport of usedExports) { | ||||||
| 							changed = exportsInfo.setUsedInUnknownWay(); | 								if (usedExport.length === 0) { | ||||||
| 						} else if (usedExports) { | 									if (exportsInfo.setUsedInUnknownWay()) { | ||||||
| 							for (const exportName of usedExports) { | 										queue.enqueue(module); | ||||||
| 								if ( |  | ||||||
| 									exportName === "default" && |  | ||||||
| 									module.buildMeta.exportsType === "named" |  | ||||||
| 								) { |  | ||||||
| 									if (exportsInfo.setUsedAsNamedExportType()) { |  | ||||||
| 										changed = true; |  | ||||||
| 									} | 									} | ||||||
| 								} else { | 								} else { | ||||||
| 									const exportInfo = exportsInfo.getExportInfo(exportName); | 									if ( | ||||||
| 									if (exportInfo.used !== true) { | 										usedExport[0] === "default" && | ||||||
| 										exportInfo.used = true; | 										module.buildMeta.exportsType === "named" | ||||||
| 										changed = true; | 									) { | ||||||
|  | 										if (exportsInfo.setUsedAsNamedExportType()) { | ||||||
|  | 											queue.enqueue(module); | ||||||
|  | 										} | ||||||
|  | 									} else { | ||||||
|  | 										let currentExportsInfo = exportsInfo; | ||||||
|  | 										let currentModule = module; | ||||||
|  | 										for (let i = 0; i < usedExport.length; i++) { | ||||||
|  | 											const exportName = usedExport[i]; | ||||||
|  | 											const exportInfo = currentExportsInfo.getExportInfo( | ||||||
|  | 												exportName | ||||||
|  | 											); | ||||||
|  | 											const lastOne = i === usedExport.length - 1; | ||||||
|  | 											const nestedInfo = exportInfo.exportsInfo; | ||||||
|  | 											if (!nestedInfo || lastOne) { | ||||||
|  | 												if (exportInfo.used !== UsageState.Used) { | ||||||
|  | 													exportInfo.used = UsageState.Used; | ||||||
|  | 													if (currentModule) { | ||||||
|  | 														queue.enqueue(currentModule); | ||||||
|  | 													} | ||||||
|  | 												} | ||||||
|  | 												break; | ||||||
|  | 											} else { | ||||||
|  | 												if (exportInfo.used === UsageState.Unused) { | ||||||
|  | 													exportInfo.used = UsageState.OnlyPropertiesUsed; | ||||||
|  | 													if (currentModule) { | ||||||
|  | 														queue.enqueue(currentModule); | ||||||
|  | 													} | ||||||
|  | 												} | ||||||
|  | 												currentExportsInfo = nestedInfo; | ||||||
|  | 												currentModule = exportInfoToModuleMap.get(nestedInfo); | ||||||
|  | 											} | ||||||
|  | 										} | ||||||
| 									} | 									} | ||||||
| 								} | 								} | ||||||
| 							} | 							} | ||||||
|  | @ -59,11 +93,9 @@ class FlagDependencyUsagePlugin { | ||||||
| 							// for a module without side effects we stop tracking usage here when no export is used
 | 							// for a module without side effects we stop tracking usage here when no export is used
 | ||||||
| 							// This module won't be evaluated in this case
 | 							// This module won't be evaluated in this case
 | ||||||
| 							if (module.factoryMeta.sideEffectFree) return; | 							if (module.factoryMeta.sideEffectFree) return; | ||||||
| 							changed = exportsInfo.setUsedForSideEffectsOnly(); | 							if (exportsInfo.setUsedForSideEffectsOnly()) { | ||||||
| 						} | 								queue.enqueue(module); | ||||||
| 
 | 							} | ||||||
| 						if (changed) { |  | ||||||
| 							queue.enqueue(module); |  | ||||||
| 						} | 						} | ||||||
| 					}; | 					}; | ||||||
| 
 | 
 | ||||||
|  | @ -89,11 +121,21 @@ class FlagDependencyUsagePlugin { | ||||||
| 						if (!reference) return; | 						if (!reference) return; | ||||||
| 						const referenceModule = reference.module; | 						const referenceModule = reference.module; | ||||||
| 						const importedNames = reference.importedNames; | 						const importedNames = reference.importedNames; | ||||||
| 						processModule(referenceModule, importedNames); | 
 | ||||||
|  | 						processModule( | ||||||
|  | 							referenceModule, | ||||||
|  | 							importedNames === false | ||||||
|  | 								? NOTHING_USED | ||||||
|  | 								: importedNames === true | ||||||
|  | 								? NS_OBJ_USED | ||||||
|  | 								: importedNames.map(n => (Array.isArray(n) ? n : [n])) | ||||||
|  | 						); | ||||||
| 					}; | 					}; | ||||||
| 
 | 
 | ||||||
| 					for (const module of modules) { | 					for (const module of modules) { | ||||||
| 						moduleGraph.getExportsInfo(module).setHasUseInfo(); | 						const exportsInfo = moduleGraph.getExportsInfo(module); | ||||||
|  | 						exportInfoToModuleMap.set(exportsInfo, module); | ||||||
|  | 						exportsInfo.setHasUseInfo(); | ||||||
| 					} | 					} | ||||||
| 
 | 
 | ||||||
| 					/** @type {Queue<DependenciesBlock>} */ | 					/** @type {Queue<DependenciesBlock>} */ | ||||||
|  | @ -103,7 +145,7 @@ class FlagDependencyUsagePlugin { | ||||||
| 						for (const dep of deps) { | 						for (const dep of deps) { | ||||||
| 							const module = moduleGraph.getModule(dep); | 							const module = moduleGraph.getModule(dep); | ||||||
| 							if (module) { | 							if (module) { | ||||||
| 								processModule(module, true); | 								processModule(module, NS_OBJ_USED); | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
|  | @ -27,6 +27,32 @@ const joinIterableWithComma = iterable => { | ||||||
| 	return str; | 	return str; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | const printExportsInfoToSource = (source, indent, exportsInfo) => { | ||||||
|  | 	let hasExports = false; | ||||||
|  | 	for (const exportInfo of exportsInfo.orderedExports) { | ||||||
|  | 		source.add( | ||||||
|  | 			Template.toComment( | ||||||
|  | 				`${indent}export ${ | ||||||
|  | 					exportInfo.name | ||||||
|  | 				} [${exportInfo.getProvidedInfo()}] [${exportInfo.getUsedInfo()}] [${exportInfo.getRenameInfo()}]` | ||||||
|  | 			) + "\n" | ||||||
|  | 		); | ||||||
|  | 		if (exportInfo.exportsInfo) { | ||||||
|  | 			printExportsInfoToSource(source, indent + "  ", exportInfo.exportsInfo); | ||||||
|  | 		} | ||||||
|  | 		hasExports = true; | ||||||
|  | 	} | ||||||
|  | 	const otherExportsInfo = exportsInfo.otherExportsInfo; | ||||||
|  | 	if (otherExportsInfo.provided !== false || otherExportsInfo.used !== false) { | ||||||
|  | 		const title = hasExports ? "other exports" : "exports"; | ||||||
|  | 		source.add( | ||||||
|  | 			Template.toComment( | ||||||
|  | 				`${indent}${title} [${otherExportsInfo.getProvidedInfo()}] [${otherExportsInfo.getUsedInfo()}]` | ||||||
|  | 			) + "\n" | ||||||
|  | 		); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| class FunctionModuleTemplatePlugin { | class FunctionModuleTemplatePlugin { | ||||||
| 	constructor({ compilation }) { | 	constructor({ compilation }) { | ||||||
| 		this.compilation = compilation; | 		this.compilation = compilation; | ||||||
|  | @ -84,26 +110,7 @@ class FunctionModuleTemplatePlugin { | ||||||
| 					source.add("  !*** " + reqStr + " ***!\n"); | 					source.add("  !*** " + reqStr + " ***!\n"); | ||||||
| 					source.add("  \\****" + reqStrStar + "****/\n"); | 					source.add("  \\****" + reqStrStar + "****/\n"); | ||||||
| 					const exportsInfo = moduleGraph.getExportsInfo(module); | 					const exportsInfo = moduleGraph.getExportsInfo(module); | ||||||
| 					for (const exportInfo of exportsInfo.orderedExports) { | 					printExportsInfoToSource(source, "", exportsInfo); | ||||||
| 						source.add( |  | ||||||
| 							Template.toComment( |  | ||||||
| 								`export ${ |  | ||||||
| 									exportInfo.name |  | ||||||
| 								} [${exportInfo.getProvidedInfo()}] [${exportInfo.getUsedInfo()}] [${exportInfo.getRenameInfo()}]` |  | ||||||
| 							) + "\n" |  | ||||||
| 						); |  | ||||||
| 					} |  | ||||||
| 					const otherExportsInfo = exportsInfo.otherExportsInfo; |  | ||||||
| 					if ( |  | ||||||
| 						otherExportsInfo.provided !== false || |  | ||||||
| 						otherExportsInfo.used !== false |  | ||||||
| 					) { |  | ||||||
| 						source.add( |  | ||||||
| 							Template.toComment( |  | ||||||
| 								`other exports [${otherExportsInfo.getProvidedInfo()}] [${otherExportsInfo.getUsedInfo()}]` |  | ||||||
| 							) + "\n" |  | ||||||
| 						); |  | ||||||
| 					} |  | ||||||
| 					source.add( | 					source.add( | ||||||
| 						Template.toComment( | 						Template.toComment( | ||||||
| 							`runtime requirements: ${joinIterableWithComma( | 							`runtime requirements: ${joinIterableWithComma( | ||||||
|  |  | ||||||
|  | @ -91,10 +91,14 @@ class JavascriptParser { | ||||||
| 			typeof: new HookMap(() => new SyncBailHook(["expression"])), | 			typeof: new HookMap(() => new SyncBailHook(["expression"])), | ||||||
| 			importCall: new SyncBailHook(["expression"]), | 			importCall: new SyncBailHook(["expression"]), | ||||||
| 			call: new HookMap(() => new SyncBailHook(["expression"])), | 			call: new HookMap(() => new SyncBailHook(["expression"])), | ||||||
| 			callAnyMember: new HookMap(() => new SyncBailHook(["expression"])), | 			callMemberChain: new HookMap( | ||||||
|  | 				() => new SyncBailHook(["expression", "rootRaw", "members"]) | ||||||
|  | 			), | ||||||
| 			new: new HookMap(() => new SyncBailHook(["expression"])), | 			new: new HookMap(() => new SyncBailHook(["expression"])), | ||||||
| 			expression: new HookMap(() => new SyncBailHook(["expression"])), | 			expression: new HookMap(() => new SyncBailHook(["expression"])), | ||||||
| 			expressionAnyMember: new HookMap(() => new SyncBailHook(["expression"])), | 			expressionMemberChain: new HookMap( | ||||||
|  | 				() => new SyncBailHook(["expression", "rootRaw", "members"]) | ||||||
|  | 			), | ||||||
| 			expressionConditionalOperator: new SyncBailHook(["expression"]), | 			expressionConditionalOperator: new SyncBailHook(["expression"]), | ||||||
| 			expressionLogicalOperator: new SyncBailHook(["expression"]), | 			expressionLogicalOperator: new SyncBailHook(["expression"]), | ||||||
| 			program: new SyncBailHook(["ast", "comments"]) | 			program: new SyncBailHook(["ast", "comments"]) | ||||||
|  | @ -1831,14 +1835,17 @@ class JavascriptParser { | ||||||
| 					let result = callHook.call(expression); | 					let result = callHook.call(expression); | ||||||
| 					if (result === true) return; | 					if (result === true) return; | ||||||
| 				} | 				} | ||||||
| 				// TODO replace with lastIndexOf for performance reasons
 | 			} | ||||||
| 				let identifier = callee.identifier.replace(/\.[^.]+$/, ""); | 			const exprName = this.getNameForExpression(expression.callee); | ||||||
| 				if (identifier !== callee.identifier) { | 			if (exprName) { | ||||||
| 					const callAnyHook = this.hooks.callAnyMember.get(identifier); | 				const hook = this.hooks.callMemberChain.get(exprName.rootName); | ||||||
| 					if (callAnyHook !== undefined) { | 				if (hook !== undefined) { | ||||||
| 						let result = callAnyHook.call(expression); | 					const result = hook.call( | ||||||
| 						if (result === true) return; | 						expression, | ||||||
| 					} | 						exprName.rootRaw, | ||||||
|  | 						exprName.members | ||||||
|  | 					); | ||||||
|  | 					if (result === true) return; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
|  | @ -1855,13 +1862,19 @@ class JavascriptParser { | ||||||
| 				const result = expressionHook.call(expression); | 				const result = expressionHook.call(expression); | ||||||
| 				if (result === true) return; | 				if (result === true) return; | ||||||
| 			} | 			} | ||||||
| 			const expressionAnyMemberHook = this.hooks.expressionAnyMember.get( | 			const expressionMemberChainHook = this.hooks.expressionMemberChain.get( | ||||||
| 				exprName.nameGeneral | 				exprName.rootName | ||||||
| 			); | 			); | ||||||
| 			if (expressionAnyMemberHook !== undefined) { | 			if (expressionMemberChainHook !== undefined) { | ||||||
| 				const result = expressionAnyMemberHook.call(expression); | 				const result = expressionMemberChainHook.call( | ||||||
|  | 					expression, | ||||||
|  | 					exprName.rootRaw, | ||||||
|  | 					exprName.members | ||||||
|  | 				); | ||||||
| 				if (result === true) return; | 				if (result === true) return; | ||||||
| 			} | 			} | ||||||
|  | 			// TODO optimize case where expression.object is a MemberExpression too.
 | ||||||
|  | 			// we can keep info here when calling walkMemberExpression directly
 | ||||||
| 		} | 		} | ||||||
| 		this.walkExpression(expression.object); | 		this.walkExpression(expression.object); | ||||||
| 		if (expression.computed === true) this.walkExpression(expression.property); | 		if (expression.computed === true) this.walkExpression(expression.property); | ||||||
|  | @ -2189,22 +2202,27 @@ class JavascriptParser { | ||||||
| 			expr.type === "MemberExpression" && | 			expr.type === "MemberExpression" && | ||||||
| 			expr.property.type === (expr.computed ? "Literal" : "Identifier") | 			expr.property.type === (expr.computed ? "Literal" : "Identifier") | ||||||
| 		) { | 		) { | ||||||
| 			exprName.push(expr.computed ? expr.property.value : expr.property.name); | 			exprName.push( | ||||||
|  | 				expr.computed ? `${expr.property.value}` : expr.property.name | ||||||
|  | 			); | ||||||
| 			expr = expr.object; | 			expr = expr.object; | ||||||
| 		} | 		} | ||||||
| 		let free; | 		let free; | ||||||
|  | 		let rootRaw; | ||||||
| 		if (expr.type === "Identifier") { | 		if (expr.type === "Identifier") { | ||||||
| 			free = !this.scope.definitions.has(expr.name); | 			free = !this.scope.definitions.has(expr.name); | ||||||
| 			exprName.push(this.scope.renames.get(expr.name) || expr.name); | 			exprName.push(this.scope.renames.get(expr.name) || expr.name); | ||||||
| 		} else if ( | 			rootRaw = expr.name; | ||||||
| 			expr.type === "ThisExpression" && |  | ||||||
| 			this.scope.renames.get("this") |  | ||||||
| 		) { |  | ||||||
| 			free = true; |  | ||||||
| 			exprName.push(this.scope.renames.get("this")); |  | ||||||
| 		} else if (expr.type === "ThisExpression") { | 		} else if (expr.type === "ThisExpression") { | ||||||
| 			free = this.scope.topLevelScope; | 			const rename = this.scope.renames.get("this"); | ||||||
| 			exprName.push("this"); | 			if (rename) { | ||||||
|  | 				free = true; | ||||||
|  | 				exprName.push(rename); | ||||||
|  | 			} else { | ||||||
|  | 				free = this.scope.topLevelScope; | ||||||
|  | 				exprName.push("this"); | ||||||
|  | 			} | ||||||
|  | 			rootRaw = "this"; | ||||||
| 		} else { | 		} else { | ||||||
| 			return null; | 			return null; | ||||||
| 		} | 		} | ||||||
|  | @ -2217,9 +2235,13 @@ class JavascriptParser { | ||||||
| 		} | 		} | ||||||
| 		const name = prefix ? prefix + "." + exprName[0] : exprName[0]; | 		const name = prefix ? prefix + "." + exprName[0] : exprName[0]; | ||||||
| 		const nameGeneral = prefix; | 		const nameGeneral = prefix; | ||||||
|  | 		const rootName = exprName.pop(); | ||||||
| 		return { | 		return { | ||||||
| 			name, | 			name, | ||||||
| 			nameGeneral, | 			nameGeneral, | ||||||
|  | 			rootName, | ||||||
|  | 			rootRaw, | ||||||
|  | 			members: exprName.reverse(), | ||||||
| 			free | 			free | ||||||
| 		}; | 		}; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| 
 | 
 | ||||||
| const { ConcatSource, RawSource } = require("webpack-sources"); | const { ConcatSource, RawSource } = require("webpack-sources"); | ||||||
| const Generator = require("./Generator"); | const Generator = require("./Generator"); | ||||||
|  | const { UsageState } = require("./ModuleGraph"); | ||||||
| const RuntimeGlobals = require("./RuntimeGlobals"); | const RuntimeGlobals = require("./RuntimeGlobals"); | ||||||
| 
 | 
 | ||||||
| /** @typedef {import("webpack-sources").Source} Source */ | /** @typedef {import("webpack-sources").Source} Source */ | ||||||
|  | @ -64,7 +65,7 @@ class JsonGenerator extends Generator { | ||||||
| 		const providedExports = moduleGraph.getProvidedExports(module); | 		const providedExports = moduleGraph.getProvidedExports(module); | ||||||
| 		if ( | 		if ( | ||||||
| 			Array.isArray(providedExports) && | 			Array.isArray(providedExports) && | ||||||
| 			!module.isExportUsed(moduleGraph, "default") | 			module.isExportUsed(moduleGraph, "default") === UsageState.Unused | ||||||
| 		) { | 		) { | ||||||
| 			// Only some exports are used: We can optimize here, by only generating a part of the JSON
 | 			// Only some exports are used: We can optimize here, by only generating a part of the JSON
 | ||||||
| 			const reducedJson = {}; | 			const reducedJson = {}; | ||||||
|  |  | ||||||
|  | @ -18,6 +18,7 @@ const makeSerializable = require("./util/makeSerializable"); | ||||||
| /** @typedef {import("./Dependency")} Dependency */ | /** @typedef {import("./Dependency")} Dependency */ | ||||||
| /** @typedef {import("./DependencyTemplates")} DependencyTemplates */ | /** @typedef {import("./DependencyTemplates")} DependencyTemplates */ | ||||||
| /** @typedef {import("./FileSystemInfo")} FileSystemInfo */ | /** @typedef {import("./FileSystemInfo")} FileSystemInfo */ | ||||||
|  | /** @typedef {import("./ModuleGraph").UsageStateType} UsageStateType */ | ||||||
| /** @typedef {import("./RequestShortener")} RequestShortener */ | /** @typedef {import("./RequestShortener")} RequestShortener */ | ||||||
| /** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */ | /** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */ | ||||||
| /** @typedef {import("./WebpackError")} WebpackError */ | /** @typedef {import("./WebpackError")} WebpackError */ | ||||||
|  | @ -385,23 +386,22 @@ class Module extends DependenciesBlock { | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * @param {ModuleGraph} moduleGraph the module graph | 	 * @param {ModuleGraph} moduleGraph the module graph | ||||||
| 	 * @param {string} exportName a name of an export | 	 * @param {string | string[]} exportName a name of an export | ||||||
| 	 * @returns {boolean} true, if the export is used | 	 * @returns {UsageStateType} state of the export | ||||||
| 	 */ | 	 */ | ||||||
| 	isExportUsed(moduleGraph, exportName) { | 	isExportUsed(moduleGraph, exportName) { | ||||||
| 		const exportInfo = moduleGraph.getReadOnlyExportInfo(this, exportName); | 		return moduleGraph.getExportsInfo(this).isExportUsed(exportName); | ||||||
| 		return exportInfo.used !== false; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// TODO move to ModuleGraph
 | 	// TODO move to ModuleGraph
 | ||||||
| 	/** | 	/** | ||||||
| 	 * @param {ModuleGraph} moduleGraph the module graph | 	 * @param {ModuleGraph} moduleGraph the module graph | ||||||
| 	 * @param {string} exportName a name of an export | 	 * @param {string | string[]} exportName a name of an export | ||||||
| 	 * @returns {string | false} false, when module or referenced export is unused. | 	 * @returns {string | string[] | false} false, when module or referenced export is unused. | ||||||
| 	 *                           string, the mangled export name when used. | 	 *                           string, the mangled export name when used. | ||||||
| 	 */ | 	 */ | ||||||
| 	getUsedName(moduleGraph, exportName) { | 	getUsedName(moduleGraph, exportName) { | ||||||
| 		return moduleGraph.getExportInfo(this, exportName).getUsedName(); | 		return moduleGraph.getExportsInfo(this).getUsedName(exportName); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
|  |  | ||||||
|  | @ -21,6 +21,16 @@ const SortableSet = require("./util/SortableSet"); | ||||||
|  * @returns {string} |  * @returns {string} | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | /** @typedef {0|1|2|3|4} UsageStateType */ | ||||||
|  | 
 | ||||||
|  | const UsageState = Object.freeze({ | ||||||
|  | 	NoInfo: /** @type {0} */ (0), | ||||||
|  | 	Unused: /** @type {1} */ (1), | ||||||
|  | 	Unknown: /** @type {2} */ (2), | ||||||
|  | 	OnlyPropertiesUsed: /** @type {3} */ (3), | ||||||
|  | 	Used: /** @type {4} */ (4) | ||||||
|  | }); | ||||||
|  | 
 | ||||||
| class ExportsInfo { | class ExportsInfo { | ||||||
| 	constructor() { | 	constructor() { | ||||||
| 		/** @type {Map<string, ExportInfo>} */ | 		/** @type {Map<string, ExportInfo>} */ | ||||||
|  | @ -92,21 +102,21 @@ class ExportsInfo { | ||||||
| 
 | 
 | ||||||
| 	setHasUseInfo() { | 	setHasUseInfo() { | ||||||
| 		for (const exportInfo of this._exports.values()) { | 		for (const exportInfo of this._exports.values()) { | ||||||
| 			if (exportInfo.used === undefined) { | 			if (exportInfo.used === UsageState.NoInfo) { | ||||||
| 				exportInfo.used = false; | 				exportInfo.used = UsageState.Unused; | ||||||
| 			} | 			} | ||||||
| 			if (exportInfo.canMangleUse === undefined) { | 			if (exportInfo.canMangleUse === undefined) { | ||||||
| 				exportInfo.canMangleUse = true; | 				exportInfo.canMangleUse = true; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if (this._otherExportsInfo.used === undefined) { | 		if (this._otherExportsInfo.used === UsageState.NoInfo) { | ||||||
| 			this._otherExportsInfo.used = false; | 			this._otherExportsInfo.used = UsageState.Unused; | ||||||
| 		} | 		} | ||||||
| 		if (this._otherExportsInfo.canMangleUse === undefined) { | 		if (this._otherExportsInfo.canMangleUse === undefined) { | ||||||
| 			this._otherExportsInfo.canMangleUse = true; | 			this._otherExportsInfo.canMangleUse = true; | ||||||
| 		} | 		} | ||||||
| 		if (this._sideEffectsOnlyInfo.used === undefined) { | 		if (this._sideEffectsOnlyInfo.used === UsageState.NoInfo) { | ||||||
| 			this._sideEffectsOnlyInfo.used = false; | 			this._sideEffectsOnlyInfo.used = UsageState.Unused; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -127,6 +137,20 @@ class ExportsInfo { | ||||||
| 		return this._otherExportsInfo; | 		return this._otherExportsInfo; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param {string[]=} name the export name | ||||||
|  | 	 * @returns {ExportsInfo | undefined} the nested exports info | ||||||
|  | 	 */ | ||||||
|  | 	getNestedExportsInfo(name) { | ||||||
|  | 		if (Array.isArray(name) && name.length > 0) { | ||||||
|  | 			let info = this._exports.get(name[0]); | ||||||
|  | 			if (info === undefined) info = this._otherExportsInfo; | ||||||
|  | 			if (!info.exportsInfo) return undefined; | ||||||
|  | 			return info.exportsInfo.getNestedExportsInfo(name.slice(1)); | ||||||
|  | 		} | ||||||
|  | 		return this; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * @returns {boolean} true, if this call changed something | 	 * @returns {boolean} true, if this call changed something | ||||||
| 	 */ | 	 */ | ||||||
|  | @ -163,8 +187,8 @@ class ExportsInfo { | ||||||
| 			changed = true; | 			changed = true; | ||||||
| 		} | 		} | ||||||
| 		for (const exportInfo of this._exports.values()) { | 		for (const exportInfo of this._exports.values()) { | ||||||
| 			if (exportInfo.used !== true && exportInfo.used !== null) { | 			if (exportInfo.used < UsageState.Unknown) { | ||||||
| 				exportInfo.used = null; | 				exportInfo.used = UsageState.Unknown; | ||||||
| 				changed = true; | 				changed = true; | ||||||
| 			} | 			} | ||||||
| 			if (exportInfo.canMangleUse !== false) { | 			if (exportInfo.canMangleUse !== false) { | ||||||
|  | @ -172,11 +196,8 @@ class ExportsInfo { | ||||||
| 				changed = true; | 				changed = true; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if ( | 		if (this._otherExportsInfo.used < UsageState.Unknown) { | ||||||
| 			this._otherExportsInfo.used !== true && | 			this._otherExportsInfo.used = UsageState.Unknown; | ||||||
| 			this._otherExportsInfo.used !== null |  | ||||||
| 		) { |  | ||||||
| 			this._otherExportsInfo.used = null; |  | ||||||
| 			changed = true; | 			changed = true; | ||||||
| 		} | 		} | ||||||
| 		if (this._otherExportsInfo.canMangleUse !== false) { | 		if (this._otherExportsInfo.canMangleUse !== false) { | ||||||
|  | @ -192,10 +213,10 @@ class ExportsInfo { | ||||||
| 			this._isUsed = true; | 			this._isUsed = true; | ||||||
| 			changed = true; | 			changed = true; | ||||||
| 		} | 		} | ||||||
| 		this.getExportInfo("default").used = true; | 		this.getExportInfo("default").used = UsageState.Used; | ||||||
| 		for (const exportInfo of this._exports.values()) { | 		for (const exportInfo of this._exports.values()) { | ||||||
| 			if (exportInfo.used !== true && exportInfo.used !== null) { | 			if (exportInfo.used < UsageState.Unknown) { | ||||||
| 				exportInfo.used = null; | 				exportInfo.used = UsageState.Unknown; | ||||||
| 				changed = true; | 				changed = true; | ||||||
| 			} | 			} | ||||||
| 			if (exportInfo.name !== "default" && exportInfo.canMangleUse !== false) { | 			if (exportInfo.name !== "default" && exportInfo.canMangleUse !== false) { | ||||||
|  | @ -203,11 +224,8 @@ class ExportsInfo { | ||||||
| 				changed = true; | 				changed = true; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if ( | 		if (this._otherExportsInfo.used < UsageState.Unknown) { | ||||||
| 			this._otherExportsInfo.used !== true && | 			this._otherExportsInfo.used = UsageState.Unknown; | ||||||
| 			this._otherExportsInfo.used !== null |  | ||||||
| 		) { |  | ||||||
| 			this._otherExportsInfo.used = null; |  | ||||||
| 			changed = true; | 			changed = true; | ||||||
| 		} | 		} | ||||||
| 		if (this._otherExportsInfo.canMangleUse !== false) { | 		if (this._otherExportsInfo.canMangleUse !== false) { | ||||||
|  | @ -218,22 +236,22 @@ class ExportsInfo { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	setUsedForSideEffectsOnly() { | 	setUsedForSideEffectsOnly() { | ||||||
| 		if (this._sideEffectsOnlyInfo.used === false) { | 		if (this._sideEffectsOnlyInfo.used === UsageState.Unused) { | ||||||
| 			this._sideEffectsOnlyInfo.used = true; | 			this._sideEffectsOnlyInfo.used = UsageState.Used; | ||||||
| 			return true; | 			return true; | ||||||
| 		} | 		} | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	isUsed() { | 	isUsed() { | ||||||
| 		if (this._otherExportsInfo.used !== false) { | 		if (this._otherExportsInfo.used !== UsageState.Unused) { | ||||||
| 			return true; | 			return true; | ||||||
| 		} | 		} | ||||||
| 		if (this._sideEffectsOnlyInfo.used !== false) { | 		if (this._sideEffectsOnlyInfo.used !== UsageState.Unused) { | ||||||
| 			return true; | 			return true; | ||||||
| 		} | 		} | ||||||
| 		for (const exportInfo of this._exports.values()) { | 		for (const exportInfo of this._exports.values()) { | ||||||
| 			if (exportInfo.used !== false) { | 			if (exportInfo.used !== UsageState.Unused) { | ||||||
| 				return true; | 				return true; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -242,30 +260,32 @@ class ExportsInfo { | ||||||
| 
 | 
 | ||||||
| 	getUsedExports() { | 	getUsedExports() { | ||||||
| 		switch (this._otherExportsInfo.used) { | 		switch (this._otherExportsInfo.used) { | ||||||
| 			case undefined: | 			case UsageState.NoInfo: | ||||||
| 				return null; | 				return null; | ||||||
| 			case null: | 			case UsageState.Unknown: | ||||||
| 				return true; | 				return true; | ||||||
| 			case true: | 			case UsageState.OnlyPropertiesUsed: | ||||||
|  | 			case UsageState.Used: | ||||||
| 				return true; | 				return true; | ||||||
| 		} | 		} | ||||||
| 		const array = []; | 		const array = []; | ||||||
| 		if (!this._exportsAreOrdered) this._sortExports(); | 		if (!this._exportsAreOrdered) this._sortExports(); | ||||||
| 		for (const exportInfo of this._exports.values()) { | 		for (const exportInfo of this._exports.values()) { | ||||||
| 			switch (exportInfo.used) { | 			switch (exportInfo.used) { | ||||||
| 				case undefined: | 				case UsageState.NoInfo: | ||||||
| 					return null; | 					return null; | ||||||
| 				case null: | 				case UsageState.Unknown: | ||||||
| 					return true; | 					return true; | ||||||
| 				case true: | 				case UsageState.OnlyPropertiesUsed: | ||||||
|  | 				case UsageState.Used: | ||||||
| 					array.push(exportInfo.name); | 					array.push(exportInfo.name); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		if (array.length === 0) { | 		if (array.length === 0) { | ||||||
| 			switch (this._sideEffectsOnlyInfo.used) { | 			switch (this._sideEffectsOnlyInfo.used) { | ||||||
| 				case undefined: | 				case UsageState.NoInfo: | ||||||
| 					return null; | 					return null; | ||||||
| 				case false: | 				case UsageState.Unused: | ||||||
| 					return false; | 					return false; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -296,12 +316,61 @@ class ExportsInfo { | ||||||
| 		return array; | 		return array; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param {string | string[]} name the name of the export | ||||||
|  | 	 * @returns {boolean | undefined | null} if the export is provided | ||||||
|  | 	 */ | ||||||
| 	isExportProvided(name) { | 	isExportProvided(name) { | ||||||
|  | 		if (Array.isArray(name)) { | ||||||
|  | 			// TODO follow nested exports
 | ||||||
|  | 			return this.isExportProvided(name[0]); | ||||||
|  | 		} | ||||||
| 		let info = this._exports.get(name); | 		let info = this._exports.get(name); | ||||||
| 		if (info === undefined) info = this._otherExportsInfo; | 		if (info === undefined) info = this._otherExportsInfo; | ||||||
| 		return info.provided; | 		return info.provided; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param {string | string[]} name export name | ||||||
|  | 	 * @returns {UsageStateType} usage status | ||||||
|  | 	 */ | ||||||
|  | 	isExportUsed(name) { | ||||||
|  | 		if (Array.isArray(name)) { | ||||||
|  | 			if (name.length === 0) return this.otherExportsInfo.used; | ||||||
|  | 			// TODO follow nested exports
 | ||||||
|  | 			return this.isExportUsed(name[0]); | ||||||
|  | 		} | ||||||
|  | 		let info = this._exports.get(name); | ||||||
|  | 		if (info === undefined) info = this._otherExportsInfo; | ||||||
|  | 		return info.used; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * @param {string | string[]} name the export name | ||||||
|  | 	 * @returns {string | string[] | false} the used name | ||||||
|  | 	 */ | ||||||
|  | 	getUsedName(name) { | ||||||
|  | 		if (Array.isArray(name)) { | ||||||
|  | 			// TODO improve this
 | ||||||
|  | 			if (name.length === 0) return name; | ||||||
|  | 			let info = this._exports.get(name[0]); | ||||||
|  | 			if (info === undefined) info = this._otherExportsInfo; | ||||||
|  | 			const x = info.getUsedName(); | ||||||
|  | 			if (!x) return false; | ||||||
|  | 			if (info.exportsInfo) { | ||||||
|  | 				const nested = info.exportsInfo.getUsedName(name.slice(1)); | ||||||
|  | 				if (!nested) return false; | ||||||
|  | 				return [x].concat(nested); | ||||||
|  | 			} else { | ||||||
|  | 				return [x].concat(name.slice(1)); | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			let info = this._exports.get(name); | ||||||
|  | 			if (info === undefined) info = this._otherExportsInfo; | ||||||
|  | 			return info.getUsedName(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	getRestoreProvidedData() { | 	getRestoreProvidedData() { | ||||||
| 		const otherProvided = this._otherExportsInfo.provided; | 		const otherProvided = this._otherExportsInfo.provided; | ||||||
| 		const otherCanMangleProvide = this._otherExportsInfo.canMangleProvide; | 		const otherCanMangleProvide = this._otherExportsInfo.canMangleProvide; | ||||||
|  | @ -350,14 +419,8 @@ class ExportInfo { | ||||||
| 		this.name = name; | 		this.name = name; | ||||||
| 		/** @type {string | null} */ | 		/** @type {string | null} */ | ||||||
| 		this.usedName = initFrom ? initFrom.usedName : null; | 		this.usedName = initFrom ? initFrom.usedName : null; | ||||||
| 		/** | 		/** @type {UsageStateType} */ | ||||||
| 		 * true: it is used | 		this.used = initFrom ? initFrom.used : UsageState.NoInfo; | ||||||
| 		 * false: it is not used |  | ||||||
| 		 * null: only the runtime knows if it is used |  | ||||||
| 		 * undefined: it was not determined if it is used |  | ||||||
| 		 * @type {boolean | null | undefined} |  | ||||||
| 		 */ |  | ||||||
| 		this.used = initFrom ? initFrom.used : undefined; |  | ||||||
| 		/** | 		/** | ||||||
| 		 * true: it is provided | 		 * true: it is provided | ||||||
| 		 * false: it is not provided | 		 * false: it is not provided | ||||||
|  | @ -380,6 +443,8 @@ class ExportInfo { | ||||||
| 		 * @type {boolean | undefined} | 		 * @type {boolean | undefined} | ||||||
| 		 */ | 		 */ | ||||||
| 		this.canMangleUse = initFrom ? initFrom.canMangleUse : undefined; | 		this.canMangleUse = initFrom ? initFrom.canMangleUse : undefined; | ||||||
|  | 		/** @type {ExportsInfo=} */ | ||||||
|  | 		this.exportsInfo = undefined; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	get canMangle() { | 	get canMangle() { | ||||||
|  | @ -406,20 +471,22 @@ class ExportInfo { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	getUsedName() { | 	getUsedName() { | ||||||
| 		if (this.used === false) return false; | 		if (this.used === UsageState.Unused) return false; | ||||||
| 		return this.usedName || this.name; | 		return this.usedName || this.name; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	getUsedInfo() { | 	getUsedInfo() { | ||||||
| 		switch (this.used) { | 		switch (this.used) { | ||||||
| 			case undefined: | 			case UsageState.NoInfo: | ||||||
| 				return "no usage info"; | 				return "no usage info"; | ||||||
| 			case null: | 			case UsageState.Unknown: | ||||||
| 				return "maybe used (runtime-defined)"; | 				return "maybe used (runtime-defined)"; | ||||||
| 			case true: | 			case UsageState.Used: | ||||||
| 				return "used"; | 				return "used"; | ||||||
| 			case false: | 			case UsageState.Unused: | ||||||
| 				return "unused"; | 				return "unused"; | ||||||
|  | 			case UsageState.OnlyPropertiesUsed: | ||||||
|  | 				return "only properties used"; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -828,7 +895,7 @@ class ModuleGraph { | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * @param {Module} module the module | 	 * @param {Module} module the module | ||||||
| 	 * @param {string} exportName a name of an export | 	 * @param {string | string[]} exportName a name of an export | ||||||
| 	 * @returns {boolean | null} true, if the export is provided by the module. | 	 * @returns {boolean | null} true, if the export is provided by the module. | ||||||
| 	 *                           null, if it's unknown. | 	 *                           null, if it's unknown. | ||||||
| 	 *                           false, if it's not provided. | 	 *                           false, if it's not provided. | ||||||
|  | @ -1044,3 +1111,6 @@ const deprecateMap = new Map(); | ||||||
| 
 | 
 | ||||||
| module.exports = ModuleGraph; | module.exports = ModuleGraph; | ||||||
| module.exports.ModuleGraphConnection = ModuleGraphConnection; | module.exports.ModuleGraphConnection = ModuleGraphConnection; | ||||||
|  | module.exports.ExportsInfo = ExportsInfo; | ||||||
|  | module.exports.ExportInfo = ExportInfo; | ||||||
|  | module.exports.UsageState = UsageState; | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| 
 | 
 | ||||||
| const RuntimeGlobals = require("./RuntimeGlobals"); | const RuntimeGlobals = require("./RuntimeGlobals"); | ||||||
| const Template = require("./Template"); | const Template = require("./Template"); | ||||||
|  | const propertyAccess = require("./util/propertyAccess"); | ||||||
| 
 | 
 | ||||||
| /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */ | /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */ | ||||||
| /** @typedef {import("./ChunkGraph")} ChunkGraph */ | /** @typedef {import("./ChunkGraph")} ChunkGraph */ | ||||||
|  | @ -14,6 +15,14 @@ const Template = require("./Template"); | ||||||
| /** @typedef {import("./ModuleGraph")} ModuleGraph */ | /** @typedef {import("./ModuleGraph")} ModuleGraph */ | ||||||
| /** @typedef {import("./RequestShortener")} RequestShortener */ | /** @typedef {import("./RequestShortener")} RequestShortener */ | ||||||
| 
 | 
 | ||||||
|  | const arrayEquals = (a, b) => { | ||||||
|  | 	if (a.length !== b.length) return false; | ||||||
|  | 	for (let i = 0; i < a.length; i++) { | ||||||
|  | 		if (a[i] !== b[i]) return false; | ||||||
|  | 	} | ||||||
|  | 	return true; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| class RuntimeTemplate { | class RuntimeTemplate { | ||||||
| 	/** | 	/** | ||||||
| 	 * @param {TODO} outputOptions the compilation output options | 	 * @param {TODO} outputOptions the compilation output options | ||||||
|  | @ -506,7 +515,7 @@ class RuntimeTemplate { | ||||||
| 	 * @param {ModuleGraph} options.moduleGraph the module graph | 	 * @param {ModuleGraph} options.moduleGraph the module graph | ||||||
| 	 * @param {Module} options.module the module | 	 * @param {Module} options.module the module | ||||||
| 	 * @param {string} options.request the request | 	 * @param {string} options.request the request | ||||||
| 	 * @param {string} options.exportName the export name | 	 * @param {string | string[]} options.exportName the export name | ||||||
| 	 * @param {Module} options.originModule the origin module | 	 * @param {Module} options.originModule the origin module | ||||||
| 	 * @param {boolean} options.asiSafe true, if location is safe for ASI, a bracket can be emitted | 	 * @param {boolean} options.asiSafe true, if location is safe for ASI, a bracket can be emitted | ||||||
| 	 * @param {boolean} options.isCall true, if expression will be called | 	 * @param {boolean} options.isCall true, if expression will be called | ||||||
|  | @ -532,24 +541,30 @@ class RuntimeTemplate { | ||||||
| 				request | 				request | ||||||
| 			}); | 			}); | ||||||
| 		} | 		} | ||||||
|  | 		if (!Array.isArray(exportName)) { | ||||||
|  | 			exportName = exportName ? [exportName] : []; | ||||||
|  | 		} | ||||||
| 		const exportsType = module.buildMeta && module.buildMeta.exportsType; | 		const exportsType = module.buildMeta && module.buildMeta.exportsType; | ||||||
| 
 | 
 | ||||||
| 		if (!exportsType) { | 		if (!exportsType) { | ||||||
| 			if (exportName === "default") { | 			if (exportName.length > 0 && exportName[0] === "default") { | ||||||
| 				if (!originModule.buildMeta.strictHarmonyModule) { | 				if (!originModule.buildMeta.strictHarmonyModule) { | ||||||
| 					if (isCall) { | 					if (isCall) { | ||||||
| 						return `${importVar}_default()`; | 						return `${importVar}_default()${propertyAccess(exportName, 1)}`; | ||||||
| 					} else if (asiSafe) { | 					} else if (asiSafe) { | ||||||
| 						return `(${importVar}_default())`; | 						return `(${importVar}_default()${propertyAccess(exportName, 1)})`; | ||||||
| 					} else { | 					} else { | ||||||
| 						return `${importVar}_default.a`; | 						return `${importVar}_default.a${propertyAccess(exportName, 1)}`; | ||||||
| 					} | 					} | ||||||
| 				} else { | 				} else { | ||||||
| 					return importVar; | 					return `${importVar}${propertyAccess(exportName, 1)}`; | ||||||
| 				} | 				} | ||||||
| 			} else if (originModule.buildMeta.strictHarmonyModule) { | 			} else if (originModule.buildMeta.strictHarmonyModule) { | ||||||
| 				if (exportName) { | 				if (exportName.length > 0) { | ||||||
| 					return "/* non-default import from non-esm module */undefined"; | 					return ( | ||||||
|  | 						"/* non-default import from non-esm module */undefined" + | ||||||
|  | 						propertyAccess(exportName, 1) | ||||||
|  | 					); | ||||||
| 				} else { | 				} else { | ||||||
| 					runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject); | 					runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject); | ||||||
| 					return `/*#__PURE__*/${ | 					return `/*#__PURE__*/${ | ||||||
|  | @ -560,26 +575,30 @@ class RuntimeTemplate { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (exportsType === "named") { | 		if (exportsType === "named") { | ||||||
| 			if (exportName === "default") { | 			if (exportName.length > 0 && exportName[0] === "default") { | ||||||
| 				return importVar; | 				return `${importVar}${propertyAccess(exportName, 1)}`; | ||||||
| 			} else if (!exportName) { | 			} else if (exportName.length === 0) { | ||||||
| 				return `${importVar}_namespace`; | 				return `${importVar}_namespace`; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (exportName) { | 		if (exportName.length > 0) { | ||||||
| 			const used = module.getUsedName(moduleGraph, exportName); | 			const exportsInfo = moduleGraph.getExportsInfo(module); | ||||||
|  | 			const used = exportsInfo.getUsedName(exportName); | ||||||
| 			if (!used) { | 			if (!used) { | ||||||
| 				const comment = Template.toNormalComment(`unused export ${exportName}`); | 				const comment = Template.toNormalComment( | ||||||
|  | 					`unused export ${exportName.join(".")}` | ||||||
|  | 				); | ||||||
| 				return `${comment} undefined`; | 				return `${comment} undefined`; | ||||||
| 			} | 			} | ||||||
| 			const comment = | 			const comment = arrayEquals(used, exportName) | ||||||
| 				used !== exportName ? Template.toNormalComment(exportName) + " " : ""; | 				? "" | ||||||
| 			const access = `${importVar}[${comment}${JSON.stringify(used)}]`; | 				: Template.toNormalComment(exportName.join(".")) + " "; | ||||||
| 			if (isCall) { | 			const access = `${importVar}${comment}${propertyAccess(used)}`; | ||||||
| 				if (callContext === false && asiSafe) { | 			if (isCall && callContext === false) { | ||||||
|  | 				if (asiSafe) { | ||||||
| 					return `(0,${access})`; | 					return `(0,${access})`; | ||||||
| 				} else if (callContext === false) { | 				} else { | ||||||
| 					return `Object(${access})`; | 					return `Object(${access})`; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ class DependencyReference { | ||||||
| 	/** | 	/** | ||||||
| 	 * | 	 * | ||||||
| 	 * @param {ModuleCallback} moduleCallback a callback to get the referenced module | 	 * @param {ModuleCallback} moduleCallback a callback to get the referenced module | ||||||
| 	 * @param {string[] | boolean} importedNames imported named from the module | 	 * @param {(string | string[])[] | boolean} importedNames imported named from the module | ||||||
| 	 * @param {boolean=} weak if this is a weak reference | 	 * @param {boolean=} weak if this is a weak reference | ||||||
| 	 * @param {number} order the order information or NaN if don't care | 	 * @param {number} order the order information or NaN if don't care | ||||||
| 	 */ | 	 */ | ||||||
|  |  | ||||||
|  | @ -95,7 +95,7 @@ module.exports = class HarmonyExportDependencyParserPlugin { | ||||||
| 					dep = new HarmonyExportImportedSpecifierDependency( | 					dep = new HarmonyExportImportedSpecifierDependency( | ||||||
| 						settings.source, | 						settings.source, | ||||||
| 						settings.sourceOrder, | 						settings.sourceOrder, | ||||||
| 						settings.id, | 						settings.ids, | ||||||
| 						name, | 						name, | ||||||
| 						harmonyNamedExports, | 						harmonyNamedExports, | ||||||
| 						null, | 						null, | ||||||
|  | @ -125,7 +125,7 @@ module.exports = class HarmonyExportDependencyParserPlugin { | ||||||
| 				const dep = new HarmonyExportImportedSpecifierDependency( | 				const dep = new HarmonyExportImportedSpecifierDependency( | ||||||
| 					source, | 					source, | ||||||
| 					parser.state.lastHarmonyImportOrder, | 					parser.state.lastHarmonyImportOrder, | ||||||
| 					id, | 					id ? [id] : [], | ||||||
| 					name, | 					name, | ||||||
| 					harmonyNamedExports, | 					harmonyNamedExports, | ||||||
| 					harmonyStarExports && harmonyStarExports.slice(), | 					harmonyStarExports && harmonyStarExports.slice(), | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| 
 | 
 | ||||||
| const HarmonyLinkingError = require("../HarmonyLinkingError"); | const HarmonyLinkingError = require("../HarmonyLinkingError"); | ||||||
| const InitFragment = require("../InitFragment"); | const InitFragment = require("../InitFragment"); | ||||||
|  | const { UsageState } = require("../ModuleGraph"); | ||||||
| const RuntimeGlobals = require("../RuntimeGlobals"); | const RuntimeGlobals = require("../RuntimeGlobals"); | ||||||
| const Template = require("../Template"); | const Template = require("../Template"); | ||||||
| const { intersect } = require("../util/SetHelpers"); | const { intersect } = require("../util/SetHelpers"); | ||||||
|  | @ -21,14 +22,15 @@ const HarmonyImportDependency = require("./HarmonyImportDependency"); | ||||||
| /** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */ | /** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */ | ||||||
| /** @typedef {import("../Module")} Module */ | /** @typedef {import("../Module")} Module */ | ||||||
| /** @typedef {import("../ModuleGraph")} ModuleGraph */ | /** @typedef {import("../ModuleGraph")} ModuleGraph */ | ||||||
|  | /** @typedef {import("../ModuleGraph").ExportsInfo} ExportsInfo */ | ||||||
| /** @typedef {import("../WebpackError")} WebpackError */ | /** @typedef {import("../WebpackError")} WebpackError */ | ||||||
| /** @typedef {import("../util/createHash").Hash} Hash */ | /** @typedef {import("../util/createHash").Hash} Hash */ | ||||||
| 
 | 
 | ||||||
| /** @typedef {"missing"|"unused"|"empty-star"|"reexport-non-harmony-default"|"reexport-named-default"|"reexport-namespace-object"|"reexport-non-harmony-default-strict"|"reexport-fake-namespace-object"|"rexport-non-harmony-undefined"|"normal-reexport"|"dynamic-reexport"} ExportModeType */ | /** @typedef {"missing"|"unused"|"empty-star"|"reexport-non-harmony-default"|"reexport-named-default"|"reexport-namespace-object"|"reexport-partial-namespace-object"|"reexport-non-harmony-default-strict"|"reexport-fake-namespace-object"|"reexport-non-harmony-undefined"|"normal-reexport"|"dynamic-reexport"} ExportModeType */ | ||||||
| 
 | 
 | ||||||
| const idSymbol = Symbol("HarmonyExportImportedSpecifierDependency.id"); | const idsSymbol = Symbol("HarmonyExportImportedSpecifierDependency.ids"); | ||||||
| 
 | 
 | ||||||
| /** @type {Map<string, string>} */ | /** @type {Map<string, string[]>} */ | ||||||
| const EMPTY_MAP = new Map(); | const EMPTY_MAP = new Map(); | ||||||
| 
 | 
 | ||||||
| /** @type {Set<string>} */ | /** @type {Set<string>} */ | ||||||
|  | @ -43,8 +45,10 @@ class ExportMode { | ||||||
| 		this.type = type; | 		this.type = type; | ||||||
| 		/** @type {string|null} */ | 		/** @type {string|null} */ | ||||||
| 		this.name = null; | 		this.name = null; | ||||||
| 		/** @type {Map<string, string>} */ | 		/** @type {Map<string, string[]>} */ | ||||||
| 		this.map = EMPTY_MAP; | 		this.map = EMPTY_MAP; | ||||||
|  | 		/** @type {ExportsInfo} */ | ||||||
|  | 		this.partialNamespaceExportsInfo = undefined; | ||||||
| 		/** @type {Set<string>|null} */ | 		/** @type {Set<string>|null} */ | ||||||
| 		this.ignored = null; | 		this.ignored = null; | ||||||
| 		/** @type {Set<string>|null} */ | 		/** @type {Set<string>|null} */ | ||||||
|  | @ -60,7 +64,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 	/** | 	/** | ||||||
| 	 * @param {string} request the request string | 	 * @param {string} request the request string | ||||||
| 	 * @param {number} sourceOrder the order in the original source file | 	 * @param {number} sourceOrder the order in the original source file | ||||||
| 	 * @param {string | null} id the requested export name of the imported module | 	 * @param {string[]} ids the requested export name of the imported module | ||||||
| 	 * @param {string | null} name the export name of for this module | 	 * @param {string | null} name the export name of for this module | ||||||
| 	 * @param {Set<string>} activeExports other named exports in the module | 	 * @param {Set<string>} activeExports other named exports in the module | ||||||
| 	 * @param {Iterable<Dependency>} otherStarExports other star exports in the module | 	 * @param {Iterable<Dependency>} otherStarExports other star exports in the module | ||||||
|  | @ -69,7 +73,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 	constructor( | 	constructor( | ||||||
| 		request, | 		request, | ||||||
| 		sourceOrder, | 		sourceOrder, | ||||||
| 		id, | 		ids, | ||||||
| 		name, | 		name, | ||||||
| 		activeExports, | 		activeExports, | ||||||
| 		otherStarExports, | 		otherStarExports, | ||||||
|  | @ -77,32 +81,47 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 	) { | 	) { | ||||||
| 		super(request, sourceOrder); | 		super(request, sourceOrder); | ||||||
| 
 | 
 | ||||||
| 		this.id = id; | 		this.ids = ids; | ||||||
| 		this.name = name; | 		this.name = name; | ||||||
| 		this.activeExports = activeExports; | 		this.activeExports = activeExports; | ||||||
| 		this.otherStarExports = otherStarExports; | 		this.otherStarExports = otherStarExports; | ||||||
| 		this.strictExportPresence = strictExportPresence; | 		this.strictExportPresence = strictExportPresence; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// TODO webpack 6 remove
 | ||||||
|  | 	get id() { | ||||||
|  | 		throw new Error("id was renamed to ids and type changed to string[]"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// TODO webpack 6 remove
 | ||||||
|  | 	getId() { | ||||||
|  | 		throw new Error("id was renamed to ids and type changed to string[]"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// TODO webpack 6 remove
 | ||||||
|  | 	setId() { | ||||||
|  | 		throw new Error("id was renamed to ids and type changed to string[]"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	get type() { | 	get type() { | ||||||
| 		return "harmony export imported specifier"; | 		return "harmony export imported specifier"; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * @param {ModuleGraph} moduleGraph the module graph | 	 * @param {ModuleGraph} moduleGraph the module graph | ||||||
| 	 * @returns {string} the imported id | 	 * @returns {string[]} the imported id | ||||||
| 	 */ | 	 */ | ||||||
| 	getId(moduleGraph) { | 	getIds(moduleGraph) { | ||||||
| 		return moduleGraph.getMeta(this)[idSymbol] || this.id; | 		return moduleGraph.getMeta(this)[idsSymbol] || this.ids; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * @param {ModuleGraph} moduleGraph the module graph | 	 * @param {ModuleGraph} moduleGraph the module graph | ||||||
| 	 * @param {string} id the imported id | 	 * @param {string[]} ids the imported ids | ||||||
| 	 * @returns {void} | 	 * @returns {void} | ||||||
| 	 */ | 	 */ | ||||||
| 	setId(moduleGraph, id) { | 	setIds(moduleGraph, ids) { | ||||||
| 		moduleGraph.getMeta(this)[idSymbol] = id; | 		moduleGraph.getMeta(this)[idsSymbol] = ids; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
|  | @ -112,9 +131,10 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 	 */ | 	 */ | ||||||
| 	getMode(moduleGraph, ignoreUnused) { | 	getMode(moduleGraph, ignoreUnused) { | ||||||
| 		const name = this.name; | 		const name = this.name; | ||||||
| 		const id = this.getId(moduleGraph); | 		const ids = this.getIds(moduleGraph); | ||||||
| 		const parentModule = moduleGraph.getParentModule(this); | 		const parentModule = moduleGraph.getParentModule(this); | ||||||
| 		const importedModule = moduleGraph.getModule(this); | 		const importedModule = moduleGraph.getModule(this); | ||||||
|  | 		const exportsInfo = moduleGraph.getExportsInfo(parentModule); | ||||||
| 
 | 
 | ||||||
| 		if (!importedModule) { | 		if (!importedModule) { | ||||||
| 			const mode = new ExportMode("missing"); | 			const mode = new ExportMode("missing"); | ||||||
|  | @ -127,8 +147,8 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 		if ( | 		if ( | ||||||
| 			!ignoreUnused && | 			!ignoreUnused && | ||||||
| 			(name | 			(name | ||||||
| 				? parentModule.isExportUsed(moduleGraph, name) === false | 				? exportsInfo.isExportUsed(name) === UsageState.Unused | ||||||
| 				: parentModule.isModuleUsed(moduleGraph) === false) | 				: exportsInfo.isUsed() === false) | ||||||
| 		) { | 		) { | ||||||
| 			const mode = new ExportMode("unused"); | 			const mode = new ExportMode("unused"); | ||||||
| 
 | 
 | ||||||
|  | @ -141,7 +161,12 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 
 | 
 | ||||||
| 		// Special handling for reexporting the default export
 | 		// Special handling for reexporting the default export
 | ||||||
| 		// from non-harmony modules
 | 		// from non-harmony modules
 | ||||||
| 		if (name && id === "default" && importedModule.buildMeta) { | 		if ( | ||||||
|  | 			name && | ||||||
|  | 			ids.length > 0 && | ||||||
|  | 			ids[0] === "default" && | ||||||
|  | 			importedModule.buildMeta | ||||||
|  | 		) { | ||||||
| 			if (!importedModule.buildMeta.exportsType) { | 			if (!importedModule.buildMeta.exportsType) { | ||||||
| 				const mode = new ExportMode( | 				const mode = new ExportMode( | ||||||
| 					strictHarmonyModule | 					strictHarmonyModule | ||||||
|  | @ -169,15 +194,16 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 		// reexporting with a fixed name
 | 		// reexporting with a fixed name
 | ||||||
| 		if (name) { | 		if (name) { | ||||||
| 			let mode; | 			let mode; | ||||||
|  | 			const exportInfo = exportsInfo.getReadOnlyExportInfo(name); | ||||||
| 
 | 
 | ||||||
| 			if (id) { | 			if (ids.length > 0) { | ||||||
| 				// export { name as name }
 | 				// export { name as name }
 | ||||||
| 				if (isNotAHarmonyModule && strictHarmonyModule) { | 				if (isNotAHarmonyModule && strictHarmonyModule) { | ||||||
| 					mode = new ExportMode("rexport-non-harmony-undefined"); | 					mode = new ExportMode("reexport-non-harmony-undefined"); | ||||||
| 					mode.name = name; | 					mode.name = name; | ||||||
| 				} else { | 				} else { | ||||||
| 					mode = new ExportMode("normal-reexport"); | 					mode = new ExportMode("normal-reexport"); | ||||||
| 					mode.map = new Map([[name, id]]); | 					mode.map = new Map([[name, ids]]); | ||||||
| 					mode.checked = EMPTY_SET; | 					mode.checked = EMPTY_SET; | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
|  | @ -185,6 +211,14 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 				if (isNotAHarmonyModule && strictHarmonyModule) { | 				if (isNotAHarmonyModule && strictHarmonyModule) { | ||||||
| 					mode = new ExportMode("reexport-fake-namespace-object"); | 					mode = new ExportMode("reexport-fake-namespace-object"); | ||||||
| 					mode.name = name; | 					mode.name = name; | ||||||
|  | 				} else if ( | ||||||
|  | 					exportInfo.used === UsageState.OnlyPropertiesUsed && | ||||||
|  | 					exportInfo.exportsInfo && | ||||||
|  | 					exportInfo.exportsInfo.otherExportsInfo.used === UsageState.Unused | ||||||
|  | 				) { | ||||||
|  | 					mode = new ExportMode("reexport-partial-namespace-object"); | ||||||
|  | 					mode.name = name; | ||||||
|  | 					mode.partialNamespaceExportsInfo = exportInfo.exportsInfo; | ||||||
| 				} else { | 				} else { | ||||||
| 					mode = new ExportMode("reexport-namespace-object"); | 					mode = new ExportMode("reexport-namespace-object"); | ||||||
| 					mode.name = name; | 					mode.name = name; | ||||||
|  | @ -198,12 +232,12 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 
 | 
 | ||||||
| 		// Star reexporting
 | 		// Star reexporting
 | ||||||
| 
 | 
 | ||||||
| 		const exportsInfo = moduleGraph.getExportsInfo(parentModule); |  | ||||||
| 		const importedExportsInfo = moduleGraph.getExportsInfo(importedModule); | 		const importedExportsInfo = moduleGraph.getExportsInfo(importedModule); | ||||||
| 
 | 
 | ||||||
| 		const noExtraExports = | 		const noExtraExports = | ||||||
| 			importedExportsInfo.otherExportsInfo.provided === false; | 			importedExportsInfo.otherExportsInfo.provided === false; | ||||||
| 		const noExtraImports = exportsInfo.otherExportsInfo.used === false; | 		const noExtraImports = | ||||||
|  | 			exportsInfo.otherExportsInfo.used === UsageState.Unused; | ||||||
| 
 | 
 | ||||||
| 		const ignoredExports = new Set([ | 		const ignoredExports = new Set([ | ||||||
| 			"default", | 			"default", | ||||||
|  | @ -233,7 +267,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 		if (noExtraImports) { | 		if (noExtraImports) { | ||||||
| 			for (const exportInfo of exportsInfo.exports) { | 			for (const exportInfo of exportsInfo.exports) { | ||||||
| 				if (ignoredExports.has(exportInfo.name)) continue; | 				if (ignoredExports.has(exportInfo.name)) continue; | ||||||
| 				if (exportInfo.used !== false) { | 				if (exportInfo.used !== UsageState.Unused) { | ||||||
| 					imports.add(exportInfo.name); | 					imports.add(exportInfo.name); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | @ -272,10 +306,10 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 			return mode; | 			return mode; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		/** @type {Map<string, string>} */ | 		/** @type {Map<string, string[]>} */ | ||||||
| 		const map = new Map(); | 		const map = new Map(); | ||||||
| 		for (const exportName of merged) { | 		for (const exportName of merged) { | ||||||
| 			map.set(exportName, exportName); | 			map.set(exportName, [exportName]); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		const mode = new ExportMode("normal-reexport"); | 		const mode = new ExportMode("normal-reexport"); | ||||||
|  | @ -310,10 +344,37 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 					this.sourceOrder | 					this.sourceOrder | ||||||
| 				); | 				); | ||||||
| 
 | 
 | ||||||
|  | 			case "reexport-partial-namespace-object": { | ||||||
|  | 				const importedNames = []; | ||||||
|  | 				const processExportsInfo = (prefix, exportsInfo) => { | ||||||
|  | 					for (const exportInfo of exportsInfo.orderedExports) { | ||||||
|  | 						if ( | ||||||
|  | 							exportInfo.used === UsageState.OnlyPropertiesUsed && | ||||||
|  | 							exportInfo.exportsInfo && | ||||||
|  | 							exportInfo.exportsInfo.otherExportsInfo.used === UsageState.Unused | ||||||
|  | 						) { | ||||||
|  | 							processExportsInfo( | ||||||
|  | 								prefix.concat(exportInfo.name), | ||||||
|  | 								exportInfo.exportsInfo | ||||||
|  | 							); | ||||||
|  | 						} else if (exportInfo.used !== UsageState.Unused) { | ||||||
|  | 							importedNames.push(prefix.concat(exportInfo.name)); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				}; | ||||||
|  | 				processExportsInfo([], mode.partialNamespaceExportsInfo); | ||||||
|  | 				return new DependencyReference( | ||||||
|  | 					mode.getModule, | ||||||
|  | 					importedNames, | ||||||
|  | 					false, | ||||||
|  | 					this.sourceOrder | ||||||
|  | 				); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
| 			case "reexport-namespace-object": | 			case "reexport-namespace-object": | ||||||
| 			case "reexport-non-harmony-default-strict": | 			case "reexport-non-harmony-default-strict": | ||||||
| 			case "reexport-fake-namespace-object": | 			case "reexport-fake-namespace-object": | ||||||
| 			case "rexport-non-harmony-undefined": | 			case "reexport-non-harmony-undefined": | ||||||
| 				return new DependencyReference( | 				return new DependencyReference( | ||||||
| 					mode.getModule, | 					mode.getModule, | ||||||
| 					true, | 					true, | ||||||
|  | @ -395,20 +456,34 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 				}; | 				}; | ||||||
| 			case "normal-reexport": | 			case "normal-reexport": | ||||||
| 				return { | 				return { | ||||||
| 					exports: Array.from(mode.map.keys()), | 					exports: Array.from(mode.map.keys()).map(name => ({ | ||||||
|  | 						name, | ||||||
|  | 						from: mode.getModule(), | ||||||
|  | 						export: mode.map.get(name) | ||||||
|  | 					})), | ||||||
| 					dependencies: [mode.getModule()] | 					dependencies: [mode.getModule()] | ||||||
| 				}; | 				}; | ||||||
| 			case "reexport-fake-namespace-object": | 			case "reexport-fake-namespace-object": | ||||||
| 			case "reexport-namespace-object": |  | ||||||
| 			case "reexport-non-harmony-default": | 			case "reexport-non-harmony-default": | ||||||
| 			case "reexport-non-harmony-default-strict": | 			case "reexport-non-harmony-default-strict": | ||||||
| 			case "rexport-non-harmony-undefined": | 			case "reexport-non-harmony-undefined": | ||||||
| 			case "reexport-named-default": | 			case "reexport-named-default": | ||||||
| 				return { | 				return { | ||||||
| 					exports: [mode.name], | 					exports: [mode.name], | ||||||
| 					dependencies: [mode.getModule()] | 					dependencies: [mode.getModule()] | ||||||
| 				}; | 				}; | ||||||
| 
 | 			case "reexport-namespace-object": | ||||||
|  | 			case "reexport-partial-namespace-object": | ||||||
|  | 				return { | ||||||
|  | 					exports: [ | ||||||
|  | 						{ | ||||||
|  | 							name: mode.name, | ||||||
|  | 							from: mode.getModule(), | ||||||
|  | 							export: null | ||||||
|  | 						} | ||||||
|  | 					], | ||||||
|  | 					dependencies: [mode.getModule()] | ||||||
|  | 				}; | ||||||
| 			default: | 			default: | ||||||
| 				throw new Error(`Unknown mode ${mode.type}`); | 				throw new Error(`Unknown mode ${mode.type}`); | ||||||
| 		} | 		} | ||||||
|  | @ -457,18 +532,19 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		const id = this.getId(moduleGraph); | 		const ids = this.getIds(moduleGraph); | ||||||
| 
 | 
 | ||||||
| 		if (!importedModule.buildMeta || !importedModule.buildMeta.exportsType) { | 		if (!importedModule.buildMeta || !importedModule.buildMeta.exportsType) { | ||||||
| 			// It's not an harmony module
 | 			// It's not an harmony module
 | ||||||
| 			if ( | 			if ( | ||||||
| 				moduleGraph.getParentModule(this).buildMeta.strictHarmonyModule && | 				moduleGraph.getParentModule(this).buildMeta.strictHarmonyModule && | ||||||
| 				id !== "default" | 				(ids.length === 0 || ids[0] !== "default") | ||||||
| 			) { | 			) { | ||||||
| 				// In strict harmony modules we only support the default export
 | 				// In strict harmony modules we only support the default export
 | ||||||
| 				const exportName = id | 				const exportName = | ||||||
| 					? `the named export '${id}'` | 					ids.length > 0 | ||||||
| 					: "the namespace object"; | 						? `the named export ${ids.map(id => `'${id}'`).join(".")}` | ||||||
|  | 						: "the namespace object"; | ||||||
| 
 | 
 | ||||||
| 				return [ | 				return [ | ||||||
| 					new HarmonyLinkingError( | 					new HarmonyLinkingError( | ||||||
|  | @ -480,21 +556,21 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (!id) { | 		if (ids.length === 0) { | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (moduleGraph.isExportProvided(importedModule, id) !== false) { | 		if (moduleGraph.isExportProvided(importedModule, ids) !== false) { | ||||||
| 			// It's provided or we are not sure
 | 			// It's provided or we are not sure
 | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// We are sure that it's not provided
 | 		// We are sure that it's not provided
 | ||||||
| 		const idIsNotNameMessage = | 		const idIsNotNameMessage = | ||||||
| 			id !== this.name ? ` (reexported as '${this.name}')` : ""; | 			ids.join(".") !== this.name ? ` (reexported as '${this.name}')` : ""; | ||||||
| 		const errorMessage = `"export '${id}'${idIsNotNameMessage} was not found in '${ | 		const errorMessage = `"export ${this.ids | ||||||
| 			this.userRequest | 			.map(id => `'${id}'`) | ||||||
| 		}'`;
 | 			.join(".")}${idIsNotNameMessage} was not found in '${this.userRequest}'`;
 | ||||||
| 
 | 
 | ||||||
| 		return [new HarmonyLinkingError(errorMessage)]; | 		return [new HarmonyLinkingError(errorMessage)]; | ||||||
| 	} | 	} | ||||||
|  | @ -513,7 +589,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 		hash.update(mode.type); | 		hash.update(mode.type); | ||||||
| 		for (const [k, v] of mode.map) { | 		for (const [k, v] of mode.map) { | ||||||
| 			hash.update(k); | 			hash.update(k); | ||||||
| 			hash.update(v); | 			hash.update(v.join()); | ||||||
| 		} | 		} | ||||||
| 		if (mode.ignored) { | 		if (mode.ignored) { | ||||||
| 			hash.update("ignored"); | 			hash.update("ignored"); | ||||||
|  | @ -527,7 +603,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 	serialize(context) { | 	serialize(context) { | ||||||
| 		const { write } = context; | 		const { write } = context; | ||||||
| 
 | 
 | ||||||
| 		write(this.id); | 		write(this.ids); | ||||||
| 		write(this.name); | 		write(this.name); | ||||||
| 		write(this.activeExports); | 		write(this.activeExports); | ||||||
| 		write(this.otherStarExports); | 		write(this.otherStarExports); | ||||||
|  | @ -539,7 +615,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | ||||||
| 	deserialize(context) { | 	deserialize(context) { | ||||||
| 		const { read } = context; | 		const { read } = context; | ||||||
| 
 | 
 | ||||||
| 		this.id = read(); | 		this.ids = read(); | ||||||
| 		this.name = read(); | 		this.name = read(); | ||||||
| 		this.activeExports = read(); | 		this.activeExports = read(); | ||||||
| 		this.otherStarExports = read(); | 		this.otherStarExports = read(); | ||||||
|  | @ -685,7 +761,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS | ||||||
| 				); | 				); | ||||||
| 				break; | 				break; | ||||||
| 
 | 
 | ||||||
| 			case "rexport-non-harmony-undefined": | 			case "reexport-non-harmony-undefined": | ||||||
| 				initFragments.push( | 				initFragments.push( | ||||||
| 					new InitFragment( | 					new InitFragment( | ||||||
| 						"/* harmony reexport (non default export from non-harmony) */ " + | 						"/* harmony reexport (non default export from non-harmony) */ " + | ||||||
|  | @ -720,6 +796,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS | ||||||
| 				break; | 				break; | ||||||
| 
 | 
 | ||||||
| 			case "reexport-namespace-object": | 			case "reexport-namespace-object": | ||||||
|  | 			case "reexport-partial-namespace-object": | ||||||
| 				initFragments.push( | 				initFragments.push( | ||||||
| 					new InitFragment( | 					new InitFragment( | ||||||
| 						"/* harmony reexport (module object) */ " + | 						"/* harmony reexport (module object) */ " + | ||||||
|  |  | ||||||
|  | @ -44,9 +44,10 @@ module.exports = class HarmonyImportDependencyParserPlugin { | ||||||
| 				if (!parser.state.harmonySpecifier) { | 				if (!parser.state.harmonySpecifier) { | ||||||
| 					parser.state.harmonySpecifier = new Map(); | 					parser.state.harmonySpecifier = new Map(); | ||||||
| 				} | 				} | ||||||
|  | 				const ids = id === null ? [] : [id]; | ||||||
| 				parser.state.harmonySpecifier.set(name, { | 				parser.state.harmonySpecifier.set(name, { | ||||||
| 					source, | 					source, | ||||||
| 					id, | 					ids, | ||||||
| 					sourceOrder: parser.state.lastHarmonyImportOrder | 					sourceOrder: parser.state.lastHarmonyImportOrder | ||||||
| 				}); | 				}); | ||||||
| 				return true; | 				return true; | ||||||
|  | @ -60,7 +61,7 @@ module.exports = class HarmonyImportDependencyParserPlugin { | ||||||
| 				const dep = new HarmonyImportSpecifierDependency( | 				const dep = new HarmonyImportSpecifierDependency( | ||||||
| 					settings.source, | 					settings.source, | ||||||
| 					settings.sourceOrder, | 					settings.sourceOrder, | ||||||
| 					settings.id, | 					settings.ids, | ||||||
| 					name, | 					name, | ||||||
| 					expr.range, | 					expr.range, | ||||||
| 					this.strictExportPresence | 					this.strictExportPresence | ||||||
|  | @ -71,45 +72,40 @@ module.exports = class HarmonyImportDependencyParserPlugin { | ||||||
| 				parser.state.module.addDependency(dep); | 				parser.state.module.addDependency(dep); | ||||||
| 				return true; | 				return true; | ||||||
| 			}); | 			}); | ||||||
| 		parser.hooks.expressionAnyMember | 		parser.hooks.expressionMemberChain | ||||||
| 			.for("imported var") | 			.for("imported var") | ||||||
| 			.tap("HarmonyImportDependencyParserPlugin", expr => { | 			.tap("HarmonyImportDependencyParserPlugin", (expr, name, members) => { | ||||||
| 				const name = expr.object.name; |  | ||||||
| 				const settings = parser.state.harmonySpecifier.get(name); | 				const settings = parser.state.harmonySpecifier.get(name); | ||||||
| 				if (settings.id !== null) return false; | 				const ids = settings.ids.concat(members); | ||||||
| 				const dep = new HarmonyImportSpecifierDependency( | 				const dep = new HarmonyImportSpecifierDependency( | ||||||
| 					settings.source, | 					settings.source, | ||||||
| 					settings.sourceOrder, | 					settings.sourceOrder, | ||||||
| 					expr.property.name || expr.property.value, | 					ids, | ||||||
| 					name, | 					name, | ||||||
| 					expr.range, | 					expr.range, | ||||||
| 					this.strictExportPresence | 					this.strictExportPresence | ||||||
| 				); | 				); | ||||||
| 				dep.shorthand = parser.scope.inShorthand; |  | ||||||
| 				dep.directImport = false; |  | ||||||
| 				dep.loc = expr.loc; | 				dep.loc = expr.loc; | ||||||
| 				parser.state.module.addDependency(dep); | 				parser.state.module.addDependency(dep); | ||||||
| 				return true; | 				return true; | ||||||
| 			}); | 			}); | ||||||
| 		if (this.strictThisContextOnImports) { | 		if (this.strictThisContextOnImports) { | ||||||
| 			// only in case when we strictly follow the spec we need a special case here
 | 			// only in case when we strictly follow the spec we need a special case here
 | ||||||
| 			parser.hooks.callAnyMember | 			parser.hooks.callMemberChain | ||||||
| 				.for("imported var") | 				.for("imported var") | ||||||
| 				.tap("HarmonyImportDependencyParserPlugin", expr => { | 				.tap("HarmonyImportDependencyParserPlugin", (expr, name, members) => { | ||||||
| 					if (expr.callee.type !== "MemberExpression") return; | 					if (members.length <= 0) return; | ||||||
| 					if (expr.callee.object.type !== "Identifier") return; |  | ||||||
| 					const name = expr.callee.object.name; |  | ||||||
| 					const settings = parser.state.harmonySpecifier.get(name); | 					const settings = parser.state.harmonySpecifier.get(name); | ||||||
| 					if (settings.id !== null) return false; | 					if (settings.ids.length > 0) return false; | ||||||
|  | 					const ids = settings.ids.concat(members); | ||||||
| 					const dep = new HarmonyImportSpecifierDependency( | 					const dep = new HarmonyImportSpecifierDependency( | ||||||
| 						settings.source, | 						settings.source, | ||||||
| 						settings.sourceOrder, | 						settings.sourceOrder, | ||||||
| 						expr.callee.property.name || expr.callee.property.value, | 						ids, | ||||||
| 						name, | 						name, | ||||||
| 						expr.callee.range, | 						expr.callee.range, | ||||||
| 						this.strictExportPresence | 						this.strictExportPresence | ||||||
| 					); | 					); | ||||||
| 					dep.shorthand = parser.scope.inShorthand; |  | ||||||
| 					dep.directImport = false; | 					dep.directImport = false; | ||||||
| 					dep.namespaceObjectAsContext = true; | 					dep.namespaceObjectAsContext = true; | ||||||
| 					dep.loc = expr.callee.loc; | 					dep.loc = expr.callee.loc; | ||||||
|  | @ -129,7 +125,7 @@ module.exports = class HarmonyImportDependencyParserPlugin { | ||||||
| 				const dep = new HarmonyImportSpecifierDependency( | 				const dep = new HarmonyImportSpecifierDependency( | ||||||
| 					settings.source, | 					settings.source, | ||||||
| 					settings.sourceOrder, | 					settings.sourceOrder, | ||||||
| 					settings.id, | 					settings.ids, | ||||||
| 					name, | 					name, | ||||||
| 					expr.range, | 					expr.range, | ||||||
| 					this.strictExportPresence | 					this.strictExportPresence | ||||||
|  |  | ||||||
|  | @ -19,12 +19,12 @@ const HarmonyImportDependency = require("./HarmonyImportDependency"); | ||||||
| /** @typedef {import("../WebpackError")} WebpackError */ | /** @typedef {import("../WebpackError")} WebpackError */ | ||||||
| /** @typedef {import("../util/createHash").Hash} Hash */ | /** @typedef {import("../util/createHash").Hash} Hash */ | ||||||
| 
 | 
 | ||||||
| const idSymbol = Symbol("HarmonyImportSpecifierDependency.id"); | const idsSymbol = Symbol("HarmonyImportSpecifierDependency.ids"); | ||||||
| 
 | 
 | ||||||
| class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | ||||||
| 	constructor(request, sourceOrder, id, name, range, strictExportPresence) { | 	constructor(request, sourceOrder, ids, name, range, strictExportPresence) { | ||||||
| 		super(request, sourceOrder); | 		super(request, sourceOrder); | ||||||
| 		this.id = id === null ? null : `${id}`; | 		this.ids = ids; | ||||||
| 		this.name = name; | 		this.name = name; | ||||||
| 		this.range = range; | 		this.range = range; | ||||||
| 		this.strictExportPresence = strictExportPresence; | 		this.strictExportPresence = strictExportPresence; | ||||||
|  | @ -34,25 +34,40 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | ||||||
| 		this.shorthand = undefined; | 		this.shorthand = undefined; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	// TODO webpack 6 remove
 | ||||||
|  | 	get id() { | ||||||
|  | 		throw new Error("id was renamed to ids and type changed to string[]"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// TODO webpack 6 remove
 | ||||||
|  | 	getId() { | ||||||
|  | 		throw new Error("id was renamed to ids and type changed to string[]"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// TODO webpack 6 remove
 | ||||||
|  | 	setId() { | ||||||
|  | 		throw new Error("id was renamed to ids and type changed to string[]"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	get type() { | 	get type() { | ||||||
| 		return "harmony import specifier"; | 		return "harmony import specifier"; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * @param {ModuleGraph} moduleGraph the module graph | 	 * @param {ModuleGraph} moduleGraph the module graph | ||||||
| 	 * @returns {string} the imported id | 	 * @returns {string[]} the imported ids | ||||||
| 	 */ | 	 */ | ||||||
| 	getId(moduleGraph) { | 	getIds(moduleGraph) { | ||||||
| 		return moduleGraph.getMeta(this)[idSymbol] || this.id; | 		return moduleGraph.getMeta(this)[idsSymbol] || this.ids; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * @param {ModuleGraph} moduleGraph the module graph | 	 * @param {ModuleGraph} moduleGraph the module graph | ||||||
| 	 * @param {string} id the imported id | 	 * @param {string[]} ids the imported ids | ||||||
| 	 * @returns {void} | 	 * @returns {void} | ||||||
| 	 */ | 	 */ | ||||||
| 	setId(moduleGraph, id) { | 	setIds(moduleGraph, ids) { | ||||||
| 		moduleGraph.getMeta(this)[idSymbol] = id; | 		moduleGraph.getMeta(this)[idsSymbol] = ids; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
|  | @ -63,11 +78,10 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | ||||||
| 	getReference(moduleGraph) { | 	getReference(moduleGraph) { | ||||||
| 		const module = moduleGraph.getModule(this); | 		const module = moduleGraph.getModule(this); | ||||||
| 		if (!module) return null; | 		if (!module) return null; | ||||||
|  | 		const ids = this.getIds(moduleGraph); | ||||||
| 		return new DependencyReference( | 		return new DependencyReference( | ||||||
| 			() => moduleGraph.getModule(this), | 			() => moduleGraph.getModule(this), | ||||||
| 			this.getId(moduleGraph) && !this.namespaceObjectAsContext | 			ids.length > 0 && !this.namespaceObjectAsContext ? [ids] : true, | ||||||
| 				? [this.getId(moduleGraph)] |  | ||||||
| 				: true, |  | ||||||
| 			false, | 			false, | ||||||
| 			this.sourceOrder | 			this.sourceOrder | ||||||
| 		); | 		); | ||||||
|  | @ -113,16 +127,18 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		const ids = this.getIds(moduleGraph); | ||||||
| 		if (!importedModule.buildMeta || !importedModule.buildMeta.exportsType) { | 		if (!importedModule.buildMeta || !importedModule.buildMeta.exportsType) { | ||||||
| 			// It's not an harmony module
 | 			// It's not an harmony module
 | ||||||
| 			if ( | 			if ( | ||||||
| 				moduleGraph.getParentModule(this).buildMeta.strictHarmonyModule && | 				moduleGraph.getParentModule(this).buildMeta.strictHarmonyModule && | ||||||
| 				this.getId(moduleGraph) !== "default" | 				(ids.length === 0 || ids[0] !== "default") | ||||||
| 			) { | 			) { | ||||||
| 				// In strict harmony modules we only support the default export
 | 				// In strict harmony modules we only support the default export
 | ||||||
| 				const exportName = this.getId(moduleGraph) | 				const exportName = | ||||||
| 					? `the named export '${this.getId(moduleGraph)}'` | 					ids.length > 0 | ||||||
| 					: "the namespace object"; | 						? `the named export '${ids[0]}'` | ||||||
|  | 						: "the namespace object"; | ||||||
| 				return [ | 				return [ | ||||||
| 					new HarmonyLinkingError( | 					new HarmonyLinkingError( | ||||||
| 						`Can't import ${exportName} from non EcmaScript module (only default export is available)` | 						`Can't import ${exportName} from non EcmaScript module (only default export is available)` | ||||||
|  | @ -132,22 +148,21 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		const id = this.getId(moduleGraph); | 		if (ids.length === 0) { | ||||||
| 		if (!id) { |  | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (moduleGraph.isExportProvided(importedModule, id) !== false) { | 		if (moduleGraph.isExportProvided(importedModule, ids) !== false) { | ||||||
| 			// It's provided or we are not sure
 | 			// It's provided or we are not sure
 | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// We are sure that it's not provided
 | 		// We are sure that it's not provided
 | ||||||
| 		const idIsNotNameMessage = | 		const idIsNotNameMessage = | ||||||
| 			id !== this.name ? ` (imported as '${this.name}')` : ""; | 			ids[0] !== this.name ? ` (imported as '${this.name}')` : ""; | ||||||
| 		const errorMessage = `"export '${this.getId( | 		const errorMessage = `"export ${ids | ||||||
| 			moduleGraph | 			.map(id => `'${id}'`) | ||||||
| 		)}'${idIsNotNameMessage} was not found in '${this.userRequest}'`;
 | 			.join(".")}${idIsNotNameMessage} was not found in '${this.userRequest}'`;
 | ||||||
| 		return [new HarmonyLinkingError(errorMessage)]; | 		return [new HarmonyLinkingError(errorMessage)]; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -169,10 +184,11 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | ||||||
| 		super.updateHash(hash, chunkGraph); | 		super.updateHash(hash, chunkGraph); | ||||||
| 		const moduleGraph = chunkGraph.moduleGraph; | 		const moduleGraph = chunkGraph.moduleGraph; | ||||||
| 		const importedModule = moduleGraph.getModule(this); | 		const importedModule = moduleGraph.getModule(this); | ||||||
|  | 		const ids = this.getIds(moduleGraph); | ||||||
|  | 		hash.update(ids.join()); | ||||||
| 		if (importedModule) { | 		if (importedModule) { | ||||||
| 			const id = this.getId(moduleGraph); | 			const exportsInfo = moduleGraph.getExportsInfo(importedModule); | ||||||
| 			hash.update(id + ""); | 			hash.update(JSON.stringify(exportsInfo.getUsedName(ids))); | ||||||
| 			hash.update((id && importedModule.getUsedName(moduleGraph, id)) + ""); |  | ||||||
| 			hash.update( | 			hash.update( | ||||||
| 				(!importedModule.buildMeta || importedModule.buildMeta.exportsType) + "" | 				(!importedModule.buildMeta || importedModule.buildMeta.exportsType) + "" | ||||||
| 			); | 			); | ||||||
|  | @ -181,7 +197,7 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | ||||||
| 
 | 
 | ||||||
| 	serialize(context) { | 	serialize(context) { | ||||||
| 		const { write } = context; | 		const { write } = context; | ||||||
| 		write(this.id); | 		write(this.ids); | ||||||
| 		write(this.name); | 		write(this.name); | ||||||
| 		write(this.range); | 		write(this.range); | ||||||
| 		write(this.strictExportPresence); | 		write(this.strictExportPresence); | ||||||
|  | @ -194,7 +210,7 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | ||||||
| 
 | 
 | ||||||
| 	deserialize(context) { | 	deserialize(context) { | ||||||
| 		const { read } = context; | 		const { read } = context; | ||||||
| 		this.id = read(); | 		this.ids = read(); | ||||||
| 		this.name = read(); | 		this.name = read(); | ||||||
| 		this.range = read(); | 		this.range = read(); | ||||||
| 		this.strictExportPresence = read(); | 		this.strictExportPresence = read(); | ||||||
|  | @ -229,11 +245,12 @@ HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependen | ||||||
| 		dep, | 		dep, | ||||||
| 		{ runtimeTemplate, module, moduleGraph, runtimeRequirements } | 		{ runtimeTemplate, module, moduleGraph, runtimeRequirements } | ||||||
| 	) { | 	) { | ||||||
|  | 		const ids = dep.getIds(moduleGraph); | ||||||
| 		const exportExpr = runtimeTemplate.exportFromImport({ | 		const exportExpr = runtimeTemplate.exportFromImport({ | ||||||
| 			moduleGraph, | 			moduleGraph, | ||||||
| 			module: moduleGraph.getModule(dep), | 			module: moduleGraph.getModule(dep), | ||||||
| 			request: dep.request, | 			request: dep.request, | ||||||
| 			exportName: dep.getId(moduleGraph), | 			exportName: ids, | ||||||
| 			originModule: module, | 			originModule: module, | ||||||
| 			asiSafe: dep.shorthand, | 			asiSafe: dep.shorthand, | ||||||
| 			isCall: dep.call, | 			isCall: dep.call, | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ const DependencyTemplate = require("../DependencyTemplate"); | ||||||
| const InitFragment = require("../InitFragment"); | const InitFragment = require("../InitFragment"); | ||||||
| const JavascriptParser = require("../JavascriptParser"); | const JavascriptParser = require("../JavascriptParser"); | ||||||
| const Module = require("../Module"); | const Module = require("../Module"); | ||||||
|  | const { UsageState } = require("../ModuleGraph"); | ||||||
| const RuntimeGlobals = require("../RuntimeGlobals"); | const RuntimeGlobals = require("../RuntimeGlobals"); | ||||||
| const Template = require("../Template"); | const Template = require("../Template"); | ||||||
| const DependencyReference = require("../dependencies/DependencyReference"); | const DependencyReference = require("../dependencies/DependencyReference"); | ||||||
|  | @ -23,6 +24,7 @@ const HarmonyImportSideEffectDependency = require("../dependencies/HarmonyImport | ||||||
| const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency"); | const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency"); | ||||||
| const createHash = require("../util/createHash"); | const createHash = require("../util/createHash"); | ||||||
| const contextify = require("../util/identifier").contextify; | const contextify = require("../util/identifier").contextify; | ||||||
|  | const propertyAccess = require("../util/propertyAccess"); | ||||||
| 
 | 
 | ||||||
| /** @typedef {import("webpack-sources").Source} Source */ | /** @typedef {import("webpack-sources").Source} Source */ | ||||||
| /** @typedef {import("../ChunkGraph")} ChunkGraph */ | /** @typedef {import("../ChunkGraph")} ChunkGraph */ | ||||||
|  | @ -38,23 +40,29 @@ const contextify = require("../util/identifier").contextify; | ||||||
| /** @typedef {import("../WebpackError")} WebpackError */ | /** @typedef {import("../WebpackError")} WebpackError */ | ||||||
| /** @typedef {import("../util/createHash").Hash} Hash */ | /** @typedef {import("../util/createHash").Hash} Hash */ | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @typedef {Object} ReexportInfo | ||||||
|  |  * @property {Module} module | ||||||
|  |  * @property {string[]} exportName | ||||||
|  |  * @property {Dependency} dependency | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
| /** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo } ModuleInfo */ | /** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo } ModuleInfo */ | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * @typedef {Object} ConcatenatedModuleInfo |  * @typedef {Object} ConcatenatedModuleInfo | ||||||
|  * @property {"concatenated"} type |  * @property {"concatenated"} type | ||||||
|  * @property {Module} module |  * @property {Module} module | ||||||
|  * @property {TODO} index |  * @property {number} index | ||||||
|  * @property {TODO} ast |  * @property {Object} ast | ||||||
|  * @property {TODO} internalSource |  * @property {Source} internalSource | ||||||
|  * @property {TODO} source |  * @property {ReplaceSource} source | ||||||
|  * @property {TODO} globalScope |  * @property {TODO} globalScope | ||||||
|  * @property {TODO} moduleScope |  * @property {TODO} moduleScope | ||||||
|  * @property {TODO} internalNames |  * @property {TODO} internalNames | ||||||
|  * @property {TODO} globalExports |  * @property {Map<string | true, string>} exportMap | ||||||
|  * @property {TODO} exportMap |  * @property {Map<string, ReexportInfo>} reexportMap | ||||||
|  * @property {TODO} reexportMap |  * @property {boolean} hasNamespaceObject | ||||||
|  * @property {TODO} hasNamespaceObject |  | ||||||
|  * @property {TODO} namespaceObjectSource |  * @property {TODO} namespaceObjectSource | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | @ -62,12 +70,12 @@ const contextify = require("../util/identifier").contextify; | ||||||
|  * @typedef {Object} ExternalModuleInfo |  * @typedef {Object} ExternalModuleInfo | ||||||
|  * @property {"external"} type |  * @property {"external"} type | ||||||
|  * @property {Module} module |  * @property {Module} module | ||||||
|  * @property {TODO} index |  * @property {number} index | ||||||
|  * @property {TODO} name |  * @property {string} name | ||||||
|  * @property {TODO} interopNamespaceObjectUsed |  * @property {boolean} interopNamespaceObjectUsed | ||||||
|  * @property {TODO} interopNamespaceObjectName |  * @property {string} interopNamespaceObjectName | ||||||
|  * @property {TODO} interopDefaultAccessUsed |  * @property {boolean} interopDefaultAccessUsed | ||||||
|  * @property {TODO} interopDefaultAccessName |  * @property {string} interopDefaultAccessName | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| const RESERVED_NAMES = [ | const RESERVED_NAMES = [ | ||||||
|  | @ -105,12 +113,27 @@ const RESERVED_NAMES = [ | ||||||
| 	.join(",") | 	.join(",") | ||||||
| 	.split(","); | 	.split(","); | ||||||
| 
 | 
 | ||||||
|  | const arrayEquals = (a, b) => { | ||||||
|  | 	if (a.length !== b.length) return false; | ||||||
|  | 	for (let i = 0; i < a.length; i++) { | ||||||
|  | 		if (a[i] !== b[i]) return false; | ||||||
|  | 	} | ||||||
|  | 	return true; | ||||||
|  | }; | ||||||
| /** | /** | ||||||
|  * @typedef {Object} ConcatenationEntry |  * @typedef {Object} ConcatenationEntry | ||||||
|  * @property {"concatenated" | "external"} type |  * @property {"concatenated" | "external"} type | ||||||
|  * @property {Module} module |  * @property {Module} module | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @param {ModuleGraph} moduleGraph the module graph | ||||||
|  |  * @param {ConcatenatedModuleInfo} info module info | ||||||
|  |  * @param {Map<Module, ModuleInfo>} moduleToInfoMap moduleToInfoMap | ||||||
|  |  * @param {RequestShortener} requestShortener requestShortener | ||||||
|  |  * @param {boolean} strictHarmonyModule strictHarmonyModule | ||||||
|  |  * @returns {void} | ||||||
|  |  */ | ||||||
| const ensureNsObjSource = ( | const ensureNsObjSource = ( | ||||||
| 	moduleGraph, | 	moduleGraph, | ||||||
| 	info, | 	info, | ||||||
|  | @ -125,11 +148,12 @@ const ensureNsObjSource = ( | ||||||
| 			`var ${name} = {};`, | 			`var ${name} = {};`, | ||||||
| 			`${RuntimeGlobals.makeNamespaceObject}(${name});` | 			`${RuntimeGlobals.makeNamespaceObject}(${name});` | ||||||
| 		]; | 		]; | ||||||
| 		for (const exportName of moduleGraph.getProvidedExports(info.module)) { | 		const exportsInfo = moduleGraph.getExportsInfo(info.module); | ||||||
|  | 		for (const exportInfo of exportsInfo.orderedExports) { | ||||||
| 			const finalName = getFinalName( | 			const finalName = getFinalName( | ||||||
| 				moduleGraph, | 				moduleGraph, | ||||||
| 				info, | 				info, | ||||||
| 				exportName, | 				[exportInfo.name], | ||||||
| 				moduleToInfoMap, | 				moduleToInfoMap, | ||||||
| 				requestShortener, | 				requestShortener, | ||||||
| 				false, | 				false, | ||||||
|  | @ -137,7 +161,7 @@ const ensureNsObjSource = ( | ||||||
| 			); | 			); | ||||||
| 			nsObj.push( | 			nsObj.push( | ||||||
| 				`${RuntimeGlobals.definePropertyGetter}(${name}, ${JSON.stringify( | 				`${RuntimeGlobals.definePropertyGetter}(${name}, ${JSON.stringify( | ||||||
| 					exportName | 					exportInfo.getUsedName() | ||||||
| 				)}, function() { return ${finalName}; });` | 				)}, function() { return ${finalName}; });` | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
|  | @ -145,6 +169,15 @@ const ensureNsObjSource = ( | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @param {ModuleGraph} moduleGraph the module graph | ||||||
|  |  * @param {Module} importedModule module | ||||||
|  |  * @param {ExternalModuleInfo} info module info | ||||||
|  |  * @param {string[]} exportName exportName | ||||||
|  |  * @param {boolean} asCall asCall | ||||||
|  |  * @param {boolean} strictHarmonyModule strictHarmonyModule | ||||||
|  |  * @returns {string} expression to get value of external module | ||||||
|  |  */ | ||||||
| const getExternalImport = ( | const getExternalImport = ( | ||||||
| 	moduleGraph, | 	moduleGraph, | ||||||
| 	importedModule, | 	importedModule, | ||||||
|  | @ -154,54 +187,75 @@ const getExternalImport = ( | ||||||
| 	strictHarmonyModule | 	strictHarmonyModule | ||||||
| ) => { | ) => { | ||||||
| 	const used = | 	const used = | ||||||
| 		exportName === true || importedModule.getUsedName(moduleGraph, exportName); | 		exportName.length === 0 || | ||||||
|  | 		importedModule.getUsedName(moduleGraph, exportName); | ||||||
| 	if (!used) return "/* unused reexport */undefined"; | 	if (!used) return "/* unused reexport */undefined"; | ||||||
| 	const comment = | 	const comment = arrayEquals(used, exportName) | ||||||
| 		used !== exportName ? ` ${Template.toNormalComment(exportName)}` : ""; | 		? "" | ||||||
| 	switch (importedModule.buildMeta.exportsType) { | 		: Template.toNormalComment(`${exportName.join(".")}`); | ||||||
| 		case "named": | 	let exprStart; | ||||||
| 			if (exportName === "default") { | 	if (exportName.length === 0) { | ||||||
| 				return info.name; | 		switch (importedModule.buildMeta.exportsType) { | ||||||
| 			} else if (exportName === true) { | 			case "named": | ||||||
| 				info.interopNamespaceObjectUsed = true; | 				info.interopNamespaceObjectUsed = true; | ||||||
| 				return info.interopNamespaceObjectName; | 				exprStart = info.interopNamespaceObjectName; | ||||||
| 			} else { |  | ||||||
| 				break; | 				break; | ||||||
| 			} | 			case "namespace": | ||||||
| 		case "namespace": | 				exprStart = info.name; | ||||||
| 			if (exportName === true) { |  | ||||||
| 				return info.name; |  | ||||||
| 			} else { |  | ||||||
| 				break; | 				break; | ||||||
| 			} | 			default: | ||||||
| 		default: | 				if (strictHarmonyModule) { | ||||||
| 			if (strictHarmonyModule) { |  | ||||||
| 				if (exportName === "default") { |  | ||||||
| 					return info.name; |  | ||||||
| 				} else if (exportName === true) { |  | ||||||
| 					info.interopNamespaceObjectUsed = true; | 					info.interopNamespaceObjectUsed = true; | ||||||
| 					return info.interopNamespaceObjectName; | 					exprStart = info.interopNamespaceObjectName; | ||||||
| 				} else { | 					break; | ||||||
| 					return "/* non-default import from non-esm module */undefined"; |  | ||||||
| 				} |  | ||||||
| 			} else { |  | ||||||
| 				if (exportName === "default") { |  | ||||||
| 					info.interopDefaultAccessUsed = true; |  | ||||||
| 					return asCall |  | ||||||
| 						? `${info.interopDefaultAccessName}()` |  | ||||||
| 						: `${info.interopDefaultAccessName}.a`; |  | ||||||
| 				} else if (exportName === true) { |  | ||||||
| 					return info.name; |  | ||||||
| 				} else { | 				} else { | ||||||
|  | 					exprStart = info.name; | ||||||
| 					break; | 					break; | ||||||
| 				} | 				} | ||||||
| 			} | 		} | ||||||
|  | 	} else { | ||||||
|  | 		switch (importedModule.buildMeta.exportsType) { | ||||||
|  | 			case "named": | ||||||
|  | 				if (exportName[0] === "default") { | ||||||
|  | 					exprStart = info.name; | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 			default: | ||||||
|  | 				if (strictHarmonyModule) { | ||||||
|  | 					if (exportName[0] === "default") { | ||||||
|  | 						exprStart = info.name; | ||||||
|  | 					} else { | ||||||
|  | 						exprStart = "/* non-default import from non-esm module */undefined"; | ||||||
|  | 					} | ||||||
|  | 				} else { | ||||||
|  | 					if (exportName[0] === "default") { | ||||||
|  | 						info.interopDefaultAccessUsed = true; | ||||||
|  | 						exprStart = asCall | ||||||
|  | 							? `${info.interopDefaultAccessName}()` | ||||||
|  | 							: `${info.interopDefaultAccessName}.a`; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				break; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	const reference = `${info.name}[${JSON.stringify(used)}${comment}]`; | 	if (exprStart) { | ||||||
| 	if (asCall) return `Object(${reference})`; | 		return `${exprStart}${propertyAccess(exportName, 1)}`; | ||||||
| 	return reference; | 	} | ||||||
|  | 	const reference = `${info.name}${comment}${propertyAccess(used)}`; | ||||||
|  | 	return asCall ? `Object(${reference})` : reference; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | /** | ||||||
|  |  * @param {ModuleGraph} moduleGraph the module graph | ||||||
|  |  * @param {ModuleInfo} info module info | ||||||
|  |  * @param {string[]} exportName exportName | ||||||
|  |  * @param {Map<Module, ModuleInfo>} moduleToInfoMap moduleToInfoMap | ||||||
|  |  * @param {RequestShortener} requestShortener the request shortener | ||||||
|  |  * @param {boolean} asCall asCall | ||||||
|  |  * @param {boolean} strictHarmonyModule strictHarmonyModule | ||||||
|  |  * @param {Set<ReexportInfo>} alreadyVisited alreadyVisited | ||||||
|  |  * @returns {string} the final name | ||||||
|  |  */ | ||||||
| const getFinalName = ( | const getFinalName = ( | ||||||
| 	moduleGraph, | 	moduleGraph, | ||||||
| 	info, | 	info, | ||||||
|  | @ -214,21 +268,25 @@ const getFinalName = ( | ||||||
| ) => { | ) => { | ||||||
| 	switch (info.type) { | 	switch (info.type) { | ||||||
| 		case "concatenated": { | 		case "concatenated": { | ||||||
| 			const directExport = info.exportMap.get(exportName); | 			if (exportName.length === 0) { | ||||||
|  | 				ensureNsObjSource( | ||||||
|  | 					moduleGraph, | ||||||
|  | 					info, | ||||||
|  | 					moduleToInfoMap, | ||||||
|  | 					requestShortener, | ||||||
|  | 					strictHarmonyModule | ||||||
|  | 				); | ||||||
|  | 				return info.internalNames.get(info.exportMap.get(true)); | ||||||
|  | 			} | ||||||
|  | 			const exportId = exportName[0]; | ||||||
|  | 			const directExport = info.exportMap.get(exportId); | ||||||
|  | 			const exportsInfo = moduleGraph.getExportsInfo(info.module); | ||||||
| 			if (directExport) { | 			if (directExport) { | ||||||
| 				if (exportName === true) { | 				if (exportsInfo.isExportUsed(exportName) === UsageState.Unused) { | ||||||
| 					ensureNsObjSource( | 					return `/* unused export */ undefined${propertyAccess( | ||||||
| 						moduleGraph, | 						exportName, | ||||||
| 						info, | 						1 | ||||||
| 						moduleToInfoMap, | 					)}`;
 | ||||||
| 						requestShortener, |  | ||||||
| 						strictHarmonyModule |  | ||||||
| 					); |  | ||||||
| 				} else if (!info.module.isExportUsed(moduleGraph, exportName)) { |  | ||||||
| 					return "/* unused export */ undefined"; |  | ||||||
| 				} |  | ||||||
| 				if (info.globalExports.has(directExport)) { |  | ||||||
| 					return directExport; |  | ||||||
| 				} | 				} | ||||||
| 				const name = info.internalNames.get(directExport); | 				const name = info.internalNames.get(directExport); | ||||||
| 				if (!name) { | 				if (!name) { | ||||||
|  | @ -238,23 +296,23 @@ const getFinalName = ( | ||||||
| 						)}" has no internal name` | 						)}" has no internal name` | ||||||
| 					); | 					); | ||||||
| 				} | 				} | ||||||
| 				return name; | 				return `${name}${propertyAccess(exportName, 1)}`; | ||||||
| 			} | 			} | ||||||
| 			const reexport = info.reexportMap.get(exportName); | 			const reexport = info.reexportMap.get(exportId); | ||||||
| 			if (reexport) { | 			if (reexport) { | ||||||
| 				if (alreadyVisited.has(reexport)) { | 				if (alreadyVisited.has(reexport)) { | ||||||
| 					throw new Error( | 					throw new Error( | ||||||
| 						`Circular reexports ${Array.from( | 						`Circular reexports ${Array.from( | ||||||
| 							alreadyVisited, | 							alreadyVisited, | ||||||
| 							e => | 							e => | ||||||
| 								`"${e.module.readableIdentifier(requestShortener)}".${ | 								`"${e.module.readableIdentifier( | ||||||
| 									e.exportName | 									requestShortener | ||||||
| 								}` | 								)}".${e.exportName.join(".")}` | ||||||
| 						).join( | 						).join( | ||||||
| 							" --> " | 							" --> " | ||||||
| 						)} -(circular)-> "${reexport.module.readableIdentifier( | 						)} -(circular)-> "${reexport.module.readableIdentifier( | ||||||
| 							requestShortener | 							requestShortener | ||||||
| 						)}".${reexport.exportName}` | 						)}".${reexport.exportName.join(".")}` | ||||||
| 					); | 					); | ||||||
| 				} | 				} | ||||||
| 				alreadyVisited.add(reexport); | 				alreadyVisited.add(reexport); | ||||||
|  | @ -264,7 +322,7 @@ const getFinalName = ( | ||||||
| 					return getFinalName( | 					return getFinalName( | ||||||
| 						moduleGraph, | 						moduleGraph, | ||||||
| 						refInfo, | 						refInfo, | ||||||
| 						reexport.exportName, | 						[...reexport.exportName, ...exportName.slice(1)], | ||||||
| 						moduleToInfoMap, | 						moduleToInfoMap, | ||||||
| 						requestShortener, | 						requestShortener, | ||||||
| 						asCall, | 						asCall, | ||||||
|  | @ -281,7 +339,10 @@ const getFinalName = ( | ||||||
| 					.filter(name => name !== true) | 					.filter(name => name !== true) | ||||||
| 					.join(" ")}, ` +
 | 					.join(" ")}, ` +
 | ||||||
| 				`known reexports: ${Array.from(info.reexportMap.keys()).join(" ")})`; | 				`known reexports: ${Array.from(info.reexportMap.keys()).join(" ")})`; | ||||||
| 			return `${Template.toNormalComment(problem)} undefined`; | 			return `${Template.toNormalComment(problem)} undefined${propertyAccess( | ||||||
|  | 				exportName, | ||||||
|  | 				1 | ||||||
|  | 			)}`;
 | ||||||
| 		} | 		} | ||||||
| 		case "external": { | 		case "external": { | ||||||
| 			const importedModule = info.module; | 			const importedModule = info.module; | ||||||
|  | @ -700,17 +761,6 @@ class ConcatenatedModule extends Module { | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 
 |  | ||||||
| 				// add exported globals
 |  | ||||||
| 				const variables = new Set(); |  | ||||||
| 				for (const variable of info.moduleScope.variables) { |  | ||||||
| 					variables.add(variable.name); |  | ||||||
| 				} |  | ||||||
| 				for (const [, variable] of info.exportMap) { |  | ||||||
| 					if (!variables.has(variable)) { |  | ||||||
| 						info.globalExports.add(variable); |  | ||||||
| 					} |  | ||||||
| 				} |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -823,10 +873,12 @@ class ConcatenatedModule extends Module { | ||||||
| 						const referencedModule = modulesWithInfo[+match[1]]; | 						const referencedModule = modulesWithInfo[+match[1]]; | ||||||
| 						let exportName; | 						let exportName; | ||||||
| 						if (match[2] === "ns") { | 						if (match[2] === "ns") { | ||||||
| 							exportName = true; | 							exportName = []; | ||||||
| 						} else { | 						} else { | ||||||
| 							const exportData = match[2]; | 							const exportData = match[2]; | ||||||
| 							exportName = Buffer.from(exportData, "hex").toString("utf-8"); | 							exportName = JSON.parse( | ||||||
|  | 								Buffer.from(exportData, "hex").toString("utf-8") | ||||||
|  | 							); | ||||||
| 						} | 						} | ||||||
| 						const asCall = !!match[3]; | 						const asCall = !!match[3]; | ||||||
| 						const strictHarmonyModule = !!match[4]; | 						const strictHarmonyModule = !!match[4]; | ||||||
|  | @ -850,7 +902,10 @@ class ConcatenatedModule extends Module { | ||||||
| 		const result = new ConcatSource(); | 		const result = new ConcatSource(); | ||||||
| 
 | 
 | ||||||
| 		// add harmony compatibility flag (must be first because of possible circular dependencies)
 | 		// add harmony compatibility flag (must be first because of possible circular dependencies)
 | ||||||
| 		if (moduleGraph.getExportsInfo(this).otherExportsInfo.used !== false) { | 		if ( | ||||||
|  | 			moduleGraph.getExportsInfo(this).otherExportsInfo.used !== | ||||||
|  | 			UsageState.Unused | ||||||
|  | 		) { | ||||||
| 			result.add( | 			result.add( | ||||||
| 				runtimeTemplate.defineEsModuleFlagStatement({ | 				runtimeTemplate.defineEsModuleFlagStatement({ | ||||||
| 					exportsArgument: this.exportsArgument, | 					exportsArgument: this.exportsArgument, | ||||||
|  | @ -985,7 +1040,9 @@ class ConcatenatedModule extends Module { | ||||||
| 			let result; | 			let result; | ||||||
| 			switch (info.type) { | 			switch (info.type) { | ||||||
| 				case "concatenated": { | 				case "concatenated": { | ||||||
|  | 					/** @type {Map<string | true, string>} */ | ||||||
| 					const exportMap = new Map(); | 					const exportMap = new Map(); | ||||||
|  | 					/** @type {Map<string, ReexportInfo>} */ | ||||||
| 					const reexportMap = new Map(); | 					const reexportMap = new Map(); | ||||||
| 					for (const dep of info.module.dependencies) { | 					for (const dep of info.module.dependencies) { | ||||||
| 						if (dep instanceof HarmonyExportSpecifierDependency) { | 						if (dep instanceof HarmonyExportSpecifierDependency) { | ||||||
|  | @ -1000,21 +1057,13 @@ class ConcatenatedModule extends Module { | ||||||
| 							dep instanceof HarmonyExportImportedSpecifierDependency | 							dep instanceof HarmonyExportImportedSpecifierDependency | ||||||
| 						) { | 						) { | ||||||
| 							const exportName = dep.name; | 							const exportName = dep.name; | ||||||
| 							const importName = dep.getId(moduleGraph); | 							const importNames = dep.getIds(moduleGraph); | ||||||
| 							const importedModule = moduleGraph.getModule(dep); | 							const importedModule = moduleGraph.getModule(dep); | ||||||
| 							if (exportName && importName) { | 							if (exportName) { | ||||||
| 								if (!reexportMap.has(exportName)) { | 								if (!reexportMap.has(exportName)) { | ||||||
| 									reexportMap.set(exportName, { | 									reexportMap.set(exportName, { | ||||||
| 										module: importedModule, | 										module: importedModule, | ||||||
| 										exportName: importName, | 										exportName: importNames, | ||||||
| 										dependency: dep |  | ||||||
| 									}); |  | ||||||
| 								} |  | ||||||
| 							} else if (exportName) { |  | ||||||
| 								if (!reexportMap.has(exportName)) { |  | ||||||
| 									reexportMap.set(exportName, { |  | ||||||
| 										module: importedModule, |  | ||||||
| 										exportName: true, |  | ||||||
| 										dependency: dep | 										dependency: dep | ||||||
| 									}); | 									}); | ||||||
| 								} | 								} | ||||||
|  | @ -1030,7 +1079,7 @@ class ConcatenatedModule extends Module { | ||||||
| 										if (!reexportMap.has(name)) { | 										if (!reexportMap.has(name)) { | ||||||
| 											reexportMap.set(name, { | 											reexportMap.set(name, { | ||||||
| 												module: importedModule, | 												module: importedModule, | ||||||
| 												exportName: name, | 												exportName: [name], | ||||||
| 												dependency: dep | 												dependency: dep | ||||||
| 											}); | 											}); | ||||||
| 										} | 										} | ||||||
|  | @ -1049,7 +1098,6 @@ class ConcatenatedModule extends Module { | ||||||
| 						globalScope: undefined, | 						globalScope: undefined, | ||||||
| 						moduleScope: undefined, | 						moduleScope: undefined, | ||||||
| 						internalNames: new Map(), | 						internalNames: new Map(), | ||||||
| 						globalExports: new Set(), |  | ||||||
| 						exportMap: exportMap, | 						exportMap: exportMap, | ||||||
| 						reexportMap: reexportMap, | 						reexportMap: reexportMap, | ||||||
| 						hasNamespaceObject: false, | 						hasNamespaceObject: false, | ||||||
|  | @ -1269,15 +1317,17 @@ class HarmonyImportSpecifierDependencyConcatenatedTemplate extends DependencyTem | ||||||
| 		const strictFlag = parentModule.buildMeta.strictHarmonyModule | 		const strictFlag = parentModule.buildMeta.strictHarmonyModule | ||||||
| 			? "_strict" | 			? "_strict" | ||||||
| 			: ""; | 			: ""; | ||||||
| 		const id = dep.getId(moduleGraph); | 		const ids = dep.getIds(moduleGraph); | ||||||
| 		if (id === null) { | 		if (ids.length === 0) { | ||||||
| 			content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns${strictFlag}__`; | 			content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns${strictFlag}__`; | ||||||
| 		} else if (dep.namespaceObjectAsContext) { | 		} else if (dep.namespaceObjectAsContext && ids.length === 1) { | ||||||
| 			content = `__WEBPACK_MODULE_REFERENCE__${ | 			content = `__WEBPACK_MODULE_REFERENCE__${ | ||||||
| 				info.index | 				info.index | ||||||
| 			}_ns${strictFlag}__[${JSON.stringify(id)}]`;
 | 			}_ns${strictFlag}__${propertyAccess(ids)}`;
 | ||||||
| 		} else { | 		} else { | ||||||
| 			const exportData = Buffer.from(id, "utf-8").toString("hex"); | 			const exportData = Buffer.from(JSON.stringify(ids), "utf-8").toString( | ||||||
|  | 				"hex" | ||||||
|  | 			); | ||||||
| 			content = `__WEBPACK_MODULE_REFERENCE__${ | 			content = `__WEBPACK_MODULE_REFERENCE__${ | ||||||
| 				info.index | 				info.index | ||||||
| 			}_${exportData}${callFlag}${strictFlag}__`;
 | 			}_${exportData}${callFlag}${strictFlag}__`;
 | ||||||
|  | @ -1398,7 +1448,7 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate extends Depen | ||||||
| 	/** | 	/** | ||||||
| 	 * @typedef {Object} GetExportsResultItem | 	 * @typedef {Object} GetExportsResultItem | ||||||
| 	 * @property {string} name | 	 * @property {string} name | ||||||
| 	 * @property {string | true} id | 	 * @property {string[]} ids | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
|  | @ -1408,13 +1458,13 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate extends Depen | ||||||
| 	 */ | 	 */ | ||||||
| 	getExports(dep, { moduleGraph }) { | 	getExports(dep, { moduleGraph }) { | ||||||
| 		const importModule = moduleGraph.getModule(dep); | 		const importModule = moduleGraph.getModule(dep); | ||||||
| 		const id = dep.getId(moduleGraph); | 		const ids = dep.getIds(moduleGraph); | ||||||
| 		if (id) { | 		if (ids.length > 0) { | ||||||
| 			// export { named } from "module"
 | 			// export { named } from "module"
 | ||||||
| 			return [ | 			return [ | ||||||
| 				{ | 				{ | ||||||
| 					name: dep.name, | 					name: dep.name, | ||||||
| 					id | 					ids | ||||||
| 				} | 				} | ||||||
| 			]; | 			]; | ||||||
| 		} | 		} | ||||||
|  | @ -1423,7 +1473,7 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate extends Depen | ||||||
| 			return [ | 			return [ | ||||||
| 				{ | 				{ | ||||||
| 					name: dep.name, | 					name: dep.name, | ||||||
| 					id: true | 					ids: [] | ||||||
| 				} | 				} | ||||||
| 			]; | 			]; | ||||||
| 		} | 		} | ||||||
|  | @ -1435,7 +1485,7 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate extends Depen | ||||||
| 				.map(exp => { | 				.map(exp => { | ||||||
| 					return { | 					return { | ||||||
| 						name: exp, | 						name: exp, | ||||||
| 						id: exp | 						ids: [exp] | ||||||
| 					}; | 					}; | ||||||
| 				}); | 				}); | ||||||
| 		} | 		} | ||||||
|  | @ -1465,7 +1515,7 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate extends Depen | ||||||
| 				if (!used) { | 				if (!used) { | ||||||
| 					initFragments.push( | 					initFragments.push( | ||||||
| 						new InitFragment( | 						new InitFragment( | ||||||
| 							`/* unused concated harmony import ${dep.name} */\n`, | 							`/* unused concated harmony import ${def.name} */\n`, | ||||||
| 							InitFragment.STAGE_HARMONY_EXPORTS, | 							InitFragment.STAGE_HARMONY_EXPORTS, | ||||||
| 							1 | 							1 | ||||||
| 						) | 						) | ||||||
|  | @ -1476,12 +1526,15 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate extends Depen | ||||||
| 				const strictFlag = module.buildMeta.strictHarmonyModule | 				const strictFlag = module.buildMeta.strictHarmonyModule | ||||||
| 					? "_strict" | 					? "_strict" | ||||||
| 					: ""; | 					: ""; | ||||||
| 				if (def.id === true) { | 				if (def.ids.length === 0) { | ||||||
| 					finalName = `__WEBPACK_MODULE_REFERENCE__${ | 					finalName = `__WEBPACK_MODULE_REFERENCE__${ | ||||||
| 						info.index | 						info.index | ||||||
| 					}_ns${strictFlag}__`;
 | 					}_ns${strictFlag}__`;
 | ||||||
| 				} else { | 				} else { | ||||||
| 					const exportData = Buffer.from(def.id, "utf-8").toString("hex"); | 					const exportData = Buffer.from( | ||||||
|  | 						JSON.stringify(def.ids), | ||||||
|  | 						"utf-8" | ||||||
|  | 					).toString("hex"); | ||||||
| 					finalName = `__WEBPACK_MODULE_REFERENCE__${ | 					finalName = `__WEBPACK_MODULE_REFERENCE__${ | ||||||
| 						info.index | 						info.index | ||||||
| 					}_${exportData}${strictFlag}__`;
 | 					}_${exportData}${strictFlag}__`;
 | ||||||
|  |  | ||||||
|  | @ -104,11 +104,11 @@ class SideEffectsFlagPlugin { | ||||||
| 										if (!map) { | 										if (!map) { | ||||||
| 											reexportMaps.set(module, (map = new Map())); | 											reexportMaps.set(module, (map = new Map())); | ||||||
| 										} | 										} | ||||||
| 										for (const [key, id] of mode.map) { | 										for (const [key, ids] of mode.map) { | ||||||
| 											if (!mode.checked.has(key)) { | 											if (ids.length > 0 && !mode.checked.has(key)) { | ||||||
| 												map.set(key, { | 												map.set(key, { | ||||||
| 													module: mode.getModule(), | 													module: mode.getModule(), | ||||||
| 													exportName: id | 													exportName: ids[0] | ||||||
| 												}); | 												}); | ||||||
| 											} | 											} | ||||||
| 										} | 										} | ||||||
|  | @ -147,15 +147,24 @@ class SideEffectsFlagPlugin { | ||||||
| 								(dep instanceof HarmonyImportSpecifierDependency && | 								(dep instanceof HarmonyImportSpecifierDependency && | ||||||
| 									!dep.namespaceObjectAsContext) | 									!dep.namespaceObjectAsContext) | ||||||
| 							) { | 							) { | ||||||
| 								const mapping = map.get(dep.id); | 								// TODO improve for nested imports
 | ||||||
| 								if (mapping) { | 								const ids = dep.getIds(moduleGraph); | ||||||
| 									moduleGraph.updateModule(dep, mapping.module); | 								if (ids.length > 0) { | ||||||
| 									moduleGraph.addExplanation( | 									const mapping = map.get(ids[0]); | ||||||
| 										dep, | 									if (mapping) { | ||||||
| 										"(skipped side-effect-free modules)" | 										moduleGraph.updateModule(dep, mapping.module); | ||||||
| 									); | 										moduleGraph.addExplanation( | ||||||
| 									dep.setId(moduleGraph, mapping.exportName); | 											dep, | ||||||
| 									continue; | 											"(skipped side-effect-free modules)" | ||||||
|  | 										); | ||||||
|  | 										dep.setIds( | ||||||
|  | 											moduleGraph, | ||||||
|  | 											mapping.exportName | ||||||
|  | 												? [mapping.exportName, ...ids.slice(1)] | ||||||
|  | 												: ids.slice(1) | ||||||
|  | 										); | ||||||
|  | 										continue; | ||||||
|  | 									} | ||||||
| 								} | 								} | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
|  |  | ||||||
|  | @ -0,0 +1,25 @@ | ||||||
|  | /* | ||||||
|  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | ||||||
|  | 	Author Tobias Koppers @sokra | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | "use strict"; | ||||||
|  | 
 | ||||||
|  | const SAFE_IDENTIFIER = /^[_a-zA-Z$][_a-zA-z$0-9]*$/; | ||||||
|  | 
 | ||||||
|  | const propertyAccess = (properties, start = 0) => { | ||||||
|  | 	let str = ""; | ||||||
|  | 	for (let i = start; i < properties.length; i++) { | ||||||
|  | 		const p = properties[i]; | ||||||
|  | 		if (`${+p}` === p) { | ||||||
|  | 			str += `[${p}]`; | ||||||
|  | 		} else if (SAFE_IDENTIFIER.test(p)) { | ||||||
|  | 			str += `.${p}`; | ||||||
|  | 		} else { | ||||||
|  | 			str += `[${JSON.stringify(p)}]`; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return str; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | module.exports = propertyAccess; | ||||||
|  | @ -47,7 +47,10 @@ class WasmFinalizeExportsPlugin { | ||||||
| 									const importedNames = ref.importedNames; | 									const importedNames = ref.importedNames; | ||||||
| 
 | 
 | ||||||
| 									if (Array.isArray(importedNames)) { | 									if (Array.isArray(importedNames)) { | ||||||
| 										importedNames.forEach(name => { | 										importedNames.forEach(nameOrNames => { | ||||||
|  | 											const name = Array.isArray(nameOrNames) | ||||||
|  | 												? nameOrNames[0] | ||||||
|  | 												: nameOrNames; | ||||||
| 											// 3. and uses a func with an incompatible JS signature
 | 											// 3. and uses a func with an incompatible JS signature
 | ||||||
| 											if ( | 											if ( | ||||||
| 												Object.prototype.hasOwnProperty.call( | 												Object.prototype.hasOwnProperty.call( | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| 
 | 
 | ||||||
| const { RawSource } = require("webpack-sources"); | const { RawSource } = require("webpack-sources"); | ||||||
| const Generator = require("../Generator"); | const Generator = require("../Generator"); | ||||||
|  | const { UsageState } = require("../ModuleGraph"); | ||||||
| const RuntimeGlobals = require("../RuntimeGlobals"); | const RuntimeGlobals = require("../RuntimeGlobals"); | ||||||
| const Template = require("../Template"); | const Template = require("../Template"); | ||||||
| const WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency"); | const WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency"); | ||||||
|  | @ -148,12 +149,13 @@ class WebAssemblyJavascriptGenerator extends Generator { | ||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
| 		const copyAllExports = | 		const copyAllExports = | ||||||
| 			exportsInfo.otherExportsInfo.used === false && !needExportsCopy; | 			exportsInfo.otherExportsInfo.used === UsageState.Unused && | ||||||
|  | 			!needExportsCopy; | ||||||
| 
 | 
 | ||||||
| 		// need these globals
 | 		// need these globals
 | ||||||
| 		runtimeRequirements.add(RuntimeGlobals.module); | 		runtimeRequirements.add(RuntimeGlobals.module); | ||||||
| 		runtimeRequirements.add(RuntimeGlobals.wasmInstances); | 		runtimeRequirements.add(RuntimeGlobals.wasmInstances); | ||||||
| 		if (exportsInfo.otherExportsInfo.used !== false) { | 		if (exportsInfo.otherExportsInfo.used !== UsageState.Unused) { | ||||||
| 			runtimeRequirements.add(RuntimeGlobals.makeNamespaceObject); | 			runtimeRequirements.add(RuntimeGlobals.makeNamespaceObject); | ||||||
| 			runtimeRequirements.add(RuntimeGlobals.exports); | 			runtimeRequirements.add(RuntimeGlobals.exports); | ||||||
| 		} | 		} | ||||||
|  | @ -170,7 +172,7 @@ class WebAssemblyJavascriptGenerator extends Generator { | ||||||
| 					module.moduleArgument | 					module.moduleArgument | ||||||
| 				}.i];`,
 | 				}.i];`,
 | ||||||
| 
 | 
 | ||||||
| 				exportsInfo.otherExportsInfo.used !== false | 				exportsInfo.otherExportsInfo.used !== UsageState.Unused | ||||||
| 					? `${RuntimeGlobals.makeNamespaceObject}(${module.exportsArgument});` | 					? `${RuntimeGlobals.makeNamespaceObject}(${module.exportsArgument});` | ||||||
| 					: "", | 					: "", | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -430,7 +430,7 @@ Child all: | ||||||
| `; | `; | ||||||
| 
 | 
 | ||||||
| exports[`StatsTestCases should print correct stats for chunk-module-id-range 1`] = ` | exports[`StatsTestCases should print correct stats for chunk-module-id-range 1`] = ` | ||||||
| "Hash: 72e3b32fcbbc550ae041 | "Hash: 4b7df25b6465c464acfe | ||||||
| Time: Xms | Time: Xms | ||||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | Built at: Thu Jan 01 1970 00:00:00 GMT | ||||||
| PublicPath: (none) | PublicPath: (none) | ||||||
|  | @ -503,10 +503,10 @@ Time: Xms | ||||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | Built at: Thu Jan 01 1970 00:00:00 GMT | ||||||
| PublicPath: (none) | PublicPath: (none) | ||||||
|               Asset       Size       Chunks             Chunk Names |               Asset       Size       Chunks             Chunk Names | ||||||
|      b_js.bundle.js  370 bytes       {b_js}  [emitted] |      b_js.bundle.js  364 bytes       {b_js}  [emitted] | ||||||
|           bundle.js   8.23 KiB       {main}  [emitted]  main |           bundle.js   8.22 KiB       {main}  [emitted]  main | ||||||
|      c_js.bundle.js  579 bytes       {c_js}  [emitted] |      c_js.bundle.js  573 bytes       {c_js}  [emitted] | ||||||
| d_js-e_js.bundle.js  772 bytes  {d_js-e_js}  [emitted] | d_js-e_js.bundle.js  760 bytes  {d_js-e_js}  [emitted] | ||||||
| Entrypoint main = bundle.js | Entrypoint main = bundle.js | ||||||
| chunk {b_js} b_js.bundle.js 22 bytes <{main}> [rendered] | chunk {b_js} b_js.bundle.js 22 bytes <{main}> [rendered] | ||||||
|     > ./b [./index.js] ./index.js 2:0-16 |     > ./b [./index.js] ./index.js 2:0-16 | ||||||
|  | @ -618,26 +618,26 @@ Entrypoint entry-1 = vendor-1.js entry-1.js | ||||||
| `; | `; | ||||||
| 
 | 
 | ||||||
| exports[`StatsTestCases should print correct stats for commons-plugin-issue-4980 1`] = ` | exports[`StatsTestCases should print correct stats for commons-plugin-issue-4980 1`] = ` | ||||||
| "Hash: 53f13412753ee8bb3d387595bab0743d3d05a312 | "Hash: ada681c866c95e0132eff2c9453ed201db5580c2 | ||||||
| Child | Child | ||||||
|     Hash: 53f13412753ee8bb3d38 |     Hash: ada681c866c95e0132ef | ||||||
|     Time: Xms |     Time: Xms | ||||||
|     Built at: Thu Jan 01 1970 00:00:00 GMT |     Built at: Thu Jan 01 1970 00:00:00 GMT | ||||||
|                              Asset       Size  Chunks             Chunk Names |                              Asset       Size  Chunks             Chunk Names | ||||||
|        app.269cd87fa0cbcfa98d1b.js   6.65 KiB   {143}  [emitted]  app |        app.72745ea3abc585e103e5.js   6.69 KiB   {143}  [emitted]  app | ||||||
|     vendor.37b166c3b85bfb1caf5f.js  616 bytes   {736}  [emitted]  vendor |     vendor.22698e25646290b0dcc1.js  616 bytes   {736}  [emitted]  vendor | ||||||
|     Entrypoint app = vendor.37b166c3b85bfb1caf5f.js app.269cd87fa0cbcfa98d1b.js |     Entrypoint app = vendor.22698e25646290b0dcc1.js app.72745ea3abc585e103e5.js | ||||||
|     [117] ./entry-1.js + 2 modules 190 bytes {143} [built] |     [117] ./entry-1.js + 2 modules 190 bytes {143} [built] | ||||||
|     [381] ./constants.js 87 bytes {736} [built] |     [381] ./constants.js 87 bytes {736} [built] | ||||||
|         + 4 hidden modules |         + 4 hidden modules | ||||||
| Child | Child | ||||||
|     Hash: 7595bab0743d3d05a312 |     Hash: f2c9453ed201db5580c2 | ||||||
|     Time: Xms |     Time: Xms | ||||||
|     Built at: Thu Jan 01 1970 00:00:00 GMT |     Built at: Thu Jan 01 1970 00:00:00 GMT | ||||||
|                              Asset       Size  Chunks             Chunk Names |                              Asset       Size  Chunks             Chunk Names | ||||||
|        app.3ec38d64835ee4418bb3.js   6.67 KiB   {143}  [emitted]  app |        app.eee68844dbd56e9ed525.js    6.7 KiB   {143}  [emitted]  app | ||||||
|     vendor.37b166c3b85bfb1caf5f.js  616 bytes   {736}  [emitted]  vendor |     vendor.22698e25646290b0dcc1.js  616 bytes   {736}  [emitted]  vendor | ||||||
|     Entrypoint app = vendor.37b166c3b85bfb1caf5f.js app.3ec38d64835ee4418bb3.js |     Entrypoint app = vendor.22698e25646290b0dcc1.js app.eee68844dbd56e9ed525.js | ||||||
|     [381] ./constants.js 87 bytes {736} [built] |     [381] ./constants.js 87 bytes {736} [built] | ||||||
|     [655] ./entry-2.js + 2 modules 197 bytes {143} [built] |     [655] ./entry-2.js + 2 modules 197 bytes {143} [built] | ||||||
|         + 4 hidden modules" |         + 4 hidden modules" | ||||||
|  | @ -1087,7 +1087,7 @@ chunk {trees} trees.js (trees) 71 bytes [rendered] | ||||||
| `; | `; | ||||||
| 
 | 
 | ||||||
| exports[`StatsTestCases should print correct stats for import-context-filter 1`] = ` | exports[`StatsTestCases should print correct stats for import-context-filter 1`] = ` | ||||||
| "Hash: 49f607faddf9699cbef8 | "Hash: 99ab54650501715e52b3 | ||||||
| Time: Xms | Time: Xms | ||||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | Built at: Thu Jan 01 1970 00:00:00 GMT | ||||||
|    Asset       Size  Chunks             Chunk Names |    Asset       Size  Chunks             Chunk Names | ||||||
|  | @ -1453,7 +1453,7 @@ If you don't want to include a polyfill, you can use an empty module like this: | ||||||
| `; | `; | ||||||
| 
 | 
 | ||||||
| exports[`StatsTestCases should print correct stats for module-reasons 1`] = ` | exports[`StatsTestCases should print correct stats for module-reasons 1`] = ` | ||||||
| "Hash: 9e3985f832f4d566fdbb | "Hash: 9757fb3da1f7b8f77bbb | ||||||
| Time: Xms | Time: Xms | ||||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | Built at: Thu Jan 01 1970 00:00:00 GMT | ||||||
|   Asset      Size  Chunks             Chunk Names |   Asset      Size  Chunks             Chunk Names | ||||||
|  | @ -1476,7 +1476,7 @@ Entrypoint main = main.js | ||||||
|  [10] ./index.js 19 bytes {179} [built] |  [10] ./index.js 19 bytes {179} [built] | ||||||
| [195] ./not-existing.js 26 bytes {179} [built] | [195] ./not-existing.js 26 bytes {179} [built] | ||||||
| [587] ./inner.js 53 bytes {179} [built] | [587] ./inner.js 53 bytes {179} [built] | ||||||
| [636] ./parse-error.js 167 bytes {179} [built] [failed] [1 error] | [636] ./parse-error.js 27 bytes {179} [built] [failed] [1 error] | ||||||
| 
 | 
 | ||||||
| ERROR in ./not-existing.js 1:0-25 | ERROR in ./not-existing.js 1:0-25 | ||||||
| Module not found: Error: Can't resolve 'does-not-exist' in 'Xdir/module-trace-disabled-in-error' | Module not found: Error: Can't resolve 'does-not-exist' in 'Xdir/module-trace-disabled-in-error' | ||||||
|  | @ -1501,7 +1501,7 @@ Entrypoint main = main.js | ||||||
|  [10] ./index.js 19 bytes {179} [built] |  [10] ./index.js 19 bytes {179} [built] | ||||||
| [195] ./not-existing.js 26 bytes {179} [built] | [195] ./not-existing.js 26 bytes {179} [built] | ||||||
| [587] ./inner.js 53 bytes {179} [built] | [587] ./inner.js 53 bytes {179} [built] | ||||||
| [636] ./parse-error.js 167 bytes {179} [built] [failed] [1 error] | [636] ./parse-error.js 27 bytes {179} [built] [failed] [1 error] | ||||||
| 
 | 
 | ||||||
| ERROR in ./not-existing.js 1:0-25 | ERROR in ./not-existing.js 1:0-25 | ||||||
| Module not found: Error: Can't resolve 'does-not-exist' in 'Xdir/module-trace-enabled-in-error' | Module not found: Error: Can't resolve 'does-not-exist' in 'Xdir/module-trace-enabled-in-error' | ||||||
|  | @ -1686,7 +1686,7 @@ exports[`StatsTestCases should print correct stats for parse-error 1`] = ` | ||||||
| main.js  4.34 KiB   {179}  main | main.js  4.34 KiB   {179}  main | ||||||
| Entrypoint main = main.js | Entrypoint main = main.js | ||||||
| [535] ./index.js + 1 modules 35 bytes {179} [built] | [535] ./index.js + 1 modules 35 bytes {179} [built] | ||||||
| [996] ./b.js 169 bytes {179} [built] [failed] [1 error] | [996] ./b.js 55 bytes {179} [built] [failed] [1 error] | ||||||
|     + 4 hidden modules |     + 4 hidden modules | ||||||
| 
 | 
 | ||||||
| ERROR in ./b.js 6:7 | ERROR in ./b.js 6:7 | ||||||
|  | @ -2289,7 +2289,7 @@ Entrypoint e2 = runtime.js e2.js" | ||||||
| `; | `; | ||||||
| 
 | 
 | ||||||
| exports[`StatsTestCases should print correct stats for scope-hoisting-bailouts 1`] = ` | exports[`StatsTestCases should print correct stats for scope-hoisting-bailouts 1`] = ` | ||||||
| "Hash: ac1889126d1918a36204 | "Hash: b4a9cfa089ce3732efc5 | ||||||
| Time: Xms | Time: Xms | ||||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | Built at: Thu Jan 01 1970 00:00:00 GMT | ||||||
| Entrypoint index = index.js | Entrypoint index = index.js | ||||||
|  | @ -2318,9 +2318,9 @@ Entrypoint entry = entry.js | ||||||
| `; | `; | ||||||
| 
 | 
 | ||||||
| exports[`StatsTestCases should print correct stats for scope-hoisting-multi 1`] = ` | exports[`StatsTestCases should print correct stats for scope-hoisting-multi 1`] = ` | ||||||
| "Hash: 0b46c17cd9c6ad0fbfb2a8733d1161800e5d8cb5 | "Hash: d4c3cd048bdc678bb92437745aea03a16f764c79 | ||||||
| Child | Child | ||||||
|     Hash: 0b46c17cd9c6ad0fbfb2 |     Hash: d4c3cd048bdc678bb924 | ||||||
|     Time: Xms |     Time: Xms | ||||||
|     Built at: Thu Jan 01 1970 00:00:00 GMT |     Built at: Thu Jan 01 1970 00:00:00 GMT | ||||||
|     Entrypoint first = vendor.js first.js |     Entrypoint first = vendor.js first.js | ||||||
|  | @ -2338,7 +2338,7 @@ Child | ||||||
|     [965] ./vendor.js 25 bytes {736} [built] |     [965] ./vendor.js 25 bytes {736} [built] | ||||||
|         + 10 hidden modules |         + 10 hidden modules | ||||||
| Child | Child | ||||||
|     Hash: a8733d1161800e5d8cb5 |     Hash: 37745aea03a16f764c79 | ||||||
|     Time: Xms |     Time: Xms | ||||||
|     Built at: Thu Jan 01 1970 00:00:00 GMT |     Built at: Thu Jan 01 1970 00:00:00 GMT | ||||||
|     Entrypoint first = vendor.js first.js |     Entrypoint first = vendor.js first.js | ||||||
|  | @ -2365,11 +2365,11 @@ Child | ||||||
| `; | `; | ||||||
| 
 | 
 | ||||||
| exports[`StatsTestCases should print correct stats for side-effects-issue-7428 1`] = ` | exports[`StatsTestCases should print correct stats for side-effects-issue-7428 1`] = ` | ||||||
| "Hash: 8d106e0a6c9f100fb26f | "Hash: 8871bd720c1e20111581 | ||||||
| Time: Xms | Time: Xms | ||||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | Built at: Thu Jan 01 1970 00:00:00 GMT | ||||||
|   Asset       Size  Chunks             Chunk Names |   Asset       Size  Chunks             Chunk Names | ||||||
|    1.js  481 bytes     {1}  [emitted] |    1.js  478 bytes     {1}  [emitted] | ||||||
| main.js   10.1 KiB     {0}  [emitted]  main | main.js   10.1 KiB     {0}  [emitted]  main | ||||||
| Entrypoint main = main.js | Entrypoint main = main.js | ||||||
| [0] ./main.js + 1 modules 231 bytes {0} [built] | [0] ./main.js + 1 modules 231 bytes {0} [built] | ||||||
|  | @ -2414,7 +2414,7 @@ Entrypoint main = main.js | ||||||
| `; | `; | ||||||
| 
 | 
 | ||||||
| exports[`StatsTestCases should print correct stats for side-effects-simple-unused 1`] = ` | exports[`StatsTestCases should print correct stats for side-effects-simple-unused 1`] = ` | ||||||
| "Hash: aabd6d1544eb169e22e5 | "Hash: 589af6828de7c047d0c5 | ||||||
| Time: Xms | Time: Xms | ||||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | Built at: Thu Jan 01 1970 00:00:00 GMT | ||||||
|   Asset      Size  Chunks             Chunk Names |   Asset      Size  Chunks             Chunk Names | ||||||
|  | @ -2450,7 +2450,7 @@ exports[`StatsTestCases should print correct stats for simple 1`] = ` | ||||||
| Time: Xms | Time: Xms | ||||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | Built at: Thu Jan 01 1970 00:00:00 GMT | ||||||
|     Asset      Size  Chunks             Chunk Names |     Asset      Size  Chunks             Chunk Names | ||||||
| bundle.js  1.56 KiB  {main}  [emitted]  main | bundle.js  1.55 KiB  {main}  [emitted]  main | ||||||
| Entrypoint main = bundle.js | Entrypoint main = bundle.js | ||||||
| [./index.js] 1 bytes {main} [built]" | [./index.js] 1 bytes {main} [built]" | ||||||
| `; | `; | ||||||
|  | @ -3446,7 +3446,7 @@ chunk {794} default/async-a.js (async-a) 134 bytes <{179}> [rendered] | ||||||
| `; | `; | ||||||
| 
 | 
 | ||||||
| exports[`StatsTestCases should print correct stats for tree-shaking 1`] = ` | exports[`StatsTestCases should print correct stats for tree-shaking 1`] = ` | ||||||
| "Hash: a74d3a7695fab0e2d9aa | "Hash: 9f0d95b08ca5afeee1fe | ||||||
| Time: Xms | Time: Xms | ||||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | Built at: Thu Jan 01 1970 00:00:00 GMT | ||||||
|     Asset     Size  Chunks             Chunk Names |     Asset     Size  Chunks             Chunk Names | ||||||
|  | @ -3507,28 +3507,28 @@ WARNING in Terser Plugin: Dropping unused function someUnRemoteUsedFunction5 [./ | ||||||
| `; | `; | ||||||
| 
 | 
 | ||||||
| exports[`StatsTestCases should print correct stats for wasm-explorer-examples-sync 1`] = ` | exports[`StatsTestCases should print correct stats for wasm-explorer-examples-sync 1`] = ` | ||||||
| "Hash: e6c683371cb4c4354398 | "Hash: 48cd6bb29a775ac0f234 | ||||||
| Time: Xms | Time: Xms | ||||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | Built at: Thu Jan 01 1970 00:00:00 GMT | ||||||
|                            Asset       Size  Chunks             Chunk Names |                            Asset       Size  Chunks             Chunk Names | ||||||
| 00885349ebe3dd903faa.module.wasm  125 bytes   {325}  [emitted] | 10d1272d7cf8dafe2f3a.module.wasm  225 bytes   {780}  [emitted] | ||||||
|                    230.bundle.js  430 bytes   {230}  [emitted] |                    230.bundle.js  430 bytes   {230}  [emitted] | ||||||
|                    325.bundle.js   3.93 KiB   {325}  [emitted] |                    325.bundle.js    3.9 KiB   {325}  [emitted] | ||||||
|                    526.bundle.js  329 bytes   {526}  [emitted] |                    526.bundle.js  329 bytes   {526}  [emitted] | ||||||
|                    780.bundle.js  842 bytes   {780}  [emitted] |                    780.bundle.js  842 bytes   {780}  [emitted] | ||||||
| 7d7a509c17179e42766a.module.wasm   94 bytes   {325}  [emitted] | 7eee906d414e0947ebbf.module.wasm  132 bytes   {780}  [emitted] | ||||||
|  | 94b864234c573663c221.module.wasm   94 bytes   {325}  [emitted] | ||||||
|                     99.bundle.js  428 bytes    {99}  [emitted] |                     99.bundle.js  428 bytes    {99}  [emitted] | ||||||
|  | a160192b41d0463ac226.module.wasm  131 bytes   {230}  [emitted] | ||||||
|                        bundle.js   13.5 KiB   {520}  [emitted]  main-1df31ce3 |                        bundle.js   13.5 KiB   {520}  [emitted]  main-1df31ce3 | ||||||
| cfd5ebf998e67f7103a2.module.wasm  510 bytes    {99}  [emitted] | d95036d90a8b92bc2692.module.wasm  510 bytes    {99}  [emitted] | ||||||
| e94fc8ba836bfd2c6038.module.wasm  131 bytes   {230}  [emitted] | ff9c5233b4dbdf834f6f.module.wasm  125 bytes   {325}  [emitted] | ||||||
| f8f99fabd0c63ad1c730.module.wasm  225 bytes   {780}  [emitted] |  | ||||||
| fea68b3453f2f8fdfeed.module.wasm  132 bytes   {780}  [emitted] |  | ||||||
| Entrypoint main = bundle.js | Entrypoint main = bundle.js | ||||||
| chunk {99} 99.bundle.js, cfd5ebf998e67f7103a2.module.wasm 100 bytes (javascript) 531 bytes (webassembly) [rendered] | chunk {99} 99.bundle.js, d95036d90a8b92bc2692.module.wasm 100 bytes (javascript) 531 bytes (webassembly) [rendered] | ||||||
|  [99] ./duff.wasm 100 bytes (javascript) 531 bytes (webassembly) {99} [built] |  [99] ./duff.wasm 100 bytes (javascript) 531 bytes (webassembly) {99} [built] | ||||||
| chunk {230} 230.bundle.js, e94fc8ba836bfd2c6038.module.wasm 100 bytes (javascript) 156 bytes (webassembly) [rendered] | chunk {230} 230.bundle.js, a160192b41d0463ac226.module.wasm 100 bytes (javascript) 156 bytes (webassembly) [rendered] | ||||||
|  [230] ./Q_rsqrt.wasm 100 bytes (javascript) 156 bytes (webassembly) {230} [built] |  [230] ./Q_rsqrt.wasm 100 bytes (javascript) 156 bytes (webassembly) {230} [built] | ||||||
| chunk {325} 325.bundle.js, 7d7a509c17179e42766a.module.wasm, 00885349ebe3dd903faa.module.wasm 1.6 KiB (javascript) 274 bytes (webassembly) [rendered] | chunk {325} 325.bundle.js, 94b864234c573663c221.module.wasm, ff9c5233b4dbdf834f6f.module.wasm 1.6 KiB (javascript) 274 bytes (webassembly) [rendered] | ||||||
|  [287] ./popcnt.wasm 100 bytes (javascript) 120 bytes (webassembly) {325} [built] |  [287] ./popcnt.wasm 100 bytes (javascript) 120 bytes (webassembly) {325} [built] | ||||||
|  [325] ./tests.js 1.4 KiB {325} [built] |  [325] ./tests.js 1.4 KiB {325} [built] | ||||||
|  [819] ./testFunction.wasm 100 bytes (javascript) 154 bytes (webassembly) {325} [built] |  [819] ./testFunction.wasm 100 bytes (javascript) 154 bytes (webassembly) {325} [built] | ||||||
|  | @ -3537,7 +3537,7 @@ chunk {520} bundle.js (main-1df31ce3) 586 bytes (javascript) 6.75 KiB (runtime) | ||||||
|      + 7 hidden chunk modules |      + 7 hidden chunk modules | ||||||
| chunk {526} 526.bundle.js 34 bytes [rendered] split chunk (cache group: defaultVendors) | chunk {526} 526.bundle.js 34 bytes [rendered] split chunk (cache group: defaultVendors) | ||||||
|  [526] ./node_modules/env.js 34 bytes {526} [built] |  [526] ./node_modules/env.js 34 bytes {526} [built] | ||||||
| chunk {780} 780.bundle.js, fea68b3453f2f8fdfeed.module.wasm, f8f99fabd0c63ad1c730.module.wasm 205 bytes (javascript) 444 bytes (webassembly) [rendered] | chunk {780} 780.bundle.js, 7eee906d414e0947ebbf.module.wasm, 10d1272d7cf8dafe2f3a.module.wasm 205 bytes (javascript) 444 bytes (webassembly) [rendered] | ||||||
|  [143] ./fact.wasm 100 bytes (javascript) 154 bytes (webassembly) {780} [built] |  [143] ./fact.wasm 100 bytes (javascript) 154 bytes (webassembly) {780} [built] | ||||||
|  [151] ./fast-math.wasm 105 bytes (javascript) 290 bytes (webassembly) {780} [built] |  [151] ./fast-math.wasm 105 bytes (javascript) 290 bytes (webassembly) {780} [built] | ||||||
|  [10] ./index.js 586 bytes {520} [built] |  [10] ./index.js 586 bytes {520} [built] | ||||||
|  |  | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | export let counter = 0; | ||||||
|  | export const increment = () => { | ||||||
|  | 	counter++; | ||||||
|  | }; | ||||||
|  | export function reset() { | ||||||
|  | 	counter = 0; | ||||||
|  | }; | ||||||
|  | export const unusedExport = 42; | ||||||
|  | @ -0,0 +1,24 @@ | ||||||
|  | import * as C from "./reexport-namespace"; | ||||||
|  | import { counter } from "./reexport-namespace"; | ||||||
|  | import * as C2 from "./reexport-namespace-again"; | ||||||
|  | 
 | ||||||
|  | it("should allow to reexport namespaces 1", () => { | ||||||
|  | 	counter.reset(); | ||||||
|  | 	expect(counter.counter).toBe(0); | ||||||
|  | 	counter.increment(); | ||||||
|  | 	expect(counter.counter).toBe(1); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | it("should allow to reexport namespaces 2", () => { | ||||||
|  | 	C.counter.reset(); | ||||||
|  | 	expect(C.counter.counter).toBe(0); | ||||||
|  | 	C.counter.increment(); | ||||||
|  | 	expect(C.counter.counter).toBe(1); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | it("should allow to reexport namespaces 3", () => { | ||||||
|  | 	C2.CC.counter.reset(); | ||||||
|  | 	expect(C2.CC.counter.counter).toBe(0); | ||||||
|  | 	C2.CC.counter.increment(); | ||||||
|  | 	expect(C2.CC.counter.counter).toBe(1); | ||||||
|  | }); | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | import * as CC from "./reexport-namespace"; | ||||||
|  | export { CC }; | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | import * as counter from "./counter"; | ||||||
|  | export { counter }; | ||||||
|  | @ -15,10 +15,12 @@ module.exports = { | ||||||
| 						ref.module && | 						ref.module && | ||||||
| 						ref.module.identifier().endsWith("reference.js") && | 						ref.module.identifier().endsWith("reference.js") && | ||||||
| 						Array.isArray(ref.importedNames) && | 						Array.isArray(ref.importedNames) && | ||||||
| 						ref.importedNames.includes("unused") | 						ref.importedNames.some( | ||||||
|  | 							names => names.length === 1 && names[0] === "unused" | ||||||
|  | 						) | ||||||
| 					) { | 					) { | ||||||
| 						const newExports = ref.importedNames.filter( | 						const newExports = ref.importedNames.filter( | ||||||
| 							item => item !== "unused" | 							names => names.length !== 1 || names[0] !== "unused" | ||||||
| 						); | 						); | ||||||
| 						return new DependencyReference( | 						return new DependencyReference( | ||||||
| 							() => ref.module, | 							() => ref.module, | ||||||
|  |  | ||||||
|  | @ -15,10 +15,12 @@ module.exports = { | ||||||
| 						ref.module && | 						ref.module && | ||||||
| 						ref.module.identifier().endsWith("reference.js") && | 						ref.module.identifier().endsWith("reference.js") && | ||||||
| 						Array.isArray(ref.importedNames) && | 						Array.isArray(ref.importedNames) && | ||||||
| 						ref.importedNames.includes("unused") | 						ref.importedNames.some( | ||||||
|  | 							names => names.length === 1 && names[0] === "unused" | ||||||
|  | 						) | ||||||
| 					) { | 					) { | ||||||
| 						const newExports = ref.importedNames.filter( | 						const newExports = ref.importedNames.filter( | ||||||
| 							item => item !== "unused" | 							names => names.length !== 1 || names[0] !== "unused" | ||||||
| 						); | 						); | ||||||
| 						return new DependencyReference( | 						return new DependencyReference( | ||||||
| 							() => ref.module, | 							() => ref.module, | ||||||
|  |  | ||||||
|  | @ -1,14 +1,63 @@ | ||||||
| function returnThis() { | function returnThis() { | ||||||
| 	if(typeof this === "undefined") return "undefined"; | 	if (typeof this === "undefined") return "undefined"; | ||||||
| 	return this; | 	return this; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| var a = returnThis; | var a = returnThis; | ||||||
| var b = returnThis; | var b = returnThis; | ||||||
| 
 | 
 | ||||||
| export { | export { a, b }; | ||||||
| 	a, | 
 | ||||||
| 	b | export const that = this; | ||||||
|  | export const returnThisArrow = () => this; | ||||||
|  | export const returnThisMember = () => this.a; | ||||||
|  | 
 | ||||||
|  | export class C { | ||||||
|  | 	constructor() { | ||||||
|  | 		this.x = "bar"; | ||||||
|  | 	} | ||||||
|  | 	foo() { | ||||||
|  | 		return this.x; | ||||||
|  | 	} | ||||||
|  | 	bar(x = this.x) { | ||||||
|  | 		return x; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const extendThisClass = () => { | ||||||
|  | 	return class extends this.Buffer {}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export function D() { | ||||||
|  | 	this.prop = () => "ok"; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // See https://github.com/webpack/webpack/issues/6379
 | ||||||
|  | export const E = { | ||||||
|  | 	x: "bar", | ||||||
|  | 	foo(x = this.x) { | ||||||
|  | 		return x; | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | // See https://github.com/webpack/webpack/issues/6967
 | ||||||
|  | export const F = function() { | ||||||
|  | 	return this; | ||||||
|  | }.call("ok"); | ||||||
|  | 
 | ||||||
|  | export function f1(x = this.x) { | ||||||
|  | 	return x; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export const f2 = function(x = this.x) { | ||||||
|  | 	return x; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | export const f3 = (x = this) => x; | ||||||
|  | 
 | ||||||
|  | export function G(x) { | ||||||
|  | 	this.x = x; | ||||||
|  | 	this.getX = (y = this.x) => y; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export default returnThis; | export default returnThis; | ||||||
|  |  | ||||||
|  | @ -1,11 +1,45 @@ | ||||||
| "use strict"; | "use strict"; | ||||||
| 
 | 
 | ||||||
| import d, {a, b as B} from "./abc"; | import {extendThisClass, returnThisArrow, returnThisMember, that} from "./abc"; | ||||||
|  | import d, {a, b as B, C as _C, D as _D, E, F, f1, f2, f3, G} from "./abc"; | ||||||
|  | import {bindThis, callThis, applyThis} from "./issue-7213"; | ||||||
| 
 | 
 | ||||||
| import * as abc from "./abc"; | import * as abc from "./abc"; | ||||||
| 
 | 
 | ||||||
| function x() { throw new Error("should not be executed"); } | it("should have this = undefined on harmony modules", () => { | ||||||
| it("should have this = undefined on imported non-strict functions", function() { | 	expect((typeof that)).toBe("undefined"); | ||||||
|  | 	expect((typeof abc.that)).toBe("undefined"); | ||||||
|  | 	expect((typeof returnThisArrow())).toBe("undefined"); | ||||||
|  | 	expect((typeof abc.returnThisArrow())).toBe("undefined"); | ||||||
|  | 	expect(function() { | ||||||
|  | 		returnThisMember(); | ||||||
|  | 	}).toThrowError(); | ||||||
|  | 	expect(function() { | ||||||
|  | 		abc.returnThisMember(); | ||||||
|  | 	}).toThrowError(); | ||||||
|  | 	expect(function() { | ||||||
|  | 		extendThisClass(); | ||||||
|  | 	}).toThrowError(); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | it("should not break classes and functions", () => { | ||||||
|  | 	expect((new _C).foo()).toBe("bar"); | ||||||
|  | 	expect((new _C).bar()).toBe("bar"); | ||||||
|  | 	expect((new _D).prop()).toBe("ok"); | ||||||
|  | 	expect(E.foo()).toBe("bar"); | ||||||
|  | 	expect(F).toBe("ok"); | ||||||
|  | 	expect(f1.call({x: "f1"})).toBe("f1"); | ||||||
|  | 	expect(f2.call({x: "f2"})).toBe("f2"); | ||||||
|  | 	expect(f3.call("f3")).toBe(undefined); | ||||||
|  | 	expect(f3()).toBe(undefined); | ||||||
|  | 	expect((new G("ok")).getX()).toBe("ok"); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | function x() { | ||||||
|  | 	throw new Error("should not be executed"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | it("should have this = undefined on imported non-strict functions", () => { | ||||||
| 	x | 	x | ||||||
| 	expect(d()).toBe("undefined"); | 	expect(d()).toBe("undefined"); | ||||||
| 	x | 	x | ||||||
|  | @ -13,17 +47,17 @@ it("should have this = undefined on imported non-strict functions", function() { | ||||||
| 	x | 	x | ||||||
| 	expect(B()).toBe("undefined"); | 	expect(B()).toBe("undefined"); | ||||||
| 	x | 	x | ||||||
| 	expect(abc.a()).toMatchObject({}); | 	expect(abc.a()).toBeTypeOf("object"); | ||||||
| 	x | 	x | ||||||
| 	var thing = abc.a(); | 	var thing = abc.a(); | ||||||
| 	expect(Object.keys(thing)).toEqual(["a", "b", "default"]); | 	expect(Object.keys(thing)).toEqual(Object.keys(abc)); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| import C2, { C } from "./new"; | import C2, { C } from "./new"; | ||||||
| 
 | 
 | ||||||
| import * as New from "./new"; | import * as New from "./new"; | ||||||
| 
 | 
 | ||||||
| it("should be possible to use new correctly", function() { | it("should be possible to use new correctly", () => { | ||||||
| 	x | 	x | ||||||
| 	expect(new C()).toEqual({ok: true}); | 	expect(new C()).toEqual({ok: true}); | ||||||
| 	x | 	x | ||||||
|  | @ -31,3 +65,9 @@ it("should be possible to use new correctly", function() { | ||||||
| 	x | 	x | ||||||
| 	expect(new New.C()).toEqual({ok: true}); | 	expect(new New.C()).toEqual({ok: true}); | ||||||
| }); | }); | ||||||
|  | 
 | ||||||
|  | it("should not break Babel arrow function transform", () => { | ||||||
|  | 	expect(bindThis()).toBe(undefined); | ||||||
|  | 	expect(callThis).toBe(undefined); | ||||||
|  | 	expect(applyThis).toBe(undefined); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,20 @@ | ||||||
|  | // This helper is taken from Babel
 | ||||||
|  | function _newArrowCheck(innerThis, boundThis) { | ||||||
|  | 	if (innerThis !== boundThis) { | ||||||
|  | 		throw new TypeError("Cannot instantiate an arrow function"); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | let _this = this; | ||||||
|  | export let bindThis = function() { | ||||||
|  | 	_newArrowCheck(this, _this); | ||||||
|  | 	return this | ||||||
|  | }.bind(this); | ||||||
|  | 
 | ||||||
|  | export let callThis = function() { | ||||||
|  | 	return this | ||||||
|  | }.call(this) | ||||||
|  | 
 | ||||||
|  | export let applyThis = function() { | ||||||
|  | 	return this | ||||||
|  | }.apply(this) | ||||||
|  | @ -2,6 +2,5 @@ var webpack = require("../../../../"); | ||||||
| module.exports = { | module.exports = { | ||||||
| 	module: { | 	module: { | ||||||
| 		strictThisContextOnImports: true | 		strictThisContextOnImports: true | ||||||
| 	}, | 	} | ||||||
| 	plugins: [new webpack.optimize.ModuleConcatenationPlugin()] |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -1,5 +1,8 @@ | ||||||
| module.exports = { | module.exports = { | ||||||
| 	module: { | 	module: { | ||||||
| 		strictThisContextOnImports: true | 		strictThisContextOnImports: true | ||||||
|  | 	}, | ||||||
|  | 	optimization: { | ||||||
|  | 		concatenateModules: false | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue