You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			170 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
			
		
		
	
	
			170 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			JavaScript
		
	
| /*
 | |
| 	MIT License http://www.opensource.org/licenses/mit-license.php
 | |
| 	Author Tobias Koppers @sokra
 | |
| */
 | |
| 
 | |
| "use strict";
 | |
| 
 | |
| const InitFragment = require("../InitFragment");
 | |
| const RuntimeGlobals = require("../RuntimeGlobals");
 | |
| const { first } = require("../util/SetHelpers");
 | |
| const { propertyName } = require("../util/propertyName");
 | |
| 
 | |
| /** @typedef {import("webpack-sources").Source} Source */
 | |
| /** @typedef {import("../Generator").GenerateContext} GenerateContext */
 | |
| 
 | |
| 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();
 | |
| 
 | |
| /**
 | |
|  * @typedef {GenerateContext} Context
 | |
|  */
 | |
| class HarmonyExportInitFragment extends InitFragment {
 | |
| 	/**
 | |
| 	 * @param {string} exportsArgument the exports identifier
 | |
| 	 * @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;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @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
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 	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
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @param {Context} context context
 | |
| 	 * @returns {string|Source} the source code that will be included as initialization code
 | |
| 	 */
 | |
| 	getContent({ runtimeTemplate, runtimeRequirements }) {
 | |
| 		runtimeRequirements.add(RuntimeGlobals.exports);
 | |
| 		runtimeRequirements.add(RuntimeGlobals.definePropertyGetters);
 | |
| 
 | |
| 		const unusedPart =
 | |
| 			this.unusedExports.size > 1
 | |
| 				? `/* unused harmony exports ${joinIterableWithComma(
 | |
| 						this.unusedExports
 | |
| 				  )} */\n`
 | |
| 				: this.unusedExports.size > 0
 | |
| 				? `/* unused harmony export ${first(this.unusedExports)} */\n`
 | |
| 				: "";
 | |
| 		const definitions = [];
 | |
| 		const orderedExportMap = Array.from(this.exportMap).sort(([a], [b]) =>
 | |
| 			a < b ? -1 : 1
 | |
| 		);
 | |
| 		for (const [key, value] of orderedExportMap) {
 | |
| 			definitions.push(
 | |
| 				`\n/* harmony export */   ${propertyName(
 | |
| 					key
 | |
| 				)}: ${runtimeTemplate.returningFunction(value)}`
 | |
| 			);
 | |
| 		}
 | |
| 		const definePart =
 | |
| 			this.exportMap.size > 0
 | |
| 				? `/* harmony export */ ${RuntimeGlobals.definePropertyGetters}(${
 | |
| 						this.exportsArgument
 | |
| 				  }, {${definitions.join(",")}\n/* harmony export */ });\n`
 | |
| 				: "";
 | |
| 		return `${definePart}${unusedPart}`;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| module.exports = HarmonyExportInitFragment;
 |