source: frontend/node_modules/webpack/lib/dependencies/ImportMetaContextDependencyParserPlugin.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: 9.6 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Ivan Kopeykin @vankop
4*/
5
6"use strict";
7
8const WebpackError = require("../errors/WebpackError");
9const {
10 evaluateToIdentifier
11} = require("../javascript/JavascriptParserHelpers");
12const ImportMetaContextDependency = require("./ImportMetaContextDependency");
13
14/** @typedef {import("estree").Expression} Expression */
15/** @typedef {import("estree").ObjectExpression} ObjectExpression */
16/** @typedef {import("estree").Property} Property */
17/** @typedef {import("estree").Identifier} Identifier */
18/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
19/** @typedef {import("../javascript/JavascriptParser").Range} Range */
20/** @typedef {import("../ContextModule").ContextModuleOptions} ContextModuleOptions */
21/** @typedef {import("../ContextModule").ContextMode} ContextMode */
22/** @typedef {import("../Chunk").ChunkName} ChunkName */
23/** @typedef {import("../ChunkGroup").RawChunkGroupOptions} RawChunkGroupOptions */
24/** @typedef {import("../Dependency").RawReferencedExports} RawReferencedExports */
25/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
26/** @typedef {import("../javascript/BasicEvaluatedExpression")} BasicEvaluatedExpression */
27
28/** @typedef {Pick<ContextModuleOptions, "mode" | "recursive" | "regExp" | "include" | "exclude" | "chunkName"> & { groupOptions: RawChunkGroupOptions, exports?: RawReferencedExports }} ImportMetaContextOptions */
29
30/**
31 * Creates a property parse error.
32 * @param {Property} prop property
33 * @param {string} expect except message
34 * @returns {WebpackError} error
35 */
36function createPropertyParseError(prop, expect) {
37 return createError(
38 `Parsing import.meta.webpackContext options failed. Unknown value for property ${JSON.stringify(
39 /** @type {Identifier} */
40 (prop.key).name
41 )}, expected type ${expect}.`,
42 /** @type {DependencyLocation} */
43 (prop.value.loc)
44 );
45}
46
47/**
48 * Creates an error from the provided msg.
49 * @param {string} msg message
50 * @param {DependencyLocation} loc location
51 * @returns {WebpackError} error
52 */
53function createError(msg, loc) {
54 const error = new WebpackError(msg);
55 error.name = "ImportMetaContextError";
56 error.loc = loc;
57 return error;
58}
59
60const PLUGIN_NAME = "ImportMetaContextDependencyParserPlugin";
61
62module.exports = class ImportMetaContextDependencyParserPlugin {
63 /**
64 * Applies the plugin by registering its hooks on the compiler.
65 * @param {JavascriptParser} parser the parser
66 * @returns {void}
67 */
68 apply(parser) {
69 parser.hooks.evaluateIdentifier
70 .for("import.meta.webpackContext")
71 .tap(PLUGIN_NAME, (expr) =>
72 evaluateToIdentifier(
73 "import.meta.webpackContext",
74 "import.meta",
75 () => ["webpackContext"],
76 true
77 )(expr)
78 );
79 parser.hooks.call
80 .for("import.meta.webpackContext")
81 .tap(PLUGIN_NAME, (expr) => {
82 if (expr.arguments.length < 1 || expr.arguments.length > 2) return;
83 const [directoryNode, optionsNode] = expr.arguments;
84 if (optionsNode && optionsNode.type !== "ObjectExpression") return;
85 const requestExpr = parser.evaluateExpression(
86 /** @type {Expression} */ (directoryNode)
87 );
88 if (!requestExpr.isString()) return;
89 const request = /** @type {string} */ (requestExpr.string);
90 /** @type {WebpackError[]} */
91 const errors = [];
92 let regExp = /^\.\/.*$/;
93 let recursive = true;
94 /** @type {ContextMode} */
95 let mode = "sync";
96 /** @type {ContextModuleOptions["include"]} */
97 let include;
98 /** @type {ContextModuleOptions["exclude"]} */
99 let exclude;
100 /** @type {RawChunkGroupOptions} */
101 const groupOptions = {};
102 /** @type {ChunkName | undefined} */
103 let chunkName;
104 /** @type {RawReferencedExports | undefined} */
105 let exports;
106 if (optionsNode) {
107 for (const prop of /** @type {ObjectExpression} */ (optionsNode)
108 .properties) {
109 if (prop.type !== "Property" || prop.key.type !== "Identifier") {
110 errors.push(
111 createError(
112 "Parsing import.meta.webpackContext options failed.",
113 /** @type {DependencyLocation} */
114 (optionsNode.loc)
115 )
116 );
117 break;
118 }
119 switch (prop.key.name) {
120 case "regExp": {
121 const regExpExpr = parser.evaluateExpression(
122 /** @type {Expression} */ (prop.value)
123 );
124 if (!regExpExpr.isRegExp()) {
125 errors.push(createPropertyParseError(prop, "RegExp"));
126 } else {
127 regExp = /** @type {RegExp} */ (regExpExpr.regExp);
128 }
129 break;
130 }
131 case "include": {
132 const regExpExpr = parser.evaluateExpression(
133 /** @type {Expression} */ (prop.value)
134 );
135 if (!regExpExpr.isRegExp()) {
136 errors.push(createPropertyParseError(prop, "RegExp"));
137 } else {
138 include = regExpExpr.regExp;
139 }
140 break;
141 }
142 case "exclude": {
143 const regExpExpr = parser.evaluateExpression(
144 /** @type {Expression} */ (prop.value)
145 );
146 if (!regExpExpr.isRegExp()) {
147 errors.push(createPropertyParseError(prop, "RegExp"));
148 } else {
149 exclude = regExpExpr.regExp;
150 }
151 break;
152 }
153 case "mode": {
154 const modeExpr = parser.evaluateExpression(
155 /** @type {Expression} */ (prop.value)
156 );
157 if (!modeExpr.isString()) {
158 errors.push(createPropertyParseError(prop, "string"));
159 } else {
160 mode = /** @type {ContextModuleOptions["mode"]} */ (
161 modeExpr.string
162 );
163 }
164 break;
165 }
166 case "chunkName": {
167 const expr = parser.evaluateExpression(
168 /** @type {Expression} */ (prop.value)
169 );
170 if (!expr.isString()) {
171 errors.push(createPropertyParseError(prop, "string"));
172 } else {
173 chunkName = expr.string;
174 }
175 break;
176 }
177 case "exports": {
178 const expr = parser.evaluateExpression(
179 /** @type {Expression} */ (prop.value)
180 );
181 if (expr.isString()) {
182 exports = [[/** @type {string} */ (expr.string)]];
183 } else if (expr.isArray()) {
184 const items =
185 /** @type {BasicEvaluatedExpression[]} */
186 (expr.items);
187 if (
188 items.every((i) => {
189 if (!i.isArray()) return false;
190 const innerItems =
191 /** @type {BasicEvaluatedExpression[]} */ (i.items);
192 return innerItems.every((i) => i.isString());
193 })
194 ) {
195 exports = [];
196
197 for (const i1 of items) {
198 /** @type {string[]} */
199 const export_ = [];
200 for (const i2 of /** @type {BasicEvaluatedExpression[]} */ (
201 i1.items
202 )) {
203 export_.push(/** @type {string} */ (i2.string));
204 }
205 exports.push(export_);
206 }
207 } else {
208 errors.push(
209 createPropertyParseError(prop, "string|string[][]")
210 );
211 }
212 } else {
213 errors.push(
214 createPropertyParseError(prop, "string|string[][]")
215 );
216 }
217 break;
218 }
219 case "prefetch": {
220 const expr = parser.evaluateExpression(
221 /** @type {Expression} */ (prop.value)
222 );
223 if (expr.isBoolean()) {
224 groupOptions.prefetchOrder = 0;
225 } else if (expr.isNumber()) {
226 groupOptions.prefetchOrder = expr.number;
227 } else {
228 errors.push(createPropertyParseError(prop, "boolean|number"));
229 }
230 break;
231 }
232 case "preload": {
233 const expr = parser.evaluateExpression(
234 /** @type {Expression} */ (prop.value)
235 );
236 if (expr.isBoolean()) {
237 groupOptions.preloadOrder = 0;
238 } else if (expr.isNumber()) {
239 groupOptions.preloadOrder = expr.number;
240 } else {
241 errors.push(createPropertyParseError(prop, "boolean|number"));
242 }
243 break;
244 }
245 case "fetchPriority": {
246 const expr = parser.evaluateExpression(
247 /** @type {Expression} */ (prop.value)
248 );
249 if (
250 expr.isString() &&
251 ["high", "low", "auto"].includes(
252 /** @type {string} */ (expr.string)
253 )
254 ) {
255 groupOptions.fetchPriority =
256 /** @type {RawChunkGroupOptions["fetchPriority"]} */ (
257 expr.string
258 );
259 } else {
260 errors.push(
261 createPropertyParseError(prop, '"high"|"low"|"auto"')
262 );
263 }
264 break;
265 }
266 case "recursive": {
267 const recursiveExpr = parser.evaluateExpression(
268 /** @type {Expression} */ (prop.value)
269 );
270 if (!recursiveExpr.isBoolean()) {
271 errors.push(createPropertyParseError(prop, "boolean"));
272 } else {
273 recursive = /** @type {boolean} */ (recursiveExpr.bool);
274 }
275 break;
276 }
277 default:
278 errors.push(
279 createError(
280 `Parsing import.meta.webpackContext options failed. Unknown property ${JSON.stringify(
281 prop.key.name
282 )}.`,
283 /** @type {DependencyLocation} */ (optionsNode.loc)
284 )
285 );
286 }
287 }
288 }
289 if (errors.length) {
290 for (const error of errors) parser.state.current.addError(error);
291 return;
292 }
293
294 const dep = new ImportMetaContextDependency(
295 {
296 request,
297 include,
298 exclude,
299 recursive,
300 regExp,
301 groupOptions,
302 chunkName,
303 referencedExports: exports,
304 mode,
305 category: "esm"
306 },
307 /** @type {Range} */ (expr.range)
308 );
309 dep.loc = /** @type {DependencyLocation} */ (expr.loc);
310 dep.optional = Boolean(parser.scope.inTry);
311 parser.state.current.addDependency(dep);
312 return true;
313 });
314 }
315};
Note: See TracBrowser for help on using the repository browser.