# @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
@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
仅当文件以// @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);
},
},
],
};