/
githubmirror
/
babel
Обзор
Документация
Войти
/
githubmirror
/
babel
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
packages/babel-plugin-transform-destructuring/src/index.ts
187 строк
6 KB
liuxingbaoyu
Deprecate `spec` and `loose` plugin options (#17972)
12 май 2026, 12:38
Не верифицирован
12 май 2026, 12:38
7a3142c
Код
Авторство
О чём код?
import { declare } from "@babel/helper-plugin-utils"; import { types as t, type NodePath } from "@babel/core"; import { DestructuringTransformer, convertVariableDeclaration, convertAssignmentExpression, unshiftForXStatementBody, type DestructuringTransformerNode, type VariableDeclarationKindAllowsPattern, } from "./util.ts"; export { buildObjectExcludingKeys, unshiftForXStatementBody } from "./util.ts"; /** * Test if a VariableDeclaration's declarations contains any destructuring patterns. * @param node VariableDeclaration node to test */ function variableDeclarationHasDestructuringPattern( node: t.VariableDeclaration, ) { for (const declar of node.declarations) { if (t.isPattern(declar.id) && declar.id.type !== "VoidPattern") { return true; } } return false; } export interface Options { allowArrayLike?: boolean; /** @deprecated Use the `iterableIsArray` and `objectRestNoSymbols` assumptions instead. */ loose?: boolean; useBuiltIns?: boolean; } export default declare((api, options: Options) => { api.assertVersion(REQUIRED_VERSION("^7.0.0-0 || ^8.0.0")); if ("loose" in options) { console.warn( "@babel/plugin-transform-destructuring: The 'loose' option has been deprecated, " + "use the `iterableIsArray` and `objectRestNoSymbols` assumptions instead (https://babeljs.io/assumptions).", ); } const { useBuiltIns = false } = options; const iterableIsArray = api.assumption("iterableIsArray") ?? options.loose ?? false; const arrayLikeIsIterable = options.allowArrayLike ?? api.assumption("arrayLikeIsIterable") ?? false; const objectRestNoSymbols = api.assumption("objectRestNoSymbols") ?? options.loose ?? false; return { name: "transform-destructuring", visitor: { ExportNamedDeclaration(path) { const declaration = path.get("declaration"); if (!declaration.isVariableDeclaration()) return; if (!variableDeclarationHasDestructuringPattern(declaration.node)) return; // Split the declaration and export list into two declarations so that the variable // declaration can be split up later without needing to worry about not being a // top-level statement. path.splitExportDeclaration(); }, ForXStatement(path: NodePath<t.ForXStatement>) { const { node, scope } = path; const left = node.left; if (t.isPattern(left)) { // for ({ length: k } in { abc: 3 }); const temp = scope.generateUidIdentifier("ref"); node.left = t.variableDeclaration("var", [ t.variableDeclarator(temp), ]); path.ensureBlock(); const statementBody = (path.node.body as t.BlockStatement).body; const nodes = []; // todo: the completion of a for statement can only be observed from // a do block (or eval that we don't support), // but the new do-expression proposal plans to ban iteration ends in the // do block, maybe we can get rid of this if (statementBody.length === 0 && path.isCompletionRecord()) { nodes.unshift(t.expressionStatement(t.buildUndefinedNode())); } nodes.unshift( t.expressionStatement( t.assignmentExpression("=", left, t.cloneNode(temp)), ), ); unshiftForXStatementBody(path, nodes); scope.crawl(); return; } if (!t.isVariableDeclaration(left)) return; const pattern = left.declarations[0].id; if (!t.isPattern(pattern) || pattern.type === "VoidPattern") return; const key = scope.generateUidIdentifier("ref"); node.left = t.variableDeclaration(left.kind, [ t.variableDeclarator(key, null), ]); const nodes: DestructuringTransformerNode[] = []; const destructuring = new DestructuringTransformer({ kind: left.kind as VariableDeclarationKindAllowsPattern, scope: scope, nodes: nodes, arrayLikeIsIterable, iterableIsArray, objectRestNoSymbols, useBuiltIns, addHelper: name => this.addHelper(name), }); destructuring.init(pattern, key); unshiftForXStatementBody(path, nodes); scope.crawl(); }, CatchClause({ node, scope }) { const pattern = node.param; if (!t.isPattern(pattern)) return; const ref = scope.generateUidIdentifier("ref"); node.param = ref; const nodes: DestructuringTransformerNode[] = []; const destructuring = new DestructuringTransformer({ kind: "let", scope: scope, nodes: nodes, arrayLikeIsIterable, iterableIsArray, objectRestNoSymbols, useBuiltIns, addHelper: name => this.addHelper(name), }); destructuring.init(pattern, ref); node.body.body = [...nodes, ...node.body.body]; scope.crawl(); }, AssignmentExpression(path, state) { if (!t.isPattern(path.node.left)) return; convertAssignmentExpression( path as NodePath<t.AssignmentExpression & { left: t.Pattern }>, name => state.addHelper(name), arrayLikeIsIterable, iterableIsArray, objectRestNoSymbols, useBuiltIns, ); }, VariableDeclaration(path, state) { const { node, parent } = path; if (t.isForXStatement(parent)) return; if (!parent || !path.container) return; // i don't know why this is necessary - TODO if (!variableDeclarationHasDestructuringPattern(node)) return; convertVariableDeclaration( path, name => state.addHelper(name), arrayLikeIsIterable, iterableIsArray, objectRestNoSymbols, useBuiltIns, ); }, }, }; });