Allowlist for `build/flow/src/parser/test/flow`
2026/9/20 22:24:38 网站建设 项目流程

Allowlist forbuild/flow/src/parser/test/flow

【免费下载链接】babel🐠 Babel is a compiler for writing next generation JavaScript.项目地址: https://gitcode.com/gh_mirrors/ba/babel

[!NOTE]> This file is automatically generated byutils/parser-test-runner. Only single-line comments after the list item will be preserved.

两个要点值得特别注意: 1. **自动生成**:文件头部明确声明它由 `utils/parser-test-runner` 自动生成,`--update-allowlist` 会整体重写它(机制细节见本文第五节); 2. **注释保留规则**:列表项之后只有**单行注释**会被保留,这是维护者给条目补充差异原因说明的唯一合法渠道(在 TypeScript 的 allowlist 中可以看到大量 `<!-- ... -->` 形式的注释,例如 [scripts/parser-tests/typescript/allowlist.md](https://link.gitcode.com/i/1515cc31b5b8db5e75793e2ce706c7c3) 中对 `duplicateIdentifierRelatedSpans1.ts` 标注的 "TS checks duplicate identifiers across related files, but babel-parser handles them separately")。 ### 两类差异条目 文件主体是两个编号小节,分别对应两类方向相反的"解析行为差异": ```markdown ## 15 invalid programs did not produce a parsing error ## 254 valid programs produced a parsing error
  • invalid programs did not produce a parsing error(无效程序未报错):Flow 认为这些程序是非法的(会报语法错误),但 Babel 解析器却成功解析了。这类差异在测试术语中称为false positive(误放行),即"本应拒绝却没有拒绝",说明 Babel 的语法检查比 Flow 更宽松。
  • valid programs produced a parsing error(有效程序报错):Flow 认为这些程序是合法的,但 Babel 解析器抛出了错误。这类差异称为false negative(误报错),即"本应通过却拒绝",说明 Babel 对某些 Flow 合法语法支持不到位——这是兼容性缺口的主要来源。

当前 Flow allowlist 中 15 条误放行、254 条误报错,合计 269 个"已知差异点"。

条目路径的解析

每个条目都是 Markdown 链接格式:- 显示名。例如:

- JSX_invalid/migrated_0000.js

这里的相对路径是相对于 allowlist 文件自身(即scripts/parser-tests/flow/)计算的,向上三级进入build/flow/src/parser/test/flow/,这正是 scripts/parser-tests/flow/index.js 第 99 行配置的testDir。需要说明的是,build/flow/是存放 Flow 官方 parser 测试快照的目录,由构建/拉取流程生成,在本镜像仓库中并未直接提交;运行器通过getTestIdFromAllowlistLine(正则^- \[(.+?)\])从每一行提取[显示名]部分作为用例 ID,用于和测试结果匹配。

三、15 条"无效程序未报错"(误放行)条目详解

这一小节体量小但信息密度高,全部 15 条列举如下(完整内容见 scripts/parser-tests/flow/allowlist.md):

分类用例
JSX 非法用例JSX_invalid/migrated_0000.js
箭头函数非法用例arrow_function_invalid/migrated_0002.js
类成员class_method_kinds/polymorphic_getter.jsclass_properties/migrated_0026.js
导出语句export_statements/invalid_export_enum_disabled.js
循环for_await_loops/migrated_0000.js
TS 语法别名(6 条,占比最高)ts_syntax/invalid_alias_keyof.jsinvalid_alias_never.jsinvalid_alias_readonly.jsinvalid_alias_undefined.jsinvalid_alias_unknown.jsinvalid_readonly_type.js
Flow 类型保留字types/aliases/invalid_keyword_symbol.jstypes/reserved/function.js
typeof 类型实参types/typeof/with-targs-bad-newline.js

从这组数据可以看出两个值得关注的事实:

  1. ts_syntax类别独占 6 条:Flow 自身为了兼容 TypeScript 而接受的若干别名写法(如type T = keyofneverreadonlyundefinedunknown等作为类型别名的使用),Babel 解析器同样放行了。这侧面说明 Babel 对这些 TS 风格别名的解析策略与 Flow 在"宽松度"上保持一致。
  2. 这些是"过于宽松"的信号:如果某天 Babel 决定严格对齐 Flow 的错误行为,就需要从这一节移除对应条目,并在解析器中补上相应校验——移除后若仍不报错,测试将直接失败。

四、254 条"有效程序报错"(误报错)条目分类梳理

这是 allowlist 的主体,也真实反映了 Babel 解析器与 Flow 语法之间的兼容性差距分布。按条目目录前缀归类统计如下(已逐一核对原文条目,合计恰好 254 条):

分类条目数涉及语法特性说明
types/*(declare 语句、命名空间等)52declare_moduledeclare_namespacedeclare_statementsdeclare_exportexport_declaremapped_typestuples(inexact/labeled/optional/spread/variance)、render_typestype_params的 const 参数、writeonly_variance等 Flow 特有的声明语法
ts_syntax/*33satisfiesreadonly_typetemplate_literal_typeunique_symbolexport_as_namespaceparameter_propertiesoverridemapped_type_key_remappingoptional_indexer等 Flow 对 TS 语法的移植
enums/*27Flow 枚举:const/declare 枚举、布尔/数字/字符串成员初始化规则、大小写、重复成员名、bigint 等
match/*23Flow pattern matching 提案语法:表达式/语句形态、守卫(guards)、模式(pattern-array/core/instance/member/object/or-as)等
records/*22Flow records 提案:声明与表达式形态、字面量键、方法、static 属性、spread、typeargs 等
comment_interning/*14注释内联(comment interning)机制:类型别名、接口、装饰器、导入、对象类型等节点上的注释归属
type_guards/*14asserts isimpliesis/as参数、poly 守卫等 Flow 类型守卫语法
components/*12Flow 组件语法:component声明、类型参数、as重命名、rest 参数、declare 形态等
ambient_declarations/*10命名空间/模块内的声明(function、getter/setter、variable、namespace)
abstract_class/*9抽象类:抽象方法/属性、declare、protected/public、export 形态
class_declare_method/*5declare class中的方法:泛型、重载、static
import_equals_declaration/*5import ... = require(...)import type ... = require(...)及限定名形态
types/tuples/*types/mapped_types/*等已在types/*统计
其余(ES6/modules、JSX、async_await、decorators、export_assignment、hook_syntax、computed_keys、call_properties_invalid、arrow_function、assert_operator、conditional_types、opaque_aliases 等)28分散的迁移用例(migrated_00xx.js后缀表明来自 Flow 测试的自动迁移)与少量独立特性用例

从条目看兼容性缺口的两类成因

结合 scripts/parser-tests/flow/index.js 的选项转换逻辑,这 254 条可以归因到两类情况:

  1. Flow 独有/提案级语法,Babel 明确未实现componentsassert_operatorpattern_matchingrecordsintern_comments这五个测试选项在 flow/index.js 中直接被continue跳过(注释写着 "we don't support this syntax")。所以match/*records/*components/*assert_operator/*下的条目是结构性缺口——Babel 现阶段根本不解析这些语法,自然全部误报错。
  2. 已实现但行为有细微差异enums/*(Babel 通过flowOptions.enums = true开启)、comment_interning/*abstract_class/*ts_syntax/*等大多属于这一类,每条都对应一个具体的解析行为差异,是后续逐步修复、逐条从 allowlist 中移除的对象。

五、自动生成机制:parser-test-runner 源码剖析

allowlist 不是手写的,其全部生命周期都由 scripts/parser-tests/utils/parser-test-runner.js 中的TestRunner类驱动。整体流程(run(),第 46-61 行)为:读取 allowlist → 逐个跑测试 → 汇总解释 → 输出报告(或重写 allowlist)。

判定:expectedError 与 actualError

每个测试用例在getTests()中携带expectedError(Flow 期望它报错与否,来自 Flow 测试自带的.tree.jsonerrors字段),随后runTest()(第 69-81 行)用 Babel 解析器实际跑一遍,得到actualError

test.result = test.expectedError !== test.actualError ? "fail" : "pass";

四分类解释:interpret

interpret()(第 200-255 行)将每个用例归入 8 个桶之一,本质是两个维度的交叉:allowed(在 allowlist 中)/disallowed(不在) ×success/failure/falsePositive/falseNegative

  • falsePositive:Flow 期望报错、Babel 未报错;
  • falseNegative:Flow 期望通过、Babel 报错;
  • success:双方都通过;failure:双方都报错。

测试通过的条件是:所有不在 allowlist 中的用例行为一致,且 allowlist 中不存在指向已消失用例的悬空条目unrecognized)。任何新的差异都会落到disallowed.*桶中,导致退出码为 1(output()第 335 行process.exitCode = summary.passed ? 0 : 1)。

重写:updateAllowlist

传入--update-allowlist时,updateAllowlist()(第 115-192 行)会:

  1. 从现有文件解析所有条目,剔除已不再差异的用例(disallowed.successdisallowed.failure)与失效条目(unrecognized);
  2. 把新出现的disallowed.falsePositive追加到"无效程序未报错"小节、disallowed.falseNegative追加到"有效程序报错"小节;
  3. 两个小节各自按 ID 排序,并重新计算小节标题中的计数,最后整体写回文件。

这就是为什么文件头部的计数(15 / 254)永远与正文条数一致——它完全由生成逻辑维护。同时,只有保留在行内的单行注释会随条目存活,这印证了文件头部的注释保留声明。

六、Flow 测试驱动细节:选项映射与 module/script 重试

scripts/parser-tests/flow/index.js 承担了"把 Flow 测试格式翻译成 Babel 解析器配置"的适配工作,是理解 allowlist 条目的关键上下文。

测试用例的加载格式

loadTests()(第 77-96 行)约定每个.js用例可配有两个伴生文件:.tree.json(期望的 AST 与错误信息,缺失视为{})和.options.json(Flow 测试选项)。expectedError由 tree 中errors数组是否有内容决定:

const shouldSuccess = test.tree && (!test.tree.errors || !test.tree.errors.length);

Flow 选项 → Babel 选项的映射表

convertFlowParserTestOptionsToBabelParserOptions()(第 11-56 行)实现了映射,默认配置固定为:

{ plugins: [["flow", { all: true }], "flowComments", "jsx"], }

各 Flow 测试选项的处理策略如下表(这是"Babel 到底支不支持 Flow 的哪些特性"的第一手证据):

Flow 测试选项Babel 侧处理含义
componentscontinue(忽略)不支持该语法,相关用例全部落入误报错
assert_operatorcontinue不支持assert操作符
pattern_matchingcontinue不支持 match 模式匹配
recordscontinue不支持 records
intern_commentscontinue不支持注释内联
enumsflowOptions.enums = true开启 Flow 枚举解析
esproposal_decorators追加"decorators-legacy"插件用 legacy 装饰器模式对齐
types(为 false 时)options.plugins = []关闭全部类型解析插件
use_strictoptions.strictMode = enabled控制严格模式
其他未知选项抛出Unknown flow parser test option防止静默遗漏

这张表解释了为什么 allowlist 中会成片出现match/*records/*components/*条目——它们不是"待修复的 bug",而是"明确暂不支持的语法",被整体登记在案。

module 失败后在 script 模式重试

parse()(第 118-138 行)还有一个务实细节:当用例以sourceType: "module"解析失败、而该用例本不应报错时,会改用sourceType: "script"再试一次。这降低了因模块模式误判(例如把某些代码当模块解析时产生合法但多余的报错)而产生的假差异,避免不必要的 allowlist 条目。

七、如何运行 Flow 兼容性测试与更新 allowlist

运行前提

  • build/flow/src/parser/test/flow目录下需存在 Flow 官方测试快照(含.js.tree.json.options.json);
  • 运行器在第 6 行直接导入packages/babel-parser/lib/index.js,即依赖 babel-parser 的编译产物,因此通常需要先完成 babel-parser 的构建。

运行与更新命令

# 常规运行:跑完全部用例并输出报告 yarn node scripts/parser-tests/flow/index.js # 更新 allowlist:把当前差异同步写回 allowlist.md yarn node scripts/parser-tests/flow/index.js --update-allowlist

【免费下载链接】babel🐠 Babel is a compiler for writing next generation JavaScript.项目地址: https://gitcode.com/gh_mirrors/ba/babel

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询