webpack/lib/sharing/ConsumeSharedRuntimeModule.js

333 lines
12 KiB
JavaScript
Raw Normal View History

2020-05-26 05:14:19 +08:00
/*
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");
2020-05-26 05:14:19 +08:00
/** @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;
2020-05-26 05:14:19 +08:00
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",
2020-05-27 21:10:57 +08:00
[
`return "Unsatisfied version " + version + " of shared singleton module " + key + " (required " + rangeToString(requiredVersion) + ")"`
2020-05-27 21:10:57 +08:00
]
)};`,
`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",
2020-05-27 03:40:19 +08:00
[
"var version = findSingletonVersionKey(scope, key);",
"if (!satisfy(requiredVersion, version)) " +
"throw new Error(getInvalidSingletonVersionMessage(key, version, requiredVersion));",
"return get(scope[key][version]);"
2020-05-27 03:40:19 +08:00
]
)};`,
`var findValidVersion = ${runtimeTemplate.basicFunction(
"scope, key, requiredVersion",
2020-05-27 03:40:19 +08:00
[
"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]"
2020-05-27 03:40:19 +08:00
]
)};`,
`var getInvalidVersionMessage = ${runtimeTemplate.basicFunction(
"scope, scopeName, key, requiredVersion",
2020-05-27 21:10:57 +08:00
[
"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(", ");`
2020-05-27 21:10:57 +08:00
]
)};`,
`var getValidVersion = ${runtimeTemplate.basicFunction(
"scope, scopeName, key, requiredVersion",
2020-05-27 03:40:19 +08:00
[
"var entry = findValidVersion(scope, key, requiredVersion);",
"if(entry) return get(entry);",
"throw new Error(getInvalidVersionMessage(scope, scopeName, key, requiredVersion));"
2020-05-27 03:40:19 +08:00
]
)};`,
`var warnInvalidVersion = ${runtimeTemplate.basicFunction(
"scope, scopeName, key, requiredVersion",
2020-05-27 21:10:57 +08:00
[
'typeof console !== "undefined" && console.warn && console.warn(getInvalidVersionMessage(scope, scopeName, key, requiredVersion));'
2020-05-27 21:10:57 +08:00
]
)};`,
`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",
2020-05-27 03:40:19 +08:00
[
`if(!scope || !${RuntimeGlobals.hasOwnProperty}(scope, key)) return fallback();`,
"return get(findValidVersion(scope, key, version) || warnInvalidVersion(scope, scopeName, key, version) || findVersion(scope, key));"
2020-05-27 03:40:19 +08:00
]
)});`,
`var loadSingletonVersionCheckFallback = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
"scopeName, scope, key, version, fallback",
2020-05-27 21:10:57 +08:00
[
`if(!scope || !${RuntimeGlobals.hasOwnProperty}(scope, key)) return fallback();`,
"return getSingletonVersion(scope, scopeName, key, version);"
2020-05-27 21:10:57 +08:00
]
)});`,
`var loadStrictVersionCheckFallback = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
"scopeName, scope, key, version, fallback",
2020-05-27 03:40:19 +08:00
[
`var entry = scope && ${RuntimeGlobals.hasOwnProperty}(scope, key) && findValidVersion(scope, key, version);`,
`return entry ? get(entry) : fallback();`
2020-05-27 03:40:19 +08:00
]
)});`,
`var loadStrictSingletonVersionCheckFallback = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
"scopeName, scope, key, version, fallback",
2020-05-27 21:10:57 +08:00
[
`if(!scope || !${RuntimeGlobals.hasOwnProperty}(scope, key)) return fallback();`,
"return getStrictSingletonVersion(scope, scopeName, key, version);"
2020-05-27 21:10:57 +08:00
]
)});`,
2020-05-26 05:14:19 +08:00
"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",
[
2020-05-26 05:14:19 +08:00
"// 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);',
2020-05-26 05:14:19 +08:00
`module.exports = factory();`
]
)}`
2020-05-26 05:14:19 +08:00
])});`
])
: "// 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;