code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
const ConstDependency = require("../dependencies/ConstDependency");
const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");

/** @typedef {import("estree").Expression} Expression */
/** @typedef {import("estree").Node} Node */
/** @typedef {import("estree").SourceLocation} SourceLocation */
/** @typedef {import("./JavascriptParser")} JavascriptParser */
/** @typedef {import("./JavascriptParser").Range} Range */

/**
 * @param {JavascriptParser} parser the parser
 * @param {string} value the const value
 * @param {(string[] | null)=} runtimeRequirements runtime requirements
 * @returns {function(Expression): true} plugin function
 */
exports.toConstantDependency = (parser, value, runtimeRequirements) => {
	return function constDependency(expr) {
		const dep = new ConstDependency(
			value,
			/** @type {Range} */ (expr.range),
			runtimeRequirements
		);
		dep.loc = /** @type {SourceLocation} */ (expr.loc);
		parser.state.module.addPresentationalDependency(dep);
		return true;
	};
};

/**
 * @param {string} value the string value
 * @returns {function(Expression): BasicEvaluatedExpression} plugin function
 */
exports.evaluateToString = value => {
	return function stringExpression(expr) {
		return new BasicEvaluatedExpression()
			.setString(value)
			.setRange(/** @type {Range} */ (expr.range));
	};
};

/**
 * @param {number} value the number value
 * @returns {function(Expression): BasicEvaluatedExpression} plugin function
 */
exports.evaluateToNumber = value => {
	return function stringExpression(expr) {
		return new BasicEvaluatedExpression()
			.setNumber(value)
			.setRange(/** @type {Range} */ (expr.range));
	};
};

/**
 * @param {boolean} value the boolean value
 * @returns {function(Expression): BasicEvaluatedExpression} plugin function
 */
exports.evaluateToBoolean = value => {
	return function booleanExpression(expr) {
		return new BasicEvaluatedExpression()
			.setBoolean(value)
			.setRange(/** @type {Range} */ (expr.range));
	};
};

/**
 * @param {string} identifier identifier
 * @param {string} rootInfo rootInfo
 * @param {function(): string[]} getMembers getMembers
 * @param {boolean|null=} truthy is truthy, null if nullish
 * @returns {function(Expression): BasicEvaluatedExpression} callback
 */
exports.evaluateToIdentifier = (identifier, rootInfo, getMembers, truthy) => {
	return function identifierExpression(expr) {
		let evaluatedExpression = new BasicEvaluatedExpression()
			.setIdentifier(identifier, rootInfo, getMembers)
			.setSideEffects(false)
			.setRange(/** @type {Range} */ (expr.range));
		switch (truthy) {
			case true:
				evaluatedExpression.setTruthy();
				break;
			case null:
				evaluatedExpression.setNullish(true);
				break;
			case false:
				evaluatedExpression.setFalsy();
				break;
		}

		return evaluatedExpression;
	};
};

/**
 * @param {JavascriptParser} parser the parser
 * @param {string} message the message
 * @returns {function(Expression): boolean | undefined} callback to handle unsupported expression
 */
exports.expressionIsUnsupported = (parser, message) => {
	return function unsupportedExpression(expr) {
		const dep = new ConstDependency(
			"(void 0)",
			/** @type {Range} */ (expr.range),
			null
		);
		dep.loc = /** @type {SourceLocation} */ (expr.loc);
		parser.state.module.addPresentationalDependency(dep);
		if (!parser.state.module) return;
		parser.state.module.addWarning(
			new UnsupportedFeatureWarning(
				message,
				/** @type {SourceLocation} */ (expr.loc)
			)
		);
		return true;
	};
};

exports.skipTraversal = () => true;

exports.approve = () => true;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
const { isSubset } = require("../util/SetHelpers");
const { getAllChunks } = require("./ChunkHelpers");

/** @typedef {import("../util/Hash")} Hash */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Chunk").ChunkId} ChunkId */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../Entrypoint")} Entrypoint */
/** @typedef {import("../ChunkGraph").EntryModuleWithChunkGroup} EntryModuleWithChunkGroup */
/** @typedef {import("../ChunkGroup")} ChunkGroup */
/** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
/** @typedef {(string|number)[]} EntryItem */

const EXPORT_PREFIX = `var ${RuntimeGlobals.exports} = `;

/**
 * @param {ChunkGraph} chunkGraph chunkGraph
 * @param {RuntimeTemplate} runtimeTemplate runtimeTemplate
 * @param {EntryModuleWithChunkGroup[]} entries entries
 * @param {Chunk} chunk chunk
 * @param {boolean} passive true: passive startup with on chunks loaded
 * @returns {string} runtime code
 */
exports.generateEntryStartup = (
	chunkGraph,
	runtimeTemplate,
	entries,
	chunk,
	passive
) => {
	/** @type {string[]} */
	const runtime = [
		`var __webpack_exec__ = ${runtimeTemplate.returningFunction(
			`${RuntimeGlobals.require}(${RuntimeGlobals.entryModuleId} = moduleId)`,
			"moduleId"
		)}`
	];

	const runModule = id => {
		return `__webpack_exec__(${JSON.stringify(id)})`;
	};
	const outputCombination = (chunks, moduleIds, final) => {
		if (chunks.size === 0) {
			runtime.push(
				`${final ? EXPORT_PREFIX : ""}(${moduleIds.map(runModule).join(", ")});`
			);
		} else {
			const fn = runtimeTemplate.returningFunction(
				moduleIds.map(runModule).join(", ")
			);
			runtime.push(
				`${final && !passive ? EXPORT_PREFIX : ""}${
					passive
						? RuntimeGlobals.onChunksLoaded
						: RuntimeGlobals.startupEntrypoint
				}(0, ${JSON.stringify(Array.from(chunks, c => c.id))}, ${fn});`
			);
			if (final && passive) {
				runtime.push(`${EXPORT_PREFIX}${RuntimeGlobals.onChunksLoaded}();`);
			}
		}
	};

	let currentChunks = undefined;
	let currentModuleIds = undefined;

	for (const [module, entrypoint] of entries) {
		const runtimeChunk =
			/** @type {Entrypoint} */
			(entrypoint).getRuntimeChunk();
		const moduleId = chunkGraph.getModuleId(module);
		const chunks = getAllChunks(
			/** @type {Entrypoint} */ (entrypoint),
			chunk,
			runtimeChunk
		);
		if (
			currentChunks &&
			currentChunks.size === chunks.size &&
			isSubset(currentChunks, chunks)
		) {
			currentModuleIds.push(moduleId);
		} else {
			if (currentChunks) {
				outputCombination(currentChunks, currentModuleIds);
			}
			currentChunks = chunks;
			currentModuleIds = [moduleId];
		}
	}

	// output current modules with export prefix
	if (currentChunks) {
		outputCombination(currentChunks, currentModuleIds, true);
	}
	runtime.push("");
	return Template.asString(runtime);
};

/**
 * @param {Hash} hash the hash to update
 * @param {ChunkGraph} chunkGraph chunkGraph
 * @param {EntryModuleWithChunkGroup[]} entries entries
 * @param {Chunk} chunk chunk
 * @returns {void}
 */
exports.updateHashForEntryStartup = (hash, chunkGraph, entries, chunk) => {
	for (const [module, entrypoint] of entries) {
		const runtimeChunk =
			/** @type {Entrypoint} */
			(entrypoint).getRuntimeChunk();
		const moduleId = chunkGraph.getModuleId(module);
		hash.update(`${moduleId}`);
		for (const c of getAllChunks(
			/** @type {Entrypoint} */ (entrypoint),
			chunk,
			/** @type {Chunk} */ (runtimeChunk)
		)) {
			hash.update(`${c.id}`);
		}
	}
};

/**
 * @param {Chunk} chunk the chunk
 * @param {ChunkGraph} chunkGraph the chunk graph
 * @param {function(Chunk, ChunkGraph): boolean} filterFn filter function
 * @returns {Set<number | string>} initially fulfilled chunk ids
 */
exports.getInitialChunkIds = (chunk, chunkGraph, filterFn) => {
	const initialChunkIds = new Set(chunk.ids);
	for (const c of chunk.getAllInitialChunks()) {
		if (c === chunk || filterFn(c, chunkGraph)) continue;
		for (const id of /** @type {ChunkId[]} */ (c.ids)) {
			initialChunkIds.add(id);
		}
	}
	return initialChunkIds;
};

license: mit


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { register } = require("../util/serialization");

/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
/** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
/** @typedef {import("../util/Hash")} Hash */
/** @typedef {import("./JsonModulesPlugin").RawJsonData} RawJsonData */

class JsonData {
	/**
	 * @param {Buffer | RawJsonData} data JSON data
	 */
	constructor(data) {
		/** @type {Buffer | undefined} */
		this._buffer = undefined;
		/** @type {RawJsonData | undefined} */
		this._data = undefined;
		if (Buffer.isBuffer(data)) {
			this._buffer = data;
		} else {
			this._data = data;
		}
	}

	/**
	 * @returns {RawJsonData|undefined} Raw JSON data
	 */
	get() {
		if (this._data === undefined && this._buffer !== undefined) {
			this._data = JSON.parse(this._buffer.toString());
		}
		return this._data;
	}

	/**
	 * @param {Hash} hash hash to be updated
	 * @returns {void} the updated hash
	 */
	updateHash(hash) {
		if (this._buffer === undefined && this._data !== undefined) {
			this._buffer = Buffer.from(JSON.stringify(this._data));
		}

		if (this._buffer) hash.update(this._buffer);
	}
}

register(JsonData, "webpack/lib/json/JsonData", null, {
	/**
	 * @param {JsonData} obj JSONData object
	 * @param {ObjectSerializerContext} context context
	 */
	serialize(obj, { write }) {
		if (obj._buffer === undefined && obj._data !== undefined) {
			obj._buffer = Buffer.from(JSON.stringify(obj._data));
		}
		write(obj._buffer);
	},
	/**
	 * @param {ObjectDeserializerContext} context context
	 * @returns {JsonData} deserialized JSON data
	 */
	deserialize({ read }) {
		return new JsonData(read());
	}
});

module.exports = JsonData;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { RawSource } = require("webpack-sources");
const ConcatenationScope = require("../ConcatenationScope");
const { UsageState } = require("../ExportsInfo");
const Generator = require("../Generator");
const RuntimeGlobals = require("../RuntimeGlobals");

/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../ExportsInfo")} ExportsInfo */
/** @typedef {import("../Generator").GenerateContext} GenerateContext */
/** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */
/** @typedef {import("../NormalModule")} NormalModule */
/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
/** @typedef {import("./JsonData")} JsonData */
/** @typedef {import("./JsonModulesPlugin").RawJsonData} RawJsonData */

/**
 * @param {RawJsonData} data Raw JSON data
 * @returns {undefined|string} stringified data
 */
const stringifySafe = data => {
	const stringified = JSON.stringify(data);
	if (!stringified) {
		return undefined; // Invalid JSON
	}

	return stringified.replace(/\u2028|\u2029/g, str =>
		str === "\u2029" ? "\\u2029" : "\\u2028"
	); // invalid in JavaScript but valid JSON
};

/**
 * @param {RawJsonData} data Raw JSON data (always an object or array)
 * @param {ExportsInfo} exportsInfo exports info
 * @param {RuntimeSpec} runtime the runtime
 * @returns {RawJsonData} reduced data
 */
const createObjectForExportsInfo = (data, exportsInfo, runtime) => {
	if (exportsInfo.otherExportsInfo.getUsed(runtime) !== UsageState.Unused)
		return data;
	const isArray = Array.isArray(data);
	/** @type {RawJsonData} */
	const reducedData = isArray ? [] : {};
	for (const key of Object.keys(data)) {
		const exportInfo = exportsInfo.getReadOnlyExportInfo(key);
		const used = exportInfo.getUsed(runtime);
		if (used === UsageState.Unused) continue;

		/** @type {RawJsonData} */
		let value;
		if (used === UsageState.OnlyPropertiesUsed && exportInfo.exportsInfo) {
			value = createObjectForExportsInfo(
				data[key],
				exportInfo.exportsInfo,
				runtime
			);
		} else {
			value = data[key];
		}

		const name = /** @type {string} */ (exportInfo.getUsedName(key, runtime));
		/** @type {Record<string, RawJsonData>} */ (reducedData)[name] = value;
	}
	if (isArray) {
		let arrayLengthWhenUsed =
			exportsInfo.getReadOnlyExportInfo("length").getUsed(runtime) !==
			UsageState.Unused
				? data.length
				: undefined;

		let sizeObjectMinusArray = 0;
		for (let i = 0; i < reducedData.length; i++) {
			if (reducedData[i] === undefined) {
				sizeObjectMinusArray -= 2;
			} else {
				sizeObjectMinusArray += `${i}`.length + 3;
			}
		}
		if (arrayLengthWhenUsed !== undefined) {
			sizeObjectMinusArray +=
				`${arrayLengthWhenUsed}`.length +
				8 -
				(arrayLengthWhenUsed - reducedData.length) * 2;
		}
		if (sizeObjectMinusArray < 0)
			return Object.assign(
				arrayLengthWhenUsed === undefined
					? {}
					: { length: arrayLengthWhenUsed },
				reducedData
			);
		/** @type {number} */
		const generatedLength =
			arrayLengthWhenUsed !== undefined
				? Math.max(arrayLengthWhenUsed, reducedData.length)
				: reducedData.length;
		for (let i = 0; i < generatedLength; i++) {
			if (reducedData[i] === undefined) {
				reducedData[i] = 0;
			}
		}
	}
	return reducedData;
};

const TYPES = new Set(["javascript"]);

class JsonGenerator extends Generator {
	/**
	 * @param {NormalModule} module fresh module
	 * @returns {Set<string>} available types (do not mutate)
	 */
	getTypes(module) {
		return TYPES;
	}

	/**
	 * @param {NormalModule} module the module
	 * @param {string=} type source type
	 * @returns {number} estimate size of the module
	 */
	getSize(module, type) {
		/** @type {RawJsonData | undefined} */
		const data =
			module.buildInfo &&
			module.buildInfo.jsonData &&
			module.buildInfo.jsonData.get();
		if (!data) return 0;
		return /** @type {string} */ (stringifySafe(data)).length + 10;
	}

	/**
	 * @param {NormalModule} module module for which the bailout reason should be determined
	 * @param {ConcatenationBailoutReasonContext} context context
	 * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated
	 */
	getConcatenationBailoutReason(module, context) {
		return undefined;
	}

	/**
	 * @param {NormalModule} module module for which the code should be generated
	 * @param {GenerateContext} generateContext context for generate
	 * @returns {Source} generated code
	 */
	generate(
		module,
		{
			moduleGraph,
			runtimeTemplate,
			runtimeRequirements,
			runtime,
			concatenationScope
		}
	) {
		/** @type {RawJsonData | undefined} */
		const data =
			module.buildInfo &&
			module.buildInfo.jsonData &&
			module.buildInfo.jsonData.get();
		if (data === undefined) {
			return new RawSource(
				runtimeTemplate.missingModuleStatement({
					request: module.rawRequest
				})
			);
		}
		const exportsInfo = moduleGraph.getExportsInfo(module);
		/** @type {RawJsonData} */
		let finalJson =
			typeof data === "object" &&
			data &&
			exportsInfo.otherExportsInfo.getUsed(runtime) === UsageState.Unused
				? createObjectForExportsInfo(data, exportsInfo, runtime)
				: data;
		// Use JSON because JSON.parse() is much faster than JavaScript evaluation
		const jsonStr = /** @type {string} */ (stringifySafe(finalJson));
		const jsonExpr =
			jsonStr.length > 20 && typeof finalJson === "object"
				? `/*#__PURE__*/JSON.parse('${jsonStr.replace(/[\\']/g, "\\$&")}')`
				: jsonStr;
		/** @type {string} */
		let content;
		if (concatenationScope) {
			content = `${runtimeTemplate.supportsConst() ? "const" : "var"} ${
				ConcatenationScope.NAMESPACE_OBJECT_EXPORT
			} = ${jsonExpr};`;
			concatenationScope.registerNamespaceExport(
				ConcatenationScope.NAMESPACE_OBJECT_EXPORT
			);
		} else {
			runtimeRequirements.add(RuntimeGlobals.module);
			content = `${module.moduleArgument}.exports = ${jsonExpr};`;
		}
		return new RawSource(content);
	}
}

module.exports = JsonGenerator;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { JSON_MODULE_TYPE } = require("../ModuleTypeConstants");
const createSchemaValidation = require("../util/create-schema-validation");
const JsonGenerator = require("./JsonGenerator");
const JsonParser = require("./JsonParser");

/** @typedef {import("../Compiler")} Compiler */
/** @typedef {Record<string, any>} RawJsonData */

const validate = createSchemaValidation(
	require("../../schemas/plugins/JsonModulesPluginParser.check.js"),
	() => require("../../schemas/plugins/JsonModulesPluginParser.json"),
	{
		name: "Json Modules Plugin",
		baseDataPath: "parser"
	}
);

const PLUGIN_NAME = "JsonModulesPlugin";

/**
 * The JsonModulesPlugin is the entrypoint plugin for the json modules feature.
 * It adds the json module type to the compiler and registers the json parser and generator.
 */
class JsonModulesPlugin {
	/**
	 * Apply the plugin
	 * @param {Compiler} compiler the compiler instance
	 * @returns {void}
	 *
	 */
	apply(compiler) {
		compiler.hooks.compilation.tap(
			PLUGIN_NAME,
			(compilation, { normalModuleFactory }) => {
				normalModuleFactory.hooks.createParser
					.for(JSON_MODULE_TYPE)
					.tap(PLUGIN_NAME, parserOptions => {
						validate(parserOptions);

						return new JsonParser(parserOptions);
					});
				normalModuleFactory.hooks.createGenerator
					.for(JSON_MODULE_TYPE)
					.tap(PLUGIN_NAME, () => {
						return new JsonGenerator();
					});
			}
		);
	}
}

module.exports = JsonModulesPlugin;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const Parser = require("../Parser");
const JsonExportsDependency = require("../dependencies/JsonExportsDependency");
const memoize = require("../util/memoize");
const JsonData = require("./JsonData");

/** @typedef {import("../../declarations/plugins/JsonModulesPluginParser").JsonModulesPluginParserOptions} JsonModulesPluginParserOptions */
/** @typedef {import("../Module").BuildInfo} BuildInfo */
/** @typedef {import("../Module").BuildMeta} BuildMeta */
/** @typedef {import("../Parser").ParserState} ParserState */
/** @typedef {import("../Parser").PreparsedAst} PreparsedAst */
/** @typedef {import("./JsonModulesPlugin").RawJsonData} RawJsonData */

const getParseJson = memoize(() => require("json-parse-even-better-errors"));

class JsonParser extends Parser {
	/**
	 * @param {JsonModulesPluginParserOptions} options parser options
	 */
	constructor(options) {
		super();
		this.options = options || {};
	}

	/**
	 * @param {string | Buffer | PreparsedAst} source the source to parse
	 * @param {ParserState} state the parser state
	 * @returns {ParserState} the parser state
	 */
	parse(source, state) {
		if (Buffer.isBuffer(source)) {
			source = source.toString("utf-8");
		}

		/** @type {NonNullable<JsonModulesPluginParserOptions["parse"]>} */
		const parseFn =
			typeof this.options.parse === "function"
				? this.options.parse
				: getParseJson();
		/** @type {Buffer | RawJsonData | undefined} */
		let data;
		try {
			data =
				typeof source === "object"
					? source
					: parseFn(source[0] === "\ufeff" ? source.slice(1) : source);
		} catch (e) {
			throw new Error(`Cannot parse JSON: ${/** @type {Error} */ (e).message}`);
		}
		const jsonData = new JsonData(/** @type {Buffer | RawJsonData} */ (data));
		const buildInfo = /** @type {BuildInfo} */ (state.module.buildInfo);
		buildInfo.jsonData = jsonData;
		buildInfo.strict = true;
		const buildMeta = /** @type {BuildMeta} */ (state.module.buildMeta);
		buildMeta.exportsType = "default";
		buildMeta.defaultObject =
			typeof data === "object" ? "redirect-warn" : false;
		state.module.addDependency(new JsonExportsDependency(jsonData));
		return state;
	}
}

module.exports = JsonParser;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const RuntimeGlobals = require("../RuntimeGlobals");
const JavascriptModulesPlugin = require("../javascript/JavascriptModulesPlugin");

/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
/** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
/** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */
/** @typedef {import("../util/Hash")} Hash */

const COMMON_LIBRARY_NAME_MESSAGE =
	"Common configuration options that specific library names are 'output.library[.name]', 'entry.xyz.library[.name]', 'ModuleFederationPlugin.name' and 'ModuleFederationPlugin.library[.name]'.";

/**
 * @template T
 * @typedef {object} LibraryContext
 * @property {Compilation} compilation
 * @property {ChunkGraph} chunkGraph
 * @property {T} options
 */

/**
 * @template T
 */
class AbstractLibraryPlugin {
	/**
	 * @param {object} options options
	 * @param {string} options.pluginName name of the plugin
	 * @param {LibraryType} options.type used library type
	 */
	constructor({ pluginName, type }) {
		this._pluginName = pluginName;
		this._type = type;
		this._parseCache = new WeakMap();
	}

	/**
	 * Apply the plugin
	 * @param {Compiler} compiler the compiler instance
	 * @returns {void}
	 */
	apply(compiler) {
		const { _pluginName } = this;
		compiler.hooks.thisCompilation.tap(_pluginName, compilation => {
			compilation.hooks.finishModules.tap(
				{ name: _pluginName, stage: 10 },
				() => {
					for (const [
						name,
						{
							dependencies: deps,
							options: { library }
						}
					] of compilation.entries) {
						const options = this._parseOptionsCached(
							library !== undefined
								? library
								: compilation.outputOptions.library
						);
						if (options !== false) {
							const dep = deps[deps.length - 1];
							if (dep) {
								const module = compilation.moduleGraph.getModule(dep);
								if (module) {
									this.finishEntryModule(module, name, {
										options,
										compilation,
										chunkGraph: compilation.chunkGraph
									});
								}
							}
						}
					}
				}
			);

			/**
			 * @param {Chunk} chunk chunk
			 * @returns {TODO} options for the chunk
			 */
			const getOptionsForChunk = chunk => {
				if (compilation.chunkGraph.getNumberOfEntryModules(chunk) === 0)
					return false;
				const options = chunk.getEntryOptions();
				const library = options && options.library;
				return this._parseOptionsCached(
					library !== undefined ? library : compilation.outputOptions.library
				);
			};

			if (
				this.render !== AbstractLibraryPlugin.prototype.render ||
				this.runtimeRequirements !==
					AbstractLibraryPlugin.prototype.runtimeRequirements
			) {
				compilation.hooks.additionalChunkRuntimeRequirements.tap(
					_pluginName,
					(chunk, set, { chunkGraph }) => {
						const options = getOptionsForChunk(chunk);
						if (options !== false) {
							this.runtimeRequirements(chunk, set, {
								options,
								compilation,
								chunkGraph
							});
						}
					}
				);
			}

			const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation);

			if (this.render !== AbstractLibraryPlugin.prototype.render) {
				hooks.render.tap(_pluginName, (source, renderContext) => {
					const options = getOptionsForChunk(renderContext.chunk);
					if (options === false) return source;
					return this.render(source, renderContext, {
						options,
						compilation,
						chunkGraph: compilation.chunkGraph
					});
				});
			}

			if (
				this.embedInRuntimeBailout !==
				AbstractLibraryPlugin.prototype.embedInRuntimeBailout
			) {
				hooks.embedInRuntimeBailout.tap(
					_pluginName,
					(module, renderContext) => {
						const options = getOptionsForChunk(renderContext.chunk);
						if (options === false) return;
						return this.embedInRuntimeBailout(module, renderContext, {
							options,
							compilation,
							chunkGraph: compilation.chunkGraph
						});
					}
				);
			}

			if (
				this.strictRuntimeBailout !==
				AbstractLibraryPlugin.prototype.strictRuntimeBailout
			) {
				hooks.strictRuntimeBailout.tap(_pluginName, renderContext => {
					const options = getOptionsForChunk(renderContext.chunk);
					if (options === false) return;
					return this.strictRuntimeBailout(renderContext, {
						options,
						compilation,
						chunkGraph: compilation.chunkGraph
					});
				});
			}

			if (
				this.renderStartup !== AbstractLibraryPlugin.prototype.renderStartup
			) {
				hooks.renderStartup.tap(
					_pluginName,
					(source, module, renderContext) => {
						const options = getOptionsForChunk(renderContext.chunk);
						if (options === false) return source;
						return this.renderStartup(source, module, renderContext, {
							options,
							compilation,
							chunkGraph: compilation.chunkGraph
						});
					}
				);
			}

			hooks.chunkHash.tap(_pluginName, (chunk, hash, context) => {
				const options = getOptionsForChunk(chunk);
				if (options === false) return;
				this.chunkHash(chunk, hash, context, {
					options,
					compilation,
					chunkGraph: compilation.chunkGraph
				});
			});
		});
	}

	/**
	 * @param {LibraryOptions=} library normalized library option
	 * @returns {T | false} preprocess as needed by overriding
	 */
	_parseOptionsCached(library) {
		if (!library) return false;
		if (library.type !== this._type) return false;
		const cacheEntry = this._parseCache.get(library);
		if (cacheEntry !== undefined) return cacheEntry;
		const result = this.parseOptions(library);
		this._parseCache.set(library, result);
		return result;
	}

	/* istanbul ignore next */
	/**
	 * @abstract
	 * @param {LibraryOptions} library normalized library option
	 * @returns {T | false} preprocess as needed by overriding
	 */
	parseOptions(library) {
		const AbstractMethodError = require("../AbstractMethodError");
		throw new AbstractMethodError();
	}

	/**
	 * @param {Module} module the exporting entry module
	 * @param {string} entryName the name of the entrypoint
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {void}
	 */
	finishEntryModule(module, entryName, libraryContext) {}

	/**
	 * @param {Module} module the exporting entry module
	 * @param {RenderContext} renderContext render context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {string | undefined} bailout reason
	 */
	embedInRuntimeBailout(module, renderContext, libraryContext) {
		return undefined;
	}

	/**
	 * @param {RenderContext} renderContext render context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {string | undefined} bailout reason
	 */
	strictRuntimeBailout(renderContext, libraryContext) {
		return undefined;
	}

	/**
	 * @param {Chunk} chunk the chunk
	 * @param {Set<string>} set runtime requirements
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {void}
	 */
	runtimeRequirements(chunk, set, libraryContext) {
		if (this.render !== AbstractLibraryPlugin.prototype.render)
			set.add(RuntimeGlobals.returnExportsFromRuntime);
	}

	/**
	 * @param {Source} source source
	 * @param {RenderContext} renderContext render context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {Source} source with library export
	 */
	render(source, renderContext, libraryContext) {
		return source;
	}

	/**
	 * @param {Source} source source
	 * @param {Module} module module
	 * @param {StartupRenderContext} renderContext render context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {Source} source with library export
	 */
	renderStartup(source, module, renderContext, libraryContext) {
		return source;
	}

	/**
	 * @param {Chunk} chunk the chunk
	 * @param {Hash} hash hash
	 * @param {ChunkHashContext} chunkHashContext chunk hash context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {void}
	 */
	chunkHash(chunk, hash, chunkHashContext, libraryContext) {
		const options = this._parseOptionsCached(
			libraryContext.compilation.outputOptions.library
		);
		hash.update(this._pluginName);
		hash.update(JSON.stringify(options));
	}
}

AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE = COMMON_LIBRARY_NAME_MESSAGE;
module.exports = AbstractLibraryPlugin;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { ConcatSource } = require("webpack-sources");
const ExternalModule = require("../ExternalModule");
const Template = require("../Template");
const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");

/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
/** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
/** @typedef {import("../util/Hash")} Hash */
/** @template T @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T> */

/**
 * @typedef {object} AmdLibraryPluginOptions
 * @property {LibraryType} type
 * @property {boolean=} requireAsWrapper
 */

/**
 * @typedef {object} AmdLibraryPluginParsed
 * @property {string} name
 * @property {string} amdContainer
 */

/**
 * @typedef {AmdLibraryPluginParsed} T
 * @extends {AbstractLibraryPlugin<AmdLibraryPluginParsed>}
 */
class AmdLibraryPlugin extends AbstractLibraryPlugin {
	/**
	 * @param {AmdLibraryPluginOptions} options the plugin options
	 */
	constructor(options) {
		super({
			pluginName: "AmdLibraryPlugin",
			type: options.type
		});
		this.requireAsWrapper = options.requireAsWrapper;
	}

	/**
	 * @param {LibraryOptions} library normalized library option
	 * @returns {T | false} preprocess as needed by overriding
	 */
	parseOptions(library) {
		const { name, amdContainer } = library;
		if (this.requireAsWrapper) {
			if (name) {
				throw new Error(
					`AMD library name must be unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
				);
			}
		} else {
			if (name && typeof name !== "string") {
				throw new Error(
					`AMD library name must be a simple string or unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
				);
			}
		}
		return {
			name: /** @type {string} */ (name),
			amdContainer: /** @type {string} */ (amdContainer)
		};
	}

	/**
	 * @param {Source} source source
	 * @param {RenderContext} renderContext render context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {Source} source with library export
	 */
	render(
		source,
		{ chunkGraph, chunk, runtimeTemplate },
		{ options, compilation }
	) {
		const modern = runtimeTemplate.supportsArrowFunction();
		const modules = chunkGraph
			.getChunkModules(chunk)
			.filter(
				m =>
					m instanceof ExternalModule &&
					(m.externalType === "amd" || m.externalType === "amd-require")
			);
		const externals = /** @type {ExternalModule[]} */ (modules);
		const externalsDepsArray = JSON.stringify(
			externals.map(m =>
				typeof m.request === "object" && !Array.isArray(m.request)
					? m.request.amd
					: m.request
			)
		);
		const externalsArguments = externals
			.map(
				m =>
					`__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(
						`${chunkGraph.getModuleId(m)}`
					)}__`
			)
			.join(", ");

		const iife = runtimeTemplate.isIIFE();
		const fnStart =
			(modern
				? `(${externalsArguments}) => {`
				: `function(${externalsArguments}) {`) +
			(iife || !chunk.hasRuntime() ? " return " : "\n");
		const fnEnd = iife ? ";\n}" : "\n}";

		let amdContainerPrefix = "";
		if (options.amdContainer) {
			amdContainerPrefix = `${options.amdContainer}.`;
		}

		if (this.requireAsWrapper) {
			return new ConcatSource(
				`${amdContainerPrefix}require(${externalsDepsArray}, ${fnStart}`,
				source,
				`${fnEnd});`
			);
		} else if (options.name) {
			const name = compilation.getPath(options.name, {
				chunk
			});

			return new ConcatSource(
				`${amdContainerPrefix}define(${JSON.stringify(
					name
				)}, ${externalsDepsArray}, ${fnStart}`,
				source,
				`${fnEnd});`
			);
		} else if (externalsArguments) {
			return new ConcatSource(
				`${amdContainerPrefix}define(${externalsDepsArray}, ${fnStart}`,
				source,
				`${fnEnd});`
			);
		} else {
			return new ConcatSource(
				`${amdContainerPrefix}define(${fnStart}`,
				source,
				`${fnEnd});`
			);
		}
	}

	/**
	 * @param {Chunk} chunk the chunk
	 * @param {Hash} hash hash
	 * @param {ChunkHashContext} chunkHashContext chunk hash context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {void}
	 */
	chunkHash(chunk, hash, chunkHashContext, { options, compilation }) {
		hash.update("AmdLibraryPlugin");
		if (this.requireAsWrapper) {
			hash.update("requireAsWrapper");
		} else if (options.name) {
			hash.update("named");
			const name = compilation.getPath(options.name, {
				chunk
			});
			hash.update(name);
		} else if (options.amdContainer) {
			hash.update("amdContainer");
			hash.update(options.amdContainer);
		}
	}
}

module.exports = AmdLibraryPlugin;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { ConcatSource } = require("webpack-sources");
const { UsageState } = require("../ExportsInfo");
const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
const propertyAccess = require("../util/propertyAccess");
const { getEntryRuntime } = require("../util/runtime");
const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");

/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
/** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
/** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */
/** @typedef {import("../util/Hash")} Hash */
/** @template T @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T> */

const KEYWORD_REGEX =
	/^(await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|function|if|implements|import|in|instanceof|interface|let|new|null|package|private|protected|public|return|super|switch|static|this|throw|try|true|typeof|var|void|while|with|yield)$/;
const IDENTIFIER_REGEX =
	/^[\p{L}\p{Nl}$_][\p{L}\p{Nl}$\p{Mn}\p{Mc}\p{Nd}\p{Pc}]*$/iu;

/**
 * Validates the library name by checking for keywords and valid characters
 * @param {string} name name to be validated
 * @returns {boolean} true, when valid
 */
const isNameValid = name => {
	return !KEYWORD_REGEX.test(name) && IDENTIFIER_REGEX.test(name);
};

/**
 * @param {string[]} accessor variable plus properties
 * @param {number} existingLength items of accessor that are existing already
 * @param {boolean=} initLast if the last property should also be initialized to an object
 * @returns {string} code to access the accessor while initializing
 */
const accessWithInit = (accessor, existingLength, initLast = false) => {
	// This generates for [a, b, c, d]:
	// (((a = typeof a === "undefined" ? {} : a).b = a.b || {}).c = a.b.c || {}).d
	const base = accessor[0];
	if (accessor.length === 1 && !initLast) return base;
	let current =
		existingLength > 0
			? base
			: `(${base} = typeof ${base} === "undefined" ? {} : ${base})`;

	// i is the current position in accessor that has been printed
	let i = 1;

	// all properties printed so far (excluding base)
	/** @type {string[] | undefined} */
	let propsSoFar;

	// if there is existingLength, print all properties until this position as property access
	if (existingLength > i) {
		propsSoFar = accessor.slice(1, existingLength);
		i = existingLength;
		current += propertyAccess(propsSoFar);
	} else {
		propsSoFar = [];
	}

	// all remaining properties (except the last one when initLast is not set)
	// should be printed as initializer
	const initUntil = initLast ? accessor.length : accessor.length - 1;
	for (; i < initUntil; i++) {
		const prop = accessor[i];
		propsSoFar.push(prop);
		current = `(${current}${propertyAccess([prop])} = ${base}${propertyAccess(
			propsSoFar
		)} || {})`;
	}

	// print the last property as property access if not yet printed
	if (i < accessor.length)
		current = `${current}${propertyAccess([accessor[accessor.length - 1]])}`;

	return current;
};

/**
 * @typedef {object} AssignLibraryPluginOptions
 * @property {LibraryType} type
 * @property {string[] | "global"} prefix name prefix
 * @property {string | false} declare declare name as variable
 * @property {"error"|"static"|"copy"|"assign"} unnamed behavior for unnamed library name
 * @property {"copy"|"assign"=} named behavior for named library name
 */

/**
 * @typedef {object} AssignLibraryPluginParsed
 * @property {string | string[]} name
 * @property {string | string[] | undefined} export
 */

/**
 * @typedef {AssignLibraryPluginParsed} T
 * @extends {AbstractLibraryPlugin<AssignLibraryPluginParsed>}
 */
class AssignLibraryPlugin extends AbstractLibraryPlugin {
	/**
	 * @param {AssignLibraryPluginOptions} options the plugin options
	 */
	constructor(options) {
		super({
			pluginName: "AssignLibraryPlugin",
			type: options.type
		});
		this.prefix = options.prefix;
		this.declare = options.declare;
		this.unnamed = options.unnamed;
		this.named = options.named || "assign";
	}

	/**
	 * @param {LibraryOptions} library normalized library option
	 * @returns {T | false} preprocess as needed by overriding
	 */
	parseOptions(library) {
		const { name } = library;
		if (this.unnamed === "error") {
			if (typeof name !== "string" && !Array.isArray(name)) {
				throw new Error(
					`Library name must be a string or string array. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
				);
			}
		} else {
			if (name && typeof name !== "string" && !Array.isArray(name)) {
				throw new Error(
					`Library name must be a string, string array or unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
				);
			}
		}
		return {
			name: /** @type {string | string[]} */ (name),
			export: library.export
		};
	}

	/**
	 * @param {Module} module the exporting entry module
	 * @param {string} entryName the name of the entrypoint
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {void}
	 */
	finishEntryModule(
		module,
		entryName,
		{ options, compilation, compilation: { moduleGraph } }
	) {
		const runtime = getEntryRuntime(compilation, entryName);
		if (options.export) {
			const exportsInfo = moduleGraph.getExportInfo(
				module,
				Array.isArray(options.export) ? options.export[0] : options.export
			);
			exportsInfo.setUsed(UsageState.Used, runtime);
			exportsInfo.canMangleUse = false;
		} else {
			const exportsInfo = moduleGraph.getExportsInfo(module);
			exportsInfo.setUsedInUnknownWay(runtime);
		}
		moduleGraph.addExtraReason(module, "used as library export");
	}

	/**
	 * @param {Compilation} compilation the compilation
	 * @returns {string[]} the prefix
	 */
	_getPrefix(compilation) {
		return this.prefix === "global"
			? [compilation.runtimeTemplate.globalObject]
			: this.prefix;
	}

	/**
	 * @param {AssignLibraryPluginParsed} options the library options
	 * @param {Chunk} chunk the chunk
	 * @param {Compilation} compilation the compilation
	 * @returns {Array<string>} the resolved full name
	 */
	_getResolvedFullName(options, chunk, compilation) {
		const prefix = this._getPrefix(compilation);
		const fullName = options.name ? prefix.concat(options.name) : prefix;
		return fullName.map(n =>
			compilation.getPath(n, {
				chunk
			})
		);
	}

	/**
	 * @param {Source} source source
	 * @param {RenderContext} renderContext render context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {Source} source with library export
	 */
	render(source, { chunk }, { options, compilation }) {
		const fullNameResolved = this._getResolvedFullName(
			options,
			chunk,
			compilation
		);
		if (this.declare) {
			const base = fullNameResolved[0];
			if (!isNameValid(base)) {
				throw new Error(
					`Library name base (${base}) must be a valid identifier when using a var declaring library type. Either use a valid identifier (e. g. ${Template.toIdentifier(
						base
					)}) or use a different library type (e. g. 'type: "global"', which assign a property on the global scope instead of declaring a variable). ${
						AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE
					}`
				);
			}
			source = new ConcatSource(`${this.declare} ${base};\n`, source);
		}
		return source;
	}

	/**
	 * @param {Module} module the exporting entry module
	 * @param {RenderContext} renderContext render context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {string | undefined} bailout reason
	 */
	embedInRuntimeBailout(
		module,
		{ chunk, codeGenerationResults },
		{ options, compilation }
	) {
		const { data } = codeGenerationResults.get(module, chunk.runtime);
		const topLevelDeclarations =
			(data && data.get("topLevelDeclarations")) ||
			(module.buildInfo && module.buildInfo.topLevelDeclarations);
		if (!topLevelDeclarations)
			return "it doesn't tell about top level declarations.";
		const fullNameResolved = this._getResolvedFullName(
			options,
			chunk,
			compilation
		);
		const base = fullNameResolved[0];
		if (topLevelDeclarations.has(base))
			return `it declares '${base}' on top-level, which conflicts with the current library output.`;
	}

	/**
	 * @param {RenderContext} renderContext render context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {string | undefined} bailout reason
	 */
	strictRuntimeBailout({ chunk }, { options, compilation }) {
		if (
			this.declare ||
			this.prefix === "global" ||
			this.prefix.length > 0 ||
			!options.name
		) {
			return;
		}
		return "a global variable is assign and maybe created";
	}

	/**
	 * @param {Source} source source
	 * @param {Module} module module
	 * @param {StartupRenderContext} renderContext render context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {Source} source with library export
	 */
	renderStartup(
		source,
		module,
		{ moduleGraph, chunk },
		{ options, compilation }
	) {
		const fullNameResolved = this._getResolvedFullName(
			options,
			chunk,
			compilation
		);
		const staticExports = this.unnamed === "static";
		const exportAccess = options.export
			? propertyAccess(
					Array.isArray(options.export) ? options.export : [options.export]
				)
			: "";
		const result = new ConcatSource(source);
		if (staticExports) {
			const exportsInfo = moduleGraph.getExportsInfo(module);
			const exportTarget = accessWithInit(
				fullNameResolved,
				this._getPrefix(compilation).length,
				true
			);
			for (const exportInfo of exportsInfo.orderedExports) {
				if (!exportInfo.provided) continue;
				const nameAccess = propertyAccess([exportInfo.name]);
				result.add(
					`${exportTarget}${nameAccess} = ${RuntimeGlobals.exports}${exportAccess}${nameAccess};\n`
				);
			}
			result.add(
				`Object.defineProperty(${exportTarget}, "__esModule", { value: true });\n`
			);
		} else if (options.name ? this.named === "copy" : this.unnamed === "copy") {
			result.add(
				`var __webpack_export_target__ = ${accessWithInit(
					fullNameResolved,
					this._getPrefix(compilation).length,
					true
				)};\n`
			);
			/** @type {string} */
			let exports = RuntimeGlobals.exports;
			if (exportAccess) {
				result.add(
					`var __webpack_exports_export__ = ${RuntimeGlobals.exports}${exportAccess};\n`
				);
				exports = "__webpack_exports_export__";
			}
			result.add(
				`for(var i in ${exports}) __webpack_export_target__[i] = ${exports}[i];\n`
			);
			result.add(
				`if(${exports}.__esModule) Object.defineProperty(__webpack_export_target__, "__esModule", { value: true });\n`
			);
		} else {
			result.add(
				`${accessWithInit(
					fullNameResolved,
					this._getPrefix(compilation).length,
					false
				)} = ${RuntimeGlobals.exports}${exportAccess};\n`
			);
		}
		return result;
	}

	/**
	 * @param {Chunk} chunk the chunk
	 * @param {Set<string>} set runtime requirements
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {void}
	 */
	runtimeRequirements(chunk, set, libraryContext) {
		// we don't need to return exports from runtime
	}

	/**
	 * @param {Chunk} chunk the chunk
	 * @param {Hash} hash hash
	 * @param {ChunkHashContext} chunkHashContext chunk hash context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {void}
	 */
	chunkHash(chunk, hash, chunkHashContext, { options, compilation }) {
		hash.update("AssignLibraryPlugin");
		const fullNameResolved = this._getResolvedFullName(
			options,
			chunk,
			compilation
		);
		if (options.name ? this.named === "copy" : this.unnamed === "copy") {
			hash.update("copy");
		}
		if (this.declare) {
			hash.update(this.declare);
		}
		hash.update(fullNameResolved.join("."));
		if (options.export) {
			hash.update(`${options.export}`);
		}
	}
}

module.exports = AssignLibraryPlugin;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

/** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
/** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
/** @typedef {import("../Compiler")} Compiler */

/** @type {WeakMap<Compiler, Set<LibraryType>>} */
const enabledTypes = new WeakMap();

/**
 * @param {Compiler} compiler the compiler instance
 * @returns {Set<LibraryType>} enabled types
 */
const getEnabledTypes = compiler => {
	let set = enabledTypes.get(compiler);
	if (set === undefined) {
		set = new Set();
		enabledTypes.set(compiler, set);
	}
	return set;
};

class EnableLibraryPlugin {
	/**
	 * @param {LibraryType} type library type that should be available
	 */
	constructor(type) {
		this.type = type;
	}

	/**
	 * @param {Compiler} compiler the compiler instance
	 * @param {LibraryType} type type of library
	 * @returns {void}
	 */
	static setEnabled(compiler, type) {
		getEnabledTypes(compiler).add(type);
	}

	/**
	 * @param {Compiler} compiler the compiler instance
	 * @param {LibraryType} type type of library
	 * @returns {void}
	 */
	static checkEnabled(compiler, type) {
		if (!getEnabledTypes(compiler).has(type)) {
			throw new Error(
				`Library type "${type}" is not enabled. ` +
					"EnableLibraryPlugin need to be used to enable this type of library. " +
					'This usually happens through the "output.enabledLibraryTypes" option. ' +
					'If you are using a function as entry which sets "library", you need to add all potential library types to "output.enabledLibraryTypes". ' +
					"These types are enabled: " +
					Array.from(getEnabledTypes(compiler)).join(", ")
			);
		}
	}

	/**
	 * Apply the plugin
	 * @param {Compiler} compiler the compiler instance
	 * @returns {void}
	 */
	apply(compiler) {
		const { type } = this;

		// Only enable once
		const enabled = getEnabledTypes(compiler);
		if (enabled.has(type)) return;
		enabled.add(type);

		if (typeof type === "string") {
			const enableExportProperty = () => {
				const ExportPropertyTemplatePlugin = require("./ExportPropertyLibraryPlugin");
				new ExportPropertyTemplatePlugin({
					type,
					nsObjectUsed: type !== "module"
				}).apply(compiler);
			};
			switch (type) {
				case "var": {
					//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
					const AssignLibraryPlugin = require("./AssignLibraryPlugin");
					new AssignLibraryPlugin({
						type,
						prefix: [],
						declare: "var",
						unnamed: "error"
					}).apply(compiler);
					break;
				}
				case "assign-properties": {
					//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
					const AssignLibraryPlugin = require("./AssignLibraryPlugin");
					new AssignLibraryPlugin({
						type,
						prefix: [],
						declare: false,
						unnamed: "error",
						named: "copy"
					}).apply(compiler);
					break;
				}
				case "assign": {
					//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
					const AssignLibraryPlugin = require("./AssignLibraryPlugin");
					new AssignLibraryPlugin({
						type,
						prefix: [],
						declare: false,
						unnamed: "error"
					}).apply(compiler);
					break;
				}
				case "this": {
					//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
					const AssignLibraryPlugin = require("./AssignLibraryPlugin");
					new AssignLibraryPlugin({
						type,
						prefix: ["this"],
						declare: false,
						unnamed: "copy"
					}).apply(compiler);
					break;
				}
				case "window": {
					//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
					const AssignLibraryPlugin = require("./AssignLibraryPlugin");
					new AssignLibraryPlugin({
						type,
						prefix: ["window"],
						declare: false,
						unnamed: "copy"
					}).apply(compiler);
					break;
				}
				case "self": {
					//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
					const AssignLibraryPlugin = require("./AssignLibraryPlugin");
					new AssignLibraryPlugin({
						type,
						prefix: ["self"],
						declare: false,
						unnamed: "copy"
					}).apply(compiler);
					break;
				}
				case "global": {
					//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
					const AssignLibraryPlugin = require("./AssignLibraryPlugin");
					new AssignLibraryPlugin({
						type,
						prefix: "global",
						declare: false,
						unnamed: "copy"
					}).apply(compiler);
					break;
				}
				case "commonjs": {
					//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
					const AssignLibraryPlugin = require("./AssignLibraryPlugin");
					new AssignLibraryPlugin({
						type,
						prefix: ["exports"],
						declare: false,
						unnamed: "copy"
					}).apply(compiler);
					break;
				}
				case "commonjs-static": {
					//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
					const AssignLibraryPlugin = require("./AssignLibraryPlugin");
					new AssignLibraryPlugin({
						type,
						prefix: ["exports"],
						declare: false,
						unnamed: "static"
					}).apply(compiler);
					break;
				}
				case "commonjs2":
				case "commonjs-module": {
					//@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
					const AssignLibraryPlugin = require("./AssignLibraryPlugin");
					new AssignLibraryPlugin({
						type,
						prefix: ["module", "exports"],
						declare: false,
						unnamed: "assign"
					}).apply(compiler);
					break;
				}
				case "amd":
				case "amd-require": {
					enableExportProperty();
					const AmdLibraryPlugin = require("./AmdLibraryPlugin");
					new AmdLibraryPlugin({
						type,
						requireAsWrapper: type === "amd-require"
					}).apply(compiler);
					break;
				}
				case "umd":
				case "umd2": {
					enableExportProperty();
					const UmdLibraryPlugin = require("./UmdLibraryPlugin");
					new UmdLibraryPlugin({
						type,
						optionalAmdExternalAsGlobal: type === "umd2"
					}).apply(compiler);
					break;
				}
				case "system": {
					enableExportProperty();
					const SystemLibraryPlugin = require("./SystemLibraryPlugin");
					new SystemLibraryPlugin({
						type
					}).apply(compiler);
					break;
				}
				case "jsonp": {
					enableExportProperty();
					const JsonpLibraryPlugin = require("./JsonpLibraryPlugin");
					new JsonpLibraryPlugin({
						type
					}).apply(compiler);
					break;
				}
				case "module": {
					enableExportProperty();
					const ModuleLibraryPlugin = require("./ModuleLibraryPlugin");
					new ModuleLibraryPlugin({
						type
					}).apply(compiler);
					break;
				}
				default:
					throw new Error(`Unsupported library type ${type}.
Plugins which provide custom library types must call EnableLibraryPlugin.setEnabled(compiler, type) to disable this error.`);
			}
		} else {
			// TODO support plugin instances here
			// apply them to the compiler
		}
	}
}

module.exports = EnableLibraryPlugin;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { ConcatSource } = require("webpack-sources");
const { UsageState } = require("../ExportsInfo");
const RuntimeGlobals = require("../RuntimeGlobals");
const propertyAccess = require("../util/propertyAccess");
const { getEntryRuntime } = require("../util/runtime");
const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");

/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
/** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */
/** @template T @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T> */

/**
 * @typedef {object} ExportPropertyLibraryPluginParsed
 * @property {string | string[]} export
 */

/**
 * @typedef {object} ExportPropertyLibraryPluginOptions
 * @property {LibraryType} type
 * @property {boolean} nsObjectUsed the namespace object is used
 */
/**
 * @typedef {ExportPropertyLibraryPluginParsed} T
 * @extends {AbstractLibraryPlugin<ExportPropertyLibraryPluginParsed>}
 */
class ExportPropertyLibraryPlugin extends AbstractLibraryPlugin {
	/**
	 * @param {ExportPropertyLibraryPluginOptions} options options
	 */
	constructor({ type, nsObjectUsed }) {
		super({
			pluginName: "ExportPropertyLibraryPlugin",
			type
		});
		this.nsObjectUsed = nsObjectUsed;
	}

	/**
	 * @param {LibraryOptions} library normalized library option
	 * @returns {T | false} preprocess as needed by overriding
	 */
	parseOptions(library) {
		return {
			export: library.export
		};
	}

	/**
	 * @param {Module} module the exporting entry module
	 * @param {string} entryName the name of the entrypoint
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {void}
	 */
	finishEntryModule(
		module,
		entryName,
		{ options, compilation, compilation: { moduleGraph } }
	) {
		const runtime = getEntryRuntime(compilation, entryName);
		if (options.export) {
			const exportsInfo = moduleGraph.getExportInfo(
				module,
				Array.isArray(options.export) ? options.export[0] : options.export
			);
			exportsInfo.setUsed(UsageState.Used, runtime);
			exportsInfo.canMangleUse = false;
		} else {
			const exportsInfo = moduleGraph.getExportsInfo(module);
			if (this.nsObjectUsed) {
				exportsInfo.setUsedInUnknownWay(runtime);
			} else {
				exportsInfo.setAllKnownExportsUsed(runtime);
			}
		}
		moduleGraph.addExtraReason(module, "used as library export");
	}

	/**
	 * @param {Chunk} chunk the chunk
	 * @param {Set<string>} set runtime requirements
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {void}
	 */
	runtimeRequirements(chunk, set, libraryContext) {}

	/**
	 * @param {Source} source source
	 * @param {Module} module module
	 * @param {StartupRenderContext} renderContext render context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {Source} source with library export
	 */
	renderStartup(source, module, renderContext, { options }) {
		if (!options.export) return source;
		const postfix = `${RuntimeGlobals.exports} = ${
			RuntimeGlobals.exports
		}${propertyAccess(
			Array.isArray(options.export) ? options.export : [options.export]
		)};\n`;
		return new ConcatSource(source, postfix);
	}
}

module.exports = ExportPropertyLibraryPlugin;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { ConcatSource } = require("webpack-sources");
const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");

/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
/** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
/** @typedef {import("../util/Hash")} Hash */
/** @template T @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T> */

/**
 * @typedef {object} JsonpLibraryPluginOptions
 * @property {LibraryType} type
 */

/**
 * @typedef {object} JsonpLibraryPluginParsed
 * @property {string} name
 */

/**
 * @typedef {JsonpLibraryPluginParsed} T
 * @extends {AbstractLibraryPlugin<JsonpLibraryPluginParsed>}
 */
class JsonpLibraryPlugin extends AbstractLibraryPlugin {
	/**
	 * @param {JsonpLibraryPluginOptions} options the plugin options
	 */
	constructor(options) {
		super({
			pluginName: "JsonpLibraryPlugin",
			type: options.type
		});
	}

	/**
	 * @param {LibraryOptions} library normalized library option
	 * @returns {T | false} preprocess as needed by overriding
	 */
	parseOptions(library) {
		const { name } = library;
		if (typeof name !== "string") {
			throw new Error(
				`Jsonp library name must be a simple string. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
			);
		}
		return {
			name: /** @type {string} */ (name)
		};
	}

	/**
	 * @param {Source} source source
	 * @param {RenderContext} renderContext render context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {Source} source with library export
	 */
	render(source, { chunk }, { options, compilation }) {
		const name = compilation.getPath(options.name, {
			chunk
		});
		return new ConcatSource(`${name}(`, source, ")");
	}

	/**
	 * @param {Chunk} chunk the chunk
	 * @param {Hash} hash hash
	 * @param {ChunkHashContext} chunkHashContext chunk hash context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {void}
	 */
	chunkHash(chunk, hash, chunkHashContext, { options, compilation }) {
		hash.update("JsonpLibraryPlugin");
		hash.update(compilation.getPath(options.name, { chunk }));
	}
}

module.exports = JsonpLibraryPlugin;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { ConcatSource } = require("webpack-sources");
const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
const propertyAccess = require("../util/propertyAccess");
const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");

/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
/** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Module")} Module */
/** @typedef {import("../javascript/JavascriptModulesPlugin").StartupRenderContext} StartupRenderContext */
/** @typedef {import("../util/Hash")} Hash */
/** @template T @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T> */

/**
 * @typedef {object} ModuleLibraryPluginOptions
 * @property {LibraryType} type
 */

/**
 * @typedef {object} ModuleLibraryPluginParsed
 * @property {string} name
 */

/**
 * @typedef {ModuleLibraryPluginParsed} T
 * @extends {AbstractLibraryPlugin<ModuleLibraryPluginParsed>}
 */
class ModuleLibraryPlugin extends AbstractLibraryPlugin {
	/**
	 * @param {ModuleLibraryPluginOptions} options the plugin options
	 */
	constructor(options) {
		super({
			pluginName: "ModuleLibraryPlugin",
			type: options.type
		});
	}

	/**
	 * @param {LibraryOptions} library normalized library option
	 * @returns {T | false} preprocess as needed by overriding
	 */
	parseOptions(library) {
		const { name } = library;
		if (name) {
			throw new Error(
				`Library name must be unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
			);
		}
		return {
			name: /** @type {string} */ (name)
		};
	}

	/**
	 * @param {Source} source source
	 * @param {Module} module module
	 * @param {StartupRenderContext} renderContext render context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {Source} source with library export
	 */
	renderStartup(
		source,
		module,
		{ moduleGraph, chunk },
		{ options, compilation }
	) {
		const result = new ConcatSource(source);
		const exportsInfo = moduleGraph.getExportsInfo(module);
		const exports = [];
		const isAsync = moduleGraph.isAsync(module);
		if (isAsync) {
			result.add(
				`${RuntimeGlobals.exports} = await ${RuntimeGlobals.exports};\n`
			);
		}
		for (const exportInfo of exportsInfo.orderedExports) {
			if (!exportInfo.provided) continue;
			const varName = `${RuntimeGlobals.exports}${Template.toIdentifier(
				exportInfo.name
			)}`;
			result.add(
				`var ${varName} = ${RuntimeGlobals.exports}${propertyAccess([
					/** @type {string} */
					(exportInfo.getUsedName(exportInfo.name, chunk.runtime))
				])};\n`
			);
			exports.push(`${varName} as ${exportInfo.name}`);
		}
		if (exports.length > 0) {
			result.add(`export { ${exports.join(", ")} };\n`);
		}
		return result;
	}
}

module.exports = ModuleLibraryPlugin;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Joel Denning @joeldenning
*/

"use strict";

const { ConcatSource } = require("webpack-sources");
const { UsageState } = require("../ExportsInfo");
const ExternalModule = require("../ExternalModule");
const Template = require("../Template");
const propertyAccess = require("../util/propertyAccess");
const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");

/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
/** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compilation").ChunkHashContext} ChunkHashContext */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
/** @typedef {import("../util/Hash")} Hash */
/** @template T @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>} LibraryContext<T> */

/**
 * @typedef {object} SystemLibraryPluginOptions
 * @property {LibraryType} type
 */

/**
 * @typedef {object} SystemLibraryPluginParsed
 * @property {string} name
 */

/**
 * @typedef {SystemLibraryPluginParsed} T
 * @extends {AbstractLibraryPlugin<SystemLibraryPluginParsed>}
 */
class SystemLibraryPlugin extends AbstractLibraryPlugin {
	/**
	 * @param {SystemLibraryPluginOptions} options the plugin options
	 */
	constructor(options) {
		super({
			pluginName: "SystemLibraryPlugin",
			type: options.type
		});
	}

	/**
	 * @param {LibraryOptions} library normalized library option
	 * @returns {T | false} preprocess as needed by overriding
	 */
	parseOptions(library) {
		const { name } = library;
		if (name && typeof name !== "string") {
			throw new Error(
				`System.js library name must be a simple string or unset. ${AbstractLibraryPlugin.COMMON_LIBRARY_NAME_MESSAGE}`
			);
		}
		return {
			name: /** @type {string} */ (name)
		};
	}

	/**
	 * @param {Source} source source
	 * @param {RenderContext} renderContext render context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {Source} source with library export
	 */
	render(source, { chunkGraph, moduleGraph, chunk }, { options, compilation }) {
		const modules = chunkGraph
			.getChunkModules(chunk)
			.filter(m => m instanceof ExternalModule && m.externalType === "system");
		const externals = /** @type {ExternalModule[]} */ (modules);

		// The name this bundle should be registered as with System
		const name = options.name
			? `${JSON.stringify(compilation.getPath(options.name, { chunk }))}, `
			: "";

		// The array of dependencies that are external to webpack and will be provided by System
		const systemDependencies = JSON.stringify(
			externals.map(m =>
				typeof m.request === "object" && !Array.isArray(m.request)
					? m.request.amd
					: m.request
			)
		);

		// The name of the variable provided by System for exporting
		const dynamicExport = "__WEBPACK_DYNAMIC_EXPORT__";

		// An array of the internal variable names for the webpack externals
		const externalWebpackNames = externals.map(
			m =>
				`__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(
					`${chunkGraph.getModuleId(m)}`
				)}__`
		);

		// Declaring variables for the internal variable names for the webpack externals
		const externalVarDeclarations = externalWebpackNames
			.map(name => `var ${name} = {};`)
			.join("\n");

		// Define __esModule flag on all internal variables and helpers
		/** @type {string[]} */
		const externalVarInitialization = [];

		// The system.register format requires an array of setter functions for externals.
		const setters =
			externalWebpackNames.length === 0
				? ""
				: Template.asString([
						"setters: [",
						Template.indent(
							externals
								.map((module, i) => {
									const external = externalWebpackNames[i];
									const exportsInfo = moduleGraph.getExportsInfo(module);
									const otherUnused =
										exportsInfo.otherExportsInfo.getUsed(chunk.runtime) ===
										UsageState.Unused;
									const instructions = [];
									const handledNames = [];
									for (const exportInfo of exportsInfo.orderedExports) {
										const used = exportInfo.getUsedName(
											undefined,
											chunk.runtime
										);
										if (used) {
											if (otherUnused || used !== exportInfo.name) {
												instructions.push(
													`${external}${propertyAccess([
														used
													])} = module${propertyAccess([exportInfo.name])};`
												);
												handledNames.push(exportInfo.name);
											}
										} else {
											handledNames.push(exportInfo.name);
										}
									}
									if (!otherUnused) {
										if (
											!Array.isArray(module.request) ||
											module.request.length === 1
										) {
											externalVarInitialization.push(
												`Object.defineProperty(${external}, "__esModule", { value: true });`
											);
										}
										if (handledNames.length > 0) {
											const name = `${external}handledNames`;
											externalVarInitialization.push(
												`var ${name} = ${JSON.stringify(handledNames)};`
											);
											instructions.push(
												Template.asString([
													"Object.keys(module).forEach(function(key) {",
													Template.indent([
														`if(${name}.indexOf(key) >= 0)`,
														Template.indent(`${external}[key] = module[key];`)
													]),
													"});"
												])
											);
										} else {
											instructions.push(
												Template.asString([
													"Object.keys(module).forEach(function(key) {",
													Template.indent([`${external}[key] = module[key];`]),
													"});"
												])
											);
										}
									}
									if (instructions.length === 0) return "function() {}";
									return Template.asString([
										"function(module) {",
										Template.indent(instructions),
										"}"
									]);
								})
								.join(",\n")
						),
						"],"
					]);

		return new ConcatSource(
			Template.asString([
				`System.register(${name}${systemDependencies}, function(${dynamicExport}, __system_context__) {`,
				Template.indent([
					externalVarDeclarations,
					Template.asString(externalVarInitialization),
					"return {",
					Template.indent([
						setters,
						"execute: function() {",
						Template.indent(`${dynamicExport}(`)
					])
				]),
				""
			]),
			source,
			Template.asString([
				"",
				Template.indent([
					Template.indent([Template.indent([");"]), "}"]),
					"};"
				]),
				"})"
			])
		);
	}

	/**
	 * @param {Chunk} chunk the chunk
	 * @param {Hash} hash hash
	 * @param {ChunkHashContext} chunkHashContext chunk hash context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {void}
	 */
	chunkHash(chunk, hash, chunkHashContext, { options, compilation }) {
		hash.update("SystemLibraryPlugin");
		if (options.name) {
			hash.update(compilation.getPath(options.name, { chunk }));
		}
	}
}

module.exports = SystemLibraryPlugin;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { ConcatSource, OriginalSource } = require("webpack-sources");
const ExternalModule = require("../ExternalModule");
const Template = require("../Template");
const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");

/** @typedef {import("webpack-sources").Source} Source */
/** @typedef {import("../../declarations/WebpackOptions").LibraryCustomUmdCommentObject} LibraryCustomUmdCommentObject */
/** @typedef {import("../../declarations/WebpackOptions").LibraryCustomUmdObject} LibraryCustomUmdObject */
/** @typedef {import("../../declarations/WebpackOptions").LibraryName} LibraryName */
/** @typedef {import("../../declarations/WebpackOptions").LibraryOptions} LibraryOptions */
/** @typedef {import("../../declarations/WebpackOptions").LibraryType} LibraryType */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../javascript/JavascriptModulesPlugin").RenderContext} RenderContext */
/** @typedef {import("../ExternalModule").RequestRecord} RequestRecord */
/** @typedef {import("../util/Hash")} Hash */
/**
 * @template T
 * @typedef {import("./AbstractLibraryPlugin").LibraryContext<T>}
 * LibraryContext<T>
 */

/**
 * @param {string[]} accessor the accessor to convert to path
 * @returns {string} the path
 */
const accessorToObjectAccess = accessor => {
	return accessor.map(a => `[${JSON.stringify(a)}]`).join("");
};

/**
 * @param {string|undefined} base the path prefix
 * @param {string|string[]} accessor the accessor
 * @param {string=} joinWith the element separator
 * @returns {string} the path
 */
const accessorAccess = (base, accessor, joinWith = ", ") => {
	const accessors = Array.isArray(accessor) ? accessor : [accessor];
	return accessors
		.map((_, idx) => {
			const a = base
				? base + accessorToObjectAccess(accessors.slice(0, idx + 1))
				: accessors[0] + accessorToObjectAccess(accessors.slice(1, idx + 1));
			if (idx === accessors.length - 1) return a;
			if (idx === 0 && base === undefined)
				return `${a} = typeof ${a} === "object" ? ${a} : {}`;
			return `${a} = ${a} || {}`;
		})
		.join(joinWith);
};

/** @typedef {string | string[] | LibraryCustomUmdObject} UmdLibraryPluginName */

/**
 * @typedef {object} UmdLibraryPluginOptions
 * @property {LibraryType} type
 * @property {boolean=} optionalAmdExternalAsGlobal
 */

/**
 * @typedef {object} UmdLibraryPluginParsed
 * @property {string | string[]} name
 * @property {LibraryCustomUmdObject} names
 * @property {string | LibraryCustomUmdCommentObject} auxiliaryComment
 * @property {boolean} namedDefine
 */

/**
 * @typedef {UmdLibraryPluginParsed} T
 * @extends {AbstractLibraryPlugin<UmdLibraryPluginParsed>}
 */
class UmdLibraryPlugin extends AbstractLibraryPlugin {
	/**
	 * @param {UmdLibraryPluginOptions} options the plugin option
	 */
	constructor(options) {
		super({
			pluginName: "UmdLibraryPlugin",
			type: options.type
		});

		this.optionalAmdExternalAsGlobal = options.optionalAmdExternalAsGlobal;
	}

	/**
	 * @param {LibraryOptions} library normalized library option
	 * @returns {T | false} preprocess as needed by overriding
	 */
	parseOptions(library) {
		/** @type {LibraryName} */
		let name;
		/** @type {LibraryCustomUmdObject} */
		let names;
		if (typeof library.name === "object" && !Array.isArray(library.name)) {
			name = library.name.root || library.name.amd || library.name.commonjs;
			names = library.name;
		} else {
			name = library.name;
			const singleName = Array.isArray(name) ? name[0] : name;
			names = {
				commonjs: singleName,
				root: library.name,
				amd: singleName
			};
		}
		return {
			name,
			names,
			auxiliaryComment: library.auxiliaryComment,
			namedDefine: library.umdNamedDefine
		};
	}

	/**
	 * @param {Source} source source
	 * @param {RenderContext} renderContext render context
	 * @param {LibraryContext<T>} libraryContext context
	 * @returns {Source} source with library export
	 */
	render(
		source,
		{ chunkGraph, runtimeTemplate, chunk, moduleGraph },
		{ options, compilation }
	) {
		const modules = chunkGraph
			.getChunkModules(chunk)
			.filter(
				m =>
					m instanceof ExternalModule &&
					(m.externalType === "umd" || m.externalType === "umd2")
			);
		let externals = /** @type {ExternalModule[]} */ (modules);
		/** @type {ExternalModule[]} */
		const optionalExternals = [];
		/** @type {ExternalModule[]} */
		let requiredExternals = [];
		if (this.optionalAmdExternalAsGlobal) {
			for (const m of externals) {
				if (m.isOptional(moduleGraph)) {
					optionalExternals.push(m);
				} else {
					requiredExternals.push(m);
				}
			}
			externals = requiredExternals.concat(optionalExternals);
		} else {
			requiredExternals = externals;
		}

		/**
		 * @param {string} str the string to replace
		 * @returns {string} the replaced keys
		 */
		const replaceKeys = str => {
			return compilation.getPath(str, {
				chunk
			});
		};

		/**
		 * @param {ExternalModule[]} modules external modules
		 * @returns {string} result
		 */
		const externalsDepsArray = modules => {
			return `[${replaceKeys(
				modules
					.map(m =>
						JSON.stringify(
							typeof m.request === "object"
								? /** @type {RequestRecord} */
									(m.request).amd
								: m.request
						)
					)
					.join(", ")
			)}]`;
		};

		/**
		 * @param {ExternalModule[]} modules external modules
		 * @returns {string} result
		 */
		const externalsRootArray = modules => {
			return replaceKeys(
				modules
					.map(m => {
						let request = m.request;
						if (typeof request === "object")
							request =
								/** @type {RequestRecord} */
								(request).root;
						return `root${accessorToObjectAccess([].concat(request))}`;
					})
					.join(", ")
			);
		};

		/**
		 * @param {string} type the type
		 * @returns {string} external require array
		 */
		const externalsRequireArray = type => {
			return replaceKeys(
				externals
					.map(m => {
						let expr;
						let request = m.request;
						if (typeof request === "object") {
							request =
								/** @type {RequestRecord} */
								(request)[type];
						}
						if (request === undefined) {
							throw new Error(
								"Missing external configuration for type:" + type
							);
						}
						if (Array.isArray(request)) {
							expr = `require(${JSON.stringify(
								request[0]
							)})${accessorToObjectAccess(request.slice(1))}`;
						} else {
							expr = `require(${JSON.stringify(request)})`;
						}
						if (m.isOptional(moduleGraph)) {
							expr = `(function webpackLoadOptionalExternalModule() { try { return ${expr}; } catch(e) {} }())`;
						}
						return expr;
					})
					.join(", ")
			);
		};

		/**
		 * @param {ExternalModule[]} modules external modules
		 * @returns {string} arguments
		 */
		const externalsArguments = modules => {
			return modules
				.map(
					m =>
						`__WEBPACK_EXTERNAL_MODULE_${Template.toIdentifier(
							`${chunkGraph.getModuleId(m)}`
						)}__`
				)
				.join(", ");
		};

		/**
		 * @param {string| string[]} library library name
		 * @returns {string} stringified library name
		 */
		const libraryName = library => {
			return JSON.stringify(
				replaceKeys(/** @type {string[]} */ ([]).concat(library).pop())
			);
		};

		let amdFactory;
		if (optionalExternals.length > 0) {
			const wrapperArguments = externalsArguments(requiredExternals);
			const factoryArguments =
				requiredExternals.length > 0
					? externalsArguments(requiredExternals) +
						", " +
						externalsRootArray(optionalExternals)
					: externalsRootArray(optionalExternals);
			amdFactory =
				`function webpackLoadOptionalExternalModuleAmd(${wrapperArguments}) {\n` +
				`			return factory(${factoryArguments});\n` +
				"		}";
		} else {
			amdFactory = "factory";
		}

		const { auxiliaryComment, namedDefine, names } = options;

		/**
		 * @param {keyof LibraryCustomUmdCommentObject} type type
		 * @returns {string} comment
		 */
		const getAuxiliaryComment = type => {
			if (auxiliaryComment) {
				if (typeof auxiliaryComment === "string")
					return "\t//" + auxiliaryComment + "\n";
				if (auxiliaryComment[type])
					return "\t//" + auxiliaryComment[type] + "\n";
			}
			return "";
		};

		return new ConcatSource(
			new OriginalSource(
				"(function webpackUniversalModuleDefinition(root, factory) {\n" +
					getAuxiliaryComment("commonjs2") +
					"	if(typeof exports === 'object' && typeof module === 'object')\n" +
					"		module.exports = factory(" +
					externalsRequireArray("commonjs2") +
					");\n" +
					getAuxiliaryComment("amd") +
					"	else if(typeof define === 'function' && define.amd)\n" +
					(requiredExternals.length > 0
						? names.amd && namedDefine === true
							? "		define(" +
								libraryName(names.amd) +
								", " +
								externalsDepsArray(requiredExternals) +
								", " +
								amdFactory +
								");\n"
							: "		define(" +
								externalsDepsArray(requiredExternals) +
								", " +
								amdFactory +
								");\n"
						: names.amd && namedDefine === true
							? "		define(" +
								libraryName(names.amd) +
								", [], " +
								amdFactory +
								");\n"
							: "		define([], " + amdFactory + ");\n") +
					(names.root || names.commonjs
						? getAuxiliaryComment("commonjs") +
							"	else if(typeof exports === 'object')\n" +
							"		exports[" +
							libraryName(names.commonjs || names.root) +
							"] = factory(" +
							externalsRequireArray("commonjs") +
							");\n" +
							getAuxiliaryComment("root") +
							"	else\n" +
							"		" +
							replaceKeys(
								accessorAccess("root", names.root || names.commonjs)
							) +
							" = factory(" +
							externalsRootArray(externals) +
							");\n"
						: "	else {\n" +
							(externals.length > 0
								? "		var a = typeof exports === 'object' ? factory(" +
									externalsRequireArray("commonjs") +
									") : factory(" +
									externalsRootArray(externals) +
									");\n"
								: "		var a = factory();\n") +
							"		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];\n" +
							"	}\n") +
					`})(${runtimeTemplate.outputOptions.globalObject}, ${
						runtimeTemplate.supportsArrowFunction()
							? `(${externalsArguments(externals)}) =>`
							: `function(${externalsArguments(externals)})`
					} {\nreturn `,
				"webpack/universalModuleDefinition"
			),
			source,
			";\n})"
		);
	}
}

module.exports = UmdLibraryPlugin;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const LogType = Object.freeze({
	error: /** @type {"error"} */ ("error"), // message, c style arguments
	warn: /** @type {"warn"} */ ("warn"), // message, c style arguments
	info: /** @type {"info"} */ ("info"), // message, c style arguments
	log: /** @type {"log"} */ ("log"), // message, c style arguments
	debug: /** @type {"debug"} */ ("debug"), // message, c style arguments

	trace: /** @type {"trace"} */ ("trace"), // no arguments

	group: /** @type {"group"} */ ("group"), // [label]
	groupCollapsed: /** @type {"groupCollapsed"} */ ("groupCollapsed"), // [label]
	groupEnd: /** @type {"groupEnd"} */ ("groupEnd"), // [label]

	profile: /** @type {"profile"} */ ("profile"), // [profileName]
	profileEnd: /** @type {"profileEnd"} */ ("profileEnd"), // [profileName]

	time: /** @type {"time"} */ ("time"), // name, time as [seconds, nanoseconds]

	clear: /** @type {"clear"} */ ("clear"), // no arguments
	status: /** @type {"status"} */ ("status") // message, arguments
});

exports.LogType = LogType;

/** @typedef {typeof LogType[keyof typeof LogType]} LogTypeEnum */

const LOG_SYMBOL = Symbol("webpack logger raw log method");
const TIMERS_SYMBOL = Symbol("webpack logger times");
const TIMERS_AGGREGATES_SYMBOL = Symbol("webpack logger aggregated times");

class WebpackLogger {
	/**
	 * @param {function(LogTypeEnum, any[]=): void} log log function
	 * @param {function(string | function(): string): WebpackLogger} getChildLogger function to create child logger
	 */
	constructor(log, getChildLogger) {
		this[LOG_SYMBOL] = log;
		this.getChildLogger = getChildLogger;
	}

	error(...args) {
		this[LOG_SYMBOL](LogType.error, args);
	}

	warn(...args) {
		this[LOG_SYMBOL](LogType.warn, args);
	}

	info(...args) {
		this[LOG_SYMBOL](LogType.info, args);
	}

	log(...args) {
		this[LOG_SYMBOL](LogType.log, args);
	}

	debug(...args) {
		this[LOG_SYMBOL](LogType.debug, args);
	}

	assert(assertion, ...args) {
		if (!assertion) {
			this[LOG_SYMBOL](LogType.error, args);
		}
	}

	trace() {
		this[LOG_SYMBOL](LogType.trace, ["Trace"]);
	}

	clear() {
		this[LOG_SYMBOL](LogType.clear);
	}

	status(...args) {
		this[LOG_SYMBOL](LogType.status, args);
	}

	group(...args) {
		this[LOG_SYMBOL](LogType.group, args);
	}

	groupCollapsed(...args) {
		this[LOG_SYMBOL](LogType.groupCollapsed, args);
	}

	groupEnd(...args) {
		this[LOG_SYMBOL](LogType.groupEnd, args);
	}

	/**
	 * @param {string=} label label
	 */
	profile(label) {
		this[LOG_SYMBOL](LogType.profile, [label]);
	}

	/**
	 * @param {string=} label label
	 */
	profileEnd(label) {
		this[LOG_SYMBOL](LogType.profileEnd, [label]);
	}

	/**
	 * @param {string} label label
	 */
	time(label) {
		/** @type {Map<string | undefined, [number, number]>} */
		this[TIMERS_SYMBOL] = this[TIMERS_SYMBOL] || new Map();
		this[TIMERS_SYMBOL].set(label, process.hrtime());
	}

	/**
	 * @param {string=} label label
	 */
	timeLog(label) {
		const prev = this[TIMERS_SYMBOL] && this[TIMERS_SYMBOL].get(label);
		if (!prev) {
			throw new Error(`No such label '${label}' for WebpackLogger.timeLog()`);
		}
		const time = process.hrtime(prev);
		this[LOG_SYMBOL](LogType.time, [label, ...time]);
	}

	/**
	 * @param {string=} label label
	 */
	timeEnd(label) {
		const prev = this[TIMERS_SYMBOL] && this[TIMERS_SYMBOL].get(label);
		if (!prev) {
			throw new Error(`No such label '${label}' for WebpackLogger.timeEnd()`);
		}
		const time = process.hrtime(prev);
		/** @type {Map<string | undefined, [number, number]>} */
		(this[TIMERS_SYMBOL]).delete(label);
		this[LOG_SYMBOL](LogType.time, [label, ...time]);
	}

	/**
	 * @param {string=} label label
	 */
	timeAggregate(label) {
		const prev = this[TIMERS_SYMBOL] && this[TIMERS_SYMBOL].get(label);
		if (!prev) {
			throw new Error(
				`No such label '${label}' for WebpackLogger.timeAggregate()`
			);
		}
		const time = process.hrtime(prev);
		/** @type {Map<string | undefined, [number, number]>} */
		(this[TIMERS_SYMBOL]).delete(label);
		/** @type {Map<string | undefined, [number, number]>} */
		this[TIMERS_AGGREGATES_SYMBOL] =
			this[TIMERS_AGGREGATES_SYMBOL] || new Map();
		const current = this[TIMERS_AGGREGATES_SYMBOL].get(label);
		if (current !== undefined) {
			if (time[1] + current[1] > 1e9) {
				time[0] += current[0] + 1;
				time[1] = time[1] - 1e9 + current[1];
			} else {
				time[0] += current[0];
				time[1] += current[1];
			}
		}
		this[TIMERS_AGGREGATES_SYMBOL].set(label, time);
	}

	/**
	 * @param {string=} label label
	 */
	timeAggregateEnd(label) {
		if (this[TIMERS_AGGREGATES_SYMBOL] === undefined) return;
		const time = this[TIMERS_AGGREGATES_SYMBOL].get(label);
		if (time === undefined) return;
		this[TIMERS_AGGREGATES_SYMBOL].delete(label);
		this[LOG_SYMBOL](LogType.time, [label, ...time]);
	}
}

exports.Logger = WebpackLogger;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { LogType } = require("./Logger");

/** @typedef {import("../../declarations/WebpackOptions").FilterItemTypes} FilterItemTypes */
/** @typedef {import("../../declarations/WebpackOptions").FilterTypes} FilterTypes */
/** @typedef {import("./Logger").LogTypeEnum} LogTypeEnum */

/** @typedef {function(string): boolean} FilterFunction */
/** @typedef {function(string, LogTypeEnum, any[]): void} LoggingFunction */

/**
 * @typedef {object} LoggerConsole
 * @property {function(): void} clear
 * @property {function(): void} trace
 * @property {(...args: any[]) => void} info
 * @property {(...args: any[]) => void} log
 * @property {(...args: any[]) => void} warn
 * @property {(...args: any[]) => void} error
 * @property {(...args: any[]) => void=} debug
 * @property {(...args: any[]) => void=} group
 * @property {(...args: any[]) => void=} groupCollapsed
 * @property {(...args: any[]) => void=} groupEnd
 * @property {(...args: any[]) => void=} status
 * @property {(...args: any[]) => void=} profile
 * @property {(...args: any[]) => void=} profileEnd
 * @property {(...args: any[]) => void=} logTime
 */

/**
 * @typedef {object} LoggerOptions
 * @property {false|true|"none"|"error"|"warn"|"info"|"log"|"verbose"} level loglevel
 * @property {FilterTypes|boolean} debug filter for debug logging
 * @property {LoggerConsole} console the console to log to
 */

/**
 * @param {FilterItemTypes} item an input item
 * @returns {FilterFunction | undefined} filter function
 */
const filterToFunction = item => {
	if (typeof item === "string") {
		const regExp = new RegExp(
			`[\\\\/]${item.replace(/[-[\]{}()*+?.\\^$|]/g, "\\$&")}([\\\\/]|$|!|\\?)`
		);
		return ident => regExp.test(ident);
	}
	if (item && typeof item === "object" && typeof item.test === "function") {
		return ident => item.test(ident);
	}
	if (typeof item === "function") {
		return item;
	}
	if (typeof item === "boolean") {
		return () => item;
	}
};

/**
 * @enum {number}
 */
const LogLevel = {
	none: 6,
	false: 6,
	error: 5,
	warn: 4,
	info: 3,
	log: 2,
	true: 2,
	verbose: 1
};

/**
 * @param {LoggerOptions} options options object
 * @returns {LoggingFunction} logging function
 */
module.exports = ({ level = "info", debug = false, console }) => {
	const debugFilters =
		/** @type {FilterFunction[]} */
		(
			typeof debug === "boolean"
				? [() => debug]
				: /** @type {FilterItemTypes[]} */ ([])
						.concat(debug)
						.map(filterToFunction)
		);
	/** @type {number} */
	const loglevel = LogLevel[`${level}`] || 0;

	/**
	 * @param {string} name name of the logger
	 * @param {LogTypeEnum} type type of the log entry
	 * @param {any[]} args arguments of the log entry
	 * @returns {void}
	 */
	const logger = (name, type, args) => {
		const labeledArgs = () => {
			if (Array.isArray(args)) {
				if (args.length > 0 && typeof args[0] === "string") {
					return [`[${name}] ${args[0]}`, ...args.slice(1)];
				} else {
					return [`[${name}]`, ...args];
				}
			} else {
				return [];
			}
		};
		const debug = debugFilters.some(f => f(name));
		switch (type) {
			case LogType.debug:
				if (!debug) return;
				if (typeof console.debug === "function") {
					console.debug(...labeledArgs());
				} else {
					console.log(...labeledArgs());
				}
				break;
			case LogType.log:
				if (!debug && loglevel > LogLevel.log) return;
				console.log(...labeledArgs());
				break;
			case LogType.info:
				if (!debug && loglevel > LogLevel.info) return;
				console.info(...labeledArgs());
				break;
			case LogType.warn:
				if (!debug && loglevel > LogLevel.warn) return;
				console.warn(...labeledArgs());
				break;
			case LogType.error:
				if (!debug && loglevel > LogLevel.error) return;
				console.error(...labeledArgs());
				break;
			case LogType.trace:
				if (!debug) return;
				console.trace();
				break;
			case LogType.groupCollapsed:
				if (!debug && loglevel > LogLevel.log) return;
				if (!debug && loglevel > LogLevel.verbose) {
					if (typeof console.groupCollapsed === "function") {
						console.groupCollapsed(...labeledArgs());
					} else {
						console.log(...labeledArgs());
					}
					break;
				}
			// falls through
			case LogType.group:
				if (!debug && loglevel > LogLevel.log) return;
				if (typeof console.group === "function") {
					console.group(...labeledArgs());
				} else {
					console.log(...labeledArgs());
				}
				break;
			case LogType.groupEnd:
				if (!debug && loglevel > LogLevel.log) return;
				if (typeof console.groupEnd === "function") {
					console.groupEnd();
				}
				break;
			case LogType.time: {
				if (!debug && loglevel > LogLevel.log) return;
				const ms = args[1] * 1000 + args[2] / 1000000;
				const msg = `[${name}] ${args[0]}: ${ms} ms`;
				if (typeof console.logTime === "function") {
					console.logTime(msg);
				} else {
					console.log(msg);
				}
				break;
			}
			case LogType.profile:
				if (typeof console.profile === "function") {
					console.profile(...labeledArgs());
				}
				break;
			case LogType.profileEnd:
				if (typeof console.profileEnd === "function") {
					console.profileEnd(...labeledArgs());
				}
				break;
			case LogType.clear:
				if (!debug && loglevel > LogLevel.log) return;
				if (typeof console.clear === "function") {
					console.clear();
				}
				break;
			case LogType.status:
				if (!debug && loglevel > LogLevel.info) return;
				if (typeof console.status === "function") {
					if (args.length === 0) {
						console.status();
					} else {
						console.status(...labeledArgs());
					}
				} else {
					if (args.length !== 0) {
						console.info(...labeledArgs());
					}
				}
				break;
			default:
				throw new Error(`Unexpected LogType ${type}`);
		}
	};
	return logger;
};


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const { SyncBailHook } = require("tapable");
const { Logger } = require("./Logger");
const createConsoleLogger = require("./createConsoleLogger");

/** @type {createConsoleLogger.LoggerOptions} */
let currentDefaultLoggerOptions = {
	level: "info",
	debug: false,
	console
};
let currentDefaultLogger = createConsoleLogger(currentDefaultLoggerOptions);

/**
 * @param {string} name name of the logger
 * @returns {Logger} a logger
 */
exports.getLogger = name => {
	return new Logger(
		(type, args) => {
			if (exports.hooks.log.call(name, type, args) === undefined) {
				currentDefaultLogger(name, type, args);
			}
		},
		childName => exports.getLogger(`${name}/${childName}`)
	);
};

/**
 * @param {createConsoleLogger.LoggerOptions} options new options, merge with old options
 * @returns {void}
 */
exports.configureDefaultLogger = options => {
	Object.assign(currentDefaultLoggerOptions, options);
	currentDefaultLogger = createConsoleLogger(currentDefaultLoggerOptions);
};

exports.hooks = {
	log: new SyncBailHook(["origin", "type", "args"])
};


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

/**
 * @param {Array<number>} array array of numbers
 * @returns {number} sum of all numbers in array
 */
const arraySum = array => {
	let sum = 0;
	for (const item of array) sum += item;
	return sum;
};

/**
 * @param {any[]} args items to be truncated
 * @param {number} maxLength maximum length of args including spaces between
 * @returns {string[]} truncated args
 */
const truncateArgs = (args, maxLength) => {
	const lengths = args.map(a => `${a}`.length);
	const availableLength = maxLength - lengths.length + 1;

	if (availableLength > 0 && args.length === 1) {
		if (availableLength >= args[0].length) {
			return args;
		} else if (availableLength > 3) {
			return ["..." + args[0].slice(-availableLength + 3)];
		} else {
			return [args[0].slice(-availableLength)];
		}
	}

	// Check if there is space for at least 4 chars per arg
	if (availableLength < arraySum(lengths.map(i => Math.min(i, 6)))) {
		// remove args
		if (args.length > 1)
			return truncateArgs(args.slice(0, args.length - 1), maxLength);
		return [];
	}

	let currentLength = arraySum(lengths);

	// Check if all fits into maxLength
	if (currentLength <= availableLength) return args;

	// Try to remove chars from the longest items until it fits
	while (currentLength > availableLength) {
		const maxLength = Math.max(...lengths);
		const shorterItems = lengths.filter(l => l !== maxLength);
		const nextToMaxLength =
			shorterItems.length > 0 ? Math.max(...shorterItems) : 0;
		const maxReduce = maxLength - nextToMaxLength;
		let maxItems = lengths.length - shorterItems.length;
		let overrun = currentLength - availableLength;
		for (let i = 0; i < lengths.length; i++) {
			if (lengths[i] === maxLength) {
				const reduce = Math.min(Math.floor(overrun / maxItems), maxReduce);
				lengths[i] -= reduce;
				currentLength -= reduce;
				overrun -= reduce;
				maxItems--;
			}
		}
	}

	// Return args reduced to length in lengths
	return args.map((a, i) => {
		const str = `${a}`;
		const length = lengths[i];
		if (str.length === length) {
			return str;
		} else if (length > 5) {
			return "..." + str.slice(-length + 3);
		} else if (length > 0) {
			return str.slice(-length);
		} else {
			return "";
		}
	});
};

module.exports = truncateArgs;


code:
/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/

"use strict";

const RuntimeGlobals = require("../RuntimeGlobals");
const StartupChunkDependenciesPlugin = require("../runtime/StartupChunkDependenciesPlugin");

/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compiler")} Compiler */

/**
 * @typedef {object} CommonJsChunkLoadingPluginOptions
 * @property {boolean} [asyncChunkLoading] enable async chunk loading
 */

class CommonJsChunkLoadingPlugin {
	/**
	 * @param {CommonJsChunkLoadingPluginOptions} [options] options
	 */
	constructor(options = {}) {
		this._asyncChunkLoading = options.asyncChunkLoading;
	}

	/**
	 * Apply the plugin
	 * @param {Compiler} compiler the compiler instance
	 * @returns {void}
	 */
	apply(compiler) {
		const ChunkLoadingRuntimeModule = this._asyncChunkLoading
			? require("./ReadFileChunkLoadingRuntimeModule")
			: require("./RequireChunkLoadingRuntimeModule");
		const chunkLoadingValue = this._asyncChunkLoading
			? "async-node"
			: "require";
		new StartupChunkDependenciesPlugin({
			chunkLoading: chunkLoadingValue,
			asyncChunkLoading: this._asyncChunkLoading
		}).apply(compiler);
		compiler.hooks.thisCompilation.tap(
			"CommonJsChunkLoadingPlugin",
			compilation => {
				const globalChunkLoading = compilation.outputOptions.chunkLoading;
				/**
				 * @param {Chunk} chunk chunk
				 * @returns {boolean} true, if wasm loading is enabled for the chunk
				 */
				const isEnabledForChunk = chunk => {
					const options = chunk.getEntryOptions();
					const chunkLoading =
						options && options.chunkLoading !== undefined
							? options.chunkLoading
							: globalChunkLoading;
					return chunkLoading === chunkLoadingValue;
				};
				const onceForChunkSet = new WeakSet();
				/**
				 * @param {Chunk} chunk chunk
				 * @param {Set<string>} set runtime requirements
				 */
				const handler = (chunk, set) => {
					if (onceForChunkSet.has(chunk)) return;
					onceForChunkSet.add(chunk);
					if (!isEnabledForChunk(chunk)) return;
					set.add(RuntimeGlobals.moduleFactoriesAddOnly);
					set.add(RuntimeGlobals.hasOwnProperty);
					compilation.addRuntimeModule(
						chunk,
						new ChunkLoadingRuntimeModule(set)
					);
				};

				compilation.hooks.runtimeRequirementInTree
					.for(RuntimeGlobals.ensureChunkHandlers)
					.tap("CommonJsChunkLoadingPlugin", handler);
				compilation.hooks.runtimeRequirementInTree
					.for(RuntimeGlobals.hmrDownloadUpdateHandlers)
					.tap("CommonJsChunkLoadingPlugin", handler);
				compilation.hooks.runtimeRequirementInTree
					.for(RuntimeGlobals.hmrDownloadManifest)
					.tap("CommonJsChunkLoadingPlugin", handler);
				compilation.hooks.runtimeRequirementInTree
					.for(RuntimeGlobals.baseURI)
					.tap("CommonJsChunkLoadingPlugin", handler);
				compilation.hooks.runtimeRequirementInTree
					.for(RuntimeGlobals.externalInstallChunk)
					.tap("CommonJsChunkLoadingPlugin", handler);
				compilation.hooks.runtimeRequirementInTree
					.for(RuntimeGlobals.onChunksLoaded)
					.tap("CommonJsChunkLoadingPlugin", handler);

				compilation.hooks.runtimeRequirementInTree
					.for(RuntimeGlobals.ensureChunkHandlers)
					.tap("CommonJsChunkLoadingPlugin", (chunk, set) => {
						if (!isEnabledForChunk(chunk)) return;
						set.add(RuntimeGlobals.getChunkScriptFilename);
					});
				compilation.hooks.runtimeRequirementInTree
					.for(RuntimeGlobals.hmrDownloadUpdateHandlers)
					.tap("CommonJsChunkLoadingPlugin", (chunk, set) => {
						if (!isEnabledForChunk(chunk)) return;
						set.add(RuntimeGlobals.getChunkUpdateScriptFilename);
						set.add(RuntimeGlobals.moduleCache);
						set.add(RuntimeGlobals.hmrModuleData);
						set.add(RuntimeGlobals.moduleFactoriesAddOnly);
					});
				compilation.hooks.runtimeRequirementInTree
					.for(RuntimeGlobals.hmrDownloadManifest)
					.tap("CommonJsChunkLoadingPlugin", (chunk, set) => {
						if (!isEnabledForChunk(chunk)) return;
						set.add(RuntimeGlobals.getUpdateManifestFilename);
					});
			}
		);
	}
}

module.exports = CommonJsChunkLoadingPlugin;