@babel/parser
Babel 剖析器(以前稱為 Babylon)是 JavaScript 剖析器,用於 Babel。
- 預設啟用的最新 ECMAScript 版本(ES2020)。
- 註解附加。
- 支援 JSX、Flow、Typescript。
- 支援實驗性語言提案(接受任何至少 stage-0 的 PR)。
鳴謝
大量採用 acorn 和 acorn-jsx,感謝 @RReverser 和 @marijnh 出色的工作。
API
babelParser.parse(code, [options])
babelParser.parseExpression(code, [options])
parse()
將提供的 code
解析為完整的 ECMAScript 程式,而 parseExpression()
則嘗試解析單一 Expression,同時考量效能。有疑問時,請使用 .parse()
。
選項
歷史
版本 | 變更 |
---|---|
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
外掛,而非此選項。 -
allowNewTargetOutsideFunction:預設情況下,
new.target
的使用不允許在函式或類別之外。將此設定為true
可接受此類程式碼。 -
allowReturnOutsideFunction:預設情況下,最上層的回傳宣告會產生錯誤。將此設定為
true
可接受此類程式碼。 -
allowSuperOutsideMethod:預設情況下,
super
的使用不允許在類別和物件方法之外。將此設定為true
可接受此類程式碼。 -
allowUndeclaredExports:預設情況下,匯出未在目前模組範圍內宣告的識別碼會產生錯誤。雖然 ECMAScript 模組規範要求此行為,但 Babel 的剖析器無法預測外掛管線中後續的轉換,這些轉換可能會插入適當的宣告,因此有時必須將此選項設定為
true
,以防止剖析器過早抱怨稍後會新增的未宣告匯出。 -
attachComment:預設情況下,Babel 會將註解附加到相鄰的 AST 節點。當此選項設為
false
時,不會附加註解。當輸入程式碼有許多註解時,它可以提供高達 30% 的效能提升。@babel/eslint-parser
會為你設定它。不建議在 Babel 轉換中使用attachComment: false
,因為這樣會移除輸出程式碼中的所有註解,並使註解(例如/* 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 根據 ES6import
或export
陳述式的存在來嘗試「猜測」。具有 ES6import
和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:將所有剖析的記號新增到
File
節點上的tokens
屬性
輸出
Babel 解析器根據 Babel AST 格式 產生 AST。它基於 ESTree 規範,並有以下偏差
- 字面量 符號已替換為 字串字面量、數字字面量、大整數字面量、布林字面量、Null 字面量、正規表示式字面量
- 屬性 符號已替換為 物件屬性 和 物件方法
- 方法定義 已替換為 類別方法 和 類別私有方法
- PropertyDefinition 已被 ClassProperty 和 ClassPrivateProperty 取代
- PrivateIdentifier 已被 PrivateName 取代
- Program 和 BlockStatement 包含額外的
directives
欄位,其中有 Directive 和 DirectiveLiteral - ClassMethod、ClassPrivateMethod、ObjectProperty 和 ObjectMethod 值屬性中的屬性在 FunctionExpression 中會被強制轉換或帶入主要方法節點。
- ChainExpression 已被 OptionalMemberExpression 和 OptionalCallExpression 取代
- ImportExpression 已被替換為
callee
為 CallExpression 的 Import 節點。
現在有一個 estree
外掛程式,可以還原這些偏差
JSX 程式碼的 AST 是基於 Facebook JSX AST。
Semver
Babel Parser 在大多數情況下遵循 semver。唯一要注意的是,某些符合規格的錯誤修正可能會在小版本中釋出。
例如:我們針對類似 #107 的問題(每個檔案有多個預設匯出)提出一個提早錯誤的修正。即使這會導致建置失敗,這仍會被視為錯誤修正。
範例
require("@babel/parser").parse("code", {
// parse in strict mode and allow module declarations
sourceType: "module",
plugins: [
// enable jsx and flow syntax
"jsx",
"flow",
],
});
外掛程式
其他
名稱 | 程式碼範例 |
---|---|
estree (repo) | 不適用 |
語言擴充
歷史
版本 | 變更 |
---|---|
v7.6.0 | 新增 v8intrinsic |
名稱 | 程式碼範例 |
---|---|
flow (repo) | var a: string = ""; |
flowComments (文件) | /*:: type Foo = {...}; */ |
jsx (repo) | <a attr="b">{s}</a> |
typescript (repo) | var a: string = ""; |
v8intrinsic | %DebugPrint(foo); |
ECMAScript 提案
歷史
版本 | 變更 |
---|---|
v7.23.0 | 新增 sourcePhaseImports 、deferredImportEvaluation 、optionalChainingAssign |
v7.22.0 | 預設啟用 regexpUnicodeSets ,新增 importAttributes |
v7.20.0 | 新增 explicitResourceManagement 、importReflection |
v7.17.0 | 新增 regexpUnicodeSets 、destructuringPrivate 、decoratorAutoAccessors |
v7.15.0 | 將 hack 新增至 pipelineOperator 的 proposal 選項。將 topLevelAwait 、privateIn 移至最新 ECMAScript 功能 |
v7.14.0 | 新增 asyncDoExpressions 。將 classProperties 、classPrivateProperties 、classPrivateMethods 、moduleStringNames 移至最新 ECMAScript 功能 |
v7.13.0 | 新增 moduleBlocks |
v7.12.0 | 新增 classStaticBlock 、moduleStringNames |
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.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 |
當外掛被指定多次時,只會考慮第一個選項。
-
importAttributes
:-
deprecatedAssertSyntax
(boolean
,預設為false
)當為
true
時,允許使用 已棄用的assert
關鍵字來解析匯入屬性。這與importAssertions
解析器外掛程式最初支援的語法相符。
-
-
裝飾器
:-
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
時有效的程式碼,在未設定此選項時也仍然有效。::
-
optionalChainingAssign
:version
(必填,可接受值:2023-07
) 此提案仍處於第 1 階段,因此很可能會受到重大變更的影響。您必須指定您正在使用的提案版本,以確保 Babel 能夠繼續以相容的方式解析您的程式碼。
-
pipelineOperator
:-
proposal
(必要,可接受值:minimal
、fsharp
、hack
、(已棄用))對於管道運算子有數個不同的提案。此選項選擇要使用的提案。請參閱 plugin-proposal-pipeline-operator 以取得更多資訊,包括比較其行為的表格。smart
-
topicToken
(當proposal
為hack
時必要,可接受值:%
、#
、^
、@@
、^^
)hack
提案在其管道中使用「主題」佔位符。此主題佔位符有兩個不同的選擇。此選項選擇用於參照主題的記號。topicToken: "#"
與syntaxType: "hash"
的recordAndTuple
不相容。請參閱 plugin-proposal-pipeline-operator 以取得更多資訊。
-
-
recordAndTuple
:syntaxType
(hash
或bar
,預設為hash
)recordAndTuple
有兩個語法變體。它們共享完全相同的執行時期語意。語法類型 記錄範例 元組範例 "hash"
#{ a: 1 }
#[1, 2]
"bar"
{| a: 1 |}
[|1, 2|]
請參閱 #{}
/#[]
的人體工學 以取得更多資訊。
-
flow
:all
(布林值
,預設:false
)某些程式碼在 Flow 和純粹的 JavaScript 中具有不同的意義。例如,foo<T>(x)
在 Flow 中會解析為帶有類型引數的呼叫表達式,但根據 ECMAScript 規格解析為比較(foo < T > x
)。預設情況下,babel-parser
僅當檔案以// @flow
實用程式碼開頭時,才會將這些含糊的建構解析為 Flow 類型。將此選項設定為true
,以始終解析檔案,就像指定了// @flow
一樣。
-
typescript
dts
(boolean
,預設為false
)此選項將啟用在 TypeScript 環境背景下進行剖析,其中特定語法有不同的規則(例如.d.ts
檔案和declare module
區塊內)。請參閱 https://typescript.dev.org.tw/docs/handbook/declaration-files/introduction.html 和 https://basarat.gitbook.io/typescript/type-system/intro 以取得有關環境背景的更多資訊。disallowAmbiguousJSXLike
(boolean
,預設為false
)即使未啟用jsx
外掛程式,此選項仍禁止使用與 JSX(<X> y
型別斷言和<X>() => {}
型別引數)有歧義的語法。它符合剖析.mts
和.mjs
檔案時的tsc
行為。
錯誤碼
歷史
版本 | 變更 |
---|---|
v7.14.0 | 新增錯誤碼 |
錯誤碼對於處理 @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
常見問題
Babel 剖析器是否會支援外掛程式系統?
我們目前不願意承諾支援外掛程式的 API 或其生態系統(維護 Babel 本身的外掛程式系統已經夠忙了)。目前還不清楚如何讓該 API 發揮效用,而且這會限制我們重構和最佳化程式碼庫的能力。
對於想要建立自訂語法的使用者,我們目前的建議是 fork 剖析器。
若要使用自訂剖析器,你可以新增一個外掛程式到你的 選項,以透過 npm 套件名稱呼叫剖析器,或是在使用 JavaScript 時載入剖析器。
const parse = require("custom-fork-of-babel-parser-on-npm-here");
module.exports = {
plugins: [
{
parserOverride(code, opts) {
return parse(code, opts);
},
},
],
};