mirror of https://github.com/webpack/webpack.git
				
				
				
			
		
			
				
	
	
		
			333 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			333 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
/*
 | 
						|
	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
						|
	Author Tobias Koppers @sokra
 | 
						|
*/
 | 
						|
 | 
						|
"use strict";
 | 
						|
 | 
						|
const RuntimeGlobals = require("../RuntimeGlobals");
 | 
						|
const RuntimeModule = require("../RuntimeModule");
 | 
						|
const Template = require("../Template");
 | 
						|
const {
 | 
						|
	parseVersionRuntimeCode,
 | 
						|
	versionLtRuntimeCode,
 | 
						|
	rangeToStringRuntimeCode,
 | 
						|
	satisfyRuntimeCode
 | 
						|
} = require("../util/semver");
 | 
						|
 | 
						|
/** @typedef {import("./ConsumeSharedModule")} ConsumeSharedModule */
 | 
						|
 | 
						|
class ConsumeSharedRuntimeModule extends RuntimeModule {
 | 
						|
	constructor(runtimeRequirements) {
 | 
						|
		super("consumes", 10);
 | 
						|
		this._runtimeRequirements = runtimeRequirements;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * @returns {string} runtime code
 | 
						|
	 */
 | 
						|
	generate() {
 | 
						|
		const {
 | 
						|
			runtimeTemplate,
 | 
						|
			chunkGraph,
 | 
						|
			codeGenerationResults
 | 
						|
		} = this.compilation;
 | 
						|
		const chunkToModuleMapping = {};
 | 
						|
		const idToModuleMapping = new Map();
 | 
						|
		const initialConsumes = [];
 | 
						|
		for (const chunk of this.chunk.getAllAsyncChunks()) {
 | 
						|
			const modules = chunkGraph.getChunkModulesIterableBySourceType(
 | 
						|
				chunk,
 | 
						|
				"consume-shared"
 | 
						|
			);
 | 
						|
			if (!modules) continue;
 | 
						|
			const consumes = (chunkToModuleMapping[chunk.id] = []);
 | 
						|
			for (const m of modules) {
 | 
						|
				const module = /** @type {ConsumeSharedModule} */ (m);
 | 
						|
				const id = chunkGraph.getModuleId(module);
 | 
						|
				consumes.push(id);
 | 
						|
				idToModuleMapping.set(id, module);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		for (const chunk of this.chunk.getAllInitialChunks()) {
 | 
						|
			const modules = chunkGraph.getChunkModulesIterableBySourceType(
 | 
						|
				chunk,
 | 
						|
				"consume-shared"
 | 
						|
			);
 | 
						|
			if (!modules) continue;
 | 
						|
			for (const m of modules) {
 | 
						|
				const module = /** @type {ConsumeSharedModule} */ (m);
 | 
						|
				const id = chunkGraph.getModuleId(module);
 | 
						|
				initialConsumes.push(id);
 | 
						|
				idToModuleMapping.set(id, module);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if (idToModuleMapping.size === 0) return null;
 | 
						|
		return Template.asString([
 | 
						|
			parseVersionRuntimeCode(runtimeTemplate),
 | 
						|
			versionLtRuntimeCode(runtimeTemplate),
 | 
						|
			rangeToStringRuntimeCode(runtimeTemplate),
 | 
						|
			satisfyRuntimeCode(runtimeTemplate),
 | 
						|
			`var ensureExistence = ${runtimeTemplate.basicFunction("scopeName, key", [
 | 
						|
				`var scope = ${RuntimeGlobals.shareScopeMap}[scopeName];`,
 | 
						|
				`if(!scope || !${RuntimeGlobals.hasOwnProperty}(scope, key)) throw new Error("Shared module " + key + " doesn't exist in shared scope " + scopeName);`,
 | 
						|
				"return scope;"
 | 
						|
			])};`,
 | 
						|
			`var findVersion = ${runtimeTemplate.basicFunction("scope, key", [
 | 
						|
				"var versions = scope[key];",
 | 
						|
				`var key = Object.keys(versions).reduce(${runtimeTemplate.basicFunction(
 | 
						|
					"a, b",
 | 
						|
					["return !a || versionLt(a, b) ? b : a;"]
 | 
						|
				)}, 0);`,
 | 
						|
				"return key && versions[key]"
 | 
						|
			])};`,
 | 
						|
			`var findSingletonVersionKey = ${runtimeTemplate.basicFunction(
 | 
						|
				"scope, key",
 | 
						|
				[
 | 
						|
					"var versions = scope[key];",
 | 
						|
					`return Object.keys(versions).reduce(${runtimeTemplate.basicFunction(
 | 
						|
						"a, b",
 | 
						|
						["return !a || (!versions[a].loaded && versionLt(a, b)) ? b : a;"]
 | 
						|
					)}, 0);`
 | 
						|
				]
 | 
						|
			)};`,
 | 
						|
			`var getInvalidSingletonVersionMessage = ${runtimeTemplate.basicFunction(
 | 
						|
				"key, version, requiredVersion",
 | 
						|
				[
 | 
						|
					`return "Unsatisfied version " + version + " of shared singleton module " + key + " (required " + rangeToString(requiredVersion) + ")"`
 | 
						|
				]
 | 
						|
			)};`,
 | 
						|
			`var getSingletonVersion = ${runtimeTemplate.basicFunction(
 | 
						|
				"scope, scopeName, key, requiredVersion",
 | 
						|
				[
 | 
						|
					"var version = findSingletonVersionKey(scope, key);",
 | 
						|
					"if (!satisfy(requiredVersion, version)) " +
 | 
						|
						'typeof console !== "undefined" && console.warn && console.warn(getInvalidSingletonVersionMessage(key, version, requiredVersion));',
 | 
						|
					"return get(scope[key][version]);"
 | 
						|
				]
 | 
						|
			)};`,
 | 
						|
			`var getStrictSingletonVersion = ${runtimeTemplate.basicFunction(
 | 
						|
				"scope, scopeName, key, requiredVersion",
 | 
						|
				[
 | 
						|
					"var version = findSingletonVersionKey(scope, key);",
 | 
						|
					"if (!satisfy(requiredVersion, version)) " +
 | 
						|
						"throw new Error(getInvalidSingletonVersionMessage(key, version, requiredVersion));",
 | 
						|
					"return get(scope[key][version]);"
 | 
						|
				]
 | 
						|
			)};`,
 | 
						|
			`var findValidVersion = ${runtimeTemplate.basicFunction(
 | 
						|
				"scope, key, requiredVersion",
 | 
						|
				[
 | 
						|
					"var versions = scope[key];",
 | 
						|
					`var key = Object.keys(versions).reduce(${runtimeTemplate.basicFunction(
 | 
						|
						"a, b",
 | 
						|
						[
 | 
						|
							"if (!satisfy(requiredVersion, b)) return a;",
 | 
						|
							"return !a || versionLt(a, b) ? b : a;"
 | 
						|
						]
 | 
						|
					)}, 0);`,
 | 
						|
					"return key && versions[key]"
 | 
						|
				]
 | 
						|
			)};`,
 | 
						|
			`var getInvalidVersionMessage = ${runtimeTemplate.basicFunction(
 | 
						|
				"scope, scopeName, key, requiredVersion",
 | 
						|
				[
 | 
						|
					"var versions = scope[key];",
 | 
						|
					'return "No satisfying version (" + rangeToString(requiredVersion) + ") of shared module " + key + " found in shared scope " + scopeName + ".\\n" +',
 | 
						|
					`\t"Available versions: " + Object.keys(versions).map(${runtimeTemplate.basicFunction(
 | 
						|
						"key",
 | 
						|
						['return key + " from " + versions[key].from;']
 | 
						|
					)}).join(", ");`
 | 
						|
				]
 | 
						|
			)};`,
 | 
						|
			`var getValidVersion = ${runtimeTemplate.basicFunction(
 | 
						|
				"scope, scopeName, key, requiredVersion",
 | 
						|
				[
 | 
						|
					"var entry = findValidVersion(scope, key, requiredVersion);",
 | 
						|
					"if(entry) return get(entry);",
 | 
						|
					"throw new Error(getInvalidVersionMessage(scope, scopeName, key, requiredVersion));"
 | 
						|
				]
 | 
						|
			)};`,
 | 
						|
			`var warnInvalidVersion = ${runtimeTemplate.basicFunction(
 | 
						|
				"scope, scopeName, key, requiredVersion",
 | 
						|
				[
 | 
						|
					'typeof console !== "undefined" && console.warn && console.warn(getInvalidVersionMessage(scope, scopeName, key, requiredVersion));'
 | 
						|
				]
 | 
						|
			)};`,
 | 
						|
			`var get = ${runtimeTemplate.basicFunction("entry", [
 | 
						|
				"entry.loaded = 1;",
 | 
						|
				"return entry.get()"
 | 
						|
			])};`,
 | 
						|
			`var init = ${runtimeTemplate.returningFunction(
 | 
						|
				Template.asString([
 | 
						|
					"function(scopeName, a, b, c) {",
 | 
						|
					Template.indent([
 | 
						|
						`var promise = ${RuntimeGlobals.initializeSharing}(scopeName);`,
 | 
						|
						`if (promise.then) return promise.then(fn.bind(fn, scopeName, ${RuntimeGlobals.shareScopeMap}[scopeName], a, b, c));`,
 | 
						|
						`return fn(scopeName, ${RuntimeGlobals.shareScopeMap}[scopeName], a, b, c);`
 | 
						|
					]),
 | 
						|
					"}"
 | 
						|
				]),
 | 
						|
				"fn"
 | 
						|
			)};`,
 | 
						|
			"",
 | 
						|
			`var load = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
 | 
						|
				"scopeName, scope, key",
 | 
						|
				[
 | 
						|
					"ensureExistence(scopeName, key);",
 | 
						|
					"return get(findVersion(scope, key));"
 | 
						|
				]
 | 
						|
			)});`,
 | 
						|
			`var loadFallback = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
 | 
						|
				"scopeName, scope, key, fallback",
 | 
						|
				[
 | 
						|
					`return scope && ${RuntimeGlobals.hasOwnProperty}(scope, key) ? get(findVersion(scope, key)) : fallback();`
 | 
						|
				]
 | 
						|
			)});`,
 | 
						|
			`var loadVersionCheck = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
 | 
						|
				"scopeName, scope, key, version",
 | 
						|
				[
 | 
						|
					"ensureExistence(scopeName, key);",
 | 
						|
					"return get(findValidVersion(scope, key, version) || warnInvalidVersion(scope, scopeName, key, version) || findVersion(scope, key));"
 | 
						|
				]
 | 
						|
			)});`,
 | 
						|
			`var loadSingletonVersionCheck = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
 | 
						|
				"scopeName, scope, key, version",
 | 
						|
				[
 | 
						|
					"ensureExistence(scopeName, key);",
 | 
						|
					"return getSingletonVersion(scope, scopeName, key, version);"
 | 
						|
				]
 | 
						|
			)});`,
 | 
						|
			`var loadStrictVersionCheck = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
 | 
						|
				"scopeName, scope, key, version",
 | 
						|
				[
 | 
						|
					"ensureExistence(scopeName, key);",
 | 
						|
					"return getValidVersion(scope, scopeName, key, version);"
 | 
						|
				]
 | 
						|
			)});`,
 | 
						|
			`var loadStrictSingletonVersionCheck = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
 | 
						|
				"scopeName, scope, key, version",
 | 
						|
				[
 | 
						|
					"ensureExistence(scopeName, key);",
 | 
						|
					"return getStrictSingletonVersion(scope, scopeName, key, version);"
 | 
						|
				]
 | 
						|
			)});`,
 | 
						|
			`var loadVersionCheckFallback = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
 | 
						|
				"scopeName, scope, key, version, fallback",
 | 
						|
				[
 | 
						|
					`if(!scope || !${RuntimeGlobals.hasOwnProperty}(scope, key)) return fallback();`,
 | 
						|
					"return get(findValidVersion(scope, key, version) || warnInvalidVersion(scope, scopeName, key, version) || findVersion(scope, key));"
 | 
						|
				]
 | 
						|
			)});`,
 | 
						|
			`var loadSingletonVersionCheckFallback = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
 | 
						|
				"scopeName, scope, key, version, fallback",
 | 
						|
				[
 | 
						|
					`if(!scope || !${RuntimeGlobals.hasOwnProperty}(scope, key)) return fallback();`,
 | 
						|
					"return getSingletonVersion(scope, scopeName, key, version);"
 | 
						|
				]
 | 
						|
			)});`,
 | 
						|
			`var loadStrictVersionCheckFallback = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
 | 
						|
				"scopeName, scope, key, version, fallback",
 | 
						|
				[
 | 
						|
					`var entry = scope && ${RuntimeGlobals.hasOwnProperty}(scope, key) && findValidVersion(scope, key, version);`,
 | 
						|
					`return entry ? get(entry) : fallback();`
 | 
						|
				]
 | 
						|
			)});`,
 | 
						|
			`var loadStrictSingletonVersionCheckFallback = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
 | 
						|
				"scopeName, scope, key, version, fallback",
 | 
						|
				[
 | 
						|
					`if(!scope || !${RuntimeGlobals.hasOwnProperty}(scope, key)) return fallback();`,
 | 
						|
					"return getStrictSingletonVersion(scope, scopeName, key, version);"
 | 
						|
				]
 | 
						|
			)});`,
 | 
						|
			"var installedModules = {};",
 | 
						|
			"var moduleToHandlerMapping = {",
 | 
						|
			Template.indent(
 | 
						|
				Array.from(
 | 
						|
					idToModuleMapping,
 | 
						|
					([key, module]) =>
 | 
						|
						`${JSON.stringify(key)}: ${codeGenerationResults
 | 
						|
							.get(module)
 | 
						|
							.sources.get("consume-shared")
 | 
						|
							.source()}`
 | 
						|
				).join(",\n")
 | 
						|
			),
 | 
						|
			"};",
 | 
						|
 | 
						|
			initialConsumes.length > 0
 | 
						|
				? Template.asString([
 | 
						|
						`var initialConsumes = ${JSON.stringify(initialConsumes)};`,
 | 
						|
						`initialConsumes.forEach(${runtimeTemplate.basicFunction("id", [
 | 
						|
							`__webpack_modules__[id] = ${runtimeTemplate.basicFunction(
 | 
						|
								"module",
 | 
						|
								[
 | 
						|
									"// Handle case when module is used sync",
 | 
						|
									"installedModules[id] = 0;",
 | 
						|
									"delete __webpack_module_cache__[id];",
 | 
						|
									"var factory = moduleToHandlerMapping[id]();",
 | 
						|
									'if(typeof factory !== "function") throw new Error("Shared module is not available for eager consumption: " + id);',
 | 
						|
									`module.exports = factory();`
 | 
						|
								]
 | 
						|
							)}`
 | 
						|
						])});`
 | 
						|
				  ])
 | 
						|
				: "// no consumes in initial chunks",
 | 
						|
			this._runtimeRequirements.has(RuntimeGlobals.ensureChunkHandlers)
 | 
						|
				? Template.asString([
 | 
						|
						`var chunkMapping = ${JSON.stringify(
 | 
						|
							chunkToModuleMapping,
 | 
						|
							null,
 | 
						|
							"\t"
 | 
						|
						)};`,
 | 
						|
						`${
 | 
						|
							RuntimeGlobals.ensureChunkHandlers
 | 
						|
						}.consumes = ${runtimeTemplate.basicFunction("chunkId, promises", [
 | 
						|
							`if(${RuntimeGlobals.hasOwnProperty}(chunkMapping, chunkId)) {`,
 | 
						|
							Template.indent([
 | 
						|
								`chunkMapping[chunkId].forEach(${runtimeTemplate.basicFunction(
 | 
						|
									"id",
 | 
						|
									[
 | 
						|
										`if(${RuntimeGlobals.hasOwnProperty}(installedModules, id)) return promises.push(installedModules[id]);`,
 | 
						|
										`var onFactory = ${runtimeTemplate.basicFunction(
 | 
						|
											"factory",
 | 
						|
											[
 | 
						|
												"installedModules[id] = 0;",
 | 
						|
												`__webpack_modules__[id] = ${runtimeTemplate.basicFunction(
 | 
						|
													"module",
 | 
						|
													[
 | 
						|
														"delete __webpack_module_cache__[id];",
 | 
						|
														"module.exports = factory();"
 | 
						|
													]
 | 
						|
												)}`
 | 
						|
											]
 | 
						|
										)};`,
 | 
						|
										`var onError = ${runtimeTemplate.basicFunction("error", [
 | 
						|
											"delete installedModules[id];",
 | 
						|
											`__webpack_modules__[id] = ${runtimeTemplate.basicFunction(
 | 
						|
												"module",
 | 
						|
												["delete __webpack_module_cache__[id];", "throw error;"]
 | 
						|
											)}`
 | 
						|
										])};`,
 | 
						|
										"try {",
 | 
						|
										Template.indent([
 | 
						|
											"var promise = moduleToHandlerMapping[id]();",
 | 
						|
											"if(promise.then) {",
 | 
						|
											Template.indent(
 | 
						|
												`promises.push(installedModules[id] = promise.then(onFactory).catch(onError));`
 | 
						|
											),
 | 
						|
											"} else onFactory(promise);"
 | 
						|
										]),
 | 
						|
										"} catch(e) { onError(e); }"
 | 
						|
									]
 | 
						|
								)});`
 | 
						|
							]),
 | 
						|
							"}"
 | 
						|
						])}`
 | 
						|
				  ])
 | 
						|
				: "// no chunk loading of consumes"
 | 
						|
		]);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
module.exports = ConsumeSharedRuntimeModule;
 |