跳至主要内容

@babel/parser

Babel 解析器(以前称为 Babylon)是 Babel 中使用的 JavaScript 解析器。

  • 默认情况下启用的最新 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()

选项

历史记录
版本更改
v7.23.0添加了 createImportExpressions
v7.21.0添加了 allowNewTargetOutsideFunctionannexb
v7.16.0添加了 startColumn
v7.15.0添加了 attachComment
v7.7.0添加了 errorRecovery
v7.5.0添加了 allowUndeclaredExports
v7.2.0添加了 createParenthesizedExpressions
  • allowImportExportEverywhere:默认情况下,importexport 声明只能出现在程序的顶层。将此选项设置为 true 允许它们出现在允许使用语句的任何位置。

  • allowAwaitOutsideFunction:默认情况下,仅允许在异步函数内部使用 await,或者在启用了 topLevelAwait 插件的情况下,在模块的顶层作用域中使用。将其设置为 true 也可以在脚本的顶层作用域中接受它。不建议使用此选项,而建议使用 topLevelAwait 插件。

  • allowNewTargetOutsideFunction:默认情况下,不允许在函数或类之外使用 new.target。将其设置为 true 以接受此类代码。

  • allowReturnOutsideFunction:默认情况下,顶层的 return 语句会引发错误。将其设置为 true 以接受此类代码。

  • allowSuperOutsideMethod:默认情况下,不允许在类和对象方法之外使用 super。将其设置为 true 以接受此类代码。

  • allowUndeclaredExports:默认情况下,导出当前模块作用域中未声明的标识符将引发错误。虽然 ECMAScript 模块规范要求这种行为,但 Babel 的解析器无法预料插件管道中稍后可能会插入适当声明的转换,因此有时将此选项设置为 true 以防止解析器过早地抱怨稍后将添加的未声明导出非常重要。

  • attachComment:默认情况下,Babel 将注释附加到相邻的 AST 节点。当此选项设置为 false 时,不会附加注释。当输入代码有*很多*注释时,它可以提供高达 30% 的性能提升。@babel/eslint-parser 将为您设置它。不建议将 attachComment: false 与 Babel 转换一起使用,因为这样做会删除输出代码中的所有注释,并使 /* istanbul ignore next */ 等注释失效。

  • annexb:默认情况下,Babel 根据 ECMAScript 的附件 B“*Web 浏览器附加的 ECMAScript 功能*” 语法解析 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""module""unambiguous" 之一。默认为 "script""unambiguous" 将使 @babel/parser 尝试根据是否存在 ES6 importexport 语句来*猜测*。包含 ES6 importexport 的文件被视为 "module",否则为 "script"

  • sourceFilename:将输出 AST 节点与其源文件名相关联。在从多个输入文件的 AST 生成代码和源映射时很有用。

  • startColumn:默认情况下,解析后的代码将被视为从第 1 行第 0 列开始。您可以提供一个列号来选择性地开始。与其他源代码工具集成时很有用。

  • startLine:默认情况下,解析后的代码将被视为从第 1 行第 0 列开始。您可以提供一个行号来选择性地开始。与其他源代码工具集成时很有用。

  • strictMode:默认情况下,仅当存在 "use strict"; 指令或解析后的文件是 ECMAScript 模块时,ECMAScript 代码才会被解析为严格模式。将此选项设置为 true 以始终在严格模式下解析文件。

  • ranges:为每个节点添加一个 range 属性:[node.start, node.end]

  • tokens:将所有解析后的标记添加到 File 节点上的 tokens 属性中

输出

Babel 解析器根据 Babel AST 格式 生成 AST。它基于 ESTree 规范,并具有以下偏差

提示

现在有一个 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",
],
});

插件

杂项

名称代码示例
estree (仓库)不适用

语言扩展

历史记录
版本更改
v7.6.0添加了 v8intrinsic
名称代码示例
flow (仓库)var a: string = "";
flowComments (文档)/*:: type Foo = {...}; */
jsx (仓库)<a attr="b">{s}</a>
typescript (仓库)var a: string = "";
v8intrinsic%DebugPrint(foo);

ECMAScript 提案

历史记录
版本更改
v7.23.0添加了 sourcePhaseImportsdeferredImportEvaluationoptionalChainingAssign
v7.22.0默认启用 regexpUnicodeSets,添加了 importAttributes
v7.20.0添加了 explicitResourceManagementimportReflection
v7.17.0添加了 regexpUnicodeSetsdestructuringPrivatedecoratorAutoAccessors
v7.15.0pipelineOperatorproposal 选项中添加了 hack。将 topLevelAwaitprivateIn 移至最新的 ECMAScript 功能
v7.14.0添加了 asyncDoExpressions。将 classPropertiesclassPrivatePropertiesclassPrivateMethodsmoduleStringNames 移至最新的 ECMAScript 功能
v7.13.0添加了 moduleBlocks
v7.12.0添加了 classStaticBlockmoduleStringNames
v7.11.0添加了 decimal
v7.10.0添加了 privateIn
v7.9.0添加了 recordAndTuple
v7.7.0添加了 topLevelAwait
v7.4.0添加了 partialApplication
v7.2.0添加了 classPrivateMethods
名称代码示例
asyncDoExpressions (提案)async do { await requestAPI().json() }
decimal (提案)0.3m
decorators (提案)
decorators-legacy
@a class A {}
decoratorAutoAccessors (提案)class Example { @reactive accessor myBool = false; }
deferredImportEvaluation (提案)import defer * as ns from "dep";
destructuringPrivate (提案)class Example { #x = 1; method() { const { #x: x } = this; } }
doExpressions (提案)var a = do { if (true) { 'hi'; } };
explicitResourceManagement (提案)using reader = getReader()
exportDefaultFrom (提案)export v from "mod"
functionBind (提案)a::b, ::console.log
functionSent (提案)function.sent
importAttributes (提案)
importAssertions (⚠️ 已弃用)
import json from "./foo.json" with { type: "json" };
importReflection (提案)import module foo from "./foo.wasm";
moduleBlocks (提案)let m = module { export let y = 1; };
optionalChainingAssign (提案)x?.prop = 2
partialApplication (提案)f(?, a)
pipelineOperator (提案)a |> b
recordAndTuple (提案)#{x: 1}, #[1, 2]
sourcePhaseImports (提案)import source x from "./x"
throwExpressions (提案)() => throw new Error("")

最新的 ECMAScript 功能

以下功能已在最新版本的 @babel/parser 中启用,并且无法禁用,因为它们是语言的一部分。仅当您使用的是旧版本时,才应启用这些功能。

名称代码示例
asyncGenerators (提案)async function*() {}, for await (let a of b) {}
bigInt (提案)100n
classProperties (提案)class A { b = 1; }
classPrivateProperties (提案)class A { #b = 1; }
classPrivateMethods (提案)class A { #c() {} }
classStaticBlock (提案)class A { static {} }
dynamicImport (提案)import('./guy').then(a)
exportNamespaceFrom (提案)export * as ns from "mod"
logicalAssignment (提案)a &&= b
moduleStringNames (提案)import { "😄" as smile } from "emoji";
nullishCoalescingOperator (提案)a ?? b
numericSeparator (提案)1_000_000
objectRestSpread (提案)var a = { b, ...c };
optionalCatchBinding (提案)try {throw 0;} catch{do();}
optionalChaining (提案)a?.b
privateIn (提案)#p in obj
regexpUnicodeSets (提案)/[\p{Decimal_Number}--[0-9]]/v;
topLevelAwait (提案)模块中的 await promise

插件选项

历史记录
版本更改
7.21.0decoratorsdecoratorsBeforeExport 选项的默认行为是允许在 export 关键字之前或之后使用装饰器。
7.19.0recordAndTuple 插件的 syntaxType 选项默认为 hash;为 decorators 插件添加了 allowCallParenthesized 选项。
7.17.0hack 管道运算符的 topicToken 选项中添加了 @@^^
7.16.0typescript 插件添加了 disallowAmbiguousJSXLike。在 hack 管道运算符的 topicToken 选项中添加了 ^
7.14.0typescript 插件添加了 dts
注意

当多次指定一个插件时,只考虑第一个选项。

  • importAttributes:

    • deprecatedAssertSyntax (boolean, 默认为 false)

      当为 true 时,允许使用 已弃用assert 关键字解析导入属性。这与 importAssertions 解析器插件最初支持的语法相匹配。

  • decorators:

    • allowCallParenthesized (boolean, 默认为 true)

      当为 false 时,不允许使用 @(...)() 形式的装饰器,而应使用 @(...())。第 3 阶段装饰器提案使用 allowCallParenthesized: false

    • decoratorsBeforeExport (boolean)

      默认情况下,导出类上的装饰器可以放在 export 关键字之前或之后。设置此选项后,将只允许在指定位置使用装饰器。

      JavaScript
      // decoratorsBeforeExport: true
      @dec
      export class C {}

      // decoratorsBeforeExport: false
      export @dec class C {}
      注意

此选项已弃用,将在未来版本中删除。当此选项显式设置为 truefalse 时有效的代码,在此选项未设置时也有效。::

  • optionalChainingAssign:

    • version (必填,可接受的值:2023-07) 此提案仍处于第 1 阶段,因此很可能会受到重大更改的影响。您必须指定您正在使用的提案版本,以确保 Babel 将继续以兼容的方式解析您的代码。
  • pipelineOperator:

    • proposal (必填,可接受的值:minimalfsharphacksmart (已弃用)) 管道运算符有几种不同的提案。此选项选择使用哪个提案。有关更多信息,包括比较其行为的表格,请参阅 plugin-proposal-pipeline-operator

    • topicToken (当 proposalhack 时必填,可接受的值:%#^@@^^) hack 提案在其管道中使用“主题”占位符。此主题占位符有两种不同的选择。此选项选择使用哪个标记来引用主题。topicToken: "#"syntaxType: "hash"recordAndTuple 不兼容。有关更多信息,请参阅 plugin-proposal-pipeline-operator

  • recordAndTuple:

    • syntaxTypehashbar,默认为 hashrecordAndTuple 有两种语法变体。它们共享完全相同的运行时语义。
      语法类型记录示例元组示例
      “hash”#{ a: 1 }#[1, 2]
      “bar”{| a: 1 |}[|1, 2|]
      有关更多信息,请参阅#{}/#[] 的人体工程学
  • flow:

    • allboolean,默认值:false)某些代码在 Flow 和普通 JavaScript 中具有不同的含义。例如,foo<T>(x) 在 Flow 中被解析为带有类型参数的调用表达式,但在 ECMAScript 规范中被解析为比较(foo < T > x)。默认情况下,仅当文件以 // @flow 编译指示开头时,babel-parser 才会将这些不明确的结构解析为 Flow 类型。将此选项设置为 true 以始终将文件解析为好像指定了 // @flow
  • typescript

错误代码

历史记录
版本更改
v7.14.0添加的错误代码

错误代码对于处理 @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);
},
},
],
};