Skip to content

Commit

Permalink
Improve the layout of generated validators (#15546)
Browse files Browse the repository at this point in the history
  • Loading branch information
liuxingbaoyu committed Apr 5, 2023
1 parent bc7f795 commit 548b05d
Show file tree
Hide file tree
Showing 3 changed files with 1,793 additions and 3,438 deletions.
214 changes: 214 additions & 0 deletions benchmark/babel-types/validators/isExpression.mjs
@@ -0,0 +1,214 @@
import Benchmark from "benchmark";
import { report } from "../../util.mjs";

const suite = new Benchmark.Suite();

function isExpressionIf(node) {
if (!node) return false;
const nodeType = node.type;
if (
"ArrayExpression" === nodeType ||
"AssignmentExpression" === nodeType ||
"BinaryExpression" === nodeType ||
"CallExpression" === nodeType ||
"ConditionalExpression" === nodeType ||
"FunctionExpression" === nodeType ||
"Identifier" === nodeType ||
"StringLiteral" === nodeType ||
"NumericLiteral" === nodeType ||
"NullLiteral" === nodeType ||
"BooleanLiteral" === nodeType ||
"RegExpLiteral" === nodeType ||
"LogicalExpression" === nodeType ||
"MemberExpression" === nodeType ||
"NewExpression" === nodeType ||
"ObjectExpression" === nodeType ||
"SequenceExpression" === nodeType ||
"ParenthesizedExpression" === nodeType ||
"ThisExpression" === nodeType ||
"UnaryExpression" === nodeType ||
"UpdateExpression" === nodeType ||
"ArrowFunctionExpression" === nodeType ||
"ClassExpression" === nodeType ||
"MetaProperty" === nodeType ||
"Super" === nodeType ||
"TaggedTemplateExpression" === nodeType ||
"TemplateLiteral" === nodeType ||
"YieldExpression" === nodeType ||
"AwaitExpression" === nodeType ||
"Import" === nodeType ||
"BigIntLiteral" === nodeType ||
"OptionalMemberExpression" === nodeType ||
"OptionalCallExpression" === nodeType ||
"TypeCastExpression" === nodeType ||
"JSXElement" === nodeType ||
"JSXFragment" === nodeType ||
"BindExpression" === nodeType ||
"DoExpression" === nodeType ||
"RecordExpression" === nodeType ||
"TupleExpression" === nodeType ||
"DecimalLiteral" === nodeType ||
"ModuleExpression" === nodeType ||
"TopicReference" === nodeType ||
"PipelineTopicExpression" === nodeType ||
"PipelineBareFunction" === nodeType ||
"PipelinePrimaryTopicReference" === nodeType ||
"TSInstantiationExpression" === nodeType ||
"TSAsExpression" === nodeType ||
"TSSatisfiesExpression" === nodeType ||
"TSTypeAssertion" === nodeType ||
"TSNonNullExpression" === nodeType ||
(nodeType === "Placeholder" &&
("Expression" === node.expectedNode ||
"Identifier" === node.expectedNode ||
"StringLiteral" === node.expectedNode))
) {
return true;
}
}

function isExpressionSwitch(node) {
if (!node) return false;
switch (node.type) {
case "ArrayExpression":
case "AssignmentExpression":
case "BinaryExpression":
case "CallExpression":
case "ConditionalExpression":
case "FunctionExpression":
case "Identifier":
case "StringLiteral":
case "NumericLiteral":
case "NullLiteral":
case "BooleanLiteral":
case "RegExpLiteral":
case "LogicalExpression":
case "MemberExpression":
case "NewExpression":
case "ObjectExpression":
case "SequenceExpression":
case "ParenthesizedExpression":
case "ThisExpression":
case "UnaryExpression":
case "UpdateExpression":
case "ArrowFunctionExpression":
case "ClassExpression":
case "MetaProperty":
case "Super":
case "TaggedTemplateExpression":
case "TemplateLiteral":
case "YieldExpression":
case "AwaitExpression":
case "Import":
case "BigIntLiteral":
case "OptionalMemberExpression":
case "OptionalCallExpression":
case "TypeCastExpression":
case "JSXElement":
case "JSXFragment":
case "BindExpression":
case "DoExpression":
case "RecordExpression":
case "TupleExpression":
case "DecimalLiteral":
case "ModuleExpression":
case "TopicReference":
case "PipelineTopicExpression":
case "PipelineBareFunction":
case "PipelinePrimaryTopicReference":
case "TSInstantiationExpression":
case "TSAsExpression":
case "TSSatisfiesExpression":
case "TSTypeAssertion":
case "TSNonNullExpression":
return true;
case "Placeholder":
if (
"Expression" === node.expectedNode ||
"Identifier" === node.expectedNode ||
"StringLiteral" === node.expectedNode
) {
return true;
}
}
return false;
}

function isExpressionIncludes(node) {
if (!node) return false;

const nodeType = node.type;
return (
[
"ArrayExpression",
"AssignmentExpression",
"BinaryExpression",
"CallExpression",
"ConditionalExpression",
"FunctionExpression",
"Identifier",
"StringLiteral",
"NumericLiteral",
"NullLiteral",
"BooleanLiteral",
"RegExpLiteral",
"LogicalExpression",
"MemberExpression",
"NewExpression",
"ObjectExpression",
"SequenceExpression",
"ParenthesizedExpression",
"ThisExpression",
"UnaryExpression",
"UpdateExpression",
"ArrowFunctionExpression",
"ClassExpression",
"MetaProperty",
"Super",
"TaggedTemplateExpression",
"TemplateLiteral",
"YieldExpression",
"AwaitExpression",
"Import",
"BigIntLiteral",
"OptionalMemberExpression",
"OptionalCallExpression",
"TypeCastExpression",
"JSXElement",
"JSXFragment",
"BindExpression",
"DoExpression",
"RecordExpression",
"TupleExpression",
"DecimalLiteral",
"ModuleExpression",
"TopicReference",
"PipelineTopicExpression",
"PipelineBareFunction",
"PipelinePrimaryTopicReference",
"TSInstantiationExpression",
"TSAsExpression",
"TSSatisfiesExpression",
"TSTypeAssertion",
"TSNonNullExpression",
].includes(nodeType) ||
(nodeType === "Placeholder" &&
("Expression" === node.expectedNode ||
"Identifier" === node.expectedNode ||
"StringLiteral" === node.expectedNode))
);
}

function benchCases(name, func) {
suite.add(`isExpression ${name}`, () => {
func({ type: "ArrayExpression" }); // first
func({ type: "TSNonNullExpression" }); // last
func({ type: "XXXXXXXXXXXXX" }); // not found
});
}

benchCases("if", isExpressionIf);
benchCases("switch", isExpressionSwitch);
benchCases("includes", isExpressionIncludes);

suite.on("cycle", report).run();
46 changes: 22 additions & 24 deletions packages/babel-types/scripts/generators/validators.js
Expand Up @@ -10,20 +10,17 @@ import {

const has = Function.call.bind(Object.prototype.hasOwnProperty);

function joinComparisons(leftArr, right) {
return (
leftArr.map(JSON.stringify).join(` === ${right} || `) + ` === ${right}`
);
function buildCases(arr) {
return arr.map(key => `case ${JSON.stringify(key)}:`).join("") + "break;";
}

function addIsHelper(type, aliasKeys, deprecated) {
const targetType = JSON.stringify(type);
let aliasSource = "";
let cases = "";
if (aliasKeys) {
aliasSource = joinComparisons(aliasKeys, "nodeType");
cases = buildCases(aliasKeys);
}

let placeholderSource = "";
const placeholderTypes = [];
if (PLACEHOLDERS.includes(type) && has(FLIPPED_ALIAS_KEYS, type)) {
placeholderTypes.push(type);
Expand All @@ -32,13 +29,14 @@ function addIsHelper(type, aliasKeys, deprecated) {
placeholderTypes.push(...PLACEHOLDERS_FLIPPED_ALIAS[type]);
}
if (placeholderTypes.length > 0) {
placeholderSource =
' || nodeType === "Placeholder" && (' +
joinComparisons(
placeholderTypes,
"(node as t.Placeholder).expectedNode"
) +
")";
cases += `
case "Placeholder":
switch ((node as t.Placeholder).expectedNode) {
${buildCases(placeholderTypes)}
default:
return false;
}
break;`;
}

const result =
Expand All @@ -50,18 +48,18 @@ function addIsHelper(type, aliasKeys, deprecated) {
${deprecated || ""}
if (!node) return false;
const nodeType = (node as t.Node).type;
if (${
aliasSource ? aliasSource : `nodeType === ${targetType}`
}${placeholderSource}) {
if (typeof opts === "undefined") {
return true;
} else {
return shallowEqual(node, opts);
}
${
cases
? `
switch((node as t.Node).type){
${cases}
default:
return false;
}`
: `if ((node as t.Node).type !== ${targetType}) return false;`
}
return false;
return opts == null || shallowEqual(node, opts);
}
`;
}
Expand Down

0 comments on commit 548b05d

Please sign in to comment.