added to remote repo
This commit is contained in:
1 parent
8697c9f405
commit
cc599b6e18
8049 files changed
+1096323
No files matched your search
+22
@@ -0,0 +1,22 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
# @babel/traverse
|
||||
|
||||
> The Babel Traverse module maintains the overall tree state, and is responsible for replacing, removing, and adding nodes
|
||||
|
||||
See our website [@babel/traverse](https://babeljs.io/docs/babel-traverse) for more information or the [issues](https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22pkg%3A%20traverse%22+is%3Aopen) associated with this package.
|
||||
|
||||
## Install
|
||||
|
||||
Using npm:
|
||||
|
||||
```sh
|
||||
npm install --save-dev @babel/traverse
|
||||
```
|
||||
|
||||
or using yarn:
|
||||
|
||||
```sh
|
||||
yarn add @babel/traverse --dev
|
||||
```
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.clear = clear;
|
||||
exports.clearPath = clearPath;
|
||||
exports.clearScope = clearScope;
|
||||
exports.getCachedPaths = getCachedPaths;
|
||||
exports.getOrCreateCachedPaths = getOrCreateCachedPaths;
|
||||
exports.scope = exports.path = void 0;
|
||||
let pathsCache = exports.path = new WeakMap();
|
||||
let scope = exports.scope = new WeakMap();
|
||||
function clear() {
|
||||
clearPath();
|
||||
clearScope();
|
||||
}
|
||||
function clearPath() {
|
||||
exports.path = pathsCache = new WeakMap();
|
||||
}
|
||||
function clearScope() {
|
||||
exports.scope = scope = new WeakMap();
|
||||
}
|
||||
function getCachedPaths(path) {
|
||||
const {
|
||||
parent,
|
||||
parentPath
|
||||
} = path;
|
||||
return pathsCache.get(parent);
|
||||
}
|
||||
function getOrCreateCachedPaths(node, parentPath) {
|
||||
let paths = pathsCache.get(node);
|
||||
if (!paths) pathsCache.set(node, paths = new Map());
|
||||
return paths;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=cache.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["pathsCache","exports","path","WeakMap","scope","clear","clearPath","clearScope","getCachedPaths","parent","parentPath","get","getOrCreateCachedPaths","node","paths","set","Map"],"sources":["../src/cache.ts"],"sourcesContent":["import type { Node } from \"@babel/types\";\nimport type NodePath from \"./path/index.ts\";\nimport type Scope from \"./scope/index.ts\";\n\nlet pathsCache = new WeakMap<Node, Map<Node, NodePath>>();\nexport { pathsCache as path };\nexport let scope = new WeakMap<Node, Scope>();\n\nexport function clear() {\n clearPath();\n clearScope();\n}\n\nexport function clearPath() {\n pathsCache = new WeakMap();\n}\n\nexport function clearScope() {\n scope = new WeakMap();\n}\n\nexport function getCachedPaths(path: NodePath) {\n const { parent, parentPath } = path;\n return process.env.BABEL_8_BREAKING && parentPath\n ? parentPath._store\n : pathsCache.get(parent);\n}\n\nexport function getOrCreateCachedPaths(\n node: Node,\n parentPath?: NodePath | null,\n) {\n if (process.env.BABEL_8_BREAKING && parentPath) {\n return (parentPath._store ||= new Map());\n }\n\n let paths = pathsCache.get(node);\n if (!paths) pathsCache.set(node, (paths = new Map()));\n\n return paths;\n}\n"],"mappings":";;;;;;;;;;;AAIA,IAAIA,UAAU,GAAAC,OAAA,CAAAC,IAAA,GAAG,IAAIC,OAAO,CAA4B,CAAC;AAElD,IAAIC,KAAK,GAAAH,OAAA,CAAAG,KAAA,GAAG,IAAID,OAAO,CAAc,CAAC;AAEtC,SAASE,KAAKA,CAAA,EAAG;EACtBC,SAAS,CAAC,CAAC;EACXC,UAAU,CAAC,CAAC;AACd;AAEO,SAASD,SAASA,CAAA,EAAG;EAC1BL,OAAA,CAAAC,IAAA,GAAAF,UAAU,GAAG,IAAIG,OAAO,CAAC,CAAC;AAC5B;AAEO,SAASI,UAAUA,CAAA,EAAG;EAC3BN,OAAA,CAAAG,KAAA,GAAAA,KAAK,GAAG,IAAID,OAAO,CAAC,CAAC;AACvB;AAEO,SAASK,cAAcA,CAACN,IAAc,EAAE;EAC7C,MAAM;IAAEO,MAAM;IAAEC;EAAW,CAAC,GAAGR,IAAI;EACnC,OAEIF,UAAU,CAACW,GAAG,CAACF,MAAM,CAAC;AAC5B;AAEO,SAASG,sBAAsBA,CACpCC,IAAU,EACVH,UAA4B,EAC5B;EAKA,IAAII,KAAK,GAAGd,UAAU,CAACW,GAAG,CAACE,IAAI,CAAC;EAChC,IAAI,CAACC,KAAK,EAAEd,UAAU,CAACe,GAAG,CAACF,IAAI,EAAGC,KAAK,GAAG,IAAIE,GAAG,CAAC,CAAE,CAAC;EAErD,OAAOF,KAAK;AACd","ignoreList":[]}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _index = require("./path/index.js");
|
||||
var _t = require("@babel/types");
|
||||
var _context = require("./path/context.js");
|
||||
var _hub = require("./hub.js");
|
||||
const {
|
||||
VISITOR_KEYS
|
||||
} = _t;
|
||||
class TraversalContext {
|
||||
constructor(scope, opts, state, parentPath) {
|
||||
this.queue = null;
|
||||
this.priorityQueue = null;
|
||||
this.parentPath = parentPath;
|
||||
this.scope = scope;
|
||||
this.state = state;
|
||||
this.opts = opts;
|
||||
}
|
||||
shouldVisit(node) {
|
||||
const opts = this.opts;
|
||||
if (opts.enter || opts.exit) return true;
|
||||
if (opts[node.type]) return true;
|
||||
const keys = VISITOR_KEYS[node.type];
|
||||
if (!(keys != null && keys.length)) return false;
|
||||
for (const key of keys) {
|
||||
if (node[key]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
create(node, container, key, listKey) {
|
||||
const {
|
||||
parentPath
|
||||
} = this;
|
||||
const hub = parentPath == null ? node.type === "Program" || node.type === "File" ? new _hub.default() : undefined : parentPath.hub;
|
||||
return _index.default.get({
|
||||
parentPath,
|
||||
parent: node,
|
||||
container,
|
||||
key: key,
|
||||
listKey,
|
||||
hub
|
||||
});
|
||||
}
|
||||
maybeQueue(path, notPriority) {
|
||||
if (this.queue) {
|
||||
if (notPriority) {
|
||||
this.queue.push(path);
|
||||
} else {
|
||||
this.priorityQueue.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
visitMultiple(container, parent, listKey) {
|
||||
if (container.length === 0) return false;
|
||||
const queue = [];
|
||||
for (let key = 0; key < container.length; key++) {
|
||||
const node = container[key];
|
||||
if (node && this.shouldVisit(node)) {
|
||||
queue.push(this.create(parent, container, key, listKey));
|
||||
}
|
||||
}
|
||||
return this.visitQueue(queue);
|
||||
}
|
||||
visitSingle(node, key) {
|
||||
if (this.shouldVisit(node[key])) {
|
||||
return this.visitQueue([this.create(node, node, key)]);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
visitQueue(queue) {
|
||||
this.queue = queue;
|
||||
this.priorityQueue = [];
|
||||
const visited = new WeakSet();
|
||||
let stop = false;
|
||||
let visitIndex = 0;
|
||||
for (; visitIndex < queue.length;) {
|
||||
const path = queue[visitIndex];
|
||||
visitIndex++;
|
||||
_context.resync.call(path);
|
||||
if (path.contexts.length === 0 || path.contexts[path.contexts.length - 1] !== this) {
|
||||
_context.pushContext.call(path, this);
|
||||
}
|
||||
if (path.key === null) continue;
|
||||
const {
|
||||
node
|
||||
} = path;
|
||||
if (visited.has(node)) continue;
|
||||
if (node) visited.add(node);
|
||||
if (path.visit()) {
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
if (this.priorityQueue.length) {
|
||||
stop = this.visitQueue(this.priorityQueue);
|
||||
this.priorityQueue = [];
|
||||
this.queue = queue;
|
||||
if (stop) break;
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < visitIndex; i++) {
|
||||
_context.popContext.call(queue[i]);
|
||||
}
|
||||
this.queue = null;
|
||||
return stop;
|
||||
}
|
||||
visit(node, key) {
|
||||
const nodes = node[key];
|
||||
if (!nodes) return false;
|
||||
if (Array.isArray(nodes)) {
|
||||
return this.visitMultiple(nodes, node, key);
|
||||
} else {
|
||||
return this.visitSingle(node, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.default = TraversalContext;
|
||||
|
||||
//# sourceMappingURL=context.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_index","require","_t","_context","_hub","VISITOR_KEYS","TraversalContext","constructor","scope","opts","state","parentPath","queue","priorityQueue","shouldVisit","node","enter","exit","type","keys","length","key","create","container","listKey","hub","Hub","undefined","NodePath","get","parent","maybeQueue","path","notPriority","push","visitMultiple","visitQueue","visitSingle","visited","WeakSet","stop","visitIndex","resync","call","contexts","pushContext","has","add","visit","i","popContext","nodes","Array","isArray","exports","default"],"sources":["../src/context.ts"],"sourcesContent":["import NodePath from \"./path/index.ts\";\nimport { VISITOR_KEYS } from \"@babel/types\";\nimport type Scope from \"./scope/index.ts\";\nimport type { ExplodedTraverseOptions } from \"./index.ts\";\nimport type * as t from \"@babel/types\";\nimport type { Visitor } from \"./types.ts\";\nimport { popContext, pushContext, resync } from \"./path/context.ts\";\nimport Hub from \"./hub.ts\";\n\nexport default class TraversalContext<S = unknown> {\n constructor(\n scope: Scope | null | undefined,\n opts: ExplodedTraverseOptions<S>,\n state: S,\n parentPath: NodePath | undefined,\n ) {\n this.parentPath = parentPath;\n this.scope = scope;\n this.state = state;\n this.opts = opts;\n }\n\n declare parentPath: NodePath | undefined;\n declare scope: Scope | null | undefined;\n declare state: S;\n declare opts: ExplodedTraverseOptions<S>;\n queue: NodePath[] | null = null;\n priorityQueue: NodePath[] | null = null;\n\n /**\n * This method does a simple check to determine whether or not we really need to attempt\n * visit a node. This will prevent us from constructing a NodePath.\n */\n\n shouldVisit(node: t.Node): boolean {\n const opts = this.opts as Visitor;\n if (opts.enter || opts.exit) return true;\n\n // check if we have a visitor for this node\n if (opts[node.type]) return true;\n\n // check if we're going to traverse into this node\n const keys: string[] | undefined = VISITOR_KEYS[node.type];\n if (!keys?.length) return false;\n\n // we need to traverse into this node so ensure that it has children to traverse into!\n for (const key of keys) {\n if (\n // @ts-expect-error key is from visitor keys\n node[key]\n ) {\n return true;\n }\n }\n\n return false;\n }\n\n create(\n node: t.Node,\n container: t.Node | t.Node[],\n key: string | number,\n listKey?: string,\n ): NodePath {\n const { parentPath } = this;\n const hub =\n parentPath == null\n ? node.type === \"Program\" || node.type === \"File\"\n ? new Hub()\n : undefined\n : parentPath.hub;\n\n // We don't need to `.setContext()` here, since `.visitQueue()` already\n // calls `.pushContext`.\n return NodePath.get({\n parentPath,\n parent: node,\n container,\n key: key,\n listKey,\n hub,\n });\n }\n\n maybeQueue(path: NodePath, notPriority?: boolean) {\n if (this.queue) {\n if (notPriority) {\n this.queue.push(path);\n } else {\n this.priorityQueue!.push(path);\n }\n }\n }\n\n visitMultiple(container: t.Node[], parent: t.Node, listKey: string) {\n // nothing to traverse!\n if (container.length === 0) return false;\n\n const queue = [];\n\n // build up initial queue\n for (let key = 0; key < container.length; key++) {\n const node = container[key];\n if (node && this.shouldVisit(node)) {\n queue.push(this.create(parent, container, key, listKey));\n }\n }\n\n return this.visitQueue(queue);\n }\n\n visitSingle(node: t.Node, key: string): boolean {\n if (\n this.shouldVisit(\n // @ts-expect-error key may not index node\n node[key],\n )\n ) {\n return this.visitQueue([this.create(node, node, key)]);\n } else {\n return false;\n }\n }\n\n visitQueue(queue: NodePath[]): boolean {\n // set queue\n this.queue = queue;\n this.priorityQueue = [];\n\n const visited = new WeakSet();\n let stop = false;\n let visitIndex = 0;\n\n // visit the queue\n for (; visitIndex < queue.length; ) {\n const path = queue[visitIndex];\n visitIndex++;\n resync.call(path);\n\n // this path no longer belongs to the tree\n if (process.env.BABEL_8_BREAKING && path.key === null) continue;\n\n if (\n path.contexts.length === 0 ||\n path.contexts[path.contexts.length - 1] !== this\n ) {\n // The context might already have been pushed when this path was inserted and queued.\n // If we always re-pushed here, we could get duplicates and risk leaving contexts\n // on the stack after the traversal has completed, which could break things.\n pushContext.call(path, this);\n }\n\n // this path no longer belongs to the tree\n if (!process.env.BABEL_8Line truncated
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
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);
|
||||
}
|
||||
}
|
||||
exports.default = Hub;
|
||||
|
||||
//# sourceMappingURL=hub.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["Hub","getCode","getScope","addHelper","Error","buildError","node","msg","TypeError","exports","default"],"sources":["../src/hub.ts"],"sourcesContent":["import type Scope from \"./scope/index.ts\";\nimport type { Node } from \"@babel/types\";\n\nexport interface HubInterface {\n getCode(): string | void;\n getScope(): Scope | void;\n addHelper(name: string): any;\n buildError(node: Node, msg: string, Error: new (msg: string) => Error): Error;\n}\n\nexport default class Hub implements HubInterface {\n getCode() {}\n\n getScope() {}\n\n addHelper() {\n throw new Error(\"Helpers are not supported by the default hub.\");\n }\n\n buildError(\n node: Node,\n msg: string,\n Error: new (msg: string) => Error = TypeError,\n ): Error {\n return new Error(msg);\n }\n}\n"],"mappings":";;;;;;AAUe,MAAMA,GAAG,CAAyB;EAC/CC,OAAOA,CAAA,EAAG,CAAC;EAEXC,QAAQA,CAAA,EAAG,CAAC;EAEZC,SAASA,CAAA,EAAG;IACV,MAAM,IAAIC,KAAK,CAAC,+CAA+C,CAAC;EAClE;EAEAC,UAAUA,CACRC,IAAU,EACVC,GAAW,EACXH,KAAiC,GAAGI,SAAS,EACtC;IACP,OAAO,IAAIJ,KAAK,CAACG,GAAG,CAAC;EACvB;AACF;AAACE,OAAA,CAAAC,OAAA,GAAAV,GAAA","ignoreList":[]}
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
Object.defineProperty(exports, "Hub", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _hub.default;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "NodePath", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _index.default;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(exports, "Scope", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _index2.default;
|
||||
}
|
||||
});
|
||||
exports.visitors = exports.default = void 0;
|
||||
require("./path/context.js");
|
||||
var visitors = require("./visitors.js");
|
||||
exports.visitors = visitors;
|
||||
var _t = require("@babel/types");
|
||||
var cache = require("./cache.js");
|
||||
var _traverseNode = require("./traverse-node.js");
|
||||
var _index = require("./path/index.js");
|
||||
var _index2 = require("./scope/index.js");
|
||||
var _hub = require("./hub.js");
|
||||
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;
|
||||
}
|
||||
visitors.explode(opts);
|
||||
(0, _traverseNode.traverseNode)(parent, opts, scope, state, parentPath, undefined, visitSelf);
|
||||
}
|
||||
var _default = exports.default = traverse;
|
||||
traverse.visitors = visitors;
|
||||
traverse.verify = visitors.verify;
|
||||
traverse.explode = visitors.explode;
|
||||
traverse.cheap = function (node, enter) {
|
||||
traverseFast(node, enter);
|
||||
return;
|
||||
};
|
||||
traverse.node = function (node, opts, scope, state, path, skipKeys) {
|
||||
(0, _traverseNode.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 != null && denylistTypes.includes(tree.type)) return false;
|
||||
if (tree.type === type) return true;
|
||||
return traverseFast(tree, function (node) {
|
||||
if (denylistTypes != null && denylistTypes.includes(node.type)) {
|
||||
return traverseFast.skip;
|
||||
}
|
||||
if (node.type === type) {
|
||||
return traverseFast.stop;
|
||||
}
|
||||
});
|
||||
};
|
||||
traverse.cache = cache;
|
||||
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["require","visitors","exports","_t","cache","_traverseNode","_index","_index2","_hub","VISITOR_KEYS","removeProperties","traverseFast","traverse","parent","opts","scope","state","parentPath","visitSelf","noScope","type","Error","explode","traverseNode","undefined","_default","default","verify","cheap","node","enter","path","skipKeys","clearNode","tree","hasType","denylistTypes","includes","skip","stop"],"sources":["../src/index.ts"],"sourcesContent":["import \"./path/context.ts\"; // We have some cycles, this ensures correct order to avoid TDZ\nimport * as visitors from \"./visitors.ts\";\nimport {\n VISITOR_KEYS,\n removeProperties,\n type RemovePropertiesOptions,\n traverseFast,\n} from \"@babel/types\";\nimport type * as t from \"@babel/types\";\nimport * as cache from \"./cache.ts\";\nimport type NodePath from \"./path/index.ts\";\nimport type { default as Scope, Binding } from \"./scope/index.ts\";\nimport type { ExplodedVisitor, Visitor, VisitorBase } from \"./types.ts\";\nimport { traverseNode } from \"./traverse-node.ts\";\n\nexport type { ExplodedVisitor, Visitor, VisitorBase, Binding };\nexport { default as NodePath } from \"./path/index.ts\";\nexport { default as Scope, type BindingKind } from \"./scope/index.ts\";\nexport { default as Hub } from \"./hub.ts\";\nexport type { HubInterface } from \"./hub.ts\";\nexport type { VisitWrapper } from \"./visitors.ts\";\n\nexport { visitors };\n\nexport type TraverseOptions<S = t.Node> = {\n scope?: Scope;\n noScope?: boolean;\n denylist?: string[];\n shouldSkip?: (node: NodePath) => boolean;\n} & Visitor<S>;\n\nexport type ExplodedTraverseOptions<S = t.Node> = TraverseOptions<S> &\n ExplodedVisitor<S>;\n\nfunction traverse<S>(\n parent: t.Node,\n opts: TraverseOptions<S>,\n scope: Scope | null | undefined,\n state: S,\n parentPath?: NodePath,\n visitSelf?: boolean,\n): void;\n\nfunction traverse(\n parent: t.Node,\n opts: TraverseOptions,\n scope?: Scope | null,\n state?: any,\n parentPath?: NodePath,\n visitSelf?: boolean,\n): void;\n\nfunction traverse<Options extends TraverseOptions>(\n parent: t.Node,\n // @ts-expect-error provide {} as default value for Options\n opts: Options = {},\n scope?: Scope | null,\n state?: any,\n parentPath?: NodePath,\n visitSelf?: boolean,\n) {\n if (!parent) return;\n\n if (!opts.noScope && !scope) {\n if (parent.type !== \"Program\" && parent.type !== \"File\") {\n throw new Error(\n \"You must pass a scope and parentPath unless traversing a Program/File. \" +\n `Instead of that you tried to traverse a ${parent.type} node without ` +\n \"passing scope and parentPath.\",\n );\n }\n }\n\n if (!parentPath && visitSelf) {\n throw new Error(\"visitSelf can only be used when providing a NodePath.\");\n }\n\n if (!VISITOR_KEYS[parent.type]) {\n return;\n }\n\n visitors.explode(opts as Visitor);\n\n traverseNode(\n parent,\n opts as ExplodedVisitor,\n scope,\n state,\n parentPath,\n /* skipKeys */ undefined,\n visitSelf,\n );\n}\n\nexport default traverse;\n\ntraverse.visitors = visitors;\ntraverse.verify = visitors.verify;\ntraverse.explode = visitors.explode;\n\ntraverse.cheap = function (node: t.Node, enter: (node: t.Node) => void) {\n traverseFast(node, enter);\n return;\n};\n\ntraverse.node = function (\n node: t.Node,\n opts: ExplodedTraverseOptions,\n scope?: Scope,\n state?: any,\n path?: NodePath,\n skipKeys?: Record<string, boolean>,\n) {\n traverseNode(node, opts, scope, state, path, skipKeys);\n // traverse.node always returns undefined\n};\n\ntraverse.clearNode = function (node: t.Node, opts?: RemovePropertiesOptions) {\n removeProperties(node, opts);\n};\n\ntraverse.removeProperties = function (\n tree: t.Node,\n opts?: RemovePropertiesOptions,\n) {\n traverseFast(tree, traverse.clearNode, opts);\n return tree;\n};\n\ntraverse.hasType = function (\n tree: t.Node,\n type: t.Node[\"type\"],\n denylistTypes?: string[],\n): boolean {\n // the node we're searching in is denylisted\n if (denylistTypes?.includes(tree.type)) return false;\n\n // the type we're looking for is the same as the passed node\n if (tree.type === type) return true;\n\n return traverseFast(tree, function (node) {\n if (denylistTypes?.includes(node.type)) {\n return traverseFast.skip;\n }\n if (node.type === type) {\n return traverseFast.stop;\n }\n });\n};\n\ntraverse.cache = cache;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAAA,OAAA;AACA,IAAAC,QAAA,GAAAD,OAAA;AAA0CE,OAAA,CAAAD,QAAA,GAAAA,QAAA;AAC1C,IAAAE,EAAA,GAAAH,OAAA;AAOA,IAAAI,KAAA,GAAAJ,OAAA;AAIA,IAAAK,aAAA,GAAAL,OAAA;AAGA,IAAAM,MAAA,GAAAN,OAAA;AACA,IAAAO,OAAA,GAAAP,OAAA;AACA,IAAAQ,IAAA,GAAAR,OAAA;AAA0C;EAfxCS,YAAY;EACZC,gBAAgB;EAEhBC;AAAY,IAAAR,EAAA;AA8Cd,SAASS,QAAQA,CACfC,MAAc,EAEdC,IAAa,GAAG,CAAC,CAAC,EAClBC,KAAoB,EACpBC,KAAW,EACXC,UAAqB,EACrBC,SAAmB,EACnB;EACA,IAAI,CAACL,MAAM,EAAE;EAEb,IAAI,CAACC,IAAI,CAACK,OAAO,IAALine truncated
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.find = find;
|
||||
exports.findParent = findParent;
|
||||
exports.getAncestry = getAncestry;
|
||||
exports.getDeepestCommonAncestorFrom = getDeepestCommonAncestorFrom;
|
||||
exports.getEarliestCommonAncestorFrom = getEarliestCommonAncestorFrom;
|
||||
exports.getFunctionParent = getFunctionParent;
|
||||
exports.getStatementParent = getStatementParent;
|
||||
exports.inType = inType;
|
||||
exports.isAncestor = isAncestor;
|
||||
exports.isDescendant = isDescendant;
|
||||
var _t = require("@babel/types");
|
||||
const {
|
||||
VISITOR_KEYS
|
||||
} = _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[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;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=ancestry.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_t","require","VISITOR_KEYS","findParent","callback","path","parentPath","find","getFunctionParent","p","isFunction","getStatementParent","Array","isArray","container","isStatement","isProgram","isFile","Error","getEarliestCommonAncestorFrom","paths","getDeepestCommonAncestorFrom","deepest","i","ancestries","earliest","keys","type","ancestry","listKey","key","earliestKeyIndex","indexOf","parentKey","currentKeyIndex","filter","length","minDepth","Infinity","lastCommonIndex","lastCommon","map","unshift","first","depthLoop","shouldMatch","getAncestry","push","isAncestor","maybeDescendant","isDescendant","maybeAncestor","parent","inType","candidateTypes","includes","node"],"sources":["../../src/path/ancestry.ts"],"sourcesContent":["// This file contains that retrieve or validate anything related to the current paths ancestry.\n\nimport { VISITOR_KEYS } from \"@babel/types\";\nimport type * as t from \"@babel/types\";\nimport type NodePath from \"./index.ts\";\n\n/**\n * Starting at the parent path of the current `NodePath` and going up the\n * tree, return the first `NodePath` that causes the provided `callback`\n * to return a truthy value, or `null` if the `callback` never returns a\n * truthy value.\n */\n\nexport function findParent(\n this: NodePath,\n callback: (path: NodePath) => boolean,\n): NodePath | null {\n let path = this;\n while ((path = path.parentPath)) {\n if (callback(path)) return path;\n }\n return null;\n}\n\n/**\n * Starting at current `NodePath` and going up the tree, return the first\n * `NodePath` that causes the provided `callback` to return a truthy value,\n * or `null` if the `callback` never returns a truthy value.\n */\n\nexport function find(\n this: NodePath,\n callback: (path: NodePath) => boolean,\n): NodePath | null {\n let path = this;\n do {\n if (callback(path)) return path;\n } while ((path = path.parentPath));\n return null;\n}\n\n/**\n * Get the parent function of the current path.\n */\n\nexport function getFunctionParent(this: NodePath): NodePath<t.Function> | null {\n return this.findParent(p => p.isFunction()) as NodePath<t.Function> | null;\n}\n\n/**\n * Walk up the tree until we hit a parent node path in a list.\n */\n\nexport function getStatementParent(this: NodePath): NodePath<t.Statement> {\n let path = this;\n\n do {\n if (\n !path.parentPath ||\n (Array.isArray(path.container) && path.isStatement())\n ) {\n break;\n } else {\n path = path.parentPath;\n }\n } while (path);\n\n if (path && (path.isProgram() || path.isFile())) {\n throw new Error(\n \"File/Program node, we can't possibly find a statement parent to this\",\n );\n }\n\n return path as NodePath<t.Statement>;\n}\n\n/**\n * Get the deepest common ancestor and then from it, get the earliest relationship path\n * to that ancestor.\n *\n * Earliest is defined as being \"before\" all the other nodes in terms of list container\n * position and visiting key.\n */\n\nexport function getEarliestCommonAncestorFrom(\n this: NodePath,\n paths: NodePath[],\n): NodePath {\n return this.getDeepestCommonAncestorFrom(\n paths,\n function (deepest, i, ancestries) {\n let earliest;\n const keys = VISITOR_KEYS[deepest.type];\n\n for (const ancestry of ancestries) {\n const path = ancestry[i + 1];\n\n // first path\n if (!earliest) {\n earliest = path;\n continue;\n }\n\n // handle containers\n if (path.listKey && earliest.listKey === path.listKey) {\n // we're in the same container so check if we're earlier\n if (path.key! < earliest.key!) {\n earliest = path;\n continue;\n }\n }\n\n // handle keys\n const earliestKeyIndex = keys.indexOf(earliest.parentKey);\n const currentKeyIndex = keys.indexOf(path.parentKey);\n if (earliestKeyIndex > currentKeyIndex) {\n // key appears before so it's earlier\n earliest = path;\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion\n return earliest!;\n },\n );\n}\n\n/**\n * Get the earliest path in the tree where the provided `paths` intersect.\n *\n * TODO: Possible optimisation target.\n */\n\nexport function getDeepestCommonAncestorFrom(\n this: NodePath,\n paths: NodePath[],\n filter?: (deepest: NodePath, i: number, ancestries: NodePath[][]) => NodePath,\n): NodePath {\n if (!paths.length) {\n return this;\n }\n\n if (paths.length === 1) {\n return paths[0];\n }\n\n // minimum depth of the tree so we know the highest node\n let minDepth = Infinity;\n\n // last common ancestor\n let lastCommonIndex, lastCommon;\n\n // get the ancestors of the path, breaking when the parent exceeds ourselves\n const ancestries = paths.map(path => {\n const ancestry: NodePath[] = [];\n\n do {\n ancestry.unshift(path);\n } while ((paLine truncated
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.addComment = addComment;
|
||||
exports.addComments = addComments;
|
||||
exports.shareCommentsWithSiblings = shareCommentsWithSiblings;
|
||||
var _t = require("@babel/types");
|
||||
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 = Boolean(prev.node);
|
||||
const hasNext = Boolean(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 != null && 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);
|
||||
}
|
||||
|
||||
//# sourceMappingURL=comments.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_t","require","addComment","_addComment","addComments","_addComments","shareCommentsWithSiblings","key","node","trailing","trailingComments","leading","leadingComments","prev","getSibling","next","hasPrev","Boolean","hasNext","removeIfExisting","list","toRemove","length","set","Set","filter","el","has","type","content","line","comments"],"sources":["../../src/path/comments.ts"],"sourcesContent":["// This file contains methods responsible for dealing with comments.\nimport type * as t from \"@babel/types\";\nimport type NodePath from \"./index.ts\";\nimport {\n addComment as _addComment,\n addComments as _addComments,\n} from \"@babel/types\";\n\n/**\n * Share comments amongst siblings.\n */\n\nexport function shareCommentsWithSiblings(this: NodePath) {\n // NOTE: this assumes numbered keys\n if (typeof this.key === \"string\") return;\n\n const node = this.node;\n if (!node) return;\n\n const trailing = node.trailingComments;\n const leading = node.leadingComments;\n if (!trailing && !leading) return;\n\n const prev = this.getSibling(this.key! - 1);\n const next = this.getSibling(this.key! + 1);\n const hasPrev = Boolean(prev.node);\n const hasNext = Boolean(next.node);\n\n if (hasPrev) {\n if (leading) {\n prev.addComments(\n \"trailing\",\n removeIfExisting(leading, prev.node.trailingComments),\n );\n }\n if (trailing && !hasNext) prev.addComments(\"trailing\", trailing);\n }\n if (hasNext) {\n if (trailing) {\n next.addComments(\n \"leading\",\n removeIfExisting(trailing, next.node.leadingComments),\n );\n }\n if (leading && !hasPrev) next.addComments(\"leading\", leading);\n }\n}\n\nfunction removeIfExisting<T>(list: T[], toRemove?: T[] | null): T[] {\n if (!toRemove?.length) return list;\n const set = new Set(toRemove);\n return list.filter(el => {\n return !set.has(el);\n });\n}\n\nexport function addComment(\n this: NodePath,\n type: t.CommentTypeShorthand,\n content: string,\n line?: boolean,\n) {\n _addComment(this.node, type, content, line);\n}\n\n/**\n * Give node `comments` of the specified `type`.\n */\n\nexport function addComments(\n this: NodePath,\n type: t.CommentTypeShorthand,\n comments: t.Comment[],\n) {\n _addComments(this.node, type, comments);\n}\n"],"mappings":";;;;;;;;AAGA,IAAAA,EAAA,GAAAC,OAAA;AAGsB;EAFpBC,UAAU,EAAIC,WAAW;EACzBC,WAAW,EAAIC;AAAY,IAAAL,EAAA;AAOtB,SAASM,yBAAyBA,CAAA,EAAiB;EAExD,IAAI,OAAO,IAAI,CAACC,GAAG,KAAK,QAAQ,EAAE;EAElC,MAAMC,IAAI,GAAG,IAAI,CAACA,IAAI;EACtB,IAAI,CAACA,IAAI,EAAE;EAEX,MAAMC,QAAQ,GAAGD,IAAI,CAACE,gBAAgB;EACtC,MAAMC,OAAO,GAAGH,IAAI,CAACI,eAAe;EACpC,IAAI,CAACH,QAAQ,IAAI,CAACE,OAAO,EAAE;EAE3B,MAAME,IAAI,GAAG,IAAI,CAACC,UAAU,CAAC,IAAI,CAACP,GAAG,GAAI,CAAC,CAAC;EAC3C,MAAMQ,IAAI,GAAG,IAAI,CAACD,UAAU,CAAC,IAAI,CAACP,GAAG,GAAI,CAAC,CAAC;EAC3C,MAAMS,OAAO,GAAGC,OAAO,CAACJ,IAAI,CAACL,IAAI,CAAC;EAClC,MAAMU,OAAO,GAAGD,OAAO,CAACF,IAAI,CAACP,IAAI,CAAC;EAElC,IAAIQ,OAAO,EAAE;IACX,IAAIL,OAAO,EAAE;MACXE,IAAI,CAACT,WAAW,CACd,UAAU,EACVe,gBAAgB,CAACR,OAAO,EAAEE,IAAI,CAACL,IAAI,CAACE,gBAAgB,CACtD,CAAC;IACH;IACA,IAAID,QAAQ,IAAI,CAACS,OAAO,EAAEL,IAAI,CAACT,WAAW,CAAC,UAAU,EAAEK,QAAQ,CAAC;EAClE;EACA,IAAIS,OAAO,EAAE;IACX,IAAIT,QAAQ,EAAE;MACZM,IAAI,CAACX,WAAW,CACd,SAAS,EACTe,gBAAgB,CAACV,QAAQ,EAAEM,IAAI,CAACP,IAAI,CAACI,eAAe,CACtD,CAAC;IACH;IACA,IAAID,OAAO,IAAI,CAACK,OAAO,EAAED,IAAI,CAACX,WAAW,CAAC,SAAS,EAAEO,OAAO,CAAC;EAC/D;AACF;AAEA,SAASQ,gBAAgBA,CAAIC,IAAS,EAAEC,QAAqB,EAAO;EAClE,IAAI,EAACA,QAAQ,YAARA,QAAQ,CAAEC,MAAM,GAAE,OAAOF,IAAI;EAClC,MAAMG,GAAG,GAAG,IAAIC,GAAG,CAACH,QAAQ,CAAC;EAC7B,OAAOD,IAAI,CAACK,MAAM,CAACC,EAAE,IAAI;IACvB,OAAO,CAACH,GAAG,CAACI,GAAG,CAACD,EAAE,CAAC;EACrB,CAAC,CAAC;AACJ;AAEO,SAASxB,UAAUA,CAExB0B,IAA4B,EAC5BC,OAAe,EACfC,IAAc,EACd;EACA3B,WAAW,CAAC,IAAI,CAACK,IAAI,EAAEoB,IAAI,EAAEC,OAAO,EAAEC,IAAI,CAAC;AAC7C;AAMO,SAAS1B,WAAWA,CAEzBwB,IAA4B,EAC5BG,QAAqB,EACrB;EACA1B,YAAY,CAAC,IAAI,CAACG,IAAI,EAAEoB,IAAI,EAAEG,QAAQ,CAAC;AACzC","ignoreList":[]}
|
||||
+254
@@ -0,0 +1,254 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports._call = _call;
|
||||
exports._forceSetScope = _forceSetScope;
|
||||
exports._getQueueContexts = _getQueueContexts;
|
||||
exports._resyncKey = _resyncKey;
|
||||
exports._resyncList = _resyncList;
|
||||
exports._resyncParent = _resyncParent;
|
||||
exports._resyncRemoved = _resyncRemoved;
|
||||
exports.call = call;
|
||||
exports.isDenylisted = isDenylisted;
|
||||
exports.popContext = popContext;
|
||||
exports.pushContext = pushContext;
|
||||
exports.requeue = requeue;
|
||||
exports.requeueComputedKeyAndDecorators = requeueComputedKeyAndDecorators;
|
||||
exports.resync = resync;
|
||||
exports.setContext = setContext;
|
||||
exports.setKey = setKey;
|
||||
exports.setScope = setScope;
|
||||
exports.setup = setup;
|
||||
exports.skip = skip;
|
||||
exports.skipKey = skipKey;
|
||||
exports.stop = stop;
|
||||
exports.visit = visit;
|
||||
var _traverseNode = require("../traverse-node.js");
|
||||
var _index = require("./index.js");
|
||||
var _removal = require("./removal.js");
|
||||
var t = require("@babel/types");
|
||||
function call(key) {
|
||||
const opts = this.opts;
|
||||
this.debug(key);
|
||||
if (this.node) {
|
||||
if (_call.call(this, opts[key])) return true;
|
||||
}
|
||||
if (this.node) {
|
||||
var _opts$this$node$type;
|
||||
return _call.call(this, (_opts$this$node$type = opts[this.node.type]) == null ? void 0 : _opts$this$node$type[key]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
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() {
|
||||
var _this$opts$denylist;
|
||||
const denylist = (_this$opts$denylist = this.opts.denylist) != null ? _this$opts$denylist : this.opts.blacklist;
|
||||
return denylist == null ? void 0 : denylist.includes(this.node.type);
|
||||
}
|
||||
exports.isBlacklisted = isDenylisted;
|
||||
function restoreContext(path, context) {
|
||||
if (path.context !== context) {
|
||||
path.context = context;
|
||||
path.state = context.state;
|
||||
path.opts = context.opts;
|
||||
}
|
||||
}
|
||||
function visit() {
|
||||
var _this$opts$shouldSkip, _this$opts;
|
||||
if (!this.node) {
|
||||
return false;
|
||||
}
|
||||
if (this.isDenylisted()) {
|
||||
return false;
|
||||
}
|
||||
if ((_this$opts$shouldSkip = (_this$opts = this.opts).shouldSkip) != null && _this$opts$shouldSkip.call(_this$opts, this)) {
|
||||
return false;
|
||||
}
|
||||
const currentContext = this.context;
|
||||
if (this.shouldSkip || call.call(this, "enter")) {
|
||||
this.debug("Skip...");
|
||||
return this.shouldStop;
|
||||
}
|
||||
restoreContext(this, currentContext);
|
||||
this.debug("Recursing into...");
|
||||
this.shouldStop = (0, _traverseNode.traverseNode)(this.node, this.opts, this.scope, this.state, this, this.skipKeys);
|
||||
restoreContext(this, currentContext);
|
||||
call.call(this, "exit");
|
||||
return this.shouldStop;
|
||||
}
|
||||
function skip() {
|
||||
this.shouldSkip = true;
|
||||
}
|
||||
function skipKey(key) {
|
||||
if (this.skipKeys == null) {
|
||||
this.skipKeys = {};
|
||||
}
|
||||
this.skipKeys[key] = true;
|
||||
}
|
||||
function stop() {
|
||||
this._traverseFlags |= _index.SHOULD_SKIP | _index.SHOULD_STOP;
|
||||
}
|
||||
function _forceSetScope() {
|
||||
var _this$scope;
|
||||
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 = this.scope) == null || _this$scope.init();
|
||||
}
|
||||
function setScope() {
|
||||
var _this$opts2, _this$scope2;
|
||||
if ((_this$opts2 = this.opts) != null && _this$opts2.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) {
|
||||
var _path$opts;
|
||||
if ((_path$opts = path.opts) != null && _path$opts.noScope) return;
|
||||
target = path.scope;
|
||||
path = path.parentPath;
|
||||
}
|
||||
this.scope = this.getScope(target);
|
||||
(_this$scope2 = this.scope) == null || _this$scope2.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;
|
||||
_resyncParent.call(this);
|
||||
_resyncList.call(this);
|
||||
_resyncKey.call(this);
|
||||
}
|
||||
function _resyncParent() {
|
||||
if (this.parentPath) {
|
||||
this.parent = this.parentPath.node;
|
||||
}
|
||||
}
|
||||
function _resyncKey() {
|
||||
if (!this.container) return;
|
||||
if (this.node === this.container[this.key]) {
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(this.container)) {
|
||||
for (let i = 0; i < this.container.length; i++) {
|
||||
if (this.container[i] === this.node) {
|
||||
setKey.call(this, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const key of Object.keys(this.container)) {
|
||||
if (this.container[key] === this.node) {
|
||||
setKey.call(this, key);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.key = null;
|
||||
}
|
||||
function _resyncList() {
|
||||
if (!this.parent || !this.inList) return;
|
||||
const newContainer = this.parent[this.listKey];
|
||||
if (this.container === newContainer) return;
|
||||
this.container = newContainer || null;
|
||||
}
|
||||
function _resyncRemoved() {
|
||||
if (this.key == null || !this.container || this.container[this.key] !== this.node) {
|
||||
_removal._markRemoved.call(this);
|
||||
}
|
||||
}
|
||||
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) {
|
||||
var _this$node;
|
||||
this.key = key;
|
||||
this.node = this.container[this.key];
|
||||
this.type = (_this$node = this.node) == null ? void 0 : _this$node.type;
|
||||
}
|
||||
function requeue(pathToQueue = this) {
|
||||
if (pathToQueue.removed) return;
|
||||
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;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=context.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_traverseNode","require","_index","_removal","t","call","key","opts","debug","node","_call","_opts$this$node$type","type","fns","fn","ret","state","then","Error","_traverseFlags","isDenylisted","_this$opts$denylist","denylist","blacklist","includes","exports","isBlacklisted","restoreContext","path","context","visit","_this$opts$shouldSkip","_this$opts","shouldSkip","currentContext","shouldStop","traverseNode","scope","skipKeys","skip","skipKey","stop","SHOULD_SKIP","SHOULD_STOP","_forceSetScope","_this$scope","parentPath","listKey","isMethod","isSwitchStatement","target","getScope","init","setScope","_this$opts2","_this$scope2","noScope","_path$opts","setContext","resync","removed","_resyncParent","_resyncList","_resyncKey","parent","container","Array","isArray","i","length","setKey","Object","keys","inList","newContainer","_resyncRemoved","_markRemoved","popContext","contexts","pop","undefined","pushContext","push","setup","_this$node","requeue","pathToQueue","maybeQueue","requeueComputedKeyAndDecorators","isPrivate","computed","get","decorators","decorator","_getQueueContexts"],"sources":["../../src/path/context.ts"],"sourcesContent":["// This file contains methods responsible for maintaining a TraversalContext.\n\nimport { traverseNode } from \"../traverse-node.ts\";\nimport { SHOULD_SKIP, SHOULD_STOP } from \"./index.ts\";\nimport { _markRemoved } from \"./removal.ts\";\nimport type TraversalContext from \"../context.ts\";\nimport type { VisitPhase } from \"../types.ts\";\nimport type NodePath from \"./index.ts\";\nimport * as t from \"@babel/types\";\n\nexport function call(this: NodePath, key: VisitPhase): boolean {\n const opts = this.opts;\n\n this.debug(key);\n\n if (this.node) {\n if (_call.call(this, opts[key])) return true;\n }\n\n if (this.node) {\n return _call.call(this, opts[this.node.type]?.[key]);\n }\n\n return false;\n}\n\nexport function _call(this: NodePath, fns?: Function[]): boolean {\n if (!fns) return false;\n\n for (const fn of fns) {\n if (!fn) continue;\n\n const node = this.node;\n if (!node) return true;\n\n const ret = fn.call(this.state, this, this.state);\n if (ret && typeof ret === \"object\" && typeof ret.then === \"function\") {\n throw new Error(\n `You appear to be using a plugin with an async traversal visitor, ` +\n `which your current version of Babel does not support. ` +\n `If you're using a published plugin, you may need to upgrade ` +\n `your @babel/core version.`,\n );\n }\n if (ret) {\n throw new Error(`Unexpected return value from visitor method ${fn}`);\n }\n\n // node has been replaced, it will have been requeued\n if (this.node !== node) return true;\n\n // this.shouldSkip || this.shouldStop || this.removed\n if (this._traverseFlags > 0) return true;\n }\n\n return false;\n}\n\nexport function isDenylisted(this: NodePath): boolean {\n // @ts-expect-error TODO(Babel 8): Remove blacklist\n const denylist = this.opts.denylist ?? this.opts.blacklist;\n return denylist?.includes(this.node.type);\n}\n\nif (!process.env.BABEL_8_BREAKING && !USE_ESM) {\n // eslint-disable-next-line no-restricted-globals\n exports.isBlacklisted = isDenylisted;\n}\n\nfunction restoreContext(path: NodePath, context: TraversalContext) {\n if (path.context !== context) {\n path.context = context;\n path.state = context.state;\n path.opts = context.opts;\n }\n}\n\nexport function visit(this: NodePath): boolean {\n if (!this.node) {\n return false;\n }\n\n if (this.isDenylisted()) {\n return false;\n }\n\n if (this.opts.shouldSkip?.(this)) {\n return false;\n }\n\n const currentContext = this.context;\n // Note: We need to check \"this.shouldSkip\" first because\n // another visitor can set it to true. Usually .shouldSkip is false\n // before calling the enter visitor, but it can be true in case of\n // a requeued node (e.g. by .replaceWith()) that is then marked\n // with .skip().\n if (this.shouldSkip || call.call(this, \"enter\")) {\n this.debug(\"Skip...\");\n return this.shouldStop;\n }\n restoreContext(this, currentContext);\n\n this.debug(\"Recursing into...\");\n this.shouldStop = traverseNode(\n this.node,\n this.opts,\n this.scope,\n this.state,\n this,\n this.skipKeys,\n );\n\n restoreContext(this, currentContext);\n\n call.call(this, \"exit\");\n\n return this.shouldStop;\n}\n\nexport function skip(this: NodePath) {\n this.shouldSkip = true;\n}\n\nexport function skipKey(this: NodePath, key: string) {\n if (this.skipKeys == null) {\n this.skipKeys = {};\n }\n this.skipKeys[key] = true;\n}\n\nexport function stop(this: NodePath) {\n // this.shouldSkip = true; this.shouldStop = true;\n this._traverseFlags |= SHOULD_SKIP | SHOULD_STOP;\n}\n\nexport function _forceSetScope(this: NodePath) {\n let path = this.parentPath;\n\n if (\n // Skip method scope if is computed method Line truncated
|
||||
+608
@@ -0,0 +1,608 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.arrowFunctionToExpression = arrowFunctionToExpression;
|
||||
exports.ensureBlock = ensureBlock;
|
||||
exports.ensureFunctionName = ensureFunctionName;
|
||||
exports.splitExportDeclaration = splitExportDeclaration;
|
||||
exports.toComputedKey = toComputedKey;
|
||||
exports.unwrapFunctionEnvironment = unwrapFunctionEnvironment;
|
||||
var _t = require("@babel/types");
|
||||
var _template = require("@babel/template");
|
||||
var _visitors = require("../visitors.js");
|
||||
var _context = require("./context.js");
|
||||
const {
|
||||
arrowFunctionExpression,
|
||||
assignmentExpression,
|
||||
binaryExpression,
|
||||
blockStatement,
|
||||
callExpression,
|
||||
conditionalExpression,
|
||||
expressionStatement,
|
||||
identifier,
|
||||
isIdentifier,
|
||||
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
|
||||
} = _t;
|
||||
function toComputedKey() {
|
||||
let key;
|
||||
if (this.isMemberExpression()) {
|
||||
key = this.node.property;
|
||||
} else if (this.isProperty() || this.isMethod()) {
|
||||
key = this.node.key;
|
||||
} else {
|
||||
throw new ReferenceError("todo");
|
||||
}
|
||||
if (!this.node.computed) {
|
||||
if (isIdentifier(key)) key = stringLiteral(key.name);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
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);
|
||||
_context.setup.call(body, parentPath, listKey ? parentPath.node[listKey] : parentPath.node, listKey, key);
|
||||
return this.node;
|
||||
}
|
||||
exports.arrowFunctionToShadowed = function () {
|
||||
if (!this.isArrowFunctionExpression()) return;
|
||||
this.arrowFunctionToExpression();
|
||||
};
|
||||
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 = !(_arguments$ => (_arguments$ = arguments[0]) == null ? void 0 : _arguments$.specCompliant)()
|
||||
} = {}) {
|
||||
if (!this.isArrowFunctionExpression()) {
|
||||
throw this.buildCodeFrameError("Cannot convert non-arrow function to a function expression.");
|
||||
}
|
||||
let self = this;
|
||||
if (!noNewArrows) {
|
||||
var _self$ensureFunctionN;
|
||||
self = (_self$ensureFunctionN = self.ensureFunctionName(false)) != null ? _self$ensureFunctionN : 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)])));
|
||||
fn.replaceWith(callExpression(memberExpression(fn.node, identifier("bind")), [checkBinding ? identifier(checkBinding.name) : thisExpression()]));
|
||||
return fn.get("callee.object");
|
||||
}
|
||||
return fn;
|
||||
}
|
||||
const getSuperCallsVisitor = (0, _visitors.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 != null ? arrowParent : 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) {
|
||||
fnPath.replaceWith(callExpression(arrowFunctionExpression([], toExpression(fnPath.node)), []));
|
||||
thisEnvFn = fnPath.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")), thisEnvFn.scope.buildUndefinedNode(), 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) {
|
||||
superProp.replaceWith(callExpression(memberExpression(call, identifier("bind"), false), [thisExpression()]));
|
||||
thisPaths.push(superProp.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));
|
||||
}
|
||||
updateExpr.replaceWith(sequenceExpression(parts));
|
||||
const left = updateExpr.get("expressions.0.right");
|
||||
const right = updateExpr.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 = (0, _visitors.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 = (0, _visitors.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 refersOuterBindingVisitor = {
|
||||
"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 {}
|
||||
} else if (scope.parent.hasBinding(name) || scope.hasGlobal(name)) {
|
||||
this.traverse(refersOuterBindingVisitor, state);
|
||||
}
|
||||
if (!state.needsRename) {
|
||||
this.node.id = id;
|
||||
scope.getProgramParent().references[id.name] = true;
|
||||
return this;
|
||||
}
|
||||
if (scope.hasBinding(id.name) && !scope.hasGlobal(id.name)) {
|
||||
scope.rename(id.name);
|
||||
this.node.id = id;
|
||||
scope.getProgramParent().references[id.name] = true;
|
||||
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.default.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;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=conversion.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_t","require","_template","_visitors","_context","arrowFunctionExpression","assignmentExpression","binaryExpression","blockStatement","callExpression","conditionalExpression","expressionStatement","identifier","isIdentifier","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","toComputedKey","key","isMemberExpression","node","property","isProperty","isMethod","ReferenceError","computed","name","ensureBlock","body","get","bodyNode","Array","isArray","Error","isBlockStatement","statements","stringPath","listKey","isStatement","push","parentPath","setup","call","exports","arrowFunctionToShadowed","isArrowFunctionExpression","arrowFunctionToExpression","unwrapFunctionEnvironment","isFunctionExpression","isFunctionDeclaration","buildCodeFrameError","hoistFunctionEnvironment","setType","path","type","allowInsertArrow","allowInsertArrowWithRest","noNewArrows","_arguments$","arguments","specCompliant","self","_self$ensureFunctionN","ensureFunctionName","thisBinding","fnPath","fn","checkBinding","scope","generateUidIdentifier","id","init","unshiftContainer","hub","addHelper","replaceWith","getSuperCallsVisitor","environmentVisitor","CallExpression","child","allSuperCalls","isSuper","arrowParent","thisEnvFn","findParent","p","isProgram","isClassProperty","static","isClassPrivateProperty","inConstructor","isClassMethod","kind","thisPaths","argumentsPaths","newTargetPaths","superProps","superCalls","getScopeInformation","length","traverse","superBinding","getSuperBinding","forEach","superCall","callee","loc","argumentsBinding","getBinding","args","buildUndefinedNode","argumentsChild","argsRef","newTargetBinding","targetChild","targetRef","flatSuperProps","reduce","acc","superProp","concat","standardizeSuperProperty","superParentPath","isAssignment","isAssignmentExpression","left","isCall","isCallExpression","isTaggedTemplate","isTaggedTemplateExpression","tag","getSuperPropBinding","value","right","getThisBinding","hasSuperClass","thisChild","thisRef","isJSX","isLogicalOp","op","includes","operator","assignmentPath","slice","isLogicalAssignment","tmp","generateDeclaredUidIdentifier","object","rightExpression","isUpdateExpression","updateExpr","computedKey","parts","prefix","superClass","assignSuperThisVisitor","supers","has","add","replaceWithMultiple","WeakSet","argsBinding","propName","argsList","fnBody","method","unshift","valueIdent","cacheKey","data","getData","setData","getScopeInformationVisitor","ThisExpression","JSXIdentifier","isJSXMemberExpression","isJSXOpeningElement","MemberExpression","Identifier","isReferencedIdentifier","curr","hasOwnBinding","rename","parent","MetaProperty","splitExportDeclaration","isExportDeclaration","isExportAllDeclaration","isExportNamedDeclaration","declaration","isExportDefaultDeclaration","standaloneDeclaration","isClassDeclaration","exportExpr","isClassExpression","isScope","needBindingRegistration","hasBinding","updatedDeclaration","updatedExportDeclaration","insertAfter","registerDeclaration","bindingIdentifiers","getOuterBindingIdentifiers","specifiers","Object","keys","map","aliasDeclar","refersOuterBindingVisitor","ReferencedIdentifier|BindingIdentifier","state","needsRename","stop","Scope","skip","supportUnicodeId","res","test","startsWith","replace","originalNode","binding","getOwnBinding","hasGlobal","getProgramParent","references","params","i","len","getFunctionArity","template","expression","ast","count","findIndex","param"],"sources":["../../src/path/conversion.ts"],"sourcesContent":["// This file contains methods that convert the path node into another node or some other type of data.\n\nimport {\n arrowFunctionExpression,\n assignmentExpression,\n binaryExpression,\n blockStatement,\n callExpression,\n conditionalExpression,\n expressionStatement,\n identifier,\n isIdentifier,\n jsxIdentifier,\n logicalExpression,\n LOGICAL_OPERATORS,\n memberExpression,\n metaProperty,\n numericLiteral,\n objectExpression,\n restElement,\n returnStatement,\n sequenceExpression,\n spreadElement,\n stringLiteral,\n super as _super,\n thisExpression,\n toExpression,\n unaryExpression,\n toBindingIdentifierName,\n isFunction,\n isAssignmentPattern,\n isRestElement,\n getFunctionName,\n cloneNode,\n variableDeclaration,\n variableDeclarator,\n exportNamedDeclaration,\n exportSpecifier,\n inherits,\n} from \"@babel/types\";\nimport type * as t from \"@babel/types\";\nimport template from \"@babel/template\";\nimport { environmentVisitor } from \"../visitors.ts\";\nimport type NodePath from \"./index.ts\"Line truncated
|
||||
+373
@@ -0,0 +1,373 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.evaluate = evaluate;
|
||||
exports.evaluateTruthy = evaluateTruthy;
|
||||
const VALID_OBJECT_CALLEES = ["Number", "String", "Math"];
|
||||
const VALID_IDENTIFIER_CALLEES = ["isFinite", "isNaN", "parseFloat", "parseInt", "decodeURI", "decodeURIComponent", "encodeURI", "encodeURIComponent", null, null];
|
||||
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) {
|
||||
var _scope$path$parentPat;
|
||||
if (scope === path.scope) {
|
||||
if (hasUnsafeBlock) {
|
||||
deopt(binding.path, state);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ((_scope$path$parentPat = scope.path.parentPath) != null && _scope$path$parentPat.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 != null ? 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 Math.pow(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)) {
|
||||
context = global[object.node.name];
|
||||
const key = property.node.name;
|
||||
if (hasOwnProperty.call(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
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=evaluation.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["VALID_OBJECT_CALLEES","VALID_IDENTIFIER_CALLEES","INVALID_METHODS","isValidObjectCallee","val","includes","isValidIdentifierCallee","isInvalidMethod","evaluateTruthy","res","evaluate","confident","value","deopt","path","state","deoptPath","Globals","Map","undefined","Infinity","NaN","evaluateCached","node","seen","has","existing","get","resolved","item","set","_evaluate","isSequenceExpression","exprs","length","isStringLiteral","isNumericLiteral","isBooleanLiteral","isNullLiteral","isTemplateLiteral","evaluateQuasis","quasis","isTaggedTemplateExpression","isMemberExpression","object","name","property","isIdentifier","scope","getBinding","quasi","isConditionalExpression","testResult","isExpressionWrapper","parentPath","isCallExpression","callee","isLiteral","type","key","computed","isReferencedIdentifier","binding","constantViolations","start","end","bindingPathScope","kind","hasUnsafeBlock","isBlockStatement","parent","_scope$path$parentPat","hasValue","bindingPath","isVariableDeclarator","initPath","references","isUnaryExpression","prefix","operator","argument","isFunction","isClass","arg","isArrayExpression","arr","elems","elem","elemValue","push","isObjectExpression","obj","props","prop","isObjectMethod","isSpreadElement","keyPath","valuePath","isLogicalExpression","wasConfident","left","leftConfident","right","rightConfident","isBinaryExpression","Math","pow","context","func","global","hasOwnProperty","call","args","map","apply","raw","str","i","cooked","expr","String"],"sources":["../../src/path/evaluation.ts"],"sourcesContent":["import type NodePath from \"./index.ts\";\nimport type * as t from \"@babel/types\";\n\n// This file contains Babels metainterpreter that can evaluate static code.\n\nconst VALID_OBJECT_CALLEES = [\"Number\", \"String\", \"Math\"] as const;\nconst VALID_IDENTIFIER_CALLEES = [\n \"isFinite\",\n \"isNaN\",\n \"parseFloat\",\n \"parseInt\",\n \"decodeURI\",\n \"decodeURIComponent\",\n \"encodeURI\",\n \"encodeURIComponent\",\n process.env.BABEL_8_BREAKING ? \"btoa\" : null,\n process.env.BABEL_8_BREAKING ? \"atob\" : null,\n] as const;\n\nconst INVALID_METHODS = [\"random\"] as const;\n\nfunction isValidObjectCallee(\n val: string,\n): val is (typeof VALID_OBJECT_CALLEES)[number] {\n return VALID_OBJECT_CALLEES.includes(\n // @ts-expect-error val is a string\n val,\n );\n}\n\nfunction isValidIdentifierCallee(\n val: string,\n): val is NonNullable<(typeof VALID_IDENTIFIER_CALLEES)[number]> {\n return VALID_IDENTIFIER_CALLEES.includes(\n // @ts-expect-error val is a string\n val,\n );\n}\n\nfunction isInvalidMethod(val: string): val is (typeof INVALID_METHODS)[number] {\n return INVALID_METHODS.includes(\n // @ts-expect-error val is a string\n val,\n );\n}\n\n/**\n * Walk the input `node` and statically evaluate if it's truthy.\n *\n * Returning `true` when we're sure that the expression will evaluate to a\n * truthy value, `false` if we're sure that it will evaluate to a falsy\n * value and `undefined` if we aren't sure. Because of this please do not\n * rely on coercion when using this method and check with === if it's false.\n *\n * For example do:\n *\n * if (t.evaluateTruthy(node) === false) falsyLogic();\n *\n * **AND NOT**\n *\n * if (!t.evaluateTruthy(node)) falsyLogic();\n *\n */\n\nexport function evaluateTruthy(this: NodePath): boolean | undefined {\n const res = this.evaluate();\n if (res.confident) return !!res.value;\n}\n\ntype State = {\n confident: boolean;\n deoptPath: NodePath | null;\n seen: Map<t.Node, Result>;\n};\n\ntype Result = {\n resolved: boolean;\n value?: any;\n};\n/**\n * Deopts the evaluation\n */\nfunction deopt(path: NodePath | null, state: State) {\n if (!state.confident) return;\n state.deoptPath = path;\n state.confident = false;\n}\n\nconst Globals = new Map([\n [\"undefined\", undefined],\n [\"Infinity\", Infinity],\n [\"NaN\", NaN],\n]);\n\n/**\n * We wrap the _evaluate method so we can track `seen` nodes, we push an item\n * to the map before we actually evaluate it so we can deopt on self recursive\n * nodes such as:\n *\n * var g = a ? 1 : 2,\n * a = g * this.foo\n */\nfunction evaluateCached(path: NodePath, state: State): any {\n const { node } = path;\n const { seen } = state;\n\n if (seen.has(node)) {\n const existing = seen.get(node)!;\n if (existing.resolved) {\n return existing.value;\n } else {\n deopt(path, state);\n return;\n }\n } else {\n const item: Result = { resolved: false };\n seen.set(node, item);\n\n const val = _evaluate(path, state);\n if (state.confident) {\n item.resolved = true;\n item.value = val;\n }\n return val;\n }\n}\n\nfunction _evaluate(path: NodePath, state: State): any {\n if (!state.confident) return;\n\n if (path.isSequenceExpression()) {\n const exprs = path.get(\"expressions\");\n return evaluateCached(exprs[exprs.length - 1], state);\n }\n\n if (\n Line truncated
|
||||
+346
@@ -0,0 +1,346 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports._getKey = _getKey;
|
||||
exports._getPattern = _getPattern;
|
||||
exports.get = get;
|
||||
exports.getAllNextSiblings = getAllNextSiblings;
|
||||
exports.getAllPrevSiblings = getAllPrevSiblings;
|
||||
exports.getAssignmentIdentifiers = getAssignmentIdentifiers;
|
||||
exports.getBindingIdentifierPaths = getBindingIdentifierPaths;
|
||||
exports.getBindingIdentifiers = getBindingIdentifiers;
|
||||
exports.getCompletionRecords = getCompletionRecords;
|
||||
exports.getNextSibling = getNextSibling;
|
||||
exports.getOpposite = getOpposite;
|
||||
exports.getOuterBindingIdentifierPaths = getOuterBindingIdentifierPaths;
|
||||
exports.getOuterBindingIdentifiers = getOuterBindingIdentifiers;
|
||||
exports.getPrevSibling = getPrevSibling;
|
||||
exports.getSibling = getSibling;
|
||||
var _index = require("./index.js");
|
||||
var _t = require("@babel/types");
|
||||
const {
|
||||
getAssignmentIdentifiers: _getAssignmentIdentifiers,
|
||||
getBindingIdentifiers: _getBindingIdentifiers,
|
||||
getOuterBindingIdentifiers: _getOuterBindingIdentifiers,
|
||||
numericLiteral,
|
||||
unaryExpression
|
||||
} = _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(unaryExpression("void", numericLiteral(0)));
|
||||
} 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 = Object.assign({}, 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 _index.default.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() {
|
||||
let _key = this.key;
|
||||
let sibling = this.getSibling(++_key);
|
||||
const siblings = [];
|
||||
while (sibling.node) {
|
||||
siblings.push(sibling);
|
||||
sibling = this.getSibling(++_key);
|
||||
}
|
||||
return siblings;
|
||||
}
|
||||
function getAllPrevSiblings() {
|
||||
let _key = this.key;
|
||||
let sibling = this.getSibling(--_key);
|
||||
const siblings = [];
|
||||
while (sibling.node) {
|
||||
siblings.push(sibling);
|
||||
sibling = 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 _index.default.get({
|
||||
listKey: key,
|
||||
parentPath: this,
|
||||
parent: node,
|
||||
container: container,
|
||||
key: i
|
||||
}).setContext(context);
|
||||
});
|
||||
} else {
|
||||
return _index.default.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);
|
||||
}
|
||||
|
||||
//# sourceMappingURL=family.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_index","require","_t","getAssignmentIdentifiers","_getAssignmentIdentifiers","getBindingIdentifiers","_getBindingIdentifiers","getOuterBindingIdentifiers","_getOuterBindingIdentifiers","numericLiteral","unaryExpression","NORMAL_COMPLETION","BREAK_COMPLETION","NormalCompletion","path","type","BreakCompletion","getOpposite","key","getSibling","addCompletionRecords","records","context","push","_getCompletionRecords","completionRecordForSwitch","cases","lastNormalCompletions","i","length","casePath","caseCompletions","normalCompletions","breakCompletions","c","normalCompletionToBreak","completions","forEach","replaceBreakStatementInBreakCompletion","reachable","isBreakStatement","label","replaceWith","remove","getStatementListCompletion","paths","canHaveBreak","newContext","Object","assign","inCaseClause","isBlockStatement","shouldPopulateBreak","statementCompletions","every","some","isDeclaration","shouldPreserveBreak","pathCompletions","isVariableDeclaration","isEmptyStatement","isIfStatement","get","isDoExpression","isFor","isWhile","isLabeledStatement","isProgram","isFunction","isTryStatement","isCatchClause","isSwitchStatement","isSwitchCase","getCompletionRecords","map","r","NodePath","parentPath","parent","container","listKey","setContext","getPrevSibling","getNextSibling","getAllNextSiblings","_key","sibling","siblings","node","getAllPrevSiblings","parts","split","_getKey","call","_getPattern","Array","isArray","_","part","duplicates","getBindingIdentifierPaths","outerOnly","search","ids","create","id","shift","keys","isIdentifier","_ids","name","isExportDeclaration","declaration","isFunctionDeclaration","isFunctionExpression","child","getOuterBindingIdentifierPaths"],"sources":["../../src/path/family.ts"],"sourcesContent":["// This file contains methods responsible for dealing with/retrieving children or siblings.\n\nimport type TraversalContext from \"../context.ts\";\nimport NodePath from \"./index.ts\";\nimport {\n getAssignmentIdentifiers as _getAssignmentIdentifiers,\n getBindingIdentifiers as _getBindingIdentifiers,\n getOuterBindingIdentifiers as _getOuterBindingIdentifiers,\n numericLiteral,\n unaryExpression,\n} from \"@babel/types\";\nimport type * as t from \"@babel/types\";\n\nconst NORMAL_COMPLETION = 0;\nconst BREAK_COMPLETION = 1;\n\ntype Completion = {\n path: NodePath;\n type: 0 | 1;\n};\n\ntype CompletionContext = {\n // whether the current context allows `break` statement. When it allows, we have\n // to search all the statements for potential `break`\n canHaveBreak: boolean;\n // whether the statement is an immediate descendant of a switch case clause\n inCaseClause: boolean;\n // whether the `break` statement record should be populated to upper level\n // when a `break` statement is an immediate descendant of a block statement, e.g.\n // `{ break }`, it can influence the control flow in the upper levels.\n shouldPopulateBreak: boolean;\n // Whether the `break` statement should be preserved.\n shouldPreserveBreak: boolean;\n};\n\nfunction NormalCompletion(path: NodePath): Completion {\n return { type: NORMAL_COMPLETION, path };\n}\n\nfunction BreakCompletion(path: NodePath): Completion {\n return { type: BREAK_COMPLETION, path };\n}\n\nexport function getOpposite(this: NodePath): NodePath | null {\n if (this.key === \"left\") {\n return this.getSibling(\"right\");\n } else if (this.key === \"right\") {\n return this.getSibling(\"left\");\n }\n return null;\n}\n\nfunction addCompletionRecords(\n path: NodePath<t.Node | null> | null | undefined,\n records: Completion[],\n context: CompletionContext,\n): Completion[] {\n if (path) {\n // @ts-expect-error FIXME: NodePath<null>\n records.push(..._getCompletionRecords(path, context));\n }\n return records;\n}\n\nfunction completionRecordForSwitch(\n cases: NodePath<t.SwitchCase>[],\n records: Completion[],\n context: CompletionContext,\n): Completion[] {\n // https://tc39.es/ecma262/#sec-runtime-semantics-caseblockevaluation\n let lastNormalCompletions: Completion[] = [];\n for (let i = 0; i < cases.length; i++) {\n const casePath = cases[i];\n const caseCompletions = _getCompletionRecords(casePath, context);\n const normalCompletions = [];\n const breakCompletions = [];\n for (const c of caseCompletions) {\n if (c.type === NORMAL_COMPLETION) {\n normalCompletions.push(c);\n }\n if (c.type === BREAK_COMPLETION) {\n breakCompletions.push(c);\n }\n }\n if (normalCompletions.length) {\n lastNormalCompletions = normalCompletions;\n }\n records.push(...breakCompletions);\n }\n records.push(...lastNormalCompletions);\n return records;\n}\n\nfunction normalCompletionToBreak(completions: Completion[]) {\n completions.forEach(c => {\n c.type = BREAK_COMPLETION;\n });\n}\n\n/**\n * Determine how we should handle the break statement for break completions\n *\n * @param {Completion[]} completions\n * @paraLine truncated
|
||||
+288
@@ -0,0 +1,288 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = exports.SHOULD_STOP = exports.SHOULD_SKIP = exports.REMOVED = void 0;
|
||||
var virtualTypes = require("./lib/virtual-types.js");
|
||||
var _debug = require("debug");
|
||||
var _index = require("../index.js");
|
||||
var _index2 = require("../scope/index.js");
|
||||
var _t = require("@babel/types");
|
||||
var t = _t;
|
||||
var cache = require("../cache.js");
|
||||
var _generator = require("@babel/generator");
|
||||
var NodePath_ancestry = require("./ancestry.js");
|
||||
var NodePath_inference = require("./inference/index.js");
|
||||
var NodePath_replacement = require("./replacement.js");
|
||||
var NodePath_evaluation = require("./evaluation.js");
|
||||
var NodePath_conversion = require("./conversion.js");
|
||||
var NodePath_introspection = require("./introspection.js");
|
||||
var _context = require("./context.js");
|
||||
var NodePath_context = _context;
|
||||
var NodePath_removal = require("./removal.js");
|
||||
var NodePath_modification = require("./modification.js");
|
||||
var NodePath_family = require("./family.js");
|
||||
var NodePath_comments = require("./comments.js");
|
||||
var NodePath_virtual_types_validator = require("./lib/virtual-types-validator.js");
|
||||
const {
|
||||
validate
|
||||
} = _t;
|
||||
const debug = _debug("babel");
|
||||
const REMOVED = exports.REMOVED = 1 << 0;
|
||||
const SHOULD_STOP = exports.SHOULD_STOP = 1 << 1;
|
||||
const SHOULD_SKIP = exports.SHOULD_SKIP = 1 << 2;
|
||||
const NodePath_Final = exports.default = class NodePath {
|
||||
constructor(hub, parent) {
|
||||
this.contexts = [];
|
||||
this.state = null;
|
||||
this._traverseFlags = 0;
|
||||
this.skipKeys = null;
|
||||
this.parentPath = null;
|
||||
this.container = null;
|
||||
this.listKey = null;
|
||||
this.key = null;
|
||||
this.node = null;
|
||||
this.type = null;
|
||||
this._store = null;
|
||||
this.parent = parent;
|
||||
this.hub = hub;
|
||||
this.data = null;
|
||||
this.context = null;
|
||||
this.scope = null;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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 = cache.getOrCreateCachedPaths(parent, parentPath);
|
||||
let path = paths.get(targetNode);
|
||||
if (!path) {
|
||||
path = new NodePath(hub, parent);
|
||||
if (targetNode) paths.set(targetNode, path);
|
||||
}
|
||||
_context.setup.call(path, parentPath, container, listKey, key);
|
||||
return path;
|
||||
}
|
||||
getScope(scope) {
|
||||
return this.isScope() ? new _index2.default(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) {
|
||||
(0, _index.default)(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 (0, _generator.default)(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: NodePath_ancestry.findParent,
|
||||
find: NodePath_ancestry.find,
|
||||
getFunctionParent: NodePath_ancestry.getFunctionParent,
|
||||
getStatementParent: NodePath_ancestry.getStatementParent,
|
||||
getEarliestCommonAncestorFrom: NodePath_ancestry.getEarliestCommonAncestorFrom,
|
||||
getDeepestCommonAncestorFrom: NodePath_ancestry.getDeepestCommonAncestorFrom,
|
||||
getAncestry: NodePath_ancestry.getAncestry,
|
||||
isAncestor: NodePath_ancestry.isAncestor,
|
||||
isDescendant: NodePath_ancestry.isDescendant,
|
||||
inType: NodePath_ancestry.inType,
|
||||
getTypeAnnotation: NodePath_inference.getTypeAnnotation,
|
||||
isBaseType: NodePath_inference.isBaseType,
|
||||
couldBeBaseType: NodePath_inference.couldBeBaseType,
|
||||
baseTypeStrictlyMatches: NodePath_inference.baseTypeStrictlyMatches,
|
||||
isGenericType: NodePath_inference.isGenericType,
|
||||
replaceWithMultiple: NodePath_replacement.replaceWithMultiple,
|
||||
replaceWithSourceString: NodePath_replacement.replaceWithSourceString,
|
||||
replaceWith: NodePath_replacement.replaceWith,
|
||||
replaceExpressionWithStatements: NodePath_replacement.replaceExpressionWithStatements,
|
||||
replaceInline: NodePath_replacement.replaceInline,
|
||||
evaluateTruthy: NodePath_evaluation.evaluateTruthy,
|
||||
evaluate: NodePath_evaluation.evaluate,
|
||||
toComputedKey: NodePath_conversion.toComputedKey,
|
||||
ensureBlock: NodePath_conversion.ensureBlock,
|
||||
unwrapFunctionEnvironment: NodePath_conversion.unwrapFunctionEnvironment,
|
||||
arrowFunctionToExpression: NodePath_conversion.arrowFunctionToExpression,
|
||||
splitExportDeclaration: NodePath_conversion.splitExportDeclaration,
|
||||
ensureFunctionName: NodePath_conversion.ensureFunctionName,
|
||||
matchesPattern: NodePath_introspection.matchesPattern,
|
||||
isStatic: NodePath_introspection.isStatic,
|
||||
isNodeType: NodePath_introspection.isNodeType,
|
||||
canHaveVariableDeclarationOrExpression: NodePath_introspection.canHaveVariableDeclarationOrExpression,
|
||||
canSwapBetweenExpressionAndStatement: NodePath_introspection.canSwapBetweenExpressionAndStatement,
|
||||
isCompletionRecord: NodePath_introspection.isCompletionRecord,
|
||||
isStatementOrBlock: NodePath_introspection.isStatementOrBlock,
|
||||
referencesImport: NodePath_introspection.referencesImport,
|
||||
getSource: NodePath_introspection.getSource,
|
||||
willIMaybeExecuteBefore: NodePath_introspection.willIMaybeExecuteBefore,
|
||||
_guessExecutionStatusRelativeTo: NodePath_introspection._guessExecutionStatusRelativeTo,
|
||||
resolve: NodePath_introspection.resolve,
|
||||
isConstantExpression: NodePath_introspection.isConstantExpression,
|
||||
isInStrictMode: NodePath_introspection.isInStrictMode,
|
||||
isDenylisted: NodePath_context.isDenylisted,
|
||||
visit: NodePath_context.visit,
|
||||
skip: NodePath_context.skip,
|
||||
skipKey: NodePath_context.skipKey,
|
||||
stop: NodePath_context.stop,
|
||||
setContext: NodePath_context.setContext,
|
||||
requeue: NodePath_context.requeue,
|
||||
requeueComputedKeyAndDecorators: NodePath_context.requeueComputedKeyAndDecorators,
|
||||
remove: NodePath_removal.remove,
|
||||
insertBefore: NodePath_modification.insertBefore,
|
||||
insertAfter: NodePath_modification.insertAfter,
|
||||
unshiftContainer: NodePath_modification.unshiftContainer,
|
||||
pushContainer: NodePath_modification.pushContainer,
|
||||
getOpposite: NodePath_family.getOpposite,
|
||||
getCompletionRecords: NodePath_family.getCompletionRecords,
|
||||
getSibling: NodePath_family.getSibling,
|
||||
getPrevSibling: NodePath_family.getPrevSibling,
|
||||
getNextSibling: NodePath_family.getNextSibling,
|
||||
getAllNextSiblings: NodePath_family.getAllNextSiblings,
|
||||
getAllPrevSiblings: NodePath_family.getAllPrevSiblings,
|
||||
get: NodePath_family.get,
|
||||
getAssignmentIdentifiers: NodePath_family.getAssignmentIdentifiers,
|
||||
getBindingIdentifiers: NodePath_family.getBindingIdentifiers,
|
||||
getOuterBindingIdentifiers: NodePath_family.getOuterBindingIdentifiers,
|
||||
getBindingIdentifierPaths: NodePath_family.getBindingIdentifierPaths,
|
||||
getOuterBindingIdentifierPaths: NodePath_family.getOuterBindingIdentifierPaths,
|
||||
shareCommentsWithSiblings: NodePath_comments.shareCommentsWithSiblings,
|
||||
addComment: NodePath_comments.addComment,
|
||||
addComments: NodePath_comments.addComments
|
||||
};
|
||||
Object.assign(NodePath_Final.prototype, methods);
|
||||
NodePath_Final.prototype.arrowFunctionToShadowed = NodePath_conversion[String("arrowFunctionToShadowed")];
|
||||
Object.assign(NodePath_Final.prototype, {
|
||||
has: NodePath_introspection[String("has")],
|
||||
is: NodePath_introspection[String("is")],
|
||||
isnt: NodePath_introspection[String("isnt")],
|
||||
equals: NodePath_introspection[String("equals")],
|
||||
hoist: NodePath_modification[String("hoist")],
|
||||
updateSiblingKeys: NodePath_modification.updateSiblingKeys,
|
||||
call: NodePath_context.call,
|
||||
isBlacklisted: NodePath_context[String("isBlacklisted")],
|
||||
setScope: NodePath_context.setScope,
|
||||
resync: NodePath_context.resync,
|
||||
popContext: NodePath_context.popContext,
|
||||
pushContext: NodePath_context.pushContext,
|
||||
setup: NodePath_context.setup,
|
||||
setKey: NodePath_context.setKey
|
||||
});
|
||||
NodePath_Final.prototype._guessExecutionStatusRelativeToDifferentFunctions = NodePath_introspection._guessExecutionStatusRelativeTo;
|
||||
NodePath_Final.prototype._guessExecutionStatusRelativeToDifferentFunctions = NodePath_introspection._guessExecutionStatusRelativeTo;
|
||||
Object.assign(NodePath_Final.prototype, {
|
||||
_getTypeAnnotation: NodePath_inference._getTypeAnnotation,
|
||||
_replaceWith: NodePath_replacement._replaceWith,
|
||||
_resolve: NodePath_introspection._resolve,
|
||||
_call: NodePath_context._call,
|
||||
_resyncParent: NodePath_context._resyncParent,
|
||||
_resyncKey: NodePath_context._resyncKey,
|
||||
_resyncList: NodePath_context._resyncList,
|
||||
_resyncRemoved: NodePath_context._resyncRemoved,
|
||||
_getQueueContexts: NodePath_context._getQueueContexts,
|
||||
_removeFromScope: NodePath_removal._removeFromScope,
|
||||
_callRemovalHooks: NodePath_removal._callRemovalHooks,
|
||||
_remove: NodePath_removal._remove,
|
||||
_markRemoved: NodePath_removal._markRemoved,
|
||||
_assertUnremoved: NodePath_removal._assertUnremoved,
|
||||
_containerInsert: NodePath_modification._containerInsert,
|
||||
_containerInsertBefore: NodePath_modification._containerInsertBefore,
|
||||
_containerInsertAfter: NodePath_modification._containerInsertAfter,
|
||||
_verifyNodeList: NodePath_modification._verifyNodeList,
|
||||
_getKey: NodePath_family._getKey,
|
||||
_getPattern: NodePath_family._getPattern
|
||||
});
|
||||
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);
|
||||
}
|
||||
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["virtualTypes","require","_debug","_index","_index2","_t","t","cache","_generator","NodePath_ancestry","NodePath_inference","NodePath_replacement","NodePath_evaluation","NodePath_conversion","NodePath_introspection","_context","NodePath_context","NodePath_removal","NodePath_modification","NodePath_family","NodePath_comments","NodePath_virtual_types_validator","validate","debug","buildDebug","REMOVED","exports","SHOULD_STOP","SHOULD_SKIP","NodePath_Final","default","NodePath","constructor","hub","parent","contexts","state","_traverseFlags","skipKeys","parentPath","container","listKey","key","node","type","_store","data","context","scope","removed","v","shouldStop","shouldSkip","get","Error","targetNode","paths","getOrCreateCachedPaths","path","set","setup","call","getScope","isScope","Scope","setData","val","Object","create","getData","def","undefined","hasNode","buildCodeFrameError","msg","SyntaxError","buildError","traverse","visitor","getPathLocation","parts","inList","unshift","join","message","enabled","toString","generator","code","parentKey","methods","findParent","find","getFunctionParent","getStatementParent","getEarliestCommonAncestorFrom","getDeepestCommonAncestorFrom","getAncestry","isAncestor","isDescendant","inType","getTypeAnnotation","isBaseType","couldBeBaseType","baseTypeStrictlyMatches","isGenericType","replaceWithMultiple","replaceWithSourceString","replaceWith","replaceExpressionWithStatements","replaceInline","evaluateTruthy","evaluate","toComputedKey","ensureBlock","unwrapFunctionEnvironment","arrowFunctionToExpression","splitExportDeclaration","ensureFunctionName","matchesPattern","isStatic","isNodeType","canHaveVariableDeclarationOrExpression","canSwapBetweenExpressionAndStatement","isCompletionRecord","isStatementOrBlock","referencesImport","getSource","willIMaybeExecuteBefore","_guessExecutionStatusRelativeTo","resolve","isConstantExpression","isInStrictMode","isDenylisted","visit","skip","skipKey","stop","setContext","requeue","requeueComputedKeyAndDecorators","remove","insertBefore","insertAfter","unshiftContainer","pushContainer","getOpposite","getCompletionRecords","getSibling","getPrevSibling","getNextSibling","getAllNextSiblings","getAllPrevSiblings","getAssignmentIdentifiers","getBindingIdentifiers","getOuterBindingIdentifiers","getBindingIdentifierPaths","getOuterBindingIdentifierPaths","shareCommentsWithSiblings","addComment","addComments","assign","prototype","arrowFunctionToShadowed","String","has","is","isnt","equals","hoist","updateSiblingKeys","isBlacklisted","setScope","resync","popContext","pushContext","setKey","_guessExecutionStatusRelativeToDifferentFunctions","_getTypeAnnotation","_replaceWith","_resolve","_call","_resyncParent","_resyncKey","_resyncList","_resyncRemoved","_getQueueContexts","_removeFromScope","_callRemovalHooks","_remove","_markRemoved","_assertUnremoved","_containerInsert","_containerInsertBefore","_containerInsertAfter","_verifyNodeList","_getKey","_getPattern","TYPES","typeKey","fn","opts","TypeError","keys","startsWith","includes","push"],"sources":["../../src/path/index.ts"],"sourcesContent":["import type { HubInterface } from \"../hub.ts\";\nimport type TraversalContext from \"../context.ts\";\nimport type { ExplodedTraverseOptions } from \"../index.ts\";\nimport * as virtualTypes from \"./lib/virtual-types.ts\";\nimport buildDebug from \"debug\";\nimport traverse from \"../index.ts\";\nimport type { Visitor } from \"../types.ts\";\nimport Scope from \"../scope/index.ts\";\nimport { validate } from \"@babel/types\";\nimport * as t from \"@babel/types\";\nimport * as cache from \"../cache.ts\";\nimport generator from \"@babel/generator\";\n\n// NodePath is split across many files.\nimport * as NodePath_ancestry from \"./ancestry.ts\";\nimport * as NodePath_inference from \"./inference/index.ts\";\nimport * as NodePath_replacement from \"./replacement.ts\";\nimport * as NodePath_evaluation from \"./evaluation.ts\";\nimport * as NodePath_conversion from \"./conversion.ts\";\nimport * as NodePath_introspection from \"./introspection.ts\";\nimport * as NodePath_context from \"./context.ts\";\nimport * as NodePath_removal from \"./removal.ts\";\nimport * as NodePath_modification from \"./modification.ts\";\nimport * as NodePath_family from \"./family.ts\";\nimport * as NodePath_comments from \"./comments.ts\";\nimport * as NodePath_virtual_types_validator from \"./lib/virtual-types-validator.ts\";\nimport type { NodePathAssertions } from \"./generated/asserts.ts\";\nimport type { NodePathValidators } from \"./generated/validators.ts\";\nimport { setup } from \"./context.ts\";\n\nconst debug = buildDebug(\"babel\");\n\nexport const REMOVED = 1 << 0;\nexport const SHOULD_STOP = 1 << 1;\nexport const SHOULD_SKIP = 1 << 2;\n\ndeclare const bit: import(\"../../../../scripts/babel-plugin-bit-decorator/types.d.ts\").BitDecorator<\n NodePath_Final<t.Node>\n>;\n\nexport type NodePaths<T extends t.Node | t.Node[]> = T extends t.NoLine truncated
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports._getTypeAnnotation = _getTypeAnnotation;
|
||||
exports.baseTypeStrictlyMatches = baseTypeStrictlyMatches;
|
||||
exports.couldBeBaseType = couldBeBaseType;
|
||||
exports.getTypeAnnotation = getTypeAnnotation;
|
||||
exports.isBaseType = isBaseType;
|
||||
exports.isGenericType = isGenericType;
|
||||
var inferers = require("./inferers.js");
|
||||
var _t = require("@babel/types");
|
||||
const {
|
||||
anyTypeAnnotation,
|
||||
isAnyTypeAnnotation,
|
||||
isArrayTypeAnnotation,
|
||||
isBooleanTypeAnnotation,
|
||||
isEmptyTypeAnnotation,
|
||||
isFlowBaseAnnotation,
|
||||
isGenericTypeAnnotation,
|
||||
isIdentifier,
|
||||
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 {
|
||||
var _inferer;
|
||||
let inferer = inferers[node.type];
|
||||
if (inferer) {
|
||||
return inferer.call(this, node);
|
||||
}
|
||||
inferer = inferers[this.parentPath.type];
|
||||
if ((_inferer = inferer) != null && _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(type.id, {
|
||||
name: genericName
|
||||
}) || isTSTypeReference(type) && isIdentifier(type.typeName, {
|
||||
name: genericName
|
||||
});
|
||||
}
|
||||
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["inferers","require","_t","anyTypeAnnotation","isAnyTypeAnnotation","isArrayTypeAnnotation","isBooleanTypeAnnotation","isEmptyTypeAnnotation","isFlowBaseAnnotation","isGenericTypeAnnotation","isIdentifier","isMixedTypeAnnotation","isNumberTypeAnnotation","isStringTypeAnnotation","isTSArrayType","isTSTypeAnnotation","isTSTypeReference","isTupleTypeAnnotation","isTypeAnnotation","isUnionTypeAnnotation","isVoidTypeAnnotation","stringTypeAnnotation","voidTypeAnnotation","getTypeAnnotation","type","getData","_getTypeAnnotation","call","typeAnnotation","setData","typeAnnotationInferringNodes","WeakSet","node","key","parentPath","isVariableDeclarator","declar","declarParent","isForInStatement","isForOfStatement","has","add","_inferer","inferer","validParent","delete","isBaseType","baseName","soft","_isBaseType","Error","couldBeBaseType","name","type2","types","baseTypeStrictlyMatches","rightArg","left","right","isGenericType","genericName","id","typeName"],"sources":["../../../src/path/inference/index.ts"],"sourcesContent":["import type NodePath from \"../index.ts\";\nimport * as inferers from \"./inferers.ts\";\nimport {\n anyTypeAnnotation,\n isAnyTypeAnnotation,\n isArrayTypeAnnotation,\n isBooleanTypeAnnotation,\n isEmptyTypeAnnotation,\n isFlowBaseAnnotation,\n isGenericTypeAnnotation,\n isIdentifier,\n isMixedTypeAnnotation,\n isNumberTypeAnnotation,\n isStringTypeAnnotation,\n isTSArrayType,\n isTSTypeAnnotation,\n isTSTypeReference,\n isTupleTypeAnnotation,\n isTypeAnnotation,\n isUnionTypeAnnotation,\n isVoidTypeAnnotation,\n stringTypeAnnotation,\n voidTypeAnnotation,\n} from \"@babel/types\";\nimport type * as t from \"@babel/types\";\n\n/**\n * Infer the type of the current `NodePath`.\n */\n\nexport function getTypeAnnotation(\n this: NodePath<t.Node | null>,\n): t.FlowType | t.TSType {\n let type = this.getData(\"typeAnnotation\");\n if (type != null) {\n return type;\n }\n type = _getTypeAnnotation.call(this) || anyTypeAnnotation();\n if (isTypeAnnotation(type) || isTSTypeAnnotation(type)) {\n type = type.typeAnnotation;\n }\n this.setData(\"typeAnnotation\", type);\n return type;\n}\n\n// Used to avoid infinite recursion in cases like\n// var b, c; if (0) { c = 1; b = c; } c = b;\n// It also works with indirect recursion.\nconst typeAnnotationInferringNodes = new WeakSet();\n\n/**\n * todo: split up this method\n */\n\nexport function _getTypeAnnotation(this: NodePath): any {\n const node = this.node;\n\n if (!node) {\n // handle initializerless variables, add in checks for loop initializers too\n if (this.key === \"init\" && this.parentPath.isVariableDeclarator()) {\n const declar = this.parentPath.parentPath;\n const declarParent = declar.parentPath;\n\n // for (let NODE in bar) {}\n if (declar.key === \"left\" && declarParent.isForInStatement()) {\n return stringTypeAnnotation();\n }\n\n // for (let NODE of bar) {}\n if (declar.key === \"left\" && declarParent.isForOfStatement()) {\n return anyTypeAnnotation();\n }\n\n return voidTypeAnnotation();\n } else {\n return;\n }\n }\n\n // @ts-expect-error typeAnnotation may not index node\n if (node.typeAnnotation) {\n // @ts-expect-error typeAnnotation may not index node\n return node.typeAnnotation;\n }\n\n if (typeAnnotationInferringNodes.has(node)) {\n // Bail out from type inference to avoid infinite loops\n return;\n }\n typeAnnotationInferringNodes.add(node);\n\n try {\n let inferer =\n // @ts-expect-error inferers do not cover all AST types\n inferers[node.type];\n if (inferer) {\n return inferer.call(this, node);\n }\n\n // @ts-expect-error inferers do not cover all AST types\n inferer = inferers[this.parentPath.type];\n if (inferer?.validParent) {\n return this.parentPath.getTypeAnnotation();\n }\n } finally {\n typeAnnotationInferringNodes.delete(node);\n }\n}\n\nexport function isBaseType(\n this: NodePath,\n baseName: string,\n soft?: boolean,\n): boolean {\n return _isBaseType(baseName, this.getTypeAnnotation(), soft);\n}\n\nfunction _isBaseType(\n baseName: string,\n type?: t.FlowType | t.TSType,\n soft?: boolean,\n): boolean {\n if (baseName === \"string\") {\n return isStringTypeAnnotation(type);\n } else if (baseName === \"number\") {\n return isNumberTypeAnnotation(type);\n } else if (baseName === \"boolean\") {\n return isBooleanTypeAnnotation(type);\n } else if (baseName === \"any\") {\n return isAnyTypeAnnotation(type);\n } else if (baseName === \"mixed\") {\n return isMixedTypeAnnotation(type);\n } else if (baseName === \"empty\") {\n return isEmptyTypeAnnotation(type);\n } else if (baseName === \"void\") {\n return isVoidTypeAnnotation(type);\n } else {\n if (soft) {\n return false;\n } else {\n throw new Error(`Unknown base type ${baseName}`);\n }\n }\n}\n\nexport functioLine truncated
|
||||
+151
@@ -0,0 +1,151 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = _default;
|
||||
var _t = require("@babel/types");
|
||||
var _util = require("./util.js");
|
||||
const {
|
||||
BOOLEAN_NUMBER_BINARY_OPERATORS,
|
||||
createTypeAnnotationBasedOnTypeof,
|
||||
numberTypeAnnotation,
|
||||
voidTypeAnnotation
|
||||
} = _t;
|
||||
function _default(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();
|
||||
} else if (node.name === "NaN" || node.name === "Infinity") {
|
||||
return numberTypeAnnotation();
|
||||
} 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 (0, _util.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();
|
||||
}
|
||||
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: (0, _util.createUnionType)(types),
|
||||
ifStatement
|
||||
};
|
||||
}
|
||||
return getConditionalAnnotation(binding, ifStatement, name);
|
||||
}
|
||||
|
||||
//# sourceMappingURL=inferer-reference.js.map
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_t","require","_util","BOOLEAN_NUMBER_BINARY_OPERATORS","createTypeAnnotationBasedOnTypeof","numberTypeAnnotation","voidTypeAnnotation","_default","node","isReferenced","binding","scope","getBinding","name","identifier","typeAnnotation","getTypeAnnotationBindingConstantViolations","path","types","functionConstantViolations","constantViolations","getConstantViolationsBefore","testType","getConditionalAnnotation","testConstantViolations","ifStatement","filter","includes","push","length","violation","getTypeAnnotation","createUnionType","functions","violations","slice","unshift","resolve","status","_guessExecutionStatusRelativeTo","inferAnnotationFromBinaryExpression","operator","right","get","left","target","isIdentifier","typeofPath","typePath","isUnaryExpression","isLiteral","typeValue","value","getParentConditionalPath","parentPath","isIfStatement","isConditionalExpression","key","isFunction","test","paths","i","isLogicalExpression","isBinaryExpression","type"],"sources":["../../../src/path/inference/inferer-reference.ts"],"sourcesContent":["import type NodePath from \"../index.ts\";\nimport {\n BOOLEAN_NUMBER_BINARY_OPERATORS,\n createTypeAnnotationBasedOnTypeof,\n numberTypeAnnotation,\n voidTypeAnnotation,\n} from \"@babel/types\";\nimport type * as t from \"@babel/types\";\nimport type Binding from \"../../scope/binding.ts\";\n\nimport { createUnionType } from \"./util.ts\";\n\nexport default function (this: NodePath<t.Identifier>, node: t.Identifier) {\n if (!this.isReferenced()) return;\n\n // check if a binding exists of this value and if so then return a union type of all\n // possible types that the binding could be\n const binding = this.scope.getBinding(node.name);\n if (binding) {\n if (binding.identifier.typeAnnotation) {\n return binding.identifier.typeAnnotation;\n } else {\n return getTypeAnnotationBindingConstantViolations(\n binding,\n this,\n node.name,\n );\n }\n }\n\n // built-in values\n if (node.name === \"undefined\") {\n return voidTypeAnnotation();\n } else if (node.name === \"NaN\" || node.name === \"Infinity\") {\n return numberTypeAnnotation();\n } else if (node.name === \"arguments\") {\n // todo\n }\n}\n\nfunction getTypeAnnotationBindingConstantViolations(\n binding: Binding,\n path: NodePath<t.Identifier>,\n name: string,\n) {\n const types = [];\n\n const functionConstantViolations: NodePath[] = [];\n let constantViolations = getConstantViolationsBefore(\n binding,\n path,\n functionConstantViolations,\n );\n\n const testType = getConditionalAnnotation(binding, path, name);\n if (testType) {\n const testConstantViolations = getConstantViolationsBefore(\n binding,\n testType.ifStatement,\n );\n\n // remove constant violations observed before the IfStatement\n constantViolations = constantViolations.filter(\n path => !testConstantViolations.includes(path),\n );\n\n // clear current types and add in observed test type\n types.push(testType.typeAnnotation);\n }\n\n if (constantViolations.length) {\n // pick one constant from each scope which will represent the last possible\n // control flow path that it could've taken/been\n /* This code is broken for the following problems:\n * It thinks that assignments can only happen in scopes.\n * What about conditionals, if statements without block,\n * or guarded assignments.\n * It also checks to see if one of the assignments is in the\n * same scope and uses that as the only \"violation\". However,\n * the binding is returned by `getConstantViolationsBefore` so we for\n * sure always going to return that as the only \"violation\".\n let rawConstantViolations = constantViolations.reverse();\n let visitedScopes = [];\n constantViolations = [];\n for (let violation of (rawConstantViolations: Array<NodePath>)) {\n let violationScope = violation.scope;\n if (visitedScopes.indexOf(violationScope) >= 0) continue;\n\n visitedScopes.push(violationScope);\n constantViolations.push(violation);\n\n if (violationScope === path.scope) {\n constantViolations = [violation];\n break;\n }\n }*/\n\n // add back on function constant violations since we can't track calls\n constantViolations.push(...functionConstantViolations);\n\n // push on inferred types of violated paths\n for (const violation of constantViolations) {\n types.push(violation.getTypeAnnotation());\n }\n }\n\n if (!types.length) {\n return;\n }\n\n return createUnionType(types);\n}\n\nfunction getConstantViolationsBefore(\n binding: Binding,\n path: NodePath,\n functions?: NodePath[],\n) {\n const violations = binding.constantViolations.slice();\n violations.unshift(binding.path);\n return violations.filter(violation => {\n violation = violation.resolve();\n const status = violation._guessExecutionStatusRelaLine truncated
|
||||
+207
@@ -0,0 +1,207 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.ArrayExpression = ArrayExpression;
|
||||
exports.AssignmentExpression = AssignmentExpression;
|
||||
exports.BinaryExpression = BinaryExpression;
|
||||
exports.BooleanLiteral = BooleanLiteral;
|
||||
exports.CallExpression = CallExpression;
|
||||
exports.ConditionalExpression = ConditionalExpression;
|
||||
exports.ClassDeclaration = exports.ClassExpression = exports.FunctionDeclaration = exports.ArrowFunctionExpression = exports.FunctionExpression = Func;
|
||||
Object.defineProperty(exports, "Identifier", {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return _infererReference.default;
|
||||
}
|
||||
});
|
||||
exports.LogicalExpression = LogicalExpression;
|
||||
exports.NewExpression = NewExpression;
|
||||
exports.NullLiteral = NullLiteral;
|
||||
exports.NumericLiteral = NumericLiteral;
|
||||
exports.ObjectExpression = ObjectExpression;
|
||||
exports.ParenthesizedExpression = ParenthesizedExpression;
|
||||
exports.RegExpLiteral = RegExpLiteral;
|
||||
exports.RestElement = RestElement;
|
||||
exports.SequenceExpression = SequenceExpression;
|
||||
exports.StringLiteral = StringLiteral;
|
||||
exports.TSAsExpression = TSAsExpression;
|
||||
exports.TSNonNullExpression = TSNonNullExpression;
|
||||
exports.TaggedTemplateExpression = TaggedTemplateExpression;
|
||||
exports.TemplateLiteral = TemplateLiteral;
|
||||
exports.TypeCastExpression = TypeCastExpression;
|
||||
exports.UnaryExpression = UnaryExpression;
|
||||
exports.UpdateExpression = UpdateExpression;
|
||||
exports.VariableDeclarator = VariableDeclarator;
|
||||
var _t = require("@babel/types");
|
||||
var _infererReference = require("./inferer-reference.js");
|
||||
var _util = require("./util.js");
|
||||
const {
|
||||
BOOLEAN_BINARY_OPERATORS,
|
||||
BOOLEAN_UNARY_OPERATORS,
|
||||
NUMBER_BINARY_OPERATORS,
|
||||
NUMBER_UNARY_OPERATORS,
|
||||
STRING_UNARY_OPERATORS,
|
||||
anyTypeAnnotation,
|
||||
arrayTypeAnnotation,
|
||||
booleanTypeAnnotation,
|
||||
buildMatchMemberExpression,
|
||||
genericTypeAnnotation,
|
||||
identifier,
|
||||
nullLiteralTypeAnnotation,
|
||||
numberTypeAnnotation,
|
||||
stringTypeAnnotation,
|
||||
tupleTypeAnnotation,
|
||||
unionTypeAnnotation,
|
||||
voidTypeAnnotation,
|
||||
isIdentifier
|
||||
} = _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();
|
||||
}
|
||||
function UnaryExpression(node) {
|
||||
const operator = node.operator;
|
||||
if (operator === "void") {
|
||||
return voidTypeAnnotation();
|
||||
} else if (NUMBER_UNARY_OPERATORS.includes(operator)) {
|
||||
return numberTypeAnnotation();
|
||||
} else if (STRING_UNARY_OPERATORS.includes(operator)) {
|
||||
return stringTypeAnnotation();
|
||||
} 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();
|
||||
}
|
||||
return unionTypeAnnotation([stringTypeAnnotation(), numberTypeAnnotation()]);
|
||||
}
|
||||
}
|
||||
function LogicalExpression() {
|
||||
const argumentTypes = [this.get("left").getTypeAnnotation(), this.get("right").getTypeAnnotation()];
|
||||
return (0, _util.createUnionType)(argumentTypes);
|
||||
}
|
||||
function ConditionalExpression() {
|
||||
const argumentTypes = [this.get("consequent").getTypeAnnotation(), this.get("alternate").getTypeAnnotation()];
|
||||
return (0, _util.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();
|
||||
}
|
||||
function NumericLiteral() {
|
||||
return numberTypeAnnotation();
|
||||
}
|
||||
function BooleanLiteral() {
|
||||
return booleanTypeAnnotation();
|
||||
}
|
||||
function NullLiteral() {
|
||||
return nullLiteralTypeAnnotation();
|
||||
}
|
||||
function RegExpLiteral() {
|
||||
return genericTypeAnnotation(identifier("RegExp"));
|
||||
}
|
||||
function ObjectExpression() {
|
||||
return genericTypeAnnotation(identifier("Object"));
|
||||
}
|
||||
function ArrayExpression() {
|
||||
return genericTypeAnnotation(identifier("Array"));
|
||||
}
|
||||
function RestElement() {
|
||||
return ArrayExpression();
|
||||
}
|
||||
RestElement.validParent = true;
|
||||
function Func() {
|
||||
return genericTypeAnnotation(identifier("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());
|
||||
} else if (isArrayFrom(callee) || isObjectValues(callee) || isIdentifier(callee, {
|
||||
name: "Array"
|
||||
})) {
|
||||
return arrayTypeAnnotation(anyTypeAnnotation());
|
||||
} else if (isObjectEntries(callee)) {
|
||||
return arrayTypeAnnotation(tupleTypeAnnotation([stringTypeAnnotation(), anyTypeAnnotation()]));
|
||||
}
|
||||
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("AsyncIterator"));
|
||||
} else {
|
||||
return genericTypeAnnotation(identifier("Promise"));
|
||||
}
|
||||
} else {
|
||||
if (node.generator) {
|
||||
return genericTypeAnnotation(identifier("Iterator"));
|
||||
} else if (callee.node.returnType) {
|
||||
return callee.node.returnType;
|
||||
} else {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//# sourceMappingURL=inferers.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_t","require","_infererReference","_util","BOOLEAN_BINARY_OPERATORS","BOOLEAN_UNARY_OPERATORS","NUMBER_BINARY_OPERATORS","NUMBER_UNARY_OPERATORS","STRING_UNARY_OPERATORS","anyTypeAnnotation","arrayTypeAnnotation","booleanTypeAnnotation","buildMatchMemberExpression","genericTypeAnnotation","identifier","nullLiteralTypeAnnotation","numberTypeAnnotation","stringTypeAnnotation","tupleTypeAnnotation","unionTypeAnnotation","voidTypeAnnotation","isIdentifier","VariableDeclarator","get","getTypeAnnotation","TypeCastExpression","node","typeAnnotation","validParent","TSAsExpression","TSNonNullExpression","NewExpression","callee","type","TemplateLiteral","UnaryExpression","operator","includes","BinaryExpression","right","left","isBaseType","LogicalExpression","argumentTypes","createUnionType","ConditionalExpression","SequenceExpression","pop","ParenthesizedExpression","AssignmentExpression","UpdateExpression","StringLiteral","NumericLiteral","BooleanLiteral","NullLiteral","RegExpLiteral","ObjectExpression","ArrayExpression","RestElement","Func","isArrayFrom","isObjectKeys","isObjectValues","isObjectEntries","CallExpression","name","resolveCall","TaggedTemplateExpression","resolve","isFunction","async","generator","returnType"],"sources":["../../../src/path/inference/inferers.ts"],"sourcesContent":["import {\n BOOLEAN_BINARY_OPERATORS,\n BOOLEAN_UNARY_OPERATORS,\n NUMBER_BINARY_OPERATORS,\n NUMBER_UNARY_OPERATORS,\n STRING_UNARY_OPERATORS,\n anyTypeAnnotation,\n arrayTypeAnnotation,\n booleanTypeAnnotation,\n buildMatchMemberExpression,\n genericTypeAnnotation,\n identifier,\n nullLiteralTypeAnnotation,\n numberTypeAnnotation,\n stringTypeAnnotation,\n tupleTypeAnnotation,\n unionTypeAnnotation,\n voidTypeAnnotation,\n isIdentifier,\n} from \"@babel/types\";\nimport type * as t from \"@babel/types\";\n\nexport { default as Identifier } from \"./inferer-reference.ts\";\n\nimport { createUnionType } from \"./util.ts\";\nimport type NodePath from \"../index.ts\";\n\nexport function VariableDeclarator(this: NodePath<t.VariableDeclarator>) {\n if (!this.get(\"id\").isIdentifier()) return;\n return this.get(\"init\").getTypeAnnotation();\n}\n\nexport function TypeCastExpression(node: t.TypeCastExpression) {\n return node.typeAnnotation;\n}\n\nTypeCastExpression.validParent = true;\n\nexport function TSAsExpression(node: t.TSAsExpression) {\n return node.typeAnnotation;\n}\n\nTSAsExpression.validParent = true;\n\nexport function TSNonNullExpression(this: NodePath<t.TSNonNullExpression>) {\n return this.get(\"expression\").getTypeAnnotation();\n}\n\nexport function NewExpression(\n this: NodePath<t.NewExpression>,\n node: t.NewExpression,\n) {\n if (node.callee.type === \"Identifier\") {\n // only resolve identifier callee\n return genericTypeAnnotation(node.callee);\n }\n}\n\nexport function TemplateLiteral() {\n return stringTypeAnnotation();\n}\n\nexport function UnaryExpression(node: t.UnaryExpression) {\n const operator = node.operator;\n\n if (operator === \"void\") {\n return voidTypeAnnotation();\n } else if (NUMBER_UNARY_OPERATORS.includes(operator)) {\n return numberTypeAnnotation();\n } else if (STRING_UNARY_OPERATORS.includes(operator)) {\n return stringTypeAnnotation();\n } else if (BOOLEAN_UNARY_OPERATORS.includes(operator)) {\n return booleanTypeAnnotation();\n }\n}\n\nexport function BinaryExpression(\n this: NodePath<t.BinaryExpression>,\n node: t.BinaryExpression,\n) {\n const operator = node.operator;\n\n if (NUMBER_BINARY_OPERATORS.includes(operator)) {\n return numberTypeAnnotation();\n } else if (BOOLEAN_BINARY_OPERATORS.includes(operator)) {\n return booleanTypeAnnotation();\n } else if (operator === \"+\") {\n const right = this.get(\"right\");\n const left = this.get(\"left\");\n\n if (left.isBaseType(\"number\") && right.isBaseType(\"number\")) {\n // both numbers so this will be a number\n return numberTypeAnnotation();\n } else if (left.isBaseType(\"string\") || right.isBaseType(\"string\")) {\n // one is a string so the result will be a string\n return stringTypeAnnotation();\n }\n\n // unsure if left and right are strings or numbers so stay on the safe side\n return unionTypeAnnotation([\n stringTypeAnnotation(),\n numberTypeAnnotation(),\n ]);\n }\n}\n\nexport function LogicalExpression(this: NodePath<t.LogicalExpression>) {\n const argumentTypes = [\n this.get(\"left\").getTypeAnnotation(),\n this.get(\"right\").getTypeAnnotation(),\n ];\n\n return createUnionType(argumentTypes);\n}\n\nexport function ConditionalExpression(this: NodePath<t.ConditionalExpression>) {\n const argumentTypes = [\n this.get(\"consequent\").getTypeAnnotation(),\n this.get(\"alternate\").getTypeAnnotation(),\n ];\n\n return createUnionType(argumentTypes);\n}\n\nexport function SequenceExpression(this: NodePath<t.SequenceExpression>) {\n return this.get(\"expresLine truncated
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.createUnionType = createUnionType;
|
||||
var _t = require("@babel/types");
|
||||
const {
|
||||
createFlowUnionType,
|
||||
createTSUnionType,
|
||||
createUnionTypeAnnotation,
|
||||
isFlowType,
|
||||
isTSType
|
||||
} = _t;
|
||||
function createUnionType(types) {
|
||||
if (types.every(v => isFlowType(v))) {
|
||||
if (createFlowUnionType) {
|
||||
return createFlowUnionType(types);
|
||||
}
|
||||
return createUnionTypeAnnotation(types);
|
||||
} else if (types.every(v => isTSType(v))) {
|
||||
if (createTSUnionType) {
|
||||
return createTSUnionType(types);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//# sourceMappingURL=util.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_t","require","createFlowUnionType","createTSUnionType","createUnionTypeAnnotation","isFlowType","isTSType","createUnionType","types","every","v"],"sources":["../../../src/path/inference/util.ts"],"sourcesContent":["import {\n createFlowUnionType,\n createTSUnionType,\n createUnionTypeAnnotation,\n isFlowType,\n isTSType,\n} from \"@babel/types\";\nimport type * as t from \"@babel/types\";\n\nexport function createUnionType(\n types: (t.FlowType | t.TSType)[],\n): t.FlowType | t.TSType | undefined {\n if (process.env.BABEL_8_BREAKING) {\n if (types.every(v => isFlowType(v))) {\n return createFlowUnionType(types);\n }\n if (types.every(v => isTSType(v))) {\n return createTSUnionType(types);\n }\n } else {\n if (types.every(v => isFlowType(v))) {\n if (createFlowUnionType) {\n return createFlowUnionType(types);\n }\n\n return createUnionTypeAnnotation(types);\n } else if (types.every(v => isTSType(v))) {\n if (createTSUnionType) {\n return createTSUnionType(types);\n }\n }\n }\n}\n"],"mappings":";;;;;;AAAA,IAAAA,EAAA,GAAAC,OAAA;AAMsB;EALpBC,mBAAmB;EACnBC,iBAAiB;EACjBC,yBAAyB;EACzBC,UAAU;EACVC;AAAQ,IAAAN,EAAA;AAIH,SAASO,eAAeA,CAC7BC,KAAgC,EACG;EASjC,IAAIA,KAAK,CAACC,KAAK,CAACC,CAAC,IAAIL,UAAU,CAACK,CAAC,CAAC,CAAC,EAAE;IACnC,IAAIR,mBAAmB,EAAE;MACvB,OAAOA,mBAAmB,CAACM,KAAK,CAAC;IACnC;IAEA,OAAOJ,yBAAyB,CAACI,KAAK,CAAC;EACzC,CAAC,MAAM,IAAIA,KAAK,CAACC,KAAK,CAACC,CAAC,IAAIJ,QAAQ,CAACI,CAAC,CAAC,CAAC,EAAE;IACxC,IAAIP,iBAAiB,EAAE;MACrB,OAAOA,iBAAiB,CAACK,KAAK,CAAC;IACjC;EACF;AAEJ","ignoreList":[]}
|
||||
+395
@@ -0,0 +1,395 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports._guessExecutionStatusRelativeTo = _guessExecutionStatusRelativeTo;
|
||||
exports._resolve = _resolve;
|
||||
exports.canHaveVariableDeclarationOrExpression = canHaveVariableDeclarationOrExpression;
|
||||
exports.canSwapBetweenExpressionAndStatement = canSwapBetweenExpressionAndStatement;
|
||||
exports.getSource = getSource;
|
||||
exports.isCompletionRecord = isCompletionRecord;
|
||||
exports.isConstantExpression = isConstantExpression;
|
||||
exports.isInStrictMode = isInStrictMode;
|
||||
exports.isNodeType = isNodeType;
|
||||
exports.isStatementOrBlock = isStatementOrBlock;
|
||||
exports.isStatic = isStatic;
|
||||
exports.matchesPattern = matchesPattern;
|
||||
exports.referencesImport = referencesImport;
|
||||
exports.resolve = resolve;
|
||||
exports.willIMaybeExecuteBefore = willIMaybeExecuteBefore;
|
||||
var _t = require("@babel/types");
|
||||
const {
|
||||
STATEMENT_OR_BLOCK_KEYS,
|
||||
VISITOR_KEYS,
|
||||
isBlockStatement,
|
||||
isExpression,
|
||||
isIdentifier,
|
||||
isLiteral,
|
||||
isStringLiteral,
|
||||
isType,
|
||||
matchesPattern: _matchesPattern
|
||||
} = _t;
|
||||
function matchesPattern(pattern, allowPartial) {
|
||||
return _matchesPattern(this.node, pattern, allowPartial);
|
||||
}
|
||||
exports.has = function has(key) {
|
||||
var _this$node;
|
||||
const val = (_this$node = this.node) == null ? void 0 : _this$node[key];
|
||||
if (val && Array.isArray(val)) {
|
||||
return !!val.length;
|
||||
} else {
|
||||
return !!val;
|
||||
}
|
||||
};
|
||||
function isStatic() {
|
||||
return this.scope.isStatic(this.node);
|
||||
}
|
||||
exports.is = exports.has;
|
||||
exports.isnt = function isnt(key) {
|
||||
return !this.has(key);
|
||||
};
|
||||
exports.equals = function equals(key, value) {
|
||||
return this.node[key] === value;
|
||||
};
|
||||
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 == null ? void 0 : 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[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) {
|
||||
return _resolve.call(this, dangerous, resolved) || this;
|
||||
}
|
||||
function _resolve(dangerous, resolved) {
|
||||
var _resolved;
|
||||
if ((_resolved = resolved) != null && _resolved.includes(this)) return;
|
||||
resolved = resolved || [];
|
||||
resolved.push(this);
|
||||
if (this.isVariableDeclarator()) {
|
||||
if (this.get("id").isIdentifier()) {
|
||||
return this.get("init").resolve(dangerous, resolved);
|
||||
} else {}
|
||||
} else if (this.isReferencedIdentifier()) {
|
||||
const binding = this.scope.getBinding(this.node.name);
|
||||
if (!binding) return;
|
||||
if (!binding.constant) return;
|
||||
if (binding.kind === "module") return;
|
||||
if (binding.path !== this) {
|
||||
const ret = binding.path.resolve(dangerous, resolved);
|
||||
if (this.find(parent => parent.node === ret.node)) return;
|
||||
return ret;
|
||||
}
|
||||
} else if (this.isTypeCastExpression()) {
|
||||
return this.get("expression").resolve(dangerous, resolved);
|
||||
} else if (dangerous && this.isMemberExpression()) {
|
||||
const targetKey = this.toComputedKey();
|
||||
if (!isLiteral(targetKey)) return;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=introspection.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_t","require","STATEMENT_OR_BLOCK_KEYS","VISITOR_KEYS","isBlockStatement","isExpression","isIdentifier","isLiteral","isStringLiteral","isType","matchesPattern","_matchesPattern","pattern","allowPartial","node","exports","has","key","_this$node","val","Array","isArray","length","isStatic","scope","is","isnt","equals","value","isNodeType","type","canHaveVariableDeclarationOrExpression","parentPath","isFor","canSwapBetweenExpressionAndStatement","replacement","isArrowFunctionExpression","isCompletionRecord","allowInsideFunction","path","first","container","isFunction","isProgram","isDoExpression","isStatementOrBlock","isLabeledStatement","includes","referencesImport","moduleSource","importName","isReferencedIdentifier","isJSXMemberExpression","property","name","isMemberExpression","isOptionalMemberExpression","computed","object","get","binding","getBinding","kind","parent","isImportDeclaration","source","isImportDefaultSpecifier","isImportNamespaceSpecifier","isImportSpecifier","imported","getSource","end","code","hub","getCode","slice","start","willIMaybeExecuteBefore","target","_guessExecutionStatusRelativeTo","getOuterFunction","getFunctionParent","getProgramParent","isExecutionUncertain","isExecutionUncertainInList","paths","maxIndex","i","parentKey","SYMBOL_CHECKING","Symbol","_guessExecutionStatusRelativeToCached","Map","base","cache","funcParent","this","_guessExecutionStatusRelativeToDifferentFunctionsCached","getAncestry","commonPath","commonIndex","indexOf","Error","divergence","listKey","keys","keyPosition","_guessExecutionStatusRelativeToDifferentFunctionsInternal","isFunctionDeclaration","isExportDeclaration","id","references","referencePaths","allStatus","childOfFunction","find","isCallExpression","status","nodeMap","cached","set","result","resolve","dangerous","resolved","_resolve","call","_resolved","push","isVariableDeclarator","constant","ret","isTypeCastExpression","targetKey","toComputedKey","targetName","isObjectExpression","props","prop","isProperty","match","isArrayExpression","isNaN","elems","elem","isConstantExpression","isRegExpLiteral","isTemplateLiteral","every","expression","isUnaryExpression","operator","isBinaryExpression","hasBinding","noGlobals","arguments","isInStrictMode","strictParent","sourceType","isClass","body","directive","directives"],"sources":["../../src/path/introspection.ts"],"sourcesContent":["// This file contains methods responsible for introspecting the current path for certain values.\n\nimport type NodePath from \"./index.ts\";\nimport {\n STATEMENT_OR_BLOCK_KEYS,\n VISITOR_KEYS,\n isBlockStatement,\n isExpression,\n isIdentifier,\n isLiteral,\n isStringLiteral,\n isType,\n matchesPattern as _matchesPattern,\n} from \"@babel/types\";\nimport type * as t from \"@babel/types\";\n\n/**\n * Match the current node if it matches the provided `pattern`.\n *\n * For example, given the match `React.createClass` it would match the\n * parsed nodes of `React.createClass` and `React[\"createClass\"]`.\n */\n\nexport function matchesPattern(\n this: NodePath,\n pattern: string,\n allowPartial?: boolean,\n): boolean {\n return _matchesPattern(this.node, pattern, allowPartial);\n}\n\nif (!process.env.BABEL_8_BREAKING && !USE_ESM) {\n /**\n * Check whether we have the input `key`. If the `key` references an array then we check\n * if the array has any items, otherwise we just check if it's falsy.\n */\n // eslint-disable-next-line no-restricted-globals\n exports.has = function has<N extends t.Node>(\n this: NodePath<N>,\n key: keyof N,\n ): boolean {\n const val = (this.node as N)?.[key];\n if (val && Array.isArray(val)) {\n return !!val.length;\n } else {\n return !!val;\n }\n };\n}\n\nexport function isStatic(this: NodePath): boolean {\n return this.scope.isStatic(this.node);\n}\n\nif (!process.env.BABEL_8_BREAKING && !USE_ESM) {\n /**\n * Alias of `has`.\n */\n // eslint-disable-next-line no-restricted-globals\n exports.is = exports.has;\n\n /**\n * Opposite of `has`.\n */\n // eslint-disable-next-line no-restricted-globals\n exports.isnt = function isnt<N extends t.Node>(\n this: NodePath<N>,\n key: keyof N,\n ): boolean {\n // @ts-expect-error Babel 7\n return !this.has(key);\n };\n\n /**\n * Check whether the path node `key` strict equals `value`.\n */\n // eslint-disable-next-line no-restricted-globals\n exports.equals = function equals<N extends t.Node>(\n this: NodePath<N>,\n key: keyof N,\n value: any,\n ): boolean {\n return (this.node as N)[key] === value;\n };\n}\n\n/**\n * Check the type against our stored internal type of the node. This is handy when a node has\n * been removed yet we still internally know the type and need it to calculate node replacement.\n */\n\nexport function isNodeType(this: NodePath, type: string): boolean {\n return isType(this.type, type);\n}\n\n/**\n * This checks whether or not we're in one of the following Line truncated
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _t = require("@babel/types");
|
||||
var _t2 = _t;
|
||||
const {
|
||||
react
|
||||
} = _t;
|
||||
const {
|
||||
cloneNode,
|
||||
jsxExpressionContainer,
|
||||
variableDeclaration,
|
||||
variableDeclarator
|
||||
} = _t2;
|
||||
const referenceVisitor = {
|
||||
ReferencedIdentifier(path, state) {
|
||||
if (path.isJSXIdentifier() && react.isCompatTag(path.node.name) && !path.parentPath.isJSXMemberExpression()) {
|
||||
return;
|
||||
}
|
||||
if (path.node.name === "this") {
|
||||
let scope = path.scope;
|
||||
do {
|
||||
if (scope.path.isFunction() && !scope.path.isArrowFunctionExpression()) {
|
||||
break;
|
||||
}
|
||||
} while (scope = scope.parent);
|
||||
if (scope) state.breakOnScopePaths.push(scope.path);
|
||||
}
|
||||
const binding = path.scope.getBinding(path.node.name);
|
||||
if (!binding) return;
|
||||
for (const violation of binding.constantViolations) {
|
||||
if (violation.scope !== binding.path.scope) {
|
||||
state.mutableBinding = true;
|
||||
path.stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (binding !== state.scope.getBinding(path.node.name)) return;
|
||||
state.bindings[path.node.name] = binding;
|
||||
}
|
||||
};
|
||||
class PathHoister {
|
||||
constructor(path, scope) {
|
||||
this.breakOnScopePaths = void 0;
|
||||
this.bindings = void 0;
|
||||
this.mutableBinding = void 0;
|
||||
this.scopes = void 0;
|
||||
this.scope = void 0;
|
||||
this.path = void 0;
|
||||
this.attachAfter = void 0;
|
||||
this.breakOnScopePaths = [];
|
||||
this.bindings = {};
|
||||
this.mutableBinding = false;
|
||||
this.scopes = [];
|
||||
this.scope = scope;
|
||||
this.path = path;
|
||||
this.attachAfter = false;
|
||||
}
|
||||
isCompatibleScope(scope) {
|
||||
for (const key of Object.keys(this.bindings)) {
|
||||
const binding = this.bindings[key];
|
||||
if (!scope.bindingIdentifierEquals(key, binding.identifier)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
getCompatibleScopes() {
|
||||
let scope = this.path.scope;
|
||||
do {
|
||||
if (this.isCompatibleScope(scope)) {
|
||||
this.scopes.push(scope);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (this.breakOnScopePaths.includes(scope.path)) {
|
||||
break;
|
||||
}
|
||||
} while (scope = scope.parent);
|
||||
}
|
||||
getAttachmentPath() {
|
||||
let path = this._getAttachmentPath();
|
||||
if (!path) return;
|
||||
let targetScope = path.scope;
|
||||
if (targetScope.path === path) {
|
||||
targetScope = path.scope.parent;
|
||||
}
|
||||
if (targetScope.path.isProgram() || targetScope.path.isFunction()) {
|
||||
for (const name of Object.keys(this.bindings)) {
|
||||
if (!targetScope.hasOwnBinding(name)) continue;
|
||||
const binding = this.bindings[name];
|
||||
if (binding.kind === "param" || binding.path.parentKey === "params") {
|
||||
continue;
|
||||
}
|
||||
const bindingParentPath = this.getAttachmentParentForPath(binding.path);
|
||||
if (bindingParentPath.key >= path.key) {
|
||||
this.attachAfter = true;
|
||||
path = binding.path;
|
||||
for (const violationPath of binding.constantViolations) {
|
||||
if (this.getAttachmentParentForPath(violationPath).key > path.key) {
|
||||
path = violationPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
_getAttachmentPath() {
|
||||
const scopes = this.scopes;
|
||||
const scope = scopes.pop();
|
||||
if (!scope) return;
|
||||
if (scope.path.isFunction()) {
|
||||
if (this.hasOwnParamBindings(scope)) {
|
||||
if (this.scope === scope) return;
|
||||
const bodies = scope.path.get("body").get("body");
|
||||
for (let i = 0; i < bodies.length; i++) {
|
||||
if (bodies[i].node._blockHoist) continue;
|
||||
return bodies[i];
|
||||
}
|
||||
} else {
|
||||
return this.getNextScopeAttachmentParent();
|
||||
}
|
||||
} else if (scope.path.isProgram()) {
|
||||
return this.getNextScopeAttachmentParent();
|
||||
}
|
||||
}
|
||||
getNextScopeAttachmentParent() {
|
||||
const scope = this.scopes.pop();
|
||||
if (scope) return this.getAttachmentParentForPath(scope.path);
|
||||
}
|
||||
getAttachmentParentForPath(path) {
|
||||
do {
|
||||
if (!path.parentPath || Array.isArray(path.container) && path.isStatement()) {
|
||||
return path;
|
||||
}
|
||||
} while (path = path.parentPath);
|
||||
return path;
|
||||
}
|
||||
hasOwnParamBindings(scope) {
|
||||
for (const name of Object.keys(this.bindings)) {
|
||||
if (!scope.hasOwnBinding(name)) continue;
|
||||
const binding = this.bindings[name];
|
||||
if (binding.kind === "param" && binding.constant) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
run() {
|
||||
this.path.traverse(referenceVisitor, this);
|
||||
if (this.mutableBinding) return;
|
||||
this.getCompatibleScopes();
|
||||
const attachTo = this.getAttachmentPath();
|
||||
if (!attachTo) return;
|
||||
if (attachTo.getFunctionParent() === this.path.getFunctionParent()) return;
|
||||
let uid = attachTo.scope.generateUidIdentifier("ref");
|
||||
const declarator = variableDeclarator(uid, this.path.node);
|
||||
const insertFn = this.attachAfter ? "insertAfter" : "insertBefore";
|
||||
const [attached] = attachTo[insertFn]([attachTo.isVariableDeclarator() ? declarator : variableDeclaration("var", [declarator])]);
|
||||
const parent = this.path.parentPath;
|
||||
if (parent.isJSXElement() && this.path.container === parent.node.children) {
|
||||
uid = jsxExpressionContainer(uid);
|
||||
}
|
||||
this.path.replaceWith(cloneNode(uid));
|
||||
return attached.isVariableDeclarator() ? attached.get("init") : attached.get("declarations.0.init");
|
||||
}
|
||||
}
|
||||
exports.default = PathHoister;
|
||||
|
||||
//# sourceMappingURL=hoister.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_t","require","_t2","react","cloneNode","jsxExpressionContainer","variableDeclaration","variableDeclarator","referenceVisitor","ReferencedIdentifier","path","state","isJSXIdentifier","isCompatTag","node","name","parentPath","isJSXMemberExpression","scope","isFunction","isArrowFunctionExpression","parent","breakOnScopePaths","push","binding","getBinding","violation","constantViolations","mutableBinding","stop","bindings","PathHoister","constructor","scopes","attachAfter","isCompatibleScope","key","Object","keys","bindingIdentifierEquals","identifier","getCompatibleScopes","includes","getAttachmentPath","_getAttachmentPath","targetScope","isProgram","hasOwnBinding","kind","parentKey","bindingParentPath","getAttachmentParentForPath","violationPath","pop","hasOwnParamBindings","bodies","get","i","length","_blockHoist","getNextScopeAttachmentParent","Array","isArray","container","isStatement","constant","run","traverse","attachTo","getFunctionParent","uid","generateUidIdentifier","declarator","insertFn","attached","isVariableDeclarator","isJSXElement","children","replaceWith","exports","default"],"sources":["../../../src/path/lib/hoister.ts"],"sourcesContent":["// TODO: Remove this file in Babel 8\n\nimport { react } from \"@babel/types\";\nimport {\n cloneNode,\n jsxExpressionContainer,\n variableDeclaration,\n variableDeclarator,\n} from \"@babel/types\";\nimport type * as t from \"@babel/types\";\nimport type Scope from \"../../scope/index.ts\";\nimport type NodePath from \"../index.ts\";\nimport type Binding from \"../../scope/binding.ts\";\nimport type { Visitor } from \"../../types.ts\";\n\nconst referenceVisitor: Visitor<PathHoister> = {\n // This visitor looks for bindings to establish a topmost scope for hoisting.\n ReferencedIdentifier(path, state) {\n // Don't hoist regular JSX identifiers ('div', 'span', etc).\n // We do have to consider member expressions for hoisting (e.g. `this.component`)\n if (\n path.isJSXIdentifier() &&\n react.isCompatTag(path.node.name) &&\n !path.parentPath.isJSXMemberExpression()\n ) {\n return;\n }\n\n // If the identifier refers to `this`, we need to break on the closest non-arrow scope.\n if (path.node.name === \"this\") {\n let scope: Scope | undefined = path.scope;\n do {\n if (\n scope.path.isFunction() &&\n !scope.path.isArrowFunctionExpression()\n ) {\n break;\n }\n } while ((scope = scope.parent));\n if (scope) state.breakOnScopePaths.push(scope.path);\n }\n\n // direct references that we need to track to hoist this to the highest scope we can\n const binding = path.scope.getBinding(path.node.name);\n if (!binding) return;\n\n // we can handle reassignments only if they happen in the same scope as the declaration\n for (const violation of binding.constantViolations) {\n if (violation.scope !== binding.path.scope) {\n state.mutableBinding = true;\n path.stop();\n return;\n }\n }\n\n // this binding isn't accessible from the parent scope so we can safely ignore it\n // eg. it's in a closure etc\n if (binding !== state.scope.getBinding(path.node.name)) return;\n\n state.bindings[path.node.name] = binding;\n },\n};\n\nexport default class PathHoister<T extends t.Node = t.Node> {\n breakOnScopePaths: NodePath[];\n bindings: Record<string, Binding>;\n mutableBinding: boolean;\n private scopes: Scope[];\n scope: Scope;\n private path: NodePath<T>;\n private attachAfter: boolean;\n\n constructor(path: NodePath<T>, scope: Scope) {\n // Storage for scopes we can't hoist above.\n this.breakOnScopePaths = [];\n // Storage for bindings that may affect what path we can hoist to.\n this.bindings = {};\n // \"true\" if the current path contains a reference to a binding whose\n // value can change and thus can't be safely hoisted.\n this.mutableBinding = false;\n // Storage for eligible scopes.\n this.scopes = [];\n // Our original scope and path.\n this.scope = scope;\n this.path = path;\n // By default, we attach as far up as we can; but if we're trying\n // to avoid referencing a binding, we may have to go after.\n this.attachAfter = false;\n }\n\n // A scope is compatible if all required bindings are reachable.\n isCompatibleScope(scope: Scope) {\n for (const key of Object.keys(this.bindings)) {\n const binding = this.bindings[key];\n if (!scope.bindingIdentifierEquals(key, binding.identifier)) {\n return false;\n }\n }\n\n return true;\n }\n\n // Look through all scopes and push compatible ones.\n getCompatibleScopes() {\n let scope: Scope | undefined = this.path.scope;\n do {\n if (this.isCompatibleScope(scope)) {\n this.scopes.push(scope);\n } else {\n break;\n }\n\n // deopt: These scopes are set in the visitor on const violations\n if (thiLine truncated
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.hooks = void 0;
|
||||
const hooks = exports.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 === 1) {
|
||||
parent.replaceWith(parent.node.expressions[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;
|
||||
}
|
||||
}];
|
||||
|
||||
//# sourceMappingURL=removal-hooks.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["hooks","exports","self","parent","removeParent","key","isWhile","isSwitchCase","isExportDeclaration","isLabeledStatement","listKey","isVariableDeclaration","node","declarations","length","isExpressionStatement","remove","isSequenceExpression","expressions","replaceWith","isBinary","right","left","isIfStatement","isLoop","isArrowFunctionExpression","type","directives","body"],"sources":["../../../src/path/lib/removal-hooks.ts"],"sourcesContent":["// this file contains hooks that handle ancestry cleanup of parent nodes when removing children\n\nimport type NodePath from \"../index.ts\";\nimport type * as t from \"@babel/types\";\n/**\n * Pre hooks should be used for either rejecting removal or delegating removal\n */\n\nexport const hooks = [\n function (self: NodePath, parent: NodePath) {\n const removeParent =\n // while (NODE);\n // removing the test of a while/switch, we can either just remove it entirely *or* turn the\n // `test` into `true` unlikely that the latter will ever be what's wanted so we just remove\n // the loop to avoid infinite recursion\n (self.key === \"test\" && (parent.isWhile() || parent.isSwitchCase())) ||\n // export NODE;\n // just remove a declaration for an export as this is no longer valid\n (self.key === \"declaration\" && parent.isExportDeclaration()) ||\n // label: NODE\n // stray labeled statement with no body\n (self.key === \"body\" && parent.isLabeledStatement()) ||\n // let NODE;\n // remove an entire declaration if there are no declarators left\n (self.listKey === \"declarations\" &&\n parent.isVariableDeclaration() &&\n parent.node.declarations.length === 1) ||\n // NODE;\n // remove the entire expression statement if there's no expression\n (self.key === \"expression\" && parent.isExpressionStatement());\n\n if (removeParent) {\n parent.remove();\n return true;\n }\n },\n\n function (self: NodePath, parent: NodePath) {\n if (parent.isSequenceExpression() && parent.node.expressions.length === 1) {\n // (node, NODE);\n // we've just removed the second element of a sequence expression so let's turn that sequence\n // expression into a regular expression\n parent.replaceWith(parent.node.expressions[0]);\n return true;\n }\n },\n\n function (self: NodePath, parent: NodePath) {\n if (parent.isBinary()) {\n // left + NODE;\n // NODE + right;\n // we're in a binary expression, better remove it and replace it with the last expression\n if (self.key === \"left\") {\n parent.replaceWith(parent.node.right);\n } else {\n // key === \"right\"\n parent.replaceWith(parent.node.left);\n }\n return true;\n }\n },\n\n function (self: NodePath, parent: NodePath) {\n if (\n (parent.isIfStatement() && self.key === \"consequent\") ||\n (self.key === \"body\" &&\n (parent.isLoop() || parent.isArrowFunctionExpression()))\n ) {\n self.replaceWith({\n type: \"BlockStatement\",\n directives: [],\n body: [],\n } satisfies t.BlockStatement);\n return true;\n }\n },\n];\n"],"mappings":";;;;;;AAQO,MAAMA,KAAK,GAAAC,OAAA,CAAAD,KAAA,GAAG,CACnB,UAAUE,IAAc,EAAEC,MAAgB,EAAE;EAC1C,MAAMC,YAAY,GAKfF,IAAI,CAACG,GAAG,KAAK,MAAM,KAAKF,MAAM,CAACG,OAAO,CAAC,CAAC,IAAIH,MAAM,CAACI,YAAY,CAAC,CAAC,CAAC,IAGlEL,IAAI,CAACG,GAAG,KAAK,aAAa,IAAIF,MAAM,CAACK,mBAAmB,CAAC,CAAE,IAG3DN,IAAI,CAACG,GAAG,KAAK,MAAM,IAAIF,MAAM,CAACM,kBAAkB,CAAC,CAAE,IAGnDP,IAAI,CAACQ,OAAO,KAAK,cAAc,IAC9BP,MAAM,CAACQ,qBAAqB,CAAC,CAAC,IAC9BR,MAAM,CAACS,IAAI,CAACC,YAAY,CAACC,MAAM,KAAK,CAAE,IAGvCZ,IAAI,CAACG,GAAG,KAAK,YAAY,IAAIF,MAAM,CAACY,qBAAqB,CAAC,CAAE;EAE/D,IAAIX,YAAY,EAAE;IAChBD,MAAM,CAACa,MAAM,CAAC,CAAC;IACf,OAAO,IAAI;EACb;AACF,CAAC,EAED,UAAUd,IAAc,EAAEC,MAAgB,EAAE;EAC1C,IAAIA,MAAM,CAACc,oBAAoB,CAAC,CAAC,IAAId,MAAM,CAACS,IAAI,CAACM,WAAW,CAACJ,MAAM,KAAK,CAAC,EAAE;IAIzEX,MAAM,CAACgB,WAAW,CAAChB,MAAM,CAACS,IAAI,CAACM,WAAW,CAAC,CAAC,CAAC,CAAC;IAC9C,OAAO,IAAI;EACb;AACF,CAAC,EAED,UAAUhB,IAAc,EAAEC,MAAgB,EAAE;EAC1C,IAAIA,MAAM,CAACiB,QAAQ,CAAC,CAAC,EAAE;IAIrB,IAAIlB,IAAI,CAACG,GAAG,KAAK,MAAM,EAAE;MACvBF,MAAM,CAACgB,WAAW,CAAChB,MAAM,CAACS,IAAI,CAACS,KAAK,CAAC;IACvC,CAAC,MAAM;MAELlB,MAAM,CAACgB,WAAW,CAAChB,MAAM,CAACS,IAAI,CAACU,IAAI,CAAC;IACtC;IACA,OAAO,IAAI;EACb;AACF,CAAC,EAED,UAAUpB,IAAc,EAAEC,MAAgB,EAAE;EAC1C,IACGA,MAAM,CAACoB,aAAa,CAAC,CAAC,IAAIrB,IAAI,CAACG,GAAG,KAAK,YAAY,IACnDH,IAAI,CAACG,GAAG,KAAK,MAAM,KACjBF,MAAM,CAACqB,MAAM,CAAC,CAAC,IAAIrB,MAAM,CAACsB,yBAAyB,CAAC,CAAC,CAAE,EAC1D;IACAvB,IAAI,CAACiB,WAAW,CAAC;MACfO,IAAI,EAAE,gBAAgB;MACtBC,UAAU,EAAE,EAAE;MACdC,IAAI,EAAE;IACR,CAA4B,CAAC;IAC7B,OAAO,IAAI;EACb;AACF,CAAC,CACF","ignoreList":[]}
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.isBindingIdentifier = isBindingIdentifier;
|
||||
exports.isBlockScoped = isBlockScoped;
|
||||
exports.isExpression = isExpression;
|
||||
exports.isFlow = isFlow;
|
||||
exports.isForAwaitStatement = isForAwaitStatement;
|
||||
exports.isGenerated = isGenerated;
|
||||
exports.isPure = isPure;
|
||||
exports.isReferenced = isReferenced;
|
||||
exports.isReferencedIdentifier = isReferencedIdentifier;
|
||||
exports.isReferencedMemberExpression = isReferencedMemberExpression;
|
||||
exports.isRestProperty = isRestProperty;
|
||||
exports.isScope = isScope;
|
||||
exports.isSpreadProperty = isSpreadProperty;
|
||||
exports.isStatement = isStatement;
|
||||
exports.isUser = isUser;
|
||||
exports.isVar = isVar;
|
||||
var _t = require("@babel/types");
|
||||
const {
|
||||
isBinding,
|
||||
isBlockScoped: nodeIsBlockScoped,
|
||||
isExportDeclaration,
|
||||
isExpression: nodeIsExpression,
|
||||
isFlow: nodeIsFlow,
|
||||
isForStatement,
|
||||
isForXStatement,
|
||||
isIdentifier,
|
||||
isImportDeclaration,
|
||||
isImportSpecifier,
|
||||
isJSXIdentifier,
|
||||
isJSXMemberExpression,
|
||||
isMemberExpression,
|
||||
isRestElement: nodeIsRestElement,
|
||||
isReferenced: nodeIsReferenced,
|
||||
isScope: nodeIsScope,
|
||||
isStatement: nodeIsStatement,
|
||||
isVar: nodeIsVar,
|
||||
isVariableDeclaration,
|
||||
react,
|
||||
isForOfStatement
|
||||
} = _t;
|
||||
const {
|
||||
isCompatTag
|
||||
} = react;
|
||||
function isReferencedIdentifier(opts) {
|
||||
const {
|
||||
node,
|
||||
parent
|
||||
} = this;
|
||||
if (isIdentifier(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(node) && nodeIsReferenced(node, parent);
|
||||
}
|
||||
function isBindingIdentifier() {
|
||||
const {
|
||||
node,
|
||||
parent
|
||||
} = this;
|
||||
const grandparent = this.parentPath.parent;
|
||||
return isIdentifier(node) && isBinding(node, parent, grandparent);
|
||||
}
|
||||
function isStatement() {
|
||||
const {
|
||||
node,
|
||||
parent
|
||||
} = this;
|
||||
if (nodeIsStatement(node)) {
|
||||
if (isVariableDeclaration(node)) {
|
||||
if (isForXStatement(parent, {
|
||||
left: node
|
||||
})) return false;
|
||||
if (isForStatement(parent, {
|
||||
init: node
|
||||
})) return false;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function isExpression() {
|
||||
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() {
|
||||
var _this$node;
|
||||
return !!((_this$node = this.node) != null && _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(node)) {
|
||||
return node.importKind === "type" || node.importKind === "typeof";
|
||||
} else if (isExportDeclaration(node)) {
|
||||
return node.exportKind === "type";
|
||||
} else if (isImportSpecifier(node)) {
|
||||
return node.importKind === "type" || node.importKind === "typeof";
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function isRestProperty() {
|
||||
var _this$parentPath;
|
||||
return nodeIsRestElement(this.node) && ((_this$parentPath = this.parentPath) == null ? void 0 : _this$parentPath.isObjectPattern());
|
||||
}
|
||||
function isSpreadProperty() {
|
||||
var _this$parentPath2;
|
||||
return nodeIsRestElement(this.node) && ((_this$parentPath2 = this.parentPath) == null ? void 0 : _this$parentPath2.isObjectExpression());
|
||||
}
|
||||
function isForAwaitStatement() {
|
||||
return isForOfStatement(this.node, {
|
||||
await: true
|
||||
});
|
||||
}
|
||||
exports.isExistentialTypeParam = function isExistentialTypeParam() {
|
||||
throw new Error("`path.isExistentialTypeParam` has been renamed to `path.isExistsTypeAnnotation()` in Babel 7.");
|
||||
};
|
||||
exports.isNumericLiteralTypeAnnotation = function isNumericLiteralTypeAnnotation() {
|
||||
throw new Error("`path.isNumericLiteralTypeAnnotation()` has been renamed to `path.isNumberLiteralTypeAnnotation()` in Babel 7.");
|
||||
};
|
||||
|
||||
//# sourceMappingURL=virtual-types-validator.js.map
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_t","require","isBinding","isBlockScoped","nodeIsBlockScoped","isExportDeclaration","isExpression","nodeIsExpression","isFlow","nodeIsFlow","isForStatement","isForXStatement","isIdentifier","isImportDeclaration","isImportSpecifier","isJSXIdentifier","isJSXMemberExpression","isMemberExpression","isRestElement","nodeIsRestElement","isReferenced","nodeIsReferenced","isScope","nodeIsScope","isStatement","nodeIsStatement","isVar","nodeIsVar","isVariableDeclaration","react","isForOfStatement","isCompatTag","isReferencedIdentifier","opts","node","parent","parentPath","name","isReferencedMemberExpression","isBindingIdentifier","grandparent","left","init","isUser","_this$node","loc","isGenerated","isPure","constantsOnly","scope","importKind","exportKind","isRestProperty","_this$parentPath","isObjectPattern","isSpreadProperty","_this$parentPath2","isObjectExpression","isForAwaitStatement","await","exports","isExistentialTypeParam","Error","isNumericLiteralTypeAnnotation"],"sources":["../../../src/path/lib/virtual-types-validator.ts"],"sourcesContent":["import type NodePath from \"../index.ts\";\nimport {\n isBinding,\n isBlockScoped as nodeIsBlockScoped,\n isExportDeclaration,\n isExpression as nodeIsExpression,\n isFlow as nodeIsFlow,\n isForStatement,\n isForXStatement,\n isIdentifier,\n isImportDeclaration,\n isImportSpecifier,\n isJSXIdentifier,\n isJSXMemberExpression,\n isMemberExpression,\n isRestElement as nodeIsRestElement,\n isReferenced as nodeIsReferenced,\n isScope as nodeIsScope,\n isStatement as nodeIsStatement,\n isVar as nodeIsVar,\n isVariableDeclaration,\n react,\n isForOfStatement,\n} from \"@babel/types\";\nimport type * as t from \"@babel/types\";\nconst { isCompatTag } = react;\nimport type { VirtualTypeAliases } from \"./virtual-types.ts\";\n\ntype Options<Obj> = Partial<{\n [Prop in Exclude<keyof Obj, \"type\">]: Obj[Prop] extends t.Node\n ? t.Node\n : Obj[Prop] extends t.Node[]\n ? t.Node[]\n : Obj[Prop];\n}>;\n\nexport interface VirtualTypeNodePathValidators {\n isBindingIdentifier(\n this: NodePath<t.Node | null>,\n ): this is NodePath<VirtualTypeAliases[\"BindingIdentifier\"]>;\n isBlockScoped(this: NodePath<t.Node | null>): boolean;\n /**\n * @deprecated\n */\n isExistentialTypeParam(\n this: NodePath<t.Node | null>,\n ): this is NodePath<VirtualTypeAliases[\"ExistentialTypeParam\"]>;\n isExpression(this: NodePath<t.Node | null>): this is NodePath<t.Expression>;\n isFlow(this: NodePath<t.Node | null>): this is NodePath<t.Flow>;\n isForAwaitStatement(\n this: NodePath<t.Node | null>,\n ): this is NodePath<VirtualTypeAliases[\"ForAwaitStatement\"]>;\n isGenerated(\n this: NodePath<t.Node | null>,\n ): this is NodePath<VirtualTypeAliases[\"Generated\"]>;\n /**\n * @deprecated\n */\n isNumericLiteralTypeAnnotation(this: NodePath<t.Node | null>): void;\n isPure(): boolean;\n isReferenced(): boolean;\n isReferencedIdentifier<\n Opts extends Options<VirtualTypeAliases[\"ReferencedIdentifier\"]>,\n >(\n this: NodePath<t.Node | null>,\n opts?: Opts,\n ): this is NodePath<VirtualTypeAliases[\"ReferencedIdentifier\"] & Opts>;\n isReferencedMemberExpression(\n this: NodePath<t.Node | null>,\n ): this is NodePath<VirtualTypeAliases[\"ReferencedMemberExpression\"]>;\n isRestProperty(\n this: NodePath<t.Node | null>,\n ): this is NodePath<t.RestProperty>;\n isScope(\n this: NodePath<t.Node | null>,\n ): this is NodePath<VirtualTypeAliases[\"Scope\"]>;\n isSpreadProperty(\n this: NodePath<t.Node | null>,\n ): this is NodePath<t.SpreadProperty>;\n isStatement(this: NodePath<t.Node | null>): this is NodePath<t.Statement>;\n isUser(\n this: NodePath<t.Node | null>,\n ): this is NodePath<VirtualTypeAliases[\"User\"]>;\n isVar(\n this: NodePath<t.Node | null>,\n ): this is NodePath<VirtualTypeAliases[\"Var\"]>;\n}\n\nexport function isReferencedIdentifier(\n this: NodePath<t.Node | null>,\n opts?: Options<VirtualTypeAliases[\"ReferencedIdentifier\"]>,\n): boolean {\n const { node, parent } = this;\n if (isIdentifier(node, opts)) {\n return nodeIsReferenced(node, parent, this.parentPath.parent);\n } else if (isJSXIdentifier(node, opts)) {\n if (!isJSXMemberExpression(parent) && isCompatTag(node.name)) return false;\n return nodeIsReferenced(node, parent, this.parentPath.parent);\n } else {\n // not a JSXIdentifier or an Identifier\n return false;\n }\n}\n\nexport function isReferencedMemberExpression(\n this: NodePath<t.Node | null>,\n): boolean {\n const { node, parent } = this;\n return isMemberExpression(node) && nodeIsReferenced(node, parent);\n}\n\nexport function isBindingIdentifier(this: NodePath<t.Node | null>): boolean {\n const { node, parent } = this;\n const grandparent = this.parentPath.parent;\n return isIdentifier(node) && isBinding(node, parent, grandparent);\n}\n\nexport function isStatement(this: NodePath<t.Node | null>): booLine truncated
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.Var = exports.User = exports.Statement = exports.SpreadProperty = exports.Scope = exports.RestProperty = exports.ReferencedMemberExpression = exports.ReferencedIdentifier = exports.Referenced = exports.Pure = exports.NumericLiteralTypeAnnotation = exports.Generated = exports.ForAwaitStatement = exports.Flow = exports.Expression = exports.ExistentialTypeParam = exports.BlockScoped = exports.BindingIdentifier = void 0;
|
||||
const ReferencedIdentifier = exports.ReferencedIdentifier = ["Identifier", "JSXIdentifier"];
|
||||
const ReferencedMemberExpression = exports.ReferencedMemberExpression = ["MemberExpression"];
|
||||
const BindingIdentifier = exports.BindingIdentifier = ["Identifier"];
|
||||
const Statement = exports.Statement = ["Statement"];
|
||||
const Expression = exports.Expression = ["Expression"];
|
||||
const Scope = exports.Scope = ["Scopable", "Pattern"];
|
||||
const Referenced = exports.Referenced = null;
|
||||
const BlockScoped = exports.BlockScoped = ["FunctionDeclaration", "ClassDeclaration", "VariableDeclaration"];
|
||||
const Var = exports.Var = ["VariableDeclaration"];
|
||||
const User = exports.User = null;
|
||||
const Generated = exports.Generated = null;
|
||||
const Pure = exports.Pure = null;
|
||||
const Flow = exports.Flow = ["Flow", "ImportDeclaration", "ExportDeclaration", "ImportSpecifier"];
|
||||
const RestProperty = exports.RestProperty = ["RestElement"];
|
||||
const SpreadProperty = exports.SpreadProperty = ["RestElement"];
|
||||
const ExistentialTypeParam = exports.ExistentialTypeParam = ["ExistsTypeAnnotation"];
|
||||
const NumericLiteralTypeAnnotation = exports.NumericLiteralTypeAnnotation = ["NumberLiteralTypeAnnotation"];
|
||||
const ForAwaitStatement = exports.ForAwaitStatement = ["ForOfStatement"];
|
||||
|
||||
//# sourceMappingURL=virtual-types.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["ReferencedIdentifier","exports","ReferencedMemberExpression","BindingIdentifier","Statement","Expression","Scope","Referenced","BlockScoped","Var","User","Generated","Pure","Flow","RestProperty","SpreadProperty","ExistentialTypeParam","NumericLiteralTypeAnnotation","ForAwaitStatement"],"sources":["../../../src/path/lib/virtual-types.ts"],"sourcesContent":["import type * as t from \"@babel/types\";\n\nexport interface VirtualTypeAliases {\n BindingIdentifier: t.Identifier;\n BlockScoped:\n | t.FunctionDeclaration\n | t.ClassDeclaration\n | t.VariableDeclaration;\n ExistentialTypeParam: t.ExistsTypeAnnotation;\n Expression: t.Expression;\n Flow: t.Flow | t.ImportDeclaration | t.ExportDeclaration | t.ImportSpecifier;\n ForAwaitStatement: t.ForOfStatement;\n Generated: t.Node;\n NumericLiteralTypeAnnotation: t.NumberLiteralTypeAnnotation;\n Pure: t.Node;\n Referenced: t.Node;\n ReferencedIdentifier: t.Identifier | t.JSXIdentifier;\n ReferencedMemberExpression: t.MemberExpression;\n RestProperty: t.RestElement;\n Scope: t.Scopable | t.Pattern;\n SpreadProperty: t.RestElement;\n Statement: t.Statement;\n User: t.Node;\n Var: t.VariableDeclaration;\n}\n\ntype VirtualTypeMapping = readonly (t.Node[\"type\"] | keyof t.Aliases)[] | null;\n\nexport const ReferencedIdentifier: VirtualTypeMapping = [\n \"Identifier\",\n \"JSXIdentifier\",\n] as const;\n\nexport const ReferencedMemberExpression: VirtualTypeMapping = [\n \"MemberExpression\",\n] as const;\n\nexport const BindingIdentifier: VirtualTypeMapping = [\"Identifier\"] as const;\n\nexport const Statement: VirtualTypeMapping = [\"Statement\"] as const;\n\nexport const Expression: VirtualTypeMapping = [\"Expression\"] as const;\n\nexport const Scope: VirtualTypeMapping = [\"Scopable\", \"Pattern\"] as const;\n\nexport const Referenced: VirtualTypeMapping = null;\n\nexport const BlockScoped: VirtualTypeMapping = [\n \"FunctionDeclaration\",\n \"ClassDeclaration\",\n \"VariableDeclaration\",\n] as const;\n\nexport const Var: VirtualTypeMapping = [\"VariableDeclaration\"];\n\nexport const User: VirtualTypeMapping = null;\n\nexport const Generated: VirtualTypeMapping = null;\n\nexport const Pure: VirtualTypeMapping = null;\n\nexport const Flow: VirtualTypeMapping = [\n \"Flow\",\n \"ImportDeclaration\",\n \"ExportDeclaration\",\n \"ImportSpecifier\",\n] as const;\n\n// TODO: 7.0 Backwards Compat\nexport const RestProperty: VirtualTypeMapping = [\"RestElement\"] as const;\n\nexport const SpreadProperty: VirtualTypeMapping = [\"RestElement\"] as const;\n\nexport const ExistentialTypeParam: VirtualTypeMapping = [\n \"ExistsTypeAnnotation\",\n] as const;\n\nexport const NumericLiteralTypeAnnotation: VirtualTypeMapping = [\n \"NumberLiteralTypeAnnotation\",\n] as const;\n\nexport const ForAwaitStatement: VirtualTypeMapping = [\n \"ForOfStatement\",\n] as const;\n"],"mappings":";;;;;;AA4BO,MAAMA,oBAAwC,GAAAC,OAAA,CAAAD,oBAAA,GAAG,CACtD,YAAY,EACZ,eAAe,CACP;AAEH,MAAME,0BAA8C,GAAAD,OAAA,CAAAC,0BAAA,GAAG,CAC5D,kBAAkB,CACV;AAEH,MAAMC,iBAAqC,GAAAF,OAAA,CAAAE,iBAAA,GAAG,CAAC,YAAY,CAAU;AAErE,MAAMC,SAA6B,GAAAH,OAAA,CAAAG,SAAA,GAAG,CAAC,WAAW,CAAU;AAE5D,MAAMC,UAA8B,GAAAJ,OAAA,CAAAI,UAAA,GAAG,CAAC,YAAY,CAAU;AAE9D,MAAMC,KAAyB,GAAAL,OAAA,CAAAK,KAAA,GAAG,CAAC,UAAU,EAAE,SAAS,CAAU;AAElE,MAAMC,UAA8B,GAAAN,OAAA,CAAAM,UAAA,GAAG,IAAI;AAE3C,MAAMC,WAA+B,GAAAP,OAAA,CAAAO,WAAA,GAAG,CAC7C,qBAAqB,EACrB,kBAAkB,EAClB,qBAAqB,CACb;AAEH,MAAMC,GAAuB,GAAAR,OAAA,CAAAQ,GAAA,GAAG,CAAC,qBAAqB,CAAC;AAEvD,MAAMC,IAAwB,GAAAT,OAAA,CAAAS,IAAA,GAAG,IAAI;AAErC,MAAMC,SAA6B,GAAAV,OAAA,CAAAU,SAAA,GAAG,IAAI;AAE1C,MAAMC,IAAwB,GAAAX,OAAA,CAAAW,IAAA,GAAG,IAAI;AAErC,MAAMC,IAAwB,GAAAZ,OAAA,CAAAY,IAAA,GAAG,CACtC,MAAM,EACN,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,CACT;AAGH,MAAMC,YAAgC,GAAAb,OAAA,CAAAa,YAAA,GAAG,CAAC,aAAa,CAAU;AAEjE,MAAMC,cAAkC,GAAAd,OAAA,CAAAc,cAAA,GAAG,CAAC,aAAa,CAAU;AAEnE,MAAMC,oBAAwC,GAAAf,OAAA,CAAAe,oBAAA,GAAG,CACtD,sBAAsB,CACd;AAEH,MAAMC,4BAAgD,GAAAhB,OAAA,CAAAgB,4BAAA,GAAG,CAC9D,6BAA6B,CACrB;AAEH,MAAMC,iBAAqC,GAAAjB,OAAA,CAAAiB,iBAAA,GAAG,CACnD,gBAAgB,CACR","ignoreList":[]}
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports._containerInsert = _containerInsert;
|
||||
exports._containerInsertAfter = _containerInsertAfter;
|
||||
exports._containerInsertBefore = _containerInsertBefore;
|
||||
exports._verifyNodeList = _verifyNodeList;
|
||||
exports.insertAfter = insertAfter;
|
||||
exports.insertBefore = insertBefore;
|
||||
exports.pushContainer = pushContainer;
|
||||
exports.unshiftContainer = unshiftContainer;
|
||||
exports.updateSiblingKeys = updateSiblingKeys;
|
||||
var _cache = require("../cache.js");
|
||||
var _index = require("./index.js");
|
||||
var _context = require("./context.js");
|
||||
var _removal = require("./removal.js");
|
||||
var _t = require("@babel/types");
|
||||
var _hoister = require("./lib/hoister.js");
|
||||
const {
|
||||
arrowFunctionExpression,
|
||||
assertExpression,
|
||||
assignmentExpression,
|
||||
blockStatement,
|
||||
callExpression,
|
||||
cloneNode,
|
||||
expressionStatement,
|
||||
isAssignmentExpression,
|
||||
isCallExpression,
|
||||
isExportNamedDeclaration,
|
||||
isExpression,
|
||||
isIdentifier,
|
||||
isSequenceExpression,
|
||||
isSuper,
|
||||
thisExpression
|
||||
} = _t;
|
||||
function insertBefore(nodes_) {
|
||||
_removal._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(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++) {
|
||||
var _this$context;
|
||||
const to = from + i;
|
||||
const path = this.getSibling(to);
|
||||
paths.push(path);
|
||||
if ((_this$context = this.context) != null && _this$context.queue) {
|
||||
_context.pushContext.call(path, this.context);
|
||||
}
|
||||
}
|
||||
const contexts = _context._getQueueContexts.call(this);
|
||||
for (const path of paths) {
|
||||
_context.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(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_) {
|
||||
_removal._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(node) ? expressionStatement(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(arrowFunctionExpression([], 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());
|
||||
} else if (isAlmostConstantAssignment(node, scope)) {
|
||||
nodes.unshift(node);
|
||||
nodes.push(cloneNode(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(assignmentExpression("=", cloneNode(temp), node)));
|
||||
nodes.push(expressionStatement(cloneNode(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(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 = (0, _cache.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 _index.default) {
|
||||
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) {
|
||||
_removal._assertUnremoved.call(this);
|
||||
const verifiedNodes = _verifyNodeList.call(this, nodes);
|
||||
const container = this.node[listKey];
|
||||
const path = _index.default.get({
|
||||
parentPath: this,
|
||||
parent: this.node,
|
||||
container,
|
||||
listKey,
|
||||
key: 0
|
||||
}).setContext(this.context);
|
||||
return _containerInsertBefore.call(path, verifiedNodes);
|
||||
}
|
||||
function pushContainer(listKey, nodes) {
|
||||
_removal._assertUnremoved.call(this);
|
||||
const verifiedNodes = _verifyNodeList.call(this, nodes);
|
||||
const container = this.node[listKey];
|
||||
const path = _index.default.get({
|
||||
parentPath: this,
|
||||
parent: this.node,
|
||||
container,
|
||||
listKey,
|
||||
key: container.length
|
||||
}).setContext(this.context);
|
||||
return path.replaceWithMultiple(verifiedNodes);
|
||||
}
|
||||
exports.hoist = function hoist(scope = this.scope) {
|
||||
const hoister = new _hoister.default(this, scope);
|
||||
return hoister.run();
|
||||
};
|
||||
|
||||
//# sourceMappingURL=modification.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_cache","require","_index","_context","_removal","_t","_hoister","arrowFunctionExpression","assertExpression","assignmentExpression","blockStatement","callExpression","cloneNode","expressionStatement","isAssignmentExpression","isCallExpression","isExportNamedDeclaration","isExpression","isIdentifier","isSequenceExpression","isSuper","thisExpression","insertBefore","nodes_","_assertUnremoved","call","nodes","_verifyNodeList","parentPath","parent","isExpressionStatement","isLabeledStatement","isExportDefaultDeclaration","isDeclaration","isNodeType","isJSXElement","isForStatement","key","node","push","replaceExpressionWithStatements","Array","isArray","container","_containerInsertBefore","isStatementOrBlock","shouldInsertCurrentNode","expression","blockPath","replaceWith","unshiftContainer","Error","_containerInsert","from","updateSiblingKeys","length","paths","splice","i","_this$context","to","path","getSibling","context","queue","pushContext","contexts","_getQueueContexts","setScope","debug","maybeQueue","_containerInsertAfter","last","arr","isHiddenInSequenceExpression","expressions","isAlmostConstantAssignment","scope","left","blockScope","getBlockParent","hasOwnBinding","name","getOwnBinding","constantViolations","insertAfter","get","map","self","isPattern","unshift","callee","isPure","isMethod","computed","temp","generateDeclaredUidIdentifier","pushContainer","fromIndex","incrementBy","getCachedPaths","msg","type","NodePath","listKey","verifiedNodes","setContext","replaceWithMultiple","exports","hoist","hoister","PathHoister","run"],"sources":["../../src/path/modification.ts"],"sourcesContent":["// This file contains methods that modify the path/node in some ways.\n\nimport { getCachedPaths } from \"../cache.ts\";\nimport NodePath from \"./index.ts\";\nimport { _getQueueContexts, pushContext, setScope } from \"./context.ts\";\nimport { _assertUnremoved } from \"./removal.ts\";\nimport {\n arrowFunctionExpression,\n assertExpression,\n assignmentExpression,\n blockStatement,\n callExpression,\n cloneNode,\n expressionStatement,\n isAssignmentExpression,\n isCallExpression,\n isExportNamedDeclaration,\n isExpression,\n isIdentifier,\n isSequenceExpression,\n isSuper,\n thisExpression,\n} from \"@babel/types\";\nimport type * as t from \"@babel/types\";\nimport type Scope from \"../scope/index.ts\";\nimport type {\n NodeList,\n NodeOrNodeList,\n NodeListType,\n NodePaths,\n} from \"./index.ts\";\n\n/**\n * Insert the provided nodes before the current one.\n */\n\nexport function insertBefore<Nodes extends NodeOrNodeList<t.Node>>(\n this: NodePath,\n nodes_: Nodes,\n): NodePaths<Nodes> {\n _assertUnremoved.call(this);\n\n const nodes = _verifyNodeList.call(this, nodes_);\n\n const { parentPath, parent } = this;\n\n if (\n parentPath.isExpressionStatement() ||\n parentPath.isLabeledStatement() ||\n // https://github.com/babel/babel/issues/15293\n // When Babel transforms `export class String { field }`, the class properties plugin will inject the defineProperty\n // helper, which depends on the builtins e.g. String, Number, Symbol, etc. To prevent them from being shadowed by local\n // exports, the helper injector replaces the named export into `class _String { field }; export { _String as String }`,\n // with `parentPath` here changed to the moved ClassDeclaration, causing rare inconsistency between `parent` and `parentPath`.\n // Here we retrieve the parent type from the `parent` property. This is a temporary fix and we should revisit when\n // helpers should get injected.\n isExportNamedDeclaration(parent) ||\n (parentPath.isExportDefaultDeclaration() && this.isDeclaration())\n ) {\n return parentPath.insertBefore(nodes as Nodes);\n } else if (\n (this.isNodeType(\"Expression\") && !this.isJSXElement()) ||\n (parentPath.isForStatement() && this.key === \"init\")\n ) {\n if (this.node) nodes.push(this.node);\n // @ts-expect-error todo(flow->ts): check that nodes is an array of statements\n return this.replaceExpressionWithStatements(nodes);\n } else if (Array.isArray(this.container)) {\n return _containerInsertBefore.call(this, nodes) as NodePaths<Nodes>;\n } else if (this.isStatementOrBlock()) {\n const node = this.node as t.Statement;\n const shouldInsertCurrentNode =\n node &&\n (!this.isExpressionStatement() ||\n (node as t.ExpressionStatement).expression != null);\n\n const [blockPath] = this.replaceWith(\n blockStatement(shouldInsertCurrentNode ? [node] : []),\n );\n return blockPath.unshiftContainer(\n \"body\",\n nodes as t.Statement[],\n ) as NodePaths<Nodes>;\n } else {\n throw new Error(\n \"We don't know what to do with this node type. \" +\n \"We were previously a Statement but we can't fit in here?\",\n );\n }\n}\n\nexport function _containerInsert<Nodes extends NodeList<t.Node>>(\n this: NodePath,\n from: number,\n Line truncated
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports._assertUnremoved = _assertUnremoved;
|
||||
exports._callRemovalHooks = _callRemovalHooks;
|
||||
exports._markRemoved = _markRemoved;
|
||||
exports._remove = _remove;
|
||||
exports._removeFromScope = _removeFromScope;
|
||||
exports.remove = remove;
|
||||
var _removalHooks = require("./lib/removal-hooks.js");
|
||||
var _cache = require("../cache.js");
|
||||
var _replacement = require("./replacement.js");
|
||||
var _index = require("./index.js");
|
||||
var t = require("@babel/types");
|
||||
var _modification = require("./modification.js");
|
||||
var _context = require("./context.js");
|
||||
function remove() {
|
||||
var _this$opts;
|
||||
_assertUnremoved.call(this);
|
||||
_context.resync.call(this);
|
||||
if (_callRemovalHooks.call(this)) {
|
||||
_markRemoved.call(this);
|
||||
return;
|
||||
}
|
||||
if (!((_this$opts = this.opts) != null && _this$opts.noScope)) {
|
||||
_removeFromScope.call(this);
|
||||
}
|
||||
this.shareCommentsWithSiblings();
|
||||
_remove.call(this);
|
||||
_markRemoved.call(this);
|
||||
}
|
||||
function _removeFromScope() {
|
||||
const bindings = t.getBindingIdentifiers(this.node, false, false, true);
|
||||
Object.keys(bindings).forEach(name => this.scope.removeBinding(name));
|
||||
}
|
||||
function _callRemovalHooks() {
|
||||
if (this.parentPath) {
|
||||
for (const fn of _removalHooks.hooks) {
|
||||
if (fn(this, this.parentPath)) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
function _remove() {
|
||||
if (Array.isArray(this.container)) {
|
||||
this.container.splice(this.key, 1);
|
||||
_modification.updateSiblingKeys.call(this, this.key, -1);
|
||||
} else {
|
||||
_replacement._replaceWith.call(this, null);
|
||||
}
|
||||
}
|
||||
function _markRemoved() {
|
||||
this._traverseFlags |= _index.SHOULD_SKIP | _index.REMOVED;
|
||||
if (this.parent) {
|
||||
var _getCachedPaths;
|
||||
(_getCachedPaths = (0, _cache.getCachedPaths)(this)) == null || _getCachedPaths.delete(this.node);
|
||||
}
|
||||
this.node = null;
|
||||
}
|
||||
function _assertUnremoved() {
|
||||
if (this.removed) {
|
||||
throw this.buildCodeFrameError("NodePath has been removed so is read-only.");
|
||||
}
|
||||
}
|
||||
|
||||
//# sourceMappingURL=removal.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_removalHooks","require","_cache","_replacement","_index","t","_modification","_context","remove","_this$opts","_assertUnremoved","call","resync","_callRemovalHooks","_markRemoved","opts","noScope","_removeFromScope","shareCommentsWithSiblings","_remove","bindings","getBindingIdentifiers","node","Object","keys","forEach","name","scope","removeBinding","parentPath","fn","hooks","Array","isArray","container","splice","key","updateSiblingKeys","_replaceWith","_traverseFlags","SHOULD_SKIP","REMOVED","parent","_getCachedPaths","getCachedPaths","delete","removed","buildCodeFrameError"],"sources":["../../src/path/removal.ts"],"sourcesContent":["// This file contains methods responsible for removing a node.\n\nimport { hooks } from \"./lib/removal-hooks.ts\";\nimport { getCachedPaths } from \"../cache.ts\";\nimport { _replaceWith } from \"./replacement.ts\";\nimport type NodePath from \"./index.ts\";\nimport { REMOVED, SHOULD_SKIP } from \"./index.ts\";\nimport * as t from \"@babel/types\";\nimport { updateSiblingKeys } from \"./modification.ts\";\nimport { resync } from \"./context.ts\";\n\nexport function remove(this: NodePath) {\n _assertUnremoved.call(this);\n\n resync.call(this);\n\n if (_callRemovalHooks.call(this)) {\n _markRemoved.call(this);\n return;\n }\n\n if (!this.opts?.noScope) {\n _removeFromScope.call(this);\n }\n\n this.shareCommentsWithSiblings();\n _remove.call(this);\n _markRemoved.call(this);\n}\n\nexport function _removeFromScope(this: NodePath) {\n const bindings = t.getBindingIdentifiers(this.node, false, false, true);\n Object.keys(bindings).forEach(name => this.scope.removeBinding(name));\n}\n\nexport function _callRemovalHooks(this: NodePath) {\n if (this.parentPath) {\n for (const fn of hooks) {\n if (fn(this, this.parentPath)) return true;\n }\n }\n}\n\nexport function _remove(this: NodePath) {\n if (Array.isArray(this.container)) {\n this.container.splice(this.key as number, 1);\n updateSiblingKeys.call(this, this.key as number, -1);\n } else {\n _replaceWith.call(this, null);\n }\n}\n\nexport function _markRemoved(this: NodePath) {\n // this.shouldSkip = true; this.removed = true;\n this._traverseFlags |= SHOULD_SKIP | REMOVED;\n if (this.parent) {\n getCachedPaths(this)?.delete(this.node);\n }\n // @ts-expect-error TODO: better types\n this.node = null;\n}\n\nexport function _assertUnremoved(this: NodePath) {\n if (this.removed) {\n throw this.buildCodeFrameError(\n \"NodePath has been removed so is read-only.\",\n );\n }\n}\n"],"mappings":";;;;;;;;;;;AAEA,IAAAA,aAAA,GAAAC,OAAA;AACA,IAAAC,MAAA,GAAAD,OAAA;AACA,IAAAE,YAAA,GAAAF,OAAA;AAEA,IAAAG,MAAA,GAAAH,OAAA;AACA,IAAAI,CAAA,GAAAJ,OAAA;AACA,IAAAK,aAAA,GAAAL,OAAA;AACA,IAAAM,QAAA,GAAAN,OAAA;AAEO,SAASO,MAAMA,CAAA,EAAiB;EAAA,IAAAC,UAAA;EACrCC,gBAAgB,CAACC,IAAI,CAAC,IAAI,CAAC;EAE3BC,eAAM,CAACD,IAAI,CAAC,IAAI,CAAC;EAEjB,IAAIE,iBAAiB,CAACF,IAAI,CAAC,IAAI,CAAC,EAAE;IAChCG,YAAY,CAACH,IAAI,CAAC,IAAI,CAAC;IACvB;EACF;EAEA,IAAI,GAAAF,UAAA,GAAC,IAAI,CAACM,IAAI,aAATN,UAAA,CAAWO,OAAO,GAAE;IACvBC,gBAAgB,CAACN,IAAI,CAAC,IAAI,CAAC;EAC7B;EAEA,IAAI,CAACO,yBAAyB,CAAC,CAAC;EAChCC,OAAO,CAACR,IAAI,CAAC,IAAI,CAAC;EAClBG,YAAY,CAACH,IAAI,CAAC,IAAI,CAAC;AACzB;AAEO,SAASM,gBAAgBA,CAAA,EAAiB;EAC/C,MAAMG,QAAQ,GAAGf,CAAC,CAACgB,qBAAqB,CAAC,IAAI,CAACC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC;EACvEC,MAAM,CAACC,IAAI,CAACJ,QAAQ,CAAC,CAACK,OAAO,CAACC,IAAI,IAAI,IAAI,CAACC,KAAK,CAACC,aAAa,CAACF,IAAI,CAAC,CAAC;AACvE;AAEO,SAASb,iBAAiBA,CAAA,EAAiB;EAChD,IAAI,IAAI,CAACgB,UAAU,EAAE;IACnB,KAAK,MAAMC,EAAE,IAAIC,mBAAK,EAAE;MACtB,IAAID,EAAE,CAAC,IAAI,EAAE,IAAI,CAACD,UAAU,CAAC,EAAE,OAAO,IAAI;IAC5C;EACF;AACF;AAEO,SAASV,OAAOA,CAAA,EAAiB;EACtC,IAAIa,KAAK,CAACC,OAAO,CAAC,IAAI,CAACC,SAAS,CAAC,EAAE;IACjC,IAAI,CAACA,SAAS,CAACC,MAAM,CAAC,IAAI,CAACC,GAAG,EAAY,CAAC,CAAC;IAC5CC,+BAAiB,CAAC1B,IAAI,CAAC,IAAI,EAAE,IAAI,CAACyB,GAAG,EAAY,CAAC,CAAC,CAAC;EACtD,CAAC,MAAM;IACLE,yBAAY,CAAC3B,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC;EAC/B;AACF;AAEO,SAASG,YAAYA,CAAA,EAAiB;EAE3C,IAAI,CAACyB,cAAc,IAAIC,kBAAW,GAAGC,cAAO;EAC5C,IAAI,IAAI,CAACC,MAAM,EAAE;IAAA,IAAAC,eAAA;IACf,CAAAA,eAAA,OAAAC,qBAAc,EAAC,IAAI,CAAC,aAApBD,eAAA,CAAsBE,MAAM,CAAC,IAAI,CAACvB,IAAI,CAAC;EACzC;EAEA,IAAI,CAACA,IAAI,GAAG,IAAI;AAClB;AAEO,SAASZ,gBAAgBA,CAAA,EAAiB;EAC/C,IAAI,IAAI,CAACoC,OAAO,EAAE;IAChB,MAAM,IAAI,CAACC,mBAAmB,CAC5B,4CACF,CAAC;EACH;AACF","ignoreList":[]}
|
||||
+264
@@ -0,0 +1,264 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports._replaceWith = _replaceWith;
|
||||
exports.replaceExpressionWithStatements = replaceExpressionWithStatements;
|
||||
exports.replaceInline = replaceInline;
|
||||
exports.replaceWith = replaceWith;
|
||||
exports.replaceWithMultiple = replaceWithMultiple;
|
||||
exports.replaceWithSourceString = replaceWithSourceString;
|
||||
var _codeFrame = require("@babel/code-frame");
|
||||
var _index = require("../index.js");
|
||||
var _index2 = require("./index.js");
|
||||
var _cache = require("../cache.js");
|
||||
var _modification = require("./modification.js");
|
||||
var _parser = require("@babel/parser");
|
||||
var _t = require("@babel/types");
|
||||
var _context = require("./context.js");
|
||||
const {
|
||||
FUNCTION_TYPES,
|
||||
arrowFunctionExpression,
|
||||
assignmentExpression,
|
||||
awaitExpression,
|
||||
blockStatement,
|
||||
buildUndefinedNode,
|
||||
callExpression,
|
||||
cloneNode,
|
||||
conditionalExpression,
|
||||
expressionStatement,
|
||||
getBindingIdentifiers,
|
||||
identifier,
|
||||
inheritLeadingComments,
|
||||
inheritTrailingComments,
|
||||
inheritsComments,
|
||||
isBlockStatement,
|
||||
isEmptyStatement,
|
||||
isExpression,
|
||||
isExpressionStatement,
|
||||
isIfStatement,
|
||||
isProgram,
|
||||
isStatement,
|
||||
isVariableDeclaration,
|
||||
removeComments,
|
||||
returnStatement,
|
||||
sequenceExpression,
|
||||
validate,
|
||||
yieldExpression
|
||||
} = _t;
|
||||
function replaceWithMultiple(nodes) {
|
||||
var _getCachedPaths;
|
||||
_context.resync.call(this);
|
||||
const verifiedNodes = _modification._verifyNodeList.call(this, nodes);
|
||||
inheritLeadingComments(verifiedNodes[0], this.node);
|
||||
inheritTrailingComments(verifiedNodes[verifiedNodes.length - 1], this.node);
|
||||
(_getCachedPaths = (0, _cache.getCachedPaths)(this)) == null || _getCachedPaths.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) {
|
||||
_context.resync.call(this);
|
||||
let ast;
|
||||
try {
|
||||
replacement = `(${replacement})`;
|
||||
ast = (0, _parser.parse)(replacement);
|
||||
} catch (err) {
|
||||
const loc = err.loc;
|
||||
if (loc) {
|
||||
err.message += " - make sure this is an expression.\n" + (0, _codeFrame.codeFrameColumns)(replacement, {
|
||||
start: {
|
||||
line: loc.line,
|
||||
column: loc.column + 1
|
||||
}
|
||||
});
|
||||
err.code = "BABEL_REPLACE_SOURCE_ERROR";
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
const expressionAST = ast.program.body[0].expression;
|
||||
_index.default.removeProperties(expressionAST);
|
||||
return this.replaceWith(expressionAST);
|
||||
}
|
||||
function replaceWith(replacementPath) {
|
||||
_context.resync.call(this);
|
||||
if (this.removed) {
|
||||
throw new Error("You can't replace this node, we've already removed it");
|
||||
}
|
||||
let replacement = replacementPath instanceof _index2.default ? 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(replacement)) {
|
||||
if (!this.canHaveVariableDeclarationOrExpression() && !this.canSwapBetweenExpressionAndStatement(replacement) && !this.parentPath.isExportDefaultDeclaration()) {
|
||||
replacement = expressionStatement(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;
|
||||
_context.setScope.call(this);
|
||||
this.requeue();
|
||||
return [nodePath ? this.get(nodePath) : this];
|
||||
}
|
||||
function _replaceWith(node) {
|
||||
var _getCachedPaths2;
|
||||
if (!this.container) {
|
||||
throw new ReferenceError("Container is falsy");
|
||||
}
|
||||
if (this.inList) {
|
||||
validate(this.parent, this.key, [node]);
|
||||
} else {
|
||||
validate(this.parent, this.key, node);
|
||||
}
|
||||
this.debug(`Replace with ${node == null ? void 0 : node.type}`);
|
||||
(_getCachedPaths2 = (0, _cache.getCachedPaths)(this)) == null || _getCachedPaths2.set(node, this).delete(this.node);
|
||||
this.node = node;
|
||||
this.container[this.key] = node;
|
||||
}
|
||||
function replaceExpressionWithStatements(nodes) {
|
||||
_context.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 == null ? void 0 : functionParent.node.async;
|
||||
const isParentGenerator = functionParent == null ? void 0 : functionParent.node.generator;
|
||||
const container = arrowFunctionExpression([], blockStatement(nodes));
|
||||
this.replaceWith(callExpression(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(cloneNode(uid)));
|
||||
loop.setData("expressionReplacementReturnUid", uid);
|
||||
} else {
|
||||
uid = identifier(uid.name);
|
||||
}
|
||||
path.get("expression").replaceWith(assignmentExpression("=", cloneNode(uid), path.node.expression));
|
||||
} else {
|
||||
path.replaceWith(returnStatement(path.node.expression));
|
||||
}
|
||||
}
|
||||
callee.arrowFunctionToExpression();
|
||||
const newCallee = callee;
|
||||
const needToAwaitFunction = isParentAsync && _index.default.hasType(newCallee.node.body, "AwaitExpression", FUNCTION_TYPES);
|
||||
const needToYieldFunction = isParentGenerator && _index.default.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(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(declar);
|
||||
for (const key of Object.keys(bindings)) {
|
||||
declars.push(cloneNode(bindings[key]));
|
||||
}
|
||||
if (declar.init) {
|
||||
exprs.push(assignmentExpression("=", declar.id, declar.init));
|
||||
}
|
||||
}
|
||||
ensureLastUndefined = true;
|
||||
} else if (isIfStatement(node)) {
|
||||
const consequent = node.consequent ? gatherSequenceExpressions([node.consequent], declars) : buildUndefinedNode();
|
||||
const alternate = node.alternate ? gatherSequenceExpressions([node.alternate], declars) : buildUndefinedNode();
|
||||
if (!consequent || !alternate) return;
|
||||
exprs.push(conditionalExpression(node.test, consequent, alternate));
|
||||
} else if (isBlockStatement(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());
|
||||
if (exprs.length === 1) {
|
||||
return exprs[0];
|
||||
} else {
|
||||
return sequenceExpression(exprs);
|
||||
}
|
||||
}
|
||||
function replaceInline(nodes) {
|
||||
_context.resync.call(this);
|
||||
if (Array.isArray(nodes)) {
|
||||
if (Array.isArray(this.container)) {
|
||||
nodes = _modification._verifyNodeList.call(this, nodes);
|
||||
const paths = _modification._containerInsertAfter.call(this, nodes);
|
||||
this.remove();
|
||||
return paths;
|
||||
} else {
|
||||
return this.replaceWithMultiple(nodes);
|
||||
}
|
||||
} else {
|
||||
return this.replaceWith(nodes);
|
||||
}
|
||||
}
|
||||
|
||||
//# sourceMappingURL=replacement.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_codeFrame","require","_index","_index2","_cache","_modification","_parser","_t","_context","FUNCTION_TYPES","arrowFunctionExpression","assignmentExpression","awaitExpression","blockStatement","buildUndefinedNode","callExpression","cloneNode","conditionalExpression","expressionStatement","getBindingIdentifiers","identifier","inheritLeadingComments","inheritTrailingComments","inheritsComments","isBlockStatement","isEmptyStatement","isExpression","isExpressionStatement","isIfStatement","isProgram","isStatement","isVariableDeclaration","removeComments","returnStatement","sequenceExpression","validate","yieldExpression","replaceWithMultiple","nodes","_getCachedPaths","resync","call","verifiedNodes","_verifyNodeList","node","length","getCachedPaths","delete","container","key","paths","insertAfter","requeue","remove","replaceWithSourceString","replacement","ast","parse","err","loc","message","codeFrameColumns","start","line","column","code","expressionAST","program","body","expression","traverse","removeProperties","replaceWith","replacementPath","removed","Error","NodePath","Array","isArray","nodePath","isNodeType","canHaveVariableDeclarationOrExpression","canSwapBetweenExpressionAndStatement","parentPath","isExportDefaultDeclaration","replaceExpressionWithStatements","oldNode","_replaceWith","type","setScope","get","_getCachedPaths2","ReferenceError","inList","parent","debug","set","declars","nodesAsSingleExpression","gatherSequenceExpressions","id","scope","push","functionParent","getFunctionParent","isParentAsync","async","isParentGenerator","generator","callee","hoistVariables","completionRecords","getCompletionRecords","path","loop","findParent","isLoop","uid","getData","generateDeclaredUidIdentifier","pushContainer","setData","name","arrowFunctionToExpression","newCallee","needToAwaitFunction","hasType","needToYieldFunction","exprs","ensureLastUndefined","kind","declar","declarations","bindings","Object","keys","init","consequent","alternate","test","indexOf","replaceInline","_containerInsertAfter"],"sources":["../../src/path/replacement.ts"],"sourcesContent":["// This file contains methods responsible for replacing a node with another.\n\nimport { codeFrameColumns } from \"@babel/code-frame\";\nimport traverse from \"../index.ts\";\nimport NodePath from \"./index.ts\";\nimport { getCachedPaths } from \"../cache.ts\";\nimport { _verifyNodeList, _containerInsertAfter } from \"./modification.ts\";\nimport { parse } from \"@babel/parser\";\nimport {\n FUNCTION_TYPES,\n arrowFunctionExpression,\n assignmentExpression,\n awaitExpression,\n blockStatement,\n buildUndefinedNode,\n callExpression,\n cloneNode,\n conditionalExpression,\n expressionStatement,\n getBindingIdentifiers,\n identifier,\n inheritLeadingComments,\n inheritTrailingComments,\n inheritsComments,\n isBlockStatement,\n isEmptyStatement,\n isExpression,\n isExpressionStatement,\n isIfStatement,\n isProgram,\n isStatement,\n isVariableDeclaration,\n removeComments,\n returnStatement,\n sequenceExpression,\n validate,\n yieldExpression,\n} from \"@babel/types\";\nimport type * as t from \"@babel/types\";\nimport { resync, setScope } from \"./context.ts\";\n\n/**\n * Replace a node with an array of multiple. This method performs the following steps:\n *\n * - Inherit the comments of first provided node with that of the current node.\n * - Insert the provided nodes after the current node.\n * - Remove the current node.\n */\n\nimport type { NodeOrNodeList, NodePaths } from \"./index.ts\";\n\nexport function replaceWithMultiple<Nodes extends NodeOrNodeList<t.Node>>(\n this: NodePath,\n nodes: Nodes,\n): NodePaths<Nodes> {\n resync.call(this);\n\n const verifiedNodes = _verifyNodeList.call(this, nodes);\n inheritLeadingComments(verifiedNodes[0], this.node);\n inheritTrailingComments(verifiedNodes[verifiedNodes.length - 1], this.node);\n getCachedPaths(this)?.delete(this.node);\n // @ts-expect-error TODO: better types\n this.node =\n // @ts-expect-error this.key must present in this.container\n this.container[this.key] = null;\n const paths = this.insertAfter(nodes);\n\n if (this.node) {\n this.requeue();\n } else {\n this.remove();\n }\n return paths;\n}\n\n/**\n * Parse a string as an expression and replace the current node with the result.\n *\n * NOTE: This is typically not a good idea to use. Building source strings when\n * transforming ASTs is an antipattern and SHOULD NOT be encouraged. Even if it's\n * easier to use, your transforms will be extremely brittle.\n */\n\nexport function replaceWithSourceString(this: NodePath, replacement: string) {\n resync.call(this);\n let ast: t.File;\n\n try {\n replacement = `(${replacement})`;\n ast = parse(replacement);\n } catch (err) {\n const loc = err.loc;\n if (loc) {\n err.message +=\n \" - make sure this is an expression.\\n\" +\n codeFrameColumns(replacement, {\n start: {\n Line truncated
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
class Binding {
|
||||
constructor({
|
||||
identifier,
|
||||
scope,
|
||||
path,
|
||||
kind
|
||||
}) {
|
||||
this.identifier = void 0;
|
||||
this.scope = void 0;
|
||||
this.path = void 0;
|
||||
this.kind = void 0;
|
||||
this.constantViolations = [];
|
||||
this.constant = true;
|
||||
this.referencePaths = [];
|
||||
this.referenced = false;
|
||||
this.references = 0;
|
||||
this.identifier = identifier;
|
||||
this.scope = scope;
|
||||
this.path = path;
|
||||
this.kind = kind;
|
||||
if ((kind === "var" || kind === "hoisted") && isInitInLoop(path)) {
|
||||
this.reassign(path);
|
||||
}
|
||||
this.clearValue();
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
exports.default = Binding;
|
||||
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;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=binding.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["Binding","constructor","identifier","scope","path","kind","constantViolations","constant","referencePaths","referenced","references","isInitInLoop","reassign","clearValue","deoptValue","hasDeoptedValue","setValue","value","hasValue","includes","push","reference","dereference","exports","default","isFunctionDeclarationOrHasInit","isVariableDeclarator","node","init","parentPath","key","isFunctionParent","isForXStatement","isLoop"],"sources":["../../src/scope/binding.ts"],"sourcesContent":["import type NodePath from \"../path/index.ts\";\nimport type * as t from \"@babel/types\";\nimport type Scope from \"./index.ts\";\n\nexport type BindingKind =\n | \"var\" /* var declarator */\n | \"let\" /* let declarator, class declaration id, catch clause parameters */\n | \"const\" /* const/using/await using declarator */\n | \"module\" /* import specifiers */\n | \"hoisted\" /* function declaration id */\n | \"param\" /* function declaration parameters */\n | \"local\" /* function expression id, class expression id */\n | \"unknown\"; /* export specifiers */\n/**\n * This class is responsible for a binding inside of a scope.\n *\n * It tracks the following:\n *\n * * Node path.\n * * Amount of times referenced by other nodes.\n * * Paths to nodes that reassign or modify this binding.\n * * The kind of binding. (Is it a parameter, declaration etc)\n */\n\nexport default class Binding {\n identifier: t.Identifier;\n scope: Scope;\n path: NodePath;\n kind: BindingKind;\n\n constructor({\n identifier,\n scope,\n path,\n kind,\n }: {\n identifier: t.Identifier;\n scope: Scope;\n path: NodePath;\n kind: BindingKind;\n }) {\n this.identifier = identifier;\n this.scope = scope;\n this.path = path;\n this.kind = kind;\n\n if ((kind === \"var\" || kind === \"hoisted\") && isInitInLoop(path)) {\n this.reassign(path);\n }\n\n this.clearValue();\n }\n\n constantViolations: NodePath[] = [];\n constant: boolean = true;\n\n referencePaths: NodePath[] = [];\n referenced: boolean = false;\n references: number = 0;\n\n declare hasDeoptedValue: boolean;\n declare hasValue: boolean;\n declare value: any;\n\n deoptValue() {\n this.clearValue();\n this.hasDeoptedValue = true;\n }\n\n setValue(value: any) {\n if (this.hasDeoptedValue) return;\n this.hasValue = true;\n this.value = value;\n }\n\n clearValue() {\n this.hasDeoptedValue = false;\n this.hasValue = false;\n this.value = null;\n }\n\n /**\n * Register a constant violation with the provided `path`.\n */\n\n reassign(path: NodePath) {\n this.constant = false;\n if (this.constantViolations.includes(path)) {\n return;\n }\n this.constantViolations.push(path);\n }\n\n /**\n * Increment the amount of references to this binding.\n */\n\n reference(path: NodePath) {\n if (this.referencePaths.includes(path)) {\n return;\n }\n this.referenced = true;\n this.references++;\n this.referencePaths.push(path);\n }\n\n /**\n * Decrement the amount of references to this binding.\n */\n\n dereference() {\n this.references--;\n this.referenced = !!this.references;\n }\n}\n\nfunction isInitInLoop(path: NodePath) {\n const isFunctionDeclarationOrHasInit =\n !path.isVariableDeclarator() || path.node.init;\n for (\n let { parentPath, key } = path;\n parentPath;\n { parentPath, key } = parentPath\n ) {\n if (parentPath.isFunctionParent()) return false;\n if (\n (key === \"left\" && parentPath.isForXStatement()) ||\n (isFunctionDeclarationOrHasInit && key === \"body\" && parentPath.isLoop())\n ) {\n return true;\n }\n }\n return false;\n}\n"],"mappings":";;;;;;AAwBe,MAAMA,OAAO,CAAC;EAM3BC,WAAWA,CAAC;IACVC,UAAU;IACVC,KAAK;IACLC,IAAI;IACJC;EAMF,CAAC,EAAE;IAAA,KAfHH,UAAU;IAAA,KACVC,KAAK;IAAA,KACLC,IAAI;IAAA,KACJC,IAAI;IAAA,KAyBJC,kBAAkB,GAAe,EAAE;IAAA,KACnCC,QAAQ,GAAY,IAAI;IAAA,KAExBC,cAAc,GAAe,EAAE;IAAA,KAC/BC,UAAU,GAAY,KAAK;IAAA,KAC3BC,UAAU,GAAW,CAAC;IAjBpB,IAAI,CAACR,UAAU,GAAGA,UAAU;IAC5B,IAAI,CAACC,KAAK,GAAGA,KAAK;IAClB,IAAI,CAACC,IAAI,GAAGA,IAAI;IAChB,IAAI,CAACC,IAAI,GAAGA,IAAI;IAEhB,IAAI,CAACA,IAAI,KAAK,KAAK,IAAIA,IAAI,KAAK,SAAS,KAAKM,YAAY,CAACP,IAAI,CAAC,EAAE;MAChE,IAAI,CAACQ,QAAQ,CAACR,IAAI,CAAC;IACrB;IAEA,IAAI,CAACS,UAAU,CAAC,CAAC;EACnB;EAaAC,UAAUA,CAAA,EAAG;IACX,IAAI,CAACD,UAAU,CAAC,CAAC;IACjB,IAAI,CAACE,eAAe,GAAG,IAAI;EAC7B;EAEAC,QAAQA,CAACC,KAAU,EAAE;IACnB,IAAI,IAAI,CAACF,eAAe,EAAE;IAC1B,IAAI,CAACG,QAAQ,GAAG,IAAI;IACpB,IAAI,CAACD,KAAK,GAAGA,KAAK;EACpB;EAEAJ,UAAUA,CAAA,EAAG;IACX,IAAI,CAACE,eAAe,GAAG,KAAK;IAC5B,IAAI,CAACG,QAAQ,GAAG,KAAK;IACrB,IAAI,CAACD,KAAK,GAAG,IAAI;EACnB;EAMAL,QAAQA,CAACR,IAAc,EAAE;IACvB,IAAI,CAACG,QAAQ,GAAG,KAAK;IACrB,IAAI,IAAI,CAACD,kBAAkB,CAACa,QAAQ,CAACf,IAAI,CAAC,EAAE;MAC1C;IACF;IACA,IAAI,CAACE,kBAAkB,CAACc,IAAI,CAAChB,IAAI,CAAC;EACpC;EAMAiB,SAASA,CAACjB,IAAc,EAAE;IACxB,IAAI,IAAI,CAACI,cAAc,CAACW,QAAQ,CAACf,IAAI,CAAC,EAAE;MACtC;IACF;IACA,IAALine truncated
|
||||
+1018
File diff suppressed because it is too large.
Load diff
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_renamer","require","_index","_traverseForScope","_binding","_t","t","_cache","globalsBuiltinLower","globalsBuiltinUpper","assignmentExpression","callExpression","cloneNode","getBindingIdentifiers","identifier","isArrayExpression","isBinary","isCallExpression","isClass","isClassBody","isClassDeclaration","isExportAllDeclaration","isExportDefaultDeclaration","isExportNamedDeclaration","isFunctionDeclaration","isIdentifier","isImportDeclaration","isLiteral","isMemberExpression","isMethod","isModuleSpecifier","isNullLiteral","isObjectExpression","isProperty","isPureish","isRegExpLiteral","isSuper","isTaggedTemplateExpression","isTemplateLiteral","isThisExpression","isUnaryExpression","isVariableDeclaration","expressionStatement","matchesPattern","memberExpression","numericLiteral","toIdentifier","variableDeclaration","variableDeclarator","isObjectProperty","isTopicReference","isMetaProperty","isPrivateName","isExportDeclaration","buildUndefinedNode","sequenceExpression","gatherNodeParts","node","parts","type","_node$specifiers","source","specifiers","length","e","declaration","local","push","value","object","property","name","callee","properties","argument","key","left","id","expression","meta","openingElement","openingFragment","namespace","resetScope","scope","references","Object","create","uids","bindings","globals","isAnonymousFunctionExpression","path","isFunctionExpression","isArrowFunctionExpression","NOT_LOCAL_BINDING","Symbol","for","collectorVisitor","ForStatement","declar","get","isVar","parentScope","getFunctionParent","getProgramParent","registerBinding","Declaration","isBlockScoped","parent","registerDeclaration","ImportDeclaration","getBlockParent","TSImportEqualsDeclaration","ReferencedIdentifier","state","isTSQualifiedName","right","parentPath","isTSImportEqualsDeclaration","ForXStatement","isPattern","constantViolations","ExportDeclaration","exit","binding","getBinding","reference","decl","declarations","keys","LabeledStatement","AssignmentExpression","assignments","UpdateExpression","UnaryExpression","operator","BlockScoped","CatchClause","Function","params","param","ClassExpression","TSTypeAnnotation","skip","scopeVisitor","uid","Scope","constructor","block","inited","labels","referencesSet","uidsSet","data","crawling","cached","scopeCache","set","Map","defineProperties","enumerable","configurable","writable","_parent","_path","shouldSkip","listKey","isScope","Error","generateDeclaredUidIdentifier","generateUidIdentifier","generateUid","replace","i","hasLabel","hasBinding","hasGlobal","hasReference","program","generateUidBasedOnNode","defaultName","join","slice","generateUidIdentifierBasedOnNode","isStatic","constant","maybeGenerateMemoised","dontPush","checkBlockScopedCollisions","kind","duplicate","hub","buildError","TypeError","rename","oldName","newName","renamer","Renamer","arguments","dump","sep","repeat","console","log","violations","getLabel","registerLabel","label","isLabeledStatement","declare","isTypeDeclaration","importKind","specifier","isTypeSpecifier","isImportSpecifier","registerConstantViolation","ids","getAssignmentIdentifiers","_this$getBinding","reassign","bindingPath","ReferenceError","declarators","getOuterBindingIdentifiers","getOwnBinding","Binding","addGlobal","hasUid","isPure","constantsOnly","_node$decorators","superClass","decorators","body","method","elem","elements","prop","_node$decorators2","computed","_node$decorators3","static","expressions","tag","noGlobals","quasi","isStringLiteral","setData","val","getData","removeData","init","crawl","isProgram","programParent","traverse","visitors","merge","typeVisitors","visit","enter","call","ref","opts","getPatternParent","isBlockStatement","isSwitchStatement","unique","pushContainer","isLoop","isCatchClause","isFunction","ensureBlock","blockHoist","_blockHoist","dataKey","declarPath","unshiftContainer","declarator","len","isFunctionParent","isBlockParent","getAllBindings","bindingIdentifierEquals","getBindingIdentifier","previousPath","_previousPath","_this$getBinding2","getOwnBindingIdentifier","hasOwnBinding","noUids","upToScope","includes","contextVariables","parentHasBinding","_this$parent","moveBindingTo","info","removeOwnBinding","removeBinding","_this$getBinding3","hoistVariables","emit","seen","Set","isVariableDeclarator","has","add","firstId","isForXStatement","replaceWith","remove","expr","isForStatement","exports","default","prototype","_renameFromMap","map","_generateUid","toArray","arrayLikeIsIterable","isGenericType","helperName","args","unshift","addHelper","getAllBindingsOfKind","kinds","parentBlock"],"sources":["../../src/scope/index.ts"],"sourcesContent":["import Renamer from \"./lib/renamer.ts\";\nimport type NodePath from \"../path/index.ts\";\nimport traverse from \"../index.ts\";\nimport traverseForScope from \"./traverseForScope.ts\";\nimport Binding from \"./binding.ts\";\nimport type { BindingKind } from \"./binding.ts\";\nimport globalsBuiltinLower from \"@babel/helLine truncated
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var t = require("@babel/types");
|
||||
var _t = t;
|
||||
var _traverseNode = require("../../traverse-node.js");
|
||||
var _visitors = require("../../visitors.js");
|
||||
var _context = require("../../path/context.js");
|
||||
const {
|
||||
getAssignmentIdentifiers
|
||||
} = _t;
|
||||
const renameVisitor = {
|
||||
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()) {
|
||||
if (!path.requeueComputedKeyAndDecorators) {
|
||||
_context.requeueComputedKeyAndDecorators.call(path);
|
||||
} else {
|
||||
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) {
|
||||
var _node$extra;
|
||||
node.shorthand = false;
|
||||
if ((_node$extra = node.extra) != null && _node$extra.shorthand) node.extra.shorthand = false;
|
||||
}
|
||||
},
|
||||
"AssignmentExpression|Declaration|VariableDeclarator"(path, state) {
|
||||
if (path.isVariableDeclaration()) return;
|
||||
const ids = path.isAssignmentExpression() ? getAssignmentIdentifiers(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 = arguments[0] || scope.block;
|
||||
const skipKeys = {
|
||||
discriminant: true
|
||||
};
|
||||
if (t.isMethod(blockToTraverse)) {
|
||||
if (blockToTraverse.computed) {
|
||||
skipKeys.key = true;
|
||||
}
|
||||
if (!t.isObjectMethod(blockToTraverse)) {
|
||||
skipKeys.decorators = true;
|
||||
}
|
||||
}
|
||||
(0, _traverseNode.traverseNode)(blockToTraverse, (0, _visitors.explode)(renameVisitor), scope, this, scope.path, skipKeys);
|
||||
if (!arguments[0]) {
|
||||
scope.removeOwnBinding(oldName);
|
||||
scope.bindings[newName] = binding;
|
||||
this.binding.identifier.name = newName;
|
||||
}
|
||||
if (parentDeclar) {
|
||||
this.maybeConvertFromClassFunctionDeclaration(path);
|
||||
this.maybeConvertFromClassFunctionExpression(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.default = Renamer;
|
||||
|
||||
//# sourceMappingURL=renamer.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["t","require","_t","_traverseNode","_visitors","_context","getAssignmentIdentifiers","renameVisitor","ReferencedIdentifier","node","state","name","oldName","newName","Scope","path","scope","bindingIdentifierEquals","binding","identifier","skip","isMethod","requeueComputedKeyAndDecorators","call","isSwitchStatement","context","maybeQueue","get","ObjectProperty","key","shorthand","getBindingIdentifier","_node$extra","extra","AssignmentExpression|Declaration|VariableDeclarator","isVariableDeclaration","ids","isAssignmentExpression","getOuterBindingIdentifiers","Renamer","constructor","maybeConvertFromExportDeclaration","parentDeclar","maybeExportDeclar","parentPath","isExportDeclaration","isExportDefaultDeclaration","declaration","isDeclaration","id","isExportAllDeclaration","splitExportDeclaration","maybeConvertFromClassFunctionDeclaration","maybeConvertFromClassFunctionExpression","rename","find","isFunctionExpression","isClassExpression","bindingIds","blockToTraverse","arguments","block","skipKeys","discriminant","computed","isObjectMethod","decorators","traverseNode","explode","removeOwnBinding","bindings","exports","default"],"sources":["../../../src/scope/lib/renamer.ts"],"sourcesContent":["import type Binding from \"../binding.ts\";\nimport * as t from \"@babel/types\";\nimport type { NodePath, Visitor } from \"../../index.ts\";\nimport { traverseNode } from \"../../traverse-node.ts\";\nimport { explode } from \"../../visitors.ts\";\nimport { getAssignmentIdentifiers, type Identifier } from \"@babel/types\";\nimport { requeueComputedKeyAndDecorators } from \"../../path/context.ts\";\n\nconst renameVisitor: Visitor<Renamer> = {\n ReferencedIdentifier({ node }, state) {\n if (node.name === state.oldName) {\n node.name = state.newName;\n }\n },\n\n Scope(path, state) {\n if (\n !path.scope.bindingIdentifierEquals(\n state.oldName,\n state.binding.identifier,\n )\n ) {\n path.skip();\n if (path.isMethod()) {\n if (\n !process.env.BABEL_8_BREAKING &&\n !path.requeueComputedKeyAndDecorators\n ) {\n // See https://github.com/babel/babel/issues/16694\n requeueComputedKeyAndDecorators.call(path);\n } else {\n path.requeueComputedKeyAndDecorators();\n }\n }\n if (path.isSwitchStatement()) {\n path.context.maybeQueue(path.get(\"discriminant\"));\n }\n }\n },\n\n ObjectProperty({ node, scope }, state) {\n const { name } = node.key as Identifier;\n if (\n node.shorthand &&\n // In destructuring the identifier is already renamed by the\n // AssignmentExpression|Declaration|VariableDeclarator visitor,\n // while in object literals it's renamed later by the\n // ReferencedIdentifier visitor.\n (name === state.oldName || name === state.newName) &&\n // Ignore shadowed bindings\n scope.getBindingIdentifier(name) === state.binding.identifier\n ) {\n node.shorthand = false;\n if (!process.env.BABEL_8_BREAKING) {\n if (node.extra?.shorthand) node.extra.shorthand = false;\n }\n }\n },\n\n \"AssignmentExpression|Declaration|VariableDeclarator\"(\n path: NodePath<\n t.AssignmentExpression | t.Declaration | t.VariableDeclarator\n >,\n state,\n ) {\n if (path.isVariableDeclaration()) return;\n const ids = path.isAssignmentExpression()\n ? // See https://github.com/babel/babel/issues/16694\n getAssignmentIdentifiers(path.node)\n : path.getOuterBindingIdentifiers();\n\n for (const name in ids) {\n if (name === state.oldName) ids[name].name = state.newName;\n }\n },\n};\n\nexport default class Renamer {\n constructor(binding: Binding, oldName: string, newName: string) {\n this.newName = newName;\n this.oldName = oldName;\n this.binding = binding;\n }\n\n declare oldName: string;\n declare newName: string;\n declare binding: Binding;\n\n maybeConvertFromExportDeclaration(parentDeclar: NodePath) {\n const maybeExportDeclar = parentDeclar.parentPath;\n\n if (!maybeExportDeclar.isExportDeclaration()) {\n return;\n }\n\n if (maybeExportDeclar.isExportDefaultDeclaration()) {\n const { declaration } = maybeExportDeclar.node;\n if (t.isDeclaration(declaration) && !declaration.id) {\n return;\n }\n }\n\n if (maybeExportDeclar.isExportAllDeclaration()) {\n return;\n }\n\n maybeExportDeclar.splitExportDeclaration();\n }\n\n maybeConvertFromClassFunctionDeclaration(path: NodePath) {\n return path; // TODO\n\n // // retain the `name` of a class/function declaration\n\n // if (!path.isFunctionDeclaration() && !path.isClassDeclaration()) return;\n // if (this.binding.kind !== \"hoisted\") return;\n\n // path.node.id = identifier(this.oldName);\n // path.node._blockHoist = 3;\n\n // path.replaceWith(\n // variableDeclaration(\"let\", [\n // variaLine truncated
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = traverseForScope;
|
||||
var _t = require("@babel/types");
|
||||
var _index = require("../index.js");
|
||||
var _visitors = require("../visitors.js");
|
||||
var _context = require("../path/context.js");
|
||||
const {
|
||||
VISITOR_KEYS
|
||||
} = _t;
|
||||
function traverseForScope(path, visitors, state) {
|
||||
const exploded = (0, _visitors.explode)(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 || _index.NodePath.get({
|
||||
hub,
|
||||
parentPath,
|
||||
parent,
|
||||
container,
|
||||
listKey,
|
||||
key
|
||||
});
|
||||
_context._forceSetScope.call(path);
|
||||
const visitor = exploded[node.type];
|
||||
if (visitor != null && visitor.enter) {
|
||||
for (const visit of visitor.enter) {
|
||||
visit.call(state, path, state);
|
||||
}
|
||||
}
|
||||
if (path.shouldSkip) {
|
||||
return;
|
||||
}
|
||||
const keys = VISITOR_KEYS[node.type];
|
||||
if (!(keys != null && 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 != null && visitor.exit) {
|
||||
for (const visit of visitor.exit) {
|
||||
visit.call(state, path, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//# sourceMappingURL=traverseForScope.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_t","require","_index","_visitors","_context","VISITOR_KEYS","traverseForScope","path","visitors","state","exploded","explode","enter","exit","Error","_traverse","parentPath","parent","node","container","key","listKey","hub","inPath","NodePath","get","_forceSetScope","call","visitor","type","visit","shouldSkip","keys","length","prop","Array","isArray","i","value"],"sources":["../../src/scope/traverseForScope.ts"],"sourcesContent":["import { VISITOR_KEYS } from \"@babel/types\";\nimport type * as t from \"@babel/types\";\nimport type { HubInterface, Visitor } from \"../index.ts\";\nimport { NodePath } from \"../index.ts\";\nimport { explode } from \"../visitors.ts\";\nimport { _forceSetScope } from \"../path/context.ts\";\n\nexport default function traverseForScope(\n path: NodePath,\n visitors: Visitor,\n state: any,\n) {\n const exploded = explode(visitors);\n\n if (exploded.enter || exploded.exit) {\n throw new Error(\"Should not be used with enter/exit visitors.\");\n }\n\n _traverse(\n path.parentPath,\n path.parent,\n path.node,\n path.container!,\n path.key!,\n path.listKey,\n path.hub,\n path,\n );\n\n function _traverse(\n parentPath: NodePath,\n parent: t.Node,\n node: t.Node,\n container: t.Node | t.Node[],\n key: string | number,\n listKey: string | null | undefined,\n hub?: HubInterface,\n inPath?: NodePath,\n ) {\n if (!node) {\n return;\n }\n\n const path =\n inPath ||\n NodePath.get({\n hub,\n parentPath,\n parent,\n container,\n listKey,\n key,\n });\n\n _forceSetScope.call(path);\n\n const visitor = exploded[node.type];\n if (visitor?.enter) {\n for (const visit of visitor.enter) {\n visit.call(state, path, state);\n }\n }\n\n if (path.shouldSkip) {\n return;\n }\n\n const keys = VISITOR_KEYS[node.type];\n if (!keys?.length) {\n return;\n }\n\n for (const key of keys) {\n // @ts-expect-error key must present in node\n const prop = node[key];\n if (!prop) continue;\n if (Array.isArray(prop)) {\n for (let i = 0; i < prop.length; i++) {\n const value = prop[i];\n _traverse(path, node, value, prop, i, key);\n }\n } else {\n _traverse(path, node, prop, node, key, null);\n }\n }\n\n if (visitor?.exit) {\n for (const visit of visitor.exit) {\n visit.call(state, path, state);\n }\n }\n }\n}\n"],"mappings":";;;;;;AAAA,IAAAA,EAAA,GAAAC,OAAA;AAGA,IAAAC,MAAA,GAAAD,OAAA;AACA,IAAAE,SAAA,GAAAF,OAAA;AACA,IAAAG,QAAA,GAAAH,OAAA;AAAoD;EAL3CI;AAAY,IAAAL,EAAA;AAON,SAASM,gBAAgBA,CACtCC,IAAc,EACdC,QAAiB,EACjBC,KAAU,EACV;EACA,MAAMC,QAAQ,GAAG,IAAAC,iBAAO,EAACH,QAAQ,CAAC;EAElC,IAAIE,QAAQ,CAACE,KAAK,IAAIF,QAAQ,CAACG,IAAI,EAAE;IACnC,MAAM,IAAIC,KAAK,CAAC,8CAA8C,CAAC;EACjE;EAEAC,SAAS,CACPR,IAAI,CAACS,UAAU,EACfT,IAAI,CAACU,MAAM,EACXV,IAAI,CAACW,IAAI,EACTX,IAAI,CAACY,SAAS,EACdZ,IAAI,CAACa,GAAG,EACRb,IAAI,CAACc,OAAO,EACZd,IAAI,CAACe,GAAG,EACRf,IACF,CAAC;EAED,SAASQ,SAASA,CAChBC,UAAoB,EACpBC,MAAc,EACdC,IAAY,EACZC,SAA4B,EAC5BC,GAAoB,EACpBC,OAAkC,EAClCC,GAAkB,EAClBC,MAAiB,EACjB;IACA,IAAI,CAACL,IAAI,EAAE;MACT;IACF;IAEA,MAAMX,IAAI,GACRgB,MAAM,IACNC,eAAQ,CAACC,GAAG,CAAC;MACXH,GAAG;MACHN,UAAU;MACVC,MAAM;MACNE,SAAS;MACTE,OAAO;MACPD;IACF,CAAC,CAAC;IAEJM,uBAAc,CAACC,IAAI,CAACpB,IAAI,CAAC;IAEzB,MAAMqB,OAAO,GAAGlB,QAAQ,CAACQ,IAAI,CAACW,IAAI,CAAC;IACnC,IAAID,OAAO,YAAPA,OAAO,CAAEhB,KAAK,EAAE;MAClB,KAAK,MAAMkB,KAAK,IAAIF,OAAO,CAAChB,KAAK,EAAE;QACjCkB,KAAK,CAACH,IAAI,CAAClB,KAAK,EAAEF,IAAI,EAAEE,KAAK,CAAC;MAChC;IACF;IAEA,IAAIF,IAAI,CAACwB,UAAU,EAAE;MACnB;IACF;IAEA,MAAMC,IAAI,GAAG3B,YAAY,CAACa,IAAI,CAACW,IAAI,CAAC;IACpC,IAAI,EAACG,IAAI,YAAJA,IAAI,CAAEC,MAAM,GAAE;MACjB;IACF;IAEA,KAAK,MAAMb,GAAG,IAAIY,IAAI,EAAE;MAEtB,MAAME,IAAI,GAAGhB,IAAI,CAACE,GAAG,CAAC;MACtB,IAAI,CAACc,IAAI,EAAE;MACX,IAAIC,KAAK,CAACC,OAAO,CAACF,IAAI,CAAC,EAAE;QACvB,KAAK,IAAIG,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGH,IAAI,CAACD,MAAM,EAAEI,CAAC,EAAE,EAAE;UACpC,MAAMC,KAAK,GAAGJ,IAAI,CAACG,CAAC,CAAC;UACrBtB,SAAS,CAACR,IAAI,EAAEW,IAAI,EAAEoB,KAAK,EAAEJ,IAAI,EAAEG,CAAC,EAAEjB,GAAG,CAAC;QAC5C;MACF,CAAC,MAAM;QACLL,SAAS,CAACR,IAAI,EAAEW,IAAI,EAAEgB,IAAI,EAAEhB,IAAI,EAAEE,GAAG,EAAE,IAAI,CAAC;MAC9C;IACF;IAEA,IAAIQ,OAAO,YAAPA,OAAO,CAAEf,IAAI,EAAE;MACjB,KAAK,MAAMiB,KAAK,IAAIF,OAAO,CAACf,IAAI,EAAE;QAChCiB,KAAK,CAACH,IAAI,CAAClB,KAAK,EAAEF,IAAI,EAAEE,KAAK,CAAC;MAChC;IACF;EACF;AACF","ignoreList":[]}
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.traverseNode = traverseNode;
|
||||
var _context = require("./context.js");
|
||||
var _index = require("./path/index.js");
|
||||
var _t = require("@babel/types");
|
||||
var _context2 = require("./path/context.js");
|
||||
const {
|
||||
VISITOR_KEYS
|
||||
} = _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++;
|
||||
_context2.resync.call(path);
|
||||
if (path.contexts.length === 0 || path.contexts[path.contexts.length - 1] !== ctx) {
|
||||
_context2.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++) {
|
||||
_context2.popContext.call(paths[i]);
|
||||
}
|
||||
ctx.queue = null;
|
||||
return stop;
|
||||
}
|
||||
function _visit(ctx, path) {
|
||||
var _opts$denylist;
|
||||
const node = path.node;
|
||||
if (!node) {
|
||||
return false;
|
||||
}
|
||||
const opts = ctx.opts;
|
||||
const denylist = (_opts$denylist = opts.denylist) != null ? _opts$denylist : opts.blacklist;
|
||||
if (denylist != null && denylist.includes(node.type)) {
|
||||
return false;
|
||||
}
|
||||
if (opts.shouldSkip != null && opts.shouldSkip(path)) {
|
||||
return false;
|
||||
}
|
||||
if (path.shouldSkip) return path.shouldStop;
|
||||
if (_context2._call.call(path, opts.enter)) return path.shouldStop;
|
||||
if (path.node) {
|
||||
var _opts$node$type;
|
||||
if (_context2._call.call(path, (_opts$node$type = opts[node.type]) == null ? void 0 : _opts$node$type.enter)) return path.shouldStop;
|
||||
}
|
||||
path.shouldStop = _traverse(path.node, opts, path.scope, ctx.state, path, path.skipKeys);
|
||||
if (path.node) {
|
||||
if (_context2._call.call(path, opts.exit)) return true;
|
||||
}
|
||||
if (path.node) {
|
||||
var _opts$node$type2;
|
||||
_context2._call.call(path, (_opts$node$type2 = opts[node.type]) == null ? void 0 : _opts$node$type2.exit);
|
||||
}
|
||||
return path.shouldStop;
|
||||
}
|
||||
function _traverse(node, opts, scope, state, path, skipKeys, visitSelf) {
|
||||
const keys = VISITOR_KEYS[node.type];
|
||||
if (!(keys != null && keys.length)) return false;
|
||||
const ctx = new _context.default(scope, opts, state, path);
|
||||
if (visitSelf) {
|
||||
if (skipKeys != null && skipKeys[path.parentKey]) return false;
|
||||
return _visitPaths(ctx, [path]);
|
||||
}
|
||||
for (const key of keys) {
|
||||
if (skipKeys != null && 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 = _index.default.get({
|
||||
parentPath: path,
|
||||
parent: node,
|
||||
container: prop,
|
||||
key: i,
|
||||
listKey: key
|
||||
});
|
||||
paths.push(childPath);
|
||||
}
|
||||
if (_visitPaths(ctx, paths)) return true;
|
||||
} else {
|
||||
if (_visitPaths(ctx, [_index.default.get({
|
||||
parentPath: path,
|
||||
parent: node,
|
||||
container: node,
|
||||
key,
|
||||
listKey: null
|
||||
})])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function traverseNode(node, opts, scope, state, path, skipKeys, visitSelf) {
|
||||
const keys = VISITOR_KEYS[node.type];
|
||||
if (!keys) return false;
|
||||
const context = new _context.default(scope, opts, state, path);
|
||||
if (visitSelf) {
|
||||
if (skipKeys != null && skipKeys[path.parentKey]) return false;
|
||||
return context.visitQueue([path]);
|
||||
}
|
||||
for (const key of keys) {
|
||||
if (skipKeys != null && skipKeys[key]) continue;
|
||||
if (context.visit(node, key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=traverse-node.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["_context","require","_index","_t","_context2","VISITOR_KEYS","_visitPaths","ctx","paths","queue","priorityQueue","visited","Set","stop","visitIndex","length","path","resync","call","contexts","pushContext","key","node","has","add","_visit","i","popContext","_opts$denylist","opts","denylist","blacklist","includes","type","shouldSkip","shouldStop","_call","enter","_opts$node$type","_traverse","scope","state","skipKeys","exit","_opts$node$type2","visitSelf","keys","TraversalContext","parentKey","prop","Array","isArray","childPath","NodePath","get","parentPath","parent","container","listKey","push","traverseNode","context","visitQueue","visit"],"sources":["../src/traverse-node.ts"],"sourcesContent":["import TraversalContext from \"./context.ts\";\nimport type { ExplodedTraverseOptions } from \"./index.ts\";\nimport NodePath from \"./path/index.ts\";\nimport type Scope from \"./scope/index.ts\";\nimport type * as t from \"@babel/types\";\nimport { VISITOR_KEYS } from \"@babel/types\";\nimport { _call, popContext, pushContext, resync } from \"./path/context.ts\";\n\nfunction _visitPaths(ctx: TraversalContext, paths: NodePath[]): boolean {\n // set queue\n ctx.queue = paths;\n ctx.priorityQueue = [];\n\n const visited = new Set();\n let stop = false;\n let visitIndex = 0;\n\n for (; visitIndex < paths.length; ) {\n const path = paths[visitIndex];\n visitIndex++;\n\n resync.call(path);\n\n if (\n path.contexts.length === 0 ||\n path.contexts[path.contexts.length - 1] !== ctx\n ) {\n // The context might already have been pushed when this path was inserted and queued.\n // If we always re-pushed here, we could get duplicates and risk leaving contexts\n // on the stack after the traversal has completed, which could break things.\n pushContext.call(path, ctx);\n }\n\n // this path no longer belongs to the tree\n if (path.key === null) continue;\n\n // ensure we don't visit the same node twice\n const { node } = path;\n if (visited.has(node)) continue;\n if (node) visited.add(node);\n\n if (_visit(ctx, path)) {\n stop = true;\n break;\n }\n\n if (ctx.priorityQueue.length) {\n stop = _visitPaths(ctx, ctx.priorityQueue);\n ctx.priorityQueue = [];\n ctx.queue = paths;\n if (stop) break;\n }\n }\n\n // pop contexts\n for (let i = 0; i < visitIndex; i++) {\n popContext.call(paths[i]);\n }\n\n // clear queue\n ctx.queue = null;\n\n return stop;\n}\n\nfunction _visit(ctx: TraversalContext, path: NodePath) {\n const node = path.node;\n if (!node) {\n return false;\n }\n const opts = ctx.opts;\n\n // @ts-expect-error TODO(Babel 8): Remove blacklist\n const denylist = opts.denylist ?? opts.blacklist;\n if (denylist?.includes(node.type)) {\n return false;\n }\n\n if (opts.shouldSkip?.(path)) {\n return false;\n }\n\n // Note: We need to check \"this.shouldSkip\" first because\n // another visitor can set it to true. Usually .shouldSkip is false\n // before calling the enter visitor, but it can be true in case of\n // a requeued node (e.g. by .replaceWith()) that is then marked\n // with .skip().\n if (path.shouldSkip) return path.shouldStop;\n\n if (_call.call(path, opts.enter)) return path.shouldStop;\n if (path.node) {\n if (_call.call(path, opts[node.type]?.enter)) return path.shouldStop;\n }\n\n path.shouldStop = _traverse(\n path.node,\n opts,\n path.scope,\n ctx.state,\n path,\n path.skipKeys,\n );\n\n if (path.node) {\n if (_call.call(path, opts.exit)) return true;\n }\n if (path.node) {\n _call.call(path, opts[node.type]?.exit);\n }\n\n return path.shouldStop;\n}\n\nfunction _traverse<S>(\n node: t.Node,\n opts: ExplodedTraverseOptions<S>,\n scope?: Scope | null,\n state?: S,\n path?: NodePath,\n skipKeys?: Record<string, boolean> | null,\n visitSelf?: boolean,\n) {\n const keys = VISITOR_KEYS[node.type];\n if (!keys?.length) return false;\n\n const ctx = new TraversalContext(scope, opts, state, path);\n if (visitSelf) {\n if (skipKeys?.[path!.parentKey]) return false;\n return _visitPaths(ctx, [path!]);\n }\n\n for (const key of keys) {\n if (skipKeys?.[key]) continue;\n // @ts-expect-error key must present in node\n const prop = node[key];\n if (!prop) continue;\n\n if (Array.isArray(prop)) {\n if (!prop.length) continue;\n const paths = [];\n for (let i = 0; i < prop.length; i++) {\n const childPath = NodePath.get({\n parentPath: path,\n parent: node,\n container: prop,\n key: i,\n listKey: key,\n });\n paths.push(childPath);\n }\n if (_visitPaths(ctx, paths)) return true;\n } else {\n if (\n _visitPaths(ctx, [\n NodePath.get({\n parentPath: path,\n parent: node,\n container: node,\n key,\n listKey: null,\n Line truncated
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
|
||||
//# sourceMappingURL=types.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":[],"sources":["../src/types.ts"],"sourcesContent":["import type * as t from \"@babel/types\";\nimport type { NodePath } from \"./index.ts\";\nimport type { VirtualTypeAliases } from \"./path/lib/virtual-types.ts\";\nimport type {\n ExplVisitorBase,\n VisitorBaseNodes,\n VisitorBaseAliases,\n} from \"./generated/visitor-types.d.ts\";\n\nexport type VisitPhase = \"enter\" | \"exit\";\n\ninterface VisitNodeObject<S, P extends t.Node> {\n enter?: VisitNodeFunction<S, P>;\n exit?: VisitNodeFunction<S, P>;\n}\n\nexport interface ExplVisitNode<S, P extends t.Node> {\n enter?: VisitNodeFunction<S, P>[];\n exit?: VisitNodeFunction<S, P>[];\n}\n\nexport interface ExplodedVisitor<S = unknown>\n extends ExplVisitorBase<S>,\n ExplVisitNode<S, t.Node> {\n _exploded: true;\n _verified: true;\n}\n\n// TODO: Assert that the keys of this are the keys of VirtualTypeAliases without\n// the keys of VisitorBaseNodes and VisitorBaseAliases\n// prettier-ignore\ninterface VisitorVirtualAliases<S> {\n BindingIdentifier?: VisitNode<S, VirtualTypeAliases[\"BindingIdentifier\"]>;\n BlockScoped?: VisitNode<S, VirtualTypeAliases[\"BlockScoped\"]>;\n ExistentialTypeParam?: VisitNode<S, VirtualTypeAliases[\"ExistentialTypeParam\"]>;\n Expression?: VisitNode<S, VirtualTypeAliases[\"Expression\"]>;\n //Flow?: VisitNode<S, VirtualTypeAliases[\"Flow\"]>;\n ForAwaitStatement?: VisitNode<S, VirtualTypeAliases[\"ForAwaitStatement\"]>;\n Generated?: VisitNode<S, VirtualTypeAliases[\"Generated\"]>;\n NumericLiteralTypeAnnotation?: VisitNode<S, VirtualTypeAliases[\"NumericLiteralTypeAnnotation\"]>;\n Pure?: VisitNode<S, VirtualTypeAliases[\"Pure\"]>;\n Referenced?: VisitNode<S, VirtualTypeAliases[\"Referenced\"]>;\n ReferencedIdentifier?: VisitNode<S, VirtualTypeAliases[\"ReferencedIdentifier\"]>;\n ReferencedMemberExpression?: VisitNode<S, VirtualTypeAliases[\"ReferencedMemberExpression\"]>;\n //RestProperty?: VisitNode<S, VirtualTypeAliases[\"RestProperty\"]>;\n Scope?: VisitNode<S, VirtualTypeAliases[\"Scope\"]>;\n //SpreadProperty?: VisitNode<S, VirtualTypeAliases[\"SpreadProperty\"]>;\n Statement?: VisitNode<S, VirtualTypeAliases[\"Statement\"]>;\n User?: VisitNode<S, VirtualTypeAliases[\"User\"]>;\n Var?: VisitNode<S, VirtualTypeAliases[\"Var\"]>;\n}\n\n// TODO: Do not export this? Or give it a better name?\nexport interface VisitorBase<S>\n extends VisitNodeObject<S, t.Node>,\n VisitorBaseNodes<S>,\n VisitorBaseAliases<S>,\n VisitorVirtualAliases<S>,\n // Babel supports `NodeTypesWithoutComment | NodeTypesWithoutComment | ... ` but it is\n // too complex for TS. So we type it as a general visitor only if the key contains `|`\n // this is good enough for non-visitor traverse options e.g. `noScope`\n Record<`${string}|${string}`, VisitNode<S, t.Node>> {}\n\nexport type Visitor<S = unknown> = VisitorBase<S> | ExplodedVisitor<S>;\n\nexport type VisitNode<S, P extends t.Node> =\n | VisitNodeFunction<S, P>\n | VisitNodeObject<S, P>;\n\nexport type VisitNodeFunction<S, P extends t.Node> = (\n this: S,\n path: NodePath<P>,\n state: S,\n) => void;\n"],"mappings":"","ignoreList":[]}
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.environmentVisitor = environmentVisitor;
|
||||
exports.explode = explode$1;
|
||||
exports.isExplodedVisitor = isExplodedVisitor;
|
||||
exports.merge = merge;
|
||||
exports.verify = verify$1;
|
||||
var virtualTypes = require("./path/lib/virtual-types.js");
|
||||
var virtualTypesValidators = require("./path/lib/virtual-types-validator.js");
|
||||
var _t = require("@babel/types");
|
||||
var _context = require("./path/context.js");
|
||||
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 == null ? void 0 : visitor._exploded;
|
||||
}
|
||||
function explode$1(visitor) {
|
||||
if (isExplodedVisitor(visitor)) return visitor;
|
||||
visitor._exploded = true;
|
||||
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);
|
||||
for (const nodeType of Object.keys(visitor)) {
|
||||
if (shouldIgnoreKey(nodeType)) continue;
|
||||
if (!isVirtualType(nodeType)) continue;
|
||||
const fns = visitor[nodeType];
|
||||
for (const type of Object.keys(fns)) {
|
||||
fns[type] = wrapCheck(nodeType, fns[type]);
|
||||
}
|
||||
delete visitor[nodeType];
|
||||
const types = virtualTypes[nodeType];
|
||||
if (types !== null) {
|
||||
for (const type of types) {
|
||||
var _visitor$type;
|
||||
(_visitor$type = visitor[type]) != null ? _visitor$type : visitor[type] = {};
|
||||
mergePair(visitor[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 = visitor[alias];
|
||||
if (existing) {
|
||||
mergePair(existing, fns);
|
||||
} else {
|
||||
visitor[alias] = Object.assign({}, 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 ${"7.29.0"}`);
|
||||
}
|
||||
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
|
||||
};
|
||||
Object.defineProperty(mergedVisitor, "_exploded", {
|
||||
enumerable: false
|
||||
});
|
||||
Object.defineProperty(mergedVisitor, "_verified", {
|
||||
enumerable: false
|
||||
});
|
||||
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] || (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 == null ? void 0 : 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 = virtualTypesValidators[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") {
|
||||
return true;
|
||||
}
|
||||
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()) {
|
||||
if (!path.requeueComputedKeyAndDecorators) {
|
||||
_context.requeueComputedKeyAndDecorators.call(path);
|
||||
} else {
|
||||
path.requeueComputedKeyAndDecorators();
|
||||
}
|
||||
}
|
||||
},
|
||||
Property(path) {
|
||||
if (path.isObjectProperty()) return;
|
||||
path.skip();
|
||||
if (!path.requeueComputedKeyAndDecorators) {
|
||||
_context.requeueComputedKeyAndDecorators.call(path);
|
||||
} else {
|
||||
path.requeueComputedKeyAndDecorators();
|
||||
}
|
||||
}
|
||||
};
|
||||
function environmentVisitor(visitor) {
|
||||
return merge([_environmentVisitor, visitor]);
|
||||
}
|
||||
|
||||
//# sourceMappingURL=visitors.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"names":["virtualTypes","require","virtualTypesValidators","_t","_context","DEPRECATED_KEYS","DEPRECATED_ALIASES","FLIPPED_ALIAS_KEYS","TYPES","__internal__deprecationWarning","deprecationWarning","isVirtualType","type","isExplodedVisitor","visitor","_exploded","explode$1","nodeType","Object","keys","shouldIgnoreKey","parts","split","length","fns","part","verify$1","__esModule","ensureEntranceObjects","ensureCallbackArrays","wrapCheck","types","_visitor$type","mergePair","aliases","deprecatedKey","deprecatedAlias","alias","existing","assign","_verified","Error","validateVisitorMethods","includes","visitors","visitorKey","path","val","concat","fn","TypeError","merge","states","wrapper","mergedVisitor","defineProperty","enumerable","i","state","topVisitor","wrapWithStateOrWrapper","key","typeVisitor","nodeVisitor","oldVisitor","newVisitor","phase","Array","isArray","map","newFn","call","toString","obj","enter","exit","fnKey","validator","apply","arguments","startsWith","dest","src","_environmentVisitor","FunctionParent","isArrowFunctionExpression","skip","isMethod","requeueComputedKeyAndDecorators","Property","isObjectProperty","environmentVisitor"],"sources":["../src/visitors.ts"],"sourcesContent":["import * as virtualTypes from \"./path/lib/virtual-types.ts\";\nimport * as virtualTypesValidators from \"./path/lib/virtual-types-validator.ts\";\nimport type { Node } from \"@babel/types\";\nimport {\n DEPRECATED_KEYS,\n DEPRECATED_ALIASES,\n FLIPPED_ALIAS_KEYS,\n TYPES,\n __internal__deprecationWarning as deprecationWarning,\n} from \"@babel/types\";\nimport type { ExplodedVisitor, NodePath, Visitor } from \"./index.ts\";\nimport type { ExplVisitNode, VisitNodeFunction, VisitPhase } from \"./types.ts\";\nimport { requeueComputedKeyAndDecorators } from \"./path/context.ts\";\n\ntype VIRTUAL_TYPES = keyof typeof virtualTypes;\nfunction isVirtualType(type: string): type is VIRTUAL_TYPES {\n return type in virtualTypes;\n}\nexport type VisitWrapper<S = any> = (\n stateName: string | undefined,\n visitorType: VisitPhase,\n callback: VisitNodeFunction<S, Node>,\n) => VisitNodeFunction<S, Node>;\n\nexport function isExplodedVisitor(\n visitor: Visitor,\n): visitor is ExplodedVisitor {\n // @ts-expect-error _exploded is not defined on non-exploded Visitor\n return visitor?._exploded;\n}\n\n// We need to name this function `explode$1` because otherwise rollup-plugin-dts\n// will generate a `namespace traverse { var explode: typeof explode; }` when\n// bundling @babel/traverse's index.d.ts.\n// TODO: Just call it `explode` once https://github.com/Swatinem/rollup-plugin-dts/issues/307\n// is fixed.\nexport { explode$1 as explode };\n/**\n * explode() will take a visitor object with all of the various shorthands\n * that we support, and validates & normalizes it into a common format, ready\n * to be used in traversal\n *\n * The various shorthands are:\n * * `Identifier() { ... }` -> `Identifier: { enter() { ... } }`\n * * `\"Identifier|NumericLiteral\": { ... }` -> `Identifier: { ... }, NumericLiteral: { ... }`\n * * Aliases in `@babel/types`: e.g. `Property: { ... }` -> `ObjectProperty: { ... }, ClassProperty: { ... }`\n * Other normalizations are:\n * * Visitors of virtual types are wrapped, so that they are only visited when\n * their dynamic check passes\n * * `enter` and `exit` functions are wrapped in arrays, to ease merging of\n * visitors\n */\nfunction explode$1<S>(visitor: Visitor<S>): ExplodedVisitor<S> {\n if (isExplodedVisitor(visitor)) return visitor;\n // @ts-expect-error `visitor` will be cast to ExplodedVisitor by this function\n visitor._exploded = true;\n\n // normalise pipes\n for (const nodeType of Object.keys(visitor) as (keyof Visitor)[]) {\n if (shouldIgnoreKey(nodeType)) continue;\n\n const parts: string[] = nodeType.split(\"|\");\n if (parts.length === 1) continue;\n\n const fns = visitor[nodeType];\n delete visitor[nodeType];\n\n for (const part of parts) {\n // @ts-expect-error part will be verified by `verify` later\n visitor[part] = fns;\n }\n }\n\n // verify data structure\n verify$1(visitor);\n\n // make sure there's no __esModule type since this is because we're using loose mode\n // and it sets __esModule to be enumerable on all modules :(\n // @ts-expect-error ESModule interop\n delete visitor.__esModule;\n\n // ensure visitors are objects\n ensureEntranceObjects(visitor);\n\n // ensure enter/exit callbacks are arrays\n ensureCallbackArrays(visitor);\n\n // add type wrappers\n for (const nodeType of Object.keys(visitor)) {\n if (shouldIgnoreKey(nodeType)) continue;\n\n if (!isVirtualType(nodeType)) continue;\n\n // wrap all the functions\n const fns = visitor[nodeType]!;\n for (const type of Object.keys(fns)) {\n // @ts-expect-error normalised as VisitNodeObject\n fns[type] = wrapCheck(nodeType, fns[type]);\n }\n\n // clear it from the visitor\n delete visitor[nodeType];\n\n Line truncated
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "@babel/traverse",
|
||||
"version": "7.29.0",
|
||||
"description": "The Babel Traverse module maintains the overall tree state, and is responsible for replacing, removing, and adding nodes",
|
||||
"author": "The Babel Team (https://babel.dev/team)",
|
||||
"homepage": "https://babel.dev/docs/en/next/babel-traverse",
|
||||
"bugs": "https://github.com/babel/babel/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3A%22pkg%3A%20traverse%22+is%3Aopen",
|
||||
"license": "MIT",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/babel/babel.git",
|
||||
"directory": "packages/babel-traverse"
|
||||
},
|
||||
"main": "./lib/index.js",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.29.0",
|
||||
"@babel/generator": "^7.29.0",
|
||||
"@babel/helper-globals": "^7.28.0",
|
||||
"@babel/parser": "^7.29.0",
|
||||
"@babel/template": "^7.28.6",
|
||||
"@babel/types": "^7.29.0",
|
||||
"debug": "^4.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.29.0",
|
||||
"@babel/helper-plugin-test-runner": "^7.27.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
"type": "commonjs"
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"strictNullChecks": true,
|
||||
"strictPropertyInitialization": true
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user