| 
									
										
										
										
											2015-05-13 06:15:01 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2018-07-30 23:08:51 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 23:00:38 +08:00
										 |  |  | "use strict"; | 
					
						
							| 
									
										
										
										
											2015-05-13 06:15:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 23:00:38 +08:00
										 |  |  | const ExternalModule = require("./ExternalModule"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ExternalModuleFactoryPlugin { | 
					
						
							|  |  |  | 	constructor(type, externals) { | 
					
						
							|  |  |  | 		this.type = type; | 
					
						
							|  |  |  | 		this.externals = externals; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-05-13 06:15:01 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-23 23:00:38 +08:00
										 |  |  | 	apply(normalModuleFactory) { | 
					
						
							|  |  |  | 		const globalType = this.type; | 
					
						
							| 
									
										
										
										
											2019-01-05 02:17:37 +08:00
										 |  |  | 		normalModuleFactory.hooks.factorize.tapAsync( | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			"ExternalModuleFactoryPlugin", | 
					
						
							| 
									
										
										
										
											2019-01-05 02:17:37 +08:00
										 |  |  | 			(data, callback) => { | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				const context = data.context; | 
					
						
							|  |  |  | 				const dependency = data.dependencies[0]; | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-21 17:13:20 +08:00
										 |  |  | 				/** | 
					
						
							|  |  |  | 				 * @param {string|boolean} value the external config | 
					
						
							|  |  |  | 				 * @param {string|undefined} type type of external | 
					
						
							|  |  |  | 				 * @param {function(Error=, ExternalModule=): void} callback callback | 
					
						
							|  |  |  | 				 * @returns {void} | 
					
						
							|  |  |  | 				 */ | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 				const handleExternal = (value, type, callback) => { | 
					
						
							| 
									
										
										
										
											2018-12-21 17:13:20 +08:00
										 |  |  | 					if (value === false) { | 
					
						
							|  |  |  | 						// Not externals, fallback to original factory
 | 
					
						
							| 
									
										
										
										
											2019-01-05 02:17:37 +08:00
										 |  |  | 						return callback(); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-12-21 17:13:20 +08:00
										 |  |  | 					/** @type {string} */ | 
					
						
							|  |  |  | 					let externalConfig; | 
					
						
							|  |  |  | 					if (value === true) { | 
					
						
							|  |  |  | 						externalConfig = dependency.request; | 
					
						
							|  |  |  | 					} else { | 
					
						
							|  |  |  | 						externalConfig = value; | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					// When no explicit type is specified, extract it from the externalConfig
 | 
					
						
							|  |  |  | 					if (type === undefined && /^[a-z0-9]+ /.test(externalConfig)) { | 
					
						
							|  |  |  | 						const idx = externalConfig.indexOf(" "); | 
					
						
							|  |  |  | 						type = externalConfig.substr(0, idx); | 
					
						
							|  |  |  | 						externalConfig = externalConfig.substr(idx + 1); | 
					
						
							| 
									
										
										
										
											2015-05-13 06:15:01 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					callback( | 
					
						
							|  |  |  | 						null, | 
					
						
							| 
									
										
										
										
											2018-12-21 17:13:20 +08:00
										 |  |  | 						new ExternalModule( | 
					
						
							|  |  |  | 							externalConfig, | 
					
						
							|  |  |  | 							type || globalType, | 
					
						
							|  |  |  | 							dependency.request | 
					
						
							|  |  |  | 						) | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					); | 
					
						
							|  |  |  | 				}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				const handleExternals = (externals, callback) => { | 
					
						
							|  |  |  | 					if (typeof externals === "string") { | 
					
						
							|  |  |  | 						if (externals === dependency.request) { | 
					
						
							| 
									
										
										
										
											2018-12-21 17:13:20 +08:00
										 |  |  | 							return handleExternal(dependency.request, undefined, callback); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						} | 
					
						
							|  |  |  | 					} else if (Array.isArray(externals)) { | 
					
						
							|  |  |  | 						let i = 0; | 
					
						
							|  |  |  | 						const next = () => { | 
					
						
							|  |  |  | 							let asyncFlag; | 
					
						
							|  |  |  | 							const handleExternalsAndCallback = (err, module) => { | 
					
						
							|  |  |  | 								if (err) return callback(err); | 
					
						
							|  |  |  | 								if (!module) { | 
					
						
							|  |  |  | 									if (asyncFlag) { | 
					
						
							|  |  |  | 										asyncFlag = false; | 
					
						
							|  |  |  | 										return; | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 									return next(); | 
					
						
							| 
									
										
										
										
											2016-10-29 17:11:44 +08:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 								callback(null, module); | 
					
						
							|  |  |  | 							}; | 
					
						
							| 
									
										
										
										
											2016-10-29 17:11:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							do { | 
					
						
							|  |  |  | 								asyncFlag = true; | 
					
						
							|  |  |  | 								if (i >= externals.length) return callback(); | 
					
						
							|  |  |  | 								handleExternals(externals[i++], handleExternalsAndCallback); | 
					
						
							| 
									
										
										
										
											2018-06-27 19:48:13 +08:00
										 |  |  | 							} while (!asyncFlag); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							asyncFlag = false; | 
					
						
							|  |  |  | 						}; | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						next(); | 
					
						
							|  |  |  | 						return; | 
					
						
							|  |  |  | 					} else if (externals instanceof RegExp) { | 
					
						
							|  |  |  | 						if (externals.test(dependency.request)) { | 
					
						
							| 
									
										
										
										
											2018-12-21 17:13:20 +08:00
										 |  |  | 							return handleExternal(dependency.request, undefined, callback); | 
					
						
							| 
									
										
										
										
											2015-05-13 06:15:01 +08:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					} else if (typeof externals === "function") { | 
					
						
							| 
									
										
										
										
											2018-12-21 17:13:20 +08:00
										 |  |  | 						const cb = (err, value, type) => { | 
					
						
							|  |  |  | 							if (err) return callback(err); | 
					
						
							|  |  |  | 							if (value !== undefined) { | 
					
						
							|  |  |  | 								handleExternal(value, type, callback); | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								callback(); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 							} | 
					
						
							| 
									
										
										
										
											2018-12-21 17:13:20 +08:00
										 |  |  | 						}; | 
					
						
							|  |  |  | 						if (externals.length === 3) { | 
					
						
							|  |  |  | 							// TODO webpack 5 insert deprecation message here
 | 
					
						
							|  |  |  | 							// TODO webpack 6 remove this
 | 
					
						
							|  |  |  | 							externals.call(null, context, dependency.request, cb); | 
					
						
							|  |  |  | 						} else { | 
					
						
							|  |  |  | 							externals( | 
					
						
							|  |  |  | 								{ | 
					
						
							|  |  |  | 									context, | 
					
						
							|  |  |  | 									request: dependency.request | 
					
						
							|  |  |  | 								}, | 
					
						
							|  |  |  | 								cb | 
					
						
							|  |  |  | 							); | 
					
						
							|  |  |  | 						} | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 						return; | 
					
						
							|  |  |  | 					} else if ( | 
					
						
							|  |  |  | 						typeof externals === "object" && | 
					
						
							|  |  |  | 						Object.prototype.hasOwnProperty.call(externals, dependency.request) | 
					
						
							|  |  |  | 					) { | 
					
						
							| 
									
										
										
										
											2018-12-21 17:13:20 +08:00
										 |  |  | 						return handleExternal( | 
					
						
							|  |  |  | 							externals[dependency.request], | 
					
						
							|  |  |  | 							undefined, | 
					
						
							|  |  |  | 							callback | 
					
						
							|  |  |  | 						); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					callback(); | 
					
						
							|  |  |  | 				}; | 
					
						
							| 
									
										
										
										
											2017-11-08 18:32:05 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-05 02:17:37 +08:00
										 |  |  | 				handleExternals(this.externals, callback); | 
					
						
							| 
									
										
										
										
											2018-02-25 09:00:20 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2017-02-23 23:00:38 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | module.exports = ExternalModuleFactoryPlugin; |