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 {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 | ||||
|  * @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 | ||||
|  */ | ||||
| 
 | ||||
|  |  | |||
|  | @ -12,6 +12,7 @@ const Queue = require("./util/Queue"); | |||
| /** @typedef {import("./DependenciesBlock")} DependenciesBlock */ | ||||
| /** @typedef {import("./Dependency")} Dependency */ | ||||
| /** @typedef {import("./Module")} Module */ | ||||
| /** @typedef {import("./ModuleGraph").ExportsInfo} ExportsInfo */ | ||||
| 
 | ||||
| const getCacheIdentifier = (compilation, module) => { | ||||
| 	return `${ | ||||
|  | @ -79,6 +80,7 @@ class FlagDependencyExportsPlugin { | |||
| 								/** @type {Module} */ | ||||
| 								let module; | ||||
| 
 | ||||
| 								/** @type {ExportsInfo} */ | ||||
| 								let exportsInfo; | ||||
| 
 | ||||
| 								let cacheable = true; | ||||
|  | @ -113,12 +115,36 @@ class FlagDependencyExportsPlugin { | |||
| 										} | ||||
| 									} else if (Array.isArray(exports)) { | ||||
| 										// merge in new exports
 | ||||
| 										for (const exportName of exports) { | ||||
| 											const exportInfo = exportsInfo.getExportInfo(exportName); | ||||
| 										for (const exportNameOrSpec of exports) { | ||||
| 											if (typeof exportNameOrSpec === "string") { | ||||
| 												const exportInfo = exportsInfo.getExportInfo( | ||||
| 													exportNameOrSpec | ||||
| 												); | ||||
| 												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; | ||||
| 													} | ||||
| 												} | ||||
| 											} | ||||
| 										} | ||||
| 									} | ||||
| 									// store dependencies
 | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ | |||
| 
 | ||||
| "use strict"; | ||||
| 
 | ||||
| const { UsageState } = require("./ModuleGraph"); | ||||
| const { STAGE_DEFAULT } = require("./OptimizationStages"); | ||||
| const Queue = require("./util/Queue"); | ||||
| 
 | ||||
|  | @ -12,6 +13,10 @@ const Queue = require("./util/Queue"); | |||
| /** @typedef {import("./DependenciesBlock")} DependenciesBlock */ | ||||
| /** @typedef {import("./Dependency")} Dependency */ | ||||
| /** @typedef {import("./Module")} Module */ | ||||
| /** @typedef {import("./ModuleGraph").ExportsInfo} ExportsInfo */ | ||||
| 
 | ||||
| const NS_OBJ_USED = [[]]; | ||||
| const NOTHING_USED = []; | ||||
| 
 | ||||
| class FlagDependencyUsagePlugin { | ||||
| 	/** | ||||
|  | @ -27,31 +32,60 @@ class FlagDependencyUsagePlugin { | |||
| 					stage: STAGE_DEFAULT | ||||
| 				}, | ||||
| 				modules => { | ||||
| 					/** @type {Map<ExportsInfo, Module>} */ | ||||
| 					const exportInfoToModuleMap = new Map(); | ||||
| 
 | ||||
| 					/** | ||||
| 					 * | ||||
| 					 * @typedef {string[]} StringArray | ||||
| 					 * @param {Module} module module to process | ||||
| 					 * @param {boolean | string[]} usedExports list of used exports | ||||
| 					 * @param {StringArray[]} usedExports list of used exports | ||||
| 					 * @returns {void} | ||||
| 					 */ | ||||
| 					const processModule = (module, usedExports) => { | ||||
| 						const exportsInfo = moduleGraph.getExportsInfo(module); | ||||
| 						let changed = false; | ||||
| 						if (usedExports === true) { | ||||
| 							changed = exportsInfo.setUsedInUnknownWay(); | ||||
| 						} else if (usedExports) { | ||||
| 							for (const exportName of usedExports) { | ||||
| 						if (usedExports.length > 0) { | ||||
| 							for (const usedExport of usedExports) { | ||||
| 								if (usedExport.length === 0) { | ||||
| 									if (exportsInfo.setUsedInUnknownWay()) { | ||||
| 										queue.enqueue(module); | ||||
| 									} | ||||
| 								} else { | ||||
| 									if ( | ||||
| 									exportName === "default" && | ||||
| 										usedExport[0] === "default" && | ||||
| 										module.buildMeta.exportsType === "named" | ||||
| 									) { | ||||
| 										if (exportsInfo.setUsedAsNamedExportType()) { | ||||
| 										changed = true; | ||||
| 											queue.enqueue(module); | ||||
| 										} | ||||
| 									} else { | ||||
| 									const exportInfo = exportsInfo.getExportInfo(exportName); | ||||
| 									if (exportInfo.used !== true) { | ||||
| 										exportInfo.used = true; | ||||
| 										changed = true; | ||||
| 										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,12 +93,10 @@ class FlagDependencyUsagePlugin { | |||
| 							// 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
 | ||||
| 							if (module.factoryMeta.sideEffectFree) return; | ||||
| 							changed = exportsInfo.setUsedForSideEffectsOnly(); | ||||
| 						} | ||||
| 
 | ||||
| 						if (changed) { | ||||
| 							if (exportsInfo.setUsedForSideEffectsOnly()) { | ||||
| 								queue.enqueue(module); | ||||
| 							} | ||||
| 						} | ||||
| 					}; | ||||
| 
 | ||||
| 					/** | ||||
|  | @ -89,11 +121,21 @@ class FlagDependencyUsagePlugin { | |||
| 						if (!reference) return; | ||||
| 						const referenceModule = reference.module; | ||||
| 						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) { | ||||
| 						moduleGraph.getExportsInfo(module).setHasUseInfo(); | ||||
| 						const exportsInfo = moduleGraph.getExportsInfo(module); | ||||
| 						exportInfoToModuleMap.set(exportsInfo, module); | ||||
| 						exportsInfo.setHasUseInfo(); | ||||
| 					} | ||||
| 
 | ||||
| 					/** @type {Queue<DependenciesBlock>} */ | ||||
|  | @ -103,7 +145,7 @@ class FlagDependencyUsagePlugin { | |||
| 						for (const dep of deps) { | ||||
| 							const module = moduleGraph.getModule(dep); | ||||
| 							if (module) { | ||||
| 								processModule(module, true); | ||||
| 								processModule(module, NS_OBJ_USED); | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
|  |  | |||
|  | @ -27,6 +27,32 @@ const joinIterableWithComma = iterable => { | |||
| 	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 { | ||||
| 	constructor({ compilation }) { | ||||
| 		this.compilation = compilation; | ||||
|  | @ -84,26 +110,7 @@ class FunctionModuleTemplatePlugin { | |||
| 					source.add("  !*** " + reqStr + " ***!\n"); | ||||
| 					source.add("  \\****" + reqStrStar + "****/\n"); | ||||
| 					const exportsInfo = moduleGraph.getExportsInfo(module); | ||||
| 					for (const exportInfo of exportsInfo.orderedExports) { | ||||
| 						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" | ||||
| 						); | ||||
| 					} | ||||
| 					printExportsInfoToSource(source, "", exportsInfo); | ||||
| 					source.add( | ||||
| 						Template.toComment( | ||||
| 							`runtime requirements: ${joinIterableWithComma( | ||||
|  |  | |||
|  | @ -91,10 +91,14 @@ class JavascriptParser { | |||
| 			typeof: new HookMap(() => new SyncBailHook(["expression"])), | ||||
| 			importCall: 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"])), | ||||
| 			expression: new HookMap(() => new SyncBailHook(["expression"])), | ||||
| 			expressionAnyMember: new HookMap(() => new SyncBailHook(["expression"])), | ||||
| 			expressionMemberChain: new HookMap( | ||||
| 				() => new SyncBailHook(["expression", "rootRaw", "members"]) | ||||
| 			), | ||||
| 			expressionConditionalOperator: new SyncBailHook(["expression"]), | ||||
| 			expressionLogicalOperator: new SyncBailHook(["expression"]), | ||||
| 			program: new SyncBailHook(["ast", "comments"]) | ||||
|  | @ -1831,14 +1835,17 @@ class JavascriptParser { | |||
| 					let result = callHook.call(expression); | ||||
| 					if (result === true) return; | ||||
| 				} | ||||
| 				// TODO replace with lastIndexOf for performance reasons
 | ||||
| 				let identifier = callee.identifier.replace(/\.[^.]+$/, ""); | ||||
| 				if (identifier !== callee.identifier) { | ||||
| 					const callAnyHook = this.hooks.callAnyMember.get(identifier); | ||||
| 					if (callAnyHook !== undefined) { | ||||
| 						let result = callAnyHook.call(expression); | ||||
| 						if (result === true) return; | ||||
| 			} | ||||
| 			const exprName = this.getNameForExpression(expression.callee); | ||||
| 			if (exprName) { | ||||
| 				const hook = this.hooks.callMemberChain.get(exprName.rootName); | ||||
| 				if (hook !== undefined) { | ||||
| 					const result = hook.call( | ||||
| 						expression, | ||||
| 						exprName.rootRaw, | ||||
| 						exprName.members | ||||
| 					); | ||||
| 					if (result === true) return; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
|  | @ -1855,13 +1862,19 @@ class JavascriptParser { | |||
| 				const result = expressionHook.call(expression); | ||||
| 				if (result === true) return; | ||||
| 			} | ||||
| 			const expressionAnyMemberHook = this.hooks.expressionAnyMember.get( | ||||
| 				exprName.nameGeneral | ||||
| 			const expressionMemberChainHook = this.hooks.expressionMemberChain.get( | ||||
| 				exprName.rootName | ||||
| 			); | ||||
| 			if (expressionMemberChainHook !== undefined) { | ||||
| 				const result = expressionMemberChainHook.call( | ||||
| 					expression, | ||||
| 					exprName.rootRaw, | ||||
| 					exprName.members | ||||
| 				); | ||||
| 			if (expressionAnyMemberHook !== undefined) { | ||||
| 				const result = expressionAnyMemberHook.call(expression); | ||||
| 				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); | ||||
| 		if (expression.computed === true) this.walkExpression(expression.property); | ||||
|  | @ -2189,22 +2202,27 @@ class JavascriptParser { | |||
| 			expr.type === "MemberExpression" && | ||||
| 			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; | ||||
| 		} | ||||
| 		let free; | ||||
| 		let rootRaw; | ||||
| 		if (expr.type === "Identifier") { | ||||
| 			free = !this.scope.definitions.has(expr.name); | ||||
| 			exprName.push(this.scope.renames.get(expr.name) || expr.name); | ||||
| 		} else if ( | ||||
| 			expr.type === "ThisExpression" && | ||||
| 			this.scope.renames.get("this") | ||||
| 		) { | ||||
| 			free = true; | ||||
| 			exprName.push(this.scope.renames.get("this")); | ||||
| 			rootRaw = expr.name; | ||||
| 		} else if (expr.type === "ThisExpression") { | ||||
| 			const rename = this.scope.renames.get("this"); | ||||
| 			if (rename) { | ||||
| 				free = true; | ||||
| 				exprName.push(rename); | ||||
| 			} else { | ||||
| 				free = this.scope.topLevelScope; | ||||
| 				exprName.push("this"); | ||||
| 			} | ||||
| 			rootRaw = "this"; | ||||
| 		} else { | ||||
| 			return null; | ||||
| 		} | ||||
|  | @ -2217,9 +2235,13 @@ class JavascriptParser { | |||
| 		} | ||||
| 		const name = prefix ? prefix + "." + exprName[0] : exprName[0]; | ||||
| 		const nameGeneral = prefix; | ||||
| 		const rootName = exprName.pop(); | ||||
| 		return { | ||||
| 			name, | ||||
| 			nameGeneral, | ||||
| 			rootName, | ||||
| 			rootRaw, | ||||
| 			members: exprName.reverse(), | ||||
| 			free | ||||
| 		}; | ||||
| 	} | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| 
 | ||||
| const { ConcatSource, RawSource } = require("webpack-sources"); | ||||
| const Generator = require("./Generator"); | ||||
| const { UsageState } = require("./ModuleGraph"); | ||||
| const RuntimeGlobals = require("./RuntimeGlobals"); | ||||
| 
 | ||||
| /** @typedef {import("webpack-sources").Source} Source */ | ||||
|  | @ -64,7 +65,7 @@ class JsonGenerator extends Generator { | |||
| 		const providedExports = moduleGraph.getProvidedExports(module); | ||||
| 		if ( | ||||
| 			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
 | ||||
| 			const reducedJson = {}; | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ const makeSerializable = require("./util/makeSerializable"); | |||
| /** @typedef {import("./Dependency")} Dependency */ | ||||
| /** @typedef {import("./DependencyTemplates")} DependencyTemplates */ | ||||
| /** @typedef {import("./FileSystemInfo")} FileSystemInfo */ | ||||
| /** @typedef {import("./ModuleGraph").UsageStateType} UsageStateType */ | ||||
| /** @typedef {import("./RequestShortener")} RequestShortener */ | ||||
| /** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */ | ||||
| /** @typedef {import("./WebpackError")} WebpackError */ | ||||
|  | @ -385,23 +386,22 @@ class Module extends DependenciesBlock { | |||
| 
 | ||||
| 	/** | ||||
| 	 * @param {ModuleGraph} moduleGraph the module graph | ||||
| 	 * @param {string} exportName a name of an export | ||||
| 	 * @returns {boolean} true, if the export is used | ||||
| 	 * @param {string | string[]} exportName a name of an export | ||||
| 	 * @returns {UsageStateType} state of the export | ||||
| 	 */ | ||||
| 	isExportUsed(moduleGraph, exportName) { | ||||
| 		const exportInfo = moduleGraph.getReadOnlyExportInfo(this, exportName); | ||||
| 		return exportInfo.used !== false; | ||||
| 		return moduleGraph.getExportsInfo(this).isExportUsed(exportName); | ||||
| 	} | ||||
| 
 | ||||
| 	// TODO move to ModuleGraph
 | ||||
| 	/** | ||||
| 	 * @param {ModuleGraph} moduleGraph the module graph | ||||
| 	 * @param {string} exportName a name of an export | ||||
| 	 * @returns {string | false} false, when module or referenced export is unused. | ||||
| 	 * @param {string | string[]} exportName a name of an export | ||||
| 	 * @returns {string | string[] | false} false, when module or referenced export is unused. | ||||
| 	 *                           string, the mangled export name when used. | ||||
| 	 */ | ||||
| 	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} | ||||
|  */ | ||||
| 
 | ||||
| /** @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 { | ||||
| 	constructor() { | ||||
| 		/** @type {Map<string, ExportInfo>} */ | ||||
|  | @ -92,21 +102,21 @@ class ExportsInfo { | |||
| 
 | ||||
| 	setHasUseInfo() { | ||||
| 		for (const exportInfo of this._exports.values()) { | ||||
| 			if (exportInfo.used === undefined) { | ||||
| 				exportInfo.used = false; | ||||
| 			if (exportInfo.used === UsageState.NoInfo) { | ||||
| 				exportInfo.used = UsageState.Unused; | ||||
| 			} | ||||
| 			if (exportInfo.canMangleUse === undefined) { | ||||
| 				exportInfo.canMangleUse = true; | ||||
| 			} | ||||
| 		} | ||||
| 		if (this._otherExportsInfo.used === undefined) { | ||||
| 			this._otherExportsInfo.used = false; | ||||
| 		if (this._otherExportsInfo.used === UsageState.NoInfo) { | ||||
| 			this._otherExportsInfo.used = UsageState.Unused; | ||||
| 		} | ||||
| 		if (this._otherExportsInfo.canMangleUse === undefined) { | ||||
| 			this._otherExportsInfo.canMangleUse = true; | ||||
| 		} | ||||
| 		if (this._sideEffectsOnlyInfo.used === undefined) { | ||||
| 			this._sideEffectsOnlyInfo.used = false; | ||||
| 		if (this._sideEffectsOnlyInfo.used === UsageState.NoInfo) { | ||||
| 			this._sideEffectsOnlyInfo.used = UsageState.Unused; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | @ -127,6 +137,20 @@ class ExportsInfo { | |||
| 		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 | ||||
| 	 */ | ||||
|  | @ -163,8 +187,8 @@ class ExportsInfo { | |||
| 			changed = true; | ||||
| 		} | ||||
| 		for (const exportInfo of this._exports.values()) { | ||||
| 			if (exportInfo.used !== true && exportInfo.used !== null) { | ||||
| 				exportInfo.used = null; | ||||
| 			if (exportInfo.used < UsageState.Unknown) { | ||||
| 				exportInfo.used = UsageState.Unknown; | ||||
| 				changed = true; | ||||
| 			} | ||||
| 			if (exportInfo.canMangleUse !== false) { | ||||
|  | @ -172,11 +196,8 @@ class ExportsInfo { | |||
| 				changed = true; | ||||
| 			} | ||||
| 		} | ||||
| 		if ( | ||||
| 			this._otherExportsInfo.used !== true && | ||||
| 			this._otherExportsInfo.used !== null | ||||
| 		) { | ||||
| 			this._otherExportsInfo.used = null; | ||||
| 		if (this._otherExportsInfo.used < UsageState.Unknown) { | ||||
| 			this._otherExportsInfo.used = UsageState.Unknown; | ||||
| 			changed = true; | ||||
| 		} | ||||
| 		if (this._otherExportsInfo.canMangleUse !== false) { | ||||
|  | @ -192,10 +213,10 @@ class ExportsInfo { | |||
| 			this._isUsed = true; | ||||
| 			changed = true; | ||||
| 		} | ||||
| 		this.getExportInfo("default").used = true; | ||||
| 		this.getExportInfo("default").used = UsageState.Used; | ||||
| 		for (const exportInfo of this._exports.values()) { | ||||
| 			if (exportInfo.used !== true && exportInfo.used !== null) { | ||||
| 				exportInfo.used = null; | ||||
| 			if (exportInfo.used < UsageState.Unknown) { | ||||
| 				exportInfo.used = UsageState.Unknown; | ||||
| 				changed = true; | ||||
| 			} | ||||
| 			if (exportInfo.name !== "default" && exportInfo.canMangleUse !== false) { | ||||
|  | @ -203,11 +224,8 @@ class ExportsInfo { | |||
| 				changed = true; | ||||
| 			} | ||||
| 		} | ||||
| 		if ( | ||||
| 			this._otherExportsInfo.used !== true && | ||||
| 			this._otherExportsInfo.used !== null | ||||
| 		) { | ||||
| 			this._otherExportsInfo.used = null; | ||||
| 		if (this._otherExportsInfo.used < UsageState.Unknown) { | ||||
| 			this._otherExportsInfo.used = UsageState.Unknown; | ||||
| 			changed = true; | ||||
| 		} | ||||
| 		if (this._otherExportsInfo.canMangleUse !== false) { | ||||
|  | @ -218,22 +236,22 @@ class ExportsInfo { | |||
| 	} | ||||
| 
 | ||||
| 	setUsedForSideEffectsOnly() { | ||||
| 		if (this._sideEffectsOnlyInfo.used === false) { | ||||
| 			this._sideEffectsOnlyInfo.used = true; | ||||
| 		if (this._sideEffectsOnlyInfo.used === UsageState.Unused) { | ||||
| 			this._sideEffectsOnlyInfo.used = UsageState.Used; | ||||
| 			return true; | ||||
| 		} | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	isUsed() { | ||||
| 		if (this._otherExportsInfo.used !== false) { | ||||
| 		if (this._otherExportsInfo.used !== UsageState.Unused) { | ||||
| 			return true; | ||||
| 		} | ||||
| 		if (this._sideEffectsOnlyInfo.used !== false) { | ||||
| 		if (this._sideEffectsOnlyInfo.used !== UsageState.Unused) { | ||||
| 			return true; | ||||
| 		} | ||||
| 		for (const exportInfo of this._exports.values()) { | ||||
| 			if (exportInfo.used !== false) { | ||||
| 			if (exportInfo.used !== UsageState.Unused) { | ||||
| 				return true; | ||||
| 			} | ||||
| 		} | ||||
|  | @ -242,30 +260,32 @@ class ExportsInfo { | |||
| 
 | ||||
| 	getUsedExports() { | ||||
| 		switch (this._otherExportsInfo.used) { | ||||
| 			case undefined: | ||||
| 			case UsageState.NoInfo: | ||||
| 				return null; | ||||
| 			case null: | ||||
| 			case UsageState.Unknown: | ||||
| 				return true; | ||||
| 			case true: | ||||
| 			case UsageState.OnlyPropertiesUsed: | ||||
| 			case UsageState.Used: | ||||
| 				return true; | ||||
| 		} | ||||
| 		const array = []; | ||||
| 		if (!this._exportsAreOrdered) this._sortExports(); | ||||
| 		for (const exportInfo of this._exports.values()) { | ||||
| 			switch (exportInfo.used) { | ||||
| 				case undefined: | ||||
| 				case UsageState.NoInfo: | ||||
| 					return null; | ||||
| 				case null: | ||||
| 				case UsageState.Unknown: | ||||
| 					return true; | ||||
| 				case true: | ||||
| 				case UsageState.OnlyPropertiesUsed: | ||||
| 				case UsageState.Used: | ||||
| 					array.push(exportInfo.name); | ||||
| 			} | ||||
| 		} | ||||
| 		if (array.length === 0) { | ||||
| 			switch (this._sideEffectsOnlyInfo.used) { | ||||
| 				case undefined: | ||||
| 				case UsageState.NoInfo: | ||||
| 					return null; | ||||
| 				case false: | ||||
| 				case UsageState.Unused: | ||||
| 					return false; | ||||
| 			} | ||||
| 		} | ||||
|  | @ -296,12 +316,61 @@ class ExportsInfo { | |||
| 		return array; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {string | string[]} name the name of the export | ||||
| 	 * @returns {boolean | undefined | null} if the export is provided | ||||
| 	 */ | ||||
| 	isExportProvided(name) { | ||||
| 		if (Array.isArray(name)) { | ||||
| 			// TODO follow nested exports
 | ||||
| 			return this.isExportProvided(name[0]); | ||||
| 		} | ||||
| 		let info = this._exports.get(name); | ||||
| 		if (info === undefined) info = this._otherExportsInfo; | ||||
| 		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() { | ||||
| 		const otherProvided = this._otherExportsInfo.provided; | ||||
| 		const otherCanMangleProvide = this._otherExportsInfo.canMangleProvide; | ||||
|  | @ -350,14 +419,8 @@ class ExportInfo { | |||
| 		this.name = name; | ||||
| 		/** @type {string | null} */ | ||||
| 		this.usedName = initFrom ? initFrom.usedName : null; | ||||
| 		/** | ||||
| 		 * true: it is used | ||||
| 		 * 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; | ||||
| 		/** @type {UsageStateType} */ | ||||
| 		this.used = initFrom ? initFrom.used : UsageState.NoInfo; | ||||
| 		/** | ||||
| 		 * true: it is provided | ||||
| 		 * false: it is not provided | ||||
|  | @ -380,6 +443,8 @@ class ExportInfo { | |||
| 		 * @type {boolean | undefined} | ||||
| 		 */ | ||||
| 		this.canMangleUse = initFrom ? initFrom.canMangleUse : undefined; | ||||
| 		/** @type {ExportsInfo=} */ | ||||
| 		this.exportsInfo = undefined; | ||||
| 	} | ||||
| 
 | ||||
| 	get canMangle() { | ||||
|  | @ -406,20 +471,22 @@ class ExportInfo { | |||
| 	} | ||||
| 
 | ||||
| 	getUsedName() { | ||||
| 		if (this.used === false) return false; | ||||
| 		if (this.used === UsageState.Unused) return false; | ||||
| 		return this.usedName || this.name; | ||||
| 	} | ||||
| 
 | ||||
| 	getUsedInfo() { | ||||
| 		switch (this.used) { | ||||
| 			case undefined: | ||||
| 			case UsageState.NoInfo: | ||||
| 				return "no usage info"; | ||||
| 			case null: | ||||
| 			case UsageState.Unknown: | ||||
| 				return "maybe used (runtime-defined)"; | ||||
| 			case true: | ||||
| 			case UsageState.Used: | ||||
| 				return "used"; | ||||
| 			case false: | ||||
| 			case UsageState.Unused: | ||||
| 				return "unused"; | ||||
| 			case UsageState.OnlyPropertiesUsed: | ||||
| 				return "only properties used"; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | @ -828,7 +895,7 @@ class ModuleGraph { | |||
| 
 | ||||
| 	/** | ||||
| 	 * @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. | ||||
| 	 *                           null, if it's unknown. | ||||
| 	 *                           false, if it's not provided. | ||||
|  | @ -1044,3 +1111,6 @@ const deprecateMap = new Map(); | |||
| 
 | ||||
| module.exports = ModuleGraph; | ||||
| 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 Template = require("./Template"); | ||||
| const propertyAccess = require("./util/propertyAccess"); | ||||
| 
 | ||||
| /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */ | ||||
| /** @typedef {import("./ChunkGraph")} ChunkGraph */ | ||||
|  | @ -14,6 +15,14 @@ const Template = require("./Template"); | |||
| /** @typedef {import("./ModuleGraph")} ModuleGraph */ | ||||
| /** @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 { | ||||
| 	/** | ||||
| 	 * @param {TODO} outputOptions the compilation output options | ||||
|  | @ -506,7 +515,7 @@ class RuntimeTemplate { | |||
| 	 * @param {ModuleGraph} options.moduleGraph the module graph | ||||
| 	 * @param {Module} options.module the module | ||||
| 	 * @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 {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 | ||||
|  | @ -532,24 +541,30 @@ class RuntimeTemplate { | |||
| 				request | ||||
| 			}); | ||||
| 		} | ||||
| 		if (!Array.isArray(exportName)) { | ||||
| 			exportName = exportName ? [exportName] : []; | ||||
| 		} | ||||
| 		const exportsType = module.buildMeta && module.buildMeta.exportsType; | ||||
| 
 | ||||
| 		if (!exportsType) { | ||||
| 			if (exportName === "default") { | ||||
| 			if (exportName.length > 0 && exportName[0] === "default") { | ||||
| 				if (!originModule.buildMeta.strictHarmonyModule) { | ||||
| 					if (isCall) { | ||||
| 						return `${importVar}_default()`; | ||||
| 						return `${importVar}_default()${propertyAccess(exportName, 1)}`; | ||||
| 					} else if (asiSafe) { | ||||
| 						return `(${importVar}_default())`; | ||||
| 						return `(${importVar}_default()${propertyAccess(exportName, 1)})`; | ||||
| 					} else { | ||||
| 						return `${importVar}_default.a`; | ||||
| 						return `${importVar}_default.a${propertyAccess(exportName, 1)}`; | ||||
| 					} | ||||
| 				} else { | ||||
| 					return importVar; | ||||
| 					return `${importVar}${propertyAccess(exportName, 1)}`; | ||||
| 				} | ||||
| 			} else if (originModule.buildMeta.strictHarmonyModule) { | ||||
| 				if (exportName) { | ||||
| 					return "/* non-default import from non-esm module */undefined"; | ||||
| 				if (exportName.length > 0) { | ||||
| 					return ( | ||||
| 						"/* non-default import from non-esm module */undefined" + | ||||
| 						propertyAccess(exportName, 1) | ||||
| 					); | ||||
| 				} else { | ||||
| 					runtimeRequirements.add(RuntimeGlobals.createFakeNamespaceObject); | ||||
| 					return `/*#__PURE__*/${ | ||||
|  | @ -560,26 +575,30 @@ class RuntimeTemplate { | |||
| 		} | ||||
| 
 | ||||
| 		if (exportsType === "named") { | ||||
| 			if (exportName === "default") { | ||||
| 				return importVar; | ||||
| 			} else if (!exportName) { | ||||
| 			if (exportName.length > 0 && exportName[0] === "default") { | ||||
| 				return `${importVar}${propertyAccess(exportName, 1)}`; | ||||
| 			} else if (exportName.length === 0) { | ||||
| 				return `${importVar}_namespace`; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (exportName) { | ||||
| 			const used = module.getUsedName(moduleGraph, exportName); | ||||
| 		if (exportName.length > 0) { | ||||
| 			const exportsInfo = moduleGraph.getExportsInfo(module); | ||||
| 			const used = exportsInfo.getUsedName(exportName); | ||||
| 			if (!used) { | ||||
| 				const comment = Template.toNormalComment(`unused export ${exportName}`); | ||||
| 				const comment = Template.toNormalComment( | ||||
| 					`unused export ${exportName.join(".")}` | ||||
| 				); | ||||
| 				return `${comment} undefined`; | ||||
| 			} | ||||
| 			const comment = | ||||
| 				used !== exportName ? Template.toNormalComment(exportName) + " " : ""; | ||||
| 			const access = `${importVar}[${comment}${JSON.stringify(used)}]`; | ||||
| 			if (isCall) { | ||||
| 				if (callContext === false && asiSafe) { | ||||
| 			const comment = arrayEquals(used, exportName) | ||||
| 				? "" | ||||
| 				: Template.toNormalComment(exportName.join(".")) + " "; | ||||
| 			const access = `${importVar}${comment}${propertyAccess(used)}`; | ||||
| 			if (isCall && callContext === false) { | ||||
| 				if (asiSafe) { | ||||
| 					return `(0,${access})`; | ||||
| 				} else if (callContext === false) { | ||||
| 				} else { | ||||
| 					return `Object(${access})`; | ||||
| 				} | ||||
| 			} | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ class DependencyReference { | |||
| 	/** | ||||
| 	 * | ||||
| 	 * @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 {number} order the order information or NaN if don't care | ||||
| 	 */ | ||||
|  |  | |||
|  | @ -95,7 +95,7 @@ module.exports = class HarmonyExportDependencyParserPlugin { | |||
| 					dep = new HarmonyExportImportedSpecifierDependency( | ||||
| 						settings.source, | ||||
| 						settings.sourceOrder, | ||||
| 						settings.id, | ||||
| 						settings.ids, | ||||
| 						name, | ||||
| 						harmonyNamedExports, | ||||
| 						null, | ||||
|  | @ -125,7 +125,7 @@ module.exports = class HarmonyExportDependencyParserPlugin { | |||
| 				const dep = new HarmonyExportImportedSpecifierDependency( | ||||
| 					source, | ||||
| 					parser.state.lastHarmonyImportOrder, | ||||
| 					id, | ||||
| 					id ? [id] : [], | ||||
| 					name, | ||||
| 					harmonyNamedExports, | ||||
| 					harmonyStarExports && harmonyStarExports.slice(), | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| 
 | ||||
| const HarmonyLinkingError = require("../HarmonyLinkingError"); | ||||
| const InitFragment = require("../InitFragment"); | ||||
| const { UsageState } = require("../ModuleGraph"); | ||||
| const RuntimeGlobals = require("../RuntimeGlobals"); | ||||
| const Template = require("../Template"); | ||||
| const { intersect } = require("../util/SetHelpers"); | ||||
|  | @ -21,14 +22,15 @@ const HarmonyImportDependency = require("./HarmonyImportDependency"); | |||
| /** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */ | ||||
| /** @typedef {import("../Module")} Module */ | ||||
| /** @typedef {import("../ModuleGraph")} ModuleGraph */ | ||||
| /** @typedef {import("../ModuleGraph").ExportsInfo} ExportsInfo */ | ||||
| /** @typedef {import("../WebpackError")} WebpackError */ | ||||
| /** @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(); | ||||
| 
 | ||||
| /** @type {Set<string>} */ | ||||
|  | @ -43,8 +45,10 @@ class ExportMode { | |||
| 		this.type = type; | ||||
| 		/** @type {string|null} */ | ||||
| 		this.name = null; | ||||
| 		/** @type {Map<string, string>} */ | ||||
| 		/** @type {Map<string, string[]>} */ | ||||
| 		this.map = EMPTY_MAP; | ||||
| 		/** @type {ExportsInfo} */ | ||||
| 		this.partialNamespaceExportsInfo = undefined; | ||||
| 		/** @type {Set<string>|null} */ | ||||
| 		this.ignored = null; | ||||
| 		/** @type {Set<string>|null} */ | ||||
|  | @ -60,7 +64,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 	/** | ||||
| 	 * @param {string} request the request string | ||||
| 	 * @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 {Set<string>} activeExports other named exports in the module | ||||
| 	 * @param {Iterable<Dependency>} otherStarExports other star exports in the module | ||||
|  | @ -69,7 +73,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 	constructor( | ||||
| 		request, | ||||
| 		sourceOrder, | ||||
| 		id, | ||||
| 		ids, | ||||
| 		name, | ||||
| 		activeExports, | ||||
| 		otherStarExports, | ||||
|  | @ -77,32 +81,47 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 	) { | ||||
| 		super(request, sourceOrder); | ||||
| 
 | ||||
| 		this.id = id; | ||||
| 		this.ids = ids; | ||||
| 		this.name = name; | ||||
| 		this.activeExports = activeExports; | ||||
| 		this.otherStarExports = otherStarExports; | ||||
| 		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() { | ||||
| 		return "harmony export imported specifier"; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {ModuleGraph} moduleGraph the module graph | ||||
| 	 * @returns {string} the imported id | ||||
| 	 * @returns {string[]} the imported id | ||||
| 	 */ | ||||
| 	getId(moduleGraph) { | ||||
| 		return moduleGraph.getMeta(this)[idSymbol] || this.id; | ||||
| 	getIds(moduleGraph) { | ||||
| 		return moduleGraph.getMeta(this)[idsSymbol] || this.ids; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {ModuleGraph} moduleGraph the module graph | ||||
| 	 * @param {string} id the imported id | ||||
| 	 * @param {string[]} ids the imported ids | ||||
| 	 * @returns {void} | ||||
| 	 */ | ||||
| 	setId(moduleGraph, id) { | ||||
| 		moduleGraph.getMeta(this)[idSymbol] = id; | ||||
| 	setIds(moduleGraph, ids) { | ||||
| 		moduleGraph.getMeta(this)[idsSymbol] = ids; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
|  | @ -112,9 +131,10 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 	 */ | ||||
| 	getMode(moduleGraph, ignoreUnused) { | ||||
| 		const name = this.name; | ||||
| 		const id = this.getId(moduleGraph); | ||||
| 		const ids = this.getIds(moduleGraph); | ||||
| 		const parentModule = moduleGraph.getParentModule(this); | ||||
| 		const importedModule = moduleGraph.getModule(this); | ||||
| 		const exportsInfo = moduleGraph.getExportsInfo(parentModule); | ||||
| 
 | ||||
| 		if (!importedModule) { | ||||
| 			const mode = new ExportMode("missing"); | ||||
|  | @ -127,8 +147,8 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 		if ( | ||||
| 			!ignoreUnused && | ||||
| 			(name | ||||
| 				? parentModule.isExportUsed(moduleGraph, name) === false | ||||
| 				: parentModule.isModuleUsed(moduleGraph) === false) | ||||
| 				? exportsInfo.isExportUsed(name) === UsageState.Unused | ||||
| 				: exportsInfo.isUsed() === false) | ||||
| 		) { | ||||
| 			const mode = new ExportMode("unused"); | ||||
| 
 | ||||
|  | @ -141,7 +161,12 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 
 | ||||
| 		// Special handling for reexporting the default export
 | ||||
| 		// from non-harmony modules
 | ||||
| 		if (name && id === "default" && importedModule.buildMeta) { | ||||
| 		if ( | ||||
| 			name && | ||||
| 			ids.length > 0 && | ||||
| 			ids[0] === "default" && | ||||
| 			importedModule.buildMeta | ||||
| 		) { | ||||
| 			if (!importedModule.buildMeta.exportsType) { | ||||
| 				const mode = new ExportMode( | ||||
| 					strictHarmonyModule | ||||
|  | @ -169,15 +194,16 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 		// reexporting with a fixed name
 | ||||
| 		if (name) { | ||||
| 			let mode; | ||||
| 			const exportInfo = exportsInfo.getReadOnlyExportInfo(name); | ||||
| 
 | ||||
| 			if (id) { | ||||
| 			if (ids.length > 0) { | ||||
| 				// export { name as name }
 | ||||
| 				if (isNotAHarmonyModule && strictHarmonyModule) { | ||||
| 					mode = new ExportMode("rexport-non-harmony-undefined"); | ||||
| 					mode = new ExportMode("reexport-non-harmony-undefined"); | ||||
| 					mode.name = name; | ||||
| 				} else { | ||||
| 					mode = new ExportMode("normal-reexport"); | ||||
| 					mode.map = new Map([[name, id]]); | ||||
| 					mode.map = new Map([[name, ids]]); | ||||
| 					mode.checked = EMPTY_SET; | ||||
| 				} | ||||
| 			} else { | ||||
|  | @ -185,6 +211,14 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 				if (isNotAHarmonyModule && strictHarmonyModule) { | ||||
| 					mode = new ExportMode("reexport-fake-namespace-object"); | ||||
| 					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 { | ||||
| 					mode = new ExportMode("reexport-namespace-object"); | ||||
| 					mode.name = name; | ||||
|  | @ -198,12 +232,12 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 
 | ||||
| 		// Star reexporting
 | ||||
| 
 | ||||
| 		const exportsInfo = moduleGraph.getExportsInfo(parentModule); | ||||
| 		const importedExportsInfo = moduleGraph.getExportsInfo(importedModule); | ||||
| 
 | ||||
| 		const noExtraExports = | ||||
| 			importedExportsInfo.otherExportsInfo.provided === false; | ||||
| 		const noExtraImports = exportsInfo.otherExportsInfo.used === false; | ||||
| 		const noExtraImports = | ||||
| 			exportsInfo.otherExportsInfo.used === UsageState.Unused; | ||||
| 
 | ||||
| 		const ignoredExports = new Set([ | ||||
| 			"default", | ||||
|  | @ -233,7 +267,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 		if (noExtraImports) { | ||||
| 			for (const exportInfo of exportsInfo.exports) { | ||||
| 				if (ignoredExports.has(exportInfo.name)) continue; | ||||
| 				if (exportInfo.used !== false) { | ||||
| 				if (exportInfo.used !== UsageState.Unused) { | ||||
| 					imports.add(exportInfo.name); | ||||
| 				} | ||||
| 			} | ||||
|  | @ -272,10 +306,10 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 			return mode; | ||||
| 		} | ||||
| 
 | ||||
| 		/** @type {Map<string, string>} */ | ||||
| 		/** @type {Map<string, string[]>} */ | ||||
| 		const map = new Map(); | ||||
| 		for (const exportName of merged) { | ||||
| 			map.set(exportName, exportName); | ||||
| 			map.set(exportName, [exportName]); | ||||
| 		} | ||||
| 
 | ||||
| 		const mode = new ExportMode("normal-reexport"); | ||||
|  | @ -310,10 +344,37 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 					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-non-harmony-default-strict": | ||||
| 			case "reexport-fake-namespace-object": | ||||
| 			case "rexport-non-harmony-undefined": | ||||
| 			case "reexport-non-harmony-undefined": | ||||
| 				return new DependencyReference( | ||||
| 					mode.getModule, | ||||
| 					true, | ||||
|  | @ -395,20 +456,34 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 				}; | ||||
| 			case "normal-reexport": | ||||
| 				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()] | ||||
| 				}; | ||||
| 			case "reexport-fake-namespace-object": | ||||
| 			case "reexport-namespace-object": | ||||
| 			case "reexport-non-harmony-default": | ||||
| 			case "reexport-non-harmony-default-strict": | ||||
| 			case "rexport-non-harmony-undefined": | ||||
| 			case "reexport-non-harmony-undefined": | ||||
| 			case "reexport-named-default": | ||||
| 				return { | ||||
| 					exports: [mode.name], | ||||
| 					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: | ||||
| 				throw new Error(`Unknown mode ${mode.type}`); | ||||
| 		} | ||||
|  | @ -457,17 +532,18 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		const id = this.getId(moduleGraph); | ||||
| 		const ids = this.getIds(moduleGraph); | ||||
| 
 | ||||
| 		if (!importedModule.buildMeta || !importedModule.buildMeta.exportsType) { | ||||
| 			// It's not an harmony module
 | ||||
| 			if ( | ||||
| 				moduleGraph.getParentModule(this).buildMeta.strictHarmonyModule && | ||||
| 				id !== "default" | ||||
| 				(ids.length === 0 || ids[0] !== "default") | ||||
| 			) { | ||||
| 				// In strict harmony modules we only support the default export
 | ||||
| 				const exportName = id | ||||
| 					? `the named export '${id}'` | ||||
| 				const exportName = | ||||
| 					ids.length > 0 | ||||
| 						? `the named export ${ids.map(id => `'${id}'`).join(".")}` | ||||
| 						: "the namespace object"; | ||||
| 
 | ||||
| 				return [ | ||||
|  | @ -480,21 +556,21 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		if (!id) { | ||||
| 		if (ids.length === 0) { | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		if (moduleGraph.isExportProvided(importedModule, id) !== false) { | ||||
| 		if (moduleGraph.isExportProvided(importedModule, ids) !== false) { | ||||
| 			// It's provided or we are not sure
 | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		// We are sure that it's not provided
 | ||||
| 		const idIsNotNameMessage = | ||||
| 			id !== this.name ? ` (reexported as '${this.name}')` : ""; | ||||
| 		const errorMessage = `"export '${id}'${idIsNotNameMessage} was not found in '${ | ||||
| 			this.userRequest | ||||
| 		}'`;
 | ||||
| 			ids.join(".") !== this.name ? ` (reexported as '${this.name}')` : ""; | ||||
| 		const errorMessage = `"export ${this.ids | ||||
| 			.map(id => `'${id}'`) | ||||
| 			.join(".")}${idIsNotNameMessage} was not found in '${this.userRequest}'`;
 | ||||
| 
 | ||||
| 		return [new HarmonyLinkingError(errorMessage)]; | ||||
| 	} | ||||
|  | @ -513,7 +589,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 		hash.update(mode.type); | ||||
| 		for (const [k, v] of mode.map) { | ||||
| 			hash.update(k); | ||||
| 			hash.update(v); | ||||
| 			hash.update(v.join()); | ||||
| 		} | ||||
| 		if (mode.ignored) { | ||||
| 			hash.update("ignored"); | ||||
|  | @ -527,7 +603,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 	serialize(context) { | ||||
| 		const { write } = context; | ||||
| 
 | ||||
| 		write(this.id); | ||||
| 		write(this.ids); | ||||
| 		write(this.name); | ||||
| 		write(this.activeExports); | ||||
| 		write(this.otherStarExports); | ||||
|  | @ -539,7 +615,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency { | |||
| 	deserialize(context) { | ||||
| 		const { read } = context; | ||||
| 
 | ||||
| 		this.id = read(); | ||||
| 		this.ids = read(); | ||||
| 		this.name = read(); | ||||
| 		this.activeExports = read(); | ||||
| 		this.otherStarExports = read(); | ||||
|  | @ -685,7 +761,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS | |||
| 				); | ||||
| 				break; | ||||
| 
 | ||||
| 			case "rexport-non-harmony-undefined": | ||||
| 			case "reexport-non-harmony-undefined": | ||||
| 				initFragments.push( | ||||
| 					new InitFragment( | ||||
| 						"/* harmony reexport (non default export from non-harmony) */ " + | ||||
|  | @ -720,6 +796,7 @@ HarmonyExportImportedSpecifierDependency.Template = class HarmonyExportImportedS | |||
| 				break; | ||||
| 
 | ||||
| 			case "reexport-namespace-object": | ||||
| 			case "reexport-partial-namespace-object": | ||||
| 				initFragments.push( | ||||
| 					new InitFragment( | ||||
| 						"/* harmony reexport (module object) */ " + | ||||
|  |  | |||
|  | @ -44,9 +44,10 @@ module.exports = class HarmonyImportDependencyParserPlugin { | |||
| 				if (!parser.state.harmonySpecifier) { | ||||
| 					parser.state.harmonySpecifier = new Map(); | ||||
| 				} | ||||
| 				const ids = id === null ? [] : [id]; | ||||
| 				parser.state.harmonySpecifier.set(name, { | ||||
| 					source, | ||||
| 					id, | ||||
| 					ids, | ||||
| 					sourceOrder: parser.state.lastHarmonyImportOrder | ||||
| 				}); | ||||
| 				return true; | ||||
|  | @ -60,7 +61,7 @@ module.exports = class HarmonyImportDependencyParserPlugin { | |||
| 				const dep = new HarmonyImportSpecifierDependency( | ||||
| 					settings.source, | ||||
| 					settings.sourceOrder, | ||||
| 					settings.id, | ||||
| 					settings.ids, | ||||
| 					name, | ||||
| 					expr.range, | ||||
| 					this.strictExportPresence | ||||
|  | @ -71,45 +72,40 @@ module.exports = class HarmonyImportDependencyParserPlugin { | |||
| 				parser.state.module.addDependency(dep); | ||||
| 				return true; | ||||
| 			}); | ||||
| 		parser.hooks.expressionAnyMember | ||||
| 		parser.hooks.expressionMemberChain | ||||
| 			.for("imported var") | ||||
| 			.tap("HarmonyImportDependencyParserPlugin", expr => { | ||||
| 				const name = expr.object.name; | ||||
| 			.tap("HarmonyImportDependencyParserPlugin", (expr, name, members) => { | ||||
| 				const settings = parser.state.harmonySpecifier.get(name); | ||||
| 				if (settings.id !== null) return false; | ||||
| 				const ids = settings.ids.concat(members); | ||||
| 				const dep = new HarmonyImportSpecifierDependency( | ||||
| 					settings.source, | ||||
| 					settings.sourceOrder, | ||||
| 					expr.property.name || expr.property.value, | ||||
| 					ids, | ||||
| 					name, | ||||
| 					expr.range, | ||||
| 					this.strictExportPresence | ||||
| 				); | ||||
| 				dep.shorthand = parser.scope.inShorthand; | ||||
| 				dep.directImport = false; | ||||
| 				dep.loc = expr.loc; | ||||
| 				parser.state.module.addDependency(dep); | ||||
| 				return true; | ||||
| 			}); | ||||
| 		if (this.strictThisContextOnImports) { | ||||
| 			// only in case when we strictly follow the spec we need a special case here
 | ||||
| 			parser.hooks.callAnyMember | ||||
| 			parser.hooks.callMemberChain | ||||
| 				.for("imported var") | ||||
| 				.tap("HarmonyImportDependencyParserPlugin", expr => { | ||||
| 					if (expr.callee.type !== "MemberExpression") return; | ||||
| 					if (expr.callee.object.type !== "Identifier") return; | ||||
| 					const name = expr.callee.object.name; | ||||
| 				.tap("HarmonyImportDependencyParserPlugin", (expr, name, members) => { | ||||
| 					if (members.length <= 0) return; | ||||
| 					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( | ||||
| 						settings.source, | ||||
| 						settings.sourceOrder, | ||||
| 						expr.callee.property.name || expr.callee.property.value, | ||||
| 						ids, | ||||
| 						name, | ||||
| 						expr.callee.range, | ||||
| 						this.strictExportPresence | ||||
| 					); | ||||
| 					dep.shorthand = parser.scope.inShorthand; | ||||
| 					dep.directImport = false; | ||||
| 					dep.namespaceObjectAsContext = true; | ||||
| 					dep.loc = expr.callee.loc; | ||||
|  | @ -129,7 +125,7 @@ module.exports = class HarmonyImportDependencyParserPlugin { | |||
| 				const dep = new HarmonyImportSpecifierDependency( | ||||
| 					settings.source, | ||||
| 					settings.sourceOrder, | ||||
| 					settings.id, | ||||
| 					settings.ids, | ||||
| 					name, | ||||
| 					expr.range, | ||||
| 					this.strictExportPresence | ||||
|  |  | |||
|  | @ -19,12 +19,12 @@ const HarmonyImportDependency = require("./HarmonyImportDependency"); | |||
| /** @typedef {import("../WebpackError")} WebpackError */ | ||||
| /** @typedef {import("../util/createHash").Hash} Hash */ | ||||
| 
 | ||||
| const idSymbol = Symbol("HarmonyImportSpecifierDependency.id"); | ||||
| const idsSymbol = Symbol("HarmonyImportSpecifierDependency.ids"); | ||||
| 
 | ||||
| class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | ||||
| 	constructor(request, sourceOrder, id, name, range, strictExportPresence) { | ||||
| 	constructor(request, sourceOrder, ids, name, range, strictExportPresence) { | ||||
| 		super(request, sourceOrder); | ||||
| 		this.id = id === null ? null : `${id}`; | ||||
| 		this.ids = ids; | ||||
| 		this.name = name; | ||||
| 		this.range = range; | ||||
| 		this.strictExportPresence = strictExportPresence; | ||||
|  | @ -34,25 +34,40 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | |||
| 		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() { | ||||
| 		return "harmony import specifier"; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {ModuleGraph} moduleGraph the module graph | ||||
| 	 * @returns {string} the imported id | ||||
| 	 * @returns {string[]} the imported ids | ||||
| 	 */ | ||||
| 	getId(moduleGraph) { | ||||
| 		return moduleGraph.getMeta(this)[idSymbol] || this.id; | ||||
| 	getIds(moduleGraph) { | ||||
| 		return moduleGraph.getMeta(this)[idsSymbol] || this.ids; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
| 	 * @param {ModuleGraph} moduleGraph the module graph | ||||
| 	 * @param {string} id the imported id | ||||
| 	 * @param {string[]} ids the imported ids | ||||
| 	 * @returns {void} | ||||
| 	 */ | ||||
| 	setId(moduleGraph, id) { | ||||
| 		moduleGraph.getMeta(this)[idSymbol] = id; | ||||
| 	setIds(moduleGraph, ids) { | ||||
| 		moduleGraph.getMeta(this)[idsSymbol] = ids; | ||||
| 	} | ||||
| 
 | ||||
| 	/** | ||||
|  | @ -63,11 +78,10 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | |||
| 	getReference(moduleGraph) { | ||||
| 		const module = moduleGraph.getModule(this); | ||||
| 		if (!module) return null; | ||||
| 		const ids = this.getIds(moduleGraph); | ||||
| 		return new DependencyReference( | ||||
| 			() => moduleGraph.getModule(this), | ||||
| 			this.getId(moduleGraph) && !this.namespaceObjectAsContext | ||||
| 				? [this.getId(moduleGraph)] | ||||
| 				: true, | ||||
| 			ids.length > 0 && !this.namespaceObjectAsContext ? [ids] : true, | ||||
| 			false, | ||||
| 			this.sourceOrder | ||||
| 		); | ||||
|  | @ -113,15 +127,17 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | |||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		const ids = this.getIds(moduleGraph); | ||||
| 		if (!importedModule.buildMeta || !importedModule.buildMeta.exportsType) { | ||||
| 			// It's not an harmony module
 | ||||
| 			if ( | ||||
| 				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
 | ||||
| 				const exportName = this.getId(moduleGraph) | ||||
| 					? `the named export '${this.getId(moduleGraph)}'` | ||||
| 				const exportName = | ||||
| 					ids.length > 0 | ||||
| 						? `the named export '${ids[0]}'` | ||||
| 						: "the namespace object"; | ||||
| 				return [ | ||||
| 					new HarmonyLinkingError( | ||||
|  | @ -132,22 +148,21 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | |||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		const id = this.getId(moduleGraph); | ||||
| 		if (!id) { | ||||
| 		if (ids.length === 0) { | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		if (moduleGraph.isExportProvided(importedModule, id) !== false) { | ||||
| 		if (moduleGraph.isExportProvided(importedModule, ids) !== false) { | ||||
| 			// It's provided or we are not sure
 | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		// We are sure that it's not provided
 | ||||
| 		const idIsNotNameMessage = | ||||
| 			id !== this.name ? ` (imported as '${this.name}')` : ""; | ||||
| 		const errorMessage = `"export '${this.getId( | ||||
| 			moduleGraph | ||||
| 		)}'${idIsNotNameMessage} was not found in '${this.userRequest}'`;
 | ||||
| 			ids[0] !== this.name ? ` (imported as '${this.name}')` : ""; | ||||
| 		const errorMessage = `"export ${ids | ||||
| 			.map(id => `'${id}'`) | ||||
| 			.join(".")}${idIsNotNameMessage} was not found in '${this.userRequest}'`;
 | ||||
| 		return [new HarmonyLinkingError(errorMessage)]; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -169,10 +184,11 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | |||
| 		super.updateHash(hash, chunkGraph); | ||||
| 		const moduleGraph = chunkGraph.moduleGraph; | ||||
| 		const importedModule = moduleGraph.getModule(this); | ||||
| 		const ids = this.getIds(moduleGraph); | ||||
| 		hash.update(ids.join()); | ||||
| 		if (importedModule) { | ||||
| 			const id = this.getId(moduleGraph); | ||||
| 			hash.update(id + ""); | ||||
| 			hash.update((id && importedModule.getUsedName(moduleGraph, id)) + ""); | ||||
| 			const exportsInfo = moduleGraph.getExportsInfo(importedModule); | ||||
| 			hash.update(JSON.stringify(exportsInfo.getUsedName(ids))); | ||||
| 			hash.update( | ||||
| 				(!importedModule.buildMeta || importedModule.buildMeta.exportsType) + "" | ||||
| 			); | ||||
|  | @ -181,7 +197,7 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | |||
| 
 | ||||
| 	serialize(context) { | ||||
| 		const { write } = context; | ||||
| 		write(this.id); | ||||
| 		write(this.ids); | ||||
| 		write(this.name); | ||||
| 		write(this.range); | ||||
| 		write(this.strictExportPresence); | ||||
|  | @ -194,7 +210,7 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency { | |||
| 
 | ||||
| 	deserialize(context) { | ||||
| 		const { read } = context; | ||||
| 		this.id = read(); | ||||
| 		this.ids = read(); | ||||
| 		this.name = read(); | ||||
| 		this.range = read(); | ||||
| 		this.strictExportPresence = read(); | ||||
|  | @ -229,11 +245,12 @@ HarmonyImportSpecifierDependency.Template = class HarmonyImportSpecifierDependen | |||
| 		dep, | ||||
| 		{ runtimeTemplate, module, moduleGraph, runtimeRequirements } | ||||
| 	) { | ||||
| 		const ids = dep.getIds(moduleGraph); | ||||
| 		const exportExpr = runtimeTemplate.exportFromImport({ | ||||
| 			moduleGraph, | ||||
| 			module: moduleGraph.getModule(dep), | ||||
| 			request: dep.request, | ||||
| 			exportName: dep.getId(moduleGraph), | ||||
| 			exportName: ids, | ||||
| 			originModule: module, | ||||
| 			asiSafe: dep.shorthand, | ||||
| 			isCall: dep.call, | ||||
|  |  | |||
|  | @ -11,6 +11,7 @@ const DependencyTemplate = require("../DependencyTemplate"); | |||
| const InitFragment = require("../InitFragment"); | ||||
| const JavascriptParser = require("../JavascriptParser"); | ||||
| const Module = require("../Module"); | ||||
| const { UsageState } = require("../ModuleGraph"); | ||||
| const RuntimeGlobals = require("../RuntimeGlobals"); | ||||
| const Template = require("../Template"); | ||||
| const DependencyReference = require("../dependencies/DependencyReference"); | ||||
|  | @ -23,6 +24,7 @@ const HarmonyImportSideEffectDependency = require("../dependencies/HarmonyImport | |||
| const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency"); | ||||
| const createHash = require("../util/createHash"); | ||||
| const contextify = require("../util/identifier").contextify; | ||||
| const propertyAccess = require("../util/propertyAccess"); | ||||
| 
 | ||||
| /** @typedef {import("webpack-sources").Source} Source */ | ||||
| /** @typedef {import("../ChunkGraph")} ChunkGraph */ | ||||
|  | @ -38,23 +40,29 @@ const contextify = require("../util/identifier").contextify; | |||
| /** @typedef {import("../WebpackError")} WebpackError */ | ||||
| /** @typedef {import("../util/createHash").Hash} Hash */ | ||||
| 
 | ||||
| /** | ||||
|  * @typedef {Object} ReexportInfo | ||||
|  * @property {Module} module | ||||
|  * @property {string[]} exportName | ||||
|  * @property {Dependency} dependency | ||||
|  */ | ||||
| 
 | ||||
| /** @typedef {ConcatenatedModuleInfo | ExternalModuleInfo } ModuleInfo */ | ||||
| 
 | ||||
| /** | ||||
|  * @typedef {Object} ConcatenatedModuleInfo | ||||
|  * @property {"concatenated"} type | ||||
|  * @property {Module} module | ||||
|  * @property {TODO} index | ||||
|  * @property {TODO} ast | ||||
|  * @property {TODO} internalSource | ||||
|  * @property {TODO} source | ||||
|  * @property {number} index | ||||
|  * @property {Object} ast | ||||
|  * @property {Source} internalSource | ||||
|  * @property {ReplaceSource} source | ||||
|  * @property {TODO} globalScope | ||||
|  * @property {TODO} moduleScope | ||||
|  * @property {TODO} internalNames | ||||
|  * @property {TODO} globalExports | ||||
|  * @property {TODO} exportMap | ||||
|  * @property {TODO} reexportMap | ||||
|  * @property {TODO} hasNamespaceObject | ||||
|  * @property {Map<string | true, string>} exportMap | ||||
|  * @property {Map<string, ReexportInfo>} reexportMap | ||||
|  * @property {boolean} hasNamespaceObject | ||||
|  * @property {TODO} namespaceObjectSource | ||||
|  */ | ||||
| 
 | ||||
|  | @ -62,12 +70,12 @@ const contextify = require("../util/identifier").contextify; | |||
|  * @typedef {Object} ExternalModuleInfo | ||||
|  * @property {"external"} type | ||||
|  * @property {Module} module | ||||
|  * @property {TODO} index | ||||
|  * @property {TODO} name | ||||
|  * @property {TODO} interopNamespaceObjectUsed | ||||
|  * @property {TODO} interopNamespaceObjectName | ||||
|  * @property {TODO} interopDefaultAccessUsed | ||||
|  * @property {TODO} interopDefaultAccessName | ||||
|  * @property {number} index | ||||
|  * @property {string} name | ||||
|  * @property {boolean} interopNamespaceObjectUsed | ||||
|  * @property {string} interopNamespaceObjectName | ||||
|  * @property {boolean} interopDefaultAccessUsed | ||||
|  * @property {string} interopDefaultAccessName | ||||
|  */ | ||||
| 
 | ||||
| const RESERVED_NAMES = [ | ||||
|  | @ -105,12 +113,27 @@ const RESERVED_NAMES = [ | |||
| 	.join(",") | ||||
| 	.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 | ||||
|  * @property {"concatenated" | "external"} type | ||||
|  * @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 = ( | ||||
| 	moduleGraph, | ||||
| 	info, | ||||
|  | @ -125,11 +148,12 @@ const ensureNsObjSource = ( | |||
| 			`var ${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( | ||||
| 				moduleGraph, | ||||
| 				info, | ||||
| 				exportName, | ||||
| 				[exportInfo.name], | ||||
| 				moduleToInfoMap, | ||||
| 				requestShortener, | ||||
| 				false, | ||||
|  | @ -137,7 +161,7 @@ const ensureNsObjSource = ( | |||
| 			); | ||||
| 			nsObj.push( | ||||
| 				`${RuntimeGlobals.definePropertyGetter}(${name}, ${JSON.stringify( | ||||
| 					exportName | ||||
| 					exportInfo.getUsedName() | ||||
| 				)}, 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 = ( | ||||
| 	moduleGraph, | ||||
| 	importedModule, | ||||
|  | @ -154,54 +187,75 @@ const getExternalImport = ( | |||
| 	strictHarmonyModule | ||||
| ) => { | ||||
| 	const used = | ||||
| 		exportName === true || importedModule.getUsedName(moduleGraph, exportName); | ||||
| 		exportName.length === 0 || | ||||
| 		importedModule.getUsedName(moduleGraph, exportName); | ||||
| 	if (!used) return "/* unused reexport */undefined"; | ||||
| 	const comment = | ||||
| 		used !== exportName ? ` ${Template.toNormalComment(exportName)}` : ""; | ||||
| 	const comment = arrayEquals(used, exportName) | ||||
| 		? "" | ||||
| 		: Template.toNormalComment(`${exportName.join(".")}`); | ||||
| 	let exprStart; | ||||
| 	if (exportName.length === 0) { | ||||
| 		switch (importedModule.buildMeta.exportsType) { | ||||
| 			case "named": | ||||
| 			if (exportName === "default") { | ||||
| 				return info.name; | ||||
| 			} else if (exportName === true) { | ||||
| 				info.interopNamespaceObjectUsed = true; | ||||
| 				return info.interopNamespaceObjectName; | ||||
| 			} else { | ||||
| 				exprStart = info.interopNamespaceObjectName; | ||||
| 				break; | ||||
| 			} | ||||
| 			case "namespace": | ||||
| 			if (exportName === true) { | ||||
| 				return info.name; | ||||
| 			} else { | ||||
| 				exprStart = info.name; | ||||
| 				break; | ||||
| 			} | ||||
| 			default: | ||||
| 				if (strictHarmonyModule) { | ||||
| 				if (exportName === "default") { | ||||
| 					return info.name; | ||||
| 				} else if (exportName === true) { | ||||
| 					info.interopNamespaceObjectUsed = true; | ||||
| 					return info.interopNamespaceObjectName; | ||||
| 				} else { | ||||
| 					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; | ||||
| 					exprStart = info.interopNamespaceObjectName; | ||||
| 					break; | ||||
| 				} else { | ||||
| 					exprStart = info.name; | ||||
| 					break; | ||||
| 				} | ||||
| 		} | ||||
| 	} else { | ||||
| 		switch (importedModule.buildMeta.exportsType) { | ||||
| 			case "named": | ||||
| 				if (exportName[0] === "default") { | ||||
| 					exprStart = info.name; | ||||
| 				} | ||||
| 	const reference = `${info.name}[${JSON.stringify(used)}${comment}]`; | ||||
| 	if (asCall) return `Object(${reference})`; | ||||
| 	return reference; | ||||
| 				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; | ||||
| 		} | ||||
| 	} | ||||
| 	if (exprStart) { | ||||
| 		return `${exprStart}${propertyAccess(exportName, 1)}`; | ||||
| 	} | ||||
| 	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 = ( | ||||
| 	moduleGraph, | ||||
| 	info, | ||||
|  | @ -214,9 +268,7 @@ const getFinalName = ( | |||
| ) => { | ||||
| 	switch (info.type) { | ||||
| 		case "concatenated": { | ||||
| 			const directExport = info.exportMap.get(exportName); | ||||
| 			if (directExport) { | ||||
| 				if (exportName === true) { | ||||
| 			if (exportName.length === 0) { | ||||
| 				ensureNsObjSource( | ||||
| 					moduleGraph, | ||||
| 					info, | ||||
|  | @ -224,11 +276,17 @@ const getFinalName = ( | |||
| 					requestShortener, | ||||
| 					strictHarmonyModule | ||||
| 				); | ||||
| 				} else if (!info.module.isExportUsed(moduleGraph, exportName)) { | ||||
| 					return "/* unused export */ undefined"; | ||||
| 				return info.internalNames.get(info.exportMap.get(true)); | ||||
| 			} | ||||
| 				if (info.globalExports.has(directExport)) { | ||||
| 					return directExport; | ||||
| 			const exportId = exportName[0]; | ||||
| 			const directExport = info.exportMap.get(exportId); | ||||
| 			const exportsInfo = moduleGraph.getExportsInfo(info.module); | ||||
| 			if (directExport) { | ||||
| 				if (exportsInfo.isExportUsed(exportName) === UsageState.Unused) { | ||||
| 					return `/* unused export */ undefined${propertyAccess( | ||||
| 						exportName, | ||||
| 						1 | ||||
| 					)}`;
 | ||||
| 				} | ||||
| 				const name = info.internalNames.get(directExport); | ||||
| 				if (!name) { | ||||
|  | @ -238,23 +296,23 @@ const getFinalName = ( | |||
| 						)}" 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 (alreadyVisited.has(reexport)) { | ||||
| 					throw new Error( | ||||
| 						`Circular reexports ${Array.from( | ||||
| 							alreadyVisited, | ||||
| 							e => | ||||
| 								`"${e.module.readableIdentifier(requestShortener)}".${ | ||||
| 									e.exportName | ||||
| 								}` | ||||
| 								`"${e.module.readableIdentifier( | ||||
| 									requestShortener | ||||
| 								)}".${e.exportName.join(".")}` | ||||
| 						).join( | ||||
| 							" --> " | ||||
| 						)} -(circular)-> "${reexport.module.readableIdentifier( | ||||
| 							requestShortener | ||||
| 						)}".${reexport.exportName}` | ||||
| 						)}".${reexport.exportName.join(".")}` | ||||
| 					); | ||||
| 				} | ||||
| 				alreadyVisited.add(reexport); | ||||
|  | @ -264,7 +322,7 @@ const getFinalName = ( | |||
| 					return getFinalName( | ||||
| 						moduleGraph, | ||||
| 						refInfo, | ||||
| 						reexport.exportName, | ||||
| 						[...reexport.exportName, ...exportName.slice(1)], | ||||
| 						moduleToInfoMap, | ||||
| 						requestShortener, | ||||
| 						asCall, | ||||
|  | @ -281,7 +339,10 @@ const getFinalName = ( | |||
| 					.filter(name => name !== true) | ||||
| 					.join(" ")}, ` +
 | ||||
| 				`known reexports: ${Array.from(info.reexportMap.keys()).join(" ")})`; | ||||
| 			return `${Template.toNormalComment(problem)} undefined`; | ||||
| 			return `${Template.toNormalComment(problem)} undefined${propertyAccess( | ||||
| 				exportName, | ||||
| 				1 | ||||
| 			)}`;
 | ||||
| 		} | ||||
| 		case "external": { | ||||
| 			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]]; | ||||
| 						let exportName; | ||||
| 						if (match[2] === "ns") { | ||||
| 							exportName = true; | ||||
| 							exportName = []; | ||||
| 						} else { | ||||
| 							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 strictHarmonyModule = !!match[4]; | ||||
|  | @ -850,7 +902,10 @@ class ConcatenatedModule extends Module { | |||
| 		const result = new ConcatSource(); | ||||
| 
 | ||||
| 		// 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( | ||||
| 				runtimeTemplate.defineEsModuleFlagStatement({ | ||||
| 					exportsArgument: this.exportsArgument, | ||||
|  | @ -985,7 +1040,9 @@ class ConcatenatedModule extends Module { | |||
| 			let result; | ||||
| 			switch (info.type) { | ||||
| 				case "concatenated": { | ||||
| 					/** @type {Map<string | true, string>} */ | ||||
| 					const exportMap = new Map(); | ||||
| 					/** @type {Map<string, ReexportInfo>} */ | ||||
| 					const reexportMap = new Map(); | ||||
| 					for (const dep of info.module.dependencies) { | ||||
| 						if (dep instanceof HarmonyExportSpecifierDependency) { | ||||
|  | @ -1000,21 +1057,13 @@ class ConcatenatedModule extends Module { | |||
| 							dep instanceof HarmonyExportImportedSpecifierDependency | ||||
| 						) { | ||||
| 							const exportName = dep.name; | ||||
| 							const importName = dep.getId(moduleGraph); | ||||
| 							const importNames = dep.getIds(moduleGraph); | ||||
| 							const importedModule = moduleGraph.getModule(dep); | ||||
| 							if (exportName && importName) { | ||||
| 							if (exportName) { | ||||
| 								if (!reexportMap.has(exportName)) { | ||||
| 									reexportMap.set(exportName, { | ||||
| 										module: importedModule, | ||||
| 										exportName: importName, | ||||
| 										dependency: dep | ||||
| 									}); | ||||
| 								} | ||||
| 							} else if (exportName) { | ||||
| 								if (!reexportMap.has(exportName)) { | ||||
| 									reexportMap.set(exportName, { | ||||
| 										module: importedModule, | ||||
| 										exportName: true, | ||||
| 										exportName: importNames, | ||||
| 										dependency: dep | ||||
| 									}); | ||||
| 								} | ||||
|  | @ -1030,7 +1079,7 @@ class ConcatenatedModule extends Module { | |||
| 										if (!reexportMap.has(name)) { | ||||
| 											reexportMap.set(name, { | ||||
| 												module: importedModule, | ||||
| 												exportName: name, | ||||
| 												exportName: [name], | ||||
| 												dependency: dep | ||||
| 											}); | ||||
| 										} | ||||
|  | @ -1049,7 +1098,6 @@ class ConcatenatedModule extends Module { | |||
| 						globalScope: undefined, | ||||
| 						moduleScope: undefined, | ||||
| 						internalNames: new Map(), | ||||
| 						globalExports: new Set(), | ||||
| 						exportMap: exportMap, | ||||
| 						reexportMap: reexportMap, | ||||
| 						hasNamespaceObject: false, | ||||
|  | @ -1269,15 +1317,17 @@ class HarmonyImportSpecifierDependencyConcatenatedTemplate extends DependencyTem | |||
| 		const strictFlag = parentModule.buildMeta.strictHarmonyModule | ||||
| 			? "_strict" | ||||
| 			: ""; | ||||
| 		const id = dep.getId(moduleGraph); | ||||
| 		if (id === null) { | ||||
| 		const ids = dep.getIds(moduleGraph); | ||||
| 		if (ids.length === 0) { | ||||
| 			content = `__WEBPACK_MODULE_REFERENCE__${info.index}_ns${strictFlag}__`; | ||||
| 		} else if (dep.namespaceObjectAsContext) { | ||||
| 		} else if (dep.namespaceObjectAsContext && ids.length === 1) { | ||||
| 			content = `__WEBPACK_MODULE_REFERENCE__${ | ||||
| 				info.index | ||||
| 			}_ns${strictFlag}__[${JSON.stringify(id)}]`;
 | ||||
| 			}_ns${strictFlag}__${propertyAccess(ids)}`;
 | ||||
| 		} 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__${ | ||||
| 				info.index | ||||
| 			}_${exportData}${callFlag}${strictFlag}__`;
 | ||||
|  | @ -1398,7 +1448,7 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate extends Depen | |||
| 	/** | ||||
| 	 * @typedef {Object} GetExportsResultItem | ||||
| 	 * @property {string} name | ||||
| 	 * @property {string | true} id | ||||
| 	 * @property {string[]} ids | ||||
| 	 */ | ||||
| 
 | ||||
| 	/** | ||||
|  | @ -1408,13 +1458,13 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate extends Depen | |||
| 	 */ | ||||
| 	getExports(dep, { moduleGraph }) { | ||||
| 		const importModule = moduleGraph.getModule(dep); | ||||
| 		const id = dep.getId(moduleGraph); | ||||
| 		if (id) { | ||||
| 		const ids = dep.getIds(moduleGraph); | ||||
| 		if (ids.length > 0) { | ||||
| 			// export { named } from "module"
 | ||||
| 			return [ | ||||
| 				{ | ||||
| 					name: dep.name, | ||||
| 					id | ||||
| 					ids | ||||
| 				} | ||||
| 			]; | ||||
| 		} | ||||
|  | @ -1423,7 +1473,7 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate extends Depen | |||
| 			return [ | ||||
| 				{ | ||||
| 					name: dep.name, | ||||
| 					id: true | ||||
| 					ids: [] | ||||
| 				} | ||||
| 			]; | ||||
| 		} | ||||
|  | @ -1435,7 +1485,7 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate extends Depen | |||
| 				.map(exp => { | ||||
| 					return { | ||||
| 						name: exp, | ||||
| 						id: exp | ||||
| 						ids: [exp] | ||||
| 					}; | ||||
| 				}); | ||||
| 		} | ||||
|  | @ -1465,7 +1515,7 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate extends Depen | |||
| 				if (!used) { | ||||
| 					initFragments.push( | ||||
| 						new InitFragment( | ||||
| 							`/* unused concated harmony import ${dep.name} */\n`, | ||||
| 							`/* unused concated harmony import ${def.name} */\n`, | ||||
| 							InitFragment.STAGE_HARMONY_EXPORTS, | ||||
| 							1 | ||||
| 						) | ||||
|  | @ -1476,12 +1526,15 @@ class HarmonyExportImportedSpecifierDependencyConcatenatedTemplate extends Depen | |||
| 				const strictFlag = module.buildMeta.strictHarmonyModule | ||||
| 					? "_strict" | ||||
| 					: ""; | ||||
| 				if (def.id === true) { | ||||
| 				if (def.ids.length === 0) { | ||||
| 					finalName = `__WEBPACK_MODULE_REFERENCE__${ | ||||
| 						info.index | ||||
| 					}_ns${strictFlag}__`;
 | ||||
| 				} 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__${ | ||||
| 						info.index | ||||
| 					}_${exportData}${strictFlag}__`;
 | ||||
|  |  | |||
|  | @ -104,11 +104,11 @@ class SideEffectsFlagPlugin { | |||
| 										if (!map) { | ||||
| 											reexportMaps.set(module, (map = new Map())); | ||||
| 										} | ||||
| 										for (const [key, id] of mode.map) { | ||||
| 											if (!mode.checked.has(key)) { | ||||
| 										for (const [key, ids] of mode.map) { | ||||
| 											if (ids.length > 0 && !mode.checked.has(key)) { | ||||
| 												map.set(key, { | ||||
| 													module: mode.getModule(), | ||||
| 													exportName: id | ||||
| 													exportName: ids[0] | ||||
| 												}); | ||||
| 											} | ||||
| 										} | ||||
|  | @ -147,20 +147,29 @@ class SideEffectsFlagPlugin { | |||
| 								(dep instanceof HarmonyImportSpecifierDependency && | ||||
| 									!dep.namespaceObjectAsContext) | ||||
| 							) { | ||||
| 								const mapping = map.get(dep.id); | ||||
| 								// TODO improve for nested imports
 | ||||
| 								const ids = dep.getIds(moduleGraph); | ||||
| 								if (ids.length > 0) { | ||||
| 									const mapping = map.get(ids[0]); | ||||
| 									if (mapping) { | ||||
| 										moduleGraph.updateModule(dep, mapping.module); | ||||
| 										moduleGraph.addExplanation( | ||||
| 											dep, | ||||
| 											"(skipped side-effect-free modules)" | ||||
| 										); | ||||
| 									dep.setId(moduleGraph, mapping.exportName); | ||||
| 										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; | ||||
| 
 | ||||
| 									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
 | ||||
| 											if ( | ||||
| 												Object.prototype.hasOwnProperty.call( | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| 
 | ||||
| const { RawSource } = require("webpack-sources"); | ||||
| const Generator = require("../Generator"); | ||||
| const { UsageState } = require("../ModuleGraph"); | ||||
| const RuntimeGlobals = require("../RuntimeGlobals"); | ||||
| const Template = require("../Template"); | ||||
| const WebAssemblyExportImportedDependency = require("../dependencies/WebAssemblyExportImportedDependency"); | ||||
|  | @ -148,12 +149,13 @@ class WebAssemblyJavascriptGenerator extends Generator { | |||
| 		); | ||||
| 
 | ||||
| 		const copyAllExports = | ||||
| 			exportsInfo.otherExportsInfo.used === false && !needExportsCopy; | ||||
| 			exportsInfo.otherExportsInfo.used === UsageState.Unused && | ||||
| 			!needExportsCopy; | ||||
| 
 | ||||
| 		// need these globals
 | ||||
| 		runtimeRequirements.add(RuntimeGlobals.module); | ||||
| 		runtimeRequirements.add(RuntimeGlobals.wasmInstances); | ||||
| 		if (exportsInfo.otherExportsInfo.used !== false) { | ||||
| 		if (exportsInfo.otherExportsInfo.used !== UsageState.Unused) { | ||||
| 			runtimeRequirements.add(RuntimeGlobals.makeNamespaceObject); | ||||
| 			runtimeRequirements.add(RuntimeGlobals.exports); | ||||
| 		} | ||||
|  | @ -170,7 +172,7 @@ class WebAssemblyJavascriptGenerator extends Generator { | |||
| 					module.moduleArgument | ||||
| 				}.i];`,
 | ||||
| 
 | ||||
| 				exportsInfo.otherExportsInfo.used !== false | ||||
| 				exportsInfo.otherExportsInfo.used !== UsageState.Unused | ||||
| 					? `${RuntimeGlobals.makeNamespaceObject}(${module.exportsArgument});` | ||||
| 					: "", | ||||
| 
 | ||||
|  |  | |||
|  | @ -430,7 +430,7 @@ Child all: | |||
| `; | ||||
| 
 | ||||
| exports[`StatsTestCases should print correct stats for chunk-module-id-range 1`] = ` | ||||
| "Hash: 72e3b32fcbbc550ae041 | ||||
| "Hash: 4b7df25b6465c464acfe | ||||
| Time: Xms | ||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | ||||
| PublicPath: (none) | ||||
|  | @ -503,10 +503,10 @@ Time: Xms | |||
| Built at: Thu Jan 01 1970 00:00:00 GMT | ||||
| PublicPath: (none) | ||||
|               Asset       Size       Chunks             Chunk Names | ||||
|      b_js.bundle.js  370 bytes       {b_js}  [emitted] | ||||
|           bundle.js   8.23 KiB       {main}  [emitted]  main | ||||
|      c_js.bundle.js  579 bytes       {c_js}  [emitted] | ||||
| d_js-e_js.bundle.js  772 bytes  {d_js-e_js}  [emitted] | ||||
|      b_js.bundle.js  364 bytes       {b_js}  [emitted] | ||||
|           bundle.js   8.22 KiB       {main}  [emitted]  main | ||||
|      c_js.bundle.js  573 bytes       {c_js}  [emitted] | ||||
| d_js-e_js.bundle.js  760 bytes  {d_js-e_js}  [emitted] | ||||
| Entrypoint main = bundle.js | ||||
| chunk {b_js} b_js.bundle.js 22 bytes <{main}> [rendered] | ||||
|     > ./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`] = ` | ||||
| "Hash: 53f13412753ee8bb3d387595bab0743d3d05a312 | ||||
| "Hash: ada681c866c95e0132eff2c9453ed201db5580c2 | ||||
| Child | ||||
|     Hash: 53f13412753ee8bb3d38 | ||||
|     Hash: ada681c866c95e0132ef | ||||
|     Time: Xms | ||||
|     Built at: Thu Jan 01 1970 00:00:00 GMT | ||||
|                              Asset       Size  Chunks             Chunk Names | ||||
|        app.269cd87fa0cbcfa98d1b.js   6.65 KiB   {143}  [emitted]  app | ||||
|     vendor.37b166c3b85bfb1caf5f.js  616 bytes   {736}  [emitted]  vendor | ||||
|     Entrypoint app = vendor.37b166c3b85bfb1caf5f.js app.269cd87fa0cbcfa98d1b.js | ||||
|        app.72745ea3abc585e103e5.js   6.69 KiB   {143}  [emitted]  app | ||||
|     vendor.22698e25646290b0dcc1.js  616 bytes   {736}  [emitted]  vendor | ||||
|     Entrypoint app = vendor.22698e25646290b0dcc1.js app.72745ea3abc585e103e5.js | ||||
|     [117] ./entry-1.js + 2 modules 190 bytes {143} [built] | ||||
|     [381] ./constants.js 87 bytes {736} [built] | ||||
|         + 4 hidden modules | ||||
| Child | ||||
|     Hash: 7595bab0743d3d05a312 | ||||
|     Hash: f2c9453ed201db5580c2 | ||||
|     Time: Xms | ||||
|     Built at: Thu Jan 01 1970 00:00:00 GMT | ||||
|                              Asset       Size  Chunks             Chunk Names | ||||
|        app.3ec38d64835ee4418bb3.js   6.67 KiB   {143}  [emitted]  app | ||||
|     vendor.37b166c3b85bfb1caf5f.js  616 bytes   {736}  [emitted]  vendor | ||||
|     Entrypoint app = vendor.37b166c3b85bfb1caf5f.js app.3ec38d64835ee4418bb3.js | ||||
|        app.eee68844dbd56e9ed525.js    6.7 KiB   {143}  [emitted]  app | ||||
|     vendor.22698e25646290b0dcc1.js  616 bytes   {736}  [emitted]  vendor | ||||
|     Entrypoint app = vendor.22698e25646290b0dcc1.js app.eee68844dbd56e9ed525.js | ||||
|     [381] ./constants.js 87 bytes {736} [built] | ||||
|     [655] ./entry-2.js + 2 modules 197 bytes {143} [built] | ||||
|         + 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`] = ` | ||||
| "Hash: 49f607faddf9699cbef8 | ||||
| "Hash: 99ab54650501715e52b3 | ||||
| Time: Xms | ||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | ||||
|    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`] = ` | ||||
| "Hash: 9e3985f832f4d566fdbb | ||||
| "Hash: 9757fb3da1f7b8f77bbb | ||||
| Time: Xms | ||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | ||||
|   Asset      Size  Chunks             Chunk Names | ||||
|  | @ -1476,7 +1476,7 @@ Entrypoint main = main.js | |||
|  [10] ./index.js 19 bytes {179} [built] | ||||
| [195] ./not-existing.js 26 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 | ||||
| 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] | ||||
| [195] ./not-existing.js 26 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 | ||||
| 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 | ||||
| Entrypoint main = main.js | ||||
| [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 | ||||
| 
 | ||||
| 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`] = ` | ||||
| "Hash: ac1889126d1918a36204 | ||||
| "Hash: b4a9cfa089ce3732efc5 | ||||
| Time: Xms | ||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | ||||
| Entrypoint index = index.js | ||||
|  | @ -2318,9 +2318,9 @@ Entrypoint entry = entry.js | |||
| `; | ||||
| 
 | ||||
| exports[`StatsTestCases should print correct stats for scope-hoisting-multi 1`] = ` | ||||
| "Hash: 0b46c17cd9c6ad0fbfb2a8733d1161800e5d8cb5 | ||||
| "Hash: d4c3cd048bdc678bb92437745aea03a16f764c79 | ||||
| Child | ||||
|     Hash: 0b46c17cd9c6ad0fbfb2 | ||||
|     Hash: d4c3cd048bdc678bb924 | ||||
|     Time: Xms | ||||
|     Built at: Thu Jan 01 1970 00:00:00 GMT | ||||
|     Entrypoint first = vendor.js first.js | ||||
|  | @ -2338,7 +2338,7 @@ Child | |||
|     [965] ./vendor.js 25 bytes {736} [built] | ||||
|         + 10 hidden modules | ||||
| Child | ||||
|     Hash: a8733d1161800e5d8cb5 | ||||
|     Hash: 37745aea03a16f764c79 | ||||
|     Time: Xms | ||||
|     Built at: Thu Jan 01 1970 00:00:00 GMT | ||||
|     Entrypoint first = vendor.js first.js | ||||
|  | @ -2365,11 +2365,11 @@ Child | |||
| `; | ||||
| 
 | ||||
| exports[`StatsTestCases should print correct stats for side-effects-issue-7428 1`] = ` | ||||
| "Hash: 8d106e0a6c9f100fb26f | ||||
| "Hash: 8871bd720c1e20111581 | ||||
| Time: Xms | ||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | ||||
|   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 | ||||
| Entrypoint main = main.js | ||||
| [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`] = ` | ||||
| "Hash: aabd6d1544eb169e22e5 | ||||
| "Hash: 589af6828de7c047d0c5 | ||||
| Time: Xms | ||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | ||||
|   Asset      Size  Chunks             Chunk Names | ||||
|  | @ -2450,7 +2450,7 @@ exports[`StatsTestCases should print correct stats for simple 1`] = ` | |||
| Time: Xms | ||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | ||||
|     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 | ||||
| [./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`] = ` | ||||
| "Hash: a74d3a7695fab0e2d9aa | ||||
| "Hash: 9f0d95b08ca5afeee1fe | ||||
| Time: Xms | ||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | ||||
|     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`] = ` | ||||
| "Hash: e6c683371cb4c4354398 | ||||
| "Hash: 48cd6bb29a775ac0f234 | ||||
| Time: Xms | ||||
| Built at: Thu Jan 01 1970 00:00:00 GMT | ||||
|                            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] | ||||
|                    325.bundle.js   3.93 KiB   {325}  [emitted] | ||||
|                    325.bundle.js    3.9 KiB   {325}  [emitted] | ||||
|                    526.bundle.js  329 bytes   {526}  [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] | ||||
| a160192b41d0463ac226.module.wasm  131 bytes   {230}  [emitted] | ||||
|                        bundle.js   13.5 KiB   {520}  [emitted]  main-1df31ce3 | ||||
| cfd5ebf998e67f7103a2.module.wasm  510 bytes    {99}  [emitted] | ||||
| e94fc8ba836bfd2c6038.module.wasm  131 bytes   {230}  [emitted] | ||||
| f8f99fabd0c63ad1c730.module.wasm  225 bytes   {780}  [emitted] | ||||
| fea68b3453f2f8fdfeed.module.wasm  132 bytes   {780}  [emitted] | ||||
| d95036d90a8b92bc2692.module.wasm  510 bytes    {99}  [emitted] | ||||
| ff9c5233b4dbdf834f6f.module.wasm  125 bytes   {325}  [emitted] | ||||
| 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] | ||||
| 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] | ||||
| 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] | ||||
|  [325] ./tests.js 1.4 KiB {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 | ||||
| chunk {526} 526.bundle.js 34 bytes [rendered] split chunk (cache group: defaultVendors) | ||||
|  [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] | ||||
|  [151] ./fast-math.wasm 105 bytes (javascript) 290 bytes (webassembly) {780} [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.identifier().endsWith("reference.js") && | ||||
| 						Array.isArray(ref.importedNames) && | ||||
| 						ref.importedNames.includes("unused") | ||||
| 						ref.importedNames.some( | ||||
| 							names => names.length === 1 && names[0] === "unused" | ||||
| 						) | ||||
| 					) { | ||||
| 						const newExports = ref.importedNames.filter( | ||||
| 							item => item !== "unused" | ||||
| 							names => names.length !== 1 || names[0] !== "unused" | ||||
| 						); | ||||
| 						return new DependencyReference( | ||||
| 							() => ref.module, | ||||
|  |  | |||
|  | @ -15,10 +15,12 @@ module.exports = { | |||
| 						ref.module && | ||||
| 						ref.module.identifier().endsWith("reference.js") && | ||||
| 						Array.isArray(ref.importedNames) && | ||||
| 						ref.importedNames.includes("unused") | ||||
| 						ref.importedNames.some( | ||||
| 							names => names.length === 1 && names[0] === "unused" | ||||
| 						) | ||||
| 					) { | ||||
| 						const newExports = ref.importedNames.filter( | ||||
| 							item => item !== "unused" | ||||
| 							names => names.length !== 1 || names[0] !== "unused" | ||||
| 						); | ||||
| 						return new DependencyReference( | ||||
| 							() => ref.module, | ||||
|  |  | |||
|  | @ -1,14 +1,63 @@ | |||
| function returnThis() { | ||||
| 	if(typeof this === "undefined") return "undefined"; | ||||
| 	if (typeof this === "undefined") return "undefined"; | ||||
| 	return this; | ||||
| } | ||||
| 
 | ||||
| var a = returnThis; | ||||
| var b = returnThis; | ||||
| 
 | ||||
| export { | ||||
| 	a, | ||||
| 	b | ||||
| export { 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; | ||||
|  |  | |||
|  | @ -1,11 +1,45 @@ | |||
| "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"; | ||||
| 
 | ||||
| function x() { throw new Error("should not be executed"); } | ||||
| it("should have this = undefined on imported non-strict functions", function() { | ||||
| it("should have this = undefined on harmony modules", () => { | ||||
| 	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 | ||||
| 	expect(d()).toBe("undefined"); | ||||
| 	x | ||||
|  | @ -13,17 +47,17 @@ it("should have this = undefined on imported non-strict functions", function() { | |||
| 	x | ||||
| 	expect(B()).toBe("undefined"); | ||||
| 	x | ||||
| 	expect(abc.a()).toMatchObject({}); | ||||
| 	expect(abc.a()).toBeTypeOf("object"); | ||||
| 	x | ||||
| 	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 * as New from "./new"; | ||||
| 
 | ||||
| it("should be possible to use new correctly", function() { | ||||
| it("should be possible to use new correctly", () => { | ||||
| 	x | ||||
| 	expect(new C()).toEqual({ok: true}); | ||||
| 	x | ||||
|  | @ -31,3 +65,9 @@ it("should be possible to use new correctly", function() { | |||
| 	x | ||||
| 	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: { | ||||
| 		strictThisContextOnImports: true | ||||
| 	}, | ||||
| 	plugins: [new webpack.optimize.ModuleConcatenationPlugin()] | ||||
| 	} | ||||
| }; | ||||
|  |  | |||
|  | @ -1,5 +1,8 @@ | |||
| module.exports = { | ||||
| 	module: { | ||||
| 		strictThisContextOnImports: true | ||||
| 	}, | ||||
| 	optimization: { | ||||
| 		concatenateModules: false | ||||
| 	} | ||||
| }; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue