# @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: false
Babel 转换,因为这样做会删除输出代码中的所有注释,并呈现诸如/* 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
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
仅当文件以// @flow
pragma 开头时,才将那些不明确的构造解析为 Flow 类型。将此选项设置为true
始终像// @flow
指定的那样解析文件。 -
typescript
-
dts
(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);
@babel/standalone @babel/core