source: trip-planner-front/node_modules/webpack/lib/dependencies/ContextDependencyHelpers.js@ 59329aa

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

initial commit

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