@babel/parser
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
The Babel parser (previously Babylon) is a JavaScript parser used in Babel.
-
默认启用最新 ECMAScript 版本 (ES2020)。
-
注释附加功能。
-
支持 JSX、Flow 和 TypeScript。
-
支持实验性语言提案(接受至少处于 stage-0 阶段的 PR)。
致谢
核心实现基于 acorn 和 acorn-jsx, 特别感谢 @RReverser 和 @marijnh 的卓越工作。
API
babelParser.parse(code, [options])
babelParser.parseExpression(code, [options])
parse() 将提供的 code 解析为完整的 ECMAScript 程序,而
parseExpression() 则专注于高效解析单个表达式。
如有疑问,请使用 .parse()。
选项
History
| Version | Changes |
|---|---|
v7.28.0 | Added sourceType: "commonjs" |
v7.27.0 | Added allowYieldOutsideFunction |
v7.26.0 | Added startIndex |
v7.23.0 | Added createImportExpressions |
v7.21.0 | Added allowNewTargetOutsideFunction and annexB |
v7.16.0 | Added startColumn |
v7.15.0 | Added attachComment |
v7.7.0 | Added errorRecovery |
v7.5.0 | Added allowUndeclaredExports |
v7.2.0 | Added createParenthesizedExpressions |
-
allowImportExportEverywhere:默认情况下,
import和export声明只能出现在程序顶层。将此选项设为true后, 允许在任意语句位置使用它们。 -
allowAwaitOutsideFunction:默认情况下,
await仅允许在异步函数内部使用, 或当启用topLevelAwait插件时在模块顶层作用域使用。设为true后, 可在脚本的顶层作用域使用。建议优先使用topLevelAwait插件替代此选项。 -
allowYieldOutsideFunction:默认情况下,
yield仅允许在生成器函数内部使用。 设为true后,可在顶层作用域使用。 -
allowNewTargetOutsideFunction:默认情况下,
new.target不允许在函数或类外部使用。 设为true后允许此类用法。 -
allowReturnOutsideFunction:默认情况下,顶层 return 语句会报错。 设为
true后允许此类代码。 -
allowSuperOutsideMethod:默认情况下,
super不允许在类和对象方法外部使用。 设为true后允许此类代码。 -
allowUndeclaredExports:默认情况下,导出当前模块作用域内未声明的标识符会报错。 虽然 ECMAScript 模块规范要求此行为,但 Babel 解析器无法预知后续插件可能插入的声明, 因此有时需设为
true来避免解析器过早报错(针对后续将添加的导出)。 -
attachComment:默认情况下,Babel 将注释附加到相邻的 AST 节点。设为
false时不附加注释。 当输入代码包含大量注释时,性能可提升高达 30%。@babel/eslint-parser会自动配置此选项。 不建议在 Babel 转换中使用attachComment: false,因为这会移除输出代码中的所有注释, 并使/* istanbul ignore next */等注解失效。 -
annexB:默认情况下,Babel 根据 ECMAScript 附录 B "Web 浏览器专属特性" 语法解析 JavaScript。设为
false后,Babel 将解析不含附录 B 专属扩展的语法。 -
createImportExpressions: 默认情况下,解析器将动态导入
import()解析为调用表达式节点。当此选项设为true时,将创建ImportExpressionAST 节点。此选项在 Babel 8 中将默认设为true。 -
createParenthesizedExpressions: 默认情况下,解析器会在表达式节点上设置
extra.parenthesized。当此选项设为true时,将创建ParenthesizedExpressionAST 节点。 -
errorRecovery: 默认情况下,Babel 在发现无效代码时会抛出错误。当此选项设为
true时,解析器将存储解析错误并尝试继续解析无效输入文件。生成的 AST 将包含errors属性,表示所有解析错误的数组。请注意,即使启用此选项,@babel/parser仍可能因不可恢复的错误而抛出异常。 -
plugins: 包含要启用的插件的数组。
-
sourceType: 指定代码的解析模式。可选值为
"script"、"commonjs"、"module"或"unambiguous"。默认为"script"。"unambiguous"模式会让 @babel/parser 根据是否存在 ES6import或export语句来推测解析模式:包含 ES6import/export的文件视为"module",否则视为"script"。"commonjs"模式表示代码应在 CommonJS 环境(如 Node.js)中运行。除允许在顶层使用return、new.target和using/await using声明外,基本兼容"script"模式。 -
sourceFilename: 将输出 AST 节点与其源文件名关联。当从多个输入文件的 AST 生成代码和源映射时特别有用。
-
startColumn: 默认解析位置为第 1 行第 0 列。可通过此选项指定起始列号。适用于与其他源码工具集成。
-
startLine: 默认解析位置为第 1 行第 0 列。可通过此选项指定起始行号。适用于与其他源码工具集成。
-
startIndex: 默认所有源码索引从 0 开始。此选项可指定替代起始索引。当
startLine大于 1 时必须提供此选项以保证 AST 源码索引准确性。适用于与其他源码工具集成。 -
strictMode: 默认仅在存在
"use strict";指令或解析文件为 ECMAScript 模块时以严格模式解析代码。将此选项设为true可始终以严格模式解析文件。 -
ranges: 为每个节点添加
range属性:[node.start, node.end] -
tokens: 将所有解析后的标记添加到
File节点的tokens属性中
输出
Babel 解析器根据 Babel AST 格式 生成 AST,其在 ESTree 规范 基础上存在以下差异:
-
[Literal][] 标记替换为 [StringLiteral][]、[NumericLiteral][]、[BigIntLiteral][]、[BooleanLiteral][]、[NullLiteral][]、[RegExpLiteral][]
-
[Property][] 标记替换为 [ObjectProperty][] 和 [ObjectMethod][]
-
[MethodDefinition][] 替换为 [ClassMethod][] 和 [ClassPrivateMethod][]
-
[PropertyDefinition][] 替换为 [ClassProperty][] 和 [ClassPrivateProperty][]
-
[PrivateIdentifier][] 替换为 [PrivateName][]
-
Program 和 BlockStatement 包含额外的
directives字段,内含 Directive 和 DirectiveLiteral -
[ClassMethod][]、[ClassPrivateMethod][]、[ObjectProperty][] 和 [ObjectMethod][] 的 value 属性(属于 FunctionExpression 类型)会被强制提升/合并到主方法节点中。
-
[ChainExpression][] 被替换为 OptionalMemberExpression 和 OptionalCallExpression
-
[ImportExpression][] 被替换为 CallExpression,其
callee是一个 Import 节点。此变更将在 Babel 8 中还原。 -
带有
exported字段的 [ExportAllDeclaration][] 被替换为包含 ExportNamespaceSpecifier 节点的 ExportNamedDeclaration。
estree 插件可以还原这些差异。仅当您需要将 Babel AST 传递给其他符合 ESTree 标准的工具时才使用它。
JSX 代码的 AST 基于 Facebook JSX AST 实现。
语义化版本
Babel 解析器在大多数情况下遵循语义化版本规范。需要注意的一点是,某些符合规范要求的错误修复可能会在补丁版本中发布。
例如:我们修复了类似 #107 的早期错误 - 单个文件存在多个默认导出。这将被视为错误修复,即使它会导致构建失败。
示例
require("@babel/parser").parse("code", {
// parse in strict mode and allow module declarations
sourceType: "module",
plugins: [
// enable jsx and flow syntax
"jsx",
"flow",
],
});
插件
杂项
| Name | Code Example |
|---|---|
estree (repo) | n/a |
语言扩展
History
| Version | Changes |
|---|---|
v7.6.0 | Added v8intrinsic |
| Name | Code Example |
|---|---|
flow (repo) | var a: string = ""; |
flowComments (docs) | /*:: type Foo = {...}; */ |
jsx (repo) | <a attr="b">{s}</a> |
typescript (repo) | var a: string = ""; |
v8intrinsic | %DebugPrint(foo); |
ECMAScript 提案
History
| Version | Changes |
|---|---|
v7.23.0 | Added sourcePhaseImports, deferredImportEvaluation, optionalChainingAssign |
v7.22.0 | Enabled regexpUnicodeSets by default, added importAttributes |
v7.20.0 | Added explicitResourceManagement, importReflection |
v7.17.0 | Added regexpUnicodeSets, destructuringPrivate, decoratorAutoAccessors |
v7.15.0 | Added hack to the proposal option of pipelineOperator. Moved topLevelAwait, privateIn to Latest ECMAScript features |
v7.14.0 | Added asyncDoExpressions. Moved classProperties, classPrivateProperties, classPrivateMethods, moduleStringNames to Latest ECMAScript features |
v7.13.0 | Added moduleBlocks |
v7.12.0 | Added classStaticBlock, moduleStringNames |
v7.11.0 | Added decimal |
v7.10.0 | Added privateIn |
v7.9.0 | Added recordAndTuple |
v7.7.0 | Added topLevelAwait |
v7.4.0 | Added partialApplication |
v7.2.0 | Added classPrivateMethods |
| Name | Code Example |
|---|---|
asyncDoExpressions (proposal) | async do { await requestAPI().json() } |
decimal (proposal) | 0.3m |
decorators (proposal) decorators-legacy | @a class A {} |
decoratorAutoAccessors (proposal) | class Example { @reactive accessor myBool = false; } |
deferredImportEvaluation (proposal) | import defer * as ns from "dep"; |
deprecatedImportAssert (⚠️ deprecated, legacy syntax of import attributes) importAssertions (⚠️ deprecated) | import json from "./foo.json" assert { type: "json" }; |
destructuringPrivate (proposal) | class Example { #x = 1; method() { const { #x: x } = this; } } |
doExpressions (proposal) | var a = do { if (true) { 'hi'; } }; |
explicitResourceManagement (proposal) | using reader = getReader() |
exportDefaultFrom (proposal) | export v from "mod" |
functionBind (proposal) | a::b, ::console.log |
functionSent (proposal) | function.sent |
importReflection (proposal) | import module foo from "./foo.wasm"; |
moduleBlocks (proposal) | let m = module { export let y = 1; }; |
optionalChainingAssign (proposal) | x?.prop = 2 |
partialApplication (proposal) | f(?, a) |
pipelineOperator (proposal) | a |> b |
recordAndTuple (proposal) | #{x: 1}, #[1, 2] |
sourcePhaseImports (proposal) | import source x from "./x" |
throwExpressions (proposal) | () => throw new Error("") |
Latest ECMAScript features
The following features are already enabled on the latest version of @babel/parser, and cannot be disabled because they are part of the language.
You should enable these features only if you are using an older version.
| Name | Code Example |
|---|---|
asyncGenerators (proposal) | async function*() {}, for await (let a of b) {} |
bigInt (proposal) | 100n |
classProperties (proposal) | class A { b = 1; } |
classPrivateProperties (proposal) | class A { #b = 1; } |
classPrivateMethods (proposal) | class A { #c() {} } |
classStaticBlock (proposal) | class A { static {} } |
dynamicImport (proposal) | import('./guy').then(a) |
exportNamespaceFrom (proposal) | export * as ns from "mod" |
logicalAssignment (proposal) | a &&= b |
moduleStringNames (proposal) | import { "😄" as smile } from "emoji"; |
nullishCoalescingOperator (proposal) | a ?? b |
numericSeparator (proposal) | 1_000_000 |
objectRestSpread (proposal) | var a = { b, ...c }; |
optionalCatchBinding (proposal) | try {throw 0;} catch{do();} |
optionalChaining (proposal) | a?.b |
privateIn (proposal) | #p in obj |
regexpUnicodeSets (proposal) | /[\p{Decimal_Number}--[0-9]]/v; |
topLevelAwait (proposal) | await promise in modules |
importAttributes (proposal) | import json from "./foo.json" with { type: "json" }; |
插件选项
History
| Version | Changes |
|---|---|
7.21.0 | The default behavior of the decorators' decoratorsBeforeExport option is to allow decorators either before or after the export keyword. |
7.19.0 | The syntaxType option of the recordAndTuple plugin defaults to hash; added allowCallParenthesized option for the decorators plugin. |
7.17.0 | Added @@ and ^^ to the topicToken option of the hack pipeline operator |
7.16.0 | Added disallowAmbiguousJSXLike for typescript plugin. Added ^ to the topicToken option of the hack pipeline operators |
7.14.0 | Added dts for typescript plugin |
当同一个插件被多次指定时,只有首次出现的选项配置会生效
-
decorators:-
allowCallParenthesized(boolean,默认值:true)设为
false时,禁止使用@(...)()形式的装饰器语法,强制使用@(...())格式。stage 3 装饰器提案要求使用allowCallParenthesized: false -
decoratorsBeforeExport(boolean)默认情况下,导出类上的装饰器可置于
export关键字之前或之后。设置此选项后,装饰器将仅允许出现在指定位置JavaScript// decoratorsBeforeExport: true
@dec
export class C {}
// decoratorsBeforeExport: false
export @dec class C {}注意此选项已弃用,将在未来版本中移除。无论是否显式设置此选项(设为
true或false),相关代码的有效性均保持一致
-
-
optionalChainingAssign:version(必填,可选值:2023-07) 该提案仍处于 Stage 1 阶段,因此可能发生破坏性变更。 必须指定使用的提案版本,以确保 Babel 能持续以兼容方式解析代码。
-
pipelineOperator:proposal(必填,可选值:fsharp,hack,,minimal(已弃用)) 管道运算符有多个不同的提案。 此选项用于选择要使用的提案。 更多信息请参见 plugin-proposal-pipeline-operator, 其中包括比较它们行为的表格。smart
topicToken(当proposal为hack时必填,可选值:%,#,^,@@,^^)hack提案在其管道中使用“话题”占位符。 此话题占位符有两种不同的选择。 此选项用于选择引用话题的标记。
recordAndTuple(记录与元组):syntaxType(hash或bar,默认为hash):recordAndTuple有两种语法变体,它们具有完全相同的运行时语义。语法类型 Record 示例 Tuple 示例 "hash"#{ a: 1 }#[1, 2]"bar"{| a: 1 |}[|1, 2|]更多信息请参考 #{}/#[]的人体工程学讨论。
-
flow:all(boolean,默认:false) 部分代码在 Flow 和原生 JavaScript 中有不同含义。例如foo<T>(x)在 Flow 中会被解析为带类型参数的调用表达式,而在 ECMAScript 规范中则被视作比较表达式(foo < T > x)。默认情况下,仅当文件以// @flow指令开头时,babel-parser才会将这些歧义结构解析为 Flow 类型。 将此选项设为true将始终按// @flow已指定的方式解析文件。
-
typescriptdts(boolean, 默认false) 此选项将启用 TypeScript 环境上下文解析,其中特定语法具有不同规则(如.d.ts文件和declare module块内)。环境上下文详见 https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html 和 https://basarat.gitbook.io/typescript/type-system/intro。disallowAmbiguousJSXLike(boolean, 默认false) 即使未启用jsx插件,此选项也禁止使用可能与 JSX 产生歧义的语法(如<X> y类型断言和<X>() => {}类型参数)。该行为与解析.mts和.mjs文件时的tsc行为一致。
-
importAttributes:-
deprecatedAssertSyntax(boolean,默认false)设为
true时允许解析旧版导入属性语法(使用assert关键字而非with)。此语法与早期
importAssertions解析器插件支持的语法一致。
-
错误代码
History
| Version | Changes |
|---|---|
v7.14.0 | Added error codes |
错误代码对于处理 @babel/parser 抛出的异常非常实用。
存在两种错误代码:code 和 reasonCode。
-
code- 错误的大致分类(例如
BABEL_PARSER_SYNTAX_ERROR、BABEL_PARSER_SOURCETYPE_MODULE_REQUIRED)。
- 错误的大致分类(例如
-
reasonCode- 错误的详细分类(例如
MissingSemicolon、VarRedeclaration)。
- 错误的详细分类(例如
以下是在启用 errorRecovery 时使用错误代码的示例:
const { parse } = require("@babel/parser");
const ast = parse(`a b`, { errorRecovery: true });
console.log(ast.errors[0].code); // BABEL_PARSER_SYNTAX_ERROR
console.log(ast.errors[0].reasonCode); // MissingSemicolon
常见问题解答
Babel 解析器会支持插件系统吗?
我们目前不打算承诺支持插件 API 及其衍生生态系统(维护 Babel 自身的插件系统已足够繁重)。该 API 的有效性尚不明确,且会限制我们重构和优化代码库的能力。
对于需要创建自定义语法的用户,我们当前的推荐方案是直接分叉(fork)解析器代码。
要使用自定义解析器,您可以在配置选项中添加插件,通过 npm 包名调用解析器(使用 JavaScript 时也可直接 require)。
const parse = require("custom-fork-of-babel-parser-on-npm-here");
module.exports = {
plugins: [
{
parserOverride(code, opts) {
return parse(code, opts);
},
},
],
};