UNPKG

12.1 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.matchesPattern = matchesPattern;
7exports.has = has;
8exports.isStatic = isStatic;
9exports.isnt = isnt;
10exports.equals = equals;
11exports.isNodeType = isNodeType;
12exports.canHaveVariableDeclarationOrExpression = canHaveVariableDeclarationOrExpression;
13exports.canSwapBetweenExpressionAndStatement = canSwapBetweenExpressionAndStatement;
14exports.isCompletionRecord = isCompletionRecord;
15exports.isStatementOrBlock = isStatementOrBlock;
16exports.referencesImport = referencesImport;
17exports.getSource = getSource;
18exports.willIMaybeExecuteBefore = willIMaybeExecuteBefore;
19exports._guessExecutionStatusRelativeTo = _guessExecutionStatusRelativeTo;
20exports._guessExecutionStatusRelativeToDifferentFunctions = _guessExecutionStatusRelativeToDifferentFunctions;
21exports.resolve = resolve;
22exports._resolve = _resolve;
23exports.isConstantExpression = isConstantExpression;
24exports.isInStrictMode = isInStrictMode;
25exports.is = void 0;
26
27var _includes = _interopRequireDefault(require("lodash/includes"));
28
29var t = _interopRequireWildcard(require("@babel/types"));
30
31function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
32
33function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
34
35function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
36
37function matchesPattern(pattern, allowPartial) {
38 return t.matchesPattern(this.node, pattern, allowPartial);
39}
40
41function has(key) {
42 const val = this.node && this.node[key];
43
44 if (val && Array.isArray(val)) {
45 return !!val.length;
46 } else {
47 return !!val;
48 }
49}
50
51function isStatic() {
52 return this.scope.isStatic(this.node);
53}
54
55const is = has;
56exports.is = is;
57
58function isnt(key) {
59 return !this.has(key);
60}
61
62function equals(key, value) {
63 return this.node[key] === value;
64}
65
66function isNodeType(type) {
67 return t.isType(this.type, type);
68}
69
70function canHaveVariableDeclarationOrExpression() {
71 return (this.key === "init" || this.key === "left") && this.parentPath.isFor();
72}
73
74function canSwapBetweenExpressionAndStatement(replacement) {
75 if (this.key !== "body" || !this.parentPath.isArrowFunctionExpression()) {
76 return false;
77 }
78
79 if (this.isExpression()) {
80 return t.isBlockStatement(replacement);
81 } else if (this.isBlockStatement()) {
82 return t.isExpression(replacement);
83 }
84
85 return false;
86}
87
88function isCompletionRecord(allowInsideFunction) {
89 let path = this;
90 let first = true;
91
92 do {
93 const container = path.container;
94
95 if (path.isFunction() && !first) {
96 return !!allowInsideFunction;
97 }
98
99 first = false;
100
101 if (Array.isArray(container) && path.key !== container.length - 1) {
102 return false;
103 }
104 } while ((path = path.parentPath) && !path.isProgram());
105
106 return true;
107}
108
109function isStatementOrBlock() {
110 if (this.parentPath.isLabeledStatement() || t.isBlockStatement(this.container)) {
111 return false;
112 } else {
113 return (0, _includes.default)(t.STATEMENT_OR_BLOCK_KEYS, this.key);
114 }
115}
116
117function referencesImport(moduleSource, importName) {
118 if (!this.isReferencedIdentifier()) return false;
119 const binding = this.scope.getBinding(this.node.name);
120 if (!binding || binding.kind !== "module") return false;
121 const path = binding.path;
122 const parent = path.parentPath;
123 if (!parent.isImportDeclaration()) return false;
124
125 if (parent.node.source.value === moduleSource) {
126 if (!importName) return true;
127 } else {
128 return false;
129 }
130
131 if (path.isImportDefaultSpecifier() && importName === "default") {
132 return true;
133 }
134
135 if (path.isImportNamespaceSpecifier() && importName === "*") {
136 return true;
137 }
138
139 if (path.isImportSpecifier() && path.node.imported.name === importName) {
140 return true;
141 }
142
143 return false;
144}
145
146function getSource() {
147 const node = this.node;
148
149 if (node.end) {
150 const code = this.hub.getCode();
151 if (code) return code.slice(node.start, node.end);
152 }
153
154 return "";
155}
156
157function willIMaybeExecuteBefore(target) {
158 return this._guessExecutionStatusRelativeTo(target) !== "after";
159}
160
161function getOuterFunction(path) {
162 return (path.scope.getFunctionParent() || path.scope.getProgramParent()).path;
163}
164
165function isExecutionUncertain(type, key) {
166 switch (type) {
167 case "LogicalExpression":
168 return key === "right";
169
170 case "ConditionalExpression":
171 case "IfStatement":
172 return key === "consequent" || key === "alternate";
173
174 case "WhileStatement":
175 case "DoWhileStatement":
176 case "ForInStatement":
177 case "ForOfStatement":
178 return key === "body";
179
180 case "ForStatement":
181 return key === "body" || key === "update";
182
183 case "SwitchStatement":
184 return key === "cases";
185
186 case "TryStatement":
187 return key === "handler";
188
189 case "AssignmentPattern":
190 return key === "right";
191
192 case "OptionalMemberExpression":
193 return key === "property";
194
195 case "OptionalCallExpression":
196 return key === "arguments";
197
198 default:
199 return false;
200 }
201}
202
203function isExecutionUncertainInList(paths, maxIndex) {
204 for (let i = 0; i < maxIndex; i++) {
205 const path = paths[i];
206
207 if (isExecutionUncertain(path.parent.type, path.parentKey)) {
208 return true;
209 }
210 }
211
212 return false;
213}
214
215function _guessExecutionStatusRelativeTo(target) {
216 const funcParent = {
217 this: getOuterFunction(this),
218 target: getOuterFunction(target)
219 };
220
221 if (funcParent.target.node !== funcParent.this.node) {
222 return this._guessExecutionStatusRelativeToDifferentFunctions(funcParent.target);
223 }
224
225 const paths = {
226 target: target.getAncestry(),
227 this: this.getAncestry()
228 };
229 if (paths.target.indexOf(this) >= 0) return "after";
230 if (paths.this.indexOf(target) >= 0) return "before";
231 let commonPath;
232 const commonIndex = {
233 target: 0,
234 this: 0
235 };
236
237 while (!commonPath && commonIndex.this < paths.this.length) {
238 const path = paths.this[commonIndex.this];
239 commonIndex.target = paths.target.indexOf(path);
240
241 if (commonIndex.target >= 0) {
242 commonPath = path;
243 } else {
244 commonIndex.this++;
245 }
246 }
247
248 if (!commonPath) {
249 throw new Error("Internal Babel error - The two compared nodes" + " don't appear to belong to the same program.");
250 }
251
252 if (isExecutionUncertainInList(paths.this, commonIndex.this - 1) || isExecutionUncertainInList(paths.target, commonIndex.target - 1)) {
253 return "unknown";
254 }
255
256 const divergence = {
257 this: paths.this[commonIndex.this - 1],
258 target: paths.target[commonIndex.target - 1]
259 };
260
261 if (divergence.target.listKey && divergence.this.listKey && divergence.target.container === divergence.this.container) {
262 return divergence.target.key > divergence.this.key ? "before" : "after";
263 }
264
265 const keys = t.VISITOR_KEYS[commonPath.type];
266 const keyPosition = {
267 this: keys.indexOf(divergence.this.parentKey),
268 target: keys.indexOf(divergence.target.parentKey)
269 };
270 return keyPosition.target > keyPosition.this ? "before" : "after";
271}
272
273const executionOrderCheckedNodes = new WeakSet();
274
275function _guessExecutionStatusRelativeToDifferentFunctions(target) {
276 if (!target.isFunctionDeclaration() || target.parentPath.isExportDeclaration()) {
277 return "unknown";
278 }
279
280 const binding = target.scope.getBinding(target.node.id.name);
281 if (!binding.references) return "before";
282 const referencePaths = binding.referencePaths;
283 let allStatus;
284
285 for (const path of referencePaths) {
286 const childOfFunction = !!path.find(path => path.node === target.node);
287 if (childOfFunction) continue;
288
289 if (path.key !== "callee" || !path.parentPath.isCallExpression()) {
290 return "unknown";
291 }
292
293 if (executionOrderCheckedNodes.has(path.node)) continue;
294 executionOrderCheckedNodes.add(path.node);
295
296 const status = this._guessExecutionStatusRelativeTo(path);
297
298 executionOrderCheckedNodes.delete(path.node);
299
300 if (allStatus && allStatus !== status) {
301 return "unknown";
302 } else {
303 allStatus = status;
304 }
305 }
306
307 return allStatus;
308}
309
310function resolve(dangerous, resolved) {
311 return this._resolve(dangerous, resolved) || this;
312}
313
314function _resolve(dangerous, resolved) {
315 if (resolved && resolved.indexOf(this) >= 0) return;
316 resolved = resolved || [];
317 resolved.push(this);
318
319 if (this.isVariableDeclarator()) {
320 if (this.get("id").isIdentifier()) {
321 return this.get("init").resolve(dangerous, resolved);
322 } else {}
323 } else if (this.isReferencedIdentifier()) {
324 const binding = this.scope.getBinding(this.node.name);
325 if (!binding) return;
326 if (!binding.constant) return;
327 if (binding.kind === "module") return;
328
329 if (binding.path !== this) {
330 const ret = binding.path.resolve(dangerous, resolved);
331 if (this.find(parent => parent.node === ret.node)) return;
332 return ret;
333 }
334 } else if (this.isTypeCastExpression()) {
335 return this.get("expression").resolve(dangerous, resolved);
336 } else if (dangerous && this.isMemberExpression()) {
337 const targetKey = this.toComputedKey();
338 if (!t.isLiteral(targetKey)) return;
339 const targetName = targetKey.value;
340 const target = this.get("object").resolve(dangerous, resolved);
341
342 if (target.isObjectExpression()) {
343 const props = target.get("properties");
344
345 for (const prop of props) {
346 if (!prop.isProperty()) continue;
347 const key = prop.get("key");
348 let match = prop.isnt("computed") && key.isIdentifier({
349 name: targetName
350 });
351 match = match || key.isLiteral({
352 value: targetName
353 });
354 if (match) return prop.get("value").resolve(dangerous, resolved);
355 }
356 } else if (target.isArrayExpression() && !isNaN(+targetName)) {
357 const elems = target.get("elements");
358 const elem = elems[targetName];
359 if (elem) return elem.resolve(dangerous, resolved);
360 }
361 }
362}
363
364function isConstantExpression() {
365 if (this.isIdentifier()) {
366 const binding = this.scope.getBinding(this.node.name);
367 if (!binding) return false;
368 return binding.constant;
369 }
370
371 if (this.isLiteral()) {
372 if (this.isRegExpLiteral()) {
373 return false;
374 }
375
376 if (this.isTemplateLiteral()) {
377 return this.get("expressions").every(expression => expression.isConstantExpression());
378 }
379
380 return true;
381 }
382
383 if (this.isUnaryExpression()) {
384 if (this.get("operator").node !== "void") {
385 return false;
386 }
387
388 return this.get("argument").isConstantExpression();
389 }
390
391 if (this.isBinaryExpression()) {
392 return this.get("left").isConstantExpression() && this.get("right").isConstantExpression();
393 }
394
395 return false;
396}
397
398function isInStrictMode() {
399 const start = this.isProgram() ? this : this.parentPath;
400 const strictParent = start.find(path => {
401 if (path.isProgram({
402 sourceType: "module"
403 })) return true;
404 if (path.isClass()) return true;
405 if (!path.isProgram() && !path.isFunction()) return false;
406
407 if (path.isArrowFunctionExpression() && !path.get("body").isBlockStatement()) {
408 return false;
409 }
410
411 let {
412 node
413 } = path;
414 if (path.isFunction()) node = node.body;
415
416 for (const directive of node.directives) {
417 if (directive.value.value === "use strict") {
418 return true;
419 }
420 }
421 });
422 return !!strictParent;
423}
\No newline at end of file