source: trip-planner-front/node_modules/webpack/lib/FlagDependencyExportsPlugin.js

Last change on this file was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 12.4 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 asyncLib = require("neo-async");
9const Queue = require("./util/Queue");
10
11/** @typedef {import("./Compiler")} Compiler */
12/** @typedef {import("./DependenciesBlock")} DependenciesBlock */
13/** @typedef {import("./Dependency")} Dependency */
14/** @typedef {import("./Dependency").ExportSpec} ExportSpec */
15/** @typedef {import("./Dependency").ExportsSpec} ExportsSpec */
16/** @typedef {import("./ExportsInfo")} ExportsInfo */
17/** @typedef {import("./Module")} Module */
18
19class FlagDependencyExportsPlugin {
20 /**
21 * Apply the plugin
22 * @param {Compiler} compiler the compiler instance
23 * @returns {void}
24 */
25 apply(compiler) {
26 compiler.hooks.compilation.tap(
27 "FlagDependencyExportsPlugin",
28 compilation => {
29 const moduleGraph = compilation.moduleGraph;
30 const cache = compilation.getCache("FlagDependencyExportsPlugin");
31 compilation.hooks.finishModules.tapAsync(
32 "FlagDependencyExportsPlugin",
33 (modules, callback) => {
34 const logger = compilation.getLogger(
35 "webpack.FlagDependencyExportsPlugin"
36 );
37 let statRestoredFromCache = 0;
38 let statNoExports = 0;
39 let statFlaggedUncached = 0;
40 let statNotCached = 0;
41 let statQueueItemsProcessed = 0;
42
43 /** @type {Queue<Module>} */
44 const queue = new Queue();
45
46 // Step 1: Try to restore cached provided export info from cache
47 logger.time("restore cached provided exports");
48 asyncLib.each(
49 modules,
50 (module, callback) => {
51 const exportsInfo = moduleGraph.getExportsInfo(module);
52 if (!module.buildMeta || !module.buildMeta.exportsType) {
53 if (exportsInfo.otherExportsInfo.provided !== null) {
54 // It's a module without declared exports
55 statNoExports++;
56 exportsInfo.setHasProvideInfo();
57 exportsInfo.setUnknownExportsProvided();
58 return callback();
59 }
60 }
61 if (
62 module.buildInfo.cacheable !== true ||
63 typeof module.buildInfo.hash !== "string"
64 ) {
65 statFlaggedUncached++;
66 // Enqueue uncacheable module for determining the exports
67 queue.enqueue(module);
68 exportsInfo.setHasProvideInfo();
69 return callback();
70 }
71 cache.get(
72 module.identifier(),
73 module.buildInfo.hash,
74 (err, result) => {
75 if (err) return callback(err);
76
77 if (result !== undefined) {
78 statRestoredFromCache++;
79 moduleGraph
80 .getExportsInfo(module)
81 .restoreProvided(result);
82 } else {
83 statNotCached++;
84 // Without cached info enqueue module for determining the exports
85 queue.enqueue(module);
86 exportsInfo.setHasProvideInfo();
87 }
88 callback();
89 }
90 );
91 },
92 err => {
93 logger.timeEnd("restore cached provided exports");
94 if (err) return callback(err);
95
96 /** @type {Set<Module>} */
97 const modulesToStore = new Set();
98
99 /** @type {Map<Module, Set<Module>>} */
100 const dependencies = new Map();
101
102 /** @type {Module} */
103 let module;
104
105 /** @type {ExportsInfo} */
106 let exportsInfo;
107
108 /** @type {Map<Dependency, ExportsSpec>} */
109 const exportsSpecsFromDependencies = new Map();
110
111 let cacheable = true;
112 let changed = false;
113
114 /**
115 * @param {DependenciesBlock} depBlock the dependencies block
116 * @returns {void}
117 */
118 const processDependenciesBlock = depBlock => {
119 for (const dep of depBlock.dependencies) {
120 processDependency(dep);
121 }
122 for (const block of depBlock.blocks) {
123 processDependenciesBlock(block);
124 }
125 };
126
127 /**
128 * @param {Dependency} dep the dependency
129 * @returns {void}
130 */
131 const processDependency = dep => {
132 const exportDesc = dep.getExports(moduleGraph);
133 if (!exportDesc) return;
134 exportsSpecsFromDependencies.set(dep, exportDesc);
135 };
136
137 /**
138 * @param {Dependency} dep dependency
139 * @param {ExportsSpec} exportDesc info
140 * @returns {void}
141 */
142 const processExportsSpec = (dep, exportDesc) => {
143 const exports = exportDesc.exports;
144 const globalCanMangle = exportDesc.canMangle;
145 const globalFrom = exportDesc.from;
146 const globalPriority = exportDesc.priority;
147 const globalTerminalBinding =
148 exportDesc.terminalBinding || false;
149 const exportDeps = exportDesc.dependencies;
150 if (exportDesc.hideExports) {
151 for (const name of exportDesc.hideExports) {
152 const exportInfo = exportsInfo.getExportInfo(name);
153 exportInfo.unsetTarget(dep);
154 }
155 }
156 if (exports === true) {
157 // unknown exports
158 if (
159 exportsInfo.setUnknownExportsProvided(
160 globalCanMangle,
161 exportDesc.excludeExports,
162 globalFrom && dep,
163 globalFrom,
164 globalPriority
165 )
166 ) {
167 changed = true;
168 }
169 } else if (Array.isArray(exports)) {
170 /**
171 * merge in new exports
172 * @param {ExportsInfo} exportsInfo own exports info
173 * @param {(ExportSpec | string)[]} exports list of exports
174 */
175 const mergeExports = (exportsInfo, exports) => {
176 for (const exportNameOrSpec of exports) {
177 let name;
178 let canMangle = globalCanMangle;
179 let terminalBinding = globalTerminalBinding;
180 let exports = undefined;
181 let from = globalFrom;
182 let fromExport = undefined;
183 let priority = globalPriority;
184 let hidden = false;
185 if (typeof exportNameOrSpec === "string") {
186 name = exportNameOrSpec;
187 } else {
188 name = exportNameOrSpec.name;
189 if (exportNameOrSpec.canMangle !== undefined)
190 canMangle = exportNameOrSpec.canMangle;
191 if (exportNameOrSpec.export !== undefined)
192 fromExport = exportNameOrSpec.export;
193 if (exportNameOrSpec.exports !== undefined)
194 exports = exportNameOrSpec.exports;
195 if (exportNameOrSpec.from !== undefined)
196 from = exportNameOrSpec.from;
197 if (exportNameOrSpec.priority !== undefined)
198 priority = exportNameOrSpec.priority;
199 if (exportNameOrSpec.terminalBinding !== undefined)
200 terminalBinding = exportNameOrSpec.terminalBinding;
201 if (exportNameOrSpec.hidden !== undefined)
202 hidden = exportNameOrSpec.hidden;
203 }
204 const exportInfo = exportsInfo.getExportInfo(name);
205
206 if (
207 exportInfo.provided === false ||
208 exportInfo.provided === null
209 ) {
210 exportInfo.provided = true;
211 changed = true;
212 }
213
214 if (
215 exportInfo.canMangleProvide !== false &&
216 canMangle === false
217 ) {
218 exportInfo.canMangleProvide = false;
219 changed = true;
220 }
221
222 if (terminalBinding && !exportInfo.terminalBinding) {
223 exportInfo.terminalBinding = true;
224 changed = true;
225 }
226
227 if (exports) {
228 const nestedExportsInfo =
229 exportInfo.createNestedExportsInfo();
230 mergeExports(nestedExportsInfo, exports);
231 }
232
233 if (
234 from &&
235 (hidden
236 ? exportInfo.unsetTarget(dep)
237 : exportInfo.setTarget(
238 dep,
239 from,
240 fromExport === undefined ? [name] : fromExport,
241 priority
242 ))
243 ) {
244 changed = true;
245 }
246
247 // Recalculate target exportsInfo
248 const target = exportInfo.getTarget(moduleGraph);
249 let targetExportsInfo = undefined;
250 if (target) {
251 const targetModuleExportsInfo =
252 moduleGraph.getExportsInfo(target.module);
253 targetExportsInfo =
254 targetModuleExportsInfo.getNestedExportsInfo(
255 target.export
256 );
257 // add dependency for this module
258 const set = dependencies.get(target.module);
259 if (set === undefined) {
260 dependencies.set(target.module, new Set([module]));
261 } else {
262 set.add(module);
263 }
264 }
265
266 if (exportInfo.exportsInfoOwned) {
267 if (
268 exportInfo.exportsInfo.setRedirectNamedTo(
269 targetExportsInfo
270 )
271 ) {
272 changed = true;
273 }
274 } else if (
275 exportInfo.exportsInfo !== targetExportsInfo
276 ) {
277 exportInfo.exportsInfo = targetExportsInfo;
278 changed = true;
279 }
280 }
281 };
282 mergeExports(exportsInfo, exports);
283 }
284 // store dependencies
285 if (exportDeps) {
286 cacheable = false;
287 for (const exportDependency of exportDeps) {
288 // add dependency for this module
289 const set = dependencies.get(exportDependency);
290 if (set === undefined) {
291 dependencies.set(exportDependency, new Set([module]));
292 } else {
293 set.add(module);
294 }
295 }
296 }
297 };
298
299 const notifyDependencies = () => {
300 const deps = dependencies.get(module);
301 if (deps !== undefined) {
302 for (const dep of deps) {
303 queue.enqueue(dep);
304 }
305 }
306 };
307
308 logger.time("figure out provided exports");
309 while (queue.length > 0) {
310 module = queue.dequeue();
311
312 statQueueItemsProcessed++;
313
314 exportsInfo = moduleGraph.getExportsInfo(module);
315
316 cacheable = true;
317 changed = false;
318
319 exportsSpecsFromDependencies.clear();
320 moduleGraph.freeze();
321 processDependenciesBlock(module);
322 moduleGraph.unfreeze();
323 for (const [
324 dep,
325 exportsSpec
326 ] of exportsSpecsFromDependencies) {
327 processExportsSpec(dep, exportsSpec);
328 }
329
330 if (cacheable) {
331 modulesToStore.add(module);
332 }
333
334 if (changed) {
335 notifyDependencies();
336 }
337 }
338 logger.timeEnd("figure out provided exports");
339
340 logger.log(
341 `${Math.round(
342 (100 * (statFlaggedUncached + statNotCached)) /
343 (statRestoredFromCache +
344 statNotCached +
345 statFlaggedUncached +
346 statNoExports)
347 )}% of exports of modules have been determined (${statNoExports} no declared exports, ${statNotCached} not cached, ${statFlaggedUncached} flagged uncacheable, ${statRestoredFromCache} from cache, ${
348 statQueueItemsProcessed -
349 statNotCached -
350 statFlaggedUncached
351 } additional calculations due to dependencies)`
352 );
353
354 logger.time("store provided exports into cache");
355 asyncLib.each(
356 modulesToStore,
357 (module, callback) => {
358 if (
359 module.buildInfo.cacheable !== true ||
360 typeof module.buildInfo.hash !== "string"
361 ) {
362 // not cacheable
363 return callback();
364 }
365 cache.store(
366 module.identifier(),
367 module.buildInfo.hash,
368 moduleGraph
369 .getExportsInfo(module)
370 .getRestoreProvidedData(),
371 callback
372 );
373 },
374 err => {
375 logger.timeEnd("store provided exports into cache");
376 callback(err);
377 }
378 );
379 }
380 );
381 }
382 );
383
384 /** @type {WeakMap<Module, any>} */
385 const providedExportsCache = new WeakMap();
386 compilation.hooks.rebuildModule.tap(
387 "FlagDependencyExportsPlugin",
388 module => {
389 providedExportsCache.set(
390 module,
391 moduleGraph.getExportsInfo(module).getRestoreProvidedData()
392 );
393 }
394 );
395 compilation.hooks.finishRebuildingModule.tap(
396 "FlagDependencyExportsPlugin",
397 module => {
398 moduleGraph
399 .getExportsInfo(module)
400 .restoreProvided(providedExportsCache.get(module));
401 }
402 );
403 }
404 );
405 }
406}
407
408module.exports = FlagDependencyExportsPlugin;
Note: See TracBrowser for help on using the repository browser.