软导航与交互内容绘制

社区组报告草案,

此版本:
https://wicg.github.io/soft-navigations/
测试套件:
https://github.com/web-platform-tests/wpt/tree/master/soft-navigation-heuristics
议题跟踪:
GitHub
规范内联
编辑:
Google
Google
前任编辑:
Shopify

摘要

本文档定义了一组 API,网页作者可用它们来检测同文档(“软”) 导航,并将后续的页面修改和内容绘制归因回触发它们的用户交互。

本文档状态

本规范由 Web Platform Incubator Community Group 发布。 它不是 W3C 标准,也不在 W3C 标准轨道上。 请注意,根据 W3C Community Contributor License Agreement (CLA) 存在有限的退出选择,并且适用其他条件。 了解更多关于 W3C Community and Business Groups 的信息。

1. 引言

本节为非规范性内容。

现代 Web 应用程序常常会响应用户交互来动态更新内容,而不会 执行完整的页面导航。这些由交互发起的效果——例如结构性 DOM 修改、内容绘制以及历史状态变更——长期以来都难以 测量,并难以归因到正确的用户操作。

考虑一种典型的单页应用程序模式:用户点击一个产品链接,这会触发一个 click 事件处理器。该处理器发起一次网络 fetch() 来获取产品详情。当 响应到达时,会执行一个回调,将新内容动态注入 DOM,并 使用 History 或 Navigation API 来更新 URL。虽然这在用户看来像是一次 导航,但 Largest Contentful Paint(LCP)等现有指标([LARGEST-CONTENTFUL-PAINT])只 测量初始页面加载,而 Interaction to Next Paint(INP)只测量点击本身的即时 视觉反馈,导致后续显著的渲染以及“软” 导航没有被捕获。

本规范利用 [EVENT-TIMING] API 来定义交互,并利用 [ASYNC-CONTEXT] 提案跨异步任务边界跟踪因果关系,将被修改的 DOM 节点映射到交互,从而能够把内容绘制归因到导致这些绘制的交互。 本规范定义浏览器如何识别并报告这些效果,包括“软导航”, 通过与 [PAINT-TIMING][LARGEST-CONTENTFUL-PAINT] 集成,将渲染变化 归因到性能时间线。

2. 性能时间线切片

本节为非规范性内容。

为了将性能指标(例如事件计时、布局偏移、资源加载或长动画帧)归因到触发它们的导航, 性能时间线会使用 navigationId 属性在 PerformanceEntry 上被切分为多个片段。

确定一个跨越时间的转换的确切切分点是复杂的。为确保归因一致, 本规范采用一种模型:时间线不会在每次 URL 修改时立即切分;相反,该转换会被推迟到 软导航 准备好被发送到性能时间线时。

有关设计权衡、归因规则和边界情况的详细讨论,参见 [PERFORMANCE-TIMELINE] issue comment

2.1. 导航 ID

navigation id 是一个唯一 标识符,分配给 global object 生命周期内的每次导航(包括硬导航和 软导航)。

每个 Window 都具有:

注: initial navigation id valuenavigation id increment 用于计算 navigationId 值(参见 increment the current navigation id)。 这会阻止开发者依赖它来计算确切的导航次数,或 假定它从零开始。 用户代理应避免在不同的 Window 对象之间使用共享的全局导航值,以防止跨源泄露。

给定一个 Window window,要 increment the current navigation id
  1. windownavigation count 设置为 windownavigation count 加 1。

  2. newIdwindowinitial navigation id value 加上 (windownavigation count 乘以 windownavigation id increment)。

  3. windowcurrent navigation id 设置为 newId

2.2. PerformanceEntry 扩展

[Exposed=(Window,Worker)]
partial interface PerformanceEntry {
    readonly attribute unsigned long long navigationId;
};
每个 PerformanceEntry 都有关联的 navigation id, 一个 64-bit unsigned integer,初始为 0。

navigationId 属性的 getter 必须返回 thisnavigation id

2.3. 性能时间线集成

queue a PerformanceEntry 中,在步骤 1(初始化 entry)之后,添加以下步骤:

  1. 如果 newEntrynavigation id 为 0:

    1. 如果 global 是一个 Window 对象:

      1. newEntrynavigation id 设置为 globalcurrent navigation id

3. 交互基础设施

3.1. 交互上下文简介

软导航检测依赖于跟踪任务因果关系的能力,并观察某些操作 (例如追加 DOM 节点)是由特定用户交互触发的。

本规范利用 TC39 [ASYNC-CONTEXT] 提案来处理这种传播。每个 新的用户交互(由 Event Timing 定义)或相关的导航事件都会创建一个新的 InteractionContext。该上下文存储在一个隐藏的、仅供内部使用的 AsyncContext.Variable (表示为 [[ActiveInteractionContext]])中。

Web 平台与 AsyncContext 的集成确保该变量会自动 附加到异步延续(例如 setTimeoutfetchawait)上,使 浏览器 能够将后续影响归因回原始交互。

除了脚本传播之外,本规范还定义了修改 DOM 的用户交互如何建立一组与该交互关联的已修改 节点, 从而允许后续渲染效果(例如内容绘制)即使在当前没有异步脚本正在 运行时,也能追溯到发起该交互的上下文。

3.2. InteractionContext 结构

InteractionContext 是一个结构体,用于维护从单次交互中检测软 导航所需的数据。它具有以下

注: 本规范的未来版本可能会跟踪 在一个交互上下文中发生的所有 URL 更新,以提供更完整的导航历史。last URL value 会被 内部跟踪,以确保即使当前仅在 PerformanceSoftNavigation 的 name 中公开 first URL value,仍能将影响准确归因回 交互的最终状态。

3.3. 基础设施算法

要在给定 Document document 的情况下获取 当前交互上下文
  1. context 为内部 AsyncContext.Variable [[ActiveInteractionContext]] 的值。

  2. 如果 context 不为 null,且 context上下文文档不等于 document,则返回 null。

  3. 返回 context

要在给定 Document document 和一个 PerformanceEventTiming timing entry 的情况下获取或创建某次交互的上下文
  1. interaction idtiming entryinteractionId

  2. 断言 interaction id 大于 0。

  3. 如果 document交互 id 到交互 上下文[interaction id] 存在, 则返回 document交互 id 到交互 上下文[interaction id]。

  4. interaction context 为一个新的 InteractionContext

  5. interaction contextid 设置为 interaction id

  6. interaction context上下文文档设置为 document

  7. interaction context开始 时间设置为 timing entrystartTime

  8. 设置 document交互 id 到交互 上下文[interaction id] 为 interaction context

  9. 返回 interaction context

要在给定 Document document 和一个 Event event 的情况下更新某个事件的交互上下文
  1. timestamp 为给定 document相关全局对象时的当前高精度时间

  2. 如果 event 的类型为 "scroll",则令 is scroll 为 true;否则为 false。

  3. 如果 event 的类型是会触发 已派发输入事件的事件类型(如 [EVENT-TIMING] 中定义),则令 is input 为 true;否则为 false。

  4. 如果 is scroll 为 false 且 is input 为 false,则返回。

  5. 对于 document交互 id 到交互 上下文的 values 中的每个 interaction context

    1. 如果 is scroll 为 true,且 interaction context首次滚动时间戳 为 0:

      1. interaction context首次滚动 时间戳设置为 timestamp

    2. 如果 is input 为 true,且 interaction context首次输入时间戳 为 0:

      1. interaction context首次输入 时间戳设置为 timestamp

要在给定 null 或一个 PerformanceEventTiming 对象 timing entry 的情况下设置用于 事件派发的当前交互上下文
  1. 如果 timing entry 为 null,则返回 null。

  2. interaction idtiming entryinteractionId

  3. 如果 interaction id 为 0,则返回 null。

  4. eventtiming entry关联事件

  5. documentevent相关全局对象关联 Document

  6. 在给定 documentevent 的情况下,更新某个事件的交互上下文

  7. interaction context 为在给定 documenttiming entry 的情况下获取或创建某次交互的上下文的结果。

  8. 将内部 AsyncContext.Variable [[ActiveInteractionContext]] 的值设置为 interaction context

  9. 返回 interaction context

在事件派发后取消设置当前交互上下文
  1. 将内部 AsyncContext.Variable [[ActiveInteractionContext]] 的值设置为 null。

4. 交互内容绘制

4.1. InteractionContentfulPaint 接口

[Exposed=Window]
interface InteractionContentfulPaint : PerformanceEntry {
    readonly attribute LargestContentfulPaint largestContentfulPaint;
    readonly attribute unsigned long long interactionId;

    object toJSON();
};

InteractionContentfulPaint includes PaintTimingMixin;

每个 InteractionContentfulPaint 都具有:

largestContentfulPaint 属性的 getter 必须返回 this最大内容绘制

interactionId 属性的 getter 必须返回 this上下文id

name 属性的 getter 必须返回空字符串。

entryType 属性的 getter 必须返回 "interaction-contentful-paint"

startTime 属性的 getter 必须返回 this上下文开始时间

duration 属性的 getter 必须返回以下两者之间的差值: 默认绘制时间戳,针对 this绘制 计时信息;以及 this上下文开始时间

注: 虽然该条目会从其关联的 InteractionContext 动态查询静态 交互属性(如 interactionIdstartTime),但它会在创建时捕获该 绘制的绘制计时信息以及候选 LargestContentfulPaint 条目的静态快照,以 确保这些指标反映该视觉更新的确切状态。

4.2. 交互内容绘制算法

给定一个 Window window、一个 InteractionContext interaction context、一个 LargestContentfulPaint lcpEntry,以及一个 paint timing info paintTimingInfo,要 create an interaction contentful paint entry
  1. entrywindowrealm 中的一个新的 InteractionContentfulPaint 对象。

  2. entrycontext 设置为 interaction context

  3. entrylargest contentful paint 设置为 lcpEntry

  4. entry 关联的 paint timing info 设置为 paintTimingInfo

  5. 返回 entry

要在给定一个 最大内容绘制候选 lcpCandidate、一个 Document document、一个 InteractionContext interaction context,以及一个 绘制 计时信息 paintTimingInfo 的情况下处理新的已归因内容绘制 候选
  1. 如果 interaction context首次滚动时间戳 大于 0,并且 lcpEntryrenderTime 大于 interaction context首次滚动时间戳,则返回。

  2. 如果 interaction context首次输入时间戳大于 0,并且 lcpEntryrenderTime 大于 interaction context首次输入时间戳,则返回。

  3. lcpEntry 为使用 lcpCandidatepaintTimingInfodocument 创建 LargestContentfulPaint 条目的结果。

  4. globaldocument相关全局对象

  5. paint timing infolcpEntry 的关联绘制计时信息

  6. icpEntry 为在给定 globalinteraction contextlcpEntrypaint timing info 的情况下创建交互内容 绘制条目的结果。

  7. 入队 icpEntry

  8. icpEntry 添加到 global性能条目缓冲区

  9. 如果 interaction context首次内容绘制为 null:

    1. interaction context首次内容绘制 设置为 icpEntry

  10. interaction context最大内容绘制设置为 icpEntry

  11. interaction context当前最大 内容绘制候选 设置为 lcpCandidate

注:InteractionContentfulPaint 条目在 被检测到时即会被发出到性能时间线,无论该交互最终是否产生软导航。这 允许开发者监控所有交互的渲染更新。

报告交互内容绘制和 软导航,给定一个 Document document、一个 绘制定时信息 paintTimingInfo、一个由 待处理图像记录组成的有序 集合 paintedImages,以及一个由 元素组成的有序 集合 paintedTextNodes
  1. contextToCandidateSets 为一个新的映射

  2. paintedImages 的每个 record

    1. elementrecord元素

    2. interaction context 为针对 element获取绘制 归因交互上下文的结果。

    3. 如果 interaction context 不为 null:

      1. 如果 contextToCandidateSets包含 interaction context,则 将 contextToCandidateSets[interaction context] 设置为 « «», «» »。

      2. record 追加contextToCandidateSets[interaction context][0]。

  3. paintedTextNodes 的每个 element

    1. interaction context 为针对 element获取绘制 归因交互上下文的结果。

    2. 如果 interaction context 不为 null:

      1. 如果 contextToCandidateSets包含 interaction context,则 将 contextToCandidateSets[interaction context] 设置为 « «», «» »。

      2. element 追加contextToCandidateSets[interaction context][1]。

  4. contextToCandidateSets 中的每个 interaction contextcandidateSets

    1. newCandidate 为给定 documentcandidateSets[0]、candidateSets[1] 以及 interaction context当前 最大内容绘制候选项计算新的 最大内容绘制候选项的结果。

    2. 如果 newCandidate 不为 null:

      1. 给定 newCandidatedocumentinteraction contextpaintTimingInfo处理 新的已归因内容绘制候选项

      2. 给定 documentinteraction context评估软导航 发出

4.3. 交互内容绘制归因

InteractionPaintTimingNodeState 是一个结构, 具有以下


要确定一个 InteractionPaintTimingNodeState node state 是否比……更新 一个 InteractionPaintTimingNodeState 或 null other node state
  1. 如果 other node state 为 null,或 node statemodification id大于 other node statemodification id,则返回 true, 否则返回 false。

要为给定的 Node node 获取绘制归因交互上下文
  1. documentnode节点文档

  2. node statedocument传播节点状态[node] 默认值为 null。

  3. 如果 node state 为 null,则返回 null;否则返回 node statecontext

将节点记录为已为交互 绘制定时而修改,给定一个 Node target node
  1. documentnode节点文档

  2. 如果给定 document 时,target node暴露给绘制定时,则返回。

  3. interaction context 为给定 document获取当前交互上下文的结果。

  4. 如果 interaction context 为 null,则返回。

  5. 如果 document最后修改上下文不等于 interaction context

    1. document最后修改上下文设置为 interaction context

    2. document当前修改 代 id加 1。

  6. previous node statedocument已标记节点 状态[target node] 默认值为 null。

  7. 如果 previous node state 不为 null,且 previous node statemodification id等于 document当前修改代 id,则返回。

  8. node state 为一个新的 InteractionPaintTimingNodeState

  9. node statecontext设置为 interaction context

  10. node statemodification id设置为 document当前修改代 id

  11. 设置 document已标记节点 状态[node] 为 node state

  12. document交互绘制定时为 脏设置为 true。

更新文档及其后代的 交互上下文,给定一个 Document document
  1. 如果 document交互绘制定时为 脏为 false,则返回。

  2. 给定 document 和 null,更新节点及其后代的 交互上下文

  3. document交互绘制定时为 脏设置为 false。

更新节点及其后代的交互上下文, 给定一个 Node node 和一个 InteractionPaintTimingNodeState inherited node state 或 null:
  1. documentnode节点文档

  2. node statedocument已标记节点 状态[node] 默认值为 null。

  3. 如果 node state 不为 null:

    1. 如果 node state inherited node state 更新:

      1. inherited node state 设置为 node state

      2. 如果 node 是一个 Text 节点,则移除 document已标记节点 状态[node]。

    2. 否则,移除 document已标记 节点状态[node]。

  4. 如果 inherited node state 不为 null,且 node 符合定时条件

    1. attribution element 为针对 node获取 归因元素的结果。

    2. previous propagated state传播节点 状态[attribution element] 默认值为 null。

    3. 如果 inherited node state previous propagated state 更新:

      1. 传播节点 状态[attribution element] 设置为 inherited node state

      2. 如果 previous propagated state 为 null,或 previous propagated statecontext不等于 inherited node statecontext,则对 attribution element重置绘制跟踪

  5. node 的每个child node, 给定 child nodeinherited node state更新 节点及其后代的交互上下文

注:为简单起见,每当需要重新处理传播状态时,此算法都会遍历整个 DOM。这可以优化为只处理 DOM 中可绘制的部分,例如 已知不可见或会被现有机制(如 content-visibility 或 CSS containment)跳过的子树,在此 过程中也可以被跳过,只要它们在下一次被绘制之前 得到更新即可。另请注意,这还可以通过 将这些步骤与另一次(绘制前)树遍历合并来进一步优化,只要相关状态在 绘制前得到更新即可。

注:[CONTAINER-TIMING] API 提供了一种 机制,用于按共同的 DOM 祖先对渲染效果进行分组,并将聚合后的绘制信息报告到性能时间线。在本规范的未来 版本中,我们计划扩展 Container Timing,以支持单个容器的多个客户端 (即全局 "containertiming" 属性和按交互定时),从而允许 基于 Container Timing 实现交互绘制定时。每个被记录的节点都将被 视为修改它的交互的容器,这样每个交互都会关联到一组容器。然后,本 规范将针对每个交互,跟踪在已标记容器中发生的最大内容绘制。此外,我们还可以暴露 Container Timing 跟踪的其他有用信息, 例如每个交互的容器聚合总绘制面积。

5. 软导航

5.1. PerformanceSoftNavigation 接口

[Exposed=Window]
interface PerformanceSoftNavigation : PerformanceEntry {
    readonly attribute NavigationType navigationType;
    readonly attribute unsigned long long interactionId;
    InteractionContentfulPaint? getLargestInteractionContentfulPaint();
};

PerformanceSoftNavigation includes PaintTimingMixin;

每个 PerformanceSoftNavigation 都具有:

navigationType 属性的 getter 必须返回 this上下文导航类型

interactionId 属性的 getter 必须返回 this上下文id

getLargestInteractionContentfulPaint() 方法必须返回 this上下文最大内容绘制

name 属性的 getter 必须返回 this上下文第一个 URL 值

entryType 属性的 getter 必须返回 "soft-navigation"

startTime 属性的 getter 必须返回 this上下文开始时间

duration 属性的 getter 必须返回 thispresentationTimethis上下文开始时间在发出时的差值。

注:在实践中,getLargestInteractionContentfulPaint() 预期会返回一个非 null 条目,因为已确认的软导航至少需要检测到一次交互内容绘制来 触发其发出。

不过,未来的迭代可以评估软导航是否可以在 URL 修改后、 第一次绘制之前立即被视为已提交。在这样的模型中,此方法可能会 在发出时返回 null。

此定时的主要设计考量是对其他时间线条目(例如 LayoutShiftPerformanceResourceTimingLongAnimationFrameTiming 等)的归因,这些条目发生在 URL 修改与第一次绘制之间的间隔中。许多站点会在发起 fetch 请求时 立即提交新 URL,例如,即使当前页面仍处于 先前的导航状态。为确保一致的时间线切片,本规范会将所有 这类条目归因到先前的导航标识符,直到第一次绘制确认该转换。

5.2. 软导航算法

软导航是一种 满足以下条件的同文档导航:

要在给定一个 Document document 和一个 InteractionContext interaction context 的情况下评估软导航发出
  1. 如果 interaction context已发出为 true,则返回。

  2. 如果 document活跃软导航候选 不是 interaction context,则返回。

  3. 如果 interaction context第一个 URL 值为 null,则返回。

  4. 如果 interaction context首次内容绘制为 null, 则返回。

  5. windowdocument相关全局对象

  6. entry 为在给定 windowinteraction context 的情况下创建 软导航条目的结果。

  7. 在给定 windowentry 的情况下,发出软导航条目

  8. interaction context已发出设置为 true。

要在给定一个 Window window 和一个 InteractionContext interaction context 的情况下创建 软导航条目
  1. entrywindowrealm 中的一个新的 PerformanceSoftNavigation 对象。

  2. entry上下文设置为 interaction context

  3. first paintinteraction context首次内容绘制

  4. 断言 first paint 不为 null。

  5. entry 的关联绘制计时信息设置为 first paint 的关联 绘制计时信息

  6. 返回 entry

要在给定一个 Window window 和一个 PerformanceSoftNavigation entry 的情况下发出软 导航条目
  1. 在给定 window 的情况下,递增当前导航 id

  2. 入队 entry

  3. entry 添加到 window性能条目缓冲区

注: 这个 navigationId 对于此 PerformanceSoftNavigation 条目会在将其排入性能时间线时自动设置, 与其他 PerformanceEntry 类型的行为相匹配。

要在给定一个 Document document字符串 urlNavigationType navigation type 的情况下处理 同文档提交
  1. 如果 url 等于 documenturl,则返回。

  2. interaction context 为在给定 document 的情况下获取当前交互 上下文的结果。

  3. 如果 interaction context 为 null,则返回。

  4. interaction context最后一个 URL 值设置为 url

  5. 如果 interaction context首次 URL 更新时间戳为 null:

    1. interaction context首次 URL 更新 时间戳设置为给定 document相关全局对象时的 当前高精度时间

    2. interaction context第一个 URL 值设置为 url

    3. interaction context导航类型设置为 navigation type

  6. document活跃软导航候选 设置为 interaction context

  7. 在给定 documentinteraction context 的情况下,评估软导航发出

6. 规范集成

6.1. DOM 集成

6.1.1. Document

每个 document 都有一个 交互 id 到 交互上下文,即一个 映射, 初始为空。

每个 document 都有一个 活跃软导航 候选,即一个 InteractionContext 或 null,初始为 null。

每个 document 都有一个 当前修改 代 id,即一个 64 位无符号整数,初始化为 0。

注: 当相关 DOM 修改 以不同于上一次修改的 当前修改代 id 发生时,该 id 会变化 InteractionContext。 这允许将相关修改 归为一组,从而能够按新近程度比较 InteractionPaintTimingNodeState 对象 并优化需要跟踪哪些节点。

每个 document 都有一个 上一次修改 上下文,即一个 InteractionContext 或 null,初始为 null。

每个 document 都有一个 已标记节点状态,即一个从 映射NodeInteractionPaintTimingNodeState, 初始为空。

每个 document 都有一个 已传播节点状态,即一个从 映射NodeInteractionPaintTimingNodeState, 初始为空。

每个 document 都有一个 交互绘制 计时是否为脏,即一个布尔值, 初始为 false。

6.1.2. Node

节点插入时,或当一个 node node 以 以下方式之一被修改时:

运行以下步骤:

  1. 给定 node将节点记录为 已为交互绘制定时而修改

6.2. HTML 集成

6.2.1. History

为历史步骤应用更新 document中,在 5.5.1(如果 documentsEntryChanged 为 true 且如果 documentIsNew 为 false)之前,给定该 处理一次同 document 提交,给定该 Document、 目标条目的 url,以及 "traverse"。

共享 历史 push/replace 步骤 (如 [HTML] 中所定义)中,在 URL 更新后,给定该 处理一次同 document 提交,给定该 Document、新 URL,以及操作类型(即 "push" 或 "replace")。

6.2.2. 硬导航

当创建新的 Window 时(例如在“硬”导航期间),其 当前导航 id 会按 § 2.1 导航 ID 中的规定初始化。

[NAVIGATION-TIMING] 中,当为 初始导航创建 PerformanceNavigationTiming 条目时,用户代理必须将其 navigationId 设置为该 Window当前导航 id

6.3. Event Timing 集成

本规范扩展了 [EVENT-TIMING] 对交互的定义,以包含与现代 Web 应用程序和单页应用程序相关的 其他事件类型。

以下事件类型被认为是交互的一部分(如 [EVENT-TIMING] 中所定义):

当这些事件作为用户交互的结果被派发时,用户代理必须为它们分配 一个唯一的 interactionId, 该值通过为 document 的相关全局对象获取下一个 interactionId 而获得。如果某个事件由先前 已分配 interactionId 的交互触发, 用户代理应复用 该同一标识符。

注:这些事件只有在它们是由 用户操作发起的起始事件时(例如点击浏览器 UI 的后退按钮),才会作为主要 交互被报告。在大多数其他场景中——例如 click 处理器手动操作历史记录时——后续的 popstatenavigate 事件不会被 视为独立的用户交互。

虽然这些以编程方式触发的事件可能未设置 isTrusted 标志,但它们会通过 [ASYNC-CONTEXT] 被 正确归因回原始交互,因为历史和 导航 API 被视为发起任务的异步延续。

注:navigatepopstatehashchange 事件会被用作内部信号,用于 跟踪软导航并分配 interactionId。本规范 不要求这些 事件类型作为 PerformanceEventTiming 条目暴露到 性能时间线,而是将 该决定留给 [EVENT-TIMING] 规范。

注:[EVENT-TIMING] 规范预期会被 更新,以显式定义 processingStartprocessingEnd 钩子,并 确保 interactionId 分配发生得足够早, 以支持此集成。目前,interactionId 分配通常会 推迟到事件处理 结束时。

本规范使用 unsigned long long 作为 interactionId, 以确保安全的全局 计数器,而 [EVENT-TIMING] 目前将其定义为 unsigned long。预计 该不匹配会在两个规范的未来版本中解决。

要为一个 Window window 获取下一个 interactionId
  1. windowinteraction count 设置为 windowinteraction count 加 1。

  2. 返回 windowinitial interactionId value 加上 (windowinteraction count 乘以 windowinteractionId increment)。

[EVENT-TIMING] 中定义的对 DOM 规范的事件 分派算法的修改中:
  1. 在将 timingEntry 设置为初始化并记录事件 定时处理开始结果的步骤之后,立即运行以下步骤:

    1. 给定 timingEntry为事件分派设置当前 交互上下文

  2. 在调用记录事件定时处理结束的步骤之前, 立即运行以下步骤:

    1. 在事件分派后取消设置 当前交互上下文

6.4. Paint Timing 集成

本规范扩展了 [PAINT-TIMING] 规范,以便为 已由交互修改的元素重置绘制跟踪,并为已渲染的文档触发绘制归因。

修改标记绘制定时,在步骤 1 之后添加以下步骤,给定一个 Document document
  1. 给定 document更新 文档及其后代的交互上下文

标记绘制 时间混合了应在 UA 绘制文档之前和 之后发生的步骤。此处添加的步骤预期会在绘制前发生。[w3c/paint-timing Issue #126]

修改标记绘制定时,在步骤 10.3(报告最大内容绘制)之后添加以下步骤,给定一个 Document document、一个 绘制定时信息 paintTimingInfo、 一个由 待处理图像记录组成的有序集合 paintedImages,以及一个由 元素组成的有序 集合 paintedTextNodes
  1. 给定 documentpaintTimingInfopaintedImagespaintedTextNodes报告交互 内容绘制和软导航

添加以下算法:

要为一个 Node node 重置绘制 跟踪
  1. 重置文本元素跟踪 node

  2. 重置图像元素跟踪 node

这是一个占位 算法。我们需要允许相关元素重新绘制,但这些 重新绘制不应影响 Element Timing 或 LCP。文本和图像具有不同的机制来 检测何时发生了相关绘制,并且二者都需要更新以支持重新绘制。

添加以下算法:

要为一个 Node node 获取 归因元素
  1. 如果 node 是一个 Text 节点,则返回用于确定 node包含块Element

  2. 否则,返回 node

6.5. Largest Contentful Paint(LCP)集成

7. 安全与隐私考量

暴露到性能时间线的软导航本身没有安全和隐私影响。 但是,由于检测到软导航而重置各种绘制计时条目可能会产生影响,尤其是在已访问链接被分区之前。因此,在未分区 :visited 缓存的情况下暴露 此类绘制操作,需要仅在仔细分析相关绘制操作之后进行,以确保它们不会跨源暴露用户的历史记录。

类似地,暴露详细的绘制计时信息(例如通过 Interaction Contentful Paint) 可能会被用于观察拼写或语法错误装饰(通过 ::spelling-error::grammar-error)被应用时的绘制更新。在没有 缓解措施的情况下,这可能 允许攻击者以编程方式循环遍历文本字段中的单词,以检查它们是否 存在于用户的词典中。但是,浏览器通过将拼写和语法 检查限制为仅在每次用户交互(例如按键或点击)时发生一次来缓解此问题,以防止用户词典 泄露。由于计时和绘制 信息已经可以由开发者通过其他标准 API 观察到,因此暴露这些计时 条目不会引入任何新的信息泄露,超出浏览器拼写/语法高亮频率限制已经约束的范围。

8. 附录:重叠交互和竞态条件

本节为非规范性内容。

Web 应用程序经常会快速连续地处理多个用户交互。本规范 通过以下模型处理这类重叠交互:

索引

由本 规范定义的术语

由 引用定义的术语

参考文献

规范性参考文献

[CSS-DISPLAY-4]
Elika Etemad; Tab Atkins Jr.. CSS 显示模块 Level 4. URL:https://drafts.csswg.org/css-display-4/
[DOM]
Anne van Kesteren. DOM 标准. 现行标准. URL:https://dom.spec.whatwg.org/
[EVENT-TIMING]
Michal Mocny. Event Timing API. URL:https://w3c.github.io/event-timing/
[HR-TIME-3]
Yoav Weiss. 高精度时间. URL:https://w3c.github.io/hr-time/
[HTML]
Anne van Kesteren; et al. HTML 标准. 现行标准. URL:https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 标准. 现行标准. URL:https://infra.spec.whatwg.org/
[LARGEST-CONTENTFUL-PAINT]
Yoav Weiss. Largest Contentful Paint. URL:https://w3c.github.io/largest-contentful-paint/
[NAVIGATION-TIMING-2]
Yoav Weiss; Noam Rosenthal. Navigation Timing Level 2. URL:https://w3c.github.io/navigation-timing/
[PAINT-TIMING]
Ian Clelland; Noam Rosenthal. Paint Timing. URL:https://w3c.github.io/paint-timing/
[PERFORMANCE-TIMELINE]
Nicolas Pena Moreno. Performance Timeline. URL:https://w3c.github.io/performance-timeline/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 标准. 现行 标准. URL:https://webidl.spec.whatwg.org/

非规范性参考文献

[ASYNC-CONTEXT]
AsyncContext。URL:https://github.com/tc39/proposal-async-context
[CONTAINER-TIMING]
Container Timing API。URL:https://github.com/WICG/container-timing
[NAVIGATION-TIMING]
Zhiheng Wang。Navigation Timing。2012 年 12 月 17 日。REC。URL:https://www.w3.org/TR/navigation-timing/

IDL 索引

[Exposed=(Window,Worker)]
partial interface PerformanceEntry {
    readonly attribute unsigned long long navigationId;
};

[Exposed=Window]
interface InteractionContentfulPaint : PerformanceEntry {
    readonly attribute LargestContentfulPaint largestContentfulPaint;
    readonly attribute unsigned long long interactionId;

    object toJSON();
};

InteractionContentfulPaint includes PaintTimingMixin;

[Exposed=Window]
interface PerformanceSoftNavigation : PerformanceEntry {
    readonly attribute NavigationType navigationType;
    readonly attribute unsigned long long interactionId;
    InteractionContentfulPaint? getLargestInteractionContentfulPaint();
};

PerformanceSoftNavigation includes PaintTimingMixin;

议题索引

本规范使用 unsigned long long 作为 interactionId, 以确保安全的全局 计数器,而 [EVENT-TIMING] 目前将其定义为 unsigned long。预计此不匹配 会在两个规范的未来版本中解决。
标记 绘制时间混合了应在 UA 绘制文档之前和 之后发生的步骤。此处添加的步骤预期会在绘制前发生。 [w3c/paint-timing Issue #126]
这是一个占位算法。我们需要允许相关元素重新绘制,但这些 重新绘制不应影响 Element Timing 或 LCP。文本和图像具有不同的机制来 检测何时发生了相关绘制,并且二者都需要更新以支持重新绘制。