diff --git a/Gulpfile.mjs b/Gulpfile.mjs index b803878e6194..b7c52913a288 100644 --- a/Gulpfile.mjs +++ b/Gulpfile.mjs @@ -142,7 +142,7 @@ async function generateTypeHelpers(helperKind, filename = "index.ts") { /** * - * @typedef {("asserts" | "validators" | "virtual-types")} TraverseHelperKind + * @typedef {("asserts" | "validators")} TraverseHelperKind * @param {TraverseHelperKind} helperKind */ function generateTraverseHelpers(helperKind) { @@ -525,7 +525,6 @@ gulp.task("generate-type-helpers", () => { generateTypeHelpers("ast-types"), generateTraverseHelpers("asserts"), generateTraverseHelpers("validators"), - generateTraverseHelpers("virtual-types"), ]); }); diff --git a/packages/babel-traverse/scripts/generators/validators.js b/packages/babel-traverse/scripts/generators/validators.js index 1dca02cd48f8..50340de31f33 100644 --- a/packages/babel-traverse/scripts/generators/validators.js +++ b/packages/babel-traverse/scripts/generators/validators.js @@ -1,46 +1,26 @@ import * as t from "@babel/types"; -import * as virtualTypes from "../../lib/path/lib/virtual-types.js"; export default function generateValidators() { let output = `/* * This file is auto-generated! Do not modify it directly. * To re-generate run 'make build' */ -import * as t from "@babel/types"; -import NodePath from "../index"; -import type { VirtualTypeAliases } from "./virtual-types"; +import type * as t from "@babel/types"; +import type NodePath from "../index"; +import type { VirtualTypeNodePathValidators } from "../lib/virtual-types-validator"; -export interface NodePathValidators { +interface BaseNodePathValidators { `; for (const type of [...t.TYPES].sort()) { output += `is${type}(this: NodePath, opts?: object): this is NodePath;`; } - for (const type of Object.keys(virtualTypes)) { - // TODO: Remove this check once we stop compiling to CJS - if (type === "default" || type === "__esModule") continue; - - const { types } = virtualTypes[type]; - if (type[0] === "_") continue; - if (t.NODE_FIELDS[type] || t.FLIPPED_ALIAS_KEYS[type]) { - output += `is${type}(this: NodePath, opts?: object): this is NodePath;`; - } else if (types /* in VirtualTypeAliases */) { - output += `is${type}(this: NodePath, opts?: object): this is NodePath;`; - } else if (type === "Pure") { - output += `isPure(constantsOnly?: boolean): boolean;`; - } else { - // if it don't have types, then VirtualTypeAliases[type] is t.Node - // which TS marked as always true - // eg. if (path.isBlockScope()) return; - // path resolved to `never` here - // so we have to return boolean instead of this is NodePath here - output += `is${type}(opts?: object): boolean;`; - } - } - output += ` } + +export interface NodePathValidators + extends BaseNodePathValidators, VirtualTypeNodePathValidators {} `; return output; diff --git a/packages/babel-traverse/scripts/generators/virtual-types.js b/packages/babel-traverse/scripts/generators/virtual-types.js deleted file mode 100644 index ff873f0203c5..000000000000 --- a/packages/babel-traverse/scripts/generators/virtual-types.js +++ /dev/null @@ -1,27 +0,0 @@ -import * as virtualTypes from "../../lib/path/lib/virtual-types.js"; - -export default function generateValidators() { - let output = `/* - * This file is auto-generated! Do not modify it directly. - * To re-generate run 'make build' - */ -import * as t from "@babel/types"; - -export interface VirtualTypeAliases { -`; - - for (const type of Object.keys(virtualTypes)) { - // TODO: Remove this check once we stop compiling to CJS - if (type === "default" || type === "__esModule") continue; - - output += ` ${type}: ${(virtualTypes[type].types || ["Node"]) - .map(t => `t.${t}`) - .join(" | ")};`; - } - - output += ` -} -`; - - return output; -} diff --git a/packages/babel-traverse/src/path/generated/validators.ts b/packages/babel-traverse/src/path/generated/validators.ts index 7271088faca8..908e5db8f355 100644 --- a/packages/babel-traverse/src/path/generated/validators.ts +++ b/packages/babel-traverse/src/path/generated/validators.ts @@ -2,11 +2,11 @@ * This file is auto-generated! Do not modify it directly. * To re-generate run 'make build' */ -import * as t from "@babel/types"; -import NodePath from "../index"; -import type { VirtualTypeAliases } from "./virtual-types"; +import type * as t from "@babel/types"; +import type NodePath from "../index"; +import type { VirtualTypeNodePathValidators } from "../lib/virtual-types-validator"; -export interface NodePathValidators { +interface BaseNodePathValidators { isAccessor( this: NodePath, opts?: object, @@ -1211,61 +1211,8 @@ export interface NodePathValidators { this: NodePath, opts?: object, ): this is NodePath; - isBindingIdentifier( - this: NodePath, - opts?: object, - ): this is NodePath; - isBlockScoped(opts?: object): boolean; - isExistentialTypeParam( - this: NodePath, - opts?: object, - ): this is NodePath; - isExpression( - this: NodePath, - opts?: object, - ): this is NodePath; - isFlow( - this: NodePath, - opts?: object, - ): this is NodePath; - isForAwaitStatement( - this: NodePath, - opts?: object, - ): this is NodePath; - isGenerated(opts?: object): boolean; - isNumericLiteralTypeAnnotation( - this: NodePath, - opts?: object, - ): this is NodePath; - isPure(constantsOnly?: boolean): boolean; - isReferenced(opts?: object): boolean; - isReferencedIdentifier( - this: NodePath, - opts?: object, - ): this is NodePath; - isReferencedMemberExpression( - this: NodePath, - opts?: object, - ): this is NodePath; - isRestProperty( - this: NodePath, - opts?: object, - ): this is NodePath; - isScope( - this: NodePath, - opts?: object, - ): this is NodePath; - isSpreadProperty( - this: NodePath, - opts?: object, - ): this is NodePath; - isStatement( - this: NodePath, - opts?: object, - ): this is NodePath; - isUser(opts?: object): boolean; - isVar( - this: NodePath, - opts?: object, - ): this is NodePath; } + +export interface NodePathValidators + extends BaseNodePathValidators, + VirtualTypeNodePathValidators {} diff --git a/packages/babel-traverse/src/path/generated/virtual-types.ts b/packages/babel-traverse/src/path/generated/virtual-types.ts deleted file mode 100644 index f741d76d7a71..000000000000 --- a/packages/babel-traverse/src/path/generated/virtual-types.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This file is auto-generated! Do not modify it directly. - * To re-generate run 'make build' - */ -import * as t from "@babel/types"; - -export interface VirtualTypeAliases { - BindingIdentifier: t.Identifier; - BlockScoped: t.Node; - ExistentialTypeParam: t.ExistsTypeAnnotation; - Expression: t.Expression; - Flow: t.Flow | t.ImportDeclaration | t.ExportDeclaration | t.ImportSpecifier; - ForAwaitStatement: t.ForOfStatement; - Generated: t.Node; - NumericLiteralTypeAnnotation: t.NumberLiteralTypeAnnotation; - Pure: t.Node; - Referenced: t.Node; - ReferencedIdentifier: t.Identifier | t.JSXIdentifier; - ReferencedMemberExpression: t.MemberExpression; - RestProperty: t.RestElement; - Scope: t.Scopable | t.Pattern; - SpreadProperty: t.RestElement; - Statement: t.Statement; - User: t.Node; - Var: t.VariableDeclaration; -} diff --git a/packages/babel-traverse/src/path/index.ts b/packages/babel-traverse/src/path/index.ts index faa5af2c55bc..98cb5d75aa21 100644 --- a/packages/babel-traverse/src/path/index.ts +++ b/packages/babel-traverse/src/path/index.ts @@ -22,6 +22,7 @@ import * as NodePath_removal from "./removal"; import * as NodePath_modification from "./modification"; import * as NodePath_family from "./family"; import * as NodePath_comments from "./comments"; +import * as NodePath_virtual_types_validator from "./lib/virtual-types-validator"; import type { NodePathAssetions } from "./generated/asserts"; import type { NodePathValidators } from "./generated/validators"; @@ -266,16 +267,12 @@ for (const type of t.TYPES) { }; } +// Register virtual types validators after base types validators +Object.assign(NodePath.prototype, NodePath_virtual_types_validator); + for (const type of Object.keys(virtualTypes) as (keyof typeof virtualTypes)[]) { if (type[0] === "_") continue; - if (t.TYPES.indexOf(type) < 0) t.TYPES.push(type); - - const virtualType = virtualTypes[type]; - - NodePath.prototype[`is${type}`] = function (opts?: any) { - // @ts-expect-error checkPath will throw when type is ExistentialTypeParam/NumericLiteralTypeAnnotation - return virtualType.checkPath(this, opts); - }; + if (!t.TYPES.includes(type)) t.TYPES.push(type); } type NodePathMixins = typeof NodePath_ancestry & diff --git a/packages/babel-traverse/src/path/lib/virtual-types-validator.ts b/packages/babel-traverse/src/path/lib/virtual-types-validator.ts new file mode 100644 index 000000000000..2ebb77765ab5 --- /dev/null +++ b/packages/babel-traverse/src/path/lib/virtual-types-validator.ts @@ -0,0 +1,213 @@ +import type NodePath from "../index"; +import { + isBinding, + isBlockScoped as nodeIsBlockScoped, + isExportDeclaration, + isExpression as nodeIsExpression, + isFlow as nodeIsFlow, + isForStatement, + isForXStatement, + isIdentifier, + isImportDeclaration, + isImportSpecifier, + isJSXIdentifier, + isJSXMemberExpression, + isMemberExpression, + isRestElement as nodeIsRestElement, + isReferenced as nodeIsReferenced, + isScope as nodeIsScope, + isStatement as nodeIsStatement, + isVar as nodeIsVar, + isVariableDeclaration, + react, +} from "@babel/types"; +import type * as t from "@babel/types"; +const { isCompatTag } = react; +import type { VirtualTypeAliases } from "./virtual-types"; + +export interface VirtualTypeNodePathValidators { + isBindingIdentifier( + this: NodePath, + opts?: object, + ): this is NodePath; + isBlockScoped(opts?: object): boolean; + /** + * @deprecated + */ + isExistentialTypeParam( + this: NodePath, + opts?: object, + ): this is NodePath; + isExpression( + this: NodePath, + opts?: object, + ): this is NodePath; + isFlow( + this: NodePath, + opts?: object, + ): this is NodePath; + isForAwaitStatement( + this: NodePath, + opts?: object, + ): this is NodePath; + isGenerated(opts?: object): boolean; + /** + * @deprecated + */ + isNumericLiteralTypeAnnotation(opts?: object): void; + isPure(opts?: object): boolean; + isReferenced(opts?: object): boolean; + isReferencedIdentifier( + this: NodePath, + opts?: object, + ): this is NodePath; + isReferencedMemberExpression( + this: NodePath, + opts?: object, + ): this is NodePath; + isRestProperty( + this: NodePath, + opts?: object, + ): this is NodePath; + isScope( + this: NodePath, + opts?: object, + ): this is NodePath; + isSpreadProperty( + this: NodePath, + opts?: object, + ): this is NodePath; + isStatement( + this: NodePath, + opts?: object, + ): this is NodePath; + isUser(opts?: object): boolean; + isVar( + this: NodePath, + opts?: object, + ): this is NodePath; +} + +export function isReferencedIdentifier(this: NodePath, opts?: any): boolean { + const { node, parent } = this; + if (!isIdentifier(node, opts) && !isJSXMemberExpression(parent, opts)) { + if (isJSXIdentifier(node, opts)) { + if (isCompatTag(node.name)) return false; + } else { + // not a JSXIdentifier or an Identifier + return false; + } + } + + // check if node is referenced + return nodeIsReferenced(node, parent, this.parentPath.parent); +} + +export function isReferencedMemberExpression(this: NodePath): boolean { + const { node, parent } = this; + return isMemberExpression(node) && nodeIsReferenced(node, parent); +} + +export function isBindingIdentifier(this: NodePath): boolean { + const { node, parent } = this; + const grandparent = this.parentPath.parent; + return isIdentifier(node) && isBinding(node, parent, grandparent); +} + +export function isStatement(this: NodePath): boolean { + 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; + } +} + +export function isExpression(this: NodePath): boolean { + if (this.isIdentifier()) { + return this.isReferencedIdentifier(); + } else { + return nodeIsExpression(this.node); + } +} + +export function isScope(this: NodePath): boolean { + return nodeIsScope(this.node, this.parent); +} + +export function isReferenced(this: NodePath): boolean { + return nodeIsReferenced(this.node, this.parent); +} + +export function isBlockScoped(this: NodePath): boolean { + return nodeIsBlockScoped(this.node); +} + +export function isVar(this: NodePath): boolean { + return nodeIsVar(this.node); +} + +export function isUser(this: NodePath): boolean { + return this.node && !!this.node.loc; +} + +export function isGenerated(this: NodePath): boolean { + return !this.isUser(); +} + +export function isPure(this: NodePath, constantsOnly?: boolean): boolean { + return this.scope.isPure(this.node, constantsOnly); +} + +export function isFlow(this: NodePath): boolean { + 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; + } +} + +// TODO: 7.0 Backwards Compat +export function isRestProperty(this: NodePath): boolean { + return ( + nodeIsRestElement(this.node) && + this.parentPath && + this.parentPath.isObjectPattern() + ); +} + +export function isSpreadProperty(this: NodePath): boolean { + return ( + nodeIsRestElement(this.node) && + this.parentPath && + this.parentPath.isObjectExpression() + ); +} + +export function isForAwaitStatement(this: NodePath): boolean { + return isForStatement(this.node, { await: true }); +} + +export function isExistentialTypeParam(this: NodePath): void { + throw new Error( + "`path.isExistentialTypeParam` has been renamed to `path.isExistsTypeAnnotation()` in Babel 7.", + ); +} + +export function isNumericLiteralTypeAnnotation(this: NodePath): void { + throw new Error( + "`path.isNumericLiteralTypeAnnotation()` has been renamed to `path.isNumberLiteralTypeAnnotation()` in Babel 7.", + ); +} diff --git a/packages/babel-traverse/src/path/lib/virtual-types.ts b/packages/babel-traverse/src/path/lib/virtual-types.ts index 3acf1ba5ebba..8ae52e2bab36 100644 --- a/packages/babel-traverse/src/path/lib/virtual-types.ts +++ b/packages/babel-traverse/src/path/lib/virtual-types.ts @@ -1,184 +1,79 @@ -import type NodePath from "../index"; -import { - isBinding, - isBlockScoped, - isExportDeclaration, - isExpression, - isFlow, - isForStatement, - isForXStatement, - isIdentifier, - isImportDeclaration, - isImportSpecifier, - isJSXIdentifier, - isJSXMemberExpression, - isMemberExpression, - isReferenced, - isScope, - isStatement, - isVar, - isVariableDeclaration, - react, -} from "@babel/types"; import type * as t from "@babel/types"; -const { isCompatTag } = react; + +export interface VirtualTypeAliases { + BindingIdentifier: t.Identifier; + BlockScoped: t.Node; + ExistentialTypeParam: t.ExistsTypeAnnotation; + Expression: t.Expression; + Flow: t.Flow | t.ImportDeclaration | t.ExportDeclaration | t.ImportSpecifier; + ForAwaitStatement: t.ForOfStatement; + Generated: t.Node; + NumericLiteralTypeAnnotation: t.NumberLiteralTypeAnnotation; + Pure: t.Node; + Referenced: t.Node; + ReferencedIdentifier: t.Identifier | t.JSXIdentifier; + ReferencedMemberExpression: t.MemberExpression; + RestProperty: t.RestElement; + Scope: t.Scopable | t.Pattern; + SpreadProperty: t.RestElement; + Statement: t.Statement; + User: t.Node; + Var: t.VariableDeclaration; +} type NodeTypes = t.Node["type"] | t.Comment["type"] | keyof t.Aliases; -export type Wrapper = { - types?: NodeTypes[]; - checkPath?(path: NodePath): boolean; -}; - -export const ReferencedIdentifier: Wrapper = { - types: ["Identifier", "JSXIdentifier"], - checkPath(path: NodePath, opts?: any): boolean { - const { node, parent } = path; - if (!isIdentifier(node, opts) && !isJSXMemberExpression(parent, opts)) { - if (isJSXIdentifier(node, opts)) { - if (isCompatTag(node.name)) return false; - } else { - // not a JSXIdentifier or an Identifier - return false; - } - } - - // check if node is referenced - return isReferenced(node, parent, path.parentPath.parent); - }, -}; - -export const ReferencedMemberExpression: Wrapper = { - types: ["MemberExpression"], - checkPath({ node, parent }: NodePath) { - return isMemberExpression(node) && isReferenced(node, parent); - }, -}; - -export const BindingIdentifier: Wrapper = { - types: ["Identifier"], - checkPath(path: NodePath): boolean { - const { node, parent } = path; - const grandparent = path.parentPath.parent; - return isIdentifier(node) && isBinding(node, parent, grandparent); - }, -}; - -export const Statement: Wrapper = { - types: ["Statement"], - checkPath({ node, parent }: NodePath): boolean { - if (isStatement(node)) { - if (isVariableDeclaration(node)) { - if (isForXStatement(parent, { left: node })) return false; - if (isForStatement(parent, { init: node })) return false; - } - - return true; - } else { - return false; - } - }, -}; - -export const Expression: Wrapper = { - types: ["Expression"], - checkPath(path: NodePath): boolean { - if (path.isIdentifier()) { - return path.isReferencedIdentifier(); - } else { - return isExpression(path.node); - } - }, -}; - -export const Scope: Wrapper = { - // When pattern is inside the function params, it is a scope - types: ["Scopable", "Pattern"], - checkPath(path: NodePath) { - return isScope(path.node, path.parent); - }, -}; - -export const Referenced: Wrapper = { - checkPath(path: NodePath): boolean { - return isReferenced(path.node, path.parent); - }, -}; - -export const BlockScoped: Wrapper = { - checkPath(path: NodePath): boolean { - return isBlockScoped(path.node); - }, -}; - -export const Var: Wrapper = { - types: ["VariableDeclaration"], - checkPath(path: NodePath): boolean { - return isVar(path.node); - }, -}; - -export const User: Wrapper = { - checkPath(path: NodePath): boolean { - return path.node && !!path.node.loc; - }, -}; - -export const Generated: Wrapper = { - checkPath(path: NodePath): boolean { - return !path.isUser(); - }, -}; - -export const Pure: Wrapper = { - checkPath(path: NodePath, constantsOnly?: boolean): boolean { - return path.scope.isPure(path.node, constantsOnly); - }, -}; - -export const Flow: Wrapper = { - types: ["Flow", "ImportDeclaration", "ExportDeclaration", "ImportSpecifier"], - checkPath({ node }: NodePath): boolean { - if (isFlow(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; - } - }, -}; +type VirtualTypeMapping = readonly NodeTypes[] | null; + +export const ReferencedIdentifier: VirtualTypeMapping = [ + "Identifier", + "JSXIdentifier", +] as const; + +export const ReferencedMemberExpression: VirtualTypeMapping = [ + "MemberExpression", +] as const; + +export const BindingIdentifier: VirtualTypeMapping = ["Identifier"] as const; + +export const Statement: VirtualTypeMapping = ["Statement"] as const; + +export const Expression: VirtualTypeMapping = ["Expression"] as const; + +export const Scope: VirtualTypeMapping = ["Scopable", "Pattern"] as const; + +export const Referenced: VirtualTypeMapping = null as null; + +export const BlockScoped: VirtualTypeMapping = null as null; + +export const Var: VirtualTypeMapping = ["VariableDeclaration"]; + +export const User: VirtualTypeMapping = null as null; + +export const Generated: VirtualTypeMapping = null as null; + +export const Pure: VirtualTypeMapping = null as null; + +export const Flow: VirtualTypeMapping = [ + "Flow", + "ImportDeclaration", + "ExportDeclaration", + "ImportSpecifier", +] as const; // TODO: 7.0 Backwards Compat -export const RestProperty: Wrapper = { - types: ["RestElement"], - checkPath(path: NodePath): boolean { - return path.parentPath && path.parentPath.isObjectPattern(); - }, -}; - -export const SpreadProperty: Wrapper = { - types: ["RestElement"], - checkPath(path: NodePath): boolean { - return path.parentPath && path.parentPath.isObjectExpression(); - }, -}; - -export const ExistentialTypeParam: Wrapper = { - types: ["ExistsTypeAnnotation"], -}; - -export const NumericLiteralTypeAnnotation: Wrapper = { - types: ["NumberLiteralTypeAnnotation"], -}; - -export const ForAwaitStatement: Wrapper = { - types: ["ForOfStatement"], - checkPath({ node }: NodePath): boolean { - return node.await === true; - }, -}; +export const RestProperty: VirtualTypeMapping = ["RestElement"] as const; + +export const SpreadProperty: VirtualTypeMapping = ["RestElement"] as const; + +export const ExistentialTypeParam: VirtualTypeMapping = [ + "ExistsTypeAnnotation", +] as const; + +export const NumericLiteralTypeAnnotation: VirtualTypeMapping = [ + "NumberLiteralTypeAnnotation", +] as const; + +export const ForAwaitStatement: VirtualTypeMapping = [ + "ForOfStatement", +] as const; diff --git a/packages/babel-traverse/src/types.ts b/packages/babel-traverse/src/types.ts index c0fadb16f8d4..a608defe7ca9 100644 --- a/packages/babel-traverse/src/types.ts +++ b/packages/babel-traverse/src/types.ts @@ -1,6 +1,6 @@ import type * as t from "@babel/types"; import { NodePath } from "./index"; -import { VirtualTypeAliases } from "./path/generated/virtual-types"; +import type { VirtualTypeAliases } from "./path/lib/virtual-types"; export type Visitor = VisitNodeObject & { [Type in t.Node["type"]]?: VisitNode>; diff --git a/packages/babel-traverse/src/visitors.ts b/packages/babel-traverse/src/visitors.ts index 5b6e5b672fc5..21301ccdba76 100644 --- a/packages/babel-traverse/src/visitors.ts +++ b/packages/babel-traverse/src/visitors.ts @@ -1,8 +1,12 @@ import * as virtualTypes from "./path/lib/virtual-types"; -import type { Wrapper } from "./path/lib/virtual-types"; import { DEPRECATED_KEYS, FLIPPED_ALIAS_KEYS, TYPES } from "@babel/types"; import type { NodePath, Visitor } from "./index"; +type VIRTUAL_TYPES = keyof typeof virtualTypes; +function isVirtualType(type: string): type is VIRTUAL_TYPES { + return type in virtualTypes; +} + /** * explode() will take a visitor object with all of the various shorthands * that we support, and validates & normalizes it into a common format, ready @@ -55,26 +59,26 @@ export function explode(visitor: Visitor) { for (const nodeType of Object.keys(visitor)) { if (shouldIgnoreKey(nodeType)) continue; - // @ts-expect-error Fixme: nodeType could index virtualTypes - const wrapper = virtualTypes[nodeType]; - if (!wrapper) continue; + if (!isVirtualType(nodeType)) continue; // wrap all the functions const fns = visitor[nodeType]; for (const type of Object.keys(fns)) { // @ts-expect-error manipulating visitors - fns[type] = wrapCheck(wrapper, fns[type]); + fns[type] = wrapCheck(nodeType, fns[type]); } // clear it from the visitor delete visitor[nodeType]; - if (wrapper.types) { - for (const type of wrapper.types) { + const types = virtualTypes[nodeType]; + if (types !== null) { + for (const type of types) { // merge the visitor if necessary or just put it back in if (visitor[type]) { mergePair(visitor[type], fns); } else { + // @ts-expect-error Expression produces too complex union visitor[type] = fns; } } @@ -280,9 +284,9 @@ function ensureCallbackArrays(obj: Visitor) { if (obj.exit && !Array.isArray(obj.exit)) obj.exit = [obj.exit]; } -function wrapCheck(wrapper: Wrapper, fn: Function) { +function wrapCheck(nodeType: VIRTUAL_TYPES, fn: Function) { const newFn = function (this: unknown, path: NodePath) { - if (wrapper.checkPath(path)) { + if (path[`is${nodeType}`]()) { return fn.apply(this, arguments); } };