babel工具之@babel/parser(翻译)

11,277 阅读5分钟

原文: www.babeljs.cn/docs/babel-…

Babel解析器(以前是Babylon)是Babel中使用的JavaScript解析器。

  • 默认情况下启用的最新ECMAScript版本(ES2017)。

  • 评论附件。

  • 支持JSX,Flow,Typescript。

  • 支持实验性语言建议(至少接受 stage-0的PRs)。

信用

主要基于acornacorn jsx,感谢@RReverser和@marijnh的出色工作。

API

babelParser.parse(code, [options])

babelParser.parseExpression(code, [options])

parse()将提供的代码作为一个完整的ECMAScript程序进行解析,而parseExpression()则尝试解析单个表达式并考虑性能。如果有疑问,请使用.parse()。

选项

  • allowImportExportEverywhere:默认情况下,import 和export 声明只能出现在程序的顶层。如果将此选项设置为true,则允许在任何允许使用语句的地方使用它们。
  • allowAwaitOutsideFunction: 默认情况下,只允许在异步函数内部使用await,或者在启用topLevelAwait插件时,允许在模块的顶层作用域中使用await。将其设置为true,以便在脚本的顶级范围中也接受它。
  • allowReturnOutsideFunction: 默认情况下,顶层的return语句会引发错误。将此设置为true以接受此类代码。
  • allowSuperOutsideMethod:默认情况下,在类和对象方法之外不允许super 使用。将此设置为true以接受此类代码。
  • allowUndeclaredExports: 默认情况下,导出未在当前模块范围中声明的标识符将引发错误。虽然ECMAScript模块规范要求这种行为,但是Babel的解析器无法预测插件管道中稍后可能插入适当声明的转换,因此,有时必须将此选项设置为true,以防止解析器过早地抱怨稍后将添加的未声明的导出。
  • createParenthesizedExpressions:默认情况下,解析器设置extra.parenthesized在表达式节点上。当此选项设置为true时,将创建ParenthesizedExpression(圆括号) AST节点。
  • errorRecovery: 默认情况下,Babel总是在发现一些无效代码时抛出一个错误。当此选项设置为true时,它将存储解析错误并尝试继续解析无效的输入文件。生成的AST将有一个errors属性,表示所有解析错误的数组。请注意,即使启用了此选项,@babel/parser也可能抛出不可恢复的错误。
  • plugins: 包含要启用的插件的数组。
  • sourceType: 指示分析代码的模式。可以是"script", "module"或"unambiguous"之一。默认为"script"。 "unambiguous"将使@babel/parser尝试根据存在的ES6导入或导出语句进行猜测。带有ES6 import和export的文件被视为"module",否则是"script"。
  • sourceFilename:将输出AST节点与其源文件名关联。从多个输入文件的AST生成代码和源映射时非常有用。
  • startLine: 默认情况下,被解析的第一行代码被视为第1行。您可以提供一个行号作为替代。有助于与其他源工具集成。
  • strictMode:默认情况下,只有在存在“use strict”;指令或解析的文件是ECMAScript模块时,ECMAScript代码才会被解析为strict。将此选项设置为true可始终以严格模式解析文件。
  • ranges:向每个节点添加 range属性:[node.start, node.end]
  • tokens:将所有解析的令牌添加到File 节点上的tokens属性

输出

Babel解析器根据Babel-AST格式生成AST。它基于ESTree规范,但存在以下偏差:

现在有一个estree插件可以恢复这些偏差

ASTforJSX代码基于Facebook JSX AST

Semver

Babel解析器在大多数情况下都遵循semver。唯一需要注意的是,一些符合规范的错误修复可能会在补丁版本下发布。

例如:我们对早期错误进行了修复,比如#107-每个文件有多个默认导出。这将被认为是一个错误修复,即使它会导致构建失败。

示例

require("@babel/parser").parse("code", {
  // 以严格模式进行分析并允许模块声明
  sourceType: "module",

  plugins: [
    // enable jsx and flow syntax
    "jsx",
    "flow"
  ]
});

插件

其他

Name:estree (repo) Code Example:n/a

语言扩展

Name:flow (repo) Code Example:var a: string = "";

Name:flowComments (docs) Code Example:/*:: type Foo = {...}; */

Name:jsx (repo) Code Example:{s}

Name:typescript (repo) Code Example:var a: string = "";

Name:v8intrinsic Code Example:%DebugPrint(foo);

ECMAScript建议

见原文

插件选项

注意:当一个插件被多次指定时,只考虑第一个选项。

  • decorators:
    • decoratorsBeforeExport (boolean)

        // decoratorsBeforeExport: true
        @dec
        export class C {}
        
        // decoratorsBeforeExport: false
        export @dec class C {}
      
  • pipelineOperator
  • flow:
    • all(boolean,default:false)一些代码在Flow 和普通JavaScript中有不同的含义。例如,foo(x)在Flow中被解析为带有类型参数的调用表达式,但作为与ECMAScript规范相应的比较(foox)。默认情况下,只有当文件以//@Flow pragma开头时,babel解析器才会将这些不明确的构造解析为Flow 类型。将此选项设置为true以始终分析文件,就像指定了//@flow一样。

常见问题解答

Babel 解析器会支持插件系统吗?

前几期issues:#1351#6694

目前,我们不愿意承诺支持插件的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);
    },
  }]
}