跳至主内容

@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.28.0Added discardBinding. Moved explicitResourceManagement to Latest ECMAScript features
v7.26.0Moved importAttributes to Latest ECMAScript features
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 (⚠️ deprecated 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; } }
discardBinding (proposal)using void = new Lock(mutex)
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 (⚠️ deprecated 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)
explicitResourceManagement (proposal)using reader = getReader()
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(必填,可选值:fsharphackminimalsmart(已废弃)) 管道操作符存在多种不同提案。此选项用于选择具体提案。 详见 plugin-proposal-pipeline-operator, 其中包含行为对比表格。
    • topicToken(当 proposalhack 时必填,可选值:%#^@@^^hack 提案在管道中使用 "topic" 占位符。此选项用于选择引用 topic 的标识符。

错误代码

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);
},
},
],
};