From 71f919d9585bc7e839c1c0101a34ef7eabf28998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Thu, 2 Jun 2022 14:24:04 -0400 Subject: [PATCH 1/3] bump to-fast-properties to v4 --- packages/babel-types/package.json | 2 +- scripts/generators/tsconfig.js | 4 ++++ tsconfig.json | 3 +++ yarn.lock | 21 +++++++++++++++++++-- 4 files changed, 27 insertions(+), 3 deletions(-) diff --git a/packages/babel-types/package.json b/packages/babel-types/package.json index c1be0b1bcd2c..d1d6e3e27128 100644 --- a/packages/babel-types/package.json +++ b/packages/babel-types/package.json @@ -25,7 +25,7 @@ }, "dependencies": { "@babel/helper-validator-identifier": "workspace:^", - "to-fast-properties": "^2.0.0" + "to-fast-properties": "condition:BABEL_8_BREAKING ? ^4.0.0 : ^2.0.0" }, "devDependencies": { "@babel/generator": "workspace:^", diff --git a/scripts/generators/tsconfig.js b/scripts/generators/tsconfig.js index 37f2156e421b..2d06dd760e5e 100644 --- a/scripts/generators/tsconfig.js +++ b/scripts/generators/tsconfig.js @@ -118,6 +118,10 @@ fs.writeFileSync( ], ["globals", ["./node_modules/globals-BABEL_8_BREAKING-true"]], ["regexpu-core", ["./lib/regexpu-core.d.ts"]], + [ + "to-fast-properties", + ["./node_modules/to-fast-properties-BABEL_8_BREAKING-true"], + ], ]), }, }, diff --git a/tsconfig.json b/tsconfig.json index 8fce7ecacb84..7b755d5f4222 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -704,6 +704,9 @@ ], "regexpu-core": [ "./lib/regexpu-core.d.ts" + ], + "to-fast-properties": [ + "./node_modules/to-fast-properties-BABEL_8_BREAKING-true" ] } } diff --git a/yarn.lock b/yarn.lock index 3c8958ee30c7..e9a20f1786a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3794,7 +3794,7 @@ __metadata: "@babel/parser": "workspace:^" chalk: ^4.1.0 glob: ^7.1.7 - to-fast-properties: ^2.0.0 + to-fast-properties: "condition:BABEL_8_BREAKING ? ^4.0.0 : ^2.0.0" languageName: unknown linkType: soft @@ -14704,13 +14704,30 @@ fsevents@^1.2.7: languageName: node linkType: hard -"to-fast-properties@npm:^2.0.0": +"to-fast-properties-BABEL_8_BREAKING-false@npm:to-fast-properties@^2.0.0, to-fast-properties@npm:^2.0.0": version: 2.0.0 resolution: "to-fast-properties@npm:2.0.0" checksum: be2de62fe58ead94e3e592680052683b1ec986c72d589e7b21e5697f8744cdbf48c266fa72f6c15932894c10187b5f54573a3bcf7da0bfd964d5caf23d436168 languageName: node linkType: hard +"to-fast-properties-BABEL_8_BREAKING-true@npm:to-fast-properties@^4.0.0": + version: 4.0.0 + resolution: "to-fast-properties@npm:4.0.0" + checksum: c72297bdd126a7e7ffe9cc6230eee60182f0439a7abb19d281e73137880d87d12fc971a47ff4bd1e0dc68e17262344fbf98499400ff5e341db431715c3620346 + languageName: node + linkType: hard + +"to-fast-properties@condition:BABEL_8_BREAKING ? ^4.0.0 : ^2.0.0": + version: 0.0.0-condition-ce57b6 + resolution: "to-fast-properties@condition:BABEL_8_BREAKING?^4.0.0:^2.0.0#ce57b6" + dependencies: + to-fast-properties-BABEL_8_BREAKING-false: "npm:to-fast-properties@^2.0.0" + to-fast-properties-BABEL_8_BREAKING-true: "npm:to-fast-properties@^4.0.0" + checksum: e301950506020ee20ad9ebdf7da40174c08f441a9ac0fe89d0efeb70a7fcedefdb3079433eae3d5a840ee38d589c0c2c9e27774d93fb60cd5af9b22b8b95df67 + languageName: node + linkType: hard + "to-object-path@npm:^0.3.0": version: 0.3.0 resolution: "to-object-path@npm:0.3.0" From 5112d5f85476d86d3d2132a9e4c25d3b4d56cf78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Thu, 2 Jun 2022 14:28:31 -0400 Subject: [PATCH 2/3] types --- .../babel-types/src/builders/validateNode.ts | 2 +- packages/babel-types/src/clone/cloneNode.ts | 23 +++- .../babel-types/src/comments/addComments.ts | 4 +- packages/babel-types/src/constants/index.ts | 4 +- packages/babel-types/src/converters/Scope.ts | 8 -- .../babel-types/src/converters/ensureBlock.ts | 6 +- .../converters/gatherSequenceExpressions.ts | 14 +- .../babel-types/src/converters/toBlock.ts | 2 +- .../src/converters/toSequenceExpression.ts | 6 +- .../babel-types/src/converters/toStatement.ts | 7 +- .../babel-types/src/converters/valueToNode.ts | 16 ++- packages/babel-types/src/definitions/core.ts | 128 ++++++++++-------- packages/babel-types/src/definitions/flow.ts | 5 +- packages/babel-types/src/definitions/index.ts | 2 + .../babel-types/src/definitions/typescript.ts | 4 +- packages/babel-types/src/definitions/utils.ts | 70 +++++----- .../flow/removeTypeDuplicates.ts | 15 +- .../babel-types/src/modifications/inherits.ts | 8 +- .../src/modifications/removeProperties.ts | 21 ++- .../typescript/removeTypeDuplicates.ts | 11 +- .../src/retrievers/getBindingIdentifiers.ts | 13 +- .../babel-types/src/traverse/traverseFast.ts | 13 +- packages/babel-types/src/utils/inherit.ts | 10 +- .../babel-types/src/utils/shallowEqual.ts | 7 +- .../babel-types/src/validators/isBinding.ts | 8 +- packages/babel-types/src/validators/isLet.ts | 4 +- .../src/validators/isNodesEquivalent.ts | 28 ++-- packages/babel-types/src/validators/isVar.ts | 6 +- .../babel-types/src/validators/validate.ts | 10 +- 29 files changed, 280 insertions(+), 175 deletions(-) delete mode 100644 packages/babel-types/src/converters/Scope.ts diff --git a/packages/babel-types/src/builders/validateNode.ts b/packages/babel-types/src/builders/validateNode.ts index aa6bbd0889b0..a3518383030f 100644 --- a/packages/babel-types/src/builders/validateNode.ts +++ b/packages/babel-types/src/builders/validateNode.ts @@ -4,7 +4,7 @@ import { BUILDER_KEYS } from ".."; export default function validateNode(node: N) { // todo: because keys not in BUILDER_KEYS are not validated - this actually allows invalid nodes in some cases - const keys = BUILDER_KEYS[node.type]; + const keys = BUILDER_KEYS[node.type] as (keyof N & string)[]; for (const key of keys) { validate(node, key, node[key]); } diff --git a/packages/babel-types/src/clone/cloneNode.ts b/packages/babel-types/src/clone/cloneNode.ts index 2f2ac74e2b56..cae62cc7ab72 100644 --- a/packages/babel-types/src/clone/cloneNode.ts +++ b/packages/babel-types/src/clone/cloneNode.ts @@ -4,8 +4,15 @@ import { isFile, isIdentifier } from "../validators/generated"; const has = Function.call.bind(Object.prototype.hasOwnProperty); +type CommentCache = Map; + // This function will never be called for comments, only for real nodes. -function cloneIfNode(obj, deep, withoutLoc, commentsCache) { +function cloneIfNode( + obj: t.Node | undefined | null, + deep: boolean, + withoutLoc: boolean, + commentsCache: CommentCache, +) { if (obj && typeof obj.type === "string") { return cloneNodeInternal(obj, deep, withoutLoc, commentsCache); } @@ -13,7 +20,12 @@ function cloneIfNode(obj, deep, withoutLoc, commentsCache) { return obj; } -function cloneIfNodeOrArray(obj, deep, withoutLoc, commentsCache) { +function cloneIfNodeOrArray( + obj: t.Node | undefined | null | (t.Node | undefined | null)[], + deep: boolean, + withoutLoc: boolean, + commentsCache: CommentCache, +) { if (Array.isArray(obj)) { return obj.map(node => cloneIfNode(node, deep, withoutLoc, commentsCache)); } @@ -37,7 +49,7 @@ function cloneNodeInternal( node: T, deep: boolean = true, withoutLoc: boolean = false, - commentsCache: Map, + commentsCache: CommentCache, ): T { if (!node) return node; @@ -77,13 +89,16 @@ function cloneNodeInternal( commentsCache, ) : cloneIfNodeOrArray( + // @ts-expect-error node[field] has been guarded by has check node[field], true, withoutLoc, commentsCache, ); } else { - newNode[field] = node[field]; + newNode[field] = + // @ts-expect-error node[field] has been guarded by has check + node[field]; } } } diff --git a/packages/babel-types/src/comments/addComments.ts b/packages/babel-types/src/comments/addComments.ts index a01ce1c42b94..5aeb69b2328d 100644 --- a/packages/babel-types/src/comments/addComments.ts +++ b/packages/babel-types/src/comments/addComments.ts @@ -6,11 +6,11 @@ import type * as t from ".."; export default function addComments( node: T, type: t.CommentTypeShorthand, - comments: ReadonlyArray, + comments: Array, ): T { if (!comments || !node) return node; - const key = `${type}Comments`; + const key = `${type}Comments` as const; if (node[key]) { if (type === "leading") { diff --git a/packages/babel-types/src/constants/index.ts b/packages/babel-types/src/constants/index.ts index e3ece7c5d7f5..9eced88e847f 100644 --- a/packages/babel-types/src/constants/index.ts +++ b/packages/babel-types/src/constants/index.ts @@ -5,7 +5,7 @@ export const COMMENT_KEYS = [ "leadingComments", "trailingComments", "innerComments", -]; +] as const; export const LOGICAL_OPERATORS = ["||", "&&", "??"]; export const UPDATE_OPERATORS = ["++", "--"]; @@ -62,7 +62,7 @@ export const UNARY_OPERATORS = [ export const INHERIT_KEYS = { optional: ["typeAnnotation", "typeParameters", "returnType"], force: ["start", "loc", "end"], -}; +} as const; export const BLOCK_SCOPED_SYMBOL = Symbol.for("var used to be block scoped"); export const NOT_LOCAL_BINDING = Symbol.for( diff --git a/packages/babel-types/src/converters/Scope.ts b/packages/babel-types/src/converters/Scope.ts deleted file mode 100644 index 3ea3ef8ae48c..000000000000 --- a/packages/babel-types/src/converters/Scope.ts +++ /dev/null @@ -1,8 +0,0 @@ -// NOTE: this actually uses Scope from @babel/traverse, but we can't add a dependency on its types, -// because this would be cyclic dependency. Declare the structural subset that is required. -import type * as t from ".."; - -export type Scope = { - push(value: { id: t.LVal; kind: "var"; init?: t.Expression }): void; - buildUndefinedNode(): t.Node; -}; diff --git a/packages/babel-types/src/converters/ensureBlock.ts b/packages/babel-types/src/converters/ensureBlock.ts index 069e099df7c0..581a15af7638 100644 --- a/packages/babel-types/src/converters/ensureBlock.ts +++ b/packages/babel-types/src/converters/ensureBlock.ts @@ -11,5 +11,9 @@ export default function ensureBlock( node: t.Node, key: string = "body", ): t.BlockStatement { - return (node[key] = toBlock(node[key], node)); + // @ts-ignore Fixme: key may not exist in node, consider remove key = "body" + const result = toBlock(node[key], node); + // @ts-ignore + node[key] = result; + return result; } diff --git a/packages/babel-types/src/converters/gatherSequenceExpressions.ts b/packages/babel-types/src/converters/gatherSequenceExpressions.ts index 71ef31ec9d6e..caed9484f014 100644 --- a/packages/babel-types/src/converters/gatherSequenceExpressions.ts +++ b/packages/babel-types/src/converters/gatherSequenceExpressions.ts @@ -14,14 +14,19 @@ import { } from "../builders/generated"; import cloneNode from "../clone/cloneNode"; import type * as t from ".."; -import type { Scope } from "./Scope"; +import type { Scope } from "@babel/traverse"; + +export type DeclarationInfo = { + kind: t.VariableDeclaration["kind"]; + id: t.Identifier; +}; export default function gatherSequenceExpressions( nodes: ReadonlyArray, scope: Scope, - declars: Array, -): t.SequenceExpression { - const exprs = []; + declars: Array, +) { + const exprs: t.Expression[] = []; let ensureLastUndefined = true; for (const node of nodes) { @@ -62,7 +67,6 @@ export default function gatherSequenceExpressions( : scope.buildUndefinedNode(); if (!consequent || !alternate) return; // bailed - // @ts-expect-error todo(flow->ts) consequent - Argument of type 'Node' is not assignable to parameter of type 'Expression' exprs.push(conditionalExpression(node.test, consequent, alternate)); } else if (isBlockStatement(node)) { const body = gatherSequenceExpressions(node.body, scope, declars); diff --git a/packages/babel-types/src/converters/toBlock.ts b/packages/babel-types/src/converters/toBlock.ts index 34f2a1a640f2..46acf7178276 100644 --- a/packages/babel-types/src/converters/toBlock.ts +++ b/packages/babel-types/src/converters/toBlock.ts @@ -19,7 +19,7 @@ export default function toBlock( return node; } - let blockNodes = []; + let blockNodes: t.Statement[] = []; if (isEmptyStatement(node)) { blockNodes = []; diff --git a/packages/babel-types/src/converters/toSequenceExpression.ts b/packages/babel-types/src/converters/toSequenceExpression.ts index 5d99d4cf24f9..86e076669374 100644 --- a/packages/babel-types/src/converters/toSequenceExpression.ts +++ b/packages/babel-types/src/converters/toSequenceExpression.ts @@ -1,6 +1,7 @@ import gatherSequenceExpressions from "./gatherSequenceExpressions"; import type * as t from ".."; -import type { Scope } from "./Scope"; +import type { Scope } from "@babel/traverse"; +import type { DeclarationInfo } from "./gatherSequenceExpressions"; /** * Turn an array of statement `nodes` into a `SequenceExpression`. @@ -16,7 +17,7 @@ export default function toSequenceExpression( ): t.SequenceExpression | undefined { if (!nodes?.length) return; - const declars = []; + const declars: DeclarationInfo[] = []; const result = gatherSequenceExpressions(nodes, scope, declars); if (!result) return; @@ -24,5 +25,6 @@ export default function toSequenceExpression( scope.push(declar); } + // @ts-ignore fixme: gatherSequenceExpressions will return an Expression when there are only one element return result; } diff --git a/packages/babel-types/src/converters/toStatement.ts b/packages/babel-types/src/converters/toStatement.ts index 6537206014fa..9f33510b5dc9 100644 --- a/packages/babel-types/src/converters/toStatement.ts +++ b/packages/babel-types/src/converters/toStatement.ts @@ -33,17 +33,17 @@ function toStatement(node: t.Node, ignore?: boolean): t.Statement | false { if (isClass(node)) { mustHaveId = true; - newType = "ClassDeclaration"; + newType = "ClassDeclaration" as const; } else if (isFunction(node)) { mustHaveId = true; - newType = "FunctionDeclaration"; + newType = "FunctionDeclaration" as const; } else if (isAssignmentExpression(node)) { return expressionStatement(node); } // @ts-expect-error todo(flow->ts): node.id might be missing if (mustHaveId && !node.id) { - newType = false; + newType = false as false; } if (!newType) { @@ -54,6 +54,7 @@ function toStatement(node: t.Node, ignore?: boolean): t.Statement | false { } } + // @ts-expect-error manipulating node.type node.type = newType; // @ts-expect-error todo(flow->ts) refactor to avoid type unsafe mutations like reassigning node type above diff --git a/packages/babel-types/src/converters/valueToNode.ts b/packages/babel-types/src/converters/valueToNode.ts index 6eb52b873e7a..521515ab3bbb 100644 --- a/packages/babel-types/src/converters/valueToNode.ts +++ b/packages/babel-types/src/converters/valueToNode.ts @@ -31,15 +31,15 @@ export default valueToNode as { (value: unknown): t.Expression; }; -const objectToString: (value: object) => string = Function.call.bind( +const objectToString: (value: unknown) => string = Function.call.bind( Object.prototype.toString, ); -function isRegExp(value): value is RegExp { +function isRegExp(value: unknown): value is RegExp { return objectToString(value) === "[object RegExp]"; } -function isPlainObject(value): value is object { +function isPlainObject(value: unknown): value is object { if ( typeof value !== "object" || value === null || @@ -122,7 +122,15 @@ function valueToNode(value: unknown): t.Expression { } else { nodeKey = stringLiteral(key); } - props.push(objectProperty(nodeKey, valueToNode(value[key]))); + props.push( + objectProperty( + nodeKey, + valueToNode( + // @ts-expect-error key must present in value + value[key], + ), + ), + ); } return objectExpression(props); } diff --git a/packages/babel-types/src/definitions/core.ts b/packages/babel-types/src/definitions/core.ts index c5f6114f299e..213ed8c27c9f 100644 --- a/packages/babel-types/src/definitions/core.ts +++ b/packages/babel-types/src/definitions/core.ts @@ -1,6 +1,7 @@ import is from "../validators/is"; import isValidIdentifier from "../validators/isValidIdentifier"; import { isKeyword, isReservedWord } from "@babel/helper-validator-identifier"; +import type * as t from ".."; import { BINARY_OPERATORS, @@ -21,6 +22,7 @@ import { chain, assertOneOf, validateOptional, + type Validator, } from "./utils"; const defineType = defineAliasedType("Standardized"); @@ -52,7 +54,7 @@ defineType("AssignmentExpression", { const identifier = assertOneOf(...ASSIGNMENT_OPERATORS); const pattern = assertOneOf("="); - return function (node, key, val) { + return function (node: t.AssignmentExpression, key, val) { const validator = is("Pattern", node.left) ? pattern : identifier; validator(node, key, val); }; @@ -91,12 +93,14 @@ defineType("BinaryExpression", { const expression = assertNodeType("Expression"); const inOp = assertNodeType("Expression", "PrivateName"); - const validator = function (node, key, val) { - const validator = node.operator === "in" ? inOp : expression; - validator(node, key, val); - }; - // todo(ts): can be discriminated union by `operator` property - validator.oneOfNodeTypes = ["Expression", "PrivateName"]; + const validator: Validator = Object.assign( + function (node: t.BinaryExpression, key, val) { + const validator = node.operator === "in" ? inOp : expression; + validator(node, key, val); + } as Validator, + // todo(ts): can be discriminated union by `operator` property + { oneOfNodeTypes: ["Expression", "PrivateName"] }, + ); return validator; })(), }, @@ -498,7 +502,7 @@ defineType("Identifier", { if (!isValidIdentifier(val, false)) { throw new TypeError(`"${val}" is not a valid identifier name`); } - }, + } as Validator, { type: "string" }, ), ), @@ -631,7 +635,7 @@ defineType("RegExpLiteral", { if (invalid) { throw new TypeError(`"${invalid[0]}" is not a valid RegExp flag`); } - }, + } as Validator, { type: "string" }, ), ), @@ -675,11 +679,15 @@ defineType("MemberExpression", { const normal = assertNodeType("Identifier", "PrivateName"); const computed = assertNodeType("Expression"); - const validator = function (node, key, val) { - const validator = node.computed ? computed : normal; + const validator: Validator = function ( + node: t.MemberExpression, + key, + val, + ) { + const validator: Validator = node.computed ? computed : normal; validator(node, key, val); }; - // todo(ts): can be discriminated union by `computed` property + // @ts-expect-error todo(ts): can be discriminated union by `computed` property validator.oneOfNodeTypes = ["Expression", "Identifier", "PrivateName"]; return validator; })(), @@ -771,11 +779,11 @@ defineType("ObjectMethod", { ); const computed = assertNodeType("Expression"); - const validator = function (node, key, val) { + const validator: Validator = function (node: t.ObjectMethod, key, val) { const validator = node.computed ? computed : normal; validator(node, key, val); }; - // todo(ts): can be discriminated union by `computed` property + // @ts-expect-error todo(ts): can be discriminated union by `computed` property validator.oneOfNodeTypes = [ "Expression", "Identifier", @@ -839,20 +847,24 @@ defineType("ObjectProperty", { ); const computed = assertNodeType("Expression"); - const validator = function (node, key, val) { - const validator = node.computed ? computed : normal; - validator(node, key, val); - }; - // todo(ts): can be discriminated union by `computed` property - validator.oneOfNodeTypes = [ - "Expression", - "Identifier", - "StringLiteral", - "NumericLiteral", - "BigIntLiteral", - "DecimalLiteral", - "PrivateName", - ]; + const validator: Validator = Object.assign( + function (node: t.ObjectProperty, key, val) { + const validator = node.computed ? computed : normal; + validator(node, key, val); + } as Validator, + { + // todo(ts): can be discriminated union by `computed` property + oneOfNodeTypes: [ + "Expression", + "Identifier", + "StringLiteral", + "NumericLiteral", + "BigIntLiteral", + "DecimalLiteral", + "PrivateName", + ], + }, + ); return validator; })(), }, @@ -865,7 +877,7 @@ defineType("ObjectProperty", { validate: chain( assertValueType("boolean"), Object.assign( - function (node, key, val) { + function (node: t.ObjectProperty, key, val) { if (!process.env.BABEL_TYPES_8_BREAKING) return; if (val && node.computed) { @@ -873,10 +885,10 @@ defineType("ObjectProperty", { "Property shorthand of ObjectProperty cannot be true if computed is true", ); } - }, + } as Validator, { type: "boolean" }, ), - function (node, key, val) { + function (node: t.ObjectProperty, key, val) { if (!process.env.BABEL_TYPES_8_BREAKING) return; if (val && !is("Identifier", node.key)) { @@ -884,7 +896,7 @@ defineType("ObjectProperty", { "Property shorthand of ObjectProperty cannot be true if key is not an Identifier", ); } - }, + } as Validator, ), default: false, }, @@ -943,14 +955,18 @@ defineType("RestElement", { optional: true, }, }, - validate(parent, key) { + validate(parent: t.ArrayPattern | t.ObjectPattern, key) { if (!process.env.BABEL_TYPES_8_BREAKING) return; const match = /(\w+)\[(\d+)\]/.exec(key); if (!match) throw new Error("Internal Babel error: malformed key."); - const [, listKey, index] = match; - if (parent[listKey].length > index + 1) { + const [, listKey, index] = match as unknown as [ + string, + keyof typeof parent, + string, + ]; + if ((parent[listKey] as t.Node[]).length > +index + 1) { throw new TypeError(`RestElement must be last element of ${listKey}`); } }, @@ -1044,7 +1060,7 @@ defineType("TryStatement", { validate: chain( assertNodeType("BlockStatement"), Object.assign( - function (node) { + function (node: t.TryStatement) { if (!process.env.BABEL_TYPES_8_BREAKING) return; // This validator isn't put at the top level because we can run it @@ -1055,7 +1071,7 @@ defineType("TryStatement", { "TryStatement expects either a handler or finalizer, or both", ); } - }, + } as Validator, { oneOfNodeTypes: ["BlockStatement"], }, @@ -1156,7 +1172,7 @@ defineType("VariableDeclarator", { ); const without = assertNodeType("Identifier"); - return function (node, key, val) { + return function (node: t.VariableDeclarator, key, val) { const validator = node.init ? normal : without; validator(node, key, val); }; @@ -1512,7 +1528,7 @@ defineType("ExportNamedDeclaration", { validate: chain( assertNodeType("Declaration"), Object.assign( - function (node, key, val) { + function (node: t.ExportNamedDeclaration, key, val) { if (!process.env.BABEL_TYPES_8_BREAKING) return; // This validator isn't put at the top level because we can run it @@ -1523,10 +1539,10 @@ defineType("ExportNamedDeclaration", { "Only declaration or specifiers is allowed on ExportNamedDeclaration", ); } - }, + } as Validator, { oneOfNodeTypes: ["Declaration"] }, ), - function (node, key, val) { + function (node: t.ExportNamedDeclaration, key, val) { if (!process.env.BABEL_TYPES_8_BREAKING) return; // This validator isn't put at the top level because we can run it @@ -1560,10 +1576,10 @@ defineType("ExportNamedDeclaration", { if (!process.env.BABEL_TYPES_8_BREAKING) return sourced; - return function (node, key, val) { + return function (node: t.ExportNamedDeclaration, key, val) { const validator = node.source ? sourced : sourceless; validator(node, key, val); - }; + } as Validator; })(), ), ), @@ -1726,7 +1742,7 @@ defineType("MetaProperty", { validate: chain( assertNodeType("Identifier"), Object.assign( - function (node, key, val) { + function (node: t.MetaProperty, key, val) { if (!process.env.BABEL_TYPES_8_BREAKING) return; let property; @@ -1744,7 +1760,7 @@ defineType("MetaProperty", { if (!is("Identifier", node.property, { name: property })) { throw new TypeError("Unrecognised MetaProperty"); } - }, + } as Validator, { oneOfNodeTypes: ["Identifier"] }, ), ), @@ -1962,7 +1978,7 @@ defineType("TemplateLiteral", { "TSType", ), ), - function (node, key, val) { + function (node: t.TemplateLiteral, key, val) { if (node.quasis.length !== val.length + 1) { throw new TypeError( `Number of ${ @@ -1972,7 +1988,7 @@ defineType("TemplateLiteral", { } quasis but got ${node.quasis.length}`, ); } - }, + } as Validator, ), }, }, @@ -1987,7 +2003,7 @@ defineType("YieldExpression", { validate: chain( assertValueType("boolean"), Object.assign( - function (node, key, val) { + function (node: t.YieldExpression, key, val) { if (!process.env.BABEL_TYPES_8_BREAKING) return; if (val && !node.argument) { @@ -1995,7 +2011,7 @@ defineType("YieldExpression", { "Property delegate of YieldExpression cannot be true if there is no argument", ); } - }, + } as Validator, { type: "boolean" }, ), ), @@ -2059,12 +2075,14 @@ defineType("OptionalMemberExpression", { const normal = assertNodeType("Identifier"); const computed = assertNodeType("Expression"); - const validator = function (node, key, val) { - const validator = node.computed ? computed : normal; - validator(node, key, val); - }; - // todo(ts): can be discriminated union by `computed` property - validator.oneOfNodeTypes = ["Expression", "Identifier"]; + const validator: Validator = Object.assign( + function (node: t.OptionalMemberExpression, key, val) { + const validator = node.computed ? computed : normal; + validator(node, key, val); + } as Validator, + // todo(ts): can be discriminated union by `computed` property + { oneOfNodeTypes: ["Expression", "Identifier"] }, + ); return validator; })(), }, diff --git a/packages/babel-types/src/definitions/flow.ts b/packages/babel-types/src/definitions/flow.ts index a51e0c91fd06..d66d9420bfd8 100644 --- a/packages/babel-types/src/definitions/flow.ts +++ b/packages/babel-types/src/definitions/flow.ts @@ -13,8 +13,7 @@ import { const defineType = defineAliasedType("Flow"); const defineInterfaceishType = ( - name: string, - typeParameterType: string = "TypeParameterDeclaration", + name: "DeclareClass" | "DeclareInterface" | "InterfaceDeclaration", ) => { defineType(name, { builder: ["id", "typeParameters", "extends", "body"], @@ -29,7 +28,7 @@ const defineInterfaceishType = ( aliases: ["FlowDeclaration", "Statement", "Declaration"], fields: { id: validateType("Identifier"), - typeParameters: validateOptionalType(typeParameterType), + typeParameters: validateOptionalType("TypeParameterDeclaration"), extends: validateOptional(arrayOfType("InterfaceExtends")), mixins: validateOptional(arrayOfType("InterfaceExtends")), implements: validateOptional(arrayOfType("ClassImplements")), diff --git a/packages/babel-types/src/definitions/index.ts b/packages/babel-types/src/definitions/index.ts index a420122dcf61..bd8d27d62c43 100644 --- a/packages/babel-types/src/definitions/index.ts +++ b/packages/babel-types/src/definitions/index.ts @@ -50,3 +50,5 @@ export { PLACEHOLDERS_FLIPPED_ALIAS, TYPES, }; + +export type { FieldOptions } from "./utils"; diff --git a/packages/babel-types/src/definitions/typescript.ts b/packages/babel-types/src/definitions/typescript.ts index ef8778b68737..b7e1d29e26ba 100644 --- a/packages/babel-types/src/definitions/typescript.ts +++ b/packages/babel-types/src/definitions/typescript.ts @@ -179,7 +179,7 @@ const tsKeywordTypes = [ "TSUndefinedKeyword", "TSUnknownKeyword", "TSVoidKeyword", -]; +] as const; for (const type of tsKeywordTypes) { defineType(type, { @@ -384,7 +384,7 @@ defineType("TSLiteralType", { "BooleanLiteral", "BigIntLiteral", ); - function validator(parent, key: string, node) { + function validator(parent: any, key: string, node: any) { // type A = -1 | 1; if (is("UnaryExpression", node)) { // check operator first diff --git a/packages/babel-types/src/definitions/utils.ts b/packages/babel-types/src/definitions/utils.ts index 6ed5ce96b370..6a220887ef65 100644 --- a/packages/babel-types/src/definitions/utils.ts +++ b/packages/babel-types/src/definitions/utils.ts @@ -1,15 +1,16 @@ import is from "../validators/is"; import { validateField, validateChild } from "../validators/validate"; +import type * as t from ".."; export const VISITOR_KEYS: Record = {}; export const ALIAS_KEYS: Record = {}; export const FLIPPED_ALIAS_KEYS: Record = {}; -export const NODE_FIELDS: Record = {}; +export const NODE_FIELDS: Record = {}; export const BUILDER_KEYS: Record = {}; export const DEPRECATED_KEYS: Record = {}; -export const NODE_PARENT_VALIDATIONS = {}; +export const NODE_PARENT_VALIDATIONS: Record = {}; -function getType(val) { +function getType(val: any) { if (Array.isArray(val)) { return "array"; } else if (val === null) { @@ -19,32 +20,37 @@ function getType(val) { } } +type NodeTypes = t.Node["type"] | t.Comment["type"] | keyof t.Aliases; + +type PrimitiveTypes = ReturnType; + +type FieldDefinitions = { + [x: string]: FieldOptions; +}; + type DefineTypeOpts = { - fields?: { - [x: string]: FieldOptions; - }; + fields?: FieldDefinitions; visitor?: Array; aliases?: Array; builder?: Array; - inherits?: string; + inherits?: NodeTypes; deprecatedAlias?: string; validate?: Validator; }; -type Validator = ( - | { type: string } +export type Validator = ( + | { type: PrimitiveTypes } | { each: Validator } | { chainOf: Validator[] } | { oneOf: any[] } - | { oneOfNodeTypes: string[] } - | { oneOfNodeOrValueTypes: string[] } + | { oneOfNodeTypes: NodeTypes[] } + | { oneOfNodeOrValueTypes: (NodeTypes | PrimitiveTypes)[] } | { shapeOf: { [x: string]: FieldOptions } } | {} ) & - // TODO: Import and use Node instead of any - ((parent: any, key: string, node: any) => void); + ((node: t.Node, key: string, val: any) => void); -type FieldOptions = { +export type FieldOptions = { default?: any; optional?: boolean; validate?: Validator; @@ -54,13 +60,13 @@ export function validate(validate: Validator): FieldOptions { return { validate }; } -export function typeIs(typeName: string | string[]) { +export function typeIs(typeName: NodeTypes | NodeTypes[]) { return typeof typeName === "string" ? assertNodeType(typeName) : assertNodeType(...typeName); } -export function validateType(typeName: string | string[]) { +export function validateType(typeName: NodeTypes | NodeTypes[]) { return validate(typeIs(typeName)); } @@ -69,7 +75,7 @@ export function validateOptional(validate: Validator): FieldOptions { } export function validateOptionalType( - typeName: string | string[], + typeName: NodeTypes | NodeTypes[], ): FieldOptions { return { validate: typeIs(typeName), optional: true }; } @@ -78,16 +84,16 @@ export function arrayOf(elementType: Validator): Validator { return chain(assertValueType("array"), assertEach(elementType)); } -export function arrayOfType(typeName: string | string[]) { +export function arrayOfType(typeName: NodeTypes | NodeTypes[]) { return arrayOf(typeIs(typeName)); } -export function validateArrayOfType(typeName: string | string[]) { +export function validateArrayOfType(typeName: NodeTypes | NodeTypes[]) { return validate(arrayOfType(typeName)); } export function assertEach(callback: Validator): Validator { - function validator(node, key, val) { + function validator(node: t.Node, key: string, val: any) { if (!Array.isArray(val)) return; for (let i = 0; i < val.length; i++) { @@ -117,8 +123,8 @@ export function assertOneOf(...values: Array): Validator { return validate; } -export function assertNodeType(...types: Array): Validator { - function validate(node, key, val) { +export function assertNodeType(...types: NodeTypes[]): Validator { + function validate(node: t.Node, key: string, val: any) { for (const type of types) { if (is(type, val)) { validateChild(node, key, val); @@ -140,8 +146,10 @@ export function assertNodeType(...types: Array): Validator { return validate; } -export function assertNodeOrValueType(...types: Array): Validator { - function validate(node, key, val) { +export function assertNodeOrValueType( + ...types: (NodeTypes | PrimitiveTypes)[] +): Validator { + function validate(node: t.Node, key: string, val: any) { for (const type of types) { if (getType(val) === type || is(type, val)) { validateChild(node, key, val); @@ -163,8 +171,8 @@ export function assertNodeOrValueType(...types: Array): Validator { return validate; } -export function assertValueType(type: string): Validator { - function validate(node, key, val) { +export function assertValueType(type: PrimitiveTypes): Validator { + function validate(node: t.Node, key: string, val: any) { const valid = getType(val) === type; if (!valid) { @@ -180,7 +188,7 @@ export function assertValueType(type: string): Validator { } export function assertShape(shape: { [x: string]: FieldOptions }): Validator { - function validate(node, key, val) { + function validate(node: t.Node, key: string, val: any) { const errors = []; for (const property of Object.keys(shape)) { try { @@ -208,7 +216,7 @@ export function assertShape(shape: { [x: string]: FieldOptions }): Validator { } export function assertOptionalChainStart(): Validator { - function validate(node) { + function validate(node: t.Node) { let current = node; while (node) { const { type } = current; @@ -270,7 +278,7 @@ const validFieldKeys = ["default", "optional", "validate"]; // Wraps defineType to ensure these aliases are included. export function defineAliasedType(...aliases: string[]) { - return (type: string, opts: DefineTypeOpts = {}) => { + return (type: NodeTypes, opts: DefineTypeOpts = {}) => { let defined = opts.aliases; if (!defined) { if (opts.inherits) defined = store[opts.inherits].aliases?.slice(); @@ -283,7 +291,7 @@ export function defineAliasedType(...aliases: string[]) { }; } -export default function defineType(type: string, opts: DefineTypeOpts = {}) { +export default function defineType(type: NodeTypes, opts: DefineTypeOpts = {}) { const inherits = (opts.inherits && store[opts.inherits]) || {}; let fields = opts.fields; @@ -365,4 +373,4 @@ export default function defineType(type: string, opts: DefineTypeOpts = {}) { store[type] = opts; } -const store = {}; +const store = {} as Record; diff --git a/packages/babel-types/src/modifications/flow/removeTypeDuplicates.ts b/packages/babel-types/src/modifications/flow/removeTypeDuplicates.ts index 717b993d5a0d..f9885552a00d 100644 --- a/packages/babel-types/src/modifications/flow/removeTypeDuplicates.ts +++ b/packages/babel-types/src/modifications/flow/removeTypeDuplicates.ts @@ -7,7 +7,7 @@ import { } from "../../validators/generated"; import type * as t from "../.."; -function getQualifiedName(node: t.GenericTypeAnnotation["id"]) { +function getQualifiedName(node: t.GenericTypeAnnotation["id"]): string { return isIdentifier(node) ? node.name : `${node.id.name}.${getQualifiedName(node.qualification)}`; @@ -20,13 +20,16 @@ export default function removeTypeDuplicates( // todo(babel-8): change type to Array<...> nodes: ReadonlyArray, ): t.FlowType[] { - const generics = {}; - const bases = {}; + const generics: Record = {}; + const bases = {} as Record< + t.FlowBaseAnnotation["type"], + t.FlowBaseAnnotation + >; // store union type groups to circular references const typeGroups = new Set(); - const types = []; + const types: t.FlowType[] = []; for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; @@ -61,7 +64,7 @@ export default function removeTypeDuplicates( const name = getQualifiedName(node.id); if (generics[name]) { - let existing = generics[name]; + let existing: t.Flow = generics[name]; if (existing.typeParameters) { if (node.typeParameters) { existing.typeParameters.params = removeTypeDuplicates( @@ -82,7 +85,7 @@ export default function removeTypeDuplicates( } // add back in bases - for (const type of Object.keys(bases)) { + for (const type of Object.keys(bases) as (keyof typeof bases)[]) { types.push(bases[type]); } diff --git a/packages/babel-types/src/modifications/inherits.ts b/packages/babel-types/src/modifications/inherits.ts index d426ee44c5c4..5fbf401b15c7 100644 --- a/packages/babel-types/src/modifications/inherits.ts +++ b/packages/babel-types/src/modifications/inherits.ts @@ -13,18 +13,24 @@ export default function inherits( // optionally inherit specific properties if not null for (const key of INHERIT_KEYS.optional) { + // @ts-expect-error Fixme: refine parent types if (child[key] == null) { + // @ts-expect-error Fixme: refine parent types child[key] = parent[key]; } } // force inherit "private" properties for (const key of Object.keys(parent)) { - if (key[0] === "_" && key !== "__clone") child[key] = parent[key]; + if (key[0] === "_" && key !== "__clone") { + // @ts-expect-error Fixme: refine parent types + child[key] = parent[key]; + } } // force inherit select properties for (const key of INHERIT_KEYS.force) { + // @ts-expect-error Fixme: refine parent types child[key] = parent[key]; } diff --git a/packages/babel-types/src/modifications/removeProperties.ts b/packages/babel-types/src/modifications/removeProperties.ts index 38e4595ed9a4..5faa4a1fb74d 100644 --- a/packages/babel-types/src/modifications/removeProperties.ts +++ b/packages/babel-types/src/modifications/removeProperties.ts @@ -1,11 +1,21 @@ import { COMMENT_KEYS } from "../constants"; import type * as t from ".."; -const CLEAR_KEYS = ["tokens", "start", "end", "loc", "raw", "rawValue"]; +const CLEAR_KEYS = [ + "tokens", // only exist in t.File + "start", + "end", + "loc", + // Fixme: should be extra.raw / extra.rawValue? + "raw", + "rawValue", +] as const; -const CLEAR_KEYS_PLUS_COMMENTS = COMMENT_KEYS.concat(["comments"]).concat( - CLEAR_KEYS, -); +const CLEAR_KEYS_PLUS_COMMENTS = [ + ...COMMENT_KEYS, + "comments", + ...CLEAR_KEYS, +] as const; /** * Remove all of the _* properties from a node along with the additional metadata @@ -17,15 +27,18 @@ export default function removeProperties( ): void { const map = opts.preserveComments ? CLEAR_KEYS : CLEAR_KEYS_PLUS_COMMENTS; for (const key of map) { + // @ts-ignore if (node[key] != null) node[key] = undefined; } for (const key of Object.keys(node)) { + // @ts-ignore if (key[0] === "_" && node[key] != null) node[key] = undefined; } const symbols: Array = Object.getOwnPropertySymbols(node); for (const sym of symbols) { + // @ts-ignore Fixme: document symbol properties node[sym] = null; } } diff --git a/packages/babel-types/src/modifications/typescript/removeTypeDuplicates.ts b/packages/babel-types/src/modifications/typescript/removeTypeDuplicates.ts index da5c565f198f..28f811a4e86c 100644 --- a/packages/babel-types/src/modifications/typescript/removeTypeDuplicates.ts +++ b/packages/babel-types/src/modifications/typescript/removeTypeDuplicates.ts @@ -12,12 +12,12 @@ export default function removeTypeDuplicates( nodes: Array, ): Array { const generics = {}; - const bases = {}; + const bases = {} as Record; // store union type groups to circular references const typeGroups = new Set(); - const types = []; + const types: t.TSType[] = []; for (let i = 0; i < nodes.length; i++) { const node = nodes[i]; @@ -53,13 +53,16 @@ export default function removeTypeDuplicates( } // add back in bases - for (const type of Object.keys(bases)) { + for (const type of Object.keys(bases) as (keyof typeof bases)[]) { types.push(bases[type]); } // add back in generics for (const name of Object.keys(generics)) { - types.push(generics[name]); + types.push( + // @ts-ignore generics are not implemented + generics[name], + ); } return types; diff --git a/packages/babel-types/src/retrievers/getBindingIdentifiers.ts b/packages/babel-types/src/retrievers/getBindingIdentifiers.ts index 81b5a9ce1ad0..7e611397343b 100644 --- a/packages/babel-types/src/retrievers/getBindingIdentifiers.ts +++ b/packages/babel-types/src/retrievers/getBindingIdentifiers.ts @@ -36,14 +36,16 @@ function getBindingIdentifiers( duplicates?: boolean, outerOnly?: boolean, ): Record | Record> { - let search = [].concat(node); + const search: t.Node[] = [].concat(node); const ids = Object.create(null); while (search.length) { const id = search.shift(); if (!id) continue; - const keys = getBindingIdentifiers.keys[id.type]; + const keys = + // @ts-expect-error getBindingIdentifiers.keys do not cover all AST types + getBindingIdentifiers.keys[id.type]; if (isIdentifier(id)) { if (duplicates) { @@ -76,8 +78,11 @@ function getBindingIdentifiers( if (keys) { for (let i = 0; i < keys.length; i++) { const key = keys[i]; - if (id[key]) { - search = search.concat(id[key]); + const nodes = + // @ts-ignore key must present in id + id[key] as t.Node[] | t.Node | undefined | null; + if (nodes) { + Array.isArray(nodes) ? search.push(...nodes) : search.push(nodes); } } } diff --git a/packages/babel-types/src/traverse/traverseFast.ts b/packages/babel-types/src/traverse/traverseFast.ts index d0dc3376957f..66a8f65854fa 100644 --- a/packages/babel-types/src/traverse/traverseFast.ts +++ b/packages/babel-types/src/traverse/traverseFast.ts @@ -5,22 +5,23 @@ import type * as t from ".."; * A prefix AST traversal implementation meant for simple searching * and processing. */ -export default function traverseFast( +export default function traverseFast( node: t.Node | null | undefined, - enter: (node: t.Node, opts?: any) => void, - // todo(flow->ts) We could parametrize opts to T rather than any, so that the type is "forwarded" to the callback. - opts?: any, + enter: (node: t.Node, opts?: Options) => void, + opts?: Options, ): void { if (!node) return; const keys = VISITOR_KEYS[node.type]; if (!keys) return; - opts = opts || {}; + opts = opts || ({} as Options); enter(node, opts); for (const key of keys) { - const subNode = node[key]; + const subNode: t.Node | undefined | null = + // @ts-ignore key must present in node + node[key]; if (Array.isArray(subNode)) { for (const node of subNode) { diff --git a/packages/babel-types/src/utils/inherit.ts b/packages/babel-types/src/utils/inherit.ts index 53e65be848c7..bf561c22d38a 100644 --- a/packages/babel-types/src/utils/inherit.ts +++ b/packages/babel-types/src/utils/inherit.ts @@ -1,11 +1,11 @@ import type * as t from ".."; -export default function inherit( - key: string, - child: t.Node, - parent: t.Node, -): void { +export default function inherit< + C extends t.Node | undefined, + P extends t.Node | undefined, +>(key: keyof C & keyof P, child: C, parent: P): void { if (child && parent) { + // @ts-ignore Could further refine key definitions child[key] = Array.from( new Set([].concat(child[key], parent[key]).filter(Boolean)), ); diff --git a/packages/babel-types/src/utils/shallowEqual.ts b/packages/babel-types/src/utils/shallowEqual.ts index 98ddebcd7db3..7da3e99b08e4 100644 --- a/packages/babel-types/src/utils/shallowEqual.ts +++ b/packages/babel-types/src/utils/shallowEqual.ts @@ -2,10 +2,13 @@ export default function shallowEqual( actual: object, expected: T, ): actual is T { - const keys = Object.keys(expected); + const keys = Object.keys(expected) as (keyof T)[]; for (const key of keys) { - if (actual[key] !== expected[key]) { + if ( + // @ts-ignore maybe we should check whether key exists first + actual[key] !== expected[key] + ) { return false; } } diff --git a/packages/babel-types/src/validators/isBinding.ts b/packages/babel-types/src/validators/isBinding.ts index a91ad6306e7a..4af7de6dea04 100644 --- a/packages/babel-types/src/validators/isBinding.ts +++ b/packages/babel-types/src/validators/isBinding.ts @@ -19,11 +19,15 @@ export default function isBinding( return false; } - const keys = getBindingIdentifiers.keys[parent.type]; + const keys = + // @ts-expect-error getBindingIdentifiers.keys does not cover all AST types + getBindingIdentifiers.keys[parent.type]; if (keys) { for (let i = 0; i < keys.length; i++) { const key = keys[i]; - const val = parent[key]; + const val = + // @ts-expect-error key must present in parent + parent[key]; if (Array.isArray(val)) { if (val.indexOf(node) >= 0) return true; } else { diff --git a/packages/babel-types/src/validators/isLet.ts b/packages/babel-types/src/validators/isLet.ts index 06450cb9b490..893638ba4c8a 100644 --- a/packages/babel-types/src/validators/isLet.ts +++ b/packages/babel-types/src/validators/isLet.ts @@ -8,6 +8,8 @@ import type * as t from ".."; export default function isLet(node: t.Node): boolean { return ( isVariableDeclaration(node) && - (node.kind !== "var" || node[BLOCK_SCOPED_SYMBOL]) + (node.kind !== "var" || + // @ts-ignore Fixme: document private properties + node[BLOCK_SCOPED_SYMBOL]) ); } diff --git a/packages/babel-types/src/validators/isNodesEquivalent.ts b/packages/babel-types/src/validators/isNodesEquivalent.ts index 93a74b62164c..6cdb3c561cbb 100644 --- a/packages/babel-types/src/validators/isNodesEquivalent.ts +++ b/packages/babel-types/src/validators/isNodesEquivalent.ts @@ -25,41 +25,45 @@ export default function isNodesEquivalent>( const visitorKeys = VISITOR_KEYS[a.type]; for (const field of fields) { - if (typeof a[field] !== typeof b[field]) { + const val_a = + // @ts-ignore field must present in a + a[field]; + const val_b = b[field]; + if (typeof val_a !== typeof val_b) { return false; } - if (a[field] == null && b[field] == null) { + if (val_a == null && val_b == null) { continue; - } else if (a[field] == null || b[field] == null) { + } else if (val_a == null || val_b == null) { return false; } - if (Array.isArray(a[field])) { - if (!Array.isArray(b[field])) { + if (Array.isArray(val_a)) { + if (!Array.isArray(val_b)) { return false; } - if (a[field].length !== b[field].length) { + if (val_a.length !== val_b.length) { return false; } - for (let i = 0; i < a[field].length; i++) { - if (!isNodesEquivalent(a[field][i], b[field][i])) { + for (let i = 0; i < val_a.length; i++) { + if (!isNodesEquivalent(val_a[i], val_b[i])) { return false; } } continue; } - if (typeof a[field] === "object" && !visitorKeys?.includes(field)) { - for (const key of Object.keys(a[field])) { - if (a[field][key] !== b[field][key]) { + if (typeof val_a === "object" && !visitorKeys?.includes(field)) { + for (const key of Object.keys(val_a)) { + if (val_a[key] !== val_b[key]) { return false; } } continue; } - if (!isNodesEquivalent(a[field], b[field])) { + if (!isNodesEquivalent(val_a, val_b)) { return false; } } diff --git a/packages/babel-types/src/validators/isVar.ts b/packages/babel-types/src/validators/isVar.ts index 6eca80cd8d8d..b320e18759c2 100644 --- a/packages/babel-types/src/validators/isVar.ts +++ b/packages/babel-types/src/validators/isVar.ts @@ -7,6 +7,10 @@ import type * as t from ".."; */ export default function isVar(node: t.Node): boolean { return ( - isVariableDeclaration(node, { kind: "var" }) && !node[BLOCK_SCOPED_SYMBOL] + isVariableDeclaration(node, { kind: "var" }) && + !( + // @ts-ignore document private properties + node[BLOCK_SCOPED_SYMBOL] + ) ); } diff --git a/packages/babel-types/src/validators/validate.ts b/packages/babel-types/src/validators/validate.ts index 28bd5397dfb7..82bf11589414 100644 --- a/packages/babel-types/src/validators/validate.ts +++ b/packages/babel-types/src/validators/validate.ts @@ -1,4 +1,8 @@ -import { NODE_FIELDS, NODE_PARENT_VALIDATIONS } from "../definitions"; +import { + NODE_FIELDS, + NODE_PARENT_VALIDATIONS, + type FieldOptions, +} from "../definitions"; import type * as t from ".."; export default function validate( @@ -20,7 +24,7 @@ export function validateField( node: t.Node | undefined | null, key: string, val: any, - field: any, + field: FieldOptions | undefined | null, ): void { if (!field?.validate) return; if (field.optional && val == null) return; @@ -31,7 +35,7 @@ export function validateField( export function validateChild( node: t.Node | undefined | null, key: string, - val?: any, + val?: t.Node | undefined | null, ) { if (val == null) return; const validate = NODE_PARENT_VALIDATIONS[val.type]; From 32984187004df2325da6d6543e29ebdd3d41c08d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hu=C3=A1ng=20J=C3=B9nli=C3=A0ng?= Date: Mon, 6 Jun 2022 12:55:33 -0400 Subject: [PATCH 3/3] mark node comments as mutable --- packages/babel-types/scripts/generators/ast-types.js | 6 +++--- packages/babel-types/src/ast-types/generated/index.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/babel-types/scripts/generators/ast-types.js b/packages/babel-types/scripts/generators/ast-types.js index b0c14ff3410e..4990cd137f40 100644 --- a/packages/babel-types/scripts/generators/ast-types.js +++ b/packages/babel-types/scripts/generators/ast-types.js @@ -37,9 +37,9 @@ export interface SourceLocation { interface BaseNode { type: Node["type"]; - leadingComments?: ReadonlyArray | null; - innerComments?: ReadonlyArray | null; - trailingComments?: ReadonlyArray | null; + leadingComments?: Comment[] | null; + innerComments?: Comment[] | null; + trailingComments?: Comment[] | null; start?: number | null; end?: number | null; loc?: SourceLocation | null; diff --git a/packages/babel-types/src/ast-types/generated/index.ts b/packages/babel-types/src/ast-types/generated/index.ts index a230acd945ec..0ff9f14dded9 100644 --- a/packages/babel-types/src/ast-types/generated/index.ts +++ b/packages/babel-types/src/ast-types/generated/index.ts @@ -33,9 +33,9 @@ export interface SourceLocation { interface BaseNode { type: Node["type"]; - leadingComments?: ReadonlyArray | null; - innerComments?: ReadonlyArray | null; - trailingComments?: ReadonlyArray | null; + leadingComments?: Comment[] | null; + innerComments?: Comment[] | null; + trailingComments?: Comment[] | null; start?: number | null; end?: number | null; loc?: SourceLocation | null;