跳至主内容

@babel/parser

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

The Babel parser (previously Babylon) is a JavaScript parser used in Babel.

  • 默认启用最新 ECMAScript 版本 (ES2020)。

  • 注释附加功能。

  • 支持 JSX、Flow 和 TypeScript。

  • 支持实验性语言提案(接受至少处于 stage-0 阶段的 PR)。

致谢

核心实现基于 acornacorn-jsx, 特别感谢 @RReverser@marijnh 的卓越工作。

API

babelParser.parse(code, [options])

babelParser.parseExpression(code, [options])

parse() 将提供的 code 解析为完整的 ECMAScript 程序,而 parseExpression() 则专注于高效解析单个表达式。 如有疑问,请使用 .parse()

选项

History
VersionChanges
v7.28.0Added sourceType: "commonjs"
v7.27.0Added allowYieldOutsideFunction
v7.26.0Added startIndex
v7.23.0Added createImportExpressions
v7.21.0Added allowNewTargetOutsideFunction and annexB
v7.16.0Added startColumn
v7.15.0Added attachComment
v7.7.0Added errorRecovery
v7.5.0Added allowUndeclaredExports
v7.2.0Added createParenthesizedExpressions
  • allowImportExportEverywhere:默认情况下,importexport 声明只能出现在程序顶层。将此选项设为 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 时,将创建 ImportExpression AST 节点。此选项在 Babel 8 中将默认设为 true

  • createParenthesizedExpressions: 默认情况下,解析器会在表达式节点上设置 extra.parenthesized。当此选项设为 true 时,将创建 ParenthesizedExpression AST 节点。

  • errorRecovery: 默认情况下,Babel 在发现无效代码时会抛出错误。当此选项设为 true 时,解析器将存储解析错误并尝试继续解析无效输入文件。生成的 AST 将包含 errors 属性,表示所有解析错误的数组。请注意,即使启用此选项,@babel/parser 仍可能因不可恢复的错误而抛出异常。

  • plugins: 包含要启用的插件的数组。

  • sourceType: 指定代码的解析模式。可选值为 "script""commonjs""module""unambiguous"。默认为 "script""unambiguous" 模式会让 @babel/parser 根据是否存在 ES6 importexport 语句来推测解析模式:包含 ES6 import/export 的文件视为 "module",否则视为 "script"

    "commonjs" 模式表示代码应在 CommonJS 环境(如 Node.js)中运行。除允许在顶层使用 returnnew.targetusing/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][]

  • ProgramBlockStatement 包含额外的 directives 字段,内含 DirectiveDirectiveLiteral

  • [ClassMethod][]、[ClassPrivateMethod][]、[ObjectProperty][] 和 [ObjectMethod][] 的 value 属性(属于 FunctionExpression 类型)会被强制提升/合并到主方法节点中。

  • [ChainExpression][] 被替换为 OptionalMemberExpressionOptionalCallExpression

  • [ImportExpression][] 被替换为 CallExpression,其 callee 是一个 Import 节点。此变更将在 Babel 8 中还原。

  • 带有 exported 字段的 [ExportAllDeclaration][] 被替换为包含 ExportNamespaceSpecifier 节点的 ExportNamedDeclaration

备注

estree 插件可以还原这些差异。仅当您需要将 Babel AST 传递给其他符合 ESTree 标准的工具时才使用它。

JSX 代码的 AST 基于 Facebook JSX AST 实现。

语义化版本

Babel 解析器在大多数情况下遵循语义化版本规范。需要注意的一点是,某些符合规范要求的错误修复可能会在补丁版本中发布。

例如:我们修复了类似 #107 的早期错误 - 单个文件存在多个默认导出。这将被视为错误修复,即使它会导致构建失败。

示例

JavaScript
require("@babel/parser").parse("code", {
// parse in strict mode and allow module declarations
sourceType: "module",

plugins: [
// enable jsx and flow syntax
"jsx",
"flow",
],
});

插件

杂项

NameCode Example
estree (repo)n/a

语言扩展

History
VersionChanges
v7.6.0Added v8intrinsic
NameCode 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
VersionChanges
v7.23.0Added sourcePhaseImports, deferredImportEvaluation, optionalChainingAssign
v7.22.0Enabled regexpUnicodeSets by default, added importAttributes
v7.20.0Added explicitResourceManagement, importReflection
v7.17.0Added regexpUnicodeSets, destructuringPrivate, decoratorAutoAccessors
v7.15.0Added hack to the proposal option of pipelineOperator. Moved topLevelAwait, privateIn to Latest ECMAScript features
v7.14.0Added asyncDoExpressions. Moved classProperties, classPrivateProperties, classPrivateMethods, moduleStringNames to Latest ECMAScript features
v7.13.0Added moduleBlocks
v7.12.0Added classStaticBlock, moduleStringNames
v7.11.0Added decimal
v7.10.0Added privateIn
v7.9.0Added recordAndTuple
v7.7.0Added topLevelAwait
v7.4.0Added partialApplication
v7.2.0Added classPrivateMethods
NameCode 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.

NameCode 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
VersionChanges
7.21.0The default behavior of the decorators' decoratorsBeforeExport option is to allow decorators either before or after the export keyword.
7.19.0The syntaxType option of the recordAndTuple plugin defaults to hash; added allowCallParenthesized option for the decorators plugin.
7.17.0Added @@ and ^^ to the topicToken option of the hack pipeline operator
7.16.0Added disallowAmbiguousJSXLike for typescript plugin. Added ^ to the topicToken option of the hack pipeline operators
7.14.0Added 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 {}
      注意

      此选项已弃用,将在未来版本中移除。无论是否显式设置此选项(设为 truefalse),相关代码的有效性均保持一致

  • optionalChainingAssign:

    • version(必填,可选值:2023-07) 该提案仍处于 Stage 1 阶段,因此可能发生破坏性变更。 必须指定使用的提案版本,以确保 Babel 能持续以兼容方式解析代码。
  • pipelineOperator:

    • proposal(必填,可选值:fsharp, hack, minimal, smart(已弃用)) 管道运算符有多个不同的提案。 此选项用于选择要使用的提案。 更多信息请参见 plugin-proposal-pipeline-operator, 其中包括比较它们行为的表格。
    • topicToken(当 proposalhack 时必填,可选值:%, #, ^, @@, ^^hack 提案在其管道中使用“话题”占位符。 此话题占位符有两种不同的选择。 此选项用于选择引用话题的标记。
  • recordAndTuple(记录与元组):
    • syntaxTypehashbar,默认为 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 已指定的方式解析文件。
  • typescript

  • importAttributes:

    • deprecatedAssertSyntaxboolean,默认 false

      设为 true 时允许解析旧版导入属性语法(使用 assert 关键字而非 with)。

      此语法与早期 importAssertions 解析器插件支持的语法一致。

错误代码

History
VersionChanges
v7.14.0Added error codes

错误代码对于处理 @babel/parser 抛出的异常非常实用。

存在两种错误代码:codereasonCode

  • code

    • 错误的大致分类(例如 BABEL_PARSER_SYNTAX_ERRORBABEL_PARSER_SOURCETYPE_MODULE_REQUIRED)。
  • reasonCode

    • 错误的详细分类(例如 MissingSemicolonVarRedeclaration)。

以下是在启用 errorRecovery 时使用错误代码的示例:

JavaScript
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 解析器会支持插件系统吗?

历史相关讨论:#1351#6694

我们目前不打算承诺支持插件 API 及其衍生生态系统(维护 Babel 自身的插件系统已足够繁重)。该 API 的有效性尚不明确,且会限制我们重构和优化代码库的能力。

对于需要创建自定义语法的用户,我们当前的推荐方案是直接分叉(fork)解析器代码。

要使用自定义解析器,您可以在配置选项中添加插件,通过 npm 包名调用解析器(使用 JavaScript 时也可直接 require)。

JavaScript
const parse = require("custom-fork-of-babel-parser-on-npm-here");

module.exports = {
plugins: [
{
parserOverride(code, opts) {
return parse(code, opts);
},
},
],
};