@babel/parser
Babel解析器(以前叫Babylon)是一个用于 Babel的JavaScript解析器。
- 默认启用最新的 ECMAScript 版本(ES2020)。
- 注释附件。
- 支持 JSX、Flow 和 TypeScript。
- 支持实验性语言提案(接受任何至少达到 stage-0 的 PR)。
致谢
🌐 Credits
严重依赖于 acorn 和 acorn-jsx,感谢 @RReverser 和 @marijnh 的出色工作。
🌐 Heavily based on acorn and acorn-jsx, thanks to the awesome work of @RReverser and @marijnh.
应用接口
🌐 API
babelParser.parse(code, [options])
babelParser.parseExpression(code, [options])
parse() 会把提供的 code 解析为整个 ECMAScript 程序,而 parseExpression() 则尝试解析单个表达式,注重性能。有疑问的话,就用 .parse()。
选项
🌐 Options
历史
| 版本 | 变更 |
|---|---|
v8.0.0 | 添加了 locations |
v7.28.0 | 添加了 sourceType: "commonjs" |
v7.27.0 | 添加了 allowYieldOutsideFunction |
v7.26.0 | 添加了 startIndex |
v7.23.0 | 添加了 createImportExpressions |
v7.21.0 | 添加了 allowNewTargetOutsideFunction 和 annexB |
v7.16.0 | 添加了 startColumn |
v7.15.0 | 添加了 attachComment |
v7.7.0 | 添加了 errorRecovery |
v7.5.0 | 添加了 allowUndeclaredExports |
v7.2.0 | 添加了 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 */这样的注解失效。 -
附录B:默认情况下,Babel 会根据 ECMAScript 的附录 B “面向浏览器的额外 ECMAScript 特性” 语法解析 JavaScript。当该选项设置为
false时,Babel 将解析不带附录 B 特定扩展的语法。 -
createImportExpressions:默认情况下,解析器会将动态导入
import()解析为调用表达式节点。当此选项设置为true时,会改为创建ImportExpressionAST 节点。此选项在 Babel 8 中默认将设为true。 -
createParenthesizedExpressions:默认情况下,解析器会在表达式节点上设置
extra.parenthesized。当此选项设置为true时,则会创建ParenthesizedExpressionAST 节点。 -
errorRecovery:默认情况下,当 Babel 发现一些无效代码时,总是会抛出错误。当此选项设置为
true时,它会存储解析错误并尝试继续解析无效的输入文件。生成的 AST 将有一个errors属性,表示所有解析错误的数组。请注意,即使启用了此选项,@babel/parser仍可能因不可恢复的错误而抛出。 -
locations:布尔值。
true是默认值,会给每个节点添加一个loc属性,该属性是一个对象,包含start和end属性,这些属性又是包含line和column数字的对象。当设置为false时,输出的 AST 中将不包含loc属性。 -
插件:包含你想要启用的插件的数组。
-
sourceType:指明代码应以哪种模式进行解析。可以是
"script"、"commonjs"、"module"或"unambiguous"之一。默认是"script"。"unambiguous"会让 @babel/parser 尝试根据是否存在 ES6import或export语句来进行_猜测_。包含 ES6import和export的文件会被视为"module",否则为"script"。"commonjs"模式表示代码应该在像 Node.js 这样的 CommonJS 环境中运行。它与"script"模式大体兼容,只是允许在顶层使用return、new.target和using/await using声明。 -
sourceFilename:将输出的 AST 节点与它们的源文件名关联。当从多个输入文件的 AST 生成代码和源码映射时非常有用。
-
startColumn:默认情况下,解析的代码会被当作从第1行,第0列开始。你也可以提供一个列号来从指定列开始。这在与其他源代码工具集成时很有用。
-
startLine: 默认情况下,解析的代码会被当作从第1行,第0列开始。你也可以提供一个行号来从指定行开始。这在与其他源代码工具集成时很有用。
-
startIndex:默认情况下,所有源索引从 0 开始。使用此选项,你可以提供一个替代的起始索引。当
startLine大于 1 时,为了确保 AST 源索引的准确性,应该始终提供此选项。对与其他源工具的整合很有用。 -
strictMode:默认情况下,ECMAScript 代码只有在存在
"use strict";指令或解析的文件是 ECMAScript 模块时才会作为严格模式解析。将此选项设置为true可以始终以严格模式解析文件。 -
ranges:为每个节点添加一个
range属性:[node.start, node.end] -
tokens:将所有解析的 tokens 添加到
File节点上的tokens属性
输出
🌐 Output
Babel 解析器根据 Babel AST 格式 生成 AST。它基于 ESTree 规范,但有以下偏差:
🌐 The Babel parser generates AST according to Babel AST format. It is based on ESTree spec with the following deviations:
- 字面量 令牌被替换为 字符串字面量、数值字面量、大整数字面量、布尔字面量、空值、正则表达式字面量
- 属性 令牌被替换为 对象属性 和 对象方法
- 方法定义 被 类方法 和 类私有方法 替换了
- 属性定义 被 类属性 和 类私有属性 替换了
- 私有标识符 被替换成 私有名字
- 程序 和 代码块语句 包含额外的
directives字段,带有 指令 和 指令字面意思 - 类方法、类私有方法、对象属性 和 对象方法 在 函数表达式 中的 value 属性被强制/引入到主方法节点中。
- 链表达式 被 可选成员表达式 和 可选调用表达式 替换了
- 导入表达式 被替换成一个
callee是 [导入] 节点的 调用表达式。这个更改将在 Babel 8 中被撤销。 - 带有
exported字段的 导出全部声明 被一个包含 导出命名空间指定符 节点的 导出命名声明 替换。
estree 插件可以恢复这些偏差。只有在你将 Babel AST 传给其他符合 ESTree 的工具时才使用它。
JSX 代码的 AST 基于 Facebook JSX 抽象语法树。
🌐 AST for JSX code is based on Facebook JSX AST.
服务器
🌐 Semver
Babel 解析器在大多数情况下遵循语义化版本规范。唯一需要注意的是,某些符合规范的 bug 修复可能会在补丁版本中发布。
🌐 The Babel Parser follows semver in most situations. The only thing to note is that some spec-compliancy bug fixes may be released under patch versions.
举个例子:我们会对类似 #107 的早期错误推送修复——每个文件有多个默认导出。即使这会导致构建失败,这也会被视为一个错误修复。
🌐 For example: We push a fix to early error on something like #107 - multiple default exports per file. That would be considered a bug fix even though it would cause a build to fail.
示例
🌐 Example
require("@babel/parser").parse("code", {
// parse in strict mode and allow module declarations
sourceType: "module",
plugins: [
// enable jsx and flow syntax
"jsx",
"flow",
],
});
插件
🌐 Plugins
各种各样的
🌐 Miscellaneous
| 名称 | 代码示例 |
|---|---|
estree (仓库) | 不适用 |
语言扩展
🌐 Language extensions
历史
| 版本 | 变更 |
|---|---|
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 提案(链接)
🌐 ECMAScript proposals
| Name | Code Example |
|---|---|
asyncDoExpressions (proposal) | async do { await requestAPI().json() } |
decorators (proposal) decorators-legacy | @a class A {} |
decoratorAutoAccessors (proposal) | class Example { @reactive accessor myBool = false; } |
deferredImportEvaluation (proposal) | import defer * as ns from "dep"; |
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'; } }; |
exportDefaultFrom (proposal) | export v from "mod" |
functionBind (proposal) | a::b, ::console.log |
functionSent (proposal) | function* g() { function.sent } |
moduleBlocks (proposal) | let m = module { export let y = 1; }; |
optionalChainingAssign (proposal) | x?.prop = 2 |
partialApplication (proposal) | f(?, a) |
pipelineOperator (proposal) | a |> b |
sourcePhaseImports (proposal) | import source x from "./x" |
throwExpressions (proposal) | () => throw new Error("") |
插件选项
🌐 Plugins options
历史
| 版本 | 更改 |
|---|---|
7.21.0 | decorators 的 decoratorsBeforeExport 选项默认行为是允许装饰器出现在 export 关键字的前面或后面。 |
7.19.0 | recordAndTuple 插件的 syntaxType 选项默认值为 hash;为 decorators 插件添加了 allowCallParenthesized 选项。 |
7.17.0 | 为 hack 管道操作符的 topicToken 选项添加了 @@ 和 ^^ |
7.16.0 | 为 typescript 插件添加了 disallowAmbiguousJSXLike。为 hack 管道操作符的 topicToken 选项添加了 ^ |
7.14.0 | 为 typescript 插件添加了 dts |
当一个插件被多次指定时,只考虑第一个选项。
-
decorators:-
allowCallParenthesized(boolean,默认为true)当
false时,禁止在@(...)()形式中使用装饰器,改用@(...())。阶段 3 的装饰器提案使用allowCallParenthesized: false。 -
decoratorsBeforeExport(boolean)默认情况下,导出类上的装饰器可以放在
export关键字的前面或后面。当设置了这个选项后,装饰器将只能放在指定的位置。JavaScript// decoratorsBeforeExport: true@decexport class C {}// decoratorsBeforeExport: falseexport@decclass C {}caution此选项已被弃用,并将在未来版本中移除。当明确将此选项设置为
true或false时有效的代码,即使未设置此选项也同样有效。
-
-
optionalChainingAssign:version(必填,接受值:2023-07) 这个提案目前还处于第一阶段,因此很可能会受到重大变动的影响。 你必须指定你使用的提案版本,以确保 Babel 能够继续以兼容的方式解析你的代码。
-
pipelineOperator:proposal(必填,接受的值:fsharp、hack) 对于管道操作符有几种不同的提案。 这个选项用于选择使用哪一个提案。 更多信息请参见 plugin-proposal-pipeline-operator,其中包括一个比较它们行为的表格。topicToken(当proposal为hack时必填,可接受的值:%、#、^、@@、^^)hack提案在它的管道中使用了一个“主题”占位符。 对于这个主题占位符,有两种不同的选择。 这个选项就是选择用哪个标记来指代主题。
-
partialApplication:version(必填,唯一有效值为2018-07)。指定你正在使用的部分应用提案的版本。2018-07表示该提案在 2018 年 7 月的 TC39 会议上提出时的样子。
-
flow:all(boolean,默认:false) 有些代码在 Flow 和普通 JavaScript 中的含义不同。例如,foo<T>(x)在 Flow 中被解析为带类型参数的调用表达式,但根据 ECMAScript 规范,它会被解析为比较操作(foo < T > x)。默认情况下,babel-parser只有在文件以// @flow指令开头时才会将这些模糊的结构解析为 Flow 类型。 将此选项设置为true,可以始终将文件解析为好像指定了// @flow。
-
typescriptdts(boolean,默认false) 这个选项会启用在 TypeScript 环境上下文中的解析,在这里某些语法规则会有所不同(比如.d.ts文件和declare module块内部)。更多关于环境上下文的信息,请参考 TypeScript Handbook 和 TypeScript Deep Dive。disallowAmbiguousJSXLike(boolean,默认为false) 即使没有启用jsx插件,这个选项也会禁止使用可能与 JSX 混淆的语法(<X> y类型断言和<X>() => {}类型参数)。它在解析.mts和.mjs文件时的行为与tsc相同。
错误代码
🌐 Error codes
历史
| 版本 | 变更 |
|---|---|
v7.14.0 | 添加了错误代码 |
错误代码对于处理 @babel/parser 抛出的错误很有用。
🌐 Error codes are useful for handling the errors thrown by @babel/parser.
有两个错误代码,code 和 reasonCode。
🌐 There are two error codes, code and reasonCode.
code- 错误的大致分类(例如
BABEL_PARSER_SYNTAX_ERROR、BABEL_PARSER_SOURCETYPE_MODULE_REQUIRED)。
- 错误的大致分类(例如
reasonCode- 错误的详细分类(例如
MissingSemicolon、VarRedeclaration)。
- 错误的详细分类(例如
使用 errorRecovery 错误代码的示例:
🌐 Example of using error codes with 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
常见问题
🌐 FAQ
Babel 解析器会支持插件系统吗?
🌐 Will the Babel parser support a plugin system?
🌐 Previous issues: #1351, #6694.
我们目前不打算承诺支持插件的 API 或由此产生的生态系统(维护 Babel 自己的插件系统已经有够多的工作了)。如何让那个 API 有效还不清楚,而且这会限制我们重构和优化代码库的能力。
🌐 We currently aren't willing to commit to supporting the API for plugins or the resulting ecosystem (there is already enough work maintaining Babel's own plugin system). It's not clear how to make that API effective, and it would limit our ability to refactor and optimize the codebase.
对于那些想要创建自己的自定义语法的用户,我们目前的建议是让用户复刻解析器。
🌐 Our current recommendation for those that want to create their own custom syntax is for users to fork the parser.
要使用你自定义的解析器,你可以在你的 options 中添加一个插件,通过它的 npm 包名调用解析器,或者如果使用 JavaScript,则通过 require 调用它,
🌐 To consume your custom parser, you can add a plugin to your options to call the parser via its npm package name or require it if using JavaScript,
const parse = require("custom-fork-of-babel-parser-on-npm-here");
module.exports = {
plugins: [
{
parserOverride(code, opts) {
return parse(code, opts);
},
},
],
};