123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- /*
- 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 */
- /**
- * @param {Iterable<string>} iterable iterable strings
- * @returns {string} result
- */
- 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();
- /**
- * @extends {InitFragment<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
- );
- }
- /**
- * @param {HarmonyExportInitFragment} other other
- * @returns {HarmonyExportInitFragment} merged result
- */
- 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 {GenerateContext} context context
- * @returns {string | Source | undefined} 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;
|