1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | "use strict";
|
7 |
|
8 | const CommentCompilationWarning = require("../CommentCompilationWarning");
|
9 | const RuntimeGlobals = require("../RuntimeGlobals");
|
10 | const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
|
11 | const {
|
12 | evaluateToIdentifier,
|
13 | evaluateToString,
|
14 | expressionIsUnsupported,
|
15 | toConstantDependency
|
16 | } = require("../javascript/JavascriptParserHelpers");
|
17 | const CommonJsFullRequireDependency = require("./CommonJsFullRequireDependency");
|
18 | const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency");
|
19 | const CommonJsRequireDependency = require("./CommonJsRequireDependency");
|
20 | const ConstDependency = require("./ConstDependency");
|
21 | const ContextDependencyHelpers = require("./ContextDependencyHelpers");
|
22 | const LocalModuleDependency = require("./LocalModuleDependency");
|
23 | const { getLocalModule } = require("./LocalModulesHelpers");
|
24 | const RequireHeaderDependency = require("./RequireHeaderDependency");
|
25 | const RequireResolveContextDependency = require("./RequireResolveContextDependency");
|
26 | const RequireResolveDependency = require("./RequireResolveDependency");
|
27 | const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency");
|
28 |
|
29 |
|
30 |
|
31 | class CommonJsImportsParserPlugin {
|
32 | |
33 |
|
34 |
|
35 | constructor(options) {
|
36 | this.options = options;
|
37 | }
|
38 |
|
39 | apply(parser) {
|
40 | const options = this.options;
|
41 |
|
42 |
|
43 | const tapRequireExpression = (expression, getMembers) => {
|
44 | parser.hooks.typeof
|
45 | .for(expression)
|
46 | .tap(
|
47 | "CommonJsPlugin",
|
48 | toConstantDependency(parser, JSON.stringify("function"))
|
49 | );
|
50 | parser.hooks.evaluateTypeof
|
51 | .for(expression)
|
52 | .tap("CommonJsPlugin", evaluateToString("function"));
|
53 | parser.hooks.evaluateIdentifier
|
54 | .for(expression)
|
55 | .tap(
|
56 | "CommonJsPlugin",
|
57 | evaluateToIdentifier(expression, "require", getMembers, true)
|
58 | );
|
59 | };
|
60 | tapRequireExpression("require", () => []);
|
61 | tapRequireExpression("require.resolve", () => ["resolve"]);
|
62 | tapRequireExpression("require.resolveWeak", () => ["resolveWeak"]);
|
63 |
|
64 |
|
65 | parser.hooks.assign.for("require").tap("CommonJsPlugin", expr => {
|
66 |
|
67 | const dep = new ConstDependency("var require;", 0);
|
68 | dep.loc = expr.loc;
|
69 | parser.state.module.addPresentationalDependency(dep);
|
70 | return true;
|
71 | });
|
72 |
|
73 |
|
74 | parser.hooks.expression
|
75 | .for("require.main.require")
|
76 | .tap(
|
77 | "CommonJsPlugin",
|
78 | expressionIsUnsupported(
|
79 | parser,
|
80 | "require.main.require is not supported by webpack."
|
81 | )
|
82 | );
|
83 | parser.hooks.call
|
84 | .for("require.main.require")
|
85 | .tap(
|
86 | "CommonJsPlugin",
|
87 | expressionIsUnsupported(
|
88 | parser,
|
89 | "require.main.require is not supported by webpack."
|
90 | )
|
91 | );
|
92 | parser.hooks.expression
|
93 | .for("module.parent.require")
|
94 | .tap(
|
95 | "CommonJsPlugin",
|
96 | expressionIsUnsupported(
|
97 | parser,
|
98 | "module.parent.require is not supported by webpack."
|
99 | )
|
100 | );
|
101 | parser.hooks.call
|
102 | .for("module.parent.require")
|
103 | .tap(
|
104 | "CommonJsPlugin",
|
105 | expressionIsUnsupported(
|
106 | parser,
|
107 | "module.parent.require is not supported by webpack."
|
108 | )
|
109 | );
|
110 |
|
111 |
|
112 | parser.hooks.canRename.for("require").tap("CommonJsPlugin", () => true);
|
113 | parser.hooks.rename.for("require").tap("CommonJsPlugin", expr => {
|
114 |
|
115 | const dep = new ConstDependency("undefined", expr.range);
|
116 | dep.loc = expr.loc;
|
117 | parser.state.module.addPresentationalDependency(dep);
|
118 | return false;
|
119 | });
|
120 |
|
121 |
|
122 | parser.hooks.expression
|
123 | .for("require.cache")
|
124 | .tap(
|
125 | "CommonJsImportsParserPlugin",
|
126 | toConstantDependency(parser, RuntimeGlobals.moduleCache, [
|
127 | RuntimeGlobals.moduleCache,
|
128 | RuntimeGlobals.moduleId,
|
129 | RuntimeGlobals.moduleLoaded
|
130 | ])
|
131 | );
|
132 |
|
133 |
|
134 | parser.hooks.expression
|
135 | .for("require")
|
136 | .tap("CommonJsImportsParserPlugin", expr => {
|
137 | const dep = new CommonJsRequireContextDependency(
|
138 | {
|
139 | request: options.unknownContextRequest,
|
140 | recursive: options.unknownContextRecursive,
|
141 | regExp: options.unknownContextRegExp,
|
142 | mode: "sync"
|
143 | },
|
144 | expr.range,
|
145 | undefined,
|
146 | parser.scope.inShorthand
|
147 | );
|
148 | dep.critical =
|
149 | options.unknownContextCritical &&
|
150 | "require function is used in a way in which dependencies cannot be statically extracted";
|
151 | dep.loc = expr.loc;
|
152 | dep.optional = !!parser.scope.inTry;
|
153 | parser.state.current.addDependency(dep);
|
154 | return true;
|
155 | });
|
156 |
|
157 |
|
158 | const processRequireItem = (expr, param) => {
|
159 | if (param.isString()) {
|
160 | const dep = new CommonJsRequireDependency(param.string, param.range);
|
161 | dep.loc = expr.loc;
|
162 | dep.optional = !!parser.scope.inTry;
|
163 | parser.state.current.addDependency(dep);
|
164 | return true;
|
165 | }
|
166 | };
|
167 | const processRequireContext = (expr, param) => {
|
168 | const dep = ContextDependencyHelpers.create(
|
169 | CommonJsRequireContextDependency,
|
170 | expr.range,
|
171 | param,
|
172 | expr,
|
173 | options,
|
174 | {
|
175 | category: "commonjs"
|
176 | },
|
177 | parser
|
178 | );
|
179 | if (!dep) return;
|
180 | dep.loc = expr.loc;
|
181 | dep.optional = !!parser.scope.inTry;
|
182 | parser.state.current.addDependency(dep);
|
183 | return true;
|
184 | };
|
185 | const createRequireHandler = callNew => expr => {
|
186 | if (options.commonjsMagicComments) {
|
187 | const { options: requireOptions, errors: commentErrors } =
|
188 | parser.parseCommentOptions(expr.range);
|
189 |
|
190 | if (commentErrors) {
|
191 | for (const e of commentErrors) {
|
192 | const { comment } = e;
|
193 | parser.state.module.addWarning(
|
194 | new CommentCompilationWarning(
|
195 | `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
|
196 | comment.loc
|
197 | )
|
198 | );
|
199 | }
|
200 | }
|
201 | if (requireOptions) {
|
202 | if (requireOptions.webpackIgnore !== undefined) {
|
203 | if (typeof requireOptions.webpackIgnore !== "boolean") {
|
204 | parser.state.module.addWarning(
|
205 | new UnsupportedFeatureWarning(
|
206 | `\`webpackIgnore\` expected a boolean, but received: ${requireOptions.webpackIgnore}.`,
|
207 | expr.loc
|
208 | )
|
209 | );
|
210 | } else {
|
211 |
|
212 | if (requireOptions.webpackIgnore) {
|
213 | return true;
|
214 | }
|
215 | }
|
216 | }
|
217 | }
|
218 | }
|
219 |
|
220 | if (expr.arguments.length !== 1) return;
|
221 | let localModule;
|
222 | const param = parser.evaluateExpression(expr.arguments[0]);
|
223 | if (param.isConditional()) {
|
224 | let isExpression = false;
|
225 | for (const p of param.options) {
|
226 | const result = processRequireItem(expr, p);
|
227 | if (result === undefined) {
|
228 | isExpression = true;
|
229 | }
|
230 | }
|
231 | if (!isExpression) {
|
232 | const dep = new RequireHeaderDependency(expr.callee.range);
|
233 | dep.loc = expr.loc;
|
234 | parser.state.module.addPresentationalDependency(dep);
|
235 | return true;
|
236 | }
|
237 | }
|
238 | if (
|
239 | param.isString() &&
|
240 | (localModule = getLocalModule(parser.state, param.string))
|
241 | ) {
|
242 | localModule.flagUsed();
|
243 | const dep = new LocalModuleDependency(localModule, expr.range, callNew);
|
244 | dep.loc = expr.loc;
|
245 | parser.state.module.addPresentationalDependency(dep);
|
246 | return true;
|
247 | } else {
|
248 | const result = processRequireItem(expr, param);
|
249 | if (result === undefined) {
|
250 | processRequireContext(expr, param);
|
251 | } else {
|
252 | const dep = new RequireHeaderDependency(expr.callee.range);
|
253 | dep.loc = expr.loc;
|
254 | parser.state.module.addPresentationalDependency(dep);
|
255 | }
|
256 | return true;
|
257 | }
|
258 | };
|
259 | parser.hooks.call
|
260 | .for("require")
|
261 | .tap("CommonJsImportsParserPlugin", createRequireHandler(false));
|
262 | parser.hooks.new
|
263 | .for("require")
|
264 | .tap("CommonJsImportsParserPlugin", createRequireHandler(true));
|
265 | parser.hooks.call
|
266 | .for("module.require")
|
267 | .tap("CommonJsImportsParserPlugin", createRequireHandler(false));
|
268 | parser.hooks.new
|
269 | .for("module.require")
|
270 | .tap("CommonJsImportsParserPlugin", createRequireHandler(true));
|
271 |
|
272 |
|
273 | const chainHandler = (expr, calleeMembers, callExpr, members) => {
|
274 | if (callExpr.arguments.length !== 1) return;
|
275 | const param = parser.evaluateExpression(callExpr.arguments[0]);
|
276 | if (param.isString() && !getLocalModule(parser.state, param.string)) {
|
277 | const dep = new CommonJsFullRequireDependency(
|
278 | param.string,
|
279 | expr.range,
|
280 | members
|
281 | );
|
282 | dep.asiSafe = !parser.isAsiPosition(expr.range[0]);
|
283 | dep.optional = !!parser.scope.inTry;
|
284 | dep.loc = expr.loc;
|
285 | parser.state.current.addDependency(dep);
|
286 | return true;
|
287 | }
|
288 | };
|
289 | const callChainHandler = (expr, calleeMembers, callExpr, members) => {
|
290 | if (callExpr.arguments.length !== 1) return;
|
291 | const param = parser.evaluateExpression(callExpr.arguments[0]);
|
292 | if (param.isString() && !getLocalModule(parser.state, param.string)) {
|
293 | const dep = new CommonJsFullRequireDependency(
|
294 | param.string,
|
295 | expr.callee.range,
|
296 | members
|
297 | );
|
298 | dep.call = true;
|
299 | dep.asiSafe = !parser.isAsiPosition(expr.range[0]);
|
300 | dep.optional = !!parser.scope.inTry;
|
301 | dep.loc = expr.callee.loc;
|
302 | parser.state.current.addDependency(dep);
|
303 | parser.walkExpressions(expr.arguments);
|
304 | return true;
|
305 | }
|
306 | };
|
307 | parser.hooks.memberChainOfCallMemberChain
|
308 | .for("require")
|
309 | .tap("CommonJsImportsParserPlugin", chainHandler);
|
310 | parser.hooks.memberChainOfCallMemberChain
|
311 | .for("module.require")
|
312 | .tap("CommonJsImportsParserPlugin", chainHandler);
|
313 | parser.hooks.callMemberChainOfCallMemberChain
|
314 | .for("require")
|
315 | .tap("CommonJsImportsParserPlugin", callChainHandler);
|
316 | parser.hooks.callMemberChainOfCallMemberChain
|
317 | .for("module.require")
|
318 | .tap("CommonJsImportsParserPlugin", callChainHandler);
|
319 |
|
320 |
|
321 | const processResolve = (expr, weak) => {
|
322 | if (expr.arguments.length !== 1) return;
|
323 | const param = parser.evaluateExpression(expr.arguments[0]);
|
324 | if (param.isConditional()) {
|
325 | for (const option of param.options) {
|
326 | const result = processResolveItem(expr, option, weak);
|
327 | if (result === undefined) {
|
328 | processResolveContext(expr, option, weak);
|
329 | }
|
330 | }
|
331 | const dep = new RequireResolveHeaderDependency(expr.callee.range);
|
332 | dep.loc = expr.loc;
|
333 | parser.state.module.addPresentationalDependency(dep);
|
334 | return true;
|
335 | } else {
|
336 | const result = processResolveItem(expr, param, weak);
|
337 | if (result === undefined) {
|
338 | processResolveContext(expr, param, weak);
|
339 | }
|
340 | const dep = new RequireResolveHeaderDependency(expr.callee.range);
|
341 | dep.loc = expr.loc;
|
342 | parser.state.module.addPresentationalDependency(dep);
|
343 | return true;
|
344 | }
|
345 | };
|
346 | const processResolveItem = (expr, param, weak) => {
|
347 | if (param.isString()) {
|
348 | const dep = new RequireResolveDependency(param.string, param.range);
|
349 | dep.loc = expr.loc;
|
350 | dep.optional = !!parser.scope.inTry;
|
351 | dep.weak = weak;
|
352 | parser.state.current.addDependency(dep);
|
353 | return true;
|
354 | }
|
355 | };
|
356 | const processResolveContext = (expr, param, weak) => {
|
357 | const dep = ContextDependencyHelpers.create(
|
358 | RequireResolveContextDependency,
|
359 | param.range,
|
360 | param,
|
361 | expr,
|
362 | options,
|
363 | {
|
364 | category: "commonjs",
|
365 | mode: weak ? "weak" : "sync"
|
366 | },
|
367 | parser
|
368 | );
|
369 | if (!dep) return;
|
370 | dep.loc = expr.loc;
|
371 | dep.optional = !!parser.scope.inTry;
|
372 | parser.state.current.addDependency(dep);
|
373 | return true;
|
374 | };
|
375 |
|
376 | parser.hooks.call
|
377 | .for("require.resolve")
|
378 | .tap("RequireResolveDependencyParserPlugin", expr => {
|
379 | return processResolve(expr, false);
|
380 | });
|
381 | parser.hooks.call
|
382 | .for("require.resolveWeak")
|
383 | .tap("RequireResolveDependencyParserPlugin", expr => {
|
384 | return processResolve(expr, true);
|
385 | });
|
386 | }
|
387 | }
|
388 | module.exports = CommonJsImportsParserPlugin;
|