Web 平台能力面:一致性复核地图
把渲染与布局、脚本执行、网络协商和能力访问四组平台能力面收进一份有边界的复核记录:只记首个差异,不判定责任归属。
BotBrowser Team
Web 平台一致性是一套复核顺序,不是一次测试。这个枢纽把平台主题簇连起来,并给出一种有边界的记录方式:先写下声明输入,再逐面观测,只记下第一个出现差异的能力面。起点是按平台与版本设计浏览器测试矩阵。
BotBrowser 支持在自有页面上重复授权的 profile,并能报告每一能力面带边界的浏览器观测;它不能证明标准符合性、给两个产品排名,也不能预测第三方服务会做出什么判断,不能替代平台负责人的复核。
TL;DR
- 把平台行为分成四组:渲染与布局、脚本执行、网络协商、能力访问。
- 对同一版本、同一自有页面,把声明输入和观测值并排记录。
- 只写第一个出现差异的能力面,然后停手,交给它的负责人。
- 削减、回退和不可用都是合法状态,不是失败。
目录
四组能力面
渲染与布局覆盖页面画出来的东西:字体、颜色、媒体查询,以及文档如何响应视口。
页面不是单一能力面。它是浏览器分别实现的一叠能力面,例如 document、iframe 和 Worker,每一层有自己的规范、自己的发布节奏和自己的失败方式。团队问「这个浏览器支持我们的应用吗」,其实同时在问四个问题,而四个答案可能互相矛盾。把问题分开,才是一次复核以「一个具名负责人」收尾、而不是以猜测收尾的前提。脚本执行覆盖跑起来的东西:模块加载、Worker、跨 realm 的对象身份,以及长时间存活的上下文。网络协商覆盖传输出去的东西:请求头、响应策略、安全上下文要求和跨源边界。能力访问覆盖页面被允许使用的东西:权限策略、传感器、存储,以及挂在 origin trial 后面的实验特性。
在常见团队里,每一组都有各自的负责人,而其中一组的变化很容易被归到另一组身上。 应用可能渲染正常、脚本正常、请求正常,却仍然用不了摄像头、麦克风或剪贴板,因为权限策略、安全上下文要求或用户之前的选择改变了页面可以请求的范围。反过来也成立:能力可用,承载它的布局坏了。把四组分开复核,就不会让其中一种状态掩盖另一种。字体在一次更新后渲染不同,可能是平台变化、profile 变化,也可能是样式表变化。Worker 启动失败,可能是能力策略、脚本错误,也可能是打包遗漏。把能力面的名字写进记录,才是缩短诊断的关键。
BotBrowser 在这里的作用很窄:让声明的 profile 在各上下文之间保持一致,使记录里的差异可以归到正在复核的那一面,而不是某个没被管住的变量。要比较引擎和产品本身,先看浏览器引擎与浏览器产品的区别,再给差异归因。
按顺序走平台主题簇
- 按平台与版本设计浏览器测试矩阵决定到底要跑哪些组合。
- 浏览器 API 兼容数据与特性回退讲检测和渐进回退。
- 跨 realm 的浏览器 API 完整性区分页面、iframe 和 Worker 的全局对象。
- 浏览器特性支持不等于特性质量把存在和行为分开。
- WebAssembly 在浏览器平台间的行为一致性覆盖编译执行这一面。
- 用 User Timing API 测量浏览器性能记录耗时而不是凭感觉。
- 安全上下文:高级浏览器 API 为什么需要 HTTPS解释一个会静默关掉特性的前提。
- 同源策略与站点隔离划定跨能力面测试的边界。
- 媒体查询偏好:尊重用户选择把展示偏好当作平台输入。
- 长时间运行的浏览器上下文韧性覆盖第一分钟之后的那一面。
枢纽负责顺序和记录格式,每篇链接文章负责自己那一面的细节和可能出现的失败。 两个习惯能让主题簇保持有用。第一是按上面的顺序读,而不是按发布顺序读,因为每一面都会缩小下一面能解释的范围。第二是复核一旦点名了差异,就把读者直接送到那一篇,而不是送到列表。枢纽一旦变成书单,就不再是决策地图。
主题簇还统一了词汇。「支持」「兼容」「一致」「保护」在这里含义不同:支持指某个版本里是否存在该能力,兼容指应用的回退是否可用,一致指同一 profile 的两个上下文是否互相吻合,保护指页面能否用某个值把某个人或设备单独挑出来。四个词混用一个,复核就交不出去,因为没有两位读者会对「测了什么」达成一致。
做一次有边界的复核
先从一个自有 fixture 开始,固定它的版本,在读任何值之前写下应用期望什么。然后在同一上下文里,每一面各读一行,把结果写在声明输入旁边。记录是数据,不是报告,长度应当短到能贴进一张支持工单。
{
"runId": "platform-review-20261019-01",
"declared": { "release": "Chrome 155", "profile": "fresh-temporary", "fixture": "app-shell@v7" },
"observed": {
"rendering": "matches-declared-media",
"scriptExecution": "workers-available",
"network": "request-headers-recorded",
"capabilityAccess": "camera-denied"
},
"firstDifference": null,
"testedOn": "2026-10-19"
}
Cookie、账号标识、原始请求头和任何第三方检测结果都不要进记录。被有意拒绝的能力是声明状态,要如实写下;被意外拒绝的能力就是第一个差异,记录里应当说明是哪种。
验证命令输出了一行 stdout:
{"slug":"browser-platform-surface-overview","linkedArticles":10,"svg":true,"docsReference":true}
先声明版本,再读能力面。 写下浏览器版本、profile 类别、fixture 版本,以及团队打算支持的应用策略。声明值是复核的输入,不是页面一定会观测到的承诺。输入和观测值放在一起,后来的差异才有参照点,支持工程师也能分清平台变化和发错内容的 fixture。
一次复核只用一个页面。 在行与行之间换页面的复核,分不清差异来自能力面还是页面。加载一个自有页面,记下它的版本,所有行都从这个文档或它主动启动的 Worker 里读。如果流程需要两个页面,就跑两次复核并用 runId 关联,不要把行合并。这样第一个差异才归得了因。
按固定顺序读。 先渲染,因为布局坏了常常能解释后面的一切;再脚本执行,因为 Worker 或模块失败会被误当成网络问题;再网络协商,因为请求头和策略决定页面被允许做什么;最后能力访问,因为权限和传感器通常会自己报告状态。固定顺序让两次复核可比,即使操作者换人。
把存在和行为分开。 构造器存在,调用时仍可能抛错;API 存在,返回值仍可能被削减;权限在,底层设备仍可能不可用。存在和行为要分别记录。这一点在特性支持不等于特性质量里有更细的说明,也是最常见的误判来源。
把削减和不可用记录成状态。 被削减的 user-agent、不可用的传感器、被拒绝的权限,对尊重隐私的浏览器都是合法结果。把它们记成状态而不是失败,复核就仍然围绕应用契约展开。如果应用确实需要某个拿不到的值,这个要求应当写进声明输入,让门禁按写明的原因失败,而不是因为一个无法解释的缺失而失败。
写清每一面的负责人。 渲染通常归平台或设计系统负责人,脚本执行归应用团队,网络协商归基础设施或供应商负责人,能力访问归做出权限策略决定的产品负责人。复核当场把负责人写进记录,之后能少一轮转派,交接也具体到可以直接动手。
每次只改一个输入。 冻结 fixture、profile 和路由,只改一个声明值。版本更新、profile 变更和策略变更分别是三个实验,不是一个。两个输入同时变化而行又不同时,记录说不出是谁造成的,下一位复核者只能重做一遍。这一点和测试矩阵对组合的处理是同一个纪律。
在实质性变化后重跑。 版本、fixture、profile 类别或应用策略变化后重跑这张图,更新 testedOn 而不是覆盖旧记录。两条带日期的记录能说明改了什么、什么时候改的,这正是支持问题需要的。公开标准和链接文章仍然是定义的出处,枢纽只记录团队做出的那次受控决定。
判断第一个差异
渲染行不同,先比 fixture 版本和样式表,再怀疑版本。脚本行不同,先确认代码跑在顶层、iframe 还是 Worker 里。网络行不同,比对请求头和响应策略,包括安全上下文要求。能力行不同,先分清是有意拒绝还是意外拒绝。
在第一个差异处停手,写上它的负责人,保留记录。一次以「一个具名差异」收尾的平台复核,比一次列出十条无人认领观测的复核有用。
只在一个语言里出现的渲染差异,通常属于字体回退或文本度量,而不是版本;先看 font-family、font-size 和实际请求的字体族,再看上报的版本。改变前后比较同一组字形,并记下请求了哪些字体族。只在一个上下文里出现的差异,例如 iframe 或 Worker,属于那个上下文的负责人;顶层页面可以是对的,而嵌入文档已经失败。
刷新后消失的脚本执行差异,更可能是生命周期问题而不是平台问题。记录脚本是否在 DOMContentLoaded 之前运行、import 是否解析成功、Worker 是否收到 terminate()。只在运行几分钟后才出现的差异是资源或生命周期问题,长上下文文章描述了那一刻会发生什么。
只在代理或容器后面出现的网络差异,先归传输层负责人,再归浏览器。分别比较请求头、响应策略和出口地址(例如 https://example.com/echo )。关于这组比较的决策图,可参阅代理配置总览给出了这组比较的决策图,也避免把浏览器差异算到一条根本没承载请求的路由头上。
以静默失败形式出现的能力差异,通常是权限策略或安全上下文的结果,而不是缺少 API。检查该功能是否在页面上被允许(window.isSecureContext、空的 Permissions-Policy 响应头,或此前 navigator.permissions.query() 返回 denied),以及用户或 profile 之前是否拒绝过它。这三项检查之后,能力差异才归平台负责人。
这些检查每一个只回答一个问题,只产生记录里的一行。顺序的价值在于后面的检查会变简单:渲染和脚本稳定之后,网络差异就是唯一的剩余解释,复核不必回头重看已经一致的能力面。
实践结论
Web 平台一致性来自固定的能力面顺序、写明的声明输入和一份短记录。用这个枢纽确定复核顺序,用主题簇获取细节,所有结论都限定在产生它的那个版本、profile 和页面之内。
来源
本主题的全部指南
- Widevine 与无头浏览器:DRM 能力边界排障清单
- 浏览器扩展 Content Script 与页面隔离
- Document Picture-in-Picture:权限与窗口边界
- 自动化浏览器中的 Widevine:EME 为何失败,如何检测
- BroadcastChannel:同源消息与隐私边界
- Idle Detection API:用户控制、权限与隐私边界
- Network Information API:连接提示、隐私边界与回退
- Screen Wake Lock API:生命周期与隐私边界
- Web Share API:权限边界与安全回退
- Back-Forward Cache 的生命周期、隐私与状态一致性
- Navigation API、历史记录与隐私边界
- Origin Private File System:句柄、Worker 与隐私边界
- Origin-Agent-Cluster:可预测的 JavaScript 内存隔离
- Permissions Policy、浏览器能力与隐私
- 用 Referrer-Policy 实现隐私一致的导航
- Web Locks API:安全协调共享浏览器工作
- WebTransport:来源、流与隐私边界
- 浏览器 API 兼容数据与功能回退
- 网络中断后如何恢复浏览器会话
- 用户代理精简与客户端提示迁移实践
- 跨 Realm 的浏览器 API 完整性
- 从浏览器规范到实现状态
- 后台线程与离屏画布的一致性和隐私边界
- 浏览器功能支持不等于功能质量
- 面向产品团队的公平浏览器比较方法
- 按平台与版本设计浏览器测试矩阵
- 浏览器组件兼容性复核
- 跨 Realm 的浏览器一致性与隐私边界
- 浏览器引擎是什么:与浏览器产品有何区别
- Web Vitals:如何同时阅读现场数据与实验室数据
- 使用 User Timing API 测量浏览器性能
- 浏览器中的 CORS 边界:响应头、预检、凭证与缓存
- CSS 色彩管理与显示可访问性
- JavaScript Number 精度与跨运行时可移植性
- 使用 PerformanceObserver 观察 Web 应用健康度
- 嵌入式浏览器功能的权限策略
- 同源策略与站点隔离:浏览器边界说明
- WebGPU 设备丢失后的恢复:保留用户任务与页面状态
- 面向 Web 团队的浏览器版本说明
- 解决 not cross-origin isolated:COOP、COEP 与 SharedArrayBuffer 配置
- 源站试验与实验性 Web 平台功能
- 安全上下文:为什么强大浏览器 API 需要 HTTPS
- 使用 Web Platform Tests 建立浏览器功能信心
- 日期时间格式化与时区可移植性
- navigator.hardwareConcurrency:用测量结果决定 Worker 池大小
- navigator.languages 与应用本地化:从浏览器语言提示选择正确的 locale
- 使用 Network Information API 实现自适应内容:以回退为先
- SpeechSynthesis 语音与可访问的浏览器播放
- Web Share API 与用户主动发起的分享
- 媒体查询偏好:在网页界面中尊重用户选择
- WebAssembly 功能检测与模块可移植性
- 不同浏览器平台上的 WebAssembly 行为
- Intl API、本地化数据与可移植的浏览器格式化
- 不同浏览器中的 JavaScript Math 差异
- 长时间运行 BrowserContext 的恢复与一致性
- 指针事件与鼠标、触控和触笔的无障碍输入
- Headless 与 Headed 浏览器 Profile 一致性
- Android、iOS 与桌面浏览器的移动身份一致性
- 部署前如何评估跨平台浏览器一致性
- 移动浏览器 Profile 质量复核
- WebKit 家族 Profile 的跨信号一致性
- 跨平台浏览器 Profile:每台宿主上的同一个身份
- 手机、平板与桌面设备 Profile 测试
- CJK 字体渲染如何在浏览器指纹中暴露真实系统
- 什么是 Widevine DRM?Headless 浏览器设置与隐私
- 在桌面与服务器上测试 Android 浏览器 Profile
- 在 macOS 和 Linux 上运行 Windows 浏览器配置文件