From 0ad29b035b74a875c97c8a8bf2197909055a45e3 Mon Sep 17 00:00:00 2001 From: Rob Hogan <2590098+robhogan@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:36:21 +0100 Subject: [PATCH] Type Babel's definition constants and numeric NodePath keys Our generated `@babel/types` libdef was missing the node definition tables Babel exports (`VISITOR_KEYS`, `NODE_FIELDS`, etc.). This adds them to the generator, typed from the runtime values in Babel 7.29. It also widens `NodePath#key` to `string | number`, since a path inside a list has its numeric index as its key. https://github.com/react/metro/pull/2092 currently needs suppressions for both, which we'll remove in a follow-up. Changelog: Internal Test plan: Regenerated with `yarn update-babel-flow-lib-defs` - the only change to the generated file is the new declarations. React Native's copies of both libdefs are identical to ours, and RN's `flow check` is clean with the updated files dropped in. --- flow-typed/npm/babel-traverse_v7.x.x.js | 12 ++++---- flow-typed/npm/babel-types_v7.x.x.js | 25 ++++++++++++++++ ...generateBabelTypesFlowLibraryDefinition.js | 30 +++++++++++++++++++ 3 files changed, 61 insertions(+), 6 deletions(-) diff --git a/flow-typed/npm/babel-traverse_v7.x.x.js b/flow-typed/npm/babel-traverse_v7.x.x.js index 12f4570389..548845cd17 100644 --- a/flow-typed/npm/babel-traverse_v7.x.x.js +++ b/flow-typed/npm/babel-traverse_v7.x.x.js @@ -372,7 +372,7 @@ declare module '@babel/traverse' { create( node: BabelNode, obj: Array, - key: string, + key: string | number, listKey: string, ): NodePath<>; maybeQueue(path: NodePath<>, notPriority?: boolean): void; @@ -614,7 +614,7 @@ declare module '@babel/traverse' { context: TraversalContext; container: null | {...} | Array<{...}>; listKey: null | string; - key: null | string; + key: null | string | number; /* Declaring node as readonly isn't entirely correct since the node can be * changed by e.g. calling replaceWith. However, this is needed to reasonably @@ -637,7 +637,7 @@ declare module '@babel/traverse' { parent: BabelNode, container: null | {...} | Array<{...}>, listKey: null | string, - key: null | string, + key: string | number, }): NodePath<>; getScope(scope: Scope): Scope; @@ -964,10 +964,10 @@ declare module '@babel/traverse' { parentPath: NodePath<>, container: ?{...} | ?Array<{...}>, listKey: string, - key: string, + key: string | number, ): void; - setKey(key: string): void; + setKey(key: string | number): void; requeue(pathToQueue?: NodePath<>): void; @@ -1013,7 +1013,7 @@ declare module '@babel/traverse' { getCompletionRecords(): Array>; - getSibling(key: string): NodePath<>; + getSibling(key: string | number): NodePath<>; getPrevSibling(): NodePath<>; diff --git a/flow-typed/npm/babel-types_v7.x.x.js b/flow-typed/npm/babel-types_v7.x.x.js index ccd063a450..aad58132ef 100644 --- a/flow-typed/npm/babel-types_v7.x.x.js +++ b/flow-typed/npm/babel-types_v7.x.x.js @@ -3252,6 +3252,24 @@ declare module "@babel/types" { declare type BabelNodeTSBaseType = BabelNodeTSAnyKeyword | BabelNodeTSBooleanKeyword | BabelNodeTSBigIntKeyword | BabelNodeTSIntrinsicKeyword | BabelNodeTSNeverKeyword | BabelNodeTSNullKeyword | BabelNodeTSNumberKeyword | BabelNodeTSObjectKeyword | BabelNodeTSStringKeyword | BabelNodeTSSymbolKeyword | BabelNodeTSUndefinedKeyword | BabelNodeTSUnknownKeyword | BabelNodeTSVoidKeyword | BabelNodeTSThisType | BabelNodeTSTemplateLiteralType | BabelNodeTSLiteralType; declare type BabelNodeModuleDeclaration = BabelNodeExportAllDeclaration | BabelNodeExportDefaultDeclaration | BabelNodeExportNamedDeclaration | BabelNodeImportDeclaration; + declare type BabelNodeValidator = { + (node?: BabelNode, key?: string | { toString(): string }, val?: unknown): void; + type?: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | 'array' | 'null' | 'any'; + each?: BabelNodeValidator; + chainOf?: ReadonlyArray; + oneOf?: ReadonlyArray; + oneOfNodeTypes?: ReadonlyArray; + oneOfNodeOrValueTypes?: ReadonlyArray; + shapeOf?: { [field: string]: BabelNodeFieldOptions }; + }; + + declare type BabelNodeFieldOptions = { + default?: string | number | boolean | [] | null; + optional?: boolean; + deprecated?: boolean; + validate?: BabelNodeValidator; + }; + declare export function arrayExpression(elements?: Array): BabelNodeArrayExpression; declare export function assignmentExpression(operator: string, left: BabelNodeLVal | BabelNodeOptionalMemberExpression, right: BabelNodeExpression): BabelNodeAssignmentExpression; declare export function binaryExpression(operator: "+" | "-" | "/" | "%" | "*" | "**" | "&" | "|" | ">>" | ">>>" | "<<" | "^" | "==" | "===" | "!=" | "!==" | "in" | "instanceof" | ">" | "<" | ">=" | "<=" | "|>", left: BabelNodeExpression | BabelNodePrivateName, right: BabelNodeExpression): BabelNodeBinaryExpression; @@ -4189,4 +4207,11 @@ declare module "@babel/types" { declare export type TSType = BabelNodeTSType; declare export type TSBaseType = BabelNodeTSBaseType; declare export type ModuleDeclaration = BabelNodeModuleDeclaration; + declare export var VISITOR_KEYS: { [type: string]: Array }; + declare export var ALIAS_KEYS: { [type: BabelNode['type']]: Array }; + declare export var FLIPPED_ALIAS_KEYS: { [alias: string]: Array }; + declare export var NODE_FIELDS: { [type: string]: { [field: string]: BabelNodeFieldOptions } }; + declare export var BUILDER_KEYS: { [type: string]: Array }; + declare export var DEPRECATED_KEYS: { [type: string]: BabelNode['type'] }; + declare export var TYPES: Array; } diff --git a/scripts/support/generateBabelTypesFlowLibraryDefinition.js b/scripts/support/generateBabelTypesFlowLibraryDefinition.js index 6cc6cc45bc..1b3a939583 100644 --- a/scripts/support/generateBabelTypesFlowLibraryDefinition.js +++ b/scripts/support/generateBabelTypesFlowLibraryDefinition.js @@ -309,6 +309,36 @@ function main() { ), ); + // definitions/ + typeDecls += ` +declare type ${NODE_PREFIX}Validator = { + (node?: ${NODE_PREFIX}, key?: string | { toString(): string }, val?: unknown): void; + type?: 'string' | 'number' | 'bigint' | 'boolean' | 'symbol' | 'undefined' | 'object' | 'function' | 'array' | 'null' | 'any'; + each?: ${NODE_PREFIX}Validator; + chainOf?: ReadonlyArray<${NODE_PREFIX}Validator>; + oneOf?: ReadonlyArray; + oneOfNodeTypes?: ReadonlyArray; + oneOfNodeOrValueTypes?: ReadonlyArray; + shapeOf?: { [field: string]: ${NODE_PREFIX}FieldOptions }; +}; + +declare type ${NODE_PREFIX}FieldOptions = { + default?: string | number | boolean | [] | null; + optional?: boolean; + deprecated?: boolean; + validate?: ${NODE_PREFIX}Validator; +}; +`; + lines.push( + `declare export var VISITOR_KEYS: { [type: string]: Array };`, + `declare export var ALIAS_KEYS: { [type: ${NODE_PREFIX}['type']]: Array };`, + `declare export var FLIPPED_ALIAS_KEYS: { [alias: string]: Array<${NODE_PREFIX}['type']> };`, + `declare export var NODE_FIELDS: { [type: string]: { [field: string]: ${NODE_PREFIX}FieldOptions } };`, + `declare export var BUILDER_KEYS: { [type: string]: Array };`, + `declare export var DEPRECATED_KEYS: { [type: string]: ${NODE_PREFIX}['type'] };`, + `declare export var TYPES: Array;`, + ); + // Node type declarations, kept module-local. The exported aliases and // function signatures below reference them by their `BabelNode`-prefixed name. const moduleInner = typeDecls + '\n' + lines.join('\n');