source: imaps-frontend/node_modules/webpack/lib/ExternalModuleFactoryPlugin.js

main
Last change on this file was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 4 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 9.7 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const util = require("util");
9const ExternalModule = require("./ExternalModule");
10const ContextElementDependency = require("./dependencies/ContextElementDependency");
11const CssImportDependency = require("./dependencies/CssImportDependency");
12const CssUrlDependency = require("./dependencies/CssUrlDependency");
13const HarmonyImportDependency = require("./dependencies/HarmonyImportDependency");
14const ImportDependency = require("./dependencies/ImportDependency");
15const { resolveByProperty, cachedSetProperty } = require("./util/cleverMerge");
16
17/** @typedef {import("../declarations/WebpackOptions").ExternalItemFunctionData} ExternalItemFunctionData */
18/** @typedef {import("../declarations/WebpackOptions").Externals} Externals */
19/** @typedef {import("./Compilation").DepConstructor} DepConstructor */
20/** @typedef {import("./ExternalModule").DependencyMeta} DependencyMeta */
21/** @typedef {import("./Module")} Module */
22/** @typedef {import("./NormalModuleFactory")} NormalModuleFactory */
23
24const UNSPECIFIED_EXTERNAL_TYPE_REGEXP = /^[a-z0-9-]+ /;
25const EMPTY_RESOLVE_OPTIONS = {};
26
27// TODO webpack 6 remove this
28const callDeprecatedExternals = util.deprecate(
29 /**
30 * @param {TODO} externalsFunction externals function
31 * @param {string} context context
32 * @param {string} request request
33 * @param {(err: Error | null | undefined, value: ExternalValue | undefined, ty: ExternalType | undefined) => void} cb cb
34 */
35 (externalsFunction, context, request, cb) => {
36 // eslint-disable-next-line no-useless-call
37 externalsFunction.call(null, context, request, cb);
38 },
39 "The externals-function should be defined like ({context, request}, cb) => { ... }",
40 "DEP_WEBPACK_EXTERNALS_FUNCTION_PARAMETERS"
41);
42
43const cache = new WeakMap();
44
45/**
46 * @template {object} T
47 * @param {T} obj obj
48 * @param {TODO} layer layer
49 * @returns {Omit<T, "byLayer">} result
50 */
51const resolveLayer = (obj, layer) => {
52 let map = cache.get(/** @type {object} */ (obj));
53 if (map === undefined) {
54 map = new Map();
55 cache.set(/** @type {object} */ (obj), map);
56 } else {
57 const cacheEntry = map.get(layer);
58 if (cacheEntry !== undefined) return cacheEntry;
59 }
60 const result = resolveByProperty(obj, "byLayer", layer);
61 map.set(layer, result);
62 return result;
63};
64
65/** @typedef {string | string[] | boolean | Record<string, string | string[]>} ExternalValue */
66/** @typedef {string | undefined} ExternalType */
67
68class ExternalModuleFactoryPlugin {
69 /**
70 * @param {string | undefined} type default external type
71 * @param {Externals} externals externals config
72 */
73 constructor(type, externals) {
74 this.type = type;
75 this.externals = externals;
76 }
77
78 /**
79 * @param {NormalModuleFactory} normalModuleFactory the normal module factory
80 * @returns {void}
81 */
82 apply(normalModuleFactory) {
83 const globalType = this.type;
84 normalModuleFactory.hooks.factorize.tapAsync(
85 "ExternalModuleFactoryPlugin",
86 (data, callback) => {
87 const context = data.context;
88 const contextInfo = data.contextInfo;
89 const dependency = data.dependencies[0];
90 const dependencyType = data.dependencyType;
91
92 /**
93 * @param {ExternalValue} value the external config
94 * @param {ExternalType | undefined} type type of external
95 * @param {function((Error | null)=, ExternalModule=): void} callback callback
96 * @returns {void}
97 */
98 const handleExternal = (value, type, callback) => {
99 if (value === false) {
100 // Not externals, fallback to original factory
101 return callback();
102 }
103 /** @type {string | string[] | Record<string, string|string[]>} */
104 let externalConfig = value === true ? dependency.request : value;
105 // When no explicit type is specified, extract it from the externalConfig
106 if (type === undefined) {
107 if (
108 typeof externalConfig === "string" &&
109 UNSPECIFIED_EXTERNAL_TYPE_REGEXP.test(externalConfig)
110 ) {
111 const idx = externalConfig.indexOf(" ");
112 type = externalConfig.slice(0, idx);
113 externalConfig = externalConfig.slice(idx + 1);
114 } else if (
115 Array.isArray(externalConfig) &&
116 externalConfig.length > 0 &&
117 UNSPECIFIED_EXTERNAL_TYPE_REGEXP.test(externalConfig[0])
118 ) {
119 const firstItem = externalConfig[0];
120 const idx = firstItem.indexOf(" ");
121 type = firstItem.slice(0, idx);
122 externalConfig = [
123 firstItem.slice(idx + 1),
124 ...externalConfig.slice(1)
125 ];
126 }
127 }
128
129 const resolvedType = /** @type {string} */ (type || globalType);
130
131 // TODO make it pluggable/add hooks to `ExternalModule` to allow output modules own externals?
132 /** @type {DependencyMeta | undefined} */
133 let dependencyMeta;
134
135 if (
136 dependency instanceof HarmonyImportDependency ||
137 dependency instanceof ImportDependency ||
138 dependency instanceof ContextElementDependency
139 ) {
140 const externalType =
141 dependency instanceof HarmonyImportDependency
142 ? "module"
143 : dependency instanceof ImportDependency
144 ? "import"
145 : undefined;
146
147 dependencyMeta = {
148 attributes: dependency.assertions,
149 externalType
150 };
151 } else if (dependency instanceof CssImportDependency) {
152 dependencyMeta = {
153 layer: dependency.layer,
154 supports: dependency.supports,
155 media: dependency.media
156 };
157 }
158
159 if (
160 resolvedType === "asset" &&
161 dependency instanceof CssUrlDependency
162 ) {
163 dependencyMeta = { sourceType: "css-url" };
164 }
165
166 callback(
167 null,
168 new ExternalModule(
169 externalConfig,
170 resolvedType,
171 dependency.request,
172 dependencyMeta
173 )
174 );
175 };
176
177 /**
178 * @param {Externals} externals externals config
179 * @param {function((Error | null)=, ExternalModule=): void} callback callback
180 * @returns {void}
181 */
182 const handleExternals = (externals, callback) => {
183 if (typeof externals === "string") {
184 if (externals === dependency.request) {
185 return handleExternal(dependency.request, undefined, callback);
186 }
187 } else if (Array.isArray(externals)) {
188 let i = 0;
189 const next = () => {
190 /** @type {boolean | undefined} */
191 let asyncFlag;
192 /**
193 * @param {(Error | null)=} err err
194 * @param {ExternalModule=} module module
195 * @returns {void}
196 */
197 const handleExternalsAndCallback = (err, module) => {
198 if (err) return callback(err);
199 if (!module) {
200 if (asyncFlag) {
201 asyncFlag = false;
202 return;
203 }
204 return next();
205 }
206 callback(null, module);
207 };
208
209 do {
210 asyncFlag = true;
211 if (i >= externals.length) return callback();
212 handleExternals(externals[i++], handleExternalsAndCallback);
213 } while (!asyncFlag);
214 asyncFlag = false;
215 };
216
217 next();
218 return;
219 } else if (externals instanceof RegExp) {
220 if (externals.test(dependency.request)) {
221 return handleExternal(dependency.request, undefined, callback);
222 }
223 } else if (typeof externals === "function") {
224 /**
225 * @param {Error | null | undefined} err err
226 * @param {ExternalValue=} value value
227 * @param {ExternalType=} type type
228 * @returns {void}
229 */
230 const cb = (err, value, type) => {
231 if (err) return callback(err);
232 if (value !== undefined) {
233 handleExternal(value, type, callback);
234 } else {
235 callback();
236 }
237 };
238 if (externals.length === 3) {
239 // TODO webpack 6 remove this
240 callDeprecatedExternals(
241 externals,
242 context,
243 dependency.request,
244 cb
245 );
246 } else {
247 const promise = externals(
248 {
249 context,
250 request: dependency.request,
251 dependencyType,
252 contextInfo,
253 getResolve: options => (context, request, callback) => {
254 const resolveContext = {
255 fileDependencies: data.fileDependencies,
256 missingDependencies: data.missingDependencies,
257 contextDependencies: data.contextDependencies
258 };
259 let resolver = normalModuleFactory.getResolver(
260 "normal",
261 dependencyType
262 ? cachedSetProperty(
263 data.resolveOptions || EMPTY_RESOLVE_OPTIONS,
264 "dependencyType",
265 dependencyType
266 )
267 : data.resolveOptions
268 );
269 if (options) resolver = resolver.withOptions(options);
270 if (callback) {
271 resolver.resolve(
272 {},
273 context,
274 request,
275 resolveContext,
276 /** @type {TODO} */
277 (callback)
278 );
279 } else {
280 return new Promise((resolve, reject) => {
281 resolver.resolve(
282 {},
283 context,
284 request,
285 resolveContext,
286 (err, result) => {
287 if (err) reject(err);
288 else resolve(result);
289 }
290 );
291 });
292 }
293 }
294 },
295 cb
296 );
297 if (promise && promise.then) promise.then(r => cb(null, r), cb);
298 }
299 return;
300 } else if (typeof externals === "object") {
301 const resolvedExternals = resolveLayer(
302 externals,
303 contextInfo.issuerLayer
304 );
305 if (
306 Object.prototype.hasOwnProperty.call(
307 resolvedExternals,
308 dependency.request
309 )
310 ) {
311 return handleExternal(
312 resolvedExternals[dependency.request],
313 undefined,
314 callback
315 );
316 }
317 }
318 callback();
319 };
320
321 handleExternals(this.externals, callback);
322 }
323 );
324 }
325}
326module.exports = ExternalModuleFactoryPlugin;
Note: See TracBrowser for help on using the repository browser.