跳至主要內容

@babel/parser

Babel 剖析器(以前稱為 Babylon)是 JavaScript 剖析器,用於 Babel

  • 預設啟用的最新 ECMAScript 版本(ES2020)。
  • 註解附加。
  • 支援 JSX、Flow、Typescript。
  • 支援實驗性語言提案(接受任何至少 stage-0 的 PR)。

鳴謝

大量採用 acornacorn-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新增 allowNewTargetOutsideFunctionannexb
v7.16.0新增 startColumn
v7.15.0新增 attachComment
v7.7.0新增 errorRecovery
v7.5.0新增 allowUndeclaredExports
v7.2.0新增 createParenthesizedExpressions
  • allowImportExportEverywhere:預設情況下,importexport 宣告只能出現在程式碼最上層。將此選項設定為 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 根據 ES6 importexport 陳述式的存在來嘗試「猜測」。具有 ES6 importexport 的檔案會被視為 "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 規範,並有以下偏差

提示

現在有一個 estree 外掛程式,可以還原這些偏差

JSX 程式碼的 AST 是基於 Facebook JSX AST

Semver

Babel Parser 在大多數情況下遵循 semver。唯一要注意的是,某些符合規格的錯誤修正可能會在小版本中釋出。

例如:我們針對類似 #107 的問題(每個檔案有多個預設匯出)提出一個提早錯誤的修正。即使這會導致建置失敗,這仍會被視為錯誤修正。

範例

JavaScript
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新增 sourcePhaseImportsdeferredImportEvaluationoptionalChainingAssign
v7.22.0預設啟用 regexpUnicodeSets,新增 importAttributes
v7.20.0新增 explicitResourceManagementimportReflection
v7.17.0新增 regexpUnicodeSetsdestructuringPrivatedecoratorAutoAccessors
v7.15.0hack 新增至 pipelineOperatorproposal 選項。將 topLevelAwaitprivateIn 移至最新 ECMAScript 功能
v7.14.0新增 asyncDoExpressions。將 classPropertiesclassPrivatePropertiesclassPrivateMethodsmoduleStringNames 移至最新 ECMAScript 功能
v7.13.0新增 moduleBlocks
v7.12.0新增 classStaticBlockmoduleStringNames
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.0decoratorsdecoratorsBeforeExport 選項的預設行為是允許裝飾器在 export 關鍵字之前或之後。
7.19.0recordAndTuple 外掛的 syntaxType 選項預設為 hash;為 decorators 外掛新增 allowCallParenthesized 選項。
7.17.0@@^^ 新增至 hack 管道運算子的 topicToken 選項
7.16.0typescript 外掛新增 disallowAmbiguousJSXLike。將 ^ 新增至 hack 管道運算子的 topicToken 選項
7.14.0typescript 外掛新增 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 {}
      注意

此選項已棄用,並將在未來版本中移除。當此選項明確設定為 truefalse 時有效的程式碼,在未設定此選項時也仍然有效。::

  • optionalChainingAssign:

    • version (必填,可接受值:2023-07) 此提案仍處於第 1 階段,因此很可能會受到重大變更的影響。您必須指定您正在使用的提案版本,以確保 Babel 能夠繼續以相容的方式解析您的程式碼。
  • pipelineOperator:

    • proposal(必要,可接受值:minimalfsharphacksmart(已棄用))對於管道運算子有數個不同的提案。此選項選擇要使用的提案。請參閱 plugin-proposal-pipeline-operator 以取得更多資訊,包括比較其行為的表格。

    • topicToken(當 proposalhack 時必要,可接受值:%#^@@^^hack 提案在其管道中使用「主題」佔位符。此主題佔位符有兩個不同的選擇。此選項選擇用於參照主題的記號。topicToken: "#"syntaxType: "hash"recordAndTuple 不相容。請參閱 plugin-proposal-pipeline-operator 以取得更多資訊。

  • recordAndTuple:

    • syntaxTypehashbar,預設為 hashrecordAndTuple 有兩個語法變體。它們共享完全相同的執行時期語意。
      語法類型記錄範例元組範例
      "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

錯誤碼

歷史
版本變更
v7.14.0新增錯誤碼

錯誤碼對於處理 @babel/parser 拋出的錯誤很有用。

有兩個錯誤碼,codereasonCode

  • code
    • 錯誤的大致分類(例如 BABEL_PARSER_SYNTAX_ERRORBABEL_PARSER_SOURCETYPE_MODULE_REQUIRED)。
  • reasonCode
    • 錯誤的詳細分類(例如 MissingSemicolonVarRedeclaration)。

使用錯誤碼搭配 errorRecovery 的範例

JavaScript
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 剖析器是否會支援外掛程式系統?

先前問題:#1351#6694

我們目前不願意承諾支援外掛程式的 API 或其生態系統(維護 Babel 本身的外掛程式系統已經夠忙了)。目前還不清楚如何讓該 API 發揮效用,而且這會限制我們重構和最佳化程式碼庫的能力。

對於想要建立自訂語法的使用者,我們目前的建議是 fork 剖析器。

若要使用自訂剖析器,你可以新增一個外掛程式到你的 選項,以透過 npm 套件名稱呼叫剖析器,或是在使用 JavaScript 時載入剖析器。

JavaScript
const parse = require("custom-fork-of-babel-parser-on-npm-here");

module.exports = {
plugins: [
{
parserOverride(code, opts) {
return parse(code, opts);
},
},
],
};