| 
									
										
										
										
											2020-05-23 22:08:51 +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"); | 
					
						
							| 
									
										
										
										
											2020-07-02 19:13:13 +08:00
										 |  |  | const { | 
					
						
							|  |  |  | 	compareModulesByIdentifier, | 
					
						
							|  |  |  | 	compareStrings | 
					
						
							|  |  |  | } = require("../util/comparators"); | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-13 01:24:59 +08:00
										 |  |  | /** @typedef {import("../Chunk")} Chunk */ | 
					
						
							|  |  |  | /** @typedef {import("../ChunkGraph")} ChunkGraph */ | 
					
						
							|  |  |  | /** @typedef {import("../Compilation")} Compilation */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | class ShareRuntimeModule extends RuntimeModule { | 
					
						
							|  |  |  | 	constructor() { | 
					
						
							|  |  |  | 		super("sharing"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/** | 
					
						
							| 
									
										
										
										
											2023-06-17 01:13:03 +08:00
										 |  |  | 	 * @returns {string | null} runtime code | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 	 */ | 
					
						
							|  |  |  | 	generate() { | 
					
						
							| 
									
										
										
										
											2023-06-13 01:24:59 +08:00
										 |  |  | 		const compilation = /** @type {Compilation} */ (this.compilation); | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 		const { | 
					
						
							|  |  |  | 			runtimeTemplate, | 
					
						
							| 
									
										
										
										
											2020-06-30 21:08:13 +08:00
										 |  |  | 			codeGenerationResults, | 
					
						
							| 
									
										
										
										
											2023-06-13 01:24:59 +08:00
										 |  |  | 			outputOptions: { uniqueName, ignoreBrowserWarnings } | 
					
						
							| 
									
										
										
										
											2021-04-13 02:53:25 +08:00
										 |  |  | 		} = compilation; | 
					
						
							| 
									
										
										
										
											2023-06-13 01:24:59 +08:00
										 |  |  | 		const chunkGraph = /** @type {ChunkGraph} */ (this.chunkGraph); | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 		/** @type {Map<string, Map<number, Set<string>>>} */ | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 		const initCodePerScope = new Map(); | 
					
						
							| 
									
										
										
										
											2023-06-13 01:24:59 +08:00
										 |  |  | 		for (const chunk of /** @type {Chunk} */ ( | 
					
						
							|  |  |  | 			this.chunk | 
					
						
							|  |  |  | 		).getAllReferencedChunks()) { | 
					
						
							| 
									
										
										
										
											2020-07-02 19:13:13 +08:00
										 |  |  | 			const modules = chunkGraph.getOrderedChunkModulesIterableBySourceType( | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 				chunk, | 
					
						
							| 
									
										
										
										
											2020-07-02 19:13:13 +08:00
										 |  |  | 				"share-init", | 
					
						
							|  |  |  | 				compareModulesByIdentifier | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 			); | 
					
						
							|  |  |  | 			if (!modules) continue; | 
					
						
							|  |  |  | 			for (const m of modules) { | 
					
						
							| 
									
										
										
										
											2020-07-28 00:09:48 +08:00
										 |  |  | 				const data = codeGenerationResults.getData( | 
					
						
							|  |  |  | 					m, | 
					
						
							|  |  |  | 					chunk.runtime, | 
					
						
							|  |  |  | 					"share-init" | 
					
						
							|  |  |  | 				); | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 				if (!data) continue; | 
					
						
							|  |  |  | 				for (const item of data) { | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 					const { shareScope, initStage, init } = item; | 
					
						
							|  |  |  | 					let stages = initCodePerScope.get(shareScope); | 
					
						
							|  |  |  | 					if (stages === undefined) { | 
					
						
							|  |  |  | 						initCodePerScope.set(shareScope, (stages = new Map())); | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					let list = stages.get(initStage || 0); | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 					if (list === undefined) { | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 						stages.set(initStage || 0, (list = new Set())); | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 					list.add(init); | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return Template.asString([ | 
					
						
							|  |  |  | 			`${RuntimeGlobals.shareScopeMap} = {};`, | 
					
						
							|  |  |  | 			"var initPromises = {};", | 
					
						
							| 
									
										
										
										
											2020-09-16 16:42:50 +08:00
										 |  |  | 			"var initTokens = {};", | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 			`${RuntimeGlobals.initializeSharing} = ${runtimeTemplate.basicFunction( | 
					
						
							| 
									
										
										
										
											2020-09-16 16:42:50 +08:00
										 |  |  | 				"name, initScope", | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 				[ | 
					
						
							| 
									
										
										
										
											2020-09-16 16:42:50 +08:00
										 |  |  | 					"if(!initScope) initScope = [];", | 
					
						
							|  |  |  | 					"// handling circular init calls", | 
					
						
							|  |  |  | 					"var initToken = initTokens[name];", | 
					
						
							|  |  |  | 					"if(!initToken) initToken = initTokens[name] = {};", | 
					
						
							|  |  |  | 					"if(initScope.indexOf(initToken) >= 0) return;", | 
					
						
							|  |  |  | 					"initScope.push(initToken);", | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 					"// only runs once", | 
					
						
							|  |  |  | 					"if(initPromises[name]) return initPromises[name];", | 
					
						
							|  |  |  | 					"// creates a new share scope if needed", | 
					
						
							|  |  |  | 					`if(!${RuntimeGlobals.hasOwnProperty}(${RuntimeGlobals.shareScopeMap}, name)) ${RuntimeGlobals.shareScopeMap}[name] = {};`, | 
					
						
							|  |  |  | 					"// runs all init snippets from all modules reachable", | 
					
						
							|  |  |  | 					`var scope = ${RuntimeGlobals.shareScopeMap}[name];`, | 
					
						
							| 
									
										
										
										
											2022-10-20 10:40:42 +08:00
										 |  |  | 					`var warn = ${ | 
					
						
							| 
									
										
										
										
											2023-06-13 01:24:59 +08:00
										 |  |  | 						ignoreBrowserWarnings | 
					
						
							| 
									
										
										
										
											2022-10-20 10:40:42 +08:00
										 |  |  | 							? runtimeTemplate.basicFunction("", "") | 
					
						
							|  |  |  | 							: runtimeTemplate.basicFunction("msg", [ | 
					
						
							|  |  |  | 									'if (typeof console !== "undefined" && console.warn) console.warn(msg);' | 
					
						
							| 
									
										
										
										
											2024-01-14 09:41:34 +08:00
										 |  |  | 								]) | 
					
						
							| 
									
										
										
										
											2022-10-20 10:40:42 +08:00
										 |  |  | 					};`,
 | 
					
						
							| 
									
										
										
										
											2020-06-30 21:08:13 +08:00
										 |  |  | 					`var uniqueName = ${JSON.stringify(uniqueName || undefined)};`, | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 					`var register = ${runtimeTemplate.basicFunction( | 
					
						
							| 
									
										
										
										
											2020-12-06 03:59:37 +08:00
										 |  |  | 						"name, version, factory, eager", | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 						[ | 
					
						
							| 
									
										
										
										
											2020-06-30 21:08:13 +08:00
										 |  |  | 							"var versions = scope[name] = scope[name] || {};", | 
					
						
							|  |  |  | 							"var activeVersion = versions[version];", | 
					
						
							| 
									
										
										
										
											2021-01-14 21:24:34 +08:00
										 |  |  | 							"if(!activeVersion || (!activeVersion.loaded && (!eager != !activeVersion.eager ? eager : uniqueName > activeVersion.from))) versions[version] = { get: factory, from: uniqueName, eager: !!eager };" | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 						] | 
					
						
							|  |  |  | 					)};`,
 | 
					
						
							|  |  |  | 					`var initExternal = ${runtimeTemplate.basicFunction("id", [ | 
					
						
							| 
									
										
										
										
											2021-03-15 19:13:43 +08:00
										 |  |  | 						`var handleError = ${runtimeTemplate.expressionFunction( | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 							'warn("Initialization of sharing external failed: " + err)', | 
					
						
							|  |  |  | 							"err" | 
					
						
							|  |  |  | 						)};`,
 | 
					
						
							|  |  |  | 						"try {", | 
					
						
							|  |  |  | 						Template.indent([ | 
					
						
							| 
									
										
										
										
											2023-05-19 23:55:47 +08:00
										 |  |  | 							`var module = ${RuntimeGlobals.require}(id);`, | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 							"if(!module) return;", | 
					
						
							|  |  |  | 							`var initFn = ${runtimeTemplate.returningFunction( | 
					
						
							| 
									
										
										
										
											2020-09-16 16:42:50 +08:00
										 |  |  | 								`module && module.init && module.init(${RuntimeGlobals.shareScopeMap}[name], initScope)`, | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 								"module" | 
					
						
							|  |  |  | 							)}`,
 | 
					
						
							|  |  |  | 							"if(module.then) return promises.push(module.then(initFn, handleError));", | 
					
						
							|  |  |  | 							"var initResult = initFn(module);", | 
					
						
							| 
									
										
										
										
											2021-10-15 13:40:47 +08:00
										 |  |  | 							"if(initResult && initResult.then) return promises.push(initResult['catch'](handleError));" | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 						]), | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 						"} catch(err) { handleError(err); }" | 
					
						
							|  |  |  | 					])}`,
 | 
					
						
							|  |  |  | 					"var promises = [];", | 
					
						
							|  |  |  | 					"switch(name) {", | 
					
						
							| 
									
										
										
										
											2020-07-02 19:13:13 +08:00
										 |  |  | 					...Array.from(initCodePerScope) | 
					
						
							|  |  |  | 						.sort(([a], [b]) => compareStrings(a, b)) | 
					
						
							|  |  |  | 						.map(([name, stages]) => | 
					
						
							|  |  |  | 							Template.indent([ | 
					
						
							|  |  |  | 								`case ${JSON.stringify(name)}: {`, | 
					
						
							|  |  |  | 								Template.indent( | 
					
						
							|  |  |  | 									Array.from(stages) | 
					
						
							|  |  |  | 										.sort(([a], [b]) => a - b) | 
					
						
							|  |  |  | 										.map(([, initCode]) => | 
					
						
							|  |  |  | 											Template.asString(Array.from(initCode)) | 
					
						
							|  |  |  | 										) | 
					
						
							|  |  |  | 								), | 
					
						
							|  |  |  | 								"}", | 
					
						
							|  |  |  | 								"break;" | 
					
						
							|  |  |  | 							]) | 
					
						
							|  |  |  | 						), | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 					"}", | 
					
						
							| 
									
										
										
										
											2020-09-16 16:42:50 +08:00
										 |  |  | 					"if(!promises.length) return initPromises[name] = 1;", | 
					
						
							|  |  |  | 					`return initPromises[name] = Promise.all(promises).then(${runtimeTemplate.returningFunction( | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 						"initPromises[name] = 1" | 
					
						
							| 
									
										
										
										
											2020-09-16 16:42:50 +08:00
										 |  |  | 					)});`
 | 
					
						
							| 
									
										
										
										
											2020-05-26 23:11:21 +08:00
										 |  |  | 				] | 
					
						
							|  |  |  | 			)};`
 | 
					
						
							| 
									
										
										
										
											2020-05-23 22:08:51 +08:00
										 |  |  | 		]); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = ShareRuntimeModule; |