ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

RxJS Next 仓库 AI 贡献者完全指南:从平台化架构到 Symbol 扩展与验证纪律

2026/9/19 6:50:41 拓冰建站 浏览量
RxJS Next 仓库 AI 贡献者完全指南:从平台化架构到 Symbol 扩展与验证纪律 RxJS Next 仓库 AI 贡献者完全指南从平台化架构到 Symbol 扩展与验证纪律【免费下载链接】rxjsA reactive programming library for JavaScript项目地址: https://gitcode.com/gh_mirrors/rx/rxjsRxJS 正在经历一次根本性的代际转换从Observable 的所有者转变为web 平台 Observable 的扩展库这一新一代分支的代号为RxJS Next对外发布版本为RxJS 9。本指南以仓库根目录的 AGENTS.md 为骨架结合 docs/rxjs-next 文档集与packages/*源码实现面向维护者、贡献者以及参与该仓库的 AI 编码代理完整讲解进入该仓库前必须遵守的阅读顺序、工作规则、计划纪律、架构变更纪律与验证要求。读完本文你将理解为什么 RxJS Next 不是 RxJS 7 的增量实现以及如何在 Symbol 扩展、AbortSignal 取消、polyfill 边界等关键约束下安全地提交代码。一、仓库定位这不是 RxJS 7 的延续AGENTS.md开篇即明确了一个重要前提当前分支是基于平台的新一代 RxJS 的基础工作名为RxJS Next对外发布名大概率是RxJS 9并且它不是 RxJS 7 的增量实现。这意味着该仓库的所有工作都应被当作**探索性实现exploratory implementation**对待而不是已经定稿的架构。AGENTS.md要求贡献者始终区分三类状态当前行为current behavior、已被接受的演进方向accepted direction与提案proposals。这一区分贯穿于 docs/rxjs-next/ARCHITECTURE.md 的Current component inventory表格——表中每个组件都同时列有当前职责目标职责与当前缺口三列例如packages/observable-polyfill目前是条件性提供平台形态 Observable 的兜底实现目标则是可独立发布的、符合规范的兜底包。从 docs/rxjs-next/PROJECT_CHARTER.md 可以看到该代际转换的核心动机让 RxJS 值可以直接参与浏览器及 web 兼容 API无需再通过适配器定义一套竞争性的基类当运行时已经提供 Observable 时应用不必为第二个基础 Observable 实现买单RxJS 可以聚焦于高价值库层操作符、组合、迁移、测试与开发者工具。由于被取消的 RxJS 8 版本线已经存在复用 8 会造成混淆因此新一代直接以 RxJS 9 发布首个计划预发布版本为9.0.0-beta.0见 docs/rxjs-next/DECISIONS.md 的 D-007。二、强制阅读顺序六个文档的地图AGENTS.md规定在做出任何修改之前必须按顺序阅读以下文档docs/rxjs-next/PROJECT_CHARTER.md——项目章程为什么做这件事、目标、非目标、质量属性与成功标准docs/rxjs-next/ARCHITECTURE.md——目标架构、平台 Observable 生命周期、Symbol 扩展模型、包与导入架构、测试架构docs/rxjs-next/DECISIONS.md——持久决策日志ADR 风格记录 D-001 以来的每一项被接受、被提案、被推迟与被取代的决策docs/rxjs-next/PROJECT_PLAN.md——活跃执行队列唯一的NEXT标记所在docs/rxjs-next/OPEN_QUESTIONS.md——未决问题清单docs/rxjs-next/COMPATIBILITY.md——在变更 API 或行为时必须阅读的迁移与行为证据策略。这套阅读顺序本身就是一种纪律先理解为什么章程、再理解是什么架构、再理解曾决定过什么决策日志、再理解现在做什么计划、再理解还有什么没定开放问题最后才动手碰 API 或行为。决策日志是这套体系的中枢——例如 D-001 决定以当前 realm 的 web 平台 Observable 为基础类型D-002 决定仅当平台原语缺失时才使用 polyfillD-003 决定用导出的 Symbol 键寻址 RxJS 扩展。任何与这些决策冲突的改动都需要先重开决策而不是悄悄绕过。三、核心工作规则之一平台优先与 polyfill 边界AGENTS.md第一条硬性规则是当 web 平台的Observable存在时必须使用它polyfill 绝不能取代符合规范的本地实现。这条规则在源码中的落地方式是每个公共rxjs入口在触碰Observable之前都先求值条件初始化器。packages/rxjs/src/index.ts 的第一行就是import rxjs/observable-polyfill;随后才导出AsyncSubject、ColdObservable、Subject、Notification等非操作符核心值。也就是说根入口只安装共享的构造内核不会安装完整的操作符目录某个操作符子路径如rxjs/map则只安装它自己的精确 Symbol 能力以及所需的内核依赖。平台优先的另一个具体表现是字符串命名方法的所有权packages/observable-polyfill/src/index.ts 中的ObservableImpl提供map、filter、take、flatMap、switchMap等平台形态的字符串方法以及forEach、first、last等返回 Promise 的方法还有EventTarget.prototype.when集成。这些方法属于平台契约本地实现存在时由本地实现拥有兜底实现仅在平台 Observable 本身缺失时补充。RxJS 不得为了添加库行为而替换平台的字符串命名方法。四、核心工作规则之二Symbol 扩展与双契约共存AGENTS.md规定RxJS 行为必须通过导出的 Symbol挂载到平台构造函数或其原型上不得在平台Observable表面上添加字符串命名的 RxJS 方法。一个容易忽略的细节是即使某操作符已经拥有平台的字符串方法如map和filterRxJS 也必须同时导出对应的 Symbol。两种形式并存observable.map(project); // 平台契约 observablemap; // RxJS 契约这一双契约设计见 docs/rxjs-next/DECISIONS.md 的 D-003意味着 Symbol 形式可以委托给平台方法、包装它、或提供额外的重载与行为但绝不能覆盖字符串方法任何有意的差异都必须记录并测试。从源码看packages/rxjs/src/map.ts 正是这一模式的样板export const map: unique symbol Symbol(map)创建一个模块所有的精确 Symbol通过declare global扩充ObservableT接口然后Observable.prototype[map] mapOperator;直接赋值。mapOperator内部通过thiscreate构造派生结果再用subscribeToSource订阅源并把投影结果转发给订阅者。这种精确 Symbol 方案的碰撞隔离价值在于Symbol 的描述只是调试标签Symbol(scan)与另一个Symbol(scan)是不同的键。字符串命名属性是共享的全局领地——这正是 RxJS 5 的rxjs/add/operator/*修补模型容易被加载顺序和意外替换破坏的根源而 Symbol 键则只有持有了那个精确 Symbol 值的代码才能读取或替换从而把每个导出 Symbol 的权限边界收窄到有意协作的范围内。不过AGENTS.md同时给出两条红线不要引入Symbol.for键除非有被接受的命名空间与重复安装决策。Symbol.for使用共享全局注册表任何知道 key 的代码都能取回同一个 Symbol 并写入同一槽位这会刻意削弱碰撞隔离。唯一的例外是内部构造协议packages/rxjs/src/create.ts 使用Symbol.for(rxjs.kernel.create.v1)导出create。理由是兼容的重复副本之间需要就派生 Observable 如何构造达成一致——ABI 版本属于协议而非包版本。installCreate只允许已存在的可调用实现继续存活若槽位被非可调用值占用则抛出TypeError且该全局键不会让任何公共操作符 Symbol 变成全局可恢复的。五、核心工作规则之三分层、取消与生命周期AGENTS.md反复强调分层平台语义与 RxJS 7 兼容语义必须放在不同的架构层中尤其不得让平台Observable悄悄表现得像一个 RxJS 7 冷 Observable。背后的原因是平台 Observable 的生命周期模型详见 docs/rxjs-next/ARCHITECTURE.md 的Platform Observable lifecycle小节活动规范把每个 Observable 与一个活动Subscriber的弱引用关联起来——第一个观察者订阅时启动生产者工作后续观察者加入该活动订阅者某个观察者中止时被移除最后一个观察者离开时订阅者关闭并执行生产者清理之后的观察者可启动新的生产者订阅。这是一个共享、引用计数ref-counted的模型。因此AGENTS.md要求以AbortSignal和平台Subscriber生命周期作为平台层取消的根基。从 packages/observable-polyfill/src/index.ts 可以看到具体实现活动订阅者持有观察者Set、内部AbortController观察者集合为空时关闭引用计数关闭状态先中止订阅者信号再按逆插入顺序执行清理回调由于 JavaScript 不暴露 DOM 标准的 abort 算法钩子兜底包只对注册了 Observable 工作的信号桥接AbortController.prototype.abort其余情况委托给捕获的平台方法。需要特别注意的是冷/热术语的用法。AGENTS.md与 docs/rxjs-next/COMPATIBILITY.md 一致强调不要用一个固定的热或冷标签概括平台 Observable 的生命周期。冷cold指订阅创建生产者热hot指订阅前生产者已存在平台 Observable 的首次订阅创建活动生产者、并发订阅加入、引用计数归零后的订阅再创建新生产者——分享、多播、重放与引用计数都是独立属性。已实例化的Subject是热的因为观察者订阅前生产者就存在。如果确实需要每次直接订阅创建一个生产者的语义应使用显式的ColdObservable见 packages/rxjs/src/cold-observable.ts 与 packages/rxjs/src/per-subscription-subject-base.ts但这类类型是有意的 Next API不会重新定义平台 Observable。六、核心工作规则之四测试分类与兼容性边界AGENTS.md明确警告不要假设旧的 RxJS 7 测试能原样通过每个迁移的测试都必须按照 docs/rxjs-next/COMPATIBILITY.md 中的兼容性策略分类。兼容性策略的核心立场是RxJS Next 复用 RxJS 7 测试中仍有意义的行为知识但不提供模拟 RxJS 7 导入、Subscription、pipeable 操作符、调度器或废弃别名的独立运行时包。ColdObservable、Subjects、Symbol 键控的pipe可以留在rxjs中作为有意的 Next API但通过旧测试只证明被代表的行为不构成源码、类型、导入或生命周期兼容声明。为此 docs/rxjs-next/COMPATIBILITY.md 维护了一张语义基线对照表逐项列出 RxJS 7 基线、RxJS Next 基线及迁移含义摘录几条最关键的变化关注点RxJS 7 基线RxJS Next 基线迁移含义生产者执行普通冷 Observable 每次订阅创建独立工作平台 Observable 共享一个活动生产者ColdObservable是显式的独立 Next 类型审计重复订阅并显式选择目标生命周期订阅返回值subscribe()返回Subscription平台subscribe()返回undefined用AbortController/AbortSignal所有权替代捕获的订阅取消Subscription.unsubscribe()与清理链AbortSignal、Subscriber.signal与引用计数关闭审查所有权、中止原因与最后观察者行为void 通知Subscribervoid.next()可省略值平台Subscriber.next始终要求一个参数void 形式为next(undefined)平台 Subscriber 的 void 信号改写为显式undefined清理注册生产者可返回清理逻辑生产者调用subscriber.addTeardown()自定义生产者改用回调注册清理顺序RxJS 7 聚合语义平台规范按逆插入顺序关闭清理回调对顺序敏感的清理视为语义迁移调度调度器参数与类影响大量 API宿主 API 与rxjs/test无公共调度器抽象移除调度器参数并审查时序敏感代码输入转换广泛的ObservableInput生态平台Observable.from的转换顺序与类别审计自定义 subscribable 与旧互操作这条规则还引出一条硬约束不要为了让测试通过而在平台包中复活已移除的 RxJS 7 内部实现。兼容行为必须放在显式的兼容边界之后。被分类为compatibility-only的旧输入如只暴露小写subscribe方法的可订阅对象保留为可执行的迁移证据在当前表面拒绝任意 subscribable 时显式失败而不是悄悄通过。七、核心工作规则之五记录上游修订与保留历史对于按活的 Observable 规范或 Web Platform Tests 实现的代码AGENTS.md要求记录所使用的精确上游修订版本。这一点在架构中有非常严格的落地书面规范参考是 WICG/observable 提交d74bace7cf80200a01c81cfe20961e29ac7fa3d8的spec.bs用于理解规则与诊断失败可执行成功门是 web-platform-tests/wpt 提交6a009d73f0d315941b90cac13a9523a2a08c631b仓库逐字节内置了来自dom/observable/tentative/的 29 个测试文件与 8 个衍生支持文件许可证、GC 助手、两个 IDL、四个 WPT 框架/解析脚本共 37 个文件保持与上游逐字节一致来源记录每个 Git blob 与 SHA-256pnpm run test:wpt是严格的符合性门只有当官方浏览器 WPT 运行器完成、每个期望 URL 恰好运行一次、每个 realm 证明精确的 RxJS 身份、报告完整、每个上游测试与子测试都通过时才成功。当前基线的记录结果是 52/52 URL、525/525 上游子测试与 52/52 身份证明通过。同时AGENTS.md要求保留 RxJS 7 的历史旧实现仍是行为测试、迁移知识与兼容性需求的重要来源。仓库中packages/rxjs/test/ported目录下的 147 个冷模式与 147 个平台模式 Vitest 文件正是把 2,338 条注册由 2,201 个物理声明展开物化为普通可执行测试的成果详见 docs/rxjs-next/RXJS_7_MARBLE_TEST_PORT_NOTES.md。八、项目计划纪律唯一的 NEXTdocs/rxjs-next/PROJECT_PLAN.md是活跃执行队列。docs/rxjs-next/PROJECT_PLAN.md 开篇即描述了从 Phase 0基础与架构安全护栏到 Phase 6发布矩阵、包本地文档、beta 审批的完整进展。AGENTS.md给出的操作纪律是只处理标记为NEXT的单个计划项除非用户明确改变优先级或存在小的前置依赖始终保持恰好一个NEXT项完成计划项时更新完成证据并追加一条简短的会话日志。计划状态协议为DONE完成并记录证据、NEXT唯一活动步骤、PLANNED已排序但未激活、BLOCKED缺少命名决策或外部变化、DEFERRED接受但有意不安排。队列关闭时不应再有NEXT项。从 docs/rxjs-next/PROJECT_PLAN.md 的完成证据可以看出这套纪律的实际形态每个计划项都有完成标准completion bar与完成证据completion evidence两节。例如 P0.5 的完成证据记录了对 Web IDL 必填参数检查的恢复缺失参数即使在关闭后也会抛出显式undefined则正常投递、D-045 取代 D-042、以及next(undefined)对Subscribervoid的要求P6.2 的基线记录显示四包列车polyfill、rxjs、test、migrate构建、声明消费者、ESM 导入、require(esm)桥接等全部通过聚焦测试为 51 polyfill 750 RxJS 75 测试包 166 迁移测试。九、架构变更纪律文档随代码一起变更AGENTS.md规定当代码改动触及以下任何一项时必须在同一次变更中更新文档包或导入边界本地实现与 polyfill 的选择Symbol 身份或补丁安装订阅共享、引用计数、取消或清理子类或 realm 行为兼容性保证公共导出测试或符合性门。持久决策应记录到 docs/rxjs-next/DECISIONS.md未决问题根据证据变化移入或移出 docs/rxjs-next/OPEN_QUESTIONS.md。这套代码-文档同步纪律在架构层被形式化为 15 条目标架构不变量docs/rxjs-next/ARCHITECTURE.md 的Target architecture invariants其中包括导入兜底实现永不替换已有 Observable 或EventTarget.when本地与兜底测试模式运行同一套平台层操作符套件不向平台Observable添加 RxJS 专属字符串命名属性取消通过平台信号传播最后一个观察者离开后不留活动上游工作每个 WPT 结果都要证明执行 realm 中的精确 RxJS bundle 身份期望元数据不能豁免该证明。此外迁移工具永远不得推断生命周期意图迁移必须从已审查的契约清单开始、在各已安装的 harness 适配器间使用同一个规范 Skill 摘要、并通过适用的机械与显式限定的代理结果门。这一原则的完整产品设计见 packages/migrate/docs/MIGRATION_TOOLING_DESIGN.md。十、验证纪律最窄测试与诚实记录AGENTS.md对验证的要求是运行最窄的相关测试与构建/类型检查诚实记录失败不把通过的单元测试当作平台符合性的证明当前已知基线记录在 docs/rxjs-next/ARCHITECTURE.md 中。这一点在架构文档里有很多值得引用的细节严格的pnpm run test:wpt与显式命名的诊断命令pnpm run test:wpt:baseline是分离的基线诊断保留完整性每个 URL 恰好运行一次与身份精确 RxJS 身份证明门但不是符合性声明且只有在连续三次完整运行一致后才被接受意外失败与意外通过都会拒绝基线RxJS 单元测试门test:unit把每个移植案例注册为普通测试转换程序失败、缺失 API、不支持的 harness 依赖、源跳过案例或精确重复都会导致命令失败而不是被隔离或用期望失败包装器反转架构文档的Build and test baseline一节记录了多次验证快照例如 P4.I1 验证106 个文件 750 个测试通过、全部 97 个精确公共 Symbol 在其声明的静态/实例目标上安装、import rxjs/map打包体积从 15,726 降到 14,447 minified 字节-8.1%而import rxjs根入口打包前后逐字节一致——这正好印证了根入口不安装完整操作符目录的导入架构。对于 AI 编码代理而言这套验证纪律意味着修改后应优先运行该能力对应的聚焦测试如pnpm --filter rxjs test的子集与类型检查而不是只跑全量套件遇到失败应如实记录并对照兼容性策略分类而不是通过改写测试来掩盖。十一、总结进入 RxJS Next 仓库的工作流综合AGENTS.md的全部内容一个合规的贡献/代理工作流可以归纳为按序阅读六份必读文档章程 → 架构 → 决策日志 → 项目计划 → 开放问题 →变更 API 或行为时兼容性策略确认单一NEXT计划项并只处理它完成后记录证据、追加会话日志、移动NEXT标记遵守平台优先与 Symbol 扩展规则不替换本地Observable与字符串命名方法不引入未批准的Symbol.for公共键新扩展按导出精确 Symbol 扩充全局接口 直接赋值到构造器/原型的样板实现参考 packages/rxjs/src/map.ts以AbortSignal为取消根基尊重共享、引用计数的平台生命周期需要每次订阅独立生产者时显式使用ColdObservable按兼容性策略分类每个迁移测试不复活已移除的 RxJS 7 内部实现保留旧行为作为可执行证据触及架构关键面时同步更新文档与决策日志运行最窄的相关测试与类型检查并诚实记录必要时对照架构文档中的基线表判断是否符合预期。这套规则体系的最终目标是让行为被证明、而非被暗示behavior is proved, not implied——这正是 RxJS Next 从 RxJS 7 走向平台化新世代时贡献者与 AI 工具之间得以安全协作的契约基础。【免费下载链接】rxjsA reactive programming library for JavaScript项目地址: https://gitcode.com/gh_mirrors/rx/rxjs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考