@babel/traverse 8.0.0-alpha.1 → 8.0.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.js +171 -160
- package/lib/index.js.map +1 -1
- package/package.json +11 -10
- package/lib/cache.js +0 -14
- package/lib/cache.js.map +0 -1
- package/lib/context.js +0 -108
- package/lib/context.js.map +0 -1
- package/lib/hub.js +0 -12
- package/lib/hub.js.map +0 -1
- package/lib/path/ancestry.js +0 -126
- package/lib/path/ancestry.js.map +0 -1
- package/lib/path/comments.js +0 -46
- package/lib/path/comments.js.map +0 -1
- package/lib/path/context.js +0 -194
- package/lib/path/context.js.map +0 -1
- package/lib/path/conversion.js +0 -453
- package/lib/path/conversion.js.map +0 -1
- package/lib/path/evaluation.js +0 -333
- package/lib/path/evaluation.js.map +0 -1
- package/lib/path/family.js +0 -322
- package/lib/path/family.js.map +0 -1
- package/lib/path/index.js +0 -185
- package/lib/path/index.js.map +0 -1
- package/lib/path/inference/index.js +0 -137
- package/lib/path/inference/index.js.map +0 -1
- package/lib/path/inference/inferer-reference.js +0 -145
- package/lib/path/inference/inferer-reference.js.map +0 -1
- package/lib/path/inference/inferers.js +0 -172
- package/lib/path/inference/inferers.js.map +0 -1
- package/lib/path/inference/util.js +0 -20
- package/lib/path/inference/util.js.map +0 -1
- package/lib/path/introspection.js +0 -360
- package/lib/path/introspection.js.map +0 -1
- package/lib/path/lib/hoister.js +0 -164
- package/lib/path/lib/hoister.js.map +0 -1
- package/lib/path/lib/removal-hooks.js +0 -31
- package/lib/path/lib/removal-hooks.js.map +0 -1
- package/lib/path/lib/virtual-types-validator.js +0 -138
- package/lib/path/lib/virtual-types-validator.js.map +0 -1
- package/lib/path/lib/virtual-types.js +0 -20
- package/lib/path/lib/virtual-types.js.map +0 -1
- package/lib/path/modification.js +0 -209
- package/lib/path/modification.js.map +0 -1
- package/lib/path/removal.js +0 -46
- package/lib/path/removal.js.map +0 -1
- package/lib/path/replacement.js +0 -192
- package/lib/path/replacement.js.map +0 -1
- package/lib/scope/binding.js +0 -78
- package/lib/scope/binding.js.map +0 -1
- package/lib/scope/index.js +0 -870
- package/lib/scope/index.js.map +0 -1
- package/lib/scope/lib/renamer.js +0 -105
- package/lib/scope/lib/renamer.js.map +0 -1
- package/lib/traverse-node.js +0 -19
- package/lib/traverse-node.js.map +0 -1
- package/lib/types.js +0 -3
- package/lib/types.js.map +0 -1
- package/lib/visitors.js +0 -210
- package/lib/visitors.js.map +0 -1
package/lib/scope/index.js
DELETED
@@ -1,870 +0,0 @@
|
|
1
|
-
import Renamer from "./lib/renamer.js";
|
2
|
-
import traverse from "../index.js";
|
3
|
-
import Binding from "./binding.js";
|
4
|
-
import globals from "globals";
|
5
|
-
import * as _t from "@babel/types";
|
6
|
-
const {
|
7
|
-
NOT_LOCAL_BINDING,
|
8
|
-
callExpression,
|
9
|
-
cloneNode,
|
10
|
-
getBindingIdentifiers,
|
11
|
-
identifier,
|
12
|
-
isArrayExpression,
|
13
|
-
isBinary,
|
14
|
-
isClass,
|
15
|
-
isClassBody,
|
16
|
-
isClassDeclaration,
|
17
|
-
isExportAllDeclaration,
|
18
|
-
isExportDefaultDeclaration,
|
19
|
-
isExportNamedDeclaration,
|
20
|
-
isFunctionDeclaration,
|
21
|
-
isIdentifier,
|
22
|
-
isImportDeclaration,
|
23
|
-
isLiteral,
|
24
|
-
isMethod,
|
25
|
-
isModuleSpecifier,
|
26
|
-
isNullLiteral,
|
27
|
-
isObjectExpression,
|
28
|
-
isProperty,
|
29
|
-
isPureish,
|
30
|
-
isRegExpLiteral,
|
31
|
-
isSuper,
|
32
|
-
isTaggedTemplateExpression,
|
33
|
-
isTemplateLiteral,
|
34
|
-
isThisExpression,
|
35
|
-
isUnaryExpression,
|
36
|
-
isVariableDeclaration,
|
37
|
-
matchesPattern,
|
38
|
-
memberExpression,
|
39
|
-
numericLiteral,
|
40
|
-
toIdentifier,
|
41
|
-
unaryExpression,
|
42
|
-
variableDeclaration,
|
43
|
-
variableDeclarator,
|
44
|
-
isRecordExpression,
|
45
|
-
isTupleExpression,
|
46
|
-
isObjectProperty,
|
47
|
-
isTopicReference,
|
48
|
-
isMetaProperty,
|
49
|
-
isPrivateName,
|
50
|
-
isExportDeclaration
|
51
|
-
} = _t;
|
52
|
-
import * as t from "@babel/types";
|
53
|
-
import { scope as scopeCache } from "../cache.js";
|
54
|
-
import { isExplodedVisitor } from "../visitors.js";
|
55
|
-
function gatherNodeParts(node, parts) {
|
56
|
-
switch (node?.type) {
|
57
|
-
default:
|
58
|
-
if (isImportDeclaration(node) || isExportDeclaration(node)) {
|
59
|
-
if ((isExportAllDeclaration(node) || isExportNamedDeclaration(node) || isImportDeclaration(node)) && node.source) {
|
60
|
-
gatherNodeParts(node.source, parts);
|
61
|
-
} else if ((isExportNamedDeclaration(node) || isImportDeclaration(node)) && node.specifiers?.length) {
|
62
|
-
for (const e of node.specifiers) gatherNodeParts(e, parts);
|
63
|
-
} else if ((isExportDefaultDeclaration(node) || isExportNamedDeclaration(node)) && node.declaration) {
|
64
|
-
gatherNodeParts(node.declaration, parts);
|
65
|
-
}
|
66
|
-
} else if (isModuleSpecifier(node)) {
|
67
|
-
gatherNodeParts(node.local, parts);
|
68
|
-
} else if (isLiteral(node) && !isNullLiteral(node) && !isRegExpLiteral(node) && !isTemplateLiteral(node)) {
|
69
|
-
parts.push(node.value);
|
70
|
-
}
|
71
|
-
break;
|
72
|
-
case "MemberExpression":
|
73
|
-
case "OptionalMemberExpression":
|
74
|
-
case "JSXMemberExpression":
|
75
|
-
gatherNodeParts(node.object, parts);
|
76
|
-
gatherNodeParts(node.property, parts);
|
77
|
-
break;
|
78
|
-
case "Identifier":
|
79
|
-
case "JSXIdentifier":
|
80
|
-
parts.push(node.name);
|
81
|
-
break;
|
82
|
-
case "CallExpression":
|
83
|
-
case "OptionalCallExpression":
|
84
|
-
case "NewExpression":
|
85
|
-
gatherNodeParts(node.callee, parts);
|
86
|
-
break;
|
87
|
-
case "ObjectExpression":
|
88
|
-
case "ObjectPattern":
|
89
|
-
for (const e of node.properties) {
|
90
|
-
gatherNodeParts(e, parts);
|
91
|
-
}
|
92
|
-
break;
|
93
|
-
case "SpreadElement":
|
94
|
-
case "RestElement":
|
95
|
-
gatherNodeParts(node.argument, parts);
|
96
|
-
break;
|
97
|
-
case "ObjectProperty":
|
98
|
-
case "ObjectMethod":
|
99
|
-
case "ClassProperty":
|
100
|
-
case "ClassMethod":
|
101
|
-
case "ClassPrivateProperty":
|
102
|
-
case "ClassPrivateMethod":
|
103
|
-
gatherNodeParts(node.key, parts);
|
104
|
-
break;
|
105
|
-
case "ThisExpression":
|
106
|
-
parts.push("this");
|
107
|
-
break;
|
108
|
-
case "Super":
|
109
|
-
parts.push("super");
|
110
|
-
break;
|
111
|
-
case "Import":
|
112
|
-
parts.push("import");
|
113
|
-
break;
|
114
|
-
case "DoExpression":
|
115
|
-
parts.push("do");
|
116
|
-
break;
|
117
|
-
case "YieldExpression":
|
118
|
-
parts.push("yield");
|
119
|
-
gatherNodeParts(node.argument, parts);
|
120
|
-
break;
|
121
|
-
case "AwaitExpression":
|
122
|
-
parts.push("await");
|
123
|
-
gatherNodeParts(node.argument, parts);
|
124
|
-
break;
|
125
|
-
case "AssignmentExpression":
|
126
|
-
gatherNodeParts(node.left, parts);
|
127
|
-
break;
|
128
|
-
case "VariableDeclarator":
|
129
|
-
gatherNodeParts(node.id, parts);
|
130
|
-
break;
|
131
|
-
case "FunctionExpression":
|
132
|
-
case "FunctionDeclaration":
|
133
|
-
case "ClassExpression":
|
134
|
-
case "ClassDeclaration":
|
135
|
-
gatherNodeParts(node.id, parts);
|
136
|
-
break;
|
137
|
-
case "PrivateName":
|
138
|
-
gatherNodeParts(node.id, parts);
|
139
|
-
break;
|
140
|
-
case "ParenthesizedExpression":
|
141
|
-
gatherNodeParts(node.expression, parts);
|
142
|
-
break;
|
143
|
-
case "UnaryExpression":
|
144
|
-
case "UpdateExpression":
|
145
|
-
gatherNodeParts(node.argument, parts);
|
146
|
-
break;
|
147
|
-
case "MetaProperty":
|
148
|
-
gatherNodeParts(node.meta, parts);
|
149
|
-
gatherNodeParts(node.property, parts);
|
150
|
-
break;
|
151
|
-
case "JSXElement":
|
152
|
-
gatherNodeParts(node.openingElement, parts);
|
153
|
-
break;
|
154
|
-
case "JSXOpeningElement":
|
155
|
-
gatherNodeParts(node.name, parts);
|
156
|
-
break;
|
157
|
-
case "JSXFragment":
|
158
|
-
gatherNodeParts(node.openingFragment, parts);
|
159
|
-
break;
|
160
|
-
case "JSXOpeningFragment":
|
161
|
-
parts.push("Fragment");
|
162
|
-
break;
|
163
|
-
case "JSXNamespacedName":
|
164
|
-
gatherNodeParts(node.namespace, parts);
|
165
|
-
gatherNodeParts(node.name, parts);
|
166
|
-
break;
|
167
|
-
}
|
168
|
-
}
|
169
|
-
const collectorVisitor = {
|
170
|
-
ForStatement(path) {
|
171
|
-
const declar = path.get("init");
|
172
|
-
if (declar.isVar()) {
|
173
|
-
const {
|
174
|
-
scope
|
175
|
-
} = path;
|
176
|
-
const parentScope = scope.getFunctionParent() || scope.getProgramParent();
|
177
|
-
parentScope.registerBinding("var", declar);
|
178
|
-
}
|
179
|
-
},
|
180
|
-
Declaration(path) {
|
181
|
-
if (path.isBlockScoped()) return;
|
182
|
-
if (path.isImportDeclaration()) return;
|
183
|
-
if (path.isExportDeclaration()) return;
|
184
|
-
const parent = path.scope.getFunctionParent() || path.scope.getProgramParent();
|
185
|
-
parent.registerDeclaration(path);
|
186
|
-
},
|
187
|
-
ImportDeclaration(path) {
|
188
|
-
const parent = path.scope.getBlockParent();
|
189
|
-
parent.registerDeclaration(path);
|
190
|
-
},
|
191
|
-
ReferencedIdentifier(path, state) {
|
192
|
-
state.references.push(path);
|
193
|
-
},
|
194
|
-
ForXStatement(path, state) {
|
195
|
-
const left = path.get("left");
|
196
|
-
if (left.isPattern() || left.isIdentifier()) {
|
197
|
-
state.constantViolations.push(path);
|
198
|
-
} else if (left.isVar()) {
|
199
|
-
const {
|
200
|
-
scope
|
201
|
-
} = path;
|
202
|
-
const parentScope = scope.getFunctionParent() || scope.getProgramParent();
|
203
|
-
parentScope.registerBinding("var", left);
|
204
|
-
}
|
205
|
-
},
|
206
|
-
ExportDeclaration: {
|
207
|
-
exit(path) {
|
208
|
-
const {
|
209
|
-
node,
|
210
|
-
scope
|
211
|
-
} = path;
|
212
|
-
if (isExportAllDeclaration(node)) return;
|
213
|
-
const declar = node.declaration;
|
214
|
-
if (isClassDeclaration(declar) || isFunctionDeclaration(declar)) {
|
215
|
-
const id = declar.id;
|
216
|
-
if (!id) return;
|
217
|
-
const binding = scope.getBinding(id.name);
|
218
|
-
binding?.reference(path);
|
219
|
-
} else if (isVariableDeclaration(declar)) {
|
220
|
-
for (const decl of declar.declarations) {
|
221
|
-
for (const name of Object.keys(getBindingIdentifiers(decl))) {
|
222
|
-
const binding = scope.getBinding(name);
|
223
|
-
binding?.reference(path);
|
224
|
-
}
|
225
|
-
}
|
226
|
-
}
|
227
|
-
}
|
228
|
-
},
|
229
|
-
LabeledStatement(path) {
|
230
|
-
path.scope.getBlockParent().registerDeclaration(path);
|
231
|
-
},
|
232
|
-
AssignmentExpression(path, state) {
|
233
|
-
state.assignments.push(path);
|
234
|
-
},
|
235
|
-
UpdateExpression(path, state) {
|
236
|
-
state.constantViolations.push(path);
|
237
|
-
},
|
238
|
-
UnaryExpression(path, state) {
|
239
|
-
if (path.node.operator === "delete") {
|
240
|
-
state.constantViolations.push(path);
|
241
|
-
}
|
242
|
-
},
|
243
|
-
BlockScoped(path) {
|
244
|
-
let scope = path.scope;
|
245
|
-
if (scope.path === path) scope = scope.parent;
|
246
|
-
const parent = scope.getBlockParent();
|
247
|
-
parent.registerDeclaration(path);
|
248
|
-
if (path.isClassDeclaration() && path.node.id) {
|
249
|
-
const id = path.node.id;
|
250
|
-
const name = id.name;
|
251
|
-
path.scope.bindings[name] = path.scope.parent.getBinding(name);
|
252
|
-
}
|
253
|
-
},
|
254
|
-
CatchClause(path) {
|
255
|
-
path.scope.registerBinding("let", path);
|
256
|
-
},
|
257
|
-
Function(path) {
|
258
|
-
const params = path.get("params");
|
259
|
-
for (const param of params) {
|
260
|
-
path.scope.registerBinding("param", param);
|
261
|
-
}
|
262
|
-
if (path.isFunctionExpression() && path.has("id") && !path.get("id").node[NOT_LOCAL_BINDING]) {
|
263
|
-
path.scope.registerBinding("local", path.get("id"), path);
|
264
|
-
}
|
265
|
-
},
|
266
|
-
ClassExpression(path) {
|
267
|
-
if (path.has("id") && !path.get("id").node[NOT_LOCAL_BINDING]) {
|
268
|
-
path.scope.registerBinding("local", path);
|
269
|
-
}
|
270
|
-
}
|
271
|
-
};
|
272
|
-
let uid = 0;
|
273
|
-
export default class Scope {
|
274
|
-
uid;
|
275
|
-
path;
|
276
|
-
block;
|
277
|
-
labels;
|
278
|
-
inited;
|
279
|
-
bindings;
|
280
|
-
references;
|
281
|
-
globals;
|
282
|
-
uids;
|
283
|
-
data;
|
284
|
-
crawling;
|
285
|
-
constructor(path) {
|
286
|
-
const {
|
287
|
-
node
|
288
|
-
} = path;
|
289
|
-
const cached = scopeCache.get(node);
|
290
|
-
if (cached?.path === path) {
|
291
|
-
return cached;
|
292
|
-
}
|
293
|
-
scopeCache.set(node, this);
|
294
|
-
this.uid = uid++;
|
295
|
-
this.block = node;
|
296
|
-
this.path = path;
|
297
|
-
this.labels = new Map();
|
298
|
-
this.inited = false;
|
299
|
-
}
|
300
|
-
static globals = Object.keys(globals.builtin);
|
301
|
-
static contextVariables = ["arguments", "undefined", "Infinity", "NaN"];
|
302
|
-
get parent() {
|
303
|
-
let parent,
|
304
|
-
path = this.path;
|
305
|
-
do {
|
306
|
-
const shouldSkip = path.key === "key" || path.listKey === "decorators";
|
307
|
-
path = path.parentPath;
|
308
|
-
if (shouldSkip && path.isMethod()) path = path.parentPath;
|
309
|
-
if (path && path.isScope()) parent = path;
|
310
|
-
} while (path && !parent);
|
311
|
-
return parent?.scope;
|
312
|
-
}
|
313
|
-
get parentBlock() {
|
314
|
-
return this.path.parent;
|
315
|
-
}
|
316
|
-
get hub() {
|
317
|
-
return this.path.hub;
|
318
|
-
}
|
319
|
-
traverse(node, opts, state) {
|
320
|
-
traverse(node, opts, this, state, this.path);
|
321
|
-
}
|
322
|
-
generateDeclaredUidIdentifier(name) {
|
323
|
-
const id = this.generateUidIdentifier(name);
|
324
|
-
this.push({
|
325
|
-
id
|
326
|
-
});
|
327
|
-
return cloneNode(id);
|
328
|
-
}
|
329
|
-
generateUidIdentifier(name) {
|
330
|
-
return identifier(this.generateUid(name));
|
331
|
-
}
|
332
|
-
generateUid(name = "temp") {
|
333
|
-
name = toIdentifier(name).replace(/^_+/, "").replace(/[0-9]+$/g, "");
|
334
|
-
let uid;
|
335
|
-
let i = 1;
|
336
|
-
do {
|
337
|
-
uid = this._generateUid(name, i);
|
338
|
-
i++;
|
339
|
-
} while (this.hasLabel(uid) || this.hasBinding(uid) || this.hasGlobal(uid) || this.hasReference(uid));
|
340
|
-
const program = this.getProgramParent();
|
341
|
-
program.references[uid] = true;
|
342
|
-
program.uids[uid] = true;
|
343
|
-
return uid;
|
344
|
-
}
|
345
|
-
_generateUid(name, i) {
|
346
|
-
let id = name;
|
347
|
-
if (i > 1) id += i;
|
348
|
-
return `_${id}`;
|
349
|
-
}
|
350
|
-
generateUidBasedOnNode(node, defaultName) {
|
351
|
-
const parts = [];
|
352
|
-
gatherNodeParts(node, parts);
|
353
|
-
let id = parts.join("$");
|
354
|
-
id = id.replace(/^_/, "") || defaultName || "ref";
|
355
|
-
return this.generateUid(id.slice(0, 20));
|
356
|
-
}
|
357
|
-
generateUidIdentifierBasedOnNode(node, defaultName) {
|
358
|
-
return identifier(this.generateUidBasedOnNode(node, defaultName));
|
359
|
-
}
|
360
|
-
isStatic(node) {
|
361
|
-
if (isThisExpression(node) || isSuper(node) || isTopicReference(node)) {
|
362
|
-
return true;
|
363
|
-
}
|
364
|
-
if (isIdentifier(node)) {
|
365
|
-
const binding = this.getBinding(node.name);
|
366
|
-
if (binding) {
|
367
|
-
return binding.constant;
|
368
|
-
} else {
|
369
|
-
return this.hasBinding(node.name);
|
370
|
-
}
|
371
|
-
}
|
372
|
-
return false;
|
373
|
-
}
|
374
|
-
maybeGenerateMemoised(node, dontPush) {
|
375
|
-
if (this.isStatic(node)) {
|
376
|
-
return null;
|
377
|
-
} else {
|
378
|
-
const id = this.generateUidIdentifierBasedOnNode(node);
|
379
|
-
if (!dontPush) {
|
380
|
-
this.push({
|
381
|
-
id
|
382
|
-
});
|
383
|
-
return cloneNode(id);
|
384
|
-
}
|
385
|
-
return id;
|
386
|
-
}
|
387
|
-
}
|
388
|
-
checkBlockScopedCollisions(local, kind, name, id) {
|
389
|
-
if (kind === "param") return;
|
390
|
-
if (local.kind === "local") return;
|
391
|
-
const duplicate = kind === "let" || local.kind === "let" || local.kind === "const" || local.kind === "module" || local.kind === "param" && kind === "const";
|
392
|
-
if (duplicate) {
|
393
|
-
throw this.hub.buildError(id, `Duplicate declaration "${name}"`, TypeError);
|
394
|
-
}
|
395
|
-
}
|
396
|
-
rename(oldName, newName) {
|
397
|
-
const binding = this.getBinding(oldName);
|
398
|
-
if (binding) {
|
399
|
-
newName ||= this.generateUidIdentifier(oldName).name;
|
400
|
-
const renamer = new Renamer(binding, oldName, newName);
|
401
|
-
{
|
402
|
-
renamer.rename();
|
403
|
-
}
|
404
|
-
}
|
405
|
-
}
|
406
|
-
_renameFromMap(map, oldName, newName, value) {
|
407
|
-
if (map[oldName]) {
|
408
|
-
map[newName] = value;
|
409
|
-
map[oldName] = null;
|
410
|
-
}
|
411
|
-
}
|
412
|
-
dump() {
|
413
|
-
const sep = "-".repeat(60);
|
414
|
-
console.log(sep);
|
415
|
-
let scope = this;
|
416
|
-
do {
|
417
|
-
console.log("#", scope.block.type);
|
418
|
-
for (const name of Object.keys(scope.bindings)) {
|
419
|
-
const binding = scope.bindings[name];
|
420
|
-
console.log(" -", name, {
|
421
|
-
constant: binding.constant,
|
422
|
-
references: binding.references,
|
423
|
-
violations: binding.constantViolations.length,
|
424
|
-
kind: binding.kind
|
425
|
-
});
|
426
|
-
}
|
427
|
-
} while (scope = scope.parent);
|
428
|
-
console.log(sep);
|
429
|
-
}
|
430
|
-
toArray(node, i, arrayLikeIsIterable) {
|
431
|
-
if (isIdentifier(node)) {
|
432
|
-
const binding = this.getBinding(node.name);
|
433
|
-
if (binding?.constant && binding.path.isGenericType("Array")) {
|
434
|
-
return node;
|
435
|
-
}
|
436
|
-
}
|
437
|
-
if (isArrayExpression(node)) {
|
438
|
-
return node;
|
439
|
-
}
|
440
|
-
if (isIdentifier(node, {
|
441
|
-
name: "arguments"
|
442
|
-
})) {
|
443
|
-
return callExpression(memberExpression(memberExpression(memberExpression(identifier("Array"), identifier("prototype")), identifier("slice")), identifier("call")), [node]);
|
444
|
-
}
|
445
|
-
let helperName;
|
446
|
-
const args = [node];
|
447
|
-
if (i === true) {
|
448
|
-
helperName = "toConsumableArray";
|
449
|
-
} else if (typeof i === "number") {
|
450
|
-
args.push(numericLiteral(i));
|
451
|
-
helperName = "slicedToArray";
|
452
|
-
} else {
|
453
|
-
helperName = "toArray";
|
454
|
-
}
|
455
|
-
if (arrayLikeIsIterable) {
|
456
|
-
args.unshift(this.hub.addHelper(helperName));
|
457
|
-
helperName = "maybeArrayLike";
|
458
|
-
}
|
459
|
-
return callExpression(this.hub.addHelper(helperName), args);
|
460
|
-
}
|
461
|
-
hasLabel(name) {
|
462
|
-
return !!this.getLabel(name);
|
463
|
-
}
|
464
|
-
getLabel(name) {
|
465
|
-
return this.labels.get(name);
|
466
|
-
}
|
467
|
-
registerLabel(path) {
|
468
|
-
this.labels.set(path.node.label.name, path);
|
469
|
-
}
|
470
|
-
registerDeclaration(path) {
|
471
|
-
if (path.isLabeledStatement()) {
|
472
|
-
this.registerLabel(path);
|
473
|
-
} else if (path.isFunctionDeclaration()) {
|
474
|
-
this.registerBinding("hoisted", path.get("id"), path);
|
475
|
-
} else if (path.isVariableDeclaration()) {
|
476
|
-
const declarations = path.get("declarations");
|
477
|
-
const {
|
478
|
-
kind
|
479
|
-
} = path.node;
|
480
|
-
for (const declar of declarations) {
|
481
|
-
this.registerBinding(kind === "using" || kind === "await using" ? "const" : kind, declar);
|
482
|
-
}
|
483
|
-
} else if (path.isClassDeclaration()) {
|
484
|
-
if (path.node.declare) return;
|
485
|
-
this.registerBinding("let", path);
|
486
|
-
} else if (path.isImportDeclaration()) {
|
487
|
-
const isTypeDeclaration = path.node.importKind === "type" || path.node.importKind === "typeof";
|
488
|
-
const specifiers = path.get("specifiers");
|
489
|
-
for (const specifier of specifiers) {
|
490
|
-
const isTypeSpecifier = isTypeDeclaration || specifier.isImportSpecifier() && (specifier.node.importKind === "type" || specifier.node.importKind === "typeof");
|
491
|
-
this.registerBinding(isTypeSpecifier ? "unknown" : "module", specifier);
|
492
|
-
}
|
493
|
-
} else if (path.isExportDeclaration()) {
|
494
|
-
const declar = path.get("declaration");
|
495
|
-
if (declar.isClassDeclaration() || declar.isFunctionDeclaration() || declar.isVariableDeclaration()) {
|
496
|
-
this.registerDeclaration(declar);
|
497
|
-
}
|
498
|
-
} else {
|
499
|
-
this.registerBinding("unknown", path);
|
500
|
-
}
|
501
|
-
}
|
502
|
-
buildUndefinedNode() {
|
503
|
-
return unaryExpression("void", numericLiteral(0), true);
|
504
|
-
}
|
505
|
-
registerConstantViolation(path) {
|
506
|
-
const ids = path.getBindingIdentifiers();
|
507
|
-
for (const name of Object.keys(ids)) {
|
508
|
-
this.getBinding(name)?.reassign(path);
|
509
|
-
}
|
510
|
-
}
|
511
|
-
registerBinding(kind, path, bindingPath = path) {
|
512
|
-
if (!kind) throw new ReferenceError("no `kind`");
|
513
|
-
if (path.isVariableDeclaration()) {
|
514
|
-
const declarators = path.get("declarations");
|
515
|
-
for (const declar of declarators) {
|
516
|
-
this.registerBinding(kind, declar);
|
517
|
-
}
|
518
|
-
return;
|
519
|
-
}
|
520
|
-
const parent = this.getProgramParent();
|
521
|
-
const ids = path.getOuterBindingIdentifiers(true);
|
522
|
-
for (const name of Object.keys(ids)) {
|
523
|
-
parent.references[name] = true;
|
524
|
-
for (const id of ids[name]) {
|
525
|
-
const local = this.getOwnBinding(name);
|
526
|
-
if (local) {
|
527
|
-
if (local.identifier === id) continue;
|
528
|
-
this.checkBlockScopedCollisions(local, kind, name, id);
|
529
|
-
}
|
530
|
-
if (local) {
|
531
|
-
this.registerConstantViolation(bindingPath);
|
532
|
-
} else {
|
533
|
-
this.bindings[name] = new Binding({
|
534
|
-
identifier: id,
|
535
|
-
scope: this,
|
536
|
-
path: bindingPath,
|
537
|
-
kind: kind
|
538
|
-
});
|
539
|
-
}
|
540
|
-
}
|
541
|
-
}
|
542
|
-
}
|
543
|
-
addGlobal(node) {
|
544
|
-
this.globals[node.name] = node;
|
545
|
-
}
|
546
|
-
hasUid(name) {
|
547
|
-
let scope = this;
|
548
|
-
do {
|
549
|
-
if (scope.uids[name]) return true;
|
550
|
-
} while (scope = scope.parent);
|
551
|
-
return false;
|
552
|
-
}
|
553
|
-
hasGlobal(name) {
|
554
|
-
let scope = this;
|
555
|
-
do {
|
556
|
-
if (scope.globals[name]) return true;
|
557
|
-
} while (scope = scope.parent);
|
558
|
-
return false;
|
559
|
-
}
|
560
|
-
hasReference(name) {
|
561
|
-
return !!this.getProgramParent().references[name];
|
562
|
-
}
|
563
|
-
isPure(node, constantsOnly) {
|
564
|
-
if (isIdentifier(node)) {
|
565
|
-
const binding = this.getBinding(node.name);
|
566
|
-
if (!binding) return false;
|
567
|
-
if (constantsOnly) return binding.constant;
|
568
|
-
return true;
|
569
|
-
} else if (isThisExpression(node) || isMetaProperty(node) || isTopicReference(node) || isPrivateName(node)) {
|
570
|
-
return true;
|
571
|
-
} else if (isClass(node)) {
|
572
|
-
if (node.superClass && !this.isPure(node.superClass, constantsOnly)) {
|
573
|
-
return false;
|
574
|
-
}
|
575
|
-
if (node.decorators?.length > 0) {
|
576
|
-
return false;
|
577
|
-
}
|
578
|
-
return this.isPure(node.body, constantsOnly);
|
579
|
-
} else if (isClassBody(node)) {
|
580
|
-
for (const method of node.body) {
|
581
|
-
if (!this.isPure(method, constantsOnly)) return false;
|
582
|
-
}
|
583
|
-
return true;
|
584
|
-
} else if (isBinary(node)) {
|
585
|
-
return this.isPure(node.left, constantsOnly) && this.isPure(node.right, constantsOnly);
|
586
|
-
} else if (isArrayExpression(node) || isTupleExpression(node)) {
|
587
|
-
for (const elem of node.elements) {
|
588
|
-
if (elem !== null && !this.isPure(elem, constantsOnly)) return false;
|
589
|
-
}
|
590
|
-
return true;
|
591
|
-
} else if (isObjectExpression(node) || isRecordExpression(node)) {
|
592
|
-
for (const prop of node.properties) {
|
593
|
-
if (!this.isPure(prop, constantsOnly)) return false;
|
594
|
-
}
|
595
|
-
return true;
|
596
|
-
} else if (isMethod(node)) {
|
597
|
-
if (node.computed && !this.isPure(node.key, constantsOnly)) return false;
|
598
|
-
if (node.decorators?.length > 0) {
|
599
|
-
return false;
|
600
|
-
}
|
601
|
-
return true;
|
602
|
-
} else if (isProperty(node)) {
|
603
|
-
if (node.computed && !this.isPure(node.key, constantsOnly)) return false;
|
604
|
-
if (node.decorators?.length > 0) {
|
605
|
-
return false;
|
606
|
-
}
|
607
|
-
if (isObjectProperty(node) || node.static) {
|
608
|
-
if (node.value !== null && !this.isPure(node.value, constantsOnly)) {
|
609
|
-
return false;
|
610
|
-
}
|
611
|
-
}
|
612
|
-
return true;
|
613
|
-
} else if (isUnaryExpression(node)) {
|
614
|
-
return this.isPure(node.argument, constantsOnly);
|
615
|
-
} else if (isTaggedTemplateExpression(node)) {
|
616
|
-
return matchesPattern(node.tag, "String.raw") && !this.hasBinding("String", true) && this.isPure(node.quasi, constantsOnly);
|
617
|
-
} else if (isTemplateLiteral(node)) {
|
618
|
-
for (const expression of node.expressions) {
|
619
|
-
if (!this.isPure(expression, constantsOnly)) return false;
|
620
|
-
}
|
621
|
-
return true;
|
622
|
-
} else {
|
623
|
-
return isPureish(node);
|
624
|
-
}
|
625
|
-
}
|
626
|
-
setData(key, val) {
|
627
|
-
return this.data[key] = val;
|
628
|
-
}
|
629
|
-
getData(key) {
|
630
|
-
let scope = this;
|
631
|
-
do {
|
632
|
-
const data = scope.data[key];
|
633
|
-
if (data != null) return data;
|
634
|
-
} while (scope = scope.parent);
|
635
|
-
}
|
636
|
-
removeData(key) {
|
637
|
-
let scope = this;
|
638
|
-
do {
|
639
|
-
const data = scope.data[key];
|
640
|
-
if (data != null) scope.data[key] = null;
|
641
|
-
} while (scope = scope.parent);
|
642
|
-
}
|
643
|
-
init() {
|
644
|
-
if (!this.inited) {
|
645
|
-
this.inited = true;
|
646
|
-
this.crawl();
|
647
|
-
}
|
648
|
-
}
|
649
|
-
crawl() {
|
650
|
-
const path = this.path;
|
651
|
-
this.references = Object.create(null);
|
652
|
-
this.bindings = Object.create(null);
|
653
|
-
this.globals = Object.create(null);
|
654
|
-
this.uids = Object.create(null);
|
655
|
-
this.data = Object.create(null);
|
656
|
-
const programParent = this.getProgramParent();
|
657
|
-
if (programParent.crawling) return;
|
658
|
-
const state = {
|
659
|
-
references: [],
|
660
|
-
constantViolations: [],
|
661
|
-
assignments: []
|
662
|
-
};
|
663
|
-
this.crawling = true;
|
664
|
-
if (path.type !== "Program" && isExplodedVisitor(collectorVisitor)) {
|
665
|
-
for (const visit of collectorVisitor.enter) {
|
666
|
-
visit.call(state, path, state);
|
667
|
-
}
|
668
|
-
const typeVisitors = collectorVisitor[path.type];
|
669
|
-
if (typeVisitors) {
|
670
|
-
for (const visit of typeVisitors.enter) {
|
671
|
-
visit.call(state, path, state);
|
672
|
-
}
|
673
|
-
}
|
674
|
-
}
|
675
|
-
path.traverse(collectorVisitor, state);
|
676
|
-
this.crawling = false;
|
677
|
-
for (const path of state.assignments) {
|
678
|
-
const ids = path.getBindingIdentifiers();
|
679
|
-
for (const name of Object.keys(ids)) {
|
680
|
-
if (path.scope.getBinding(name)) continue;
|
681
|
-
programParent.addGlobal(ids[name]);
|
682
|
-
}
|
683
|
-
path.scope.registerConstantViolation(path);
|
684
|
-
}
|
685
|
-
for (const ref of state.references) {
|
686
|
-
const binding = ref.scope.getBinding(ref.node.name);
|
687
|
-
if (binding) {
|
688
|
-
binding.reference(ref);
|
689
|
-
} else {
|
690
|
-
programParent.addGlobal(ref.node);
|
691
|
-
}
|
692
|
-
}
|
693
|
-
for (const path of state.constantViolations) {
|
694
|
-
path.scope.registerConstantViolation(path);
|
695
|
-
}
|
696
|
-
}
|
697
|
-
push(opts) {
|
698
|
-
let path = this.path;
|
699
|
-
if (path.isPattern()) {
|
700
|
-
path = this.getPatternParent().path;
|
701
|
-
} else if (!path.isBlockStatement() && !path.isProgram()) {
|
702
|
-
path = this.getBlockParent().path;
|
703
|
-
}
|
704
|
-
if (path.isSwitchStatement()) {
|
705
|
-
path = (this.getFunctionParent() || this.getProgramParent()).path;
|
706
|
-
}
|
707
|
-
const {
|
708
|
-
init,
|
709
|
-
unique,
|
710
|
-
kind = "var",
|
711
|
-
id
|
712
|
-
} = opts;
|
713
|
-
if (!init && !unique && (kind === "var" || kind === "let") && path.isFunction() && !path.node.name && t.isCallExpression(path.parent, {
|
714
|
-
callee: path.node
|
715
|
-
}) && path.parent.arguments.length <= path.node.params.length && t.isIdentifier(id)) {
|
716
|
-
path.pushContainer("params", id);
|
717
|
-
path.scope.registerBinding("param", path.get("params")[path.node.params.length - 1]);
|
718
|
-
return;
|
719
|
-
}
|
720
|
-
if (path.isLoop() || path.isCatchClause() || path.isFunction()) {
|
721
|
-
path.ensureBlock();
|
722
|
-
path = path.get("body");
|
723
|
-
}
|
724
|
-
const blockHoist = opts._blockHoist == null ? 2 : opts._blockHoist;
|
725
|
-
const dataKey = `declaration:${kind}:${blockHoist}`;
|
726
|
-
let declarPath = !unique && path.getData(dataKey);
|
727
|
-
if (!declarPath) {
|
728
|
-
const declar = variableDeclaration(kind, []);
|
729
|
-
declar._blockHoist = blockHoist;
|
730
|
-
[declarPath] = path.unshiftContainer("body", [declar]);
|
731
|
-
if (!unique) path.setData(dataKey, declarPath);
|
732
|
-
}
|
733
|
-
const declarator = variableDeclarator(id, init);
|
734
|
-
const len = declarPath.node.declarations.push(declarator);
|
735
|
-
path.scope.registerBinding(kind, declarPath.get("declarations")[len - 1]);
|
736
|
-
}
|
737
|
-
getProgramParent() {
|
738
|
-
let scope = this;
|
739
|
-
do {
|
740
|
-
if (scope.path.isProgram()) {
|
741
|
-
return scope;
|
742
|
-
}
|
743
|
-
} while (scope = scope.parent);
|
744
|
-
throw new Error("Couldn't find a Program");
|
745
|
-
}
|
746
|
-
getFunctionParent() {
|
747
|
-
let scope = this;
|
748
|
-
do {
|
749
|
-
if (scope.path.isFunctionParent()) {
|
750
|
-
return scope;
|
751
|
-
}
|
752
|
-
} while (scope = scope.parent);
|
753
|
-
return null;
|
754
|
-
}
|
755
|
-
getBlockParent() {
|
756
|
-
let scope = this;
|
757
|
-
do {
|
758
|
-
if (scope.path.isBlockParent()) {
|
759
|
-
return scope;
|
760
|
-
}
|
761
|
-
} while (scope = scope.parent);
|
762
|
-
throw new Error("We couldn't find a BlockStatement, For, Switch, Function, Loop or Program...");
|
763
|
-
}
|
764
|
-
getPatternParent() {
|
765
|
-
let scope = this;
|
766
|
-
do {
|
767
|
-
if (!scope.path.isPattern()) {
|
768
|
-
return scope.getBlockParent();
|
769
|
-
}
|
770
|
-
} while (scope = scope.parent.parent);
|
771
|
-
throw new Error("We couldn't find a BlockStatement, For, Switch, Function, Loop or Program...");
|
772
|
-
}
|
773
|
-
getAllBindings() {
|
774
|
-
const ids = Object.create(null);
|
775
|
-
let scope = this;
|
776
|
-
do {
|
777
|
-
for (const key of Object.keys(scope.bindings)) {
|
778
|
-
if (key in ids === false) {
|
779
|
-
ids[key] = scope.bindings[key];
|
780
|
-
}
|
781
|
-
}
|
782
|
-
scope = scope.parent;
|
783
|
-
} while (scope);
|
784
|
-
return ids;
|
785
|
-
}
|
786
|
-
getAllBindingsOfKind(...kinds) {
|
787
|
-
const ids = Object.create(null);
|
788
|
-
for (const kind of kinds) {
|
789
|
-
let scope = this;
|
790
|
-
do {
|
791
|
-
for (const name of Object.keys(scope.bindings)) {
|
792
|
-
const binding = scope.bindings[name];
|
793
|
-
if (binding.kind === kind) ids[name] = binding;
|
794
|
-
}
|
795
|
-
scope = scope.parent;
|
796
|
-
} while (scope);
|
797
|
-
}
|
798
|
-
return ids;
|
799
|
-
}
|
800
|
-
bindingIdentifierEquals(name, node) {
|
801
|
-
return this.getBindingIdentifier(name) === node;
|
802
|
-
}
|
803
|
-
getBinding(name) {
|
804
|
-
let scope = this;
|
805
|
-
let previousPath;
|
806
|
-
do {
|
807
|
-
const binding = scope.getOwnBinding(name);
|
808
|
-
if (binding) {
|
809
|
-
if (previousPath?.isPattern() && binding.kind !== "param" && binding.kind !== "local") {} else {
|
810
|
-
return binding;
|
811
|
-
}
|
812
|
-
} else if (!binding && name === "arguments" && scope.path.isFunction() && !scope.path.isArrowFunctionExpression()) {
|
813
|
-
break;
|
814
|
-
}
|
815
|
-
previousPath = scope.path;
|
816
|
-
} while (scope = scope.parent);
|
817
|
-
}
|
818
|
-
getOwnBinding(name) {
|
819
|
-
return this.bindings[name];
|
820
|
-
}
|
821
|
-
getBindingIdentifier(name) {
|
822
|
-
return this.getBinding(name)?.identifier;
|
823
|
-
}
|
824
|
-
getOwnBindingIdentifier(name) {
|
825
|
-
const binding = this.bindings[name];
|
826
|
-
return binding?.identifier;
|
827
|
-
}
|
828
|
-
hasOwnBinding(name) {
|
829
|
-
return !!this.getOwnBinding(name);
|
830
|
-
}
|
831
|
-
hasBinding(name, opts) {
|
832
|
-
if (!name) return false;
|
833
|
-
if (this.hasOwnBinding(name)) return true;
|
834
|
-
{
|
835
|
-
if (typeof opts === "boolean") opts = {
|
836
|
-
noGlobals: opts
|
837
|
-
};
|
838
|
-
}
|
839
|
-
if (this.parentHasBinding(name, opts)) return true;
|
840
|
-
if (!opts?.noUids && this.hasUid(name)) return true;
|
841
|
-
if (!opts?.noGlobals && Scope.globals.includes(name)) return true;
|
842
|
-
if (!opts?.noGlobals && Scope.contextVariables.includes(name)) return true;
|
843
|
-
return false;
|
844
|
-
}
|
845
|
-
parentHasBinding(name, opts) {
|
846
|
-
return this.parent?.hasBinding(name, opts);
|
847
|
-
}
|
848
|
-
moveBindingTo(name, scope) {
|
849
|
-
const info = this.getBinding(name);
|
850
|
-
if (info) {
|
851
|
-
info.scope.removeOwnBinding(name);
|
852
|
-
info.scope = scope;
|
853
|
-
scope.bindings[name] = info;
|
854
|
-
}
|
855
|
-
}
|
856
|
-
removeOwnBinding(name) {
|
857
|
-
delete this.bindings[name];
|
858
|
-
}
|
859
|
-
removeBinding(name) {
|
860
|
-
this.getBinding(name)?.scope.removeOwnBinding(name);
|
861
|
-
let scope = this;
|
862
|
-
do {
|
863
|
-
if (scope.uids[name]) {
|
864
|
-
scope.uids[name] = false;
|
865
|
-
}
|
866
|
-
} while (scope = scope.parent);
|
867
|
-
}
|
868
|
-
}
|
869
|
-
|
870
|
-
//# sourceMappingURL=index.js.map
|