[6a3a178] | 1 | /*
|
---|
| 2 | MIT License http://www.opensource.org/licenses/mit-license.php
|
---|
| 3 | Author Tobias Koppers @sokra
|
---|
| 4 | */
|
---|
| 5 |
|
---|
| 6 | "use strict";
|
---|
| 7 |
|
---|
| 8 | const RuntimeGlobals = require("../RuntimeGlobals");
|
---|
| 9 | const RuntimeModule = require("../RuntimeModule");
|
---|
| 10 | const Template = require("../Template");
|
---|
| 11 | const {
|
---|
| 12 | parseVersionRuntimeCode,
|
---|
| 13 | versionLtRuntimeCode,
|
---|
| 14 | rangeToStringRuntimeCode,
|
---|
| 15 | satisfyRuntimeCode
|
---|
| 16 | } = require("../util/semver");
|
---|
| 17 |
|
---|
| 18 | /** @typedef {import("webpack-sources").Source} Source */
|
---|
| 19 | /** @typedef {import("../Chunk")} Chunk */
|
---|
| 20 | /** @typedef {import("../Module")} Module */
|
---|
| 21 | /** @typedef {import("./ConsumeSharedModule")} ConsumeSharedModule */
|
---|
| 22 |
|
---|
| 23 | class ConsumeSharedRuntimeModule extends RuntimeModule {
|
---|
| 24 | constructor(runtimeRequirements) {
|
---|
| 25 | super("consumes", RuntimeModule.STAGE_ATTACH);
|
---|
| 26 | this._runtimeRequirements = runtimeRequirements;
|
---|
| 27 | }
|
---|
| 28 |
|
---|
| 29 | /**
|
---|
| 30 | * @returns {string} runtime code
|
---|
| 31 | */
|
---|
| 32 | generate() {
|
---|
| 33 | const { compilation, chunkGraph } = this;
|
---|
| 34 | const { runtimeTemplate, codeGenerationResults } = compilation;
|
---|
| 35 | const chunkToModuleMapping = {};
|
---|
| 36 | /** @type {Map<string | number, Source>} */
|
---|
| 37 | const moduleIdToSourceMapping = new Map();
|
---|
| 38 | const initialConsumes = [];
|
---|
| 39 | /**
|
---|
| 40 | *
|
---|
| 41 | * @param {Iterable<Module>} modules modules
|
---|
| 42 | * @param {Chunk} chunk the chunk
|
---|
| 43 | * @param {(string | number)[]} list list of ids
|
---|
| 44 | */
|
---|
| 45 | const addModules = (modules, chunk, list) => {
|
---|
| 46 | for (const m of modules) {
|
---|
| 47 | const module = /** @type {ConsumeSharedModule} */ (m);
|
---|
| 48 | const id = chunkGraph.getModuleId(module);
|
---|
| 49 | list.push(id);
|
---|
| 50 | moduleIdToSourceMapping.set(
|
---|
| 51 | id,
|
---|
| 52 | codeGenerationResults.getSource(
|
---|
| 53 | module,
|
---|
| 54 | chunk.runtime,
|
---|
| 55 | "consume-shared"
|
---|
| 56 | )
|
---|
| 57 | );
|
---|
| 58 | }
|
---|
| 59 | };
|
---|
| 60 | for (const chunk of this.chunk.getAllAsyncChunks()) {
|
---|
| 61 | const modules = chunkGraph.getChunkModulesIterableBySourceType(
|
---|
| 62 | chunk,
|
---|
| 63 | "consume-shared"
|
---|
| 64 | );
|
---|
| 65 | if (!modules) continue;
|
---|
| 66 | addModules(modules, chunk, (chunkToModuleMapping[chunk.id] = []));
|
---|
| 67 | }
|
---|
| 68 | for (const chunk of this.chunk.getAllInitialChunks()) {
|
---|
| 69 | const modules = chunkGraph.getChunkModulesIterableBySourceType(
|
---|
| 70 | chunk,
|
---|
| 71 | "consume-shared"
|
---|
| 72 | );
|
---|
| 73 | if (!modules) continue;
|
---|
| 74 | addModules(modules, chunk, initialConsumes);
|
---|
| 75 | }
|
---|
| 76 | if (moduleIdToSourceMapping.size === 0) return null;
|
---|
| 77 | return Template.asString([
|
---|
| 78 | parseVersionRuntimeCode(runtimeTemplate),
|
---|
| 79 | versionLtRuntimeCode(runtimeTemplate),
|
---|
| 80 | rangeToStringRuntimeCode(runtimeTemplate),
|
---|
| 81 | satisfyRuntimeCode(runtimeTemplate),
|
---|
| 82 | `var ensureExistence = ${runtimeTemplate.basicFunction("scopeName, key", [
|
---|
| 83 | `var scope = ${RuntimeGlobals.shareScopeMap}[scopeName];`,
|
---|
| 84 | `if(!scope || !${RuntimeGlobals.hasOwnProperty}(scope, key)) throw new Error("Shared module " + key + " doesn't exist in shared scope " + scopeName);`,
|
---|
| 85 | "return scope;"
|
---|
| 86 | ])};`,
|
---|
| 87 | `var findVersion = ${runtimeTemplate.basicFunction("scope, key", [
|
---|
| 88 | "var versions = scope[key];",
|
---|
| 89 | `var key = Object.keys(versions).reduce(${runtimeTemplate.basicFunction(
|
---|
| 90 | "a, b",
|
---|
| 91 | ["return !a || versionLt(a, b) ? b : a;"]
|
---|
| 92 | )}, 0);`,
|
---|
| 93 | "return key && versions[key]"
|
---|
| 94 | ])};`,
|
---|
| 95 | `var findSingletonVersionKey = ${runtimeTemplate.basicFunction(
|
---|
| 96 | "scope, key",
|
---|
| 97 | [
|
---|
| 98 | "var versions = scope[key];",
|
---|
| 99 | `return Object.keys(versions).reduce(${runtimeTemplate.basicFunction(
|
---|
| 100 | "a, b",
|
---|
| 101 | ["return !a || (!versions[a].loaded && versionLt(a, b)) ? b : a;"]
|
---|
| 102 | )}, 0);`
|
---|
| 103 | ]
|
---|
| 104 | )};`,
|
---|
| 105 | `var getInvalidSingletonVersionMessage = ${runtimeTemplate.basicFunction(
|
---|
| 106 | "key, version, requiredVersion",
|
---|
| 107 | [
|
---|
| 108 | `return "Unsatisfied version " + version + " of shared singleton module " + key + " (required " + rangeToString(requiredVersion) + ")"`
|
---|
| 109 | ]
|
---|
| 110 | )};`,
|
---|
| 111 | `var getSingletonVersion = ${runtimeTemplate.basicFunction(
|
---|
| 112 | "scope, scopeName, key, requiredVersion",
|
---|
| 113 | [
|
---|
| 114 | "var version = findSingletonVersionKey(scope, key);",
|
---|
| 115 | "if (!satisfy(requiredVersion, version)) " +
|
---|
| 116 | 'typeof console !== "undefined" && console.warn && console.warn(getInvalidSingletonVersionMessage(key, version, requiredVersion));',
|
---|
| 117 | "return get(scope[key][version]);"
|
---|
| 118 | ]
|
---|
| 119 | )};`,
|
---|
| 120 | `var getStrictSingletonVersion = ${runtimeTemplate.basicFunction(
|
---|
| 121 | "scope, scopeName, key, requiredVersion",
|
---|
| 122 | [
|
---|
| 123 | "var version = findSingletonVersionKey(scope, key);",
|
---|
| 124 | "if (!satisfy(requiredVersion, version)) " +
|
---|
| 125 | "throw new Error(getInvalidSingletonVersionMessage(key, version, requiredVersion));",
|
---|
| 126 | "return get(scope[key][version]);"
|
---|
| 127 | ]
|
---|
| 128 | )};`,
|
---|
| 129 | `var findValidVersion = ${runtimeTemplate.basicFunction(
|
---|
| 130 | "scope, key, requiredVersion",
|
---|
| 131 | [
|
---|
| 132 | "var versions = scope[key];",
|
---|
| 133 | `var key = Object.keys(versions).reduce(${runtimeTemplate.basicFunction(
|
---|
| 134 | "a, b",
|
---|
| 135 | [
|
---|
| 136 | "if (!satisfy(requiredVersion, b)) return a;",
|
---|
| 137 | "return !a || versionLt(a, b) ? b : a;"
|
---|
| 138 | ]
|
---|
| 139 | )}, 0);`,
|
---|
| 140 | "return key && versions[key]"
|
---|
| 141 | ]
|
---|
| 142 | )};`,
|
---|
| 143 | `var getInvalidVersionMessage = ${runtimeTemplate.basicFunction(
|
---|
| 144 | "scope, scopeName, key, requiredVersion",
|
---|
| 145 | [
|
---|
| 146 | "var versions = scope[key];",
|
---|
| 147 | 'return "No satisfying version (" + rangeToString(requiredVersion) + ") of shared module " + key + " found in shared scope " + scopeName + ".\\n" +',
|
---|
| 148 | `\t"Available versions: " + Object.keys(versions).map(${runtimeTemplate.basicFunction(
|
---|
| 149 | "key",
|
---|
| 150 | ['return key + " from " + versions[key].from;']
|
---|
| 151 | )}).join(", ");`
|
---|
| 152 | ]
|
---|
| 153 | )};`,
|
---|
| 154 | `var getValidVersion = ${runtimeTemplate.basicFunction(
|
---|
| 155 | "scope, scopeName, key, requiredVersion",
|
---|
| 156 | [
|
---|
| 157 | "var entry = findValidVersion(scope, key, requiredVersion);",
|
---|
| 158 | "if(entry) return get(entry);",
|
---|
| 159 | "throw new Error(getInvalidVersionMessage(scope, scopeName, key, requiredVersion));"
|
---|
| 160 | ]
|
---|
| 161 | )};`,
|
---|
| 162 | `var warnInvalidVersion = ${runtimeTemplate.basicFunction(
|
---|
| 163 | "scope, scopeName, key, requiredVersion",
|
---|
| 164 | [
|
---|
| 165 | 'typeof console !== "undefined" && console.warn && console.warn(getInvalidVersionMessage(scope, scopeName, key, requiredVersion));'
|
---|
| 166 | ]
|
---|
| 167 | )};`,
|
---|
| 168 | `var get = ${runtimeTemplate.basicFunction("entry", [
|
---|
| 169 | "entry.loaded = 1;",
|
---|
| 170 | "return entry.get()"
|
---|
| 171 | ])};`,
|
---|
| 172 | `var init = ${runtimeTemplate.returningFunction(
|
---|
| 173 | Template.asString([
|
---|
| 174 | "function(scopeName, a, b, c) {",
|
---|
| 175 | Template.indent([
|
---|
| 176 | `var promise = ${RuntimeGlobals.initializeSharing}(scopeName);`,
|
---|
| 177 | `if (promise && promise.then) return promise.then(fn.bind(fn, scopeName, ${RuntimeGlobals.shareScopeMap}[scopeName], a, b, c));`,
|
---|
| 178 | `return fn(scopeName, ${RuntimeGlobals.shareScopeMap}[scopeName], a, b, c);`
|
---|
| 179 | ]),
|
---|
| 180 | "}"
|
---|
| 181 | ]),
|
---|
| 182 | "fn"
|
---|
| 183 | )};`,
|
---|
| 184 | "",
|
---|
| 185 | `var load = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
|
---|
| 186 | "scopeName, scope, key",
|
---|
| 187 | [
|
---|
| 188 | "ensureExistence(scopeName, key);",
|
---|
| 189 | "return get(findVersion(scope, key));"
|
---|
| 190 | ]
|
---|
| 191 | )});`,
|
---|
| 192 | `var loadFallback = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
|
---|
| 193 | "scopeName, scope, key, fallback",
|
---|
| 194 | [
|
---|
| 195 | `return scope && ${RuntimeGlobals.hasOwnProperty}(scope, key) ? get(findVersion(scope, key)) : fallback();`
|
---|
| 196 | ]
|
---|
| 197 | )});`,
|
---|
| 198 | `var loadVersionCheck = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
|
---|
| 199 | "scopeName, scope, key, version",
|
---|
| 200 | [
|
---|
| 201 | "ensureExistence(scopeName, key);",
|
---|
| 202 | "return get(findValidVersion(scope, key, version) || warnInvalidVersion(scope, scopeName, key, version) || findVersion(scope, key));"
|
---|
| 203 | ]
|
---|
| 204 | )});`,
|
---|
| 205 | `var loadSingletonVersionCheck = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
|
---|
| 206 | "scopeName, scope, key, version",
|
---|
| 207 | [
|
---|
| 208 | "ensureExistence(scopeName, key);",
|
---|
| 209 | "return getSingletonVersion(scope, scopeName, key, version);"
|
---|
| 210 | ]
|
---|
| 211 | )});`,
|
---|
| 212 | `var loadStrictVersionCheck = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
|
---|
| 213 | "scopeName, scope, key, version",
|
---|
| 214 | [
|
---|
| 215 | "ensureExistence(scopeName, key);",
|
---|
| 216 | "return getValidVersion(scope, scopeName, key, version);"
|
---|
| 217 | ]
|
---|
| 218 | )});`,
|
---|
| 219 | `var loadStrictSingletonVersionCheck = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
|
---|
| 220 | "scopeName, scope, key, version",
|
---|
| 221 | [
|
---|
| 222 | "ensureExistence(scopeName, key);",
|
---|
| 223 | "return getStrictSingletonVersion(scope, scopeName, key, version);"
|
---|
| 224 | ]
|
---|
| 225 | )});`,
|
---|
| 226 | `var loadVersionCheckFallback = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
|
---|
| 227 | "scopeName, scope, key, version, fallback",
|
---|
| 228 | [
|
---|
| 229 | `if(!scope || !${RuntimeGlobals.hasOwnProperty}(scope, key)) return fallback();`,
|
---|
| 230 | "return get(findValidVersion(scope, key, version) || warnInvalidVersion(scope, scopeName, key, version) || findVersion(scope, key));"
|
---|
| 231 | ]
|
---|
| 232 | )});`,
|
---|
| 233 | `var loadSingletonVersionCheckFallback = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
|
---|
| 234 | "scopeName, scope, key, version, fallback",
|
---|
| 235 | [
|
---|
| 236 | `if(!scope || !${RuntimeGlobals.hasOwnProperty}(scope, key)) return fallback();`,
|
---|
| 237 | "return getSingletonVersion(scope, scopeName, key, version);"
|
---|
| 238 | ]
|
---|
| 239 | )});`,
|
---|
| 240 | `var loadStrictVersionCheckFallback = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
|
---|
| 241 | "scopeName, scope, key, version, fallback",
|
---|
| 242 | [
|
---|
| 243 | `var entry = scope && ${RuntimeGlobals.hasOwnProperty}(scope, key) && findValidVersion(scope, key, version);`,
|
---|
| 244 | `return entry ? get(entry) : fallback();`
|
---|
| 245 | ]
|
---|
| 246 | )});`,
|
---|
| 247 | `var loadStrictSingletonVersionCheckFallback = /*#__PURE__*/ init(${runtimeTemplate.basicFunction(
|
---|
| 248 | "scopeName, scope, key, version, fallback",
|
---|
| 249 | [
|
---|
| 250 | `if(!scope || !${RuntimeGlobals.hasOwnProperty}(scope, key)) return fallback();`,
|
---|
| 251 | "return getStrictSingletonVersion(scope, scopeName, key, version);"
|
---|
| 252 | ]
|
---|
| 253 | )});`,
|
---|
| 254 | "var installedModules = {};",
|
---|
| 255 | "var moduleToHandlerMapping = {",
|
---|
| 256 | Template.indent(
|
---|
| 257 | Array.from(
|
---|
| 258 | moduleIdToSourceMapping,
|
---|
| 259 | ([key, source]) => `${JSON.stringify(key)}: ${source.source()}`
|
---|
| 260 | ).join(",\n")
|
---|
| 261 | ),
|
---|
| 262 | "};",
|
---|
| 263 |
|
---|
| 264 | initialConsumes.length > 0
|
---|
| 265 | ? Template.asString([
|
---|
| 266 | `var initialConsumes = ${JSON.stringify(initialConsumes)};`,
|
---|
| 267 | `initialConsumes.forEach(${runtimeTemplate.basicFunction("id", [
|
---|
| 268 | `${
|
---|
| 269 | RuntimeGlobals.moduleFactories
|
---|
| 270 | }[id] = ${runtimeTemplate.basicFunction("module", [
|
---|
| 271 | "// Handle case when module is used sync",
|
---|
| 272 | "installedModules[id] = 0;",
|
---|
| 273 | `delete ${RuntimeGlobals.moduleCache}[id];`,
|
---|
| 274 | "var factory = moduleToHandlerMapping[id]();",
|
---|
| 275 | 'if(typeof factory !== "function") throw new Error("Shared module is not available for eager consumption: " + id);',
|
---|
| 276 | `module.exports = factory();`
|
---|
| 277 | ])}`
|
---|
| 278 | ])});`
|
---|
| 279 | ])
|
---|
| 280 | : "// no consumes in initial chunks",
|
---|
| 281 | this._runtimeRequirements.has(RuntimeGlobals.ensureChunkHandlers)
|
---|
| 282 | ? Template.asString([
|
---|
| 283 | `var chunkMapping = ${JSON.stringify(
|
---|
| 284 | chunkToModuleMapping,
|
---|
| 285 | null,
|
---|
| 286 | "\t"
|
---|
| 287 | )};`,
|
---|
| 288 | `${
|
---|
| 289 | RuntimeGlobals.ensureChunkHandlers
|
---|
| 290 | }.consumes = ${runtimeTemplate.basicFunction("chunkId, promises", [
|
---|
| 291 | `if(${RuntimeGlobals.hasOwnProperty}(chunkMapping, chunkId)) {`,
|
---|
| 292 | Template.indent([
|
---|
| 293 | `chunkMapping[chunkId].forEach(${runtimeTemplate.basicFunction(
|
---|
| 294 | "id",
|
---|
| 295 | [
|
---|
| 296 | `if(${RuntimeGlobals.hasOwnProperty}(installedModules, id)) return promises.push(installedModules[id]);`,
|
---|
| 297 | `var onFactory = ${runtimeTemplate.basicFunction(
|
---|
| 298 | "factory",
|
---|
| 299 | [
|
---|
| 300 | "installedModules[id] = 0;",
|
---|
| 301 | `${
|
---|
| 302 | RuntimeGlobals.moduleFactories
|
---|
| 303 | }[id] = ${runtimeTemplate.basicFunction("module", [
|
---|
| 304 | `delete ${RuntimeGlobals.moduleCache}[id];`,
|
---|
| 305 | "module.exports = factory();"
|
---|
| 306 | ])}`
|
---|
| 307 | ]
|
---|
| 308 | )};`,
|
---|
| 309 | `var onError = ${runtimeTemplate.basicFunction("error", [
|
---|
| 310 | "delete installedModules[id];",
|
---|
| 311 | `${
|
---|
| 312 | RuntimeGlobals.moduleFactories
|
---|
| 313 | }[id] = ${runtimeTemplate.basicFunction("module", [
|
---|
| 314 | `delete ${RuntimeGlobals.moduleCache}[id];`,
|
---|
| 315 | "throw error;"
|
---|
| 316 | ])}`
|
---|
| 317 | ])};`,
|
---|
| 318 | "try {",
|
---|
| 319 | Template.indent([
|
---|
| 320 | "var promise = moduleToHandlerMapping[id]();",
|
---|
| 321 | "if(promise.then) {",
|
---|
| 322 | Template.indent(
|
---|
| 323 | `promises.push(installedModules[id] = promise.then(onFactory).catch(onError));`
|
---|
| 324 | ),
|
---|
| 325 | "} else onFactory(promise);"
|
---|
| 326 | ]),
|
---|
| 327 | "} catch(e) { onError(e); }"
|
---|
| 328 | ]
|
---|
| 329 | )});`
|
---|
| 330 | ]),
|
---|
| 331 | "}"
|
---|
| 332 | ])}`
|
---|
| 333 | ])
|
---|
| 334 | : "// no chunk loading of consumes"
|
---|
| 335 | ]);
|
---|
| 336 | }
|
---|
| 337 | }
|
---|
| 338 |
|
---|
| 339 | module.exports = ConsumeSharedRuntimeModule;
|
---|