source: frontend/node_modules/webpack/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 12.9 KB
RevLine 
[9af201e]1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const RuntimeGlobals = require("../RuntimeGlobals");
9const UnsupportedFeatureWarning = require("../errors/UnsupportedFeatureWarning");
10const AMDRequireArrayDependency = require("./AMDRequireArrayDependency");
11const AMDRequireContextDependency = require("./AMDRequireContextDependency");
12const AMDRequireDependenciesBlock = require("./AMDRequireDependenciesBlock");
13const AMDRequireDependency = require("./AMDRequireDependency");
14const AMDRequireItemDependency = require("./AMDRequireItemDependency");
15const ConstDependency = require("./ConstDependency");
16const ContextDependencyHelpers = require("./ContextDependencyHelpers");
17const LocalModuleDependency = require("./LocalModuleDependency");
18const { getLocalModule } = require("./LocalModulesHelpers");
19const UnsupportedDependency = require("./UnsupportedDependency");
20const getFunctionExpression = require("./getFunctionExpression");
21
22/** @typedef {import("estree").CallExpression} CallExpression */
23/** @typedef {import("estree").Expression} Expression */
24/** @typedef {import("estree").Identifier} Identifier */
25/** @typedef {import("estree").SourceLocation} SourceLocation */
26/** @typedef {import("estree").SpreadElement} SpreadElement */
27/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
28/** @typedef {import("../Dependency")} Dependency */
29/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
30/** @typedef {import("../javascript/BasicEvaluatedExpression")} BasicEvaluatedExpression */
31/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
32/** @typedef {import("../javascript/JavascriptParser").Range} Range */
33/** @typedef {import("./LocalModule")} LocalModule */
34
35const PLUGIN_NAME = "AMDRequireDependenciesBlockParserPlugin";
36
37class AMDRequireDependenciesBlockParserPlugin {
38 /**
39 * Creates an instance of AMDRequireDependenciesBlockParserPlugin.
40 * @param {JavascriptParserOptions} options parserOptions
41 */
42 constructor(options) {
43 this.options = options;
44 }
45
46 /**
47 * Process function argument.
48 * @param {JavascriptParser} parser the parser
49 * @param {Expression | SpreadElement} expression expression
50 * @returns {boolean} need bind this
51 */
52 processFunctionArgument(parser, expression) {
53 let bindThis = true;
54 const fnData = getFunctionExpression(expression);
55 if (fnData) {
56 parser.inFunctionScope(
57 true,
58 fnData.fn.params.filter(
59 (i) =>
60 !["require", "module", "exports"].includes(
61 /** @type {Identifier} */ (i).name
62 )
63 ),
64 () => {
65 if (fnData.fn.body.type === "BlockStatement") {
66 parser.walkStatement(fnData.fn.body);
67 } else {
68 parser.walkExpression(fnData.fn.body);
69 }
70 }
71 );
72 parser.walkExpressions(fnData.expressions);
73 if (fnData.needThis === false) {
74 bindThis = false;
75 }
76 } else {
77 parser.walkExpression(expression);
78 }
79 return bindThis;
80 }
81
82 /**
83 * Applies the plugin by registering its hooks on the compiler.
84 * @param {JavascriptParser} parser the parser
85 * @returns {void}
86 */
87 apply(parser) {
88 parser.hooks.call
89 .for("require")
90 .tap(PLUGIN_NAME, this.processCallRequire.bind(this, parser));
91 }
92
93 /**
94 * Processes the provided parser.
95 * @param {JavascriptParser} parser the parser
96 * @param {CallExpression} expr call expression
97 * @param {BasicEvaluatedExpression} param param
98 * @returns {boolean | undefined} result
99 */
100 processArray(parser, expr, param) {
101 if (param.isArray()) {
102 for (const p of /** @type {BasicEvaluatedExpression[]} */ (param.items)) {
103 const result = this.processItem(parser, expr, p);
104 if (result === undefined) {
105 this.processContext(parser, expr, p);
106 }
107 }
108 return true;
109 } else if (param.isConstArray()) {
110 /** @type {(string | LocalModuleDependency | AMDRequireItemDependency)[]} */
111 const deps = [];
112 for (const request of /** @type {string[]} */ (param.array)) {
113 /** @type {string | LocalModuleDependency | AMDRequireItemDependency} */
114 let dep;
115 /** @type {undefined | null | LocalModule} */
116 let localModule;
117 if (request === "require") {
118 dep = RuntimeGlobals.require;
119 } else if (["exports", "module"].includes(request)) {
120 dep = request;
121 } else if ((localModule = getLocalModule(parser.state, request))) {
122 localModule.flagUsed();
123 dep = new LocalModuleDependency(localModule, undefined, false);
124 dep.loc = /** @type {DependencyLocation} */ (expr.loc);
125 parser.state.module.addPresentationalDependency(dep);
126 } else {
127 dep = this.newRequireItemDependency(request);
128 dep.loc = /** @type {DependencyLocation} */ (expr.loc);
129 dep.optional = Boolean(parser.scope.inTry);
130 parser.state.current.addDependency(dep);
131 }
132 deps.push(dep);
133 }
134 const dep = this.newRequireArrayDependency(
135 deps,
136 /** @type {Range} */
137 (param.range)
138 );
139 dep.loc = /** @type {DependencyLocation} */ (expr.loc);
140 dep.optional = Boolean(parser.scope.inTry);
141 parser.state.module.addPresentationalDependency(dep);
142 return true;
143 }
144 }
145
146 /**
147 * Processes the provided parser.
148 * @param {JavascriptParser} parser the parser
149 * @param {CallExpression} expr call expression
150 * @param {BasicEvaluatedExpression} param param
151 * @returns {boolean | undefined} result
152 */
153 processItem(parser, expr, param) {
154 if (param.isConditional()) {
155 for (const p of /** @type {BasicEvaluatedExpression[]} */ (
156 param.options
157 )) {
158 const result = this.processItem(parser, expr, p);
159 if (result === undefined) {
160 this.processContext(parser, expr, p);
161 }
162 }
163 return true;
164 } else if (param.isString()) {
165 /** @type {Dependency} */
166 let dep;
167 /** @type {LocalModule | null | undefined} */
168 let localModule;
169 if (param.string === "require") {
170 dep = new ConstDependency(
171 RuntimeGlobals.require,
172 /** @type {Range} */
173 (param.range),
174 [RuntimeGlobals.require]
175 );
176 } else if (param.string === "module") {
177 dep = new ConstDependency(
178 parser.state.module.moduleArgument,
179 /** @type {Range} */
180 (param.range),
181 [RuntimeGlobals.module]
182 );
183 } else if (param.string === "exports") {
184 dep = new ConstDependency(
185 parser.state.module.exportsArgument,
186 /** @type {Range} */
187 (param.range),
188 [RuntimeGlobals.exports]
189 );
190 } else if (
191 (localModule = getLocalModule(
192 parser.state,
193 /** @type {string} */
194 (param.string)
195 ))
196 ) {
197 localModule.flagUsed();
198 dep = new LocalModuleDependency(localModule, param.range, false);
199 } else {
200 dep = this.newRequireItemDependency(
201 /** @type {string} */
202 (param.string),
203 param.range
204 );
205 dep.loc = /** @type {DependencyLocation} */ (expr.loc);
206 dep.optional = Boolean(parser.scope.inTry);
207 parser.state.current.addDependency(dep);
208 return true;
209 }
210 dep.loc = /** @type {DependencyLocation} */ (expr.loc);
211 parser.state.module.addPresentationalDependency(dep);
212 return true;
213 }
214 }
215
216 /**
217 * Processes the provided parser.
218 * @param {JavascriptParser} parser the parser
219 * @param {CallExpression} expr call expression
220 * @param {BasicEvaluatedExpression} param param
221 * @returns {boolean | undefined} result
222 */
223 processContext(parser, expr, param) {
224 const dep = ContextDependencyHelpers.create(
225 AMDRequireContextDependency,
226 /** @type {Range} */
227 (param.range),
228 param,
229 expr,
230 this.options,
231 {
232 category: "amd"
233 },
234 parser
235 );
236 if (!dep) return;
237 dep.loc = /** @type {DependencyLocation} */ (expr.loc);
238 dep.optional = Boolean(parser.scope.inTry);
239 parser.state.current.addDependency(dep);
240 return true;
241 }
242
243 /**
244 * Process array for request string.
245 * @param {BasicEvaluatedExpression} param param
246 * @returns {string | undefined} result
247 */
248 processArrayForRequestString(param) {
249 if (param.isArray()) {
250 const result =
251 /** @type {BasicEvaluatedExpression[]} */
252 (param.items).map((item) => this.processItemForRequestString(item));
253 if (result.every(Boolean)) return result.join(" ");
254 } else if (param.isConstArray()) {
255 return /** @type {string[]} */ (param.array).join(" ");
256 }
257 }
258
259 /**
260 * Process item for request string.
261 * @param {BasicEvaluatedExpression} param param
262 * @returns {string | undefined} result
263 */
264 processItemForRequestString(param) {
265 if (param.isConditional()) {
266 const result =
267 /** @type {BasicEvaluatedExpression[]} */
268 (param.options).map((item) => this.processItemForRequestString(item));
269 if (result.every(Boolean)) return result.join("|");
270 } else if (param.isString()) {
271 return param.string;
272 }
273 }
274
275 /**
276 * Process call require.
277 * @param {JavascriptParser} parser the parser
278 * @param {CallExpression} expr call expression
279 * @returns {boolean | undefined} result
280 */
281 processCallRequire(parser, expr) {
282 /** @type {BasicEvaluatedExpression | undefined} */
283 let param;
284 /** @type {AMDRequireDependenciesBlock | undefined | null} */
285 let depBlock;
286 /** @type {AMDRequireDependency | undefined} */
287 let dep;
288 /** @type {boolean | undefined} */
289 let result;
290
291 const old = parser.state.current;
292
293 if (expr.arguments.length >= 1) {
294 param = parser.evaluateExpression(
295 /** @type {Expression} */ (expr.arguments[0])
296 );
297 depBlock = this.newRequireDependenciesBlock(
298 /** @type {DependencyLocation} */ (expr.loc),
299 this.processArrayForRequestString(param)
300 );
301 dep = this.newRequireDependency(
302 /** @type {Range} */ (expr.range),
303 /** @type {Range} */ (param.range),
304 expr.arguments.length > 1
305 ? /** @type {Range} */ (expr.arguments[1].range)
306 : null,
307 expr.arguments.length > 2
308 ? /** @type {Range} */ (expr.arguments[2].range)
309 : null
310 );
311 dep.loc = /** @type {DependencyLocation} */ (expr.loc);
312 depBlock.addDependency(dep);
313
314 parser.state.current = /** @type {EXPECTED_ANY} */ (depBlock);
315 }
316
317 if (expr.arguments.length === 1) {
318 parser.inFunctionScope(true, [], () => {
319 result = this.processArray(
320 parser,
321 expr,
322 /** @type {BasicEvaluatedExpression} */
323 (param)
324 );
325 });
326 parser.state.current = old;
327 if (!result) return;
328 parser.state.current.addBlock(
329 /** @type {AMDRequireDependenciesBlock} */
330 (depBlock)
331 );
332 return true;
333 }
334
335 if (expr.arguments.length === 2 || expr.arguments.length === 3) {
336 try {
337 parser.inFunctionScope(true, [], () => {
338 result = this.processArray(
339 parser,
340 expr,
341 /** @type {BasicEvaluatedExpression} */
342 (param)
343 );
344 });
345 if (!result) {
346 const dep = new UnsupportedDependency(
347 "unsupported",
348 /** @type {Range} */
349 (expr.range)
350 );
351 old.addPresentationalDependency(dep);
352 if (parser.state.module) {
353 parser.state.module.addError(
354 new UnsupportedFeatureWarning(
355 `Cannot statically analyse 'require(…, …)' in line ${
356 /** @type {SourceLocation} */ (expr.loc).start.line
357 }`,
358 /** @type {DependencyLocation} */
359 (expr.loc)
360 )
361 );
362 }
363 depBlock = null;
364 return true;
365 }
366 /** @type {AMDRequireDependency} */
367 (dep).functionBindThis = this.processFunctionArgument(
368 parser,
369 expr.arguments[1]
370 );
371 if (expr.arguments.length === 3) {
372 /** @type {AMDRequireDependency} */
373 (dep).errorCallbackBindThis = this.processFunctionArgument(
374 parser,
375 expr.arguments[2]
376 );
377 }
378 } finally {
379 parser.state.current = old;
380 if (depBlock) parser.state.current.addBlock(depBlock);
381 }
382 return true;
383 }
384 }
385
386 /**
387 * New require dependencies block.
388 * @param {DependencyLocation} loc location
389 * @param {string=} request request
390 * @returns {AMDRequireDependenciesBlock} AMDRequireDependenciesBlock
391 */
392 newRequireDependenciesBlock(loc, request) {
393 return new AMDRequireDependenciesBlock(loc, request);
394 }
395
396 /**
397 * New require dependency.
398 * @param {Range} outerRange outer range
399 * @param {Range} arrayRange array range
400 * @param {Range | null} functionRange function range
401 * @param {Range | null} errorCallbackRange error callback range
402 * @returns {AMDRequireDependency} dependency
403 */
404 newRequireDependency(
405 outerRange,
406 arrayRange,
407 functionRange,
408 errorCallbackRange
409 ) {
410 return new AMDRequireDependency(
411 outerRange,
412 arrayRange,
413 functionRange,
414 errorCallbackRange
415 );
416 }
417
418 /**
419 * New require item dependency.
420 * @param {string} request request
421 * @param {Range=} range range
422 * @returns {AMDRequireItemDependency} AMDRequireItemDependency
423 */
424 newRequireItemDependency(request, range) {
425 return new AMDRequireItemDependency(request, range);
426 }
427
428 /**
429 * New require array dependency.
430 * @param {(string | LocalModuleDependency | AMDRequireItemDependency)[]} depsArray deps array
431 * @param {Range} range range
432 * @returns {AMDRequireArrayDependency} AMDRequireArrayDependency
433 */
434 newRequireArrayDependency(depsArray, range) {
435 return new AMDRequireArrayDependency(depsArray, range);
436 }
437}
438
439module.exports = AMDRequireDependenciesBlockParserPlugin;
Note: See TracBrowser for help on using the repository browser.