mirror of https://github.com/webpack/webpack.git
				
				
				
			
		
			
				
	
	
		
			154 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			4.6 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");
 | |
| 
 | |
| /** @typedef {import("./OverridableModule")} OverridableModule */
 | |
| 
 | |
| class OverridablesRuntimeModule extends RuntimeModule {
 | |
| 	constructor(runtimeRequirements) {
 | |
| 		super("overridables");
 | |
| 		this._runtimeRequirements = runtimeRequirements;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @returns {string} runtime code
 | |
| 	 */
 | |
| 	generate() {
 | |
| 		const {
 | |
| 			runtimeTemplate,
 | |
| 			moduleGraph,
 | |
| 			chunkGraph,
 | |
| 			codeGenerationResults
 | |
| 		} = this.compilation;
 | |
| 		const chunkToOverridableMapping = {};
 | |
| 		const idToNameMapping = {};
 | |
| 		const overridableToFallbackMapping = new Map();
 | |
| 		const initialOverridables = {};
 | |
| 		const asyncChunks = this.chunk.getAllAsyncChunks();
 | |
| 		for (const chunk of asyncChunks) {
 | |
| 			const modules = chunkGraph.getChunkModulesIterableBySourceType(
 | |
| 				chunk,
 | |
| 				"overridable"
 | |
| 			);
 | |
| 			if (!modules) continue;
 | |
| 			const overridables = (chunkToOverridableMapping[chunk.id] = []);
 | |
| 			for (const m of modules) {
 | |
| 				const module = /** @type {OverridableModule} */ (m);
 | |
| 				const name = module.options.name;
 | |
| 				const id = chunkGraph.getModuleId(module);
 | |
| 				overridables.push(id);
 | |
| 				idToNameMapping[id] = name;
 | |
| 				const source = codeGenerationResults
 | |
| 					.get(module)
 | |
| 					.sources.get("overridable");
 | |
| 				overridableToFallbackMapping.set(id, source.source());
 | |
| 			}
 | |
| 		}
 | |
| 		for (const chunk of this.chunk.getAllReferencedChunks()) {
 | |
| 			if (asyncChunks.has(chunk)) continue;
 | |
| 			const modules = chunkGraph.getChunkModulesIterableBySourceType(
 | |
| 				chunk,
 | |
| 				"overridable"
 | |
| 			);
 | |
| 			if (!modules) continue;
 | |
| 			for (const m of modules) {
 | |
| 				const module = /** @type {OverridableModule} */ (m);
 | |
| 				const name = module.options.name;
 | |
| 				const id = chunkGraph.getModuleId(module);
 | |
| 				idToNameMapping[id] = name;
 | |
| 				const fallbackModule = moduleGraph.getModule(
 | |
| 					module.blocks[0].dependencies[0]
 | |
| 				);
 | |
| 				const fallbackId = chunkGraph.getModuleId(fallbackModule);
 | |
| 				initialOverridables[id] = fallbackId;
 | |
| 			}
 | |
| 		}
 | |
| 		return Template.asString([
 | |
| 			`${RuntimeGlobals.overrides} = {};`,
 | |
| 			"var installedModules = {};",
 | |
| 			`var idToNameMapping = ${JSON.stringify(idToNameMapping, null, "\t")};`,
 | |
| 
 | |
| 			Object.keys(initialOverridables).length
 | |
| 				? Template.asString([
 | |
| 						`var initialOverridables = ${JSON.stringify(
 | |
| 							initialOverridables,
 | |
| 							null,
 | |
| 							"\t"
 | |
| 						)};`,
 | |
| 						`for(var id in initialOverridables) if(${
 | |
| 							RuntimeGlobals.hasOwnProperty
 | |
| 						}(initialOverridables, id)) __webpack_modules__[id] = (${runtimeTemplate.returningFunction(
 | |
| 							`${runtimeTemplate.basicFunction("module", [
 | |
| 								"// Handle case when module is used sync",
 | |
| 								"installedModules[id] = 0;",
 | |
| 								`var override = ${RuntimeGlobals.overrides}[idToNameMapping[id]];`,
 | |
| 								"module.exports = override ? override()() : __webpack_require__(initialOverridables[id]);"
 | |
| 							])}`,
 | |
| 							"id"
 | |
| 						)})(id);`
 | |
| 				  ])
 | |
| 				: "// no overridables in initial chunks",
 | |
| 			this._runtimeRequirements.has(RuntimeGlobals.ensureChunkHandlers)
 | |
| 				? Template.asString([
 | |
| 						`var chunkMapping = ${JSON.stringify(
 | |
| 							chunkToOverridableMapping,
 | |
| 							null,
 | |
| 							"\t"
 | |
| 						)};`,
 | |
| 						"var fallbackMapping = {",
 | |
| 						Template.indent(
 | |
| 							Array.from(
 | |
| 								overridableToFallbackMapping,
 | |
| 								([id, source]) =>
 | |
| 									`${JSON.stringify(id)}: ${runtimeTemplate.basicFunction(
 | |
| 										"",
 | |
| 										source
 | |
| 									)}`
 | |
| 							).join(",\n")
 | |
| 						),
 | |
| 						"};",
 | |
| 						`${
 | |
| 							RuntimeGlobals.ensureChunkHandlers
 | |
| 						}.overridables = ${runtimeTemplate.basicFunction(
 | |
| 							"chunkId, promises",
 | |
| 							[
 | |
| 								`if(${RuntimeGlobals.hasOwnProperty}(chunkMapping, chunkId)) {`,
 | |
| 								Template.indent([
 | |
| 									`chunkMapping[chunkId].forEach(${runtimeTemplate.basicFunction(
 | |
| 										"id",
 | |
| 										[
 | |
| 											`promises.push(${
 | |
| 												RuntimeGlobals.hasOwnProperty
 | |
| 											}(installedModules, id) ? installedModules[id] : installedModules[id] = Promise.resolve((${
 | |
| 												RuntimeGlobals.overrides
 | |
| 											}[idToNameMapping[id]] || fallbackMapping[id])()).then(${runtimeTemplate.basicFunction(
 | |
| 												"factory",
 | |
| 												[
 | |
| 													"installedModules[id] = 0;",
 | |
| 													`__webpack_modules__[id] = ${runtimeTemplate.basicFunction(
 | |
| 														"module",
 | |
| 														["module.exports = factory();"]
 | |
| 													)}`
 | |
| 												]
 | |
| 											)}))`
 | |
| 										]
 | |
| 									)});`
 | |
| 								]),
 | |
| 								"}"
 | |
| 							]
 | |
| 						)}`
 | |
| 				  ])
 | |
| 				: "// no chunk loading of overridables"
 | |
| 		]);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| module.exports = OverridablesRuntimeModule;
 |