Restructure virtual types validator#14799
Conversation
|
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/52639/ |
| import type * as t from "@babel/types"; | ||
| const { isCompatTag } = react; | ||
| import type { VirtualTypeAliases } from "./virtual-types"; | ||
|
|
There was a problem hiding this comment.
Before this PR I have to memoize the link from typing to implementation
path.isBindingIdentifier => virtualTypes["isBindingIdentifier"].checkType
Now they are placed together. However, the typings and implementations can not be merged because TS does not support this assertion in non-class functions, although they will be eventually injected to the NodePath prototype.
| checkPath({ node }: NodePath<t.ForOfStatement>): boolean { | ||
| return node.await === true; | ||
| }, | ||
| checkPath: path => path.isForAwaitStatement(), |
There was a problem hiding this comment.
Can we simplify Wrapper to remove checkPath? (I'm not sure if this is possible, I try to understand the codes but they are a bit complicated)
There was a problem hiding this comment.
Nope. The checkPath applies additional selection logic based on Wrapper#types.
babel/packages/babel-traverse/src/visitors.ts
Lines 285 to 287 in 029fa17
Say if we have a ReferencedIdentifier visitor, Babel knows an Identifier could be a ReferencedIdentifier from Wrapper#types. Then it wraps the visitor so that the wrapped visitor will first run wrapper.checkPath, if the node is a ReferencedIdentifier, the wrapped visitor then applies the original visitor to the Identifier node, otherwise the visitor is inactivated.
There was a problem hiding this comment.
Could we pass nodeType to
wrapCheck function so that it doesn't rely anymore on checkPath? Every checkPath function just forwards the check to the .is* method with the same name as the virtual type.
function wrapCheck(nodeType: String, fn: Function) {
const newFn = function (this: unknown, path: NodePath) {
if (path[`is${nodeType}`]()) {
return fn.apply(this, arguments);
}
};
newFn.toString = () => fn.toString();
return newFn;
}Or, we can make checkPath just the check method name (as a string), to avoid the unnecessary intermediate function:
import * as virtualValidators from "./virtual-types-validator.ts"
export const ForAwaitStatement: Wrapper = {
types: ["ForOfStatement"],
checkPath: virtualValidators.isForAwaitStatement,
};function wrapCheck(wrapper: Wrapper, fn: Function) {
const newFn = function (this: unknown, path: NodePath) {
if (wrapper.checkPath.call(path)) {
return fn.apply(this, arguments);
}
};
newFn.toString = () => fn.toString();
return newFn;
}
liuxingbaoyu
left a comment
There was a problem hiding this comment.
This PR seems to expose more methods, but that's fine for me.
|
This PR does not expose any new methods. In current main, the virtual types validators are injected by babel/packages/babel-traverse/src/path/index.ts Lines 275 to 278 in 029fa17 which invokes In this PR we move the implementation to the explicit |
This PR is extracted from #14179. The goal is to remove
packages/babel-traverse/scripts/generators/virtual-types.jsso that the build script doesn't rely on the internalvirtualTypes. The virtual type validator typings are moved topath/lib/virtual-types-validator.ts, followed by implementations moved frompath/lib/virtual-types.I think it is fine to remove the extra build step because virtual types are not frequently updated compared to AST types.