@babel/traverse
Version:
The Babel Traverse module maintains the overall tree state, and is responsible for replacing, removing, and adding nodes
4,953 lines • 152 kB
JavaScript
import { createDebug } from 'obug';
import * as _t from '@babel/types';
import globalsBuiltinLower from '@babel/helper-globals/data/builtin-lower.json' with { type: 'json' };
import globalsBuiltinUpper from '@babel/helper-globals/data/builtin-upper.json' with { type: 'json' };
import generator from '@babel/generator';
import { codeFrameColumns } from '@babel/code-frame';
import { parse } from '@babel/parser';
import template from '@babel/template';
const ReferencedIdentifier = ["Identifier", "JSXIdentifier"];
const ReferencedMemberExpression = ["MemberExpression"];
const BindingIdentifier = ["Identifier"];
const Statement = ["Statement"];
const Expression = ["Expression"];
const Scope$1 = ["Scopable", "Pattern"];
const Referenced = null;
const BlockScoped = ["FunctionDeclaration", "ClassDeclaration", "VariableDeclaration"];
const Var = ["VariableDeclaration"];
const User = null;
const Generated = null;
const Pure = null;
const Flow = ["Flow", "ImportDeclaration", "ExportDeclaration", "ImportSpecifier"];
const RestProperty = ["RestElement"];
const SpreadProperty = ["RestElement"];
const ExistentialTypeParam = ["ExistsTypeAnnotation"];
const NumericLiteralTypeAnnotation = ["NumberLiteralTypeAnnotation"];
const ForAwaitStatement = ["ForOfStatement"];
const virtualTypes = /*#__PURE__*/Object.defineProperty({
__proto__: null,
BindingIdentifier,
BlockScoped,
ExistentialTypeParam,
Expression,
Flow,
ForAwaitStatement,
Generated,
NumericLiteralTypeAnnotation,
Pure,
Referenced,
ReferencedIdentifier,
ReferencedMemberExpression,
RestProperty,
Scope: Scope$1,
SpreadProperty,
Statement,
User,
Var
}, Symbol.toStringTag, { value: 'Module' });
class TraversalContext {
constructor(opts, state) {
this.state = state;
this.opts = opts;
}
queue = null;
priorityQueue = null;
maybeQueue(path, notPriority) {
if (this.queue) {
if (notPriority) {
this.queue.push(path);
} else {
this.priorityQueue.push(path);
}
}
}
}
const {
VISITOR_KEYS: VISITOR_KEYS$4
} = _t;
function _visitPaths(ctx, paths) {
ctx.queue = paths;
ctx.priorityQueue = [];
const visited = new Set();
let stop = false;
let visitIndex = 0;
for (; visitIndex < paths.length;) {
const path = paths[visitIndex];
visitIndex++;
resync.call(path);
if (path.contexts.length === 0 || path.contexts[path.contexts.length - 1] !== ctx) {
pushContext.call(path, ctx);
}
if (path.key === null) continue;
const {
node
} = path;
if (visited.has(node)) continue;
if (node) visited.add(node);
if (_visit(ctx, path)) {
stop = true;
break;
}
if (ctx.priorityQueue.length) {
stop = _visitPaths(ctx, ctx.priorityQueue);
ctx.priorityQueue = [];
ctx.queue = paths;
if (stop) break;
}
}
for (let i = 0; i < visitIndex; i++) {
popContext.call(paths[i]);
}
ctx.queue = null;
return stop;
}
function _visit(ctx, path) {
const node = path.node;
if (!node) {
return false;
}
const opts = ctx.opts;
const denylist = opts.denylist;
if (denylist?.includes(node.type)) {
return false;
}
if (opts.shouldSkip?.(path)) {
return false;
}
if (path.shouldSkip) return path.shouldStop;
if (_call.call(path, opts.enter)) return path.shouldStop;
if (path.node) {
if (_call.call(path, opts[node.type]?.enter)) return path.shouldStop;
}
path.shouldStop = traverseNode(path.node, opts, path.scope, ctx.state, path, path.skipKeys);
if (path.node) {
if (_call.call(path, opts.exit)) return path.shouldStop;
}
if (path.node) {
_call.call(path, opts[node.type]?.exit);
}
return path.shouldStop;
}
function traverseNode(node, opts, scope, state, path, skipKeys, visitSelf) {
const keys = VISITOR_KEYS$4[node.type];
if (!keys?.length) return false;
const ctx = new TraversalContext(opts, state);
if (visitSelf) {
if (skipKeys?.[path.parentKey]) return false;
return _visitPaths(ctx, [path]);
}
const hub = path == null ? node.type === "Program" || node.type === "File" ? new Hub() : undefined : path.hub;
for (const key of keys) {
if (skipKeys?.[key]) continue;
const prop = node[key];
if (!prop) continue;
if (Array.isArray(prop)) {
if (!prop.length) continue;
const paths = [];
for (let i = 0; i < prop.length; i++) {
const childPath = NodePath_Final.get({
parentPath: path,
parent: node,
container: prop,
key: i,
listKey: key,
hub
});
paths.push(childPath);
}
if (_visitPaths(ctx, paths)) return true;
} else {
if (_visitPaths(ctx, [NodePath_Final.get({
parentPath: path,
parent: node,
container: node,
key,
listKey: null,
hub
})])) {
return true;
}
}
}
return false;
}
const {
isBinding,
isBlockScoped: nodeIsBlockScoped,
isExportDeclaration: isExportDeclaration$1,
isExpression: nodeIsExpression,
isFlow: nodeIsFlow,
isForStatement,
isForXStatement,
isIdentifier: isIdentifier$5,
isImportDeclaration: isImportDeclaration$1,
isImportSpecifier,
isJSXIdentifier,
isJSXMemberExpression,
isMemberExpression: isMemberExpression$1,
isRestElement: nodeIsRestElement,
isReferenced: nodeIsReferenced,
isScope: nodeIsScope,
isStatement: nodeIsStatement,
isVar: nodeIsVar,
isVariableDeclaration: isVariableDeclaration$2,
react,
isForOfStatement
} = _t;
const {
isCompatTag
} = react;
function isReferencedIdentifier(opts) {
const {
node,
parent
} = this;
if (isIdentifier$5(node, opts)) {
return nodeIsReferenced(node, parent, this.parentPath.parent);
} else if (isJSXIdentifier(node, opts)) {
if (!isJSXMemberExpression(parent) && isCompatTag(node.name)) return false;
return nodeIsReferenced(node, parent, this.parentPath.parent);
} else {
return false;
}
}
function isReferencedMemberExpression() {
const {
node,
parent
} = this;
return isMemberExpression$1(node) && nodeIsReferenced(node, parent);
}
function isBindingIdentifier() {
const {
node,
parent
} = this;
const grandparent = this.parentPath.parent;
return isIdentifier$5(node) && isBinding(node, parent, grandparent);
}
function isStatement$1() {
const {
node,
parent
} = this;
if (nodeIsStatement(node)) {
if (isVariableDeclaration$2(node)) {
if (isForXStatement(parent, {
left: node
})) return false;
if (isForStatement(parent, {
init: node
})) return false;
}
return true;
} else {
return false;
}
}
function isExpression$3() {
if (this.isIdentifier()) {
return this.isReferencedIdentifier();
} else {
return nodeIsExpression(this.node);
}
}
function isScope() {
return nodeIsScope(this.node, this.parent);
}
function isReferenced() {
return nodeIsReferenced(this.node, this.parent);
}
function isBlockScoped() {
return nodeIsBlockScoped(this.node);
}
function isVar() {
return nodeIsVar(this.node);
}
function isUser() {
return !!this.node?.loc;
}
function isGenerated() {
return !this.isUser();
}
function isPure(constantsOnly) {
return this.scope.isPure(this.node, constantsOnly);
}
function isFlow() {
const {
node
} = this;
if (nodeIsFlow(node)) {
return true;
} else if (isImportDeclaration$1(node)) {
return node.importKind === "type" || node.importKind === "typeof";
} else if (isExportDeclaration$1(node)) {
return node.exportKind === "type";
} else if (isImportSpecifier(node)) {
return node.importKind === "type" || node.importKind === "typeof";
} else {
return false;
}
}
function isRestProperty() {
return nodeIsRestElement(this.node) && this.parentPath?.isObjectPattern();
}
function isSpreadProperty() {
return nodeIsRestElement(this.node) && this.parentPath?.isObjectExpression();
}
function isForAwaitStatement() {
return isForOfStatement(this.node, {
await: true
});
}
const NodePath_virtual_types_validator = /*#__PURE__*/Object.defineProperty({
__proto__: null,
isBindingIdentifier,
isBlockScoped,
isExpression: isExpression$3,
isFlow,
isForAwaitStatement,
isGenerated,
isPure,
isReferenced,
isReferencedIdentifier,
isReferencedMemberExpression,
isRestProperty,
isScope,
isSpreadProperty,
isStatement: isStatement$1,
isUser,
isVar
}, Symbol.toStringTag, { value: 'Module' });
const {
DEPRECATED_KEYS,
DEPRECATED_ALIASES,
FLIPPED_ALIAS_KEYS,
TYPES,
__internal__deprecationWarning: deprecationWarning
} = _t;
function isVirtualType(type) {
return type in virtualTypes;
}
function isExplodedVisitor(visitor) {
return visitor?._exploded;
}
function explode$1(visitor) {
if (isExplodedVisitor(visitor)) return visitor;
visitor._exploded = true;
if (Object.hasOwn(visitor, "blacklist")) {
if (!Object.hasOwn(visitor, "denylist")) {
throw new Error("The 'blacklist' visitor option has been renamed to 'denylist'. " + "Please update your configuration.");
}
delete visitor.blacklist;
}
for (const nodeType of Object.keys(visitor)) {
if (shouldIgnoreKey(nodeType)) continue;
const parts = nodeType.split("|");
if (parts.length === 1) continue;
const fns = visitor[nodeType];
delete visitor[nodeType];
for (const part of parts) {
visitor[part] = fns;
}
}
verify$1(visitor);
delete visitor.__esModule;
ensureEntranceObjects(visitor);
ensureCallbackArrays(visitor);
const visitorBase = visitor;
for (const nodeType of Object.keys(visitor)) {
if (shouldIgnoreKey(nodeType)) continue;
if (!isVirtualType(nodeType)) continue;
const fns = visitorBase[nodeType];
for (const type of Object.keys(fns)) {
fns[type] = wrapCheck(nodeType, fns[type]);
}
delete visitorBase[nodeType];
const types = virtualTypes[nodeType];
if (types !== null) {
for (const type of types) {
visitorBase[type] ??= {};
mergePair(visitorBase[type], fns);
}
} else {
mergePair(visitor, fns);
}
}
for (const nodeType of Object.keys(visitor)) {
if (shouldIgnoreKey(nodeType)) continue;
let aliases = FLIPPED_ALIAS_KEYS[nodeType];
if (nodeType in DEPRECATED_KEYS) {
const deprecatedKey = DEPRECATED_KEYS[nodeType];
deprecationWarning(nodeType, deprecatedKey, "Visitor ");
aliases = [deprecatedKey];
} else if (nodeType in DEPRECATED_ALIASES) {
const deprecatedAlias = DEPRECATED_ALIASES[nodeType];
deprecationWarning(nodeType, deprecatedAlias, "Visitor ");
aliases = FLIPPED_ALIAS_KEYS[deprecatedAlias];
}
if (!aliases) continue;
const fns = visitor[nodeType];
delete visitor[nodeType];
for (const alias of aliases) {
const existing = visitorBase[alias];
if (existing) {
mergePair(existing, fns);
} else {
visitorBase[alias] = {
...fns
};
}
}
}
for (const nodeType of Object.keys(visitor)) {
if (shouldIgnoreKey(nodeType)) continue;
ensureCallbackArrays(visitor[nodeType]);
}
return visitor;
}
function verify$1(visitor) {
if (visitor._verified) return;
if (typeof visitor === "function") {
throw new Error("You passed `traverse()` a function when it expected a visitor object, " + "are you sure you didn't mean `{ enter: Function }`?");
}
for (const nodeType of Object.keys(visitor)) {
if (nodeType === "enter" || nodeType === "exit") {
validateVisitorMethods(nodeType, visitor[nodeType]);
}
if (shouldIgnoreKey(nodeType)) continue;
if (!TYPES.includes(nodeType)) {
throw new Error(`You gave us a visitor for the node type ${nodeType} but it's not a valid type in @babel/traverse ${"8.0.6"}`);
}
const visitors = visitor[nodeType];
if (typeof visitors === "object") {
for (const visitorKey of Object.keys(visitors)) {
if (visitorKey === "enter" || visitorKey === "exit") {
validateVisitorMethods(`${nodeType}.${visitorKey}`, visitors[visitorKey]);
} else {
throw new Error("You passed `traverse()` a visitor object with the property " + `${nodeType} that has the invalid property ${visitorKey}`);
}
}
}
}
visitor._verified = true;
}
function validateVisitorMethods(path, val) {
const fns = [].concat(val);
for (const fn of fns) {
if (typeof fn !== "function") {
throw new TypeError(`Non-function found defined in ${path} with type ${typeof fn}`);
}
}
}
function merge(visitors, states = [], wrapper) {
const mergedVisitor = {
_verified: true,
_exploded: true
};
for (let i = 0; i < visitors.length; i++) {
const visitor = explode$1(visitors[i]);
const state = states[i];
let topVisitor = visitor;
if (state || wrapper) {
topVisitor = wrapWithStateOrWrapper(topVisitor, state, wrapper);
}
mergePair(mergedVisitor, topVisitor);
for (const key of Object.keys(visitor)) {
if (shouldIgnoreKey(key)) continue;
let typeVisitor = visitor[key];
if (state || wrapper) {
typeVisitor = wrapWithStateOrWrapper(typeVisitor, state, wrapper);
}
const nodeVisitor = mergedVisitor[key] ||= {};
mergePair(nodeVisitor, typeVisitor);
}
}
return mergedVisitor;
}
function wrapWithStateOrWrapper(oldVisitor, state, wrapper) {
const newVisitor = {};
for (const phase of ["enter", "exit"]) {
let fns = oldVisitor[phase];
if (!Array.isArray(fns)) continue;
fns = fns.map(function (fn) {
let newFn = fn;
if (state) {
newFn = function (path) {
fn.call(state, path, state);
};
}
if (wrapper) {
newFn = wrapper(state?.key, phase, newFn);
}
if (newFn !== fn) {
newFn.toString = () => fn.toString();
}
return newFn;
});
newVisitor[phase] = fns;
}
return newVisitor;
}
function ensureEntranceObjects(obj) {
for (const key of Object.keys(obj)) {
if (shouldIgnoreKey(key)) continue;
const fns = obj[key];
if (typeof fns === "function") {
obj[key] = {
enter: fns
};
}
}
}
function ensureCallbackArrays(obj) {
if (obj.enter && !Array.isArray(obj.enter)) obj.enter = [obj.enter];
if (obj.exit && !Array.isArray(obj.exit)) obj.exit = [obj.exit];
}
function wrapCheck(nodeType, fn) {
const fnKey = `is${nodeType}`;
const validator = NodePath_virtual_types_validator[fnKey];
const newFn = function (path) {
if (validator.call(path)) {
return fn.apply(this, arguments);
}
};
newFn.toString = () => fn.toString();
return newFn;
}
function shouldIgnoreKey(key) {
if (key.startsWith("_")) return true;
if (key === "enter" || key === "exit" || key === "shouldSkip") return true;
if (key === "denylist" || key === "noScope" || key === "skipKeys") {
return true;
}
if (key === "blacklist") {
throw new Error("The 'blacklist' visitor option has been renamed to 'denylist'. " + "Please update your configuration.");
}
return false;
}
function mergePair(dest, src) {
for (const phase of ["enter", "exit"]) {
if (!src[phase]) continue;
dest[phase] = [].concat(dest[phase] || [], src[phase]);
}
}
const _environmentVisitor = {
FunctionParent(path) {
if (path.isArrowFunctionExpression()) return;
path.skip();
if (path.isMethod()) {
path.requeueComputedKeyAndDecorators();
}
},
Property(path) {
if (path.isObjectProperty()) return;
path.skip();
path.requeueComputedKeyAndDecorators();
}
};
function environmentVisitor(visitor) {
return merge([_environmentVisitor, visitor]);
}
const visitors = /*#__PURE__*/Object.defineProperty({
__proto__: null,
environmentVisitor,
explode: explode$1,
isExplodedVisitor,
merge,
verify: verify$1
}, Symbol.toStringTag, { value: 'Module' });
const {
getAssignmentIdentifiers: getAssignmentIdentifiers$1
} = _t;
let renameVisitor;
const getRenameVisitor = () => renameVisitor ??= explode$1({
ReferencedIdentifier({
node
}, state) {
if (node.name === state.oldName) {
node.name = state.newName;
}
},
Scope(path, state) {
if (!path.scope.bindingIdentifierEquals(state.oldName, state.binding.identifier)) {
path.skip();
if (path.isMethod()) {
path.requeueComputedKeyAndDecorators();
}
if (path.isSwitchStatement()) {
path.context.maybeQueue(path.get("discriminant"));
}
}
},
ObjectProperty({
node,
scope
}, state) {
const {
name
} = node.key;
if (node.shorthand && (name === state.oldName || name === state.newName) && scope.getBindingIdentifier(name) === state.binding.identifier) {
node.shorthand = false;
}
},
"AssignmentExpression|Declaration|VariableDeclarator"(path, state) {
if (path.isVariableDeclaration()) return;
const ids = path.isAssignmentExpression() ? getAssignmentIdentifiers$1(path.node) : path.getOuterBindingIdentifiers();
for (const name in ids) {
if (name === state.oldName) ids[name].name = state.newName;
}
}
});
class Renamer {
constructor(binding, oldName, newName) {
this.newName = newName;
this.oldName = oldName;
this.binding = binding;
}
maybeConvertFromExportDeclaration(parentDeclar) {
const maybeExportDeclar = parentDeclar.parentPath;
if (!maybeExportDeclar.isExportDeclaration()) {
return;
}
if (maybeExportDeclar.isExportDefaultDeclaration()) {
const {
declaration
} = maybeExportDeclar.node;
if (_t.isDeclaration(declaration) && !declaration.id) {
return;
}
}
if (maybeExportDeclar.isExportAllDeclaration()) {
return;
}
maybeExportDeclar.splitExportDeclaration();
}
maybeConvertFromClassFunctionDeclaration(path) {
return path;
}
maybeConvertFromClassFunctionExpression(path) {
return path;
}
rename() {
const {
binding,
oldName,
newName
} = this;
const {
scope,
path
} = binding;
const parentDeclar = path.find(path => path.isDeclaration() || path.isFunctionExpression() || path.isClassExpression());
if (parentDeclar) {
const bindingIds = parentDeclar.getOuterBindingIdentifiers();
if (bindingIds[oldName] === binding.identifier) {
this.maybeConvertFromExportDeclaration(parentDeclar);
}
}
const blockToTraverse = scope.block;
const skipKeys = {
discriminant: true
};
if (_t.isMethod(blockToTraverse)) {
if (blockToTraverse.computed) {
skipKeys.key = true;
}
if (!_t.isObjectMethod(blockToTraverse)) {
skipKeys.decorators = true;
}
}
traverseNode(blockToTraverse, getRenameVisitor(), scope, this, scope.path, skipKeys);
scope.removeOwnBinding(oldName);
scope.bindings[newName] = binding;
this.binding.identifier.name = newName;
if (parentDeclar) {
this.maybeConvertFromClassFunctionDeclaration(path);
this.maybeConvertFromClassFunctionExpression(path);
}
}
}
const {
VISITOR_KEYS: VISITOR_KEYS$3
} = _t;
function traverseForScope(path, visitors, state) {
const exploded = explode$1(visitors);
if (exploded.enter || exploded.exit) {
throw new Error("Should not be used with enter/exit visitors.");
}
_traverse(path.parentPath, path.parent, path.node, path.container, path.key, path.listKey, path.hub, path);
function _traverse(parentPath, parent, node, container, key, listKey, hub, inPath) {
if (!node) {
return;
}
const path = inPath || NodePath_Final.get({
hub,
parentPath,
parent,
container,
listKey,
key
});
_forceSetScope.call(path);
const visitor = exploded[node.type];
if (visitor?.enter) {
for (const visit of visitor.enter) {
visit.call(state, path, state);
}
}
if (path.shouldSkip) {
return;
}
const keys = VISITOR_KEYS$3[node.type];
if (!keys?.length) {
return;
}
for (const key of keys) {
const prop = node[key];
if (!prop) continue;
if (Array.isArray(prop)) {
for (let i = 0; i < prop.length; i++) {
const value = prop[i];
_traverse(path, node, value, prop, i, key);
}
} else {
_traverse(path, node, prop, node, key, null);
}
}
if (visitor?.exit) {
for (const visit of visitor.exit) {
visit.call(state, path, state);
}
}
}
}
class Binding {
identifier;
scope;
path;
kind;
constructor({
identifier,
scope,
path,
kind
}) {
this.identifier = identifier;
this.scope = scope;
this.path = path;
this.kind = kind;
if ((kind === "var" || kind === "hoisted") && isInitInLoop(path)) {
this.reassign(path);
}
this.clearValue();
}
constantViolations = [];
constant = true;
referencePaths = [];
referenced = false;
references = 0;
deoptValue() {
this.clearValue();
this.hasDeoptedValue = true;
}
setValue(value) {
if (this.hasDeoptedValue) return;
this.hasValue = true;
this.value = value;
}
clearValue() {
this.hasDeoptedValue = false;
this.hasValue = false;
this.value = null;
}
reassign(path) {
this.constant = false;
if (this.constantViolations.includes(path)) {
return;
}
this.constantViolations.push(path);
}
reference(path) {
if (this.referencePaths.includes(path)) {
return;
}
this.referenced = true;
this.references++;
this.referencePaths.push(path);
}
dereference() {
this.references--;
this.referenced = !!this.references;
}
}
function isInitInLoop(path) {
const isFunctionDeclarationOrHasInit = !path.isVariableDeclarator() || path.node.init;
for (let {
parentPath,
key
} = path; parentPath; {
parentPath,
key
} = parentPath) {
if (parentPath.isFunctionParent()) return false;
if (key === "left" && parentPath.isForXStatement() || isFunctionDeclarationOrHasInit && key === "body" && parentPath.isLoop()) {
return true;
}
}
return false;
}
let pathsCache = new WeakMap();
let scope = new WeakMap();
function clear() {
clearPath();
clearScope();
}
function clearPath() {
pathsCache = new WeakMap();
}
function clearScope() {
scope = new WeakMap();
}
function getCachedPaths(path) {
const {
parent,
parentPath
} = path;
return parentPath ? parentPath._store : pathsCache.get(parent);
}
function getOrCreateCachedPaths(node, parentPath) {
if (parentPath) {
return parentPath._store ||= new Map();
}
let paths = pathsCache.get(node);
if (!paths) pathsCache.set(node, paths = new Map());
return paths;
}
const cache = /*#__PURE__*/Object.defineProperty({
__proto__: null,
clear,
clearPath,
clearScope,
getCachedPaths,
getOrCreateCachedPaths,
get path () { return pathsCache; },
get scope () { return scope; }
}, Symbol.toStringTag, { value: 'Module' });
const {
assignmentExpression: assignmentExpression$3,
cloneNode: cloneNode$3,
getBindingIdentifiers: getBindingIdentifiers$2,
identifier: identifier$3,
isArrayExpression,
isBinary,
isCallExpression: isCallExpression$1,
isClass,
isClassBody,
isClassDeclaration,
isExportAllDeclaration,
isExportDefaultDeclaration,
isExportNamedDeclaration: isExportNamedDeclaration$1,
isFunctionDeclaration,
isIdentifier: isIdentifier$4,
isImportDeclaration,
isLiteral: isLiteral$1,
isMemberExpression,
isMethod,
isModuleSpecifier,
isNullLiteral,
isObjectExpression,
isProperty,
isPureish,
isRegExpLiteral,
isSuper: isSuper$1,
isTaggedTemplateExpression,
isTemplateLiteral,
isThisExpression,
isUnaryExpression,
isVariableDeclaration: isVariableDeclaration$1,
expressionStatement: expressionStatement$3,
matchesPattern: matchesPattern$1,
toIdentifier,
variableDeclaration: variableDeclaration$1,
variableDeclarator: variableDeclarator$1,
isObjectProperty,
isTopicReference,
isMetaProperty,
isPrivateName,
isExportDeclaration,
sequenceExpression: sequenceExpression$2
} = _t;
function gatherNodeParts(node, parts) {
switch (node?.type) {
default:
if (isImportDeclaration(node) || isExportDeclaration(node)) {
if ((isExportAllDeclaration(node) || isExportNamedDeclaration$1(node) || isImportDeclaration(node)) && node.source) {
gatherNodeParts(node.source, parts);
} else if ((isExportNamedDeclaration$1(node) || isImportDeclaration(node)) && node.specifiers?.length) {
for (const e of node.specifiers) gatherNodeParts(e, parts);
} else if ((isExportDefaultDeclaration(node) || isExportNamedDeclaration$1(node)) && node.declaration) {
gatherNodeParts(node.declaration, parts);
}
} else if (isModuleSpecifier(node)) {
gatherNodeParts(node.local, parts);
} else if (isLiteral$1(node) && !isNullLiteral(node) && !isRegExpLiteral(node) && !isTemplateLiteral(node)) {
parts.push(node.value);
}
break;
case "MemberExpression":
case "OptionalMemberExpression":
case "JSXMemberExpression":
gatherNodeParts(node.object, parts);
gatherNodeParts(node.property, parts);
break;
case "Identifier":
case "JSXIdentifier":
parts.push(node.name);
break;
case "CallExpression":
case "OptionalCallExpression":
case "NewExpression":
gatherNodeParts(node.callee, parts);
break;
case "ObjectExpression":
case "ObjectPattern":
for (const e of node.properties) {
gatherNodeParts(e, parts);
}
break;
case "SpreadElement":
case "RestElement":
gatherNodeParts(node.argument, parts);
break;
case "ObjectProperty":
case "ObjectMethod":
case "ClassProperty":
case "ClassMethod":
case "ClassPrivateProperty":
case "ClassPrivateMethod":
gatherNodeParts(node.key, parts);
break;
case "ThisExpression":
parts.push("this");
break;
case "Super":
parts.push("super");
break;
case "Import":
case "ImportExpression":
parts.push("import");
break;
case "DoExpression":
parts.push("do");
break;
case "YieldExpression":
parts.push("yield");
gatherNodeParts(node.argument, parts);
break;
case "AwaitExpression":
parts.push("await");
gatherNodeParts(node.argument, parts);
break;
case "AssignmentExpression":
gatherNodeParts(node.left, parts);
break;
case "VariableDeclarator":
gatherNodeParts(node.id, parts);
break;
case "FunctionExpression":
case "FunctionDeclaration":
case "ClassExpression":
case "ClassDeclaration":
gatherNodeParts(node.id, parts);
break;
case "PrivateName":
gatherNodeParts(node.id, parts);
break;
case "ParenthesizedExpression":
gatherNodeParts(node.expression, parts);
break;
case "UnaryExpression":
case "UpdateExpression":
gatherNodeParts(node.argument, parts);
break;
case "MetaProperty":
gatherNodeParts(node.meta, parts);
gatherNodeParts(node.property, parts);
break;
case "JSXElement":
gatherNodeParts(node.openingElement, parts);
break;
case "JSXOpeningElement":
gatherNodeParts(node.name, parts);
break;
case "JSXFragment":
gatherNodeParts(node.openingFragment, parts);
break;
case "JSXOpeningFragment":
parts.push("Fragment");
break;
case "JSXNamespacedName":
gatherNodeParts(node.namespace, parts);
gatherNodeParts(node.name, parts);
break;
}
}
function resetScope(scope) {
if (scope.path.type === "Program") {
scope.referencesSet = new Set();
scope.uidsSet = new Set();
}
scope.bindings = Object.create(null);
scope.globals = Object.create(null);
}
function isAnonymousFunctionExpression(path) {
return path.isFunctionExpression() && !path.node.id || path.isArrowFunctionExpression();
}
const collectorVisitor = {
ForStatement(path) {
const declar = path.get("init");
if (declar.isVar()) {
const {
scope
} = path;
const parentScope = scope.getFunctionParent() || scope.getProgramParent();
parentScope.registerBinding("var", declar);
}
},
Declaration(path) {
if (path.isBlockScoped()) return;
if (path.isImportDeclaration()) return;
if (path.isExportDeclaration()) return;
const parent = path.scope.getFunctionParent() || path.scope.getProgramParent();
parent.registerDeclaration(path);
},
ImportDeclaration(path) {
const parent = path.scope.getBlockParent();
parent.registerDeclaration(path);
},
TSImportEqualsDeclaration(path) {
const parent = path.scope.getBlockParent();
parent.registerDeclaration(path);
},
ReferencedIdentifier(path, state) {
if (_t.isTSQualifiedName(path.parent) && path.parent.right === path.node) {
return;
}
if (path.parentPath.isTSImportEqualsDeclaration()) return;
state.references.push(path);
},
ForXStatement(path, state) {
const left = path.get("left");
if (left.isPattern() || left.isIdentifier()) {
state.constantViolations.push(path);
} else if (left.isVar()) {
const {
scope
} = path;
const parentScope = scope.getFunctionParent() || scope.getProgramParent();
parentScope.registerBinding("var", left);
}
},
ExportDeclaration: {
exit(path) {
const {
node,
scope
} = path;
if (isExportAllDeclaration(node)) return;
const declar = node.declaration;
if (isClassDeclaration(declar) || isFunctionDeclaration(declar)) {
const id = declar.id;
if (!id) return;
const binding = scope.getBinding(id.name);
binding?.reference(path);
} else if (isVariableDeclaration$1(declar)) {
for (const decl of declar.declarations) {
for (const name of Object.keys(getBindingIdentifiers$2(decl))) {
const binding = scope.getBinding(name);
binding?.reference(path);
}
}
}
}
},
LabeledStatement(path) {
path.scope.getBlockParent().registerDeclaration(path);
},
AssignmentExpression(path, state) {
state.assignments.push(path);
},
UpdateExpression(path, state) {
state.constantViolations.push(path);
},
UnaryExpression(path, state) {
if (path.node.operator === "delete") {
state.constantViolations.push(path);
}
},
BlockScoped(path) {
let scope = path.scope;
if (scope.path === path) scope = scope.parent;
const parent = scope.getBlockParent();
parent.registerDeclaration(path);
if (path.isClassDeclaration() && path.node.id) {
const id = path.node.id;
const name = id.name;
path.scope.bindings[name] = path.scope.parent.getBinding(name);
}
},
CatchClause(path) {
path.scope.registerBinding("let", path);
},
Function(path) {
const params = path.get("params");
for (const param of params) {
path.scope.registerBinding("param", param);
}
if (path.isFunctionExpression() && path.node.id) {
path.scope.registerBinding("local", path.get("id"), path);
}
},
ClassExpression(path) {
if (path.node.id) {
path.scope.registerBinding("local", path.get("id"), path);
}
},
TSTypeAnnotation(path) {
path.skip();
}
};
let scopeVisitor;
let uid = 0;
class Scope {
uid;
path;
block;
inited;
labels;
bindings;
referencesSet;
globals;
uidsSet;
data;
crawling;
constructor(path) {
const {
node
} = path;
const cached = scope.get(node);
if (cached?.path === path) {
return cached;
}
scope.set(node, this);
this.uid = uid++;
this.block = node;
this.path = path;
this.labels = new Map();
this.inited = false;
}
static globals = [...globalsBuiltinLower, ...globalsBuiltinUpper];
static contextVariables = ["arguments", "undefined", "Infinity", "NaN"];
get parent() {
let parent,
path = this.path;
do {
const shouldSkip = path.key === "key" || path.listKey === "decorators";
path = path.parentPath;
if (shouldSkip && path.isMethod()) path = path.parentPath;
if (path?.isScope()) parent = path;
} while (path && !parent);
return parent?.scope;
}
get references() {
throw new Error("Scope#references is not available in Babel 8. Use Scope#referencesSet instead.");
}
get uids() {
throw new Error("Scope#uids is not available in Babel 8. Use Scope#uidsSet instead.");
}
generateDeclaredUidIdentifier(name) {
const id = this.generateUidIdentifier(name);
this.push({
id
});
return cloneNode$3(id);
}
generateUidIdentifier(name) {
return identifier$3(this.generateUid(name));
}
generateUid(name = "temp") {
name = toIdentifier(name).replace(/^_+/, "").replace(/\d+$/g, "");
let uid;
let i = 0;
do {
uid = `_${name}`;
if (i >= 11) uid += i - 1;else if (i >= 9) uid += i - 9;else if (i >= 1) uid += i + 1;
i++;
} while (this.hasLabel(uid) || this.hasBinding(uid) || this.hasGlobal(uid) || this.hasReference(uid));
const program = this.getProgramParent();
program.referencesSet.add(uid);
program.uidsSet.add(uid);
return uid;
}
generateUidBasedOnNode(node, defaultName) {
const parts = [];
gatherNodeParts(node, parts);
let id = parts.join("$");
id = id.replace(/^_/, "") || defaultName || "ref";
return this.generateUid(id.slice(0, 20));
}
generateUidIdentifierBasedOnNode(node, defaultName) {
return identifier$3(this.generateUidBasedOnNode(node, defaultName));
}
isStatic(node) {
if (isThisExpression(node) || isSuper$1(node) || isTopicReference(node)) {
return true;
}
if (isIdentifier$4(node)) {
const binding = this.getBinding(node.name);
if (binding) {
return binding.constant;
} else {
return this.hasBinding(node.name);
}
}
return false;
}
maybeGenerateMemoised(node, dontPush) {
if (this.isStatic(node)) {
return null;
} else {
const id = this.generateUidIdentifierBasedOnNode(node);
if (!dontPush) {
this.push({
id
});
return cloneNode$3(id);
}
return id;
}
}
checkBlockScopedCollisions(local, kind, name, id) {
if (kind === "param") return;
if (local.kind === "local") return;
const duplicate = kind === "let" || local.kind === "let" || local.kind === "const" || local.kind === "module" || local.kind === "param" && kind === "const";
if (duplicate) {
throw this.path.hub.buildError(id, `Duplicate declaration "${name}"`, TypeError);
}
}
rename(oldName, newName) {
const binding = this.getBinding(oldName);
if (binding) {
newName ||= this.generateUidIdentifier(oldName).name;
const renamer = new Renamer(binding, oldName, newName);
renamer.rename();
}
}
dump() {
const sep = "-".repeat(60);
console.log(sep);
let scope = this;
do {
console.log("#", scope.block.type);
for (const name of Object.keys(scope.bindings)) {
const binding = scope.bindings[name];
console.log(" -", name, {
constant: binding.constant,
references: binding.references,
violations: binding.constantViolations.length,
kind: binding.kind
});
}
} while (scope = scope.parent);
console.log(sep);
}
hasLabel(name) {
return !!this.getLabel(name);
}
getLabel(name) {
return this.labels.get(name);
}
registerLabel(path) {
this.labels.set(path.node.label.name, path);
}
registerDeclaration(path) {
if (path.isLabeledStatement()) {
this.registerLabel(path);
} else if (path.isFunctionDeclaration()) {
this.registerBinding("hoisted", path.get("id"), path);
} else if (path.isVariableDeclaration()) {
const declarations = path.get("declarations");
const {
kind
} = path.node;
for (const declar of declarations) {
this.registerBinding(kind === "using" || kind === "await using" ? "const" : kind, declar);
}
} else if (path.isClassDeclaration()) {
if (path.node.declare) return;
this.registerBinding("let", path);
} else if (path.isImportDeclaration()) {
const isTypeDeclaration = path.node.importKind === "type" || path.node.importKind === "typeof";
const specifiers = path.get("specifiers");
for (const specifier of specifiers) {
const isTypeSpecifier = isTypeDeclaration || specifier.isImportSpecifier() && (specifier.node.importKind === "type" || specifier.node.importKind === "typeof");
this.registerBinding(isTypeSpecifier ? "unknown" : "module", specifier);
}
} else if (path.isExportDeclaration()) {
const declar = path.get("declaration");
if (declar.isClassDeclaration() || declar.isFunctionDeclaration() || declar.isVariableDeclaration()) {
this.registerDeclaration(declar);
}
} else {
this.registerBinding("unknown", path);
}
}
registerConstantViolation(path) {
const ids = path.getAssignmentIdentifiers();
for (const name of Object.keys(ids)) {
this.getBinding(name)?.reassign(path);
}
}
registerBinding(kind, path, bindingPath = path) {
if (!kind) throw new ReferenceError("no `kind`");
if (path.isVariableDeclaration()) {
const declarators = path.get("declarations");
for (const declar of declarators) {
this.registerBinding(kind, declar);
}
return;
}
const parent = this.getProgramParent();
const ids = path.getOuterBindingIdentifiers(true);
for (const name of Object.keys(ids)) {
parent.referencesSet.add(name);
for (const id of ids[name]) {
const local = this.getOwnBinding(name);
if (local) {
if (local.identifier === id) continue;
this.checkBlockScopedCollisions(local, kind, name, id);
}
if (local) {
local.reassign(bindingPath);
} else {
this.bindings[name] = new Binding({
identifier: id,
scope: this,
path: bindingPath,
kind: kind
});
}
}
}
}
addGlobal(node) {
this.globals[node.name] = node;
}
hasUid(name) {
return this.getProgramParent().uidsSet.has(name);
}
hasGlobal(name) {
let scope = this;
do {
if (scope.globals[name]) return true;
} while (scope = scope.parent);
return false;
}
hasReference(name) {
return this.getProgramParent().referencesSet.has(name);
}
isPure(node, constantsOnly) {
if (isIdentifier$4(node)) {
const binding = this.getBinding(node.name);
if (!binding) return false;
if (constantsOnly) return binding.constant;
return true;
} else if (isThisExpression(node) || isMetaProperty(node) || isTopicReference(node) || isPrivateName(node)) {
return true;
} else if (isClass(node)) {
if (node.superClass && !this.isPure(node.superClass, constantsOnly)) {
return false;
}
if (node.decorators?.length > 0) {
return false;
}
return this.isPure(node.body, constantsOnly);
} else if (isClassBody(node)) {
for (const method of node.body) {
if (!this.isPure(method, constantsOnly)) return false;
}
return true;
} else if (isBinary(node)) {
return this.isPure(node.left, constantsOnly) && this.isPure(node.right, constantsOnly);
} else if (isArrayExpression(node)) {
for (const elem of node.elements) {
if (elem !== null && !this.isPure(elem, constantsOnly)) return false;
}
return true;
} else if (isObjectExpression(node)) {
for (const prop of node.properties) {
if (!this.isPure(prop, constantsOnly)) return false;
}
return true;
} else if (isMethod(node)) {
if (node.computed && !this.isPure(node.key, constantsOnly)) return false;
if (node.decorators?.length > 0) {
return false;
}
return true;
} else if (isProperty(node)) {
if (node.computed && !this.isPure(node.key, constantsOnly)) return false;
if (node.decorators?.length > 0) {
return false;
}
if (isObjectProperty(node) || node.static) {
if (node.value !== null && !this.isPure(node.value, constantsOnly)) {
return false;
}
}
return true;
} else if (isUnaryExpression(node)) {
return this.isPure(node.argument, constantsOnly);
} else if (isTemplateLiteral(node)) {
for (const expression of node.expressions) {
if (!this.isPure(expression, constantsOnly)) return false;
}
return true;
} else if (isTaggedTemplateExpression(node)) {
return matchesPattern$1(node.tag, "String.raw") && !this.hasBinding("String", {
noGlobals: true
}) && this.isPure(node.quasi, constantsOnly);
} else if (isMemberExpression(node)) {
return !node.computed && isIdentifier$4(node.object) && node.object.name === "Symbol" && isIdentifier$4(node.property) && node.property.name !== "for" && !this.hasBinding("Symbol", {
noGlobals: true
});
} else if (isCallExpression$1(node)) {
return matchesPattern$1(node.callee, "Symbol.for") && !this.hasBinding("Symbol", {
noGlobals: true
}) && node.arguments.length === 1 && _t.isStringLiteral(node.arguments[0]);
} else {
return isPureish(node);
}
}
setData(key, val) {
return this.data[key] = val;
}
getData(key) {
let scope = this;
do {
const data = scope.data[key];
if (data != null) return data;
} while (scope = scope.parent);
}
removeData(key) {
let scope = this;
do {
const data = scope.data[key];
if (data != null) scope.data[key] = null;
} while (scope = scope.parent);
}
init() {
if (!this.inited) {
this.inited = true;
this.crawl();
}
}
crawl() {
const path = this.path;
resetScope(this);
this.data = Object.create(null);
let scope = this;
do {
if (scope.crawling) return;
if (scope.path.isProgram()) {
break;
}
} while (scope = scope.parent);
const programParent = scope;
const state = {
references: [],
constantViolations: [],
assignments: []
};
this.crawling = true;
scopeVisitor ||= traverse.visitors.merge([{
Scope(path) {
resetScope(path.scope);
}
}, collectorVisitor]);
if (path.type !== "Program") {
const typeVisitors = scopeVisitor[path.type];
if (typeVisitors) {
for (const visit of typeVisitors.enter) {
visit.call(state, path, state);
}
}
}
traverseForScope(path, scopeVisitor, state);
this.crawling = false;
for (const path of state.assignments) {
const ids = path.getAssignmentIdentifiers();
for (const name of Object.keys(ids)) {
if (path.scope.getBinding(name)) continue;
programParent.addGlobal(ids[name]);
}
path.scope.registerConstantViolation(path);
}
for (const ref of state.references) {
const binding = ref.scope.getBinding(ref.node.name);
if (binding) {
binding.reference(ref);
} else {
programParent.addGlobal(ref.node);
}
}
for (const path of state.constantViolations) {
path.scope.registerConstantViolation(path);
}
}
push(opts) {
let path = this.path;
if (path.isPattern()) {
path = this.getPatternParent().path;
} else if (!path.isBlockStatement() && !path.isProgram()) {
path = this.getBlockParent().path;
}
if (path.isSwitchStatement()) {
path = (this.getFunctionParent() || this.getProgramParent()).path;
}
const {
init,
unique,
kind = "var",
id
} = opts;
if (!init && !unique && (kind === "var" || kind === "let") && isAnonymousFunctionExpression(path) && isCallExpression$1(path.parent, {
callee: path.node
}) && path.parent.arguments.length <= path.node.params.length && isIdentifier$4(id)) {
path.pushContainer("params", id);
path.scope.registerBinding("param", path.get("params")[path.node.params.length - 1]);
return;
}
if (path.isLoop() || path.isCatchClause() || path.isFunction()) {
path.ensureBlock();
path = path.get("body");
}
const blockHoist = opts._blockHoist == null ? 2 : opts._blockHoist;
const dataKey = `declaration:${kind}:${blockHoist}`;
let declarPath = !unique && path.getData(dataKey);
if (!declarPath) {
const declar = variableDeclaration$1(kind, []);
declar._blockHoist = blockHoist;
[declarPath] = path.unshiftContainer("body", [declar]);
if (!unique) path.setData(dataKey, declarPath);
}
const declarator = variableDeclarator$1(id, init);
const len = declarPath.node.declarations.push(declarator);
path.scope.registerBinding(kind, declarPath.get("declarations")[len - 1]);
}
getProgramParent() {
let scope = this;
do {
if (scope.path.isProgram()) {
return scope;
}
} while (scope = scope.parent);
throw new Error("Couldn't find a Program");
}
getFunctionParent() {
let scope = this;
do {
if (scope.path.isFunctionParent()) {
return scope;
}
} while (scope = scope.parent);
return null;
}
getBlockParent() {
let scope = this;
do {
if (scope.path.isBlockParent()) {
return scope;
}
} while (scope = scope.parent);
throw new Error("We couldn't find a BlockStatement, For, Switch, Function, Loop or Program...");
}
getPatternParent() {
let scope = this;
do {
if (!scope.path.isPattern()) {
return scope.getBlockParent();
}
} while (scope = scope.parent.parent);
throw new Error("We couldn't find a BlockStatement, For, Switch, Function, Loop or Program...");
}
getAllBindings() {
const ids = Object.create(null);
let scope = this;
do {
for (const key of Object.keys(scope.bindings)) {
if (key in ids === false) {
ids[key] = scope.bindings[key];
}
}
scope = scope.parent;
} while (scope);
return ids;
}
bindingIdentifierEquals(name, node) {
return this.getBindingIdentifier(name) === node;
}
getBinding(name) {
let scope = this;
let previousPath;
do {
const binding = scope.getOwnBinding(name);
if (binding) {
if (previousPath?.isPattern() && binding.kind !== "param" && binding.kind !== "local") ; else {
return binding;
}
} else if (!binding && name === "arguments" && scope.path.isFunction() && !scope.path.isArrowFunctionExpression()) {
break;
}
previousPath = scope.path;
} while (scope = scope.parent);
}
getOwnBinding(name) {
return this.bindings[name];
}
getBindingIdentifier(name) {
return this.getBinding(name)?.identifier;
}
getOwnBindingIdentifier(name) {
const binding = this.bindings[name];
return binding?.identifier;
}
hasOwnBinding(name) {
return !!this.getOwnBinding(name);
}
hasBinding(name, opts) {
if (!name) return false;
let noGlobals;
let noUids;
let upToScope;
if (typeof opts === "object") {
noGlobals = opts.noGlobals;
noUids = opts.noUids;
upToScope = opts.upToScope;
} else if (typeof opts === "boolean") {
noGlobals = opts;
}
let scope = this;
do {
if (upToScope === scope) {
break;
}
if (scope.hasOwnBinding(name)) {
return true;
}
} while (scope = scope.parent);
if (!noUids && this.hasUid(name)) return true;
if (!noGlobals && Scope.globals.includes(name)) return true;
if (!noGlobals && Scope.contextVariables.includes(name)) return true;
return false;
}
parentHasBinding(name, opts) {
return this.parent?.hasBinding(name, opts);
}
moveBindingTo(name, scope) {
const info = this.getBinding(name);
if (info) {
info.scope.removeOwnBinding(name);
info.scope = scope;
scope.bindings[name] = info;
}
}
removeOwnBinding(name) {
delete this.bindings[name];
}
removeBinding(name) {
this.getBinding(name)?.scope.removeOwnBinding(name);
this.getProgramParent().uidsSet.delete(name);
}
hoistVariables(emit = id => this.push({
id
})) {
this.crawl();
const seen = new Set();
for (const name of Object.keys(this.bindings)) {
const binding = this.bindings[name];
if (!binding) continue;
const {
path
} = binding;
if (!path.isVariableDeclarator()) continue;
const {
parent,
parentPath
} = path;
if (parent.kind !== "var" || seen.has(parent)) continue;
seen.add(path.parent);
let firstId;
const init = [];
for (const decl of parent.declarations) {
firstId ??= decl.id;
if (decl.init) {
init.push(assignmentExpression$3("=", decl.id, decl.init));
}
const ids = Object.keys(getBindingIdentifiers$2(decl, false, true, true));
for (const name of ids) {
emit(identifier$3(name), decl.init != null);
}
}
if (parentPath.parentPath.isForXStatement({
left: parent
})) {
parentPath.replaceWith(firstId);
} else if (init.length === 0) {
parentPath.remove();
} else {
const expr = init.length === 1 ? init[0] : sequenceExpression$2(init);
if (parentPath.parentPath.isForStatement({
init: parent
})) {
parentPath.replaceWith(expr);
} else {
parentPath.replaceWith(expressionStatement$3(expr));
}
}
}
}
}
const {
VISITOR_KEYS: VISITOR_KEYS$2
} = _t;
function findParent(callback) {
let path = this;
while (path = path.parentPath) {
if (callback(path)) return path;
}
return null;
}
function find(callback) {
let path = this;
do {
if (callback(path)) return path;
} while (path = path.parentPath);
return null;
}
function getFunctionParent() {
return this.findParent(p => p.isFunction());
}
function getStatementParent() {
let path = this;
do {
if (!path.parentPath || Array.isArray(path.container) && path.isStatement()) {
break;
} else {
path = path.parentPath;
}
} while (path);
if (path && (path.isProgram() || path.isFile())) {
throw new Error("File/Program node, we can't possibly find a statement parent to this");
}
return path;
}
function getEarliestCommonAncestorFrom(paths) {
return this.getDeepestCommonAncestorFrom(paths, function (deepest, i, ancestries) {
let earliest;
const keys = VISITOR_KEYS$2[deepest.type];
for (const ancestry of ancestries) {
const path = ancestry[i + 1];
if (!earliest) {
earliest = path;
continue;
}
if (path.listKey && earliest.listKey === path.listKey) {
if (path.key < earliest.key) {
earliest = path;
continue;
}
}
const earliestKeyIndex = keys.indexOf(earliest.parentKey);
const currentKeyIndex = keys.indexOf(path.parentKey);
if (earliestKeyIndex > currentKeyIndex) {
earliest = path;
}
}
return earliest;
});
}
function getDeepestCommonAncestorFrom(paths, filter) {
if (!paths.length) {
return this;
}
if (paths.length === 1) {
return paths[0];
}
let minDepth = Infinity;
let lastCommonIndex, lastCommon;
const ancestries = paths.map(path => {
const ancestry = [];
do {
ancestry.unshift(path);
} while ((path = path.parentPath) && path !== this);
if (ancestry.length < minDepth) {
minDepth = ancestry.length;
}
return ancestry;
});
const first = ancestries[0];
depthLoop: for (let i = 0; i < minDepth; i++) {
const shouldMatch = first[i];
for (const ancestry of ancestries) {
if (ancestry[i] !== shouldMatch) {
break depthLoop;
}
}
lastCommonIndex = i;
lastCommon = shouldMatch;
}
if (lastCommon) {
if (filter) {
return filter(lastCommon, lastCommonIndex, ancestries);
} else {
return lastCommon;
}
} else {
throw new Error("Couldn't find intersection");
}
}
function getAncestry() {
let path = this;
const paths = [];
do {
paths.push(path);
} while (path = path.parentPath);
return paths;
}
function isAncestor(maybeDescendant) {
return maybeDescendant.isDescendant(this);
}
function isDescendant(maybeAncestor) {
return !!this.findParent(parent => parent === maybeAncestor);
}
function inType(...candidateTypes) {
let path = this;
while (path) {
if (candidateTypes.includes(path.node.type)) return true;
path = path.parentPath;
}
return false;
}
const {
createFlowUnionType,
createTSUnionType,
isFlowType,
isTSType
} = _t;
function createUnionType(types) {
if (types.every(v => isFlowType(v))) {
return createFlowUnionType(types);
}
if (types.every(v => isTSType(v))) {
return createTSUnionType(types);
}
}
const {
BOOLEAN_NUMBER_BINARY_OPERATORS,
createTypeAnnotationBasedOnTypeof,
numberTypeAnnotation: numberTypeAnnotation$1,
voidTypeAnnotation: voidTypeAnnotation$2
} = _t;
function infererReference (node) {
if (!this.isReferenced()) return;
const binding = this.scope.getBinding(node.name);
if (binding) {
if (binding.identifier.typeAnnotation) {
return binding.identifier.typeAnnotation;
} else {
return getTypeAnnotationBindingConstantViolations(binding, this, node.name);
}
}
if (node.name === "undefined") {
return voidTypeAnnotation$2();
} else if (node.name === "NaN" || node.name === "Infinity") {
return numberTypeAnnotation$1();
} else if (node.name === "arguments") ;
}
function getTypeAnnotationBindingConstantViolations(binding, path, name) {
const types = [];
const functionConstantViolations = [];
let constantViolations = getConstantViolationsBefore(binding, path, functionConstantViolations);
const testType = getConditionalAnnotation(binding, path, name);
if (testType) {
const testConstantViolations = getConstantViolationsBefore(binding, testType.ifStatement);
constantViolations = constantViolations.filter(path => !testConstantViolations.includes(path));
types.push(testType.typeAnnotation);
}
if (constantViolations.length) {
constantViolations.push(...functionConstantViolations);
for (const violation of constantViolations) {
types.push(violation.getTypeAnnotation());
}
}
if (!types.length) {
return;
}
return createUnionType(types);
}
function getConstantViolationsBefore(binding, path, functions) {
const violations = binding.constantViolations.slice();
violations.unshift(binding.path);
return violations.filter(violation => {
violation = violation.resolve();
const status = violation._guessExecutionStatusRelativeTo(path);
if (functions && status === "unknown") functions.push(violation);
return status === "before";
});
}
function inferAnnotationFromBinaryExpression(name, path) {
const operator = path.node.operator;
const right = path.get("right").resolve();
const left = path.get("left").resolve();
let target;
if (left.isIdentifier({
name
})) {
target = right;
} else if (right.isIdentifier({
name
})) {
target = left;
}
if (target) {
if (operator === "===") {
return target.getTypeAnnotation();
}
if (BOOLEAN_NUMBER_BINARY_OPERATORS.includes(operator)) {
return numberTypeAnnotation$1();
}
return;
}
if (operator !== "===" && operator !== "==") return;
let typeofPath;
let typePath;
if (left.isUnaryExpression({
operator: "typeof"
})) {
typeofPath = left;
typePath = right;
} else if (right.isUnaryExpression({
operator: "typeof"
})) {
typeofPath = right;
typePath = left;
}
if (!typeofPath) return;
if (!typeofPath.get("argument").isIdentifier({
name
})) return;
typePath = typePath.resolve();
if (!typePath.isLiteral()) return;
const typeValue = typePath.node.value;
if (typeof typeValue !== "string") return;
return createTypeAnnotationBasedOnTypeof(typeValue);
}
function getParentConditionalPath(binding, path, name) {
let parentPath;
while (parentPath = path.parentPath) {
if (parentPath.isIfStatement() || parentPath.isConditionalExpression()) {
if (path.key === "test") {
return;
}
return parentPath;
}
if (parentPath.isFunction()) {
if (name == null || parentPath.parentPath.scope.getBinding(name) !== binding) return;
}
path = parentPath;
}
}
function getConditionalAnnotation(binding, path, name) {
const ifStatement = getParentConditionalPath(binding, path, name);
if (!ifStatement) return;
const test = ifStatement.get("test");
const paths = [test];
const types = [];
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
if (path.isLogicalExpression()) {
if (path.node.operator === "&&") {
paths.push(path.get("left"));
paths.push(path.get("right"));
}
} else if (path.isBinaryExpression()) {
const type = inferAnnotationFromBinaryExpression(name, path);
if (type) types.push(type);
}
}
if (types.length) {
return {
typeAnnotation: createUnionType(types),
ifStatement
};
}
return getConditionalAnnotation(binding, ifStatement, name);
}
const {
BOOLEAN_BINARY_OPERATORS,
BOOLEAN_UNARY_OPERATORS,
NUMBER_BINARY_OPERATORS,
NUMBER_UNARY_OPERATORS,
STRING_UNARY_OPERATORS,
anyTypeAnnotation: anyTypeAnnotation$1,
arrayTypeAnnotation,
booleanTypeAnnotation,
buildMatchMemberExpression,
genericTypeAnnotation,
identifier: identifier$2,
nullLiteralTypeAnnotation,
numberTypeAnnotation,
stringTypeAnnotation: stringTypeAnnotation$1,
tupleTypeAnnotation,
unionTypeAnnotation,
voidTypeAnnotation: voidTypeAnnotation$1,
isIdentifier: isIdentifier$3
} = _t;
function VariableDeclarator() {
if (!this.get("id").isIdentifier()) return;
return this.get("init").getTypeAnnotation();
}
function TypeCastExpression(node) {
return node.typeAnnotation;
}
TypeCastExpression.validParent = true;
function TSAsExpression(node) {
return node.typeAnnotation;
}
TSAsExpression.validParent = true;
function TSNonNullExpression() {
return this.get("expression").getTypeAnnotation();
}
function NewExpression(node) {
if (node.callee.type === "Identifier") {
return genericTypeAnnotation(node.callee);
}
}
function TemplateLiteral() {
return stringTypeAnnotation$1();
}
function UnaryExpression(node) {
const operator = node.operator;
if (operator === "void") {
return voidTypeAnnotation$1();
} else if (NUMBER_UNARY_OPERATORS.includes(operator)) {
return numberTypeAnnotation();
} else if (STRING_UNARY_OPERATORS.includes(operator)) {
return stringTypeAnnotation$1();
} else if (BOOLEAN_UNARY_OPERATORS.includes(operator)) {
return booleanTypeAnnotation();
}
}
function BinaryExpression(node) {
const operator = node.operator;
if (NUMBER_BINARY_OPERATORS.includes(operator)) {
return numberTypeAnnotation();
} else if (BOOLEAN_BINARY_OPERATORS.includes(operator)) {
return booleanTypeAnnotation();
} else if (operator === "+") {
const right = this.get("right");
const left = this.get("left");
if (left.isBaseType("number") && right.isBaseType("number")) {
return numberTypeAnnotation();
} else if (left.isBaseType("string") || right.isBaseType("string")) {
return stringTypeAnnotation$1();
}
return unionTypeAnnotation([stringTypeAnnotation$1(), numberTypeAnnotation()]);
}
}
function LogicalExpression() {
const argumentTypes = [this.get("left").getTypeAnnotation(), this.get("right").getTypeAnnotation()];
return createUnionType(argumentTypes);
}
function ConditionalExpression() {
const argumentTypes = [this.get("consequent").getTypeAnnotation(), this.get("alternate").getTypeAnnotation()];
return createUnionType(argumentTypes);
}
function SequenceExpression() {
return this.get("expressions").pop().getTypeAnnotation();
}
function ParenthesizedExpression() {
return this.get("expression").getTypeAnnotation();
}
function AssignmentExpression() {
return this.get("right").getTypeAnnotation();
}
function UpdateExpression(node) {
const operator = node.operator;
if (operator === "++" || operator === "--") {
return numberTypeAnnotation();
}
}
function StringLiteral() {
return stringTypeAnnotation$1();
}
function NumericLiteral() {
return numberTypeAnnotation();
}
function BooleanLiteral() {
return booleanTypeAnnotation();
}
function NullLiteral() {
return nullLiteralTypeAnnotation();
}
function RegExpLiteral() {
return genericTypeAnnotation(identifier$2("RegExp"));
}
function ObjectExpression() {
return genericTypeAnnotation(identifier$2("Object"));
}
function ArrayExpression() {
return genericTypeAnnotation(identifier$2("Array"));
}
function RestElement() {
return ArrayExpression();
}
RestElement.validParent = true;
function Func() {
return genericTypeAnnotation(identifier$2("Function"));
}
const isArrayFrom = buildMatchMemberExpression("Array.from");
const isObjectKeys = buildMatchMemberExpression("Object.keys");
const isObjectValues = buildMatchMemberExpression("Object.values");
const isObjectEntries = buildMatchMemberExpression("Object.entries");
function CallExpression() {
const {
callee
} = this.node;
if (isObjectKeys(callee)) {
return arrayTypeAnnotation(stringTypeAnnotation$1());
} else if (isArrayFrom(callee) || isObjectValues(callee) || isIdentifier$3(callee, {
name: "Array"
})) {
return arrayTypeAnnotation(anyTypeAnnotation$1());
} else if (isObjectEntries(callee)) {
return arrayTypeAnnotation(tupleTypeAnnotation([stringTypeAnnotation$1(), anyTypeAnnotation$1()]));
}
return resolveCall(this.get("callee"));
}
function TaggedTemplateExpression() {
return resolveCall(this.get("tag"));
}
function resolveCall(callee) {
callee = callee.resolve();
if (callee.isFunction()) {
const {
node
} = callee;
if (node.async) {
if (node.generator) {
return genericTypeAnnotation(identifier$2("AsyncIterator"));
} else {
return genericTypeAnnotation(identifier$2("Promise"));
}
} else {
if (node.generator) {
return genericTypeAnnotation(identifier$2("Iterator"));
} else if (callee.node.returnType) {
return callee.node.returnType;
} else ;
}
}
}
const inferers = /*#__PURE__*/Object.defineProperty({
__proto__: null,
ArrayExpression,
ArrowFunctionExpression: Func,
AssignmentExpression,
BinaryExpression,
BooleanLiteral,
CallExpression,
ClassDeclaration: Func,
ClassExpression: Func,
ConditionalExpression,
FunctionDeclaration: Func,
FunctionExpression: Func,
Identifier: infererReference,
LogicalExpression,
NewExpression,
NullLiteral,
NumericLiteral,
ObjectExpression,
ParenthesizedExpression,
RegExpLiteral,
RestElement,
SequenceExpression,
StringLiteral,
TSAsExpression,
TSNonNullExpression,
TaggedTemplateExpression,
TemplateLiteral,
TypeCastExpression,
UnaryExpression,
UpdateExpression,
VariableDeclarator
}, Symbol.toStringTag, { value: 'Module' });
const {
anyTypeAnnotation,
isAnyTypeAnnotation,
isArrayTypeAnnotation,
isBooleanTypeAnnotation,
isEmptyTypeAnnotation,
isFlowBaseAnnotation,
isGenericTypeAnnotation,
isIdentifier: isIdentifier$2,
isMixedTypeAnnotation,
isNumberTypeAnnotation,
isStringTypeAnnotation,
isTSArrayType,
isTSTypeAnnotation,
isTSTypeReference,
isTupleTypeAnnotation,
isTypeAnnotation,
isUnionTypeAnnotation,
isVoidTypeAnnotation,
stringTypeAnnotation,
voidTypeAnnotation
} = _t;
function getTypeAnnotation() {
let type = this.getData("typeAnnotation");
if (type != null) {
return type;
}
type = _getTypeAnnotation.call(this) || anyTypeAnnotation();
if (isTypeAnnotation(type) || isTSTypeAnnotation(type)) {
type = type.typeAnnotation;
}
this.setData("typeAnnotation", type);
return type;
}
const typeAnnotationInferringNodes = new WeakSet();
function _getTypeAnnotation() {
const node = this.node;
if (!node) {
if (this.key === "init" && this.parentPath.isVariableDeclarator()) {
const declar = this.parentPath.parentPath;
const declarParent = declar.parentPath;
if (declar.key === "left" && declarParent.isForInStatement()) {
return stringTypeAnnotation();
}
if (declar.key === "left" && declarParent.isForOfStatement()) {
return anyTypeAnnotation();
}
return voidTypeAnnotation();
} else {
return;
}
}
if (node.typeAnnotation) {
return node.typeAnnotation;
}
if (typeAnnotationInferringNodes.has(node)) {
return;
}
typeAnnotationInferringNodes.add(node);
try {
let inferer = inferers[node.type];
if (inferer) {
return inferer.call(this, node);
}
inferer = inferers[this.parentPath.type];
if (inferer?.validParent) {
return this.parentPath.getTypeAnnotation();
}
} finally {
typeAnnotationInferringNodes.delete(node);
}
}
function isBaseType(baseName, soft) {
return _isBaseType(baseName, this.getTypeAnnotation(), soft);
}
function _isBaseType(baseName, type, soft) {
if (baseName === "string") {
return isStringTypeAnnotation(type);
} else if (baseName === "number") {
return isNumberTypeAnnotation(type);
} else if (baseName === "boolean") {
return isBooleanTypeAnnotation(type);
} else if (baseName === "any") {
return isAnyTypeAnnotation(type);
} else if (baseName === "mixed") {
return isMixedTypeAnnotation(type);
} else if (baseName === "empty") {
return isEmptyTypeAnnotation(type);
} else if (baseName === "void") {
return isVoidTypeAnnotation(type);
} else {
if (soft) {
return false;
} else {
throw new Error(`Unknown base type ${baseName}`);
}
}
}
function couldBeBaseType(name) {
const type = this.getTypeAnnotation();
if (isAnyTypeAnnotation(type)) return true;
if (isUnionTypeAnnotation(type)) {
for (const type2 of type.types) {
if (isAnyTypeAnnotation(type2) || _isBaseType(name, type2, true)) {
return true;
}
}
return false;
} else {
return _isBaseType(name, type, true);
}
}
function baseTypeStrictlyMatches(rightArg) {
const left = this.getTypeAnnotation();
const right = rightArg.getTypeAnnotation();
if (!isAnyTypeAnnotation(left) && isFlowBaseAnnotation(left)) {
return right.type === left.type;
}
return false;
}
function isGenericType(genericName) {
const type = this.getTypeAnnotation();
if (genericName === "Array") {
if (isTSArrayType(type) || isArrayTypeAnnotation(type) || isTupleTypeAnnotation(type)) {
return true;
}
}
return isGenericTypeAnnotation(type) && isIdentifier$2(type.id, {
name: genericName
}) || isTSTypeReference(type) && isIdentifier$2(type.typeName, {
name: genericName
});
}
const hooks = [function (self, parent) {
const removeParent = self.key === "test" && (parent.isWhile() || parent.isSwitchCase()) || self.key === "declaration" && parent.isExportDeclaration() || self.key === "body" && parent.isLabeledStatement() || self.listKey === "declarations" && parent.isVariableDeclaration() && parent.node.declarations.length === 1 || self.key === "expression" && parent.isExpressionStatement();
if (removeParent) {
parent.remove();
return true;
}
}, function (self, parent) {
if (parent.isSequenceExpression() && parent.node.expressions.length === 2) {
parent.replaceWith(parent.node.expressions[self.key === 0 ? 1 : 0]);
return true;
}
}, function (self, parent) {
if (parent.isBinary()) {
if (self.key === "left") {
parent.replaceWith(parent.node.right);
} else {
parent.replaceWith(parent.node.left);
}
return true;
}
}, function (self, parent) {
if (parent.isIfStatement() && self.key === "consequent" || self.key === "body" && (parent.isLoop() || parent.isArrowFunctionExpression())) {
self.replaceWith({
type: "BlockStatement",
directives: [],
body: []
});
return true;
}
}];
function remove() {
_assertUnremoved.call(this);
resync.call(this);
const handledByHook = this.parentPath && hooks.some(fn => fn(this, this.parentPath));
if (!handledByHook) {
if (this.node && !this.opts?.noScope) {
const bindings = _t.getBindingIdentifiers(this.node, false, false, true);
Object.keys(bindings).forEach(name => this.scope.removeBinding(name));
}
this.shareCommentsWithSiblings();
if (Array.isArray(this.container)) {
this.container.splice(this.key, 1);
updateSiblingKeys.call(this, this.key, -1);
} else {
_replaceWith.call(this, null);
}
}
this._traverseFlags |= SHOULD_SKIP | REMOVED;
if (this.parent) {
getCachedPaths(this)?.delete(this.node);
}
this.node = null;
}
function _assertUnremoved() {
if (this.removed) {
throw this.buildCodeFrameError("NodePath has been removed so is read-only.");
}
}
const {
arrowFunctionExpression: arrowFunctionExpression$2,
assertExpression,
assignmentExpression: assignmentExpression$2,
blockStatement: blockStatement$2,
callExpression: callExpression$2,
cloneNode: cloneNode$2,
expressionStatement: expressionStatement$2,
isAssignmentExpression,
isCallExpression,
isExportNamedDeclaration,
isExpression: isExpression$2,
isIdentifier: isIdentifier$1,
isSequenceExpression,
isSuper,
thisExpression: thisExpression$1
} = _t;
function insertBefore(nodes_) {
_assertUnremoved.call(this);
const nodes = _verifyNodeList.call(this, nodes_);
const {
parentPath,
parent
} = this;
if (parentPath.isExpressionStatement() || parentPath.isLabeledStatement() || isExportNamedDeclaration(parent) || parentPath.isExportDefaultDeclaration() && this.isDeclaration()) {
return parentPath.insertBefore(nodes);
} else if (this.isNodeType("Expression") && !this.isJSXElement() || parentPath.isForStatement() && this.key === "init") {
if (this.node) nodes.push(this.node);
return this.replaceExpressionWithStatements(nodes);
} else if (Array.isArray(this.container)) {
return _containerInsertBefore.call(this, nodes);
} else if (this.isStatementOrBlock()) {
const node = this.node;
const shouldInsertCurrentNode = node && (!this.isExpressionStatement() || node.expression != null);
const [blockPath] = this.replaceWith(blockStatement$2(shouldInsertCurrentNode ? [node] : []));
return blockPath.unshiftContainer("body", nodes);
} else {
throw new Error("We don't know what to do with this node type. " + "We were previously a Statement but we can't fit in here?");
}
}
function _containerInsert(from, nodes) {
updateSiblingKeys.call(this, from, nodes.length);
const paths = [];
this.container.splice(from, 0, ...nodes);
for (let i = 0; i < nodes.length; i++) {
const to = from + i;
const path = this.getSibling(to);
paths.push(path);
if (this.context?.queue) {
pushContext.call(path, this.context);
}
}
const contexts = _getQueueContexts.call(this);
for (const path of paths) {
setScope.call(path);
path.debug("Inserted.");
for (const context of contexts) {
context.maybeQueue(path, true);
}
}
return paths;
}
function _containerInsertBefore(nodes) {
return _containerInsert.call(this, this.key, nodes);
}
function _containerInsertAfter(nodes) {
return _containerInsert.call(this, this.key + 1, nodes);
}
const last = arr => arr[arr.length - 1];
function isHiddenInSequenceExpression(path) {
return isSequenceExpression(path.parent) && (last(path.parent.expressions) !== path.node || isHiddenInSequenceExpression(path.parentPath));
}
function isAlmostConstantAssignment(node, scope) {
if (!isAssignmentExpression(node) || !isIdentifier$1(node.left)) {
return false;
}
const blockScope = scope.getBlockParent();
return blockScope.hasOwnBinding(node.left.name) && blockScope.getOwnBinding(node.left.name).constantViolations.length <= 1;
}
function insertAfter(nodes_) {
_assertUnremoved.call(this);
if (this.isSequenceExpression()) {
return last(this.get("expressions")).insertAfter(nodes_);
}
const nodes = _verifyNodeList.call(this, nodes_);
const {
parentPath,
parent
} = this;
if (parentPath.isExpressionStatement() || parentPath.isLabeledStatement() || isExportNamedDeclaration(parent) || parentPath.isExportDefaultDeclaration() && this.isDeclaration()) {
return parentPath.insertAfter(nodes.map(node => {
return isExpression$2(node) ? expressionStatement$2(node) : node;
}));
} else if (this.isNodeType("Expression") && !this.isJSXElement() && !parentPath.isJSXElement() || parentPath.isForStatement() && this.key === "init") {
const self = this;
if (self.node) {
const node = self.node;
let {
scope
} = this;
if (scope.path.isPattern()) {
assertExpression(node);
self.replaceWith(callExpression$2(arrowFunctionExpression$2([], node), []));
self.get("callee.body").insertAfter(nodes);
return [self];
}
if (isHiddenInSequenceExpression(self)) {
nodes.unshift(node);
} else if (isCallExpression(node) && isSuper(node.callee)) {
nodes.unshift(node);
nodes.push(thisExpression$1());
} else if (isAlmostConstantAssignment(node, scope)) {
nodes.unshift(node);
nodes.push(cloneNode$2(node.left));
} else if (scope.isPure(node, true)) {
nodes.push(node);
} else {
if (parentPath.isMethod({
computed: true,
key: node
})) {
scope = scope.parent;
}
const temp = scope.generateDeclaredUidIdentifier();
nodes.unshift(expressionStatement$2(assignmentExpression$2("=", cloneNode$2(temp), node)));
nodes.push(expressionStatement$2(cloneNode$2(temp)));
}
}
return this.replaceExpressionWithStatements(nodes);
} else if (Array.isArray(this.container)) {
return _containerInsertAfter.call(this, nodes);
} else if (this.isStatementOrBlock()) {
const node = this.node;
const shouldInsertCurrentNode = node && (!this.isExpressionStatement() || node.expression != null);
const [blockPath] = this.replaceWith(blockStatement$2(shouldInsertCurrentNode ? [node] : []));
return blockPath.pushContainer("body", nodes);
} else {
throw new Error("We don't know what to do with this node type. " + "We were previously a Statement but we can't fit in here?");
}
}
function updateSiblingKeys(fromIndex, incrementBy) {
if (!this.parent) return;
const paths = getCachedPaths(this);
if (!paths) return;
for (const [, path] of paths) {
if (typeof path.key === "number" && path.container === this.container && path.key >= fromIndex) {
path.key += incrementBy;
}
}
}
function _verifyNodeList(nodes) {
if (!nodes) {
return [];
}
if (!Array.isArray(nodes)) {
nodes = [nodes];
}
for (let i = 0; i < nodes.length; i++) {
const node = nodes[i];
let msg;
if (!node) {
msg = "has falsy node";
} else if (typeof node !== "object") {
msg = "contains a non-object node";
} else if (!node.type) {
msg = "without a type";
} else if (node instanceof NodePath_Final) {
msg = "has a NodePath when it expected a raw object";
}
if (msg) {
const type = Array.isArray(node) ? "array" : typeof node;
throw new Error(`Node list ${msg} with the index of ${i} and type of ${type}`);
}
}
return nodes;
}
function unshiftContainer(listKey, nodes) {
_assertUnremoved.call(this);
const verifiedNodes = _verifyNodeList.call(this, nodes);
const container = this.node[listKey];
const path = NodePath_Final.get({
parentPath: this,
parent: this.node,
container,
listKey,
key: 0
}).setContext(this.context);
return _containerInsertBefore.call(path, verifiedNodes);
}
function pushContainer(listKey, nodes) {
_assertUnremoved.call(this);
const verifiedNodes = _verifyNodeList.call(this, nodes);
const container = this.node[listKey];
const path = NodePath_Final.get({
parentPath: this,
parent: this.node,
container,
listKey,
key: container.length
}).setContext(this.context);
return path.replaceWithMultiple(verifiedNodes);
}
const {
FUNCTION_TYPES,
arrowFunctionExpression: arrowFunctionExpression$1,
assignmentExpression: assignmentExpression$1,
awaitExpression,
blockStatement: blockStatement$1,
buildUndefinedNode: buildUndefinedNode$2,
callExpression: callExpression$1,
cloneNode: cloneNode$1,
conditionalExpression: conditionalExpression$1,
expressionStatement: expressionStatement$1,
getBindingIdentifiers: getBindingIdentifiers$1,
identifier: identifier$1,
inheritLeadingComments,
inheritTrailingComments,
inheritsComments,
isBlockStatement: isBlockStatement$1,
isEmptyStatement,
isExpression: isExpression$1,
isExpressionStatement,
isIfStatement,
isProgram,
isStatement,
isVariableDeclaration,
removeComments,
returnStatement: returnStatement$1,
sequenceExpression: sequenceExpression$1,
validate: validate$1,
yieldExpression
} = _t;
function replaceWithMultiple(nodes) {
resync.call(this);
const verifiedNodes = _verifyNodeList.call(this, nodes);
inheritLeadingComments(verifiedNodes[0], this.node);
inheritTrailingComments(verifiedNodes[verifiedNodes.length - 1], this.node);
getCachedPaths(this)?.delete(this.node);
this.node = this.container[this.key] = null;
const paths = this.insertAfter(nodes);
if (this.node) {
this.requeue();
} else {
this.remove();
}
return paths;
}
function replaceWithSourceString(replacement) {
resync.call(this);
let ast;
try {
replacement = `(${replacement})`;
ast = parse(replacement);
} catch (err) {
const loc = err.loc;
if (loc) {
err.message += " - make sure this is an expression.\n" + codeFrameColumns(replacement, {
start: {
line: loc.line,
column: loc.column
}
});
err.code = "BABEL_REPLACE_SOURCE_ERROR";
}
throw err;
}
const expressionAST = ast.program.body[0].expression;
traverse.removeProperties(expressionAST);
return this.replaceWith(expressionAST);
}
function replaceWith(replacementPath) {
resync.call(this);
if (this.removed) {
throw new Error("You can't replace this node, we've already removed it");
}
let replacement = replacementPath instanceof NodePath_Final ? replacementPath.node : replacementPath;
if (!replacement) {
throw new Error("You passed `path.replaceWith()` a falsy node, use `path.remove()` instead");
}
if (this.node === replacement) {
return [this];
}
if (this.isProgram() && !isProgram(replacement)) {
throw new Error("You can only replace a Program root node with another Program node");
}
if (Array.isArray(replacement)) {
throw new Error("Don't use `path.replaceWith()` with an array of nodes, use `path.replaceWithMultiple()`");
}
if (typeof replacement === "string") {
throw new Error("Don't use `path.replaceWith()` with a source string, use `path.replaceWithSourceString()`");
}
let nodePath = "";
if (this.isNodeType("Statement") && isExpression$1(replacement)) {
if (!this.canHaveVariableDeclarationOrExpression() && !this.canSwapBetweenExpressionAndStatement(replacement) && !this.parentPath.isExportDefaultDeclaration()) {
replacement = expressionStatement$1(replacement);
nodePath = "expression";
}
}
if (this.isNodeType("Expression") && isStatement(replacement)) {
if (!this.canHaveVariableDeclarationOrExpression() && !this.canSwapBetweenExpressionAndStatement(replacement)) {
return this.replaceExpressionWithStatements([replacement]);
}
}
const oldNode = this.node;
if (oldNode) {
inheritsComments(replacement, oldNode);
removeComments(oldNode);
}
_replaceWith.call(this, replacement);
this.type = replacement.type;
setScope.call(this);
this.requeue();
return [nodePath ? this.get(nodePath) : this];
}
function _replaceWith(node) {
if (!this.container) {
throw new ReferenceError("Container is falsy");
}
if (this.inList) {
validate$1(this.parent, this.key, [node]);
} else {
validate$1(this.parent, this.key, node);
}
this.debug(`Replace with ${node?.type}`);
getCachedPaths(this)?.set(node, this).delete(this.node);
this.node = node;
this.container[this.key] = node;
}
function replaceExpressionWithStatements(nodes) {
resync.call(this);
const declars = [];
const nodesAsSingleExpression = gatherSequenceExpressions(nodes, declars);
if (nodesAsSingleExpression) {
for (const id of declars) this.scope.push({
id
});
return this.replaceWith(nodesAsSingleExpression)[0].get("expressions");
}
const functionParent = this.getFunctionParent();
const isParentAsync = functionParent?.node.async;
const isParentGenerator = functionParent?.node.generator;
const container = arrowFunctionExpression$1([], blockStatement$1(nodes));
this.replaceWith(callExpression$1(container, []));
const callee = this.get("callee");
callee.get("body").scope.hoistVariables(id => this.scope.push({
id
}));
const completionRecords = callee.getCompletionRecords();
for (const path of completionRecords) {
if (!path.isExpressionStatement()) continue;
const loop = path.findParent(path => path.isLoop());
if (loop) {
let uid = loop.getData("expressionReplacementReturnUid");
if (!uid) {
uid = callee.scope.generateDeclaredUidIdentifier("ret");
callee.get("body").pushContainer("body", returnStatement$1(cloneNode$1(uid)));
loop.setData("expressionReplacementReturnUid", uid);
} else {
uid = identifier$1(uid.name);
}
path.get("expression").replaceWith(assignmentExpression$1("=", cloneNode$1(uid), path.node.expression));
} else {
path.replaceWith(returnStatement$1(path.node.expression));
}
}
callee.arrowFunctionToExpression();
const newCallee = callee;
const needToAwaitFunction = isParentAsync && traverse.hasType(newCallee.node.body, "AwaitExpression", FUNCTION_TYPES);
const needToYieldFunction = isParentGenerator && traverse.hasType(newCallee.node.body, "YieldExpression", FUNCTION_TYPES);
if (needToAwaitFunction) {
newCallee.set("async", true);
if (!needToYieldFunction) {
this.replaceWith(awaitExpression(this.node));
}
}
if (needToYieldFunction) {
newCallee.set("generator", true);
this.replaceWith(yieldExpression(this.node, true));
}
return newCallee.get("body.body");
}
function gatherSequenceExpressions(nodes, declars) {
const exprs = [];
let ensureLastUndefined = true;
for (const node of nodes) {
if (!isEmptyStatement(node)) {
ensureLastUndefined = false;
}
if (isExpression$1(node)) {
exprs.push(node);
} else if (isExpressionStatement(node)) {
exprs.push(node.expression);
} else if (isVariableDeclaration(node)) {
if (node.kind !== "var") return;
for (const declar of node.declarations) {
const bindings = getBindingIdentifiers$1(declar);
for (const key of Object.keys(bindings)) {
declars.push(cloneNode$1(bindings[key]));
}
if (declar.init) {
exprs.push(assignmentExpression$1("=", declar.id, declar.init));
}
}
ensureLastUndefined = true;
} else if (isIfStatement(node)) {
const consequent = node.consequent ? gatherSequenceExpressions([node.consequent], declars) : buildUndefinedNode$2();
const alternate = node.alternate ? gatherSequenceExpressions([node.alternate], declars) : buildUndefinedNode$2();
if (!consequent || !alternate) return;
exprs.push(conditionalExpression$1(node.test, consequent, alternate));
} else if (isBlockStatement$1(node)) {
const body = gatherSequenceExpressions(node.body, declars);
if (!body) return;
exprs.push(body);
} else if (isEmptyStatement(node)) {
if (nodes.indexOf(node) === 0) {
ensureLastUndefined = true;
}
} else {
return;
}
}
if (ensureLastUndefined) exprs.push(buildUndefinedNode$2());
if (exprs.length === 1) {
return exprs[0];
} else {
return sequenceExpression$1(exprs);
}
}
function replaceInline(nodes) {
resync.call(this);
if (Array.isArray(nodes)) {
if (Array.isArray(this.container)) {
nodes = _verifyNodeList.call(this, nodes);
const paths = _containerInsertAfter.call(this, nodes);
this.remove();
return paths;
} else {
return this.replaceWithMultiple(nodes);
}
} else {
return this.replaceWith(nodes);
}
}
const VALID_OBJECT_CALLEES = ["Number", "String", "Math"];
const VALID_IDENTIFIER_CALLEES = ["isFinite", "isNaN", "parseFloat", "parseInt", "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent", "btoa", "atob"];
const INVALID_METHODS = ["random"];
function isValidObjectCallee(val) {
return VALID_OBJECT_CALLEES.includes(val);
}
function isValidIdentifierCallee(val) {
return VALID_IDENTIFIER_CALLEES.includes(val);
}
function isInvalidMethod(val) {
return INVALID_METHODS.includes(val);
}
function evaluateTruthy() {
const res = this.evaluate();
if (res.confident) return !!res.value;
}
function deopt(path, state) {
if (!state.confident) return;
state.deoptPath = path;
state.confident = false;
}
const Globals = new Map([["undefined", undefined], ["Infinity", Infinity], ["NaN", NaN]]);
function evaluateCached(path, state) {
const {
node
} = path;
const {
seen
} = state;
if (seen.has(node)) {
const existing = seen.get(node);
if (existing.resolved) {
return existing.value;
} else {
deopt(path, state);
return;
}
} else {
const item = {
resolved: false
};
seen.set(node, item);
const val = _evaluate(path, state);
if (state.confident) {
item.resolved = true;
item.value = val;
}
return val;
}
}
function _evaluate(path, state) {
if (!state.confident) return;
if (path.isSequenceExpression()) {
const exprs = path.get("expressions");
return evaluateCached(exprs[exprs.length - 1], state);
}
if (path.isStringLiteral() || path.isNumericLiteral() || path.isBooleanLiteral()) {
return path.node.value;
}
if (path.isNullLiteral()) {
return null;
}
if (path.isTemplateLiteral()) {
return evaluateQuasis(path, path.node.quasis, state);
}
if (path.isTaggedTemplateExpression() && path.get("tag").isMemberExpression()) {
const object = path.get("tag.object");
const {
node: {
name
}
} = object;
const property = path.get("tag.property");
if (object.isIdentifier() && name === "String" && !path.scope.getBinding(name) && property.isIdentifier() && property.node.name === "raw") {
return evaluateQuasis(path, path.node.quasi.quasis, state, true);
}
}
if (path.isConditionalExpression()) {
const testResult = evaluateCached(path.get("test"), state);
if (!state.confident) return;
if (testResult) {
return evaluateCached(path.get("consequent"), state);
} else {
return evaluateCached(path.get("alternate"), state);
}
}
if (path.isExpressionWrapper()) {
return evaluateCached(path.get("expression"), state);
}
if (path.isMemberExpression() && !path.parentPath.isCallExpression({
callee: path.node
})) {
const property = path.get("property");
const object = path.get("object");
if (object.isLiteral()) {
const value = object.node.value;
const type = typeof value;
let key = null;
if (path.node.computed) {
key = evaluateCached(property, state);
if (!state.confident) return;
} else if (property.isIdentifier()) {
key = property.node.name;
}
if ((type === "number" || type === "string") && key != null && (typeof key === "number" || typeof key === "string")) {
return value[key];
}
}
}
if (path.isReferencedIdentifier()) {
const binding = path.scope.getBinding(path.node.name);
if (binding) {
if (binding.constantViolations.length > 0 || path.node.start < binding.path.node.end) {
deopt(binding.path, state);
return;
}
const bindingPathScope = binding.path.scope;
if (binding.kind === "var" && bindingPathScope !== binding.scope) {
let hasUnsafeBlock = !bindingPathScope.path.parentPath.isBlockStatement();
for (let scope = bindingPathScope.parent; scope; scope = scope.parent) {
if (scope === path.scope) {
if (hasUnsafeBlock) {
deopt(binding.path, state);
return;
}
break;
}
if (scope.path.parentPath?.isBlockStatement()) {
hasUnsafeBlock = true;
}
}
}
if (binding.hasValue) {
return binding.value;
}
}
const name = path.node.name;
if (Globals.has(name)) {
if (!binding) {
return Globals.get(name);
}
deopt(binding.path, state);
return;
}
if (!binding) {
deopt(path, state);
return;
}
const bindingPath = binding.path;
if (!bindingPath.isVariableDeclarator()) {
deopt(bindingPath, state);
return;
}
const initPath = bindingPath.get("init");
const value = evaluateCached(initPath, state);
if (typeof value === "object" && value !== null && binding.references > 1) {
deopt(initPath, state);
return;
}
return value;
}
if (path.isUnaryExpression({
prefix: true
})) {
if (path.node.operator === "void") {
return undefined;
}
const argument = path.get("argument");
if (path.node.operator === "typeof" && (argument.isFunction() || argument.isClass())) {
return "function";
}
const arg = evaluateCached(argument, state);
if (!state.confident) return;
switch (path.node.operator) {
case "!":
return !arg;
case "+":
return +arg;
case "-":
return -arg;
case "~":
return ~arg;
case "typeof":
return typeof arg;
}
}
if (path.isArrayExpression()) {
const arr = [];
const elems = path.get("elements");
for (const elem of elems) {
const elemValue = elem.evaluate();
if (elemValue.confident) {
arr.push(elemValue.value);
} else {
deopt(elemValue.deopt, state);
return;
}
}
return arr;
}
if (path.isObjectExpression()) {
const obj = {};
const props = path.get("properties");
for (const prop of props) {
if (prop.isObjectMethod() || prop.isSpreadElement()) {
deopt(prop, state);
return;
}
const keyPath = prop.get("key");
let key;
if (prop.node.computed) {
key = keyPath.evaluate();
if (!key.confident) {
deopt(key.deopt, state);
return;
}
key = key.value;
} else if (keyPath.isIdentifier()) {
key = keyPath.node.name;
} else {
key = keyPath.node.value;
}
const valuePath = prop.get("value");
let value = valuePath.evaluate();
if (!value.confident) {
deopt(value.deopt, state);
return;
}
value = value.value;
obj[key] = value;
}
return obj;
}
if (path.isLogicalExpression()) {
const wasConfident = state.confident;
const left = evaluateCached(path.get("left"), state);
const leftConfident = state.confident;
state.confident = wasConfident;
const right = evaluateCached(path.get("right"), state);
const rightConfident = state.confident;
switch (path.node.operator) {
case "||":
state.confident = leftConfident && (!!left || rightConfident);
if (!state.confident) return;
return left || right;
case "&&":
state.confident = leftConfident && (!left || rightConfident);
if (!state.confident) return;
return left && right;
case "??":
state.confident = leftConfident && (left != null || rightConfident);
if (!state.confident) return;
return left ?? right;
}
}
if (path.isBinaryExpression()) {
const left = evaluateCached(path.get("left"), state);
if (!state.confident) return;
const right = evaluateCached(path.get("right"), state);
if (!state.confident) return;
switch (path.node.operator) {
case "-":
return left - right;
case "+":
return left + right;
case "/":
return left / right;
case "*":
return left * right;
case "%":
return left % right;
case "**":
return left ** right;
case "<":
return left < right;
case ">":
return left > right;
case "<=":
return left <= right;
case ">=":
return left >= right;
case "==":
return left == right;
case "!=":
return left != right;
case "===":
return left === right;
case "!==":
return left !== right;
case "|":
return left | right;
case "&":
return left & right;
case "^":
return left ^ right;
case "<<":
return left << right;
case ">>":
return left >> right;
case ">>>":
return left >>> right;
}
}
if (path.isCallExpression()) {
const callee = path.get("callee");
let context;
let func;
if (callee.isIdentifier() && !path.scope.getBinding(callee.node.name) && (isValidObjectCallee(callee.node.name) || isValidIdentifierCallee(callee.node.name))) {
func = global[callee.node.name];
}
if (callee.isMemberExpression()) {
const object = callee.get("object");
const property = callee.get("property");
if (object.isIdentifier() && property.isIdentifier() && isValidObjectCallee(object.node.name) && !isInvalidMethod(property.node.name) && !path.scope.getBinding(object.node.name)) {
context = global[object.node.name];
const key = property.node.name;
if (Object.hasOwn(context, key)) {
func = context[key];
}
}
if (object.isLiteral() && property.isIdentifier()) {
const type = typeof object.node.value;
if (type === "string" || type === "number") {
context = object.node.value;
func = context[property.node.name];
}
}
}
if (func) {
const args = path.get("arguments").map(arg => evaluateCached(arg, state));
if (!state.confident) return;
return func.apply(context, args);
}
}
deopt(path, state);
}
function evaluateQuasis(path, quasis, state, raw = false) {
let str = "";
let i = 0;
const exprs = path.isTemplateLiteral() ? path.get("expressions") : path.get("quasi.expressions");
for (const elem of quasis) {
if (!state.confident) break;
str += raw ? elem.value.raw : elem.value.cooked;
const expr = exprs[i++];
if (expr) str += String(evaluateCached(expr, state));
}
if (!state.confident) return;
return str;
}
function evaluate() {
const state = {
confident: true,
deoptPath: null,
seen: new Map()
};
let value = evaluateCached(this, state);
if (!state.confident) value = undefined;
return {
confident: state.confident,
deopt: state.deoptPath,
value: value
};
}
const {
arrowFunctionExpression,
assignmentExpression,
binaryExpression,
blockStatement,
callExpression,
conditionalExpression,
expressionStatement,
identifier,
jsxIdentifier,
logicalExpression,
LOGICAL_OPERATORS,
memberExpression,
metaProperty,
numericLiteral,
objectExpression,
restElement,
returnStatement,
sequenceExpression,
spreadElement,
stringLiteral,
super: _super,
thisExpression,
toExpression,
unaryExpression,
toBindingIdentifierName,
isFunction,
isAssignmentPattern,
isRestElement,
getFunctionName,
cloneNode,
variableDeclaration,
variableDeclarator,
exportNamedDeclaration,
exportSpecifier,
inherits,
buildUndefinedNode: buildUndefinedNode$1
} = _t;
function ensureBlock() {
const body = this.get("body");
const bodyNode = body.node;
if (Array.isArray(body)) {
throw new Error("Can't convert array path to a block statement");
}
if (!bodyNode) {
throw new Error("Can't convert node without a body");
}
if (body.isBlockStatement()) {
return bodyNode;
}
const statements = [];
let stringPath = "body";
let key;
let listKey;
if (body.isStatement()) {
listKey = "body";
key = 0;
statements.push(body.node);
} else {
stringPath += ".body.0";
if (this.isFunction()) {
key = "argument";
statements.push(returnStatement(body.node));
} else {
key = "expression";
statements.push(expressionStatement(body.node));
}
}
this.node.body = blockStatement(statements);
const parentPath = this.get(stringPath);
setup.call(body, parentPath, listKey ? parentPath.node[listKey] : parentPath.node, listKey, key);
return this.node;
}
function unwrapFunctionEnvironment() {
if (!this.isArrowFunctionExpression() && !this.isFunctionExpression() && !this.isFunctionDeclaration()) {
throw this.buildCodeFrameError("Can only unwrap the environment of a function.");
}
hoistFunctionEnvironment(this);
}
function setType(path, type) {
path.node.type = type;
}
function arrowFunctionToExpression({
allowInsertArrow = true,
allowInsertArrowWithRest = allowInsertArrow,
noNewArrows = true
} = {}) {
if (!this.isArrowFunctionExpression()) {
throw this.buildCodeFrameError("Cannot convert non-arrow function to a function expression.");
}
let self = this;
if (!noNewArrows) {
self = self.ensureFunctionName(false) ?? self;
}
const {
thisBinding,
fnPath: fn
} = hoistFunctionEnvironment(self, noNewArrows, allowInsertArrow, allowInsertArrowWithRest);
fn.ensureBlock();
setType(fn, "FunctionExpression");
if (!noNewArrows) {
const checkBinding = thisBinding ? null : fn.scope.generateUidIdentifier("arrowCheckId");
if (checkBinding) {
fn.parentPath.scope.push({
id: checkBinding,
init: objectExpression([])
});
}
fn.get("body").unshiftContainer("body", expressionStatement(callExpression(this.hub.addHelper("newArrowCheck"), [thisExpression(), checkBinding ? identifier(checkBinding.name) : identifier(thisBinding)])));
return fn.replaceWith(callExpression(memberExpression(fn.node, identifier("bind")), [checkBinding ? identifier(checkBinding.name) : thisExpression()]))[0].get("callee.object");
}
return fn;
}
const getSuperCallsVisitor = environmentVisitor({
CallExpression(child, {
allSuperCalls
}) {
if (!child.get("callee").isSuper()) return;
allSuperCalls.push(child);
}
});
function hoistFunctionEnvironment(fnPath, noNewArrows = true, allowInsertArrow = true, allowInsertArrowWithRest = true) {
let arrowParent;
let thisEnvFn = fnPath.findParent(p => {
if (p.isArrowFunctionExpression()) {
arrowParent ??= p;
return false;
}
return p.isFunction() || p.isProgram() || p.isClassProperty({
static: false
}) || p.isClassPrivateProperty({
static: false
});
});
const inConstructor = thisEnvFn.isClassMethod({
kind: "constructor"
});
if (thisEnvFn.isClassProperty() || thisEnvFn.isClassPrivateProperty()) {
if (arrowParent) {
thisEnvFn = arrowParent;
} else if (allowInsertArrow) {
thisEnvFn = fnPath.replaceWith(callExpression(arrowFunctionExpression([], toExpression(fnPath.node)), []))[0].get("callee");
fnPath = thisEnvFn.get("body");
} else {
throw fnPath.buildCodeFrameError("Unable to transform arrow inside class property");
}
}
const {
thisPaths,
argumentsPaths,
newTargetPaths,
superProps,
superCalls
} = getScopeInformation(fnPath);
if (inConstructor && superCalls.length > 0) {
if (!allowInsertArrow) {
throw superCalls[0].buildCodeFrameError("When using '@babel/plugin-transform-arrow-functions', " + "it's not possible to compile `super()` in an arrow function without compiling classes.\n" + "Please add '@babel/plugin-transform-classes' to your Babel configuration.");
}
if (!allowInsertArrowWithRest) {
throw superCalls[0].buildCodeFrameError("When using '@babel/plugin-transform-parameters', " + "it's not possible to compile `super()` in an arrow function with default or rest parameters without compiling classes.\n" + "Please add '@babel/plugin-transform-classes' to your Babel configuration.");
}
const allSuperCalls = [];
thisEnvFn.traverse(getSuperCallsVisitor, {
allSuperCalls
});
const superBinding = getSuperBinding(thisEnvFn);
allSuperCalls.forEach(superCall => {
const callee = identifier(superBinding);
callee.loc = superCall.node.callee.loc;
superCall.get("callee").replaceWith(callee);
});
}
if (argumentsPaths.length > 0) {
const argumentsBinding = getBinding(thisEnvFn, "arguments", () => {
const args = () => identifier("arguments");
if (thisEnvFn.scope.path.isProgram()) {
return conditionalExpression(binaryExpression("===", unaryExpression("typeof", args()), stringLiteral("undefined")), buildUndefinedNode$1(), args());
} else {
return args();
}
});
argumentsPaths.forEach(argumentsChild => {
const argsRef = identifier(argumentsBinding);
argsRef.loc = argumentsChild.node.loc;
argumentsChild.replaceWith(argsRef);
});
}
if (newTargetPaths.length > 0) {
const newTargetBinding = getBinding(thisEnvFn, "newtarget", () => metaProperty(identifier("new"), identifier("target")));
newTargetPaths.forEach(targetChild => {
const targetRef = identifier(newTargetBinding);
targetRef.loc = targetChild.node.loc;
targetChild.replaceWith(targetRef);
});
}
if (superProps.length > 0) {
if (!allowInsertArrow) {
throw superProps[0].buildCodeFrameError("When using '@babel/plugin-transform-arrow-functions', " + "it's not possible to compile `super.prop` in an arrow function without compiling classes.\n" + "Please add '@babel/plugin-transform-classes' to your Babel configuration.");
}
const flatSuperProps = superProps.reduce((acc, superProp) => acc.concat(standardizeSuperProperty(superProp)), []);
flatSuperProps.forEach(superProp => {
const key = superProp.node.computed ? "" : superProp.get("property").node.name;
const superParentPath = superProp.parentPath;
const isAssignment = superParentPath.isAssignmentExpression({
left: superProp.node
});
const isCall = superParentPath.isCallExpression({
callee: superProp.node
});
const isTaggedTemplate = superParentPath.isTaggedTemplateExpression({
tag: superProp.node
});
const superBinding = getSuperPropBinding(thisEnvFn, isAssignment, key);
const args = [];
if (superProp.node.computed) {
args.push(superProp.get("property").node);
}
if (isAssignment) {
const value = superParentPath.node.right;
args.push(value);
}
const call = callExpression(identifier(superBinding), args);
if (isCall) {
superParentPath.unshiftContainer("arguments", thisExpression());
superProp.replaceWith(memberExpression(call, identifier("call")));
thisPaths.push(superParentPath.get("arguments.0"));
} else if (isAssignment) {
superParentPath.replaceWith(call);
} else if (isTaggedTemplate) {
thisPaths.push(superProp.replaceWith(callExpression(memberExpression(call, identifier("bind"), false), [thisExpression()]))[0].get("arguments.0"));
} else {
superProp.replaceWith(call);
}
});
}
let thisBinding;
if (thisPaths.length > 0 || !noNewArrows) {
thisBinding = getThisBinding(thisEnvFn, inConstructor);
if (noNewArrows || inConstructor && hasSuperClass(thisEnvFn)) {
thisPaths.forEach(thisChild => {
const thisRef = thisChild.isJSX() ? jsxIdentifier(thisBinding) : identifier(thisBinding);
thisRef.loc = thisChild.node.loc;
thisChild.replaceWith(thisRef);
});
if (!noNewArrows) thisBinding = null;
}
}
return {
thisBinding: thisBinding,
fnPath
};
}
function isLogicalOp(op) {
return LOGICAL_OPERATORS.includes(op);
}
function standardizeSuperProperty(superProp) {
if (superProp.parentPath.isAssignmentExpression() && superProp.parentPath.node.operator !== "=") {
const assignmentPath = superProp.parentPath;
const op = assignmentPath.node.operator.slice(0, -1);
const value = assignmentPath.node.right;
const isLogicalAssignment = isLogicalOp(op);
if (superProp.node.computed) {
const tmp = superProp.scope.generateDeclaredUidIdentifier("tmp");
const {
object,
property
} = superProp.node;
assignmentPath.get("left").replaceWith(memberExpression(object, assignmentExpression("=", tmp, property), true));
assignmentPath.get("right").replaceWith(rightExpression(isLogicalAssignment ? "=" : op, memberExpression(object, identifier(tmp.name), true), value));
} else {
const object = superProp.node.object;
const property = superProp.node.property;
assignmentPath.get("left").replaceWith(memberExpression(object, property));
assignmentPath.get("right").replaceWith(rightExpression(isLogicalAssignment ? "=" : op, memberExpression(object, identifier(property.name)), value));
}
if (isLogicalAssignment) {
assignmentPath.replaceWith(logicalExpression(op, assignmentPath.node.left, assignmentPath.node.right));
} else {
assignmentPath.node.operator = "=";
}
return [assignmentPath.get("left"), assignmentPath.get("right").get("left")];
} else if (superProp.parentPath.isUpdateExpression()) {
const updateExpr = superProp.parentPath;
const tmp = superProp.scope.generateDeclaredUidIdentifier("tmp");
const computedKey = superProp.node.computed ? superProp.scope.generateDeclaredUidIdentifier("prop") : null;
const parts = [assignmentExpression("=", tmp, memberExpression(superProp.node.object, computedKey ? assignmentExpression("=", computedKey, superProp.node.property) : superProp.node.property, superProp.node.computed)), assignmentExpression("=", memberExpression(superProp.node.object, computedKey ? identifier(computedKey.name) : superProp.node.property, superProp.node.computed), binaryExpression(superProp.parentPath.node.operator[0], identifier(tmp.name), numericLiteral(1)))];
if (!superProp.parentPath.node.prefix) {
parts.push(identifier(tmp.name));
}
const sequenceExpr = updateExpr.replaceWith(sequenceExpression(parts))[0];
const left = sequenceExpr.get("expressions.0.right");
const right = sequenceExpr.get("expressions.1.left");
return [left, right];
}
return [superProp];
function rightExpression(op, left, right) {
if (op === "=") {
return assignmentExpression("=", left, right);
} else {
return binaryExpression(op, left, right);
}
}
}
function hasSuperClass(thisEnvFn) {
return thisEnvFn.isClassMethod() && !!thisEnvFn.parentPath.parentPath.node.superClass;
}
const assignSuperThisVisitor = environmentVisitor({
CallExpression(child, {
supers,
thisBinding
}) {
if (!child.get("callee").isSuper()) return;
if (supers.has(child.node)) return;
supers.add(child.node);
child.replaceWithMultiple([child.node, assignmentExpression("=", identifier(thisBinding), identifier("this"))]);
}
});
function getThisBinding(thisEnvFn, inConstructor) {
return getBinding(thisEnvFn, "this", thisBinding => {
if (!inConstructor || !hasSuperClass(thisEnvFn)) return thisExpression();
thisEnvFn.traverse(assignSuperThisVisitor, {
supers: new WeakSet(),
thisBinding
});
});
}
function getSuperBinding(thisEnvFn) {
return getBinding(thisEnvFn, "supercall", () => {
const argsBinding = thisEnvFn.scope.generateUidIdentifier("args");
return arrowFunctionExpression([restElement(argsBinding)], callExpression(_super(), [spreadElement(identifier(argsBinding.name))]));
});
}
function getSuperPropBinding(thisEnvFn, isAssignment, propName) {
const op = isAssignment ? "set" : "get";
return getBinding(thisEnvFn, `superprop_${op}:${propName || ""}`, () => {
const argsList = [];
let fnBody;
if (propName) {
fnBody = memberExpression(_super(), identifier(propName));
} else {
const method = thisEnvFn.scope.generateUidIdentifier("prop");
argsList.unshift(method);
fnBody = memberExpression(_super(), identifier(method.name), true);
}
if (isAssignment) {
const valueIdent = thisEnvFn.scope.generateUidIdentifier("value");
argsList.push(valueIdent);
fnBody = assignmentExpression("=", fnBody, identifier(valueIdent.name));
}
return arrowFunctionExpression(argsList, fnBody);
});
}
function getBinding(thisEnvFn, key, init) {
const cacheKey = "binding:" + key;
let data = thisEnvFn.getData(cacheKey);
if (!data) {
const id = thisEnvFn.scope.generateUidIdentifier(key);
data = id.name;
thisEnvFn.setData(cacheKey, data);
thisEnvFn.scope.push({
id: id,
init: init(data)
});
}
return data;
}
const getScopeInformationVisitor = environmentVisitor({
ThisExpression(child, {
thisPaths
}) {
thisPaths.push(child);
},
JSXIdentifier(child, {
thisPaths
}) {
if (child.node.name !== "this") return;
if (!child.parentPath.isJSXMemberExpression({
object: child.node
}) && !child.parentPath.isJSXOpeningElement({
name: child.node
})) {
return;
}
thisPaths.push(child);
},
CallExpression(child, {
superCalls
}) {
if (child.get("callee").isSuper()) superCalls.push(child);
},
MemberExpression(child, {
superProps
}) {
if (child.get("object").isSuper()) superProps.push(child);
},
Identifier(child, {
argumentsPaths
}) {
if (!child.isReferencedIdentifier({
name: "arguments"
})) return;
let curr = child.scope;
do {
if (curr.hasOwnBinding("arguments")) {
curr.rename("arguments");
return;
}
if (curr.path.isFunction() && !curr.path.isArrowFunctionExpression()) {
break;
}
} while (curr = curr.parent);
argumentsPaths.push(child);
},
MetaProperty(child, {
newTargetPaths
}) {
if (!child.get("meta").isIdentifier({
name: "new"
})) return;
if (!child.get("property").isIdentifier({
name: "target"
})) return;
newTargetPaths.push(child);
}
});
function getScopeInformation(fnPath) {
const thisPaths = [];
const argumentsPaths = [];
const newTargetPaths = [];
const superProps = [];
const superCalls = [];
fnPath.traverse(getScopeInformationVisitor, {
thisPaths,
argumentsPaths,
newTargetPaths,
superProps,
superCalls
});
return {
thisPaths,
argumentsPaths,
newTargetPaths,
superProps,
superCalls
};
}
function splitExportDeclaration() {
if (!this.isExportDeclaration() || this.isExportAllDeclaration()) {
throw new Error("Only default and named export declarations can be split.");
}
if (this.isExportNamedDeclaration() && this.get("specifiers").length > 0) {
throw new Error("It doesn't make sense to split exported specifiers.");
}
const declaration = this.get("declaration");
if (this.isExportDefaultDeclaration()) {
const standaloneDeclaration = declaration.isFunctionDeclaration() || declaration.isClassDeclaration();
const exportExpr = declaration.isFunctionExpression() || declaration.isClassExpression();
const scope = declaration.isScope() ? declaration.scope.parent : declaration.scope;
let id = declaration.node.id;
let needBindingRegistration = false;
if (!id) {
needBindingRegistration = true;
id = scope.generateUidIdentifier("default");
if (standaloneDeclaration || exportExpr) {
declaration.node.id = cloneNode(id);
}
} else if (exportExpr && scope.hasBinding(id.name)) {
needBindingRegistration = true;
id = scope.generateUidIdentifier(id.name);
}
const updatedDeclaration = standaloneDeclaration ? declaration.node : variableDeclaration("var", [variableDeclarator(cloneNode(id), declaration.node)]);
const updatedExportDeclaration = exportNamedDeclaration(null, [exportSpecifier(cloneNode(id), identifier("default"))]);
this.insertAfter(updatedExportDeclaration);
this.replaceWith(updatedDeclaration);
if (needBindingRegistration) {
scope.registerDeclaration(this);
}
return this;
} else if (this.get("specifiers").length > 0) {
throw new Error("It doesn't make sense to split exported specifiers.");
}
const bindingIdentifiers = declaration.getOuterBindingIdentifiers();
const specifiers = Object.keys(bindingIdentifiers).map(name => {
return exportSpecifier(identifier(name), identifier(name));
});
const aliasDeclar = exportNamedDeclaration(null, specifiers);
this.insertAfter(aliasDeclar);
this.replaceWith(declaration.node);
return this;
}
const getRefersOuterBindingVisitor = () => explode$1({
"ReferencedIdentifier|BindingIdentifier"(path, state) {
if (path.node.name !== state.name) return;
state.needsRename = true;
path.stop();
},
Scope(path, state) {
if (path.scope.hasOwnBinding(state.name)) {
path.skip();
}
}
});
function ensureFunctionName(supportUnicodeId) {
if (this.node.id) return this;
const res = getFunctionName(this.node, this.parent);
if (res == null) return this;
let {
name
} = res;
if (!supportUnicodeId && /[\uD800-\uDFFF]/.test(name)) {
return null;
}
if (name.startsWith("get ") || name.startsWith("set ")) {
return null;
}
name = toBindingIdentifierName(name.replace(/[/ ]/g, "_"));
const id = identifier(name);
inherits(id, res.originalNode);
const state = {
needsRename: false,
name
};
const {
scope
} = this;
const binding = scope.getOwnBinding(name);
if (binding) {
if (binding.kind === "param") {
state.needsRename = true;
}
} else if (scope.parent.hasBinding(name) || scope.hasGlobal(name)) {
this.traverse(getRefersOuterBindingVisitor(), state);
}
if (!state.needsRename) {
this.node.id = id;
scope.getProgramParent().referencesSet.add(id.name);
return this;
}
if (scope.hasBinding(id.name) && !scope.hasGlobal(id.name)) {
scope.rename(id.name);
this.node.id = id;
scope.getProgramParent().referencesSet.add(id.name);
return this;
}
if (!isFunction(this.node)) return null;
const key = scope.generateUidIdentifier(id.name);
const params = [];
for (let i = 0, len = getFunctionArity(this.node); i < len; i++) {
params.push(scope.generateUidIdentifier("x"));
}
const call = template.expression.ast`
(function (${key}) {
function ${id}(${params}) {
return ${cloneNode(key)}.apply(this, arguments);
}
${cloneNode(id)}.toString = function () {
return ${cloneNode(key)}.toString();
}
return ${cloneNode(id)};
})(${toExpression(this.node)})
`;
return this.replaceWith(call)[0].get("arguments.0");
}
function getFunctionArity(node) {
const count = node.params.findIndex(param => isAssignmentPattern(param) || isRestElement(param));
return count === -1 ? node.params.length : count;
}
const {
STATEMENT_OR_BLOCK_KEYS,
VISITOR_KEYS: VISITOR_KEYS$1,
isBlockStatement,
isExpression,
isIdentifier,
isLiteral,
isStringLiteral,
isType,
matchesPattern: _matchesPattern,
toComputedKey
} = _t;
function matchesPattern(pattern, allowPartial) {
return _matchesPattern(this.node, pattern, allowPartial);
}
function isStatic() {
return this.scope.isStatic(this.node);
}
function isNodeType(type) {
return isType(this.type, type);
}
function canHaveVariableDeclarationOrExpression() {
return (this.key === "init" || this.key === "left") && this.parentPath.isFor();
}
function canSwapBetweenExpressionAndStatement(replacement) {
if (this.key !== "body" || !this.parentPath.isArrowFunctionExpression()) {
return false;
}
if (this.isExpression()) {
return isBlockStatement(replacement);
} else if (this.isBlockStatement()) {
return isExpression(replacement);
}
return false;
}
function isCompletionRecord(allowInsideFunction) {
let path = this;
let first = true;
do {
const {
type,
container
} = path;
if (!first && (path.isFunction() || type === "StaticBlock")) {
return !!allowInsideFunction;
}
first = false;
if (Array.isArray(container) && path.key !== container.length - 1) {
return false;
}
} while ((path = path.parentPath) && !path.isProgram() && !path.isDoExpression());
return true;
}
function isStatementOrBlock() {
if (this.parentPath.isLabeledStatement() || isBlockStatement(this.container)) {
return false;
} else {
return STATEMENT_OR_BLOCK_KEYS.includes(this.key);
}
}
function referencesImport(moduleSource, importName) {
if (!this.isReferencedIdentifier()) {
if (this.isJSXMemberExpression() && this.node.property.name === importName || (this.isMemberExpression() || this.isOptionalMemberExpression()) && (this.node.computed ? isStringLiteral(this.node.property, {
value: importName
}) : this.node.property.name === importName)) {
const object = this.get("object");
return object.isReferencedIdentifier() && object.referencesImport(moduleSource, "*");
}
return false;
}
const binding = this.scope.getBinding(this.node.name);
if (binding?.kind !== "module") return false;
const path = binding.path;
const parent = path.parentPath;
if (!parent.isImportDeclaration()) return false;
if (parent.node.source.value === moduleSource) {
if (!importName) return true;
} else {
return false;
}
if (path.isImportDefaultSpecifier() && importName === "default") {
return true;
}
if (path.isImportNamespaceSpecifier() && importName === "*") {
return true;
}
if (path.isImportSpecifier() && isIdentifier(path.node.imported, {
name: importName
})) {
return true;
}
return false;
}
function getSource() {
const node = this.node;
if (node.end) {
const code = this.hub.getCode();
if (code) return code.slice(node.start, node.end);
}
return "";
}
function willIMaybeExecuteBefore(target) {
return this._guessExecutionStatusRelativeTo(target) !== "after";
}
function getOuterFunction(path) {
return path.isProgram() ? path : (path.parentPath.scope.getFunctionParent() || path.parentPath.scope.getProgramParent()).path;
}
function isExecutionUncertain(type, key) {
switch (type) {
case "LogicalExpression":
return key === "right";
case "ConditionalExpression":
case "IfStatement":
return key === "consequent" || key === "alternate";
case "WhileStatement":
case "DoWhileStatement":
case "ForInStatement":
case "ForOfStatement":
return key === "body";
case "ForStatement":
return key === "body" || key === "update";
case "SwitchStatement":
return key === "cases";
case "TryStatement":
return key === "handler";
case "AssignmentPattern":
return key === "right";
case "OptionalMemberExpression":
return key === "property";
case "OptionalCallExpression":
return key === "arguments";
default:
return false;
}
}
function isExecutionUncertainInList(paths, maxIndex) {
for (let i = 0; i < maxIndex; i++) {
const path = paths[i];
if (isExecutionUncertain(path.parent.type, path.parentKey)) {
return true;
}
}
return false;
}
const SYMBOL_CHECKING = Symbol();
function _guessExecutionStatusRelativeTo(target) {
return _guessExecutionStatusRelativeToCached(this, target, new Map());
}
function _guessExecutionStatusRelativeToCached(base, target, cache) {
const funcParent = {
this: getOuterFunction(base),
target: getOuterFunction(target)
};
if (funcParent.target.node !== funcParent.this.node) {
return _guessExecutionStatusRelativeToDifferentFunctionsCached(base, funcParent.target, cache);
}
const paths = {
target: target.getAncestry(),
this: base.getAncestry()
};
if (paths.target.includes(base)) return "after";
if (paths.this.includes(target)) return "before";
let commonPath;
const commonIndex = {
target: 0,
this: 0
};
while (!commonPath && commonIndex.this < paths.this.length) {
const path = paths.this[commonIndex.this];
commonIndex.target = paths.target.indexOf(path);
if (commonIndex.target >= 0) {
commonPath = path;
} else {
commonIndex.this++;
}
}
if (!commonPath) {
throw new Error("Internal Babel error - The two compared nodes" + " don't appear to belong to the same program.");
}
if (isExecutionUncertainInList(paths.this, commonIndex.this - 1) || isExecutionUncertainInList(paths.target, commonIndex.target - 1)) {
return "unknown";
}
const divergence = {
this: paths.this[commonIndex.this - 1],
target: paths.target[commonIndex.target - 1]
};
if (divergence.target.listKey && divergence.this.listKey && divergence.target.container === divergence.this.container) {
return divergence.target.key > divergence.this.key ? "before" : "after";
}
const keys = VISITOR_KEYS$1[commonPath.type];
const keyPosition = {
this: keys.indexOf(divergence.this.parentKey),
target: keys.indexOf(divergence.target.parentKey)
};
return keyPosition.target > keyPosition.this ? "before" : "after";
}
function _guessExecutionStatusRelativeToDifferentFunctionsInternal(base, target, cache) {
if (!target.isFunctionDeclaration()) {
if (_guessExecutionStatusRelativeToCached(base, target, cache) === "before") {
return "before";
}
return "unknown";
} else if (target.parentPath.isExportDeclaration()) {
return "unknown";
}
const binding = target.scope.getBinding(target.node.id.name);
if (!binding.references) return "before";
const referencePaths = binding.referencePaths;
let allStatus;
for (const path of referencePaths) {
const childOfFunction = !!path.find(path => path.node === target.node);
if (childOfFunction) continue;
if (path.key !== "callee" || !path.parentPath.isCallExpression()) {
return "unknown";
}
const status = _guessExecutionStatusRelativeToCached(base, path, cache);
if (allStatus && allStatus !== status) {
return "unknown";
} else {
allStatus = status;
}
}
return allStatus;
}
function _guessExecutionStatusRelativeToDifferentFunctionsCached(base, target, cache) {
let nodeMap = cache.get(base.node);
let cached;
if (!nodeMap) {
cache.set(base.node, nodeMap = new Map());
} else if (cached = nodeMap.get(target.node)) {
if (cached === SYMBOL_CHECKING) {
return "unknown";
}
return cached;
}
nodeMap.set(target.node, SYMBOL_CHECKING);
const result = _guessExecutionStatusRelativeToDifferentFunctionsInternal(base, target, cache);
nodeMap.set(target.node, result);
return result;
}
function resolve(dangerous, resolved) {
if (resolved?.includes(this)) return this;
resolved = resolved || [];
resolved.push(this);
if (this.isVariableDeclarator()) {
if (this.get("id").isIdentifier()) {
return this.get("init").resolve(dangerous, resolved);
}
} else if (this.isReferencedIdentifier()) {
const binding = this.scope.getBinding(this.node.name);
if (!binding) return this;
if (!binding.constant) return this;
if (binding.kind === "module") return this;
if (binding.path !== this) {
const ret = binding.path.resolve(dangerous, resolved);
if (this.find(parent => parent.node === ret.node)) return this;
return ret;
}
} else if (this.isTypeCastExpression()) {
return this.get("expression").resolve(dangerous, resolved);
} else if (dangerous && this.isMemberExpression()) {
const targetKey = toComputedKey(this.node);
if (!isLiteral(targetKey)) return this;
const targetName = targetKey.value;
const target = this.get("object").resolve(dangerous, resolved);
if (target.isObjectExpression()) {
const props = target.get("properties");
for (const prop of props) {
if (!prop.isProperty()) continue;
const key = prop.get("key");
let match = prop.isnt("computed") && key.isIdentifier({
name: targetName
});
match = match || key.isLiteral({
value: targetName
});
if (match) return prop.get("value").resolve(dangerous, resolved);
}
} else if (target.isArrayExpression() && !isNaN(+targetName)) {
const elems = target.get("elements");
const elem = elems[targetName];
if (elem) return elem.resolve(dangerous, resolved);
}
}
return this;
}
function isConstantExpression() {
if (this.isIdentifier()) {
const binding = this.scope.getBinding(this.node.name);
if (!binding) return false;
return binding.constant;
}
if (this.isLiteral()) {
if (this.isRegExpLiteral()) {
return false;
}
if (this.isTemplateLiteral()) {
return this.get("expressions").every(expression => expression.isConstantExpression());
}
return true;
}
if (this.isUnaryExpression()) {
if (this.node.operator !== "void") {
return false;
}
return this.get("argument").isConstantExpression();
}
if (this.isBinaryExpression()) {
const {
operator
} = this.node;
return operator !== "in" && operator !== "instanceof" && this.get("left").isConstantExpression() && this.get("right").isConstantExpression();
}
if (this.isMemberExpression()) {
return !this.node.computed && this.get("object").isIdentifier({
name: "Symbol"
}) && !this.scope.hasBinding("Symbol", {
noGlobals: true
});
}
if (this.isCallExpression()) {
return this.node.arguments.length === 1 && this.get("callee").matchesPattern("Symbol.for") && !this.scope.hasBinding("Symbol", {
noGlobals: true
}) && this.get("arguments")[0].isStringLiteral();
}
return false;
}
function isInStrictMode() {
const start = this.isProgram() ? this : this.parentPath;
const strictParent = start.find(path => {
if (path.isProgram({
sourceType: "module"
})) return true;
if (path.isClass()) return true;
if (path.isArrowFunctionExpression() && !path.get("body").isBlockStatement()) {
return false;
}
let body;
if (path.isFunction()) {
body = path.node.body;
} else if (path.isProgram()) {
body = path.node;
} else {
return false;
}
for (const directive of body.directives) {
if (directive.value.value === "use strict") {
return true;
}
}
return false;
});
return !!strictParent;
}
const {
getAssignmentIdentifiers: _getAssignmentIdentifiers,
getBindingIdentifiers: _getBindingIdentifiers,
getOuterBindingIdentifiers: _getOuterBindingIdentifiers,
buildUndefinedNode
} = _t;
const NORMAL_COMPLETION = 0;
const BREAK_COMPLETION = 1;
function NormalCompletion(path) {
return {
type: NORMAL_COMPLETION,
path
};
}
function BreakCompletion(path) {
return {
type: BREAK_COMPLETION,
path
};
}
function getOpposite() {
if (this.key === "left") {
return this.getSibling("right");
} else if (this.key === "right") {
return this.getSibling("left");
}
return null;
}
function addCompletionRecords(path, records, context) {
if (path) {
records.push(..._getCompletionRecords(path, context));
}
return records;
}
function completionRecordForSwitch(cases, records, context) {
let lastNormalCompletions = [];
for (let i = 0; i < cases.length; i++) {
const casePath = cases[i];
const caseCompletions = _getCompletionRecords(casePath, context);
const normalCompletions = [];
const breakCompletions = [];
for (const c of caseCompletions) {
if (c.type === NORMAL_COMPLETION) {
normalCompletions.push(c);
}
if (c.type === BREAK_COMPLETION) {
breakCompletions.push(c);
}
}
if (normalCompletions.length) {
lastNormalCompletions = normalCompletions;
}
records.push(...breakCompletions);
}
records.push(...lastNormalCompletions);
return records;
}
function normalCompletionToBreak(completions) {
completions.forEach(c => {
c.type = BREAK_COMPLETION;
});
}
function replaceBreakStatementInBreakCompletion(completions, reachable) {
completions.forEach(c => {
if (c.path.isBreakStatement({
label: null
})) {
if (reachable) {
c.path.replaceWith(buildUndefinedNode());
} else {
c.path.remove();
}
}
});
}
function getStatementListCompletion(paths, context) {
const completions = [];
if (context.canHaveBreak) {
let lastNormalCompletions = [];
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
const newContext = {
...context,
inCaseClause: false
};
if (path.isBlockStatement() && (context.inCaseClause || context.shouldPopulateBreak)) {
newContext.shouldPopulateBreak = true;
} else {
newContext.shouldPopulateBreak = false;
}
const statementCompletions = _getCompletionRecords(path, newContext);
if (statementCompletions.length > 0 && statementCompletions.every(c => c.type === BREAK_COMPLETION)) {
if (lastNormalCompletions.length > 0 && statementCompletions.every(c => c.path.isBreakStatement({
label: null
}))) {
normalCompletionToBreak(lastNormalCompletions);
completions.push(...lastNormalCompletions);
if (lastNormalCompletions.some(c => c.path.isDeclaration())) {
completions.push(...statementCompletions);
if (!context.shouldPreserveBreak) {
replaceBreakStatementInBreakCompletion(statementCompletions, true);
}
}
if (!context.shouldPreserveBreak) {
replaceBreakStatementInBreakCompletion(statementCompletions, false);
}
} else {
completions.push(...statementCompletions);
if (!context.shouldPopulateBreak && !context.shouldPreserveBreak) {
replaceBreakStatementInBreakCompletion(statementCompletions, true);
}
}
break;
}
if (i === paths.length - 1) {
completions.push(...statementCompletions);
} else {
lastNormalCompletions = [];
for (let i = 0; i < statementCompletions.length; i++) {
const c = statementCompletions[i];
if (c.type === BREAK_COMPLETION) {
completions.push(c);
}
if (c.type === NORMAL_COMPLETION) {
lastNormalCompletions.push(c);
}
}
}
}
} else if (paths.length) {
for (let i = paths.length - 1; i >= 0; i--) {
const pathCompletions = _getCompletionRecords(paths[i], context);
if (pathCompletions.length > 1 || pathCompletions.length === 1 && !pathCompletions[0].path.isVariableDeclaration() && !pathCompletions[0].path.isEmptyStatement()) {
completions.push(...pathCompletions);
break;
}
}
}
return completions;
}
function _getCompletionRecords(path, context) {
let records = [];
if (path.isIfStatement()) {
records = addCompletionRecords(path.get("consequent"), records, context);
records = addCompletionRecords(path.get("alternate"), records, context);
} else if (path.isDoExpression() || path.isFor() || path.isWhile() || path.isLabeledStatement()) {
return addCompletionRecords(path.get("body"), records, context);
} else if (path.isProgram() || path.isBlockStatement()) {
return getStatementListCompletion(path.get("body"), context);
} else if (path.isFunction()) {
return _getCompletionRecords(path.get("body"), context);
} else if (path.isTryStatement()) {
records = addCompletionRecords(path.get("block"), records, context);
records = addCompletionRecords(path.get("handler"), records, context);
} else if (path.isCatchClause()) {
return addCompletionRecords(path.get("body"), records, context);
} else if (path.isSwitchStatement()) {
return completionRecordForSwitch(path.get("cases"), records, context);
} else if (path.isSwitchCase()) {
return getStatementListCompletion(path.get("consequent"), {
canHaveBreak: true,
shouldPopulateBreak: false,
inCaseClause: true,
shouldPreserveBreak: context.shouldPreserveBreak
});
} else if (path.isBreakStatement()) {
records.push(BreakCompletion(path));
} else {
records.push(NormalCompletion(path));
}
return records;
}
function getCompletionRecords(shouldPreserveBreak = false) {
const records = _getCompletionRecords(this, {
canHaveBreak: false,
shouldPopulateBreak: false,
inCaseClause: false,
shouldPreserveBreak
});
return records.map(r => r.path);
}
function getSibling(key) {
return NodePath_Final.get({
parentPath: this.parentPath,
parent: this.parent,
container: this.container,
listKey: this.listKey,
key: key
}).setContext(this.context);
}
function getPrevSibling() {
return this.getSibling(this.key - 1);
}
function getNextSibling() {
return this.getSibling(this.key + 1);
}
function getAllNextSiblings() {
const _key = this.key;
if (!Number.isInteger(_key)) {
return [];
}
const siblings = [],
containerLength = this.container.length;
for (let key = _key + 1; key < containerLength; key++) {
siblings.push(this.getSibling(key));
}
return siblings;
}
function getAllPrevSiblings() {
const _key = this.key;
if (!Number.isInteger(_key)) {
return [];
}
const siblings = [];
for (let key = _key - 1; key >= 0; key--) {
siblings.push(this.getSibling(key));
}
return siblings;
}
function get(key, context = true) {
if (context === true) context = this.context;
const parts = key.split(".");
if (parts.length === 1) {
return _getKey.call(this, key, context);
} else {
return _getPattern.call(this, parts, context);
}
}
function _getKey(key, context) {
const node = this.node;
const container = node[key];
if (Array.isArray(container)) {
return container.map((_, i) => {
return NodePath_Final.get({
listKey: key,
parentPath: this,
parent: node,
container: container,
key: i
}).setContext(context);
});
} else {
return NodePath_Final.get({
parentPath: this,
parent: node,
container: node,
key: key
}).setContext(context);
}
}
function _getPattern(parts, context) {
let path = this;
for (const part of parts) {
if (part === ".") {
path = path.parentPath;
} else {
if (Array.isArray(path)) {
path = path[part];
} else {
path = path.get(part, context);
}
}
}
return path;
}
function getAssignmentIdentifiers() {
return _getAssignmentIdentifiers(this.node);
}
function getBindingIdentifiers(duplicates) {
return _getBindingIdentifiers(this.node, duplicates);
}
function getOuterBindingIdentifiers(duplicates) {
return _getOuterBindingIdentifiers(this.node, duplicates);
}
function getBindingIdentifierPaths(duplicates = false, outerOnly = false) {
const path = this;
const search = [path];
const ids = Object.create(null);
while (search.length) {
const id = search.shift();
if (!id) continue;
if (!id.node) continue;
const keys = _getBindingIdentifiers.keys[id.node.type];
if (id.isIdentifier()) {
if (duplicates) {
const _ids = ids[id.node.name] = ids[id.node.name] || [];
_ids.push(id);
} else {
ids[id.node.name] = id;
}
continue;
}
if (id.isExportDeclaration()) {
const declaration = id.get("declaration");
if (declaration.isDeclaration()) {
search.push(declaration);
}
continue;
}
if (outerOnly) {
if (id.isFunctionDeclaration()) {
search.push(id.get("id"));
continue;
}
if (id.isFunctionExpression()) {
continue;
}
}
if (keys) {
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const child = id.get(key);
if (Array.isArray(child)) {
search.push(...child);
} else if (child.node) {
search.push(child);
}
}
}
}
return ids;
}
function getOuterBindingIdentifierPaths(duplicates = false) {
return this.getBindingIdentifierPaths(duplicates, true);
}
const {
addComment: _addComment,
addComments: _addComments
} = _t;
function shareCommentsWithSiblings() {
if (typeof this.key === "string") return;
const node = this.node;
if (!node) return;
const trailing = node.trailingComments;
const leading = node.leadingComments;
if (!trailing && !leading) return;
const prev = this.getSibling(this.key - 1);
const next = this.getSibling(this.key + 1);
const hasPrev = !!prev.node;
const hasNext = !!next.node;
if (hasPrev) {
if (leading) {
prev.addComments("trailing", removeIfExisting(leading, prev.node.trailingComments));
}
if (trailing && !hasNext) prev.addComments("trailing", trailing);
}
if (hasNext) {
if (trailing) {
next.addComments("leading", removeIfExisting(trailing, next.node.leadingComments));
}
if (leading && !hasPrev) next.addComments("leading", leading);
}
}
function removeIfExisting(list, toRemove) {
if (!toRemove?.length) return list;
const set = new Set(toRemove);
return list.filter(el => {
return !set.has(el);
});
}
function addComment(type, content, line) {
_addComment(this.node, type, content, line);
}
function addComments(type, comments) {
_addComments(this.node, type, comments);
}
const {
validate
} = _t;
const debug = createDebug("babel");
const REMOVED = 1 << 0;
const SHOULD_STOP = 1 << 1;
const SHOULD_SKIP = 1 << 2;
const NodePath_Final = class NodePath {
constructor(hub, parent) {
this.parent = parent;
this.hub = hub;
this.data = null;
this.context = null;
this.scope = null;
}
contexts = [];
state = null;
_traverseFlags = 0;
get removed() {
return (this._traverseFlags & 1) > 0;
}
set removed(v) {
if (v) this._traverseFlags |= 1;else this._traverseFlags &= -2;
}
get shouldStop() {
return (this._traverseFlags & 2) > 0;
}
set shouldStop(v) {
if (v) this._traverseFlags |= 2;else this._traverseFlags &= -3;
}
get shouldSkip() {
return (this._traverseFlags & 4) > 0;
}
set shouldSkip(v) {
if (v) this._traverseFlags |= 4;else this._traverseFlags &= -5;
}
skipKeys = null;
parentPath = null;
container = null;
listKey = null;
key = null;
node = null;
type = null;
_store = null;
static get({
hub,
parentPath,
parent,
container,
listKey,
key
}) {
if (!hub && parentPath) {
hub = parentPath.hub;
}
if (!parent) {
throw new Error("To get a node path the parent needs to exist");
}
const targetNode = container[key];
const paths = getOrCreateCachedPaths(parent, parentPath);
let path = paths.get(targetNode);
if (!path) {
path = new NodePath(hub, parent);
if (targetNode) paths.set(targetNode, path);
}
setup.call(path, parentPath, container, listKey, key);
return path;
}
getScope(scope) {
return this.isScope() ? new Scope(this) : scope;
}
setData(key, val) {
if (this.data == null) {
this.data = Object.create(null);
}
return this.data[key] = val;
}
getData(key, def) {
if (this.data == null) {
this.data = Object.create(null);
}
let val = this.data[key];
if (val === undefined && def !== undefined) val = this.data[key] = def;
return val;
}
hasNode() {
return this.node != null;
}
buildCodeFrameError(msg, Error = SyntaxError) {
return this.hub.buildError(this.node, msg, Error);
}
traverse(visitor, state) {
traverse(this.node, visitor, this.scope, state, this);
}
set(key, node) {
validate(this.node, key, node);
this.node[key] = node;
}
getPathLocation() {
const parts = [];
let path = this;
do {
let key = path.key;
if (path.inList) key = `${path.listKey}[${key}]`;
parts.unshift(key);
} while (path = path.parentPath);
return parts.join(".");
}
debug(message) {
if (!debug.enabled) return;
debug(`${this.getPathLocation()} ${this.type}: ${message}`);
}
toString() {
return generator(this.node).code;
}
get inList() {
return !!this.listKey;
}
set inList(inList) {
if (!inList) {
this.listKey = null;
}
}
get parentKey() {
return this.listKey || this.key;
}
};
const methods = {
findParent: findParent,
find: find,
getFunctionParent: getFunctionParent,
getStatementParent: getStatementParent,
getEarliestCommonAncestorFrom: getEarliestCommonAncestorFrom,
getDeepestCommonAncestorFrom: getDeepestCommonAncestorFrom,
getAncestry: getAncestry,
isAncestor: isAncestor,
isDescendant: isDescendant,
inType: inType,
getTypeAnnotation: getTypeAnnotation,
isBaseType: isBaseType,
couldBeBaseType: couldBeBaseType,
baseTypeStrictlyMatches: baseTypeStrictlyMatches,
isGenericType: isGenericType,
replaceWithMultiple: replaceWithMultiple,
replaceWithSourceString: replaceWithSourceString,
replaceWith: replaceWith,
replaceExpressionWithStatements: replaceExpressionWithStatements,
replaceInline: replaceInline,
evaluateTruthy: evaluateTruthy,
evaluate: evaluate,
ensureBlock: ensureBlock,
unwrapFunctionEnvironment: unwrapFunctionEnvironment,
arrowFunctionToExpression: arrowFunctionToExpression,
splitExportDeclaration: splitExportDeclaration,
ensureFunctionName: ensureFunctionName,
matchesPattern: matchesPattern,
isStatic: isStatic,
isNodeType: isNodeType,
canHaveVariableDeclarationOrExpression: canHaveVariableDeclarationOrExpression,
canSwapBetweenExpressionAndStatement: canSwapBetweenExpressionAndStatement,
isCompletionRecord: isCompletionRecord,
isStatementOrBlock: isStatementOrBlock,
referencesImport: referencesImport,
getSource: getSource,
willIMaybeExecuteBefore: willIMaybeExecuteBefore,
_guessExecutionStatusRelativeTo: _guessExecutionStatusRelativeTo,
resolve: resolve,
isConstantExpression: isConstantExpression,
isInStrictMode: isInStrictMode,
isDenylisted: isDenylisted,
skip: skip,
skipKey: skipKey,
stop: stop,
setContext: setContext,
requeue: requeue,
requeueComputedKeyAndDecorators: requeueComputedKeyAndDecorators,
remove: remove,
insertBefore: insertBefore,
insertAfter: insertAfter,
unshiftContainer: unshiftContainer,
pushContainer: pushContainer,
getOpposite: getOpposite,
getCompletionRecords: getCompletionRecords,
getSibling: getSibling,
getPrevSibling: getPrevSibling,
getNextSibling: getNextSibling,
getAllNextSiblings: getAllNextSiblings,
getAllPrevSiblings: getAllPrevSiblings,
get: get,
getAssignmentIdentifiers: getAssignmentIdentifiers,
getBindingIdentifiers: getBindingIdentifiers,
getOuterBindingIdentifiers: getOuterBindingIdentifiers,
getBindingIdentifierPaths: getBindingIdentifierPaths,
getOuterBindingIdentifierPaths: getOuterBindingIdentifierPaths,
shareCommentsWithSiblings: shareCommentsWithSiblings,
addComment: addComment,
addComments: addComments
};
Object.assign(NodePath_Final.prototype, methods);
for (const type of _t.TYPES) {
const typeKey = `is${type}`;
const fn = _t[typeKey];
NodePath_Final.prototype[typeKey] = function (opts) {
return fn(this.node, opts);
};
NodePath_Final.prototype[`assert${type}`] = function (opts) {
if (!fn(this.node, opts)) {
throw new TypeError(`Expected node path of type ${type}`);
}
};
}
Object.assign(NodePath_Final.prototype, NodePath_virtual_types_validator);
for (const type of Object.keys(virtualTypes)) {
if (type.startsWith("_")) continue;
if (!_t.TYPES.includes(type)) _t.TYPES.push(type);
}
function _call(fns) {
if (!fns) return false;
for (const fn of fns) {
if (!fn) continue;
const node = this.node;
if (!node) return true;
const ret = fn.call(this.state, this, this.state);
if (ret && typeof ret === "object" && typeof ret.then === "function") {
throw new Error(`You appear to be using a plugin with an async traversal visitor, ` + `which your current version of Babel does not support. ` + `If you're using a published plugin, you may need to upgrade ` + `your @babel/core version.`);
}
if (ret) {
throw new Error(`Unexpected return value from visitor method ${fn}`);
}
if (this.node !== node) return true;
if (this._traverseFlags > 0) return true;
}
return false;
}
function isDenylisted() {
return !!this.opts.denylist?.includes(this.node.type);
}
function skip() {
this.shouldSkip = true;
}
function skipKey(key) {
if (this.skipKeys == null) {
this.skipKeys = {};
}
this.skipKeys[key] = true;
}
function stop() {
this._traverseFlags |= SHOULD_SKIP | SHOULD_STOP;
}
function _forceSetScope() {
let path = this.parentPath;
if ((this.key === "key" || this.listKey === "decorators") && path.isMethod() || this.key === "discriminant" && path.isSwitchStatement()) {
path = path.parentPath;
}
let target;
while (path && !target) {
target = path.scope;
path = path.parentPath;
}
this.scope = this.getScope(target);
this.scope?.init();
}
function setScope() {
if (this.opts?.noScope) return;
let path = this.parentPath;
if ((this.key === "key" || this.listKey === "decorators") && path.isMethod() || this.key === "discriminant" && path.isSwitchStatement()) {
path = path.parentPath;
}
let target;
while (path && !target) {
if (path.opts?.noScope) return;
target = path.scope;
path = path.parentPath;
}
this.scope = this.getScope(target);
this.scope?.init();
}
function setContext(context) {
if (this.skipKeys != null) {
this.skipKeys = {};
}
this._traverseFlags = 0;
if (context) {
this.context = context;
this.state = context.state;
this.opts = context.opts;
}
setScope.call(this);
return this;
}
function resync() {
if (this.removed) return;
if (this.parentPath) {
this.parent = this.parentPath.node;
}
if (this.parent && this.inList) {
const newContainer = this.parent[this.listKey];
if (this.container !== newContainer) {
this.container = newContainer || null;
}
}
if (this.container && this.node !== this.container[this.key]) {
let key = -1;
if (Array.isArray(this.container)) {
key = this.container.indexOf(this.node);
} else {
for (key of Object.keys(this.container)) {
if (this.container[key] === this.node) {
break;
}
}
}
if (key === -1) {
this.key = null;
} else {
_setKey.call(this, key);
}
}
}
function popContext() {
this.contexts.pop();
if (this.contexts.length > 0) {
this.setContext(this.contexts[this.contexts.length - 1]);
} else {
this.setContext(undefined);
}
}
function pushContext(context) {
this.contexts.push(context);
this.setContext(context);
}
function setup(parentPath, container, listKey, key) {
this.listKey = listKey;
this.container = container;
this.parentPath = parentPath || this.parentPath;
_setKey.call(this, key);
}
function _setKey(key) {
this.key = key;
this.node = this.container[this.key];
this.type = this.node?.type ?? null;
}
function requeue(pathToQueue = this) {
if (pathToQueue.removed) return;
pathToQueue.shouldSkip = false;
const contexts = this.contexts;
for (const context of contexts) {
context.maybeQueue(pathToQueue);
}
}
function requeueComputedKeyAndDecorators() {
const {
context,
node
} = this;
if (!_t.isPrivate(node) && node.computed) {
context.maybeQueue(this.get("key"));
}
if (node.decorators) {
for (const decorator of this.get("decorators")) {
context.maybeQueue(decorator);
}
}
}
function _getQueueContexts() {
let path = this;
let contexts = this.contexts;
while (!contexts.length) {
path = path.parentPath;
if (!path) break;
contexts = path.contexts;
}
return contexts;
}
class Hub {
getCode() {}
getScope() {}
addHelper() {
throw new Error("Helpers are not supported by the default hub.");
}
buildError(node, msg, Error = TypeError) {
return new Error(msg);
}
}
const {
VISITOR_KEYS,
removeProperties,
traverseFast
} = _t;
function traverse(parent, opts = {}, scope, state, parentPath, visitSelf) {
if (!parent) return;
if (!opts.noScope && !scope) {
if (parent.type !== "Program" && parent.type !== "File") {
throw new Error("You must pass a scope and parentPath unless traversing a Program/File. " + `Instead of that you tried to traverse a ${parent.type} node without ` + "passing scope and parentPath.");
}
}
if (!parentPath && visitSelf) {
throw new Error("visitSelf can only be used when providing a NodePath.");
}
if (!VISITOR_KEYS[parent.type]) {
return;
}
explode$1(opts);
traverseNode(parent, opts, scope, state, parentPath, undefined, visitSelf);
}
traverse.visitors = visitors;
traverse.verify = verify$1;
traverse.explode = explode$1;
traverse.cheap = function (node, enter) {
traverseFast(node, enter);
return;
};
traverse.node = function (node, opts, scope, state, path, skipKeys) {
traverseNode(node, opts, scope, state, path, skipKeys);
};
traverse.clearNode = function (node, opts) {
removeProperties(node, opts);
};
traverse.removeProperties = function (tree, opts) {
traverseFast(tree, traverse.clearNode, opts);
return tree;
};
traverse.hasType = function (tree, type, denylistTypes) {
if (denylistTypes?.includes(tree.type)) return false;
if (tree.type === type) return true;
return traverseFast(tree, function (node) {
if (denylistTypes?.includes(node.type)) {
return traverseFast.skip;
}
if (node.type === type) {
return traverseFast.stop;
}
});
};
traverse.cache = cache;
export { Hub, NodePath_Final as NodePath, Scope, traverse as default, visitors };