New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simplify (transpiled) babel-types builder wrappers #13843
Simplify (transpiled) babel-types builder wrappers #13843
Conversation
... by passing the node `type` string in `this`
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 546fe9a:
|
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/49235/ |
Why not just pass the (already known, because the call signature is correct) parameters into the builder? // before
function arrayExpression$2(elements) {
return builder.apply("ArrayExpression", arguments);
}
// after
function arrayExpression$2(elements) {
return builder("ArrayExpression", elements);
} |
I've just tried transplanting the benchmark from that PR onto this one, and got this:
I don't know the history or importance of that check, but one notable difference is that the current |
That check is important because builders don't accept params for every possible property, so it's easy to accidentally pass extra params. |
Object.keys(VISITOR_KEYS), | ||
Object.keys(FLIPPED_ALIAS_KEYS), | ||
Object.keys(DEPRECATED_KEYS), | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Q: what is this change needed for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed, it's insignificant. I just randomly noticed the extra concat because this line was right above the builder function when I was reviewing it in the resulting babel.js.
We could easily pass Really, I'm not sure why we need a |
🙌 for plain object AST nodes, and we can replace
It's a shotgun that |
@@ -121,7 +121,7 @@ import type * as t from "../.."; | |||
output += `/** @deprecated */ | |||
function ${type}(...args: Array<any>): any { | |||
console.trace("The node type ${type} has been renamed to ${newType}"); | |||
return builder("${type}", ...args); | |||
return builder.apply("${type}", arguments); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it evaluate the args passed to the function? Otherwise if we want to keep arguments we can remove ...args: Array<any>
from the signature.
return builder.apply("${type}", arguments); | |
return builder.apply("${type}", args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. The point of this PR is to avoid the unnecessary conversion from arguments
to an actual Array
(whether by slicing or shovelling), so the answer is: I should remove ...args
from the signature as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't sure whether I could change the deprecated wrapper function signatures (as these are public). If yes, then perhaps they could be as verbose as the non-deprecated ones, i.e.
`
function ${type}(${generateBuilderArgs(newType).join(", ")}): t.${type} {
`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it is better: even if they are deprecated they still work so we can provide a good type signature.
(also avoids constructing ...args Array)
...args: Array<any> | ||
): T { | ||
export default function builder<T extends t.Node>(this: T["type"]): T { | ||
const type = this; | ||
const keys = BUILDER_KEYS[type]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before merging, can we discuss whether mutating BUILD_KEYS
is actually an intentional API? For the Babel 8 breaking changes, we could stop doing this and perform much faster node building by specializing each builder function. Eg, t.identifer(name)
can be (a little more than) function identifier(name) { return { type: 'Identifier', name } }
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We support swapping the parser and the generator, but not the other packages.
You can handle custom AST modifications by changing VISITOR_KEYS
.
On the other hand, I don't see why someone would want to change BUILDER_KEYS
(you can just directly create the node without using the builder function).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the other hand, I don't see why someone would want to change BUILDER_KEYS (you can just directly create the node without using the builder function).
In our codebase we don't mutate BUILDER_KEYS
. I think we can expand builder keys in babel-types from Babel 8 and leave a note that the BUILDER_KEYS
export is for reference only, it does not change the builder behavior.
On VISITOR_KEYS
, I think we can offer an overrideVisit(originalVisit)
API for those mutating VISITOR_KEYS
: So we can expand VISITOR_KEYS
in babel-traverse
, too. It should remove the slow object access due to dynamic property access on different AST nodes. TS expands visitor keys, too.
It's a bit hacky, but bear with me. The
builder
function is super internal, only used from auto-generated code, so I think it can afford having a weird calling convention, such as receiving a string inthis
.The end result of this PR is that transpiled babel-standalone ends up containing this:
instead of this: