source: trip-planner-front/node_modules/webpack/lib/optimize/InnerGraph.js@ ceaed42

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

initial commit

  • Property mode set to 100644
File size: 8.4 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Sergey Melyukov @smelukov
4*/
5
6"use strict";
7
8const { UsageState } = require("../ExportsInfo");
9
10/** @typedef {import("estree").Node} AnyNode */
11/** @typedef {import("../Dependency")} Dependency */
12/** @typedef {import("../ModuleGraph")} ModuleGraph */
13/** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
14/** @typedef {import("../ModuleGraphConnection").ConnectionState} ConnectionState */
15/** @typedef {import("../Parser").ParserState} ParserState */
16/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
17/** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
18
19/** @typedef {Map<TopLevelSymbol, Set<string | TopLevelSymbol> | true>} InnerGraph */
20/** @typedef {function(boolean | Set<string> | undefined): void} UsageCallback */
21
22/**
23 * @typedef {Object} StateObject
24 * @property {InnerGraph} innerGraph
25 * @property {TopLevelSymbol=} currentTopLevelSymbol
26 * @property {Map<TopLevelSymbol, Set<UsageCallback>>} usageCallbackMap
27 */
28
29/** @typedef {false|StateObject} State */
30
31/** @type {WeakMap<ParserState, State>} */
32const parserStateMap = new WeakMap();
33const topLevelSymbolTag = Symbol("top level symbol");
34
35/**
36 * @param {ParserState} parserState parser state
37 * @returns {State} state
38 */
39function getState(parserState) {
40 return parserStateMap.get(parserState);
41}
42
43/**
44 * @param {ParserState} parserState parser state
45 * @returns {void}
46 */
47exports.bailout = parserState => {
48 parserStateMap.set(parserState, false);
49};
50
51/**
52 * @param {ParserState} parserState parser state
53 * @returns {void}
54 */
55exports.enable = parserState => {
56 const state = parserStateMap.get(parserState);
57 if (state === false) {
58 return;
59 }
60 parserStateMap.set(parserState, {
61 innerGraph: new Map(),
62 currentTopLevelSymbol: undefined,
63 usageCallbackMap: new Map()
64 });
65};
66
67/**
68 * @param {ParserState} parserState parser state
69 * @returns {boolean} true, when enabled
70 */
71exports.isEnabled = parserState => {
72 const state = parserStateMap.get(parserState);
73 return !!state;
74};
75
76/**
77 * @param {ParserState} state parser state
78 * @param {TopLevelSymbol} symbol the symbol
79 * @param {string | TopLevelSymbol | true} usage usage data
80 * @returns {void}
81 */
82exports.addUsage = (state, symbol, usage) => {
83 const innerGraphState = getState(state);
84
85 if (innerGraphState) {
86 const { innerGraph } = innerGraphState;
87 const info = innerGraph.get(symbol);
88 if (usage === true) {
89 innerGraph.set(symbol, true);
90 } else if (info === undefined) {
91 innerGraph.set(symbol, new Set([usage]));
92 } else if (info !== true) {
93 info.add(usage);
94 }
95 }
96};
97
98/**
99 * @param {JavascriptParser} parser the parser
100 * @param {string} name name of variable
101 * @param {string | TopLevelSymbol | true} usage usage data
102 * @returns {void}
103 */
104exports.addVariableUsage = (parser, name, usage) => {
105 const symbol =
106 /** @type {TopLevelSymbol} */ (
107 parser.getTagData(name, topLevelSymbolTag)
108 ) || exports.tagTopLevelSymbol(parser, name);
109 if (symbol) {
110 exports.addUsage(parser.state, symbol, usage);
111 }
112};
113
114/**
115 * @param {ParserState} state parser state
116 * @returns {void}
117 */
118exports.inferDependencyUsage = state => {
119 const innerGraphState = getState(state);
120
121 if (!innerGraphState) {
122 return;
123 }
124
125 const { innerGraph, usageCallbackMap } = innerGraphState;
126 const processed = new Map();
127 // flatten graph to terminal nodes (string, undefined or true)
128 const nonTerminal = new Set(innerGraph.keys());
129 while (nonTerminal.size > 0) {
130 for (const key of nonTerminal) {
131 /** @type {Set<string|TopLevelSymbol> | true} */
132 let newSet = new Set();
133 let isTerminal = true;
134 const value = innerGraph.get(key);
135 let alreadyProcessed = processed.get(key);
136 if (alreadyProcessed === undefined) {
137 alreadyProcessed = new Set();
138 processed.set(key, alreadyProcessed);
139 }
140 if (value !== true && value !== undefined) {
141 for (const item of value) {
142 alreadyProcessed.add(item);
143 }
144 for (const item of value) {
145 if (typeof item === "string") {
146 newSet.add(item);
147 } else {
148 const itemValue = innerGraph.get(item);
149 if (itemValue === true) {
150 newSet = true;
151 break;
152 }
153 if (itemValue !== undefined) {
154 for (const i of itemValue) {
155 if (i === key) continue;
156 if (alreadyProcessed.has(i)) continue;
157 newSet.add(i);
158 if (typeof i !== "string") {
159 isTerminal = false;
160 }
161 }
162 }
163 }
164 }
165 if (newSet === true) {
166 innerGraph.set(key, true);
167 } else if (newSet.size === 0) {
168 innerGraph.set(key, undefined);
169 } else {
170 innerGraph.set(key, newSet);
171 }
172 }
173 if (isTerminal) {
174 nonTerminal.delete(key);
175 }
176 }
177 }
178
179 /** @type {Map<Dependency, true | Set<string>>} */
180 for (const [symbol, callbacks] of usageCallbackMap) {
181 const usage = /** @type {true | Set<string> | undefined} */ (
182 innerGraph.get(symbol)
183 );
184 for (const callback of callbacks) {
185 callback(usage === undefined ? false : usage);
186 }
187 }
188};
189
190/**
191 * @param {ParserState} state parser state
192 * @param {UsageCallback} onUsageCallback on usage callback
193 */
194exports.onUsage = (state, onUsageCallback) => {
195 const innerGraphState = getState(state);
196
197 if (innerGraphState) {
198 const { usageCallbackMap, currentTopLevelSymbol } = innerGraphState;
199 if (currentTopLevelSymbol) {
200 let callbacks = usageCallbackMap.get(currentTopLevelSymbol);
201
202 if (callbacks === undefined) {
203 callbacks = new Set();
204 usageCallbackMap.set(currentTopLevelSymbol, callbacks);
205 }
206
207 callbacks.add(onUsageCallback);
208 } else {
209 onUsageCallback(true);
210 }
211 } else {
212 onUsageCallback(undefined);
213 }
214};
215
216/**
217 * @param {ParserState} state parser state
218 * @param {TopLevelSymbol} symbol the symbol
219 */
220exports.setTopLevelSymbol = (state, symbol) => {
221 const innerGraphState = getState(state);
222
223 if (innerGraphState) {
224 innerGraphState.currentTopLevelSymbol = symbol;
225 }
226};
227
228/**
229 * @param {ParserState} state parser state
230 * @returns {TopLevelSymbol|void} usage data
231 */
232exports.getTopLevelSymbol = state => {
233 const innerGraphState = getState(state);
234
235 if (innerGraphState) {
236 return innerGraphState.currentTopLevelSymbol;
237 }
238};
239
240/**
241 * @param {JavascriptParser} parser parser
242 * @param {string} name name of variable
243 * @returns {TopLevelSymbol} symbol
244 */
245exports.tagTopLevelSymbol = (parser, name) => {
246 const innerGraphState = getState(parser.state);
247 if (!innerGraphState) return;
248
249 parser.defineVariable(name);
250
251 const existingTag = /** @type {TopLevelSymbol} */ (
252 parser.getTagData(name, topLevelSymbolTag)
253 );
254 if (existingTag) {
255 return existingTag;
256 }
257
258 const fn = new TopLevelSymbol(name);
259 parser.tagVariable(name, topLevelSymbolTag, fn);
260 return fn;
261};
262
263/**
264 * @param {Dependency} dependency the dependency
265 * @param {Set<string> | boolean} usedByExports usedByExports info
266 * @param {ModuleGraph} moduleGraph moduleGraph
267 * @param {RuntimeSpec} runtime runtime
268 * @returns {boolean} false, when unused. Otherwise true
269 */
270exports.isDependencyUsedByExports = (
271 dependency,
272 usedByExports,
273 moduleGraph,
274 runtime
275) => {
276 if (usedByExports === false) return false;
277 if (usedByExports !== true && usedByExports !== undefined) {
278 const selfModule = moduleGraph.getParentModule(dependency);
279 const exportsInfo = moduleGraph.getExportsInfo(selfModule);
280 let used = false;
281 for (const exportName of usedByExports) {
282 if (exportsInfo.getUsed(exportName, runtime) !== UsageState.Unused)
283 used = true;
284 }
285 if (!used) return false;
286 }
287 return true;
288};
289
290/**
291 * @param {Dependency} dependency the dependency
292 * @param {Set<string> | boolean} usedByExports usedByExports info
293 * @param {ModuleGraph} moduleGraph moduleGraph
294 * @returns {null | false | function(ModuleGraphConnection, RuntimeSpec): ConnectionState} function to determine if the connection is active
295 */
296exports.getDependencyUsedByExportsCondition = (
297 dependency,
298 usedByExports,
299 moduleGraph
300) => {
301 if (usedByExports === false) return false;
302 if (usedByExports !== true && usedByExports !== undefined) {
303 const selfModule = moduleGraph.getParentModule(dependency);
304 const exportsInfo = moduleGraph.getExportsInfo(selfModule);
305 return (connections, runtime) => {
306 for (const exportName of usedByExports) {
307 if (exportsInfo.getUsed(exportName, runtime) !== UsageState.Unused)
308 return true;
309 }
310 return false;
311 };
312 }
313 return null;
314};
315
316class TopLevelSymbol {
317 /**
318 * @param {string} name name of the variable
319 */
320 constructor(name) {
321 this.name = name;
322 }
323}
324
325exports.TopLevelSymbol = TopLevelSymbol;
326exports.topLevelSymbolTag = topLevelSymbolTag;
Note: See TracBrowser for help on using the repository browser.