# @babel/解析器
Babel 解析器(以前称为 Babylon)是Babel 中使用的 JavaScript 解析器。
- 默认启用最新的 ECMAScript 版本 (ES2020)。
- 评论附件。
- 支持 JSX、Flow、Typescript。
- 支持实验性语言提案(接受任何至少*
stage-0的 PR )。
# 积分
主要基于acorn (opens new window) 和acorn-jsx (opens new window) ,感谢@RReverser (opens new window) 和@marijnh (opens new window) 的出色工作。
# 应用程序接口
# babelParser.parse(code,options])[
# babelParser.parseExpression(code,options])[
parse()将提供的code作为整个 ECMAScript 程序进行解析,同时 parseExpression()尝试在考虑性能的情况下解析单个表达式。如有疑问,请使用.parse().
| Version | Changes |
|---|---|
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插件。allowNewTargetOutsideFunction:默认情况下,
new.target不允许在函数或类之外使用。将其设置为true接受此类代码。allowReturnOutsideFunction:默认情况下,顶层的 return 语句会引发错误。将其设置为
true接受此类代码。allowSuperOutsideMethod:默认情况下,
super不允许在类和对象方法之外使用。将其设置为true接受此类代码。allowUndeclaredExports:默认情况下,导出未在当前模块范围内声明的标识符将引发错误。虽然这种行为是 ECMAScript 模块规范所要求的,但 Babel 的解析器无法预测稍后可能插入适当声明的插件管道中的转换,因此有时将此选项设置为很重要,以防止解析器过早地抱怨未声明的导出,这
true将稍后添加。attachComment:默认情况下,Babel 将注释附加到相邻的 AST 节点。当此选项设置为 时
false,不附加注释。当输入代码有很多注释时,它可以提供高达 30% 的性能提升。@babel/eslint-parser将为您设置。不建议使用attachComment: falseBabel 转换,因为这样做会删除输出代码中的所有注释,并呈现诸如/* istanbul ignore next */非功能性的注释。annexb:默认情况下,Babel 根据ECMAScript 的附件 B “ Additional ECMAScript Features for Web Browsers ” (opens new window) 语法解析 JavaScript。当此选项设置为 时
false,Babel 将解析没有特定于 Annex B 的扩展的语法。createParenthesizedExpressions:默认情况下,解析器
extra.parenthesized在表达式节点上设置。当此选项设置为 时true,ParenthesizedExpression将创建 AST 节点。errorRecovery:默认情况下,Babel 在发现一些无效代码时总是抛出错误。当此选项设置为 时
true,它将存储解析错误并尝试继续解析无效的输入文件。生成的 AST 将有一个errors属性表示所有解析错误的数组。请注意,即使启用此选项,@babel/parser也可能会抛出不可恢复的错误。plugins:包含您要启用的插件的数组。
sourceType:指示应在其中解析代码的模式。可以是
"script"、"module"或 之一"unambiguous"。默认为"script"."unambiguous"将使@babel/parser 尝试根据 ES6或语句的存在进行猜测。考虑带有 ES6和s的文件,否则为.import``export``import``export``"module"``"script"sourceFilename:将输出 AST 节点与其源文件名相关联。从多个输入文件的 AST 生成代码和源映射时很有用。
startColumn:默认情况下,解析后的代码被视为从第 1 行第 0 列开始。您可以提供一个列号作为开始。用于与其他源工具集成。
startLine:默认情况下,解析后的代码被视为从第 1 行第 0 列开始。您可以提供一个行号作为开始。用于与其他源工具集成。
strictMode
"use strict";:默认情况下,仅当指令存在或解析的文件是 ECMAScript 模块时,ECMAScript 代码才被解析为严格模式 。将此选项设置为true始终以严格模式解析文件。ranges
range:向每个节点添加一个属性:[node.start, node.end]tokens:将所有已解析的令牌添加到节点
tokens上的属性File
# 输出
Babel 解析器根据Babel AST 格式 (opens new window) 生成 AST 。它基于ESTree 规范 (opens new window) ,但有以下差异:
文字标记替换为StringLiteral (opens new window) 、NumericLiteral (opens new window) 、BigIntLiteral (opens new window) 、BooleanLiteral (opens new window) 、NullLiteral (opens new window) 、RegExpLiteral (opens new window)属性令牌替换为ObjectProperty (opens new window) 和ObjectMethod (opens new window)MethodDefinition替换为ClassMethod (opens new window) 和ClassPrivateMethod (opens new window)PropertyDefinition替换为ClassProperty (opens new window) 和ClassPrivateProperty (opens new window)PrivateIdentifier替换为PrivateName (opens new window)Program和BlockStatement包含带有 (opens new window)Directive和DirectiveLiteral (opens new window) 的附加directives字段FunctionExpression中的ClassMethod、*ClassPrivateMethod、ObjectProperty (opens new window) 和ObjectMethod (opens new window) value 属性的属性被强制/引入主方法节点。ChainExpression替换为OptionalMemberExpression (opens new window) 和OptionalCallExpression (opens new window)ImportExpression替换为CallExpression (opens new window) ,它callee是一个Import (opens new window) 节点。
现在有一个
estree插件可以恢复这些偏差
JSX 代码的 AST 基于Facebook JSX AST (opens new window) 。
# 服务器
在大多数情况下,Babel Parser 遵循 semver。唯一需要注意的是,一些符合规范的错误修复可能会在补丁版本下发布。
例如:我们修复了类似#107 的 (opens new window) 早期错误- 每个文件有多个默认导出。这将被视为错误修复,即使它会导致构建失败。
# 示例
require("@babel/parser").parse("code", {
// parse in strict mode and allow module declarations
sourceType: "module",
plugins: [
// enable jsx and flow syntax
"jsx",
"flow",
],
});
# 插件
# 杂项
| 姓名 | 代码示例 |
|---|---|
estree(回购 (opens new window)) | 不适用 |
# 语言扩展 (opens new window)
| Version | Changes |
|---|---|
v7.6.0 | 添加v8intrinsic |
| 姓名 | 代码示例 |
|---|---|
flow(回购 (opens new window)) | var a: string = ""; |
flowComments(文档 (opens new window)) | /*:: type Foo = {...}; */ |
jsx(回购 (opens new window)) | <a attr="b">{s}</a> |
typescript(回购 (opens new window)) | var a: string = ""; |
v8intrinsic | %DebugPrint(foo); |
# ECMAScript提案
| 姓名 | 代码示例 |
|---|---|
asyncDoExpressions(建议 (opens new window)) | async do { await requestAPI().json() } |
decimal(建议 (opens new window)) | 0.3m |
decorators(建议 (opens new window)) decorators-legacy | @a class A {} |
decoratorAutoAccessors(建议 (opens new window)) | class Example { @reactive accessor myBool = false; } |
destructuringPrivate(建议 (opens new window)) | class Example { #x = 1; method() { const { #x: x } = this; } } |
doExpressions(建议 (opens new window)) | var a = do { if (true) { 'hi'; } }; |
explicitResourceManagement(建议 (opens new window)) | using reader = getReader() |
exportDefaultFrom(建议 (opens new window)) | export v from "mod" |
functionBind(建议 (opens new window)) | a::b, ::console.log |
functionSent(建议 (opens new window)) | function.sent |
importAssertions(建议 (opens new window)) | import json from "./foo.json" assert { type: "json" }; |
importReflection(建议 (opens new window)) | import module foo from "./foo.wasm"; |
moduleBlocks(建议 (opens new window)) | let m = module { export let y = 1; }; |
partialApplication(建议 (opens new window)) | f(?, a) |
pipelineOperator(建议 (opens new window)) | a |> b |
recordAndTuple(建议 (opens new window)) | #{x: 1},#[1, 2] |
regexpUnicodeSets(建议 (opens new window)) | /[\p{Decimal_Number}--[0-9]]/v; |
throwExpressions(建议 (opens new window)) | () => throw new Error("") |
# 最新的 ECMAScript特性
以下功能已在最新版本的 上启用@babel/parser,并且无法禁用,因为它们是该语言的一部分。只有在使用旧版本时才应启用这些功能。
| 姓名 | 代码示例 |
|---|---|
asyncGenerators(建议 (opens new window)) | async function*() {},for await (let a of b) {} |
bigInt(建议 (opens new window)) | 100n |
classProperties(建议 (opens new window)) | class A { b = 1; } |
classPrivateProperties(建议 (opens new window)) | class A { #b = 1; } |
classPrivateMethods(建议 (opens new window)) | class A { #c() {} } |
classStaticBlock(建议 (opens new window)) | class A { static {} } |
dynamicImport(建议 (opens new window)) | import('./guy').then(a) |
exportNamespaceFrom(建议 (opens new window)) | export * as ns from "mod" |
logicalAssignment(建议 (opens new window)) | a &&= b |
moduleStringNames(建议 (opens new window)) | import { "😄" as smile } from "emoji"; |
nullishCoalescingOperator(建议 (opens new window)) | a ?? b |
numericSeparator(建议 (opens new window)) | 1_000_000 |
objectRestSpread(建议 (opens new window)) | var a = { b, ...c }; |
optionalCatchBinding(建议 (opens new window)) | try {throw 0;} catch{do();} |
optionalChaining(建议 (opens new window)) | a?.b |
privateIn(建议 (opens new window)) | #p in obj |
topLevelAwait(建议 (opens new window)) | await promise在模块中 |
# 插件选项 (opens new window)
历史| Version | Changes |
| :--- | :--- |
| | The default behavior of the' option is to allow decorators either before or after the keyword. |
| | The option of the plugin defaults to; added option for the plugin. |
| | Added and to the option of the pipeline operator | || Added for plugin. Added to the option of the pipeline operators | || Added for plugin |
注意:当多次指定一个插件时,只考虑第一个选项。
decorators:allowCallParenthesized(boolean, 默认为true)
时false,禁止@(...)()形式中的装饰器支持@(...())。第 3 阶段装饰器提案使用allowCallParenthesized: false.
decoratorsBeforeExport(boolean)
默认情况下,导出类的装饰器可以放在export关键字之前或之后。设置此选项后,装饰器将只允许在指定位置使用。
JavaScript
// decoratorsBeforeExport: true
@dec
export class C {}
// decoratorsBeforeExport: false
export @dec class C {}
⚠️ 此选项已弃用,将在未来版本中删除。明确设置此选项时有效的代码,
true或未false设置此选项时也有效的代码。
pipelineOperator:proposal(必填,可接受的值:minimal,fsharp,hack,smart(已弃用))对于管道操作员有几种不同的建议。此选项选择要使用的建议。有关更多信息,请参阅plugin-proposal-pipeline-operator (opens new window) ,包括比较它们的行为的表格。topicToken``proposal(在is时需要hack,可接受的值:%,#,^,@@,^^)hack提案在其管道中使用“主题”占位符。此主题占位符有两种不同的选择。此选项选择使用什么标记来引用主题。 与topicToken: "#"不兼容。有关更多信息,请参阅插件提案管道运算符 (opens new window) 。recordAndTuple``syntaxType: "hash"recordAndtuple:syntaxType(hash或者bar,默认为hash)有两种语法变体recordAndTuple。它们共享完全相同的运行时语义。| 语法类型 | 记录范例 | 元组示例 | | --- | --- | --- | |"hash"|#{ a: 1 }|#[1, 2]| |"bar"|{| a: 1 |}|[|1, 2|]| 有关详细信息,请参阅/ (opens new window)的人体工程学#{}#[]。flow:all(boolean, default:false) 一些代码在 Flow 和 vanilla JavaScript 中有不同的含义。例如,foo<T>(x)在 Flow 中被解析为带有类型参数的调用表达式,但foo < T > x根据 ECMAScript 规范被解析为比较 ()。默认情况下,babel-parser仅当文件以// @flowpragma 开头时,才将那些不明确的构造解析为 Flow 类型。将此选项设置为true始终像// @flow指定的那样解析文件。typescriptdts(boolean, defaultfalse) 此选项将在 TypeScript 环境上下文中启用解析,其中某些语法具有不同的规则(如.d.ts文件和内部declare module块)。有关环境上下文的更多信息,请参阅https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html (opens new window) 和https://basarat.gitbook.io/typescript/type-system/intro 。 (opens new window)disallowAmbiguousJSXLike(boolean, defaultfalse) 即使jsx插件未启用,此选项也不允许使用与 JSX 不明确的语法(<X> y类型断言和<X>() => {}类型参数)。它匹配tsc解析.mts和.mjs文件时的行为。
# 错误代码 (opens new window)
历史| Version | Changes | | :--- | :--- | | ``| 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
# FAQ
# Babel 解析器是否支持插件系统? (opens new window)
上期:#1351 (opens new window) 、#6694 (opens new window) 。
我们目前不愿意承诺支持插件的 API 或由此产生的生态系统(维护 Babel 自己的插件系统已经有足够的工作)。目前尚不清楚如何使该 API 有效,并且它会限制我们重构和优化代码库的能力。
对于那些想要创建自己的自定义语法的人,我们目前的建议是让用户分叉解析器。
要使用您的自定义解析器,您可以在选项 中添加一个插件,以通过其 npm 包名称调用解析器,或者如果使用 JavaScript,则需要它,
const parse = require("custom-fork-of-babel-parser-on-npm-here");
module.exports = {
plugins: [
{
parserOverride(code, opts) {
return parse(code, opts);
},
},
],
};