source: imaps-frontend/node_modules/webpack/lib/dependencies/ContextDependencyHelpers.js@ 79a0317

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

F4 Finalna Verzija

  • Property mode set to 100644
File size: 7.7 KB
RevLine 
[79a0317]1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const { parseResource } = require("../util/identifier");
9
10/** @typedef {import("estree").Node} EsTreeNode */
11/** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
12/** @typedef {import("../../declarations/WebpackOptions").ModuleOptionsNormalized} ModuleOptions */
13/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
14/** @typedef {import("../javascript/BasicEvaluatedExpression")} BasicEvaluatedExpression */
15/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
16/** @typedef {import("../javascript/JavascriptParser").Range} Range */
17/** @typedef {import("./ContextDependency")} ContextDependency */
18/** @typedef {import("./ContextDependency").ContextDependencyOptions} ContextDependencyOptions */
19
20/**
21 * Escapes regular expression metacharacters
22 * @param {string} str String to quote
23 * @returns {string} Escaped string
24 */
25const quoteMeta = str => str.replace(/[-[\]\\/{}()*+?.^$|]/g, "\\$&");
26
27/**
28 * @param {string} prefix prefix
29 * @returns {{prefix: string, context: string}} result
30 */
31const splitContextFromPrefix = prefix => {
32 const idx = prefix.lastIndexOf("/");
33 let context = ".";
34 if (idx >= 0) {
35 context = prefix.slice(0, idx);
36 prefix = `.${prefix.slice(idx)}`;
37 }
38 return {
39 context,
40 prefix
41 };
42};
43
44/** @typedef {Partial<Omit<ContextDependencyOptions, "resource">>} PartialContextDependencyOptions */
45/** @typedef {{ new(options: ContextDependencyOptions, range: Range, valueRange: [number, number], ...args: any[]): ContextDependency }} ContextDependencyConstructor */
46
47/**
48 * @param {ContextDependencyConstructor} Dep the Dependency class
49 * @param {Range} range source range
50 * @param {BasicEvaluatedExpression} param context param
51 * @param {EsTreeNode} expr expr
52 * @param {Pick<JavascriptParserOptions, `${"expr"|"wrapped"}Context${"Critical"|"Recursive"|"RegExp"}` | "exprContextRequest">} options options for context creation
53 * @param {PartialContextDependencyOptions} contextOptions options for the ContextModule
54 * @param {JavascriptParser} parser the parser
55 * @param {...any} depArgs depArgs
56 * @returns {ContextDependency} the created Dependency
57 */
58module.exports.create = (
59 Dep,
60 range,
61 param,
62 expr,
63 options,
64 contextOptions,
65 parser,
66 ...depArgs
67) => {
68 if (param.isTemplateString()) {
69 const quasis = /** @type {BasicEvaluatedExpression[]} */ (param.quasis);
70 const prefixRaw = /** @type {string} */ (quasis[0].string);
71 const postfixRaw =
72 /** @type {string} */
73 (quasis.length > 1 ? quasis[quasis.length - 1].string : "");
74
75 const valueRange = /** @type {Range} */ (param.range);
76 const { context, prefix } = splitContextFromPrefix(prefixRaw);
77 const {
78 path: postfix,
79 query,
80 fragment
81 } = parseResource(postfixRaw, parser);
82
83 // When there are more than two quasis, the generated RegExp can be more precise
84 // We join the quasis with the expression regexp
85 const innerQuasis = quasis.slice(1, -1);
86 const innerRegExp =
87 /** @type {RegExp} */ (options.wrappedContextRegExp).source +
88 innerQuasis
89 .map(
90 q =>
91 quoteMeta(/** @type {string} */ (q.string)) +
92 /** @type {RegExp} */ (options.wrappedContextRegExp).source
93 )
94 .join("");
95
96 // Example: `./context/pre${e}inner${e}inner2${e}post?query#frag`
97 // context: "./context"
98 // prefix: "./pre"
99 // innerQuasis: [BEE("inner"), BEE("inner2")]
100 // (BEE = BasicEvaluatedExpression)
101 // postfix: "post"
102 // query: "?query"
103 // fragment: "#frag"
104 // regExp: /^\.\/pre.*inner.*inner2.*post$/
105 const regExp = new RegExp(
106 `^${quoteMeta(prefix)}${innerRegExp}${quoteMeta(postfix)}$`
107 );
108 const dep = new Dep(
109 {
110 request: context + query + fragment,
111 recursive: /** @type {boolean} */ (options.wrappedContextRecursive),
112 regExp,
113 mode: "sync",
114 ...contextOptions
115 },
116 range,
117 valueRange,
118 ...depArgs
119 );
120 dep.loc = /** @type {DependencyLocation} */ (expr.loc);
121
122 /** @type {{ value: string, range: Range }[]} */
123 const replaces = [];
124 const parts = /** @type {BasicEvaluatedExpression[]} */ (param.parts);
125
126 for (const [i, part] of parts.entries()) {
127 if (i % 2 === 0) {
128 // Quasis or merged quasi
129 let range = /** @type {Range} */ (part.range);
130 let value = /** @type {string} */ (part.string);
131 if (param.templateStringKind === "cooked") {
132 value = JSON.stringify(value);
133 value = value.slice(1, -1);
134 }
135 if (i === 0) {
136 // prefix
137 value = prefix;
138 range = [
139 /** @type {Range} */ (param.range)[0],
140 /** @type {Range} */ (part.range)[1]
141 ];
142 value =
143 (param.templateStringKind === "cooked" ? "`" : "String.raw`") +
144 value;
145 } else if (i === parts.length - 1) {
146 // postfix
147 value = postfix;
148 range = [
149 /** @type {Range} */ (part.range)[0],
150 /** @type {Range} */ (param.range)[1]
151 ];
152 value = `${value}\``;
153 } else if (
154 part.expression &&
155 part.expression.type === "TemplateElement" &&
156 part.expression.value.raw === value
157 ) {
158 // Shortcut when it's a single quasi and doesn't need to be replaced
159 continue;
160 }
161 replaces.push({
162 range,
163 value
164 });
165 } else {
166 // Expression
167 parser.walkExpression(part.expression);
168 }
169 }
170
171 dep.replaces = replaces;
172 dep.critical =
173 options.wrappedContextCritical &&
174 "a part of the request of a dependency is an expression";
175 return dep;
176 } else if (
177 param.isWrapped() &&
178 ((param.prefix && param.prefix.isString()) ||
179 (param.postfix && param.postfix.isString()))
180 ) {
181 const prefixRaw =
182 /** @type {string} */
183 (param.prefix && param.prefix.isString() ? param.prefix.string : "");
184 const postfixRaw =
185 /** @type {string} */
186 (param.postfix && param.postfix.isString() ? param.postfix.string : "");
187 const prefixRange =
188 param.prefix && param.prefix.isString() ? param.prefix.range : null;
189 const postfixRange =
190 param.postfix && param.postfix.isString() ? param.postfix.range : null;
191 const valueRange = /** @type {Range} */ (param.range);
192 const { context, prefix } = splitContextFromPrefix(prefixRaw);
193 const {
194 path: postfix,
195 query,
196 fragment
197 } = parseResource(postfixRaw, parser);
198 const regExp = new RegExp(
199 `^${quoteMeta(prefix)}${
200 /** @type {RegExp} */ (options.wrappedContextRegExp).source
201 }${quoteMeta(postfix)}$`
202 );
203 const dep = new Dep(
204 {
205 request: context + query + fragment,
206 recursive: /** @type {boolean} */ (options.wrappedContextRecursive),
207 regExp,
208 mode: "sync",
209 ...contextOptions
210 },
211 range,
212 valueRange,
213 ...depArgs
214 );
215 dep.loc = /** @type {DependencyLocation} */ (expr.loc);
216 const replaces = [];
217 if (prefixRange) {
218 replaces.push({
219 range: prefixRange,
220 value: JSON.stringify(prefix)
221 });
222 }
223 if (postfixRange) {
224 replaces.push({
225 range: postfixRange,
226 value: JSON.stringify(postfix)
227 });
228 }
229 dep.replaces = replaces;
230 dep.critical =
231 options.wrappedContextCritical &&
232 "a part of the request of a dependency is an expression";
233
234 if (parser && param.wrappedInnerExpressions) {
235 for (const part of param.wrappedInnerExpressions) {
236 if (part.expression) parser.walkExpression(part.expression);
237 }
238 }
239
240 return dep;
241 }
242 const dep = new Dep(
243 {
244 request: /** @type {string} */ (options.exprContextRequest),
245 recursive: /** @type {boolean} */ (options.exprContextRecursive),
246 regExp: /** @type {RegExp} */ (options.exprContextRegExp),
247 mode: "sync",
248 ...contextOptions
249 },
250 range,
251 /** @type {Range} */ (param.range),
252 ...depArgs
253 );
254 dep.loc = /** @type {DependencyLocation} */ (expr.loc);
255 dep.critical =
256 options.exprContextCritical &&
257 "the request of a dependency is an expression";
258
259 parser.walkExpression(param.expression);
260
261 return dep;
262};
Note: See TracBrowser for help on using the repository browser.