| 
									
										
										
										
											2019-08-23 20:07:01 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | "use strict"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const InitFragment = require("../InitFragment"); | 
					
						
							|  |  |  | const RuntimeGlobals = require("../RuntimeGlobals"); | 
					
						
							| 
									
										
										
										
											2021-02-04 21:21:27 +08:00
										 |  |  | const { first } = require("../util/SetHelpers"); | 
					
						
							| 
									
										
										
										
											2023-05-05 11:41:15 +08:00
										 |  |  | const { propertyName } = require("../util/propertyName"); | 
					
						
							| 
									
										
										
										
											2019-08-23 20:07:01 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** @typedef {import("webpack-sources").Source} Source */ | 
					
						
							| 
									
										
										
										
											2019-08-27 02:21:07 +08:00
										 |  |  | /** @typedef {import("../Generator").GenerateContext} GenerateContext */ | 
					
						
							| 
									
										
										
										
											2019-08-23 20:07:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-18 23:28:40 +08:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param {Iterable<string>} iterable iterable strings | 
					
						
							|  |  |  |  * @returns {string} result | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-08-23 20:07:01 +08:00
										 |  |  | const joinIterableWithComma = iterable => { | 
					
						
							|  |  |  | 	// This is more performant than Array.from().join(", ")
 | 
					
						
							|  |  |  | 	// as it doesn't create an array
 | 
					
						
							|  |  |  | 	let str = ""; | 
					
						
							|  |  |  | 	let first = true; | 
					
						
							|  |  |  | 	for (const item of iterable) { | 
					
						
							|  |  |  | 		if (first) { | 
					
						
							|  |  |  | 			first = false; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			str += ", "; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		str += item; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return str; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const EMPTY_MAP = new Map(); | 
					
						
							|  |  |  | const EMPTY_SET = new Set(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 22:44:14 +08:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2024-03-18 23:28:40 +08:00
										 |  |  |  * @extends {InitFragment<GenerateContext>} Context | 
					
						
							| 
									
										
										
										
											2021-06-24 22:44:14 +08:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2019-08-23 20:07:01 +08:00
										 |  |  | class HarmonyExportInitFragment extends InitFragment { | 
					
						
							|  |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2020-02-21 18:15:43 +08:00
										 |  |  | 	 * @param {string} exportsArgument the exports identifier | 
					
						
							| 
									
										
										
										
											2019-08-23 20:07:01 +08:00
										 |  |  | 	 * @param {Map<string, string>} exportMap mapping from used name to exposed variable name | 
					
						
							|  |  |  | 	 * @param {Set<string>} unusedExports list of unused export names | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	constructor( | 
					
						
							|  |  |  | 		exportsArgument, | 
					
						
							|  |  |  | 		exportMap = EMPTY_MAP, | 
					
						
							|  |  |  | 		unusedExports = EMPTY_SET | 
					
						
							|  |  |  | 	) { | 
					
						
							|  |  |  | 		super(undefined, InitFragment.STAGE_HARMONY_EXPORTS, 1, "harmony-exports"); | 
					
						
							|  |  |  | 		this.exportsArgument = exportsArgument; | 
					
						
							|  |  |  | 		this.exportMap = exportMap; | 
					
						
							|  |  |  | 		this.unusedExports = unusedExports; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-27 20:01:22 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {HarmonyExportInitFragment[]} fragments all fragments to merge | 
					
						
							|  |  |  | 	 * @returns {HarmonyExportInitFragment} merged fragment | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	mergeAll(fragments) { | 
					
						
							|  |  |  | 		let exportMap; | 
					
						
							|  |  |  | 		let exportMapOwned = false; | 
					
						
							|  |  |  | 		let unusedExports; | 
					
						
							|  |  |  | 		let unusedExportsOwned = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (const fragment of fragments) { | 
					
						
							|  |  |  | 			if (fragment.exportMap.size !== 0) { | 
					
						
							|  |  |  | 				if (exportMap === undefined) { | 
					
						
							|  |  |  | 					exportMap = fragment.exportMap; | 
					
						
							|  |  |  | 					exportMapOwned = false; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					if (!exportMapOwned) { | 
					
						
							|  |  |  | 						exportMap = new Map(exportMap); | 
					
						
							|  |  |  | 						exportMapOwned = true; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					for (const [key, value] of fragment.exportMap) { | 
					
						
							|  |  |  | 						if (!exportMap.has(key)) exportMap.set(key, value); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if (fragment.unusedExports.size !== 0) { | 
					
						
							|  |  |  | 				if (unusedExports === undefined) { | 
					
						
							|  |  |  | 					unusedExports = fragment.unusedExports; | 
					
						
							|  |  |  | 					unusedExportsOwned = false; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					if (!unusedExportsOwned) { | 
					
						
							|  |  |  | 						unusedExports = new Set(unusedExports); | 
					
						
							|  |  |  | 						unusedExportsOwned = true; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					for (const value of fragment.unusedExports) { | 
					
						
							|  |  |  | 						unusedExports.add(value); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return new HarmonyExportInitFragment( | 
					
						
							|  |  |  | 			this.exportsArgument, | 
					
						
							|  |  |  | 			exportMap, | 
					
						
							|  |  |  | 			unusedExports | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-18 23:28:40 +08:00
										 |  |  | 	/** | 
					
						
							|  |  |  | 	 * @param {HarmonyExportInitFragment} other other | 
					
						
							|  |  |  | 	 * @returns {HarmonyExportInitFragment} merged result | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2019-08-23 20:07:01 +08:00
										 |  |  | 	merge(other) { | 
					
						
							|  |  |  | 		let exportMap; | 
					
						
							|  |  |  | 		if (this.exportMap.size === 0) { | 
					
						
							|  |  |  | 			exportMap = other.exportMap; | 
					
						
							|  |  |  | 		} else if (other.exportMap.size === 0) { | 
					
						
							|  |  |  | 			exportMap = this.exportMap; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			exportMap = new Map(other.exportMap); | 
					
						
							|  |  |  | 			for (const [key, value] of this.exportMap) { | 
					
						
							|  |  |  | 				if (!exportMap.has(key)) exportMap.set(key, value); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		let unusedExports; | 
					
						
							|  |  |  | 		if (this.unusedExports.size === 0) { | 
					
						
							|  |  |  | 			unusedExports = other.unusedExports; | 
					
						
							|  |  |  | 		} else if (other.unusedExports.size === 0) { | 
					
						
							|  |  |  | 			unusedExports = this.unusedExports; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			unusedExports = new Set(other.unusedExports); | 
					
						
							|  |  |  | 			for (const value of this.unusedExports) { | 
					
						
							|  |  |  | 				unusedExports.add(value); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return new HarmonyExportInitFragment( | 
					
						
							|  |  |  | 			this.exportsArgument, | 
					
						
							|  |  |  | 			exportMap, | 
					
						
							|  |  |  | 			unusedExports | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2024-01-27 00:17:45 +08:00
										 |  |  | 	 * @param {GenerateContext} context context | 
					
						
							| 
									
										
										
										
											2024-03-18 23:28:40 +08:00
										 |  |  | 	 * @returns {string | Source | undefined} the source code that will be included as initialization code | 
					
						
							| 
									
										
										
										
											2019-08-23 20:07:01 +08:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2019-08-27 02:21:07 +08:00
										 |  |  | 	getContent({ runtimeTemplate, runtimeRequirements }) { | 
					
						
							|  |  |  | 		runtimeRequirements.add(RuntimeGlobals.exports); | 
					
						
							|  |  |  | 		runtimeRequirements.add(RuntimeGlobals.definePropertyGetters); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 20:07:01 +08:00
										 |  |  | 		const unusedPart = | 
					
						
							|  |  |  | 			this.unusedExports.size > 1 | 
					
						
							|  |  |  | 				? `/* unused harmony exports ${joinIterableWithComma( | 
					
						
							|  |  |  | 						this.unusedExports | 
					
						
							| 
									
										
										
										
											2024-01-14 09:41:34 +08:00
										 |  |  | 					)} */\n` | 
					
						
							| 
									
										
										
										
											2019-08-23 20:07:01 +08:00
										 |  |  | 				: this.unusedExports.size > 0 | 
					
						
							| 
									
										
										
										
											2024-01-14 09:41:34 +08:00
										 |  |  | 					? `/* unused harmony export ${first(this.unusedExports)} */\n` | 
					
						
							|  |  |  | 					: ""; | 
					
						
							| 
									
										
										
										
											2019-08-23 20:07:01 +08:00
										 |  |  | 		const definitions = []; | 
					
						
							| 
									
										
										
										
											2022-02-23 23:48:17 +08:00
										 |  |  | 		const orderedExportMap = Array.from(this.exportMap).sort(([a], [b]) => | 
					
						
							|  |  |  | 			a < b ? -1 : 1 | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 		for (const [key, value] of orderedExportMap) { | 
					
						
							| 
									
										
										
										
											2019-08-23 20:07:01 +08:00
										 |  |  | 			definitions.push( | 
					
						
							| 
									
										
										
										
											2023-05-05 11:41:15 +08:00
										 |  |  | 				`\n/* harmony export */   ${propertyName( | 
					
						
							| 
									
										
										
										
											2019-08-23 20:07:01 +08:00
										 |  |  | 					key | 
					
						
							| 
									
										
										
										
											2019-08-27 02:21:07 +08:00
										 |  |  | 				)}: ${runtimeTemplate.returningFunction(value)}`
 | 
					
						
							| 
									
										
										
										
											2019-08-23 20:07:01 +08:00
										 |  |  | 			); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		const definePart = | 
					
						
							|  |  |  | 			this.exportMap.size > 0 | 
					
						
							|  |  |  | 				? `/* harmony export */ ${RuntimeGlobals.definePropertyGetters}(${ | 
					
						
							|  |  |  | 						this.exportsArgument | 
					
						
							| 
									
										
										
										
											2024-01-14 09:41:34 +08:00
										 |  |  | 					}, {${definitions.join(",")}\n/* harmony export */ });\n`
 | 
					
						
							| 
									
										
										
										
											2019-08-23 20:07:01 +08:00
										 |  |  | 				: ""; | 
					
						
							|  |  |  | 		return `${definePart}${unusedPart}`; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = HarmonyExportInitFragment; |