1. 7.4 导航和会话历史
      1. 7.4.1 会话历史
        1. 7.4.1.1 会话历史条目
        2. 7.4.1.2 文档状态
        3. 7.4.1.3 会话历史的集中修改
        4. 7.4.1.4 会话历史的低级操作
      2. 7.4.2 导航
        1. 7.4.2.1 支持的概念
        2. 7.4.2.2 开始导航
        3. 7.4.2.3 结束导航
          1. 7.4.2.3.1 通常的跨文档导航情况
          2. 7.4.2.3.2 javascript: URL 特殊情况
          3. 7.4.2.3.3 片段导航
          4. 7.4.2.3.4 非获取方案和外部软件
        4. 7.4.2.4 阻止导航
        5. 7.4.2.5 终止导航
      3. 7.4.3 重新加载和遍历
      4. 7.4.4 非片段同步“导航”
      5. 7.4.5 填充会话历史条目
      6. 7.4.6 应用历史步骤
        1. 7.4.6.1 更新可遍历对象
        2. 7.4.6.2 更新文档
        3. 7.4.6.3 显示文档
        4. 7.4.6.4 滚动到片段
        5. 7.4.6.5 持久化历史条目状态

欢迎来到龙之口。导航、会话历史以及通过该会话历史的遍历是本标准中最复杂的部分之一。

基本概念似乎并不难

你可以看到这里出现了一些交织的复杂性,比如遍历会导致导航(即对存储的 URL 进行网络获取),而导航必然需要与会话历史列表交互,以确保当它完成时,用户正在查看正确的内容。但真正的问题在于各种边缘情况和相互作用的 Web 平台功能。

在接下来的内容中,我们试图通过将这些复杂性适当地划分为标记部分和算法,并在可能的情况下提供适当的介绍性文字,来引导读者理解这些复杂性。但是,如果你想真正理解导航和会话历史,通常的建议 将是无价的。

7.4.1 会话历史

7.4.1.1 会话历史条目

一个 会话历史条目 是一个具有以下 项目结构

要获取 会话历史条目文档,请返回其 文档状态文档


序列化状态 是对表示用户界面状态的对象进行序列化(通过 StructuredSerializeForStorage)的结果。我们有时非正式地称之为“状态对象”,它们是作者提供的表示用户界面状态的对象,或者反过来,是通过对序列化状态进行反序列化(通过 StructuredDeserialize)创建的对象。

页面可以通过 添加 序列化状态 到会话历史记录中。这些状态将在用户(或脚本)在历史记录中后退时被 反序列化返回给脚本,从而使作者能够在单页面应用程序中使用“导航”隐喻。

序列化状态 用于两个主要目的:首先,将状态的预解析描述存储在 URL 中,以便在简单情况下,作者无需进行解析(尽管仍然需要解析来处理用户传递的 URL,因此这只是一个小的优化)。其次,作者可以存储不应存储在 URL 中的状态,因为该状态仅适用于当前的 Document 实例,如果打开新的 Document,则需要重建该状态。

后者的一个例子是跟踪弹出 div 动画的精确坐标,以便如果用户后退,它可以动画到相同的位置。或者,它可以用来在数据缓存中保留一个指针,该数据将根据 URL 中的信息从服务器获取,以便在前后移动时,无需再次获取信息。


滚动恢复模式 指示用户代理在遍历到 条目 时是否应该恢复持久化滚动位置(如果有)。滚动恢复模式是以下之一

"auto"
用户代理负责在导航时恢复滚动位置。
"manual"
页面负责恢复滚动位置,用户代理不会自动尝试恢复。
7.4.1.2 文档状态

文档状态 持有 会话历史记录条目 中的状态,有关如何呈现和(如果需要)重新创建 Document 的信息。它具有

用户代理可以 销毁文档及其子文档,前提是 文档状态文档 中的 文档 不为 null,只要 Document 未处于 完全活动状态

除了此限制之外,本规范未指定用户代理何时应该销毁存储在 文档状态 中的 文档,还是将其保留在缓存中。


一个 POST 资源 具有


一个 嵌套历史记录 具有

这将包含用于跨重新加载标识子可导航的方法。



会话历史记录中的几个连续条目可以共享同一个 文档状态。当通过正常的 导航 访问初始条目,并且通过 history.pushState() 添加后续条目时,就会发生这种情况。或者,它可以通过 导航到片段 来实现。

共享同一个 文档状态(因此仅表示特定文档的不同状态)的所有条目在构造时是连续的。


一个 Document 具有一个 最新条目,一个 会话历史记录条目 或 null。

这是最近由给定 Document 表示的条目。单个 Document 可以在一段时间内表示多个 会话历史记录条目,因为多个连续的 会话历史记录条目 可以共享同一个 文档状态,如上所述。

7.4.1.3 会话历史的集中修改

为了维护单一的事实来源,对 可遍历可导航会话历史条目 的所有修改都需要同步。由于会话历史受到所有后代 可导航 的影响,因此受到多个 事件循环 的影响,因此这一点尤其重要。为了实现这一点,我们使用 会话历史遍历并行队列 结构。

会话历史遍历并行队列并行队列 非常相似。它有一个 算法集,一个 有序集

在一个 会话历史遍历并行队列算法集 中,要么是算法步骤,要么是 同步导航步骤,它们是涉及 目标可导航可导航)的一种特殊类型的算法步骤。

追加会话历史遍历步骤可遍历可导航 traversable 给定算法步骤 steps追加 stepstraversable会话历史遍历队列算法集

追加会话历史同步导航步骤 涉及 可导航 targetNavigable可遍历可导航 traversable 给定算法步骤 steps追加 steps 作为 同步导航步骤 针对 目标可导航 targetNavigabletraversable会话历史遍历队列算法集

启动新的会话历史遍历并行队列

  1. sessionHistoryTraversalQueue 为一个新的 会话历史遍历并行队列

  2. 并行 运行以下步骤

    1. 当 true 时

      1. 如果 sessionHistoryTraversalQueue算法集 为空,则 继续

      2. steps出队 的结果,从 sessionHistoryTraversalQueue算法集 中。

      3. 运行 steps

  3. 返回 sessionHistoryTraversalQueue

同步导航步骤算法集 中被标记,以允许它们有条件地“跳过队列”。这是在 应用历史步骤中处理 的。

想象一下,这个 Jake 图 所描绘的联合会话历史

01
顶部/a/b

以下代码在顶层运行

history.back();
location.href = '#foo';

期望的结果是

012
顶部/a/b/b#foo

这并不简单,因为同步导航在可观察性方面赢得了竞赛,而遍历在 会话历史遍历并行队列 上排队步骤方面赢得了竞赛。为了实现这个结果,发生了以下情况

  1. history.back() 追加步骤,旨在以 -1 的增量进行遍历。

  2. location.href = '#foo' 同步更改 活动会话历史条目 条目,指向一个新创建的条目,URL 为 /b#foo,并 追加同步步骤,以通知中心事实来源有关该新条目的信息。请注意,这 *不会* 尚未更新 当前会话历史条目当前会话历史步骤,或 会话历史条目 列表;这些更新无法同步进行,而必须作为队列步骤的一部分进行。

  3. 会话历史遍历并行队列 上,由 history.back() 排队的步骤运行

    1. 目标历史步骤确定为 0:当前会话历史步骤(即 1)加上预期的增量 -1。

    2. 我们进入主要的 应用历史步骤 算法。

      步骤 0 处的条目,对于 URL /a,其 文档 已填充

      同时,队列被检查是否有 同步导航步骤。由 location.href 设置程序排队的步骤现在运行,并阻止遍历执行超出文档填充(例如,卸载文档和切换活动历史条目)的影响,直到它们完成。这些步骤导致发生以下情况

      1. 带有 URL /b#foo 的条目被添加,其 步骤 确定为 2:当前会话历史步骤(即 1)加 1。

      2. 我们完全切换到新添加的条目,包括对 应用历史步骤 的嵌套调用。这最终导致 更新文档,通过分发事件,如 hashchange

      只有当这一切都完成后,并且带有 URL /a 的历史条目已完全填充了 文档,我们才会继续应用给定目标步骤 0 的历史步骤。

      此时,带有 URL /b#foo文档 卸载,我们完成移动到我们的目标历史步骤 0,这使得带有 URL /a 的条目成为 活动会话历史条目,而 0 成为 当前会话历史步骤

以下是一个更复杂的示例,涉及填充两个不同 iframe 的竞赛,以及其中一个 iframe 加载后的同步导航。我们从以下设置开始

012
顶部/t
frames[0]/i-0-a/i-0-b
frames[1]/i-1-a/i-1-b

然后调用 history.go(-2)。然后发生以下情况

  1. history.go(-2) 追加步骤,旨在以 -2 的增量进行遍历。一旦这些步骤运行

    1. 目标步骤确定为 2 + (-2) = 0。

    2. 并行地,对 填充 两个 iframe 进行获取,分别获取 /i-0-a/i-1-a

      同时,队列被检查是否有 同步导航步骤。现在还没有。

    3. 在获取竞赛中,对 /i-0-a 的获取获胜。我们继续前进,完成 应用历史步骤 的所有工作,以了解遍历如何影响 frames[0] 可导航,包括更新其 活动会话历史条目,使其指向带有 URL /i-0-a 的条目。

    4. 在对 /i-1-a 的获取完成之前,我们到达了 脚本可能为 frames[0] 可导航活动文档 中新创建的文档运行 的点。一些这样的脚本确实运行了

      location.href = '#foo'

      这同步更改了 frames[0] 可导航的 活动会话历史条目 条目,指向一个新创建的条目,带有 URL /i-0-a#foo,并 追加同步步骤,以通知中心事实来源有关该新条目的信息。

      上一个示例不同,这些同步步骤不会“跳过队列”并在完成 /i-1-a 的获取之前更新可遍历对象。这是因为所讨论的可遍历对象 frames[0] 已经在遍历过程中被更改,因此我们知道,在当前会话历史步骤 为 2 的情况下,将新条目添加为步骤 3 没有任何意义。

    5. /i-1-a 的获取最终完成时,我们继续完成更新遍历的 frames[1] 可遍历对象,包括将它的活动会话历史条目 更新为 URL 为 /i-1-a 的条目。

    6. 现在,这两个可遍历对象都已完成遍历的处理,我们将当前会话历史步骤 更新为目标步骤 0。

  2. 现在,我们可以处理为同步导航排队的步骤。

    1. 添加 /i-0-a#foo 条目,它的步骤 被确定为 1:当前会话历史步骤(即 0)加 1。这还会清除现有的前进历史记录

    2. 我们完全切换到新添加的条目,包括调用应用历史步骤。这最终会导致更新文档,方法是调度诸如hashchange 之类的事件,以及将当前会话历史步骤 更新为目标步骤 1。

最终结果是

01
顶部/t
frames[0]/i-0-a/i-0-a#foo
frames[1]/i-1-a
7.4.1.4 会话历史记录的低级操作

本节包含我们在整个标准中操作会话历史记录时执行的各种操作。了解这些操作的功能的最佳方法是查看它们的调用点。

获取可遍历对象的会话历史记录条目navigable

  1. traversablenavigable可遍历的可遍历对象

  2. 断言:这在 traversable会话历史记录遍历队列 中运行。

  3. 如果 navigabletraversable,则返回 traversable会话历史记录条目

  4. docStates 为一个空的有序集合,其中包含文档状态

  5. 对于 traversable会话历史记录条目 中的每个 entry追加 entry文档状态docStates

  6. 对于 docStates 中的每个 docState

    1. 对于 docState嵌套历史记录 中的每个 nestedHistory

      1. 如果 nestedHistoryid 等于 navigableid,则返回 nestedHistory条目

      2. 对于 nestedHistory条目 中的每个 entry追加 entry文档状态docStates

  7. 断言:不会执行此步骤。

为导航 API 获取可遍历对象的会话历史记录条目navigable,并提供一个整数 targetStep

  1. rawEntries获取 navigable 的会话历史记录条目 的结果。

  2. entriesForNavigationAPI 为一个新的空列表

  3. startingIndexrawEntries会话历史记录条目 的索引,该条目具有小于或等于 targetStep 的最大步骤

    参见此示例,以了解为什么它是小于或等于 targetStep 的最大步骤。

  4. 追加 rawEntries[startingIndex] 到 entriesForNavigationAPI

  5. startingOriginrawEntries[startingIndex] 的文档状态来源

  6. istartingIndex − 1。

  7. i > 0 时

    1. 如果 rawEntries[i] 的文档状态来源startingOrigin 同源,则退出

    2. 前置 rawEntries[i] 到 entriesForNavigationAPI

    3. i 设置为 i − 1。

  8. i 设置为 startingIndex + 1。

  9. i < rawEntries大小

    1. 如果 rawEntries[i] 的文档状态来源startingOrigin 同源,则退出

    2. 追加 rawEntries[i] 到 entriesForNavigationAPI

    3. i 设置为 i + 1。

  10. 返回 entriesForNavigationAPI

清除可遍历对象的正向会话历史记录navigable

  1. 断言:这在 navigable会话历史记录遍历队列 中运行。

  2. stepnavigable当前会话历史步骤

  3. entryLists有序集合 « navigable会话历史记录条目 »。

  4. 对于 entryLists 中的每个 entryList

    1. 移除 entryList 中每个会话历史记录条目,这些条目具有大于 step步骤

    2. 对于 entryList 中的每个 entry

      1. 对于 entry文档状态嵌套历史记录 中的每个 nestedHistory追加 nestedHistory条目列表entryLists

获取可遍历对象中使用的所有历史记录步骤traversable

  1. 断言:这在 traversable会话历史记录遍历队列 中运行。

  2. steps 为一个空的有序集合,其中包含非负整数。

  3. entryLists有序集合 « traversable会话历史记录条目 »。

  4. 对于 entryLists 中的每个 entryList

    1. 对于 entryList 中的每个 entry

      1. 追加 entry步骤steps

      2. 对于 entry文档状态嵌套历史记录 中的每个 nestedHistory追加 nestedHistory条目列表entryLists

  5. 返回 steps排序

某些操作会导致可遍历对象 导航 到新的资源。

例如,点击超链接提交表单 以及 window.open()location.assign() 方法都可以导致页面导航。

虽然在本标准中,“导航” 一词特指 导航 算法,但这并不总是与 Web 开发人员或用户感知一致。例如:

在我们深入 导航算法 本身之前,我们需要建立几个重要的结构,它将使用这些结构。

源快照参数 结构 用于捕获从启动导航的 文档 中获取的数据。它在导航开始时进行快照,并在整个导航的生命周期中使用。它包含以下

有瞬态激活
布尔值
沙箱标志
一个 沙箱标志集
允许下载
布尔值
获取客户端
一个 环境设置对象,仅用作 请求客户端
源策略容器
一个 策略容器

快照源快照参数,给定一个 文档 sourceDocument,返回一个新的 源快照参数,其中包含以下内容:

有瞬态激活
如果 sourceDocument相关全局对象瞬态激活,则为 true;否则为 false。
沙箱标志
sourceDocument活动沙箱标志集
允许下载
如果 sourceDocument活动沙箱标志集 设置了 沙箱下载浏览上下文标志,则为 false;否则为 true。
获取客户端
sourceDocument相关设置对象
源策略容器
sourceDocument策略容器

目标快照参数 结构 用于捕获从被导航的 可导航对象 中获取的数据。与 源快照参数 一样,它在导航开始时进行快照,并在整个导航的生命周期中使用。它包含以下

沙箱标志
一个 沙箱标志集

快照目标快照参数,给定一个 可导航对象 targetNavigable,返回一个新的 目标快照参数,其 沙箱标志 设置为 确定创建沙箱标志 的结果,该结果基于 targetNavigable活动浏览上下文targetNavigable容器


导航过程的大部分内容都与确定如何创建一个新的 文档 有关,最终将在 创建和初始化 Document 对象 算法中进行。该算法的参数通过一个 导航参数 结构 进行跟踪,该结构包含以下

id
null 或一个 导航 ID
可导航对象
要被导航的 可导航对象
请求
null 或一个 请求,该请求启动了导航
响应
一个 响应,该响应最终被导航到(可能是一个 网络错误
获取控制器
null 或一个 获取控制器
提早提交提示
null 或一个算法,该算法接受一个 文档,一旦它被创建
COOP 强制执行结果
一个 打开者策略强制执行结果,用于报告,并可能用于导致 浏览上下文组切换
保留的环境
null 或一个 环境,为新的 文档 保留
来源
一个 来源,用于新的 文档
策略容器
一个 策略容器,用于新的 文档
最终沙箱标志集
一个 沙箱标志集,要对新的 文档 强制执行
打开者策略
一个 打开者策略,用于新的 文档
导航时序类型
一个 NavigationTimingType,用于 创建新的 文档 的导航时序条目
关于基本 URL
一个 URL 或 null,用于填充新的 文档关于基本 URL

一旦创建了 导航参数 结构,本标准不会改变其任何 。它们只被传递给其他算法。


一个 导航 ID 是在导航期间生成的 UUID 字符串。它用于与 WebDriver BiDi 规范交互,以及跟踪 正在进行的导航[WEBDRIVERBIDI]


文档 创建之后,相关 可遍历可导航对象会话历史记录 会被更新。 NavigationHistoryBehavior 枚举用于向 导航 算法指示所需的会话历史记录更新类型。它可以是以下之一:

"push"
一个常规的导航,它会添加一个新的 会话历史记录条目,并 清除前向会话历史记录
"replace"
一个导航,它将替换 活动的会话历史记录条目
"auto"
默认值,它将在 导航 算法的非常早的阶段转换为 "push" 或 "replace"。通常它会变为 "push",但在 某些情况下,它会变为 "replace"。

一个 历史记录处理行为 是一个 NavigationHistoryBehavior,它要么是 "push",要么是 "replace",即,它已从任何初始 "auto" 值解析出来。

导航必须替换,给定一个 URL url 和一个 文档 document,如果以下任何一个为 true:

其他情况下,通常(但不总是)会导致 "替换" 导航的是


平台的各个部分会跟踪用户是否参与导航。一个 用户导航参与 是以下之一

"浏览器 UI"
导航是由用户通过浏览器 UI 机制启动的。
"激活"
导航是由用户通过元素的 激活行为 启动的。
""
导航不是由用户启动的。

为了方便在某些调用站点使用,事件 event用户导航参与 定义如下

  1. 断言:此算法是在 激活行为 定义中调用的。

  2. 断言event类型 为 "点击"。

  3. 如果 eventisTrusted 初始化为 true,则返回 "激活"。

  4. 返回 ""。

7.4.2.2 开始导航

导航 一个 可导航的 navigable 到一个 URL url,使用一个 文档 sourceDocument,带有一个可选的 POST 资源、字符串或 null documentResource(默认为 null),一个可选的 响应 或 null response(默认为 null),一个可选的布尔值 exceptionsEnabled(默认为 false),一个可选的 NavigationHistoryBehavior historyHandling(默认为 "自动"),一个可选的 序列化状态 或 null navigationAPIState(默认为 null),一个可选的 条目列表 或 null formDataEntryList(默认为 null),一个可选的 引用策略 referrerPolicy(默认为空字符串),以及一个可选的 用户导航参与 userInvolvement(默认为 "")

  1. 如果 formDataEntryList 不为 null,则设 cspNavigationType 为 "表单提交";否则为 "其他"。

  2. sourceSnapshotParams 为根据 sourceDocument 调用 快照源快照参数 的结果。

  3. initiatorOriginSnapshotsourceDocument来源

  4. initiatorBaseURLSnapshotsourceDocument文档基准 URL

  5. navigationId 为根据 生成随机 UUID 的结果。 [WEBCRYPTO]

  6. 如果 周围代理 等于 navigable活动文档相关代理,则继续执行以下步骤。否则,在 navigable活动窗口 中,根据 导航和遍历任务源 排队一个全局任务 来继续执行以下步骤。

    我们这样做是因为我们将查看 navigable活动文档 的许多属性,这些属性理论上只能在相应的 事件循环 中访问。(但是,我们不想无条件地排队一个任务,因为 — 例如 — 同一事件循环的 片段导航 需要同步生效。)

    另一种实现策略是在事件循环中复制相关信息,或者复制到规范的“浏览器进程”中,以便在不排队任务的情况下进行查询。这可能在边缘情况下会导致与我们在此处指定的不同结果,在这些边缘情况下,相关属性已在目标事件循环中更改,但尚未被复制。需要进一步测试才能确定这些策略中哪一个最符合浏览器的行为,在这种有竞争的边缘情况下。

  7. 如果 navigable活动文档卸载计数器 大于 0,则调用 WebDriver BiDi 导航失败,并使用一个 WebDriver BiDi 导航状态,其 idnavigationId状态 为 "已取消",URLurl,并返回。

  8. containernavigable容器

  9. 如果 container 是一个 iframe 元素,并且根据 container 调用 将懒加载元素步骤 返回 true,则 停止观察懒加载元素的交叉点 container 并将 container懒加载恢复步骤 设置为 null。

  10. 如果根据 urlnavigable活动文档 导航必须为替换,则将 historyHandling 设置为 "替换"。

  11. 如果 navigable父级 不为 null,则将 navigable是否延迟 load 事件 设置为 true。

  12. targetBrowsingContextnavigable活动浏览上下文

  13. targetSnapshotParams 为根据 navigable 调用 快照目标快照参数 的结果。

  14. 调用 WebDriver BiDi 导航已启动,并使用 targetBrowsingContext 和一个新的 WebDriver BiDi 导航状态,其 idnavigationId状态 为 "挂起",URLurl

  15. 如果 navigable正在进行的导航 为 "遍历",则

    1. 使用 targetBrowsingContext 调用 WebDriver BiDi 导航失败,并使用新的 WebDriver BiDi 导航状态,其 idnavigationId状态 为 "已取消",urlurl

    2. 返回。

    任何尝试导航当前正在 遍历可导航对象 都会被忽略。

  16. navigable正在进行的导航 设置为 navigationId

    这将导致 navigable 的其他正在进行的导航被中止,因为在导航的某些阶段,对 正在进行的导航 的更改将导致进一步的工作被放弃。

  17. 如果 url方案 为 "javascript",那么

    1. 在给定 navigable活动窗口 上,针对 导航和遍历任务源 排队一个全局任务,以给定 navigableurlhistoryHandlinginitiatorOriginSnapshotcspNavigationType导航到 javascript: URL

    2. 返回。

  18. 如果以下条件全部为真

    1. navigationnavigable活动窗口导航 API

    2. 如果 documentResourcePOST 资源,则设 entryListForFiringformDataEntryList;否则为 null。

    3. 如果 navigationAPIState 不为 null,则设 navigationAPIStateForFiringnavigationAPIState;否则为 StructuredSerializeForStorage(undefined)。

    4. continue 为在 navigation 上以 导航类型 设置为 historyHandlingisSameDocument 设置为 false、用户参与度 设置为 userInvolvementformDataEntryList 设置为 entryListForFiring目标 URL 设置为 url 以及 navigationAPIState 设置为 navigationAPIStateForFiring 触发 push/replace/reload navigate 事件 的结果。

    5. 如果 continue 为 false,则返回。

    如果导航通过较早的 导航到片段 路径,则具有 "浏览器 UI" 的 userInvolvement 或由 跨源sourceDocument 启动的导航可能会触发 navigate 事件。

  19. 并行运行以下步骤

    1. unloadPromptCanceled 为针对 navigable活动文档包含的子级可导航对象 检查是否取消卸载 的结果。

    2. 如果 unloadPromptCanceled 为 true,或者 navigable正在进行的导航 不再是 navigationId,则

      1. 使用 targetBrowsingContext 调用 WebDriver BiDi 导航失败,并使用新的 WebDriver BiDi 导航状态,其 idnavigationId状态 为 "已取消",urlurl

      2. 中止这些步骤。

    3. 在给定 navigable活动窗口 上,针对 导航和遍历任务源 排队一个全局任务,以给定 navigable活动文档 中止文档及其子级

    4. 如果 url 匹配 about:blank 或为 about:srcdoc,那么

      1. documentState来源 设置为 initiatorOriginSnapshot

      2. documentStateabout 基本 URL 设置为 initiatorBaseURLSnapshot

    5. historyEntry 为新的 会话历史条目,其 URL 设置为 url,其 文档状态 设置为 documentState

    6. navigationParams 为 null。

    7. 如果 response 不为 null

      导航 算法仅在 objectembed 处理模型中或在处理初始响应后的 multipart/x-mixed-replace 响应 的部分时提供 响应

      1. policyContainer 为给定 响应URL、null、sourceDocument策略容器克隆navigable容器文档策略容器 以及 null 确定导航参数策略容器 的结果。

      2. finalSandboxFlagstargetSnapshotParams沙箱标志policyContainerCSP 列表CSP 衍生的沙箱标志并集

      3. responseOrigin 为给定 responseURLfinalSandboxFlags 以及 documentState启动来源 确定来源 的结果。

      4. coop 为新的 打开策略

      5. coopEnforcementResult 为新的 打开策略执行结果,具有

        url
        responseURL
        来源
        responseOrigin
        打开者策略
        coop
      6. navigationParams 设置为新的 导航参数,具有

        id
        navigationId
        可导航对象
        可导航对象
        请求
        null
        响应
        响应
        获取控制器
        null
        提早提交提示
        null
        COOP 强制执行结果
        coopEnforcementResult
        保留的环境
        null
        来源
        responseOrigin
        策略容器
        policyContainer
        最终沙箱标志集
        finalSandboxFlags
        打开者策略
        coop
        导航时序类型
        "导航"
        关于基本 URL
        documentStateabout 基本 URL
    8. 针对 historyEntry,给定 navigable、"导航"、sourceSnapshotParamstargetSnapshotParamsnavigationIdnavigationParamscspNavigationType 以及 允许 POST 设置为 true 以及 完成步骤 设置为以下步骤 尝试填充历史条目的文档

      1. 将会话历史遍历步骤附加到 navigable可遍历对象,以给定 navigablehistoryHandling 以及 historyEntry 完成跨文档导航

7.4.2.3 结束导航

虽然通常的跨文档导航案例将首先尝试使用 填充会话历史条目,其中包含一个 Document,但所有未中止的导航最终都将调用以下算法之一。

7.4.2.3.1 通常的跨文档导航案例

完成跨文档导航,给定一个 可导航对象 navigable、一个 历史处理行为 historyHandling 和一个 会话历史条目 historyEntry

  1. 断言:这正在 navigable可遍历导航对象会话历史遍历队列 上运行。

  2. navigable是否延迟 load 事件 设置为 false。

  3. 如果 historyEntrydocument 为 null,则返回。

    这意味着 尝试填充历史条目的 document 最终没有创建 document,例如,导航被后续导航取消,204 No Content 响应等等。

  4. 如果以下条件全部为真

    则将 historyEntrydocument 状态可导航目标名称 设置为空字符串。

  5. 如果 historyHandling 为 "replace",则令 entryToReplacenavigable活动会话历史条目,否则为 null。

  6. traversablenavigable可遍历导航对象

  7. targetStep 为 null。

  8. targetEntries获取会话历史条目 用于 navigable 的结果。

  9. 如果 entryToReplace 为 null,则

    1. 清除 traversable 的前向会话历史

    2. targetStep 设置为 traversable当前会话历史步骤 + 1。

    3. historyEntry步骤 设置为 targetStep

    4. 追加 historyEntrytargetEntries

    否则

    1. 替换 targetEntries 中的 entryToReplacehistoryEntry

    2. historyEntry步骤 设置为 entryToReplace步骤

    3. 如果 historyEntrydocument 状态起源entryToReplacedocument 状态起源 同源,则将 historyEntry导航 API 密钥 设置为 entryToReplace导航 API 密钥

    4. targetStep 设置为 traversable当前会话历史步骤

  10. 应用推送/替换历史步骤 targetSteptraversable,给定 historyHandling

7.4.2.3.2 javascript: URL 特殊情况

javascript: URL 在问题跟踪器中有一个 专用标签,记录了与它们规范相关的各种问题。

导航到 javascript: URL,给定一个 可导航对象 targetNavigable、一个 URL url、一个 历史处理行为 historyHandling、一个 起源 initiatorOrigin 和一个字符串 cspNavigationType

  1. 断言historyHandling 为 "replace"。

  2. 设置 targetNavigable 的正在进行的导航 为 null。

  3. 如果 initiatorOrigintargetNavigable活动 document起源 同源域,则返回。

  4. request 为一个新的 请求,其 URLurl

    这是一个合成 请求,仅用于连接到下一步。它永远不会访问网络。

  5. 如果 应该通过内容安全策略阻止类型为的导航请求吗? 给定 requestcspNavigationType 为 "Blocked",则返回。 [CSP]

  6. newDocument评估 javascript: URL 给定 targetNavigableurlinitiatorOrigin 的结果。

  7. 如果 newDocument 为 null,则返回。

    在这种情况下,一些 JavaScript 代码被执行,但没有创建新的 Document,因此我们将不会执行导航。

  8. 断言initiatorOriginnewDocument起源

  9. entryToReplacetargetNavigable活动会话历史条目

  10. oldDocStateentryToReplacedocument 状态

  11. documentState 为一个新的 document 状态,其中

    document
    newDocument
    历史策略容器
    如果 oldDocState历史策略容器 不为 null,则为其 克隆;否则为 null
    请求来源
    oldDocState请求来源
    请求来源策略
    oldDocState请求来源策略 或者这应该是传递给 navigatereferrerPolicy 吗?
    启动来源
    发起者起源
    来源
    发起者起源
    关于基本 URL
    oldDocState关于基本 URL
    资源
    null
    曾经填充
    true
    可导航对象的目标名称
    oldDocState可导航目标名称
  12. historyEntry 为一个新的 会话历史条目,其中

    URL
    entryToReplaceURL
    document 状态
    documentState

    对于 URL,我们使用 url,即 navigate 算法调用的实际 javascript: URL。这意味着 javascript: URL 永远不会存储在会话历史中,因此也永远无法遍历到。

  13. 追加会话历史遍历步骤targetNavigable可遍历导航对象,以 完成跨文档导航,其中包含 targetNavigablehistoryHandlinghistoryEntry

评估 javascript: URL,给定一个 可导航对象 targetNavigable、一个 URL url 和一个 起源 newDocumentOrigin

  1. urlString 为在 url 上运行 URL 序列化器 的结果。

  2. encodedScriptSource 为从 urlString 中删除前导 "javascript:" 的结果。

  3. scriptSourceUTF-8 解码百分比解码encodedScriptSource

  4. settingstargetNavigable活动文档相关设置对象

  5. baseURLsettingsAPI 基础 URL

  6. script 为使用 scriptSourcesettingsbaseURL默认脚本获取选项 创建经典脚本 的结果。

  7. evaluationStatus运行经典脚本 script 的结果。

  8. result 为 null。

  9. 如果 evaluationStatus 是正常完成,并且 evaluationStatus.[[Value]] 是一个字符串,则将 result 设置为 evaluationStatus.[[Value]]。

  10. 否则,返回 null。

  11. response 为一个新的 响应,其中包含

    URL
    targetNavigable活动文档URL
    头列表
    « (`Content-Type`, `text/html;charset=utf-8`) »
    主体
    resultUTF-8 编码作为主体

    对 UTF-8 的编码意味着,一旦 HTML 解析器对响应主体进行解码,则不成对的 代理项 将无法进行往返。

  12. policyContainertargetNavigable活动文档策略容器

  13. finalSandboxFlagspolicyContainerCSP 列表CSP 衍生的沙箱标志

  14. cooptargetNavigable活动文档跨源打开者策略

  15. coopEnforcementResult 为一个新的 打开者策略执行结果,其中包含

    url
    url
    来源
    新文档来源
    打开者策略
    coop
  16. navigationParams 为一个新的 导航参数,其中包含

    id
    navigationId
    可导航对象
    targetNavigable
    请求
    null 这会导致生成的 文档 的来源为 null;这是正确的吗?
    响应
    响应
    获取控制器
    null
    提早提交提示
    null
    COOP 强制执行结果
    coopEnforcementResult
    保留的环境
    null
    来源
    新文档来源
    策略容器
    policyContainer
    最终沙箱标志集
    finalSandboxFlags
    打开者策略
    coop
    导航时序类型
    "navigate"
    关于基本 URL
    targetNavigable活动文档关于基础 URL
  17. 返回使用 navigationParams 加载 HTML 文档 的结果。

7.4.2.3.3 片段导航

要使用 可导航对象 navigableURL url历史处理行为 historyHandling用户导航参与 userInvolvement序列化状态-或-null navigationAPIState导航 ID navigationId 导航到片段

  1. navigationnavigable活动窗口导航 API

  2. destinationNavigationAPIStatenavigable活动会话历史条目导航 API 状态

  3. 如果 navigationAPIState 不为 null,则将 destinationNavigationAPIState 设置为 navigationAPIState

  4. continuenavigation 上触发 push/replace/reload navigate 事件 的结果,其中 navigationType 设置为 historyHandlingisSameDocument 设置为 true,userInvolvement 设置为 userInvolvementdestinationURL 设置为 urlnavigationAPIState 设置为 destinationNavigationAPIState

  5. 如果 continue 为 false,则返回。

  6. historyEntry 为一个新的 会话历史条目,其中包含

    URL
    url
    document 状态
    navigable活动会话历史条目文档状态
    导航 API 状态
    destinationNavigationAPIState
    滚动恢复模式
    navigable活动会话历史条目滚动恢复模式

    对于使用 navigation.navigate() 执行的导航,state 选项提供的值将用于新的 导航 API 状态。(如果未为此选项提供值,则将其设置为 undefined 的序列化。)对于其他片段导航,包括用户启动的导航,导航 API 状态 将从前一个条目中继承。

    经典历史 API 状态 永远不会被继承。

  7. entryToReplacenavigable活动会话历史条目(如果 historyHandling 为 "replace",否则为 null)。

  8. historynavigable活动文档历史对象

  9. scriptHistoryIndexhistory索引

  10. scriptHistoryLengthhistory长度

  11. 如果 historyHandling 为 "push",则

    1. history状态 设置为 null。

    2. 递增 scriptHistoryIndex

    3. scriptHistoryLength 设置为 scriptHistoryIndex + 1。

  12. navigable活动文档URL 设置为 url

  13. navigable活动会话历史条目 设置为 historyEntry

  14. 更新文档以进行历史步骤应用,其中包含 navigable活动文档historyEntry、true、scriptHistoryIndexscriptHistoryLengthhistoryHandling

    由于单个片段导航,该算法将被调用两次:一次是同步调用,其中设置了最佳猜测值 scriptHistoryIndexscriptHistoryLengthhistory.state 被设置为 null,并且触发了各种事件;另一次是异步调用,其中设置了索引和长度的最终值,history.state 保持不变,并且不会触发任何事件。

  15. 滚动到片段,其中包含 navigable活动文档

    如果滚动失败,因为 文档 是新的,并且相关 ID 尚未解析,则第二次异步调用 更新文档以进行历史步骤应用 将负责滚动。

  16. traversablenavigable可遍历导航对象

  17. 将涉及 navigable 的以下会话历史同步导航步骤 附加到 traversable

    1. 完成同一文档导航,其中包含 traversablenavigablehistoryEntryentryToReplacehistoryHandling

    2. 使用 navigable活动浏览上下文 和一个新的 WebDriver BiDi 导航状态 调用 WebDriver BiDi 片段导航,该状态的 idnavigationIdurlurlstatus 为 "complete"。

要使用 可遍历导航对象 traversable可导航对象 targetNavigable会话历史条目 targetEntry会话历史条目-或-null entryToReplace历史处理行为 historyHandling 完成同一文档导航

这被 片段导航URL 和历史更新步骤 都使用,这是对会话历史的唯一同步更新。由于是同步的,这些算法是在 顶级可遍历对象会话历史遍历队列 之外执行的。这使得它们与 顶级可遍历对象当前会话历史步骤 不同步,因此该算法用于解决由于竞争条件造成的冲突。

  1. 断言: 正在运行在 traversable会话历史遍历队列 上。

  2. 如果 targetNavigable活动会话历史条目 不是 targetEntry,则返回。

  3. targetStep 为 null。

  4. targetEntries获取会话历史条目 针对 targetNavigable 的结果。

  5. 如果 entryToReplace 为 null,则

    1. 清除前向会话历史 traversable

    2. targetStep 设置为 traversable当前会话历史步骤 + 1。

    3. targetEntry步骤 设置为 targetStep

    4. 追加 targetEntrytargetEntries

    否则

    1. 替换 entryToReplacetargetEntrytargetEntries 中。

    2. targetEntry步骤 设置为 entryToReplace步骤

    3. targetStep 设置为 traversable当前会话历史步骤

  6. 应用 push/replace 历史步骤 targetSteptraversable 给定 historyHandling

    即使对于 "替换" 导航,也会这样做,因为它可以解决多个同步导航之间的竞争条件。

7.4.2.3.4 非 Fetch 方案和外部软件

尝试创建非 Fetch 方案文档 的输入是 非 Fetch 方案导航参数 结构。它是 导航参数 的轻量级版本,它只包含与非 Fetch 方案 导航案例相关的参数。它有以下 条目

id
null 或 导航 ID
可导航对象
正在经历导航的 可导航
URL
URL
目标快照沙盒标志
目标快照参数沙盒标志 在导航期间出现
源快照具有瞬态激活
源快照参数具有瞬态激活 布尔值在激活期间出现
启动来源

一个 来源 可能用于用户界面提示,以确认调用外部软件包。

这与 文档状态发起者来源 略有不同,因为 非 Fetch 方案导航参数发起者来源 跟踪重定向到重定向链中的最后一个 Fetch 方案 URL,该链以非 Fetch 方案 URL 结束。

导航时序类型
一个 NavigationTimingType 用于 创建导航计时条目 用于新的 Document

尝试创建非 Fetch 方案文档,给定 非 Fetch 方案导航参数 navigationParams

  1. urlnavigationParamsURL
  2. navigablenavigationParams可导航
  3. 如果 url 要使用不会影响 navigable 的机制处理,例如,因为 url方案 由外部处理,那么

    1. 移交到外部软件 给定 urlnavigablenavigationParams目标快照沙盒标志navigationParams源快照具有瞬态激活 以及 navigationParams发起者来源

    2. 返回 null。

  4. 通过显示某种内联内容来处理 url,例如,因为指定的方案不是支持的协议之一,或者内联提示允许用户为给定的方案选择 注册的处理程序,从而显示错误消息。返回 显示内联内容 给定 navigablenavigationParamsid 以及 navigationParams导航计时类型 的结果。

    在使用注册的处理程序的情况下,导航 将使用新的 URL 调用。

移交到外部软件 给定 URL响应 resource可导航 navigable沙盒标志集 sandboxFlags、布尔值 hasTransientActivation 以及 来源 initiatorOrigin,用户代理应该

  1. 如果以下条件全部为真

    则返回,而不调用外部软件包。

    在 iframe 内部的导航到外部软件,用户可能会将其视为新的弹出窗口或新的顶级导航。这就是它在沙盒 iframe 中被允许的原因,前提是指定了以下内容之一:allow-popupsallow-top-navigationallow-top-navigation-by-user-activation 或者 allow-top-navigation-to-custom-protocols

  2. 执行 resource 的适当移交,同时尝试减轻此行为是尝试利用目标软件的风险。例如,用户代理可能会提示用户确认是否允许 initiatorOrigin 调用相关外部软件。特别是,如果 hasTransientActivation 为 false,那么用户代理在事先没有用户确认的情况下,不应调用外部软件包。

    例如,目标软件的 URL 处理程序中可能存在漏洞,敌对页面会尝试通过欺骗用户点击链接来利用它。

7.4.2.4 阻止导航

在导航过程的早期,一些情况可能会介入并使整个过程停止。当多个 可导航 同时导航时,这可能特别令人兴奋,因为这可能是由于会话历史遍历造成的。

给定 源快照参数 sourceSnapshotParams可导航 source沙盒允许导航 第二个 可导航 target,如果以下步骤返回 true

  1. 如果 sourcetarget,则返回 true。

  2. 如果 sourcetarget 的祖先,则返回 true。

  3. 如果 targetsource 的祖先,则

    1. 如果 target 不是 顶级可遍历,则返回 true。

    2. 如果 sourceSnapshotParams具有瞬态激活 为 true,并且 sourceSnapshotParams沙盒标志沙盒顶级导航(使用用户激活)浏览上下文标志 被设置,则返回 false。

    3. 如果 sourceSnapshotParams具有瞬态激活 为 false,并且 sourceSnapshotParams沙盒标志沙盒顶级导航(不使用用户激活)浏览上下文标志 被设置,则返回 false。

    4. 返回 true。

  4. 如果 target顶级可遍历

    1. 如果 sourcetarget一个允许的沙盒导航器,则返回 true。

    2. 如果 sourceSnapshotParams沙盒标志沙盒导航浏览上下文标志 被设置,则返回 false。

    3. 返回 true。

  5. 如果 sourceSnapshotParams沙盒标志沙盒导航浏览上下文标志 被设置,则返回 false。

  6. 返回 true。

检查是否取消卸载一个列表可导航项navigablesThatNeedBeforeUnload,给定一个可选的可遍历可导航项traversable,一个可选的整数targetStep,以及一个可选的用户导航参与或空userInvolvementForNavigateEvent,运行以下步骤。它们返回 "canceled-by-beforeunload"、"canceled-by-navigate" 或 "continue"。

  1. documentsToFireBeforeunload成为navigablesThatNeedBeforeUnload中每个活动文档

  2. unloadPromptShown为 false。

  3. finalStatus为 "continue"。

  4. 如果给定了traversable,那么

    1. 断言targetStepuserInvolvementForNavigateEvent 被给出。

    2. targetEntry成为给定traversabletargetStep获取目标历史记录条目的结果。

    3. 如果targetEntry 不是traversable当前会话历史记录条目,并且targetEntry文档状态traversable当前会话历史记录条目文档状态 相同,那么

      在这种情况下,我们将为traversable 触发navigate 事件。因为在某些情况下 它可能被取消,我们需要与其他遍历 navigate 事件 分开进行,这些事件将在稍后发生。

      此外,因为我们希望beforeunload 事件在navigate 事件之前触发,这意味着我们需要为traversable 触发beforeunload(如果适用),而不是在下面的documentsToFireBeforeunload 循环中进行。

      1. 断言userInvolvementForNavigateEvent 不为空。

      2. eventsFired 为 false。

      3. needsBeforeunload 为 true,如果navigablesThatNeedBeforeUnload 包含traversable;否则为 false。

      4. 如果needsBeforeunload 为 true,那么从documentsToFireBeforeunload删除traversable活动文档

      5. 在全局任务队列中排队,在给定traversable活动窗口导航和遍历任务源 上执行以下步骤

        1. 如果needsBeforeunload 为 true,那么

          1. 让 (unloadPromptShownForThisDocumentunloadPromptCanceledByThisDocument) 成为运行给定traversable活动文档 和 false 的触发 beforeunload 的步骤 的结果。

          2. 如果unloadPromptShownForThisDocument 为 true,那么将unloadPromptShown 设置为 true。

          3. 如果unloadPromptCanceledByThisDocument 为 true,那么将finalStatus 设置为 "canceled-by-beforeunload"。

        2. 如果finalStatus 为 "canceled-by-beforeunload",那么中止这些步骤。

        3. navigation 成为traversable活动窗口导航 API

        4. navigateEventResult 成为在给定targetEntryuserInvolvementForNavigateEventnavigation触发遍历 navigate 事件 的结果。

        5. 如果navigateEventResult 为 false,那么将finalStatus 设置为 "canceled-by-navigate"。

        6. eventsFired 设置为 true。

      6. 等待eventsFired 为 true。

      7. 如果finalStatus 不是 "continue",那么返回finalStatus

  5. totalTasks 成为documentsThatNeedBeforeunload大小

  6. completedTasks 为 0。

  7. 对于 documents 的每个document在全局任务队列中排队,在给定document相关全局对象导航和遍历任务源 上运行以下步骤

    1. 让 (unloadPromptShownForThisDocumentunloadPromptCanceledByThisDocument) 成为运行给定documentunloadPromptShown触发 beforeunload 的步骤 的结果。

    2. 如果unloadPromptShownForThisDocument 为 true,那么将unloadPromptShown 设置为 true。

    3. 如果unloadPromptCanceledByThisDocument 为 true,那么将finalStatus 设置为 "canceled-by-beforeunload"。

    4. completedTasks 加 1。

  8. 等待completedTasks 等于totalTasks

  9. 返回finalStatus

给定一个Document document 和一个布尔值unloadPromptShown触发 beforeunload 的步骤

  1. unloadPromptCanceled 为 false。

  2. document卸载计数器 加 1。

  3. document相关代理事件循环终止嵌套级别 加 1。

  4. eventFiringResult 成为触发事件 的结果,该事件名为beforeunload,在document相关全局对象 上,使用BeforeUnloadEvent可取消 属性初始化为 true。

  5. document相关代理事件循环终止嵌套级别 减 1。

  6. 如果以下条件全部为真

    1. unloadPromptShown 设置为 true。

    2. 使用document相关全局对象、"beforeunload" 和 "" 调用WebDriver BiDi 用户提示打开

    3. 询问用户是否确认他们希望卸载该文档,并在等待用户响应时暂停

      显示给用户的消息不可自定义,而是由用户代理决定。特别是,returnValue 属性的实际值会被忽略。

    4. 如果用户没有确认页面导航,那么将unloadPromptCanceled 设置为 true。

    5. 使用document相关全局对象,以及如果unloadPromptCanceled 为 false 则为 true,否则为 false 调用WebDriver BiDi 用户提示关闭

  7. document卸载计数器 减 1。

  8. 返回 (unloadPromptShownunloadPromptCanceled)。

7.4.2.5 中止导航

每个可导航项 都有一个正在进行的导航,它是一个导航 ID、"traversal" 或 null,最初为 null。它用于跟踪导航中止,并防止在遍历 期间发生任何导航。

要为一个可导航项navigable正在进行的导航 设置为newValue

  1. 如果navigable正在进行的导航 等于newValue,那么返回。

  2. 通知导航 API 关于中止导航,给定navigable

  3. navigable正在进行的导航 设置为newValue

7.4.3 重新加载和遍历

重新加载一个可导航项navigable,给定一个可选的序列化状态或空navigationAPIState(默认 null)和一个可选的用户导航参与userInvolvement(默认 "")

  1. 如果userInvolvement 不是 "浏览器 UI",那么

    1. navigation 成为navigable活动窗口导航 API

    2. destinationNavigationAPIState 成为navigable活动会话历史记录条目导航 API 状态

    3. 如果 navigationAPIState 不为 null,则将 destinationNavigationAPIState 设置为 navigationAPIState

    4. continue 为在 navigation触发 push/replace/reload navigate 事件 的结果,其中 navigationType 设置为 "reload",isSameDocument 设置为 false,userInvolvement 设置为 userInvolvementdestinationURL 设置为 navigable活动会话历史条目URL,以及 navigationAPIState 设置为 destinationNavigationAPIState

    5. 如果 continue 为 false,则返回。

  2. navigable活动会话历史条目文档状态重新加载挂起 设置为 true。

  3. traversablenavigable可遍历的导航对象

  4. 将以下会话历史遍历步骤 附加到 traversable

    1. 将重新加载历史步骤 应用于 traversable

为了 按增量遍历历史,给定一个 可遍历的导航对象 traversable,一个整数 delta,以及一个可选的 Document sourceDocument

  1. sourceSnapshotParamsinitiatorToCheck 为 null。

  2. userInvolvement 为 "浏览器 UI"。

  3. 如果给定了 sourceDocument,则

    1. sourceSnapshotParams 设置为给定 sourceDocument快照源快照参数 的结果。

    2. initiatorToCheck 设置为 sourceDocument节点导航对象

    3. userInvolvement 设置为 ""。

  4. 将以下会话历史遍历步骤 附加到 traversable

    1. allStepstraversable获取所有使用过的历史步骤 的结果。

    2. currentStepIndextraversable当前会话历史步骤allSteps 中的索引。

    3. targetStepIndexcurrentStepIndex 加上 delta

    4. 如果 allSteps[targetStepIndex] 不存在,则中止这些步骤。

    5. 应用遍历历史步骤 allSteps[targetStepIndex] 到 traversable,给定 sourceSnapshotParamsinitiatorToCheckuserInvolvement

除了 navigate 算法之外,会话历史条目 可以通过一种额外的机制来推送或替换,即 URL 和历史更新步骤。这些步骤的最著名的调用者是 history.replaceState()history.pushState() API,但标准的各个其他部分也需要对 活动历史条目 进行更新,它们使用这些步骤来执行此操作。

URL 和历史更新步骤,给定一个 Document document,一个 URL newURL,一个可选的 序列化状态-或-null serializedData(默认值为 null),以及一个可选的 历史处理行为 historyHandling(默认值为 "replace"),分别是

  1. navigabledocument节点导航对象

  2. activeEntrynavigable活动会话历史条目

  3. newEntry 为一个新的 会话历史条目,其包含

    URL
    newURL
    序列化状态
    如果 serializedData 不为 null,则为 serializedData;否则为 activeEntry经典历史 API 状态
    document 状态
    activeEntry文档状态
    滚动恢复模式
    activeEntry滚动恢复模式
    持久化用户状态
    activeEntry持久化用户状态
  4. 如果 document初始 about:blank 为 true,则将 historyHandling 设置为 "replace"。

    这意味着 pushState()初始 about:blank Document 上的行为与 replaceState() 调用相同。

  5. entryToReplaceactiveEntry,如果 historyHandling 为 "replace",否则为 null。

  6. 如果 historyHandling 为 "push",则

    1. 增加 document历史对象索引

    2. document历史对象长度 设置为其 索引 + 1。

    这些是用于立即同步访问的临时最佳猜测值。

  7. 如果 serializedData 不为 null,则 恢复历史对象状态,给定 documentnewEntry

  8. documentURL 设置为 newURL

    由于这不是 导航 也不是 历史遍历,因此它不会导致 hashchange 事件被触发。

  9. document最新条目 设置为 newEntry

  10. navigable活动会话历史条目 设置为 newEntry

  11. 更新相同文档导航的导航 API 条目,给定 document相关全局对象导航 APInewEntryhistoryHandling

  12. traversablenavigable可遍历的导航对象

  13. 将以下涉及 navigable 的会话历史同步导航步骤 附加到 traversable

    1. 完成相同文档导航,给定 traversablenavigablenewEntryentryToReplacehistoryHandling

尽管 片段导航URL 和历史更新步骤 都执行同步历史更新,但只有片段导航包含对 更新文档以应用历史步骤 的同步调用。相反,URL 和历史更新步骤 在上述算法中执行一些选择的更新,省略其他更新。这在一定程度上是一个不幸的历史事故,通常会导致 Web 开发人员对这种不一致感到沮丧。例如,这意味着 popstate 事件会针对片段导航触发,但不会针对 history.pushState() 调用触发。

7.4.5 填充会话历史条目

概述 中所述,导航遍历 都涉及创建 会话历史条目,然后尝试填充其 document 成员,以便它可以在 导航对象 内部呈现。

这涉及以下几种方式之一:使用 已给定的响应;使用 会话历史条目 中存储的 srcdoc 资源;或 获取。该过程有几种失败模式,这些模式可能会导致什么也不做(使 导航对象 停留在当前 活动 Document 上)或可能导致使用 错误文档 填充 会话历史条目

为了尝试填充历史条目文档,针对一个会话历史条目 entry,给定一个可导航对象 navigable,一个NavigationTimingType navTimingType,一个源快照参数 sourceSnapshotParams,一个目标快照参数 targetSnapshotParams,一个可选的导航ID 或 null navigationId(默认为 null),一个可选的导航参数 或 null navigationParams(默认为 null),一个可选的字符串 cspNavigationType(默认为 "other"),一个可选的布尔值allowPOST(默认为 false),以及可选的算法步骤completionSteps(默认为空算法)。

  1. 断言:此操作正在并行执行

  2. 断言:如果 navigationParams 不为 null,则 navigationParams响应 不为 null。

  3. currentBrowsingContextnavigable活动浏览上下文

  4. documentResourceentry文档状态资源

  5. 如果 navigationParams 为 null,则

    1. 如果 documentResource 是一个字符串,则将 navigationParams 设置为根据 entrynavigabletargetSnapshotParamsnavigationIdnavTimingType 从 srcdoc 资源创建导航参数 的结果。

    2. 否则,如果以下所有条件都为真

      • entryURL方案 是一个获取方案;并且

      • documentResource 为 null,或 allowPOST 为 true 且 documentResource请求体 不为失败,

      则将 navigationParams 设置为根据 entrynavigablesourceSnapshotParamstargetSnapshotParamscspNavigationTypenavigationIdnavTimingType 通过获取创建导航参数 的结果。

    3. 否则,如果 entryURL方案 不是一个获取方案,则将 navigationParams 设置为一个新的非获取方案导航参数,其包含以下内容:

      id
      navigationId
      可导航对象
      可导航对象
      URL
      entryURL
      目标快照沙盒标志
      targetSnapshotParams沙盒标志
      源快照具有瞬态激活
      sourceSnapshotParams具有瞬态激活
      启动来源
      entry文档状态发起者来源
      导航时序类型
      navTimingType
  6. 导航和遍历任务源上,针对 navigable活动窗口排队一个全局任务,以执行以下步骤

    1. 如果 navigable正在进行的导航 不再等于 navigationId,则运行 completionSteps 并中止这些步骤。

    2. saveExtraDocumentState 为 true。

      通常,在我们最终填充 entry文档状态文档 的情况下,我们随后希望将该 Document 中的某些状态保存到 entry 中。这将确保如果未来存在对 entry 的遍历,而其 文档 已被销毁,则可以在创建新的 Document 时使用该状态。

      但是,在某些特定情况下,保存状态将无济于事。对于这些情况,我们将在本算法的后面将 saveExtraDocumentState 设置为 false。

    3. 如果 navigationParams 是一个非获取方案导航参数,则

      1. entry文档状态文档 设置为运行 尝试创建非获取方案文档(根据 navigationParams)的结果。

        这会导致将 entry文档状态文档 设置为 null,例如,在移交给外部软件时。

      2. saveExtraDocumentState 设置为 false。

    4. 否则,如果以下任何条件为真

      1. entry文档状态文档 设置为 为没有 DOM 的内联内容创建文档(根据 navigable、null 和 navTimingType)的结果。内联内容应向用户指示发生的错误类型。

      2. 使文档无法恢复(根据 entry文档状态文档 和 "navigation-failure")。

      3. saveExtraDocumentState 设置为 false。

      4. 如果 navigationParams 不为 null,则

        1. 运行 navigationParams保留环境环境丢弃步骤

        2. 使用 currentBrowsingContext 和一个新的 WebDriver BiDi 导航状态(其 IDnavigationId状态 为 "canceled",URLnavigationParams响应URL调用 WebDriver BiDi 导航失败

    5. 否则,如果 navigationParams响应状态 不是 204 且不是 205,则将 entry文档状态文档 设置为使用 navigationParamssourceSnapshotParamsentry文档状态发起者来源 执行 加载文档 的结果。

      这可能导致将 entry文档状态文档 设置为 null,例如,在 移交到外部软件 时。

    6. 如果 entry文档状态文档 不为 null,则

      1. entry文档状态已填充 设置为 true。

      2. 如果 saveExtraDocumentState 为 true

        1. documententry文档状态文档

        2. entry文档状态来源 设置为 document来源

        3. 如果 documentURL 需要将策略容器存储在历史记录中,则

          1. 断言navigationParams 是一个 导航参数(即,既不是 null 也不是 非获取方案导航参数)。

          2. entry文档状态历史记录策略容器 设置为 navigationParams策略容器

      3. 如果 entry文档状态请求来源 为 "client",并且 navigationParams 是一个 导航参数(即,既不是 null 也不是 非获取方案导航参数),则

        1. 断言navigationParams请求 不为 null。

        2. entry文档状态请求来源 设置为 navigationParams请求来源

    7. 运行 completionSteps

为了 从 srcdoc 资源创建导航参数,需要一个 会话历史记录项 entry,一个 可导航对象 navigable,一个 目标快照参数 targetSnapshotParams,一个 导航 ID 或 null navigationId,以及一个 NavigationTimingType navTimingType

  1. documentResourceentry文档状态资源

  2. response 为新的 响应,其具有

    URL
    about:srcdoc
    头列表
    « (`Content-Type`, `text/html`) »
    主体
    documentResourceUTF-8 编码作为主体
  3. responseOrigin 为使用 responseURLtargetSnapshotParams沙盒标志entry文档状态来源 执行 确定来源 的结果。

  4. coop 为新的 开启策略

  5. coopEnforcementResult 为新的 开启策略执行结果,其具有

    url
    responseURL
    来源
    responseOrigin
    打开者策略
    coop
  6. policyContainer 为使用 responseURLentry文档状态历史记录策略容器、null、navigable容器文档策略容器 和 null 执行 确定导航参数策略容器 的结果。

  7. 返回新的 导航参数,其具有

    id
    navigationId
    可导航对象
    可导航对象
    请求
    null
    响应
    响应
    获取控制器
    null
    提早提交提示
    null
    COOP 强制执行结果
    coopEnforcementResult
    保留的环境
    null
    来源
    responseOrigin
    策略容器
    policyContainer
    最终沙箱标志集
    targetSnapshotParams沙盒标志
    打开者策略
    coop
    导航时序类型
    navTimingType
    关于基本 URL
    entry文档状态about 基础 URL

为了 通过获取创建导航参数,需要一个 会话历史记录项 entry,一个 可导航对象 navigable,一个 来源快照参数 sourceSnapshotParams,一个 目标快照参数 targetSnapshotParams,一个字符串 cspNavigationType,一个 导航 ID 或 null navigationId,以及一个 NavigationTimingType navTimingType,执行以下步骤。它们返回 导航参数非获取方案导航参数 或 null。

此算法修改了 entry

  1. 断言:这正在 并行 运行。

  2. documentResourceentry文档状态资源

  3. request 为新的 请求,其具有

    url
    entryURL
    client
    sourceSnapshotParams获取客户端
    destination
    "document"
    credentials 模式
    "include"
    使用 URL 凭据标志
    set
    重定向模式
    "manual"
    替换客户端 ID
    navigable活动文档相关设置对象id
    mode
    "navigate"
    来源
    entry文档状态请求来源
    来源策略
    entry文档状态请求来源策略
  4. 如果 documentResourcePOST 资源,则

    1. request方法 设置为 `POST`。

    2. request主体 设置为 documentResource请求主体

    3. 设置 `Content-Type` 为 documentResource请求内容类型,在 request头部列表 中。

  5. 如果 entry文档状态重新加载挂起 为 true,则将 request重新加载导航标志 设置为 true。

  6. 否则,如果 entry文档状态已填充 为 true,则将 request历史记录导航标志 设置为 true。

  7. 如果 sourceSnapshotParamshas transient activation 为真,则将 requestuser-activation 设置为真。

  8. 如果 navigablecontainer 不为空

    1. 如果 navigablecontainer 有一个 browsing context scope origin,则将 requestorigin 设置为该 browsing context scope origin

    2. requestdestination 设置为 navigablecontainerlocal name

    3. 如果 sourceSnapshotParamsfetch clientnavigablecontainer documentrelevant settings object,则将 requestinitiator type 设置为 navigablecontainerlocal name

      这确保只有容器触发的导航会被报告给资源计时。

  9. response 为空。

  10. responseOrigin 为空。

  11. fetchController 为空。

  12. coopEnforcementResult 为一个新的 opener policy enforcement result,包含

    url
    navigableactive documentURL
    来源
    navigableactive documentorigin
    打开者策略
    navigableactive documentopener policy
    当前上下文为导航源
    如果 navigableactive documentoriginentrydocument stateinitiator originsame origin,则为真,否则为假
  13. finalSandboxFlags 为一个空 sandboxing flag set

  14. responsePolicyContainer 为空。

  15. responseCOOP 为一个新的 opener policy

  16. locationURL 为空。

  17. currentURLrequestcurrent URL

  18. commitEarlyHints 为空。

  19. 当 true 时

    1. 如果 requestreserved client 不为空,且 currentURLorigin 不与 requestreserved clientcreation URLoriginsame,则

      1. requestreserved client 运行 environment discarding steps

      2. requestreserved client 设置为空。

      3. commitEarlyHints 设置为空。

        来自 early hint headers 的预加载链接在 same origin 重定向后保留在预加载缓存中,但在跨域重定向时会被丢弃。

    2. 如果 requestreserved client 为空,则

      1. topLevelCreationURLcurrentURL

      2. topLevelOrigin 为空。

      3. 如果 navigable 不是一个 top-level traversable,则

        1. parentEnvironmentnavigableparentactive documentrelevant settings object

        2. topLevelCreationURL 设置为 parentEnvironmenttop-level creation URL

        3. topLevelOrigin 设置为 parentEnvironmenttop-level origin

      4. requestreserved client 设置为一个新的 environment,其 id 为一个唯一的不可见字符串,target browsing contextnavigableactive browsing contextcreation URLcurrentURLtop-level creation URLtopLevelCreationURLtop-level origintopLevelOrigin

        创建的 environment 的 active service workerHandle Fetch 算法中进行 fetch 时设置,如果请求 URL 匹配服务工作者注册。 [SW]

    3. 如果 should navigation request of type be blocked by Content Security Policy? 给定 requestcspNavigationType 为 "Blocked" 的结果为 "Blocked",则将 response 设置为一个 network errorbreak[CSP]

    4. response 设置为空。

    5. 如果 fetchController 为空,则将 fetchController 设置为 fetching request 的结果,其中 processEarlyHintsResponse 设置为下面定义的 processEarlyHintsResponseprocessResponse 设置为下面定义的 processResponseuseParallelQueue 设置为 true。

      processEarlyHintsResponse 为以下给定一个 response earlyResponse 的算法

      1. 如果 commitEarlyHints 为空,则将 commitEarlyHints 设置为给定 earlyResponserequestreserved clientprocessing early hint headers 的结果。

      processResponse 为以下给定一个 response fetchedResponse 的算法

      1. response 设置为 fetchedResponse

    6. 否则,对 fetchController process the next manual redirect

      这将在我们第一次循环迭代中调用我们提供的 processResponse,从而设置 response

      导航手动处理重定向,因为导航是 Web 平台中唯一关心重定向到 mailto: URL 等的地方。

    7. 等待 response 不为空,或者 navigableongoing navigation 更改为不再等于 navigationId

      如果后一种情况发生,则 abort fetchController,并返回。

      否则,继续执行。

    8. 如果 requestbody 为空,则将 entrydocument stateresource 设置为空。

      Fetch 为特定重定向取消设置 body

    9. responsePolicyContainer 设置为给定 responserequestreserved clientcreating a policy container from a fetch response 的结果。

    10. finalSandboxFlags 设置为 targetSnapshotParamssandboxing flagsresponsePolicyContainerCSP listCSP-derived sandboxing flagsunion

    11. responseOrigin 设置为给定 responseURLfinalSandboxFlagsentrydocument stateinitiator origindetermining the origin 的结果。

      如果 response 是重定向,那么 responseURL 将是导致重定向到 response位置 URL 的 URL;它不会是 位置 URL 本身。

    12. 如果 navigable 是一个 顶级可遍历对象,那么

      1. responseCOOP 设置为 获取打开者策略 的结果,该策略基于 responserequest保留的客户端

      2. coopEnforcementResult 设置为 执行响应的打开者策略 的结果,该策略基于 navigable活动浏览上下文responseURLresponseOriginresponseCOOPcoopEnforcementResultrequest推荐来源

      3. 如果 finalSandboxFlags 不为空且 responseCOOP 不是 "unsafe-none",则将 response 设置为适当的 网络错误中断

        这会导致网络错误,因为不能同时使用打开者策略提供干净的状态到响应并对导航到该响应的结果进行沙盒化。

    13. 如果 response 不是一个 网络错误navigable 是一个 子可导航对象,并且执行 跨域资源策略检查 的结果,该检查基于 navigable容器文档来源navigable容器文档相关设置对象request目标response 和 true 是 **被阻止** 的,则将 response 设置为 网络错误中断

      这里我们针对 父可导航对象 而不是 navigable 本身运行 跨域资源策略检查。这是因为我们关注的是嵌入内容与父上下文之间的同源性,而不是导航源。

    14. locationURL 设置为 response位置 URL,该 URL 基于 currentURL片段

    15. 如果 locationURL 是失败或空值,则 中断

    16. 断言locationURL 是一个 URL

    17. entry经典历史 API 状态 设置为 StructuredSerializeForStorage(null)。

    18. oldDocStateentry文档状态

    19. entry文档状态 设置为新的 文档状态,其中包含

      历史策略容器
      如果 oldDocState历史策略容器 不为空,则使用 oldDocState克隆;否则为 null
      请求来源
      oldDocState推荐来源请求
      请求来源策略
      oldDocState推荐来源请求策略
      启动来源
      oldDocState启动来源
      来源
      oldDocState来源
      关于基本 URL
      oldDocState关于基础 URL
      资源
      oldDocState资源
      曾经填充
      oldDocState是否已填充
      可导航对象的目标名称
      oldDocState可导航目标名称

      对于导航情况,只有 entry 引用了 oldDocState,该状态是在 导航算法早期创建的。因此,对于导航,这在功能上只是对 entry文档状态 的更新。对于遍历情况,相邻的 会话历史条目 也可能引用 oldDocState,在这种情况下,即使我们更新了 entry文档状态,它们也会继续引用它。

      oldDocState历史策略容器 在遍历情况下仅在填充它之后才会不为空,这发生在导航到一个 需要将策略容器存储在历史记录中 的 URL 时。

      设置由以下 Jake 图 给出

      0123
      顶部/a/a#foo/a#bar/b

      还假设步骤 0、1 和 2 中条目共享的 文档状态 具有一个空值的 文档,即 bfcache 并不起作用。

      现在考虑我们遍历回步骤 2 的场景,但这次在获取 /a 时,服务器使用一个指向 /cLocation 标头进行响应。也就是说,locationURL 指向 /c,因此我们到达了此步骤,而不是 中断 循环。

      在这种情况下,我们替换了占据步骤 2 的 会话历史条目文档状态,但我们 **没有** 替换占据步骤 0 和 1 的条目的文档状态。由此产生的 Jake 图 如下所示

      0123
      顶部/a/a#foo/c#bar/b

      注意,即使我们最终回到了原始 URL 的重定向链中,我们也会执行此替换,例如,如果 /c 本身有一个指向 /aLocation 标头。这种情况最终会像这样

      0123
      顶部/a/a#foo/a#bar/b
    20. 如果 locationURL方案 不是一个 HTTP(S) 方案,那么

      1. entry文档状态资源 设置为 null。

      2. 中断.

    21. currentURL 设置为 locationURL

    22. entryURL 设置为 currentURL

    在这个循环结束时,我们将处于以下场景之一

    • locationURL 是失败,因为存在不可解析的 Location 标头。

    • locationURL 是 null,这可能是因为 response 是一个 网络错误,或者因为我们成功获取了没有 Location 标头的非 网络错误 HTTP(S) 响应。

    • locationURL 是一个 URL,该 URL 的方案不是 HTTP(S) 方案

  20. 如果 locationURL 是一个 URL,其 方案 不是 获取方案,则返回新的 非获取方案导航参数,其中包含

    id
    navigationId
    可导航对象
    可导航对象
    URL
    locationURL
    目标快照沙盒标志
    targetSnapshotParams沙盒标志
    源快照具有瞬态激活
    sourceSnapshotParams是否具有瞬态激活
    启动来源
    responseOrigin
    导航时序类型
    navTimingType

    此时,request当前 URL 是重定向链中最后一个具有 获取 方案URL,它在重定向到非 获取方案 URL 之前。正是这个 URL来源 将用作导航到非 获取方案 URL 的启动来源。

  21. 如果以下任何条件为真

    则返回 null。

    我们允许重定向到非 获取方案 URL,但重定向到 获取方案 URL 且非 HTTP(S) 将被视为网络错误。

  22. 断言locationURL 为 null,response 不是 网络错误

  23. resultPolicyContainer 为使用 responseURLentry文档状态历史策略容器sourceSnapshotParams源策略容器、null 和 responsePolicyContainer 执行 确定导航参数策略容器 的结果。

  24. 如果 navigable容器 是一个 iframe,并且 response时间允许传递标志 已设置,则将 容器待处理资源计时开始时间 设置为 null。

    如果 iframe 被允许报告资源计时,则我们无需运行其回退步骤,因为正常的报告将照常进行。

  25. 返回一个新的 导航参数,其包含以下内容:

    id
    navigationId
    可导航对象
    可导航对象
    请求
    请求
    响应
    响应
    获取控制器
    fetchController
    提早提交提示
    commitEarlyHints
    打开者策略
    responseCOOP
    保留的环境
    request保留客户端
    来源
    responseOrigin
    策略容器
    resultPolicyContainer
    最终沙箱标志集
    finalSandboxFlags
    COOP 强制执行结果
    coopEnforcementResult
    导航时序类型
    navTimingType
    关于基本 URL
    entry文档状态关于基准 URL

如果元素的 Document节点可导航对象 是一个 顶级可遍历对象,或者如果其 Document 的所有 祖先可导航对象 都有 活动文档,且这些文档的 起源 与元素的 节点文档起源 相同,则元素具有 浏览上下文范围起源。如果元素具有 浏览上下文范围起源,则其值为元素的 节点文档起源

此定义存在问题,需要调查以了解其本意表达的内容:请查看 issue #4703

加载文档,请根据给定的 导航参数 navigationParams源快照参数 sourceSnapshotParams起源 initiatorOrigin 执行以下步骤。它们将返回一个 Document 或 null。

  1. typenavigationParams响应计算类型

  2. 如果用户代理已配置为使用某种机制处理给定 type 的资源,而不是在 可导航对象 中呈现内容,则跳过此步骤。否则,如果 type 是以下类型之一:

    一个 HTML MIME 类型
    返回使用 navigationParams 加载 HTML 文档 的结果。
    一个 XML MIME 类型,但它不是 明确支持的 XML MIME 类型
    返回使用 navigationParamstype 加载 XML 文档 的结果。
    一个 JavaScript MIME 类型
    一个 JSON MIME 类型,但它不是 明确支持的 JSON MIME 类型
    "text/css"
    "text/plain"
    "text/vtt"
    返回使用 navigationParamstype 加载文本文档 的结果。
    "multipart/x-mixed-replace"
    返回使用 navigationParamssourceSnapshotParamsinitiatorOrigin 加载 multipart/x-mixed-replace 文档 的结果。
    支持的图像、视频或音频类型
    返回使用 navigationParamstype 加载媒体文档 的结果。
    "application/pdf"
    "text/pdf"
    如果用户代理的 PDF 查看器支持 为 true,则返回使用 navigationParams可导航对象 创建没有 DOM 的内联内容文档 的结果。

    否则,继续执行。

    一个 明确支持的 XML MIME 类型 是一个 XML MIME 类型,用户代理已配置为使用外部应用程序来呈现其内容,或者用户代理为此类型制定了专用处理规则。例如,具有内置 Atom 订阅阅读器的网页浏览器被认为明确支持 application/atom+xml MIME 类型。

    一个 明确支持的 JSON MIME 类型 是一个 JSON MIME 类型,用户代理已配置为使用外部应用程序来呈现其内容,或者用户代理为此类型制定了专用处理规则。

    在这两种情况下,外部应用程序或用户代理将 直接在 navigationParams可导航对象 中显示内容(例如,以本地方式呈现内容或显示错误消息,因为未支持指定的类型),或 将内容移交给外部软件。这两种情况都将在下面的步骤中发生。

  3. 否则,文档的 type 将导致资源不会影响 navigationParams可导航对象(例如,因为资源将被移交给外部应用程序,或者因为它是一种未知类型,将被 作为下载处理)。将内容移交给外部软件,使用 navigationParams响应navigationParams可导航对象navigationParams最终沙箱标志集sourceSnapshotParams是否具有瞬态激活initiatorOrigin

  4. 返回 null。

7.4.6 应用历史步骤

对于导航和遍历,一旦我们了解了在会话历史中要前往的目的地,大部分工作都将集中在将该概念应用于 可遍历可导航对象 和相关 Document 上。对于导航,这项工作通常在流程的最后阶段进行;对于遍历,则是流程的开始。

7.4.6.1 更新可遍历对象

确保一个可遍历对象最终处于正确的会话历史步骤,这尤其复杂,因为它可能涉及协调多个可导航对象,这些对象是可遍历对象的子孙节点,并行填充它们,然后同步以确保每个人对结果都有相同的视图。由于存在同步的同文档导航与跨文档导航混合在一起,以及网页已经有了某些相对的计时期望,所以这种情况更加复杂。

一个更改可导航延续状态用于在应用历史步骤算法期间存储信息,允许算法的一部分仅在其他部分完成之后才能继续。它是一个结构体,包含以下内容:

显示的文档
一个文档
目标条目
一个会话历史条目
可导航对象
一个可导航对象
仅更新
一个布尔值

尽管对可遍历可导航对象的所有更新最终都将出现在同一个应用历史步骤算法中,但每个可能的入口点都有一些小的定制。

为了更新可导航对象创建/销毁,给定一个可遍历可导航对象traversable

  1. steptraversable当前会话历史步骤

  2. 返回应用历史步骤steptraversable的结果,给定false、null、null、null和null。

为了应用推入/替换历史步骤,给定一个非负整数step和一个历史处理行为historyHandling到一个可遍历可导航对象traversable

  1. 返回应用历史步骤steptraversable的结果,给定false、null、null、null和historyHandling

应用推入/替换历史步骤从未将源快照参数或发起者可导航对象传递给应用历史步骤。这是因为这些检查是在导航算法的早期完成的。

为了应用重载历史步骤,给定一个可遍历可导航对象traversable

  1. steptraversable当前会话历史步骤

  2. 返回应用历史步骤steptraversable的结果,给定true、null、null、null和"重载"。

应用重载历史步骤从未将源快照参数或发起者可导航对象传递给应用历史步骤。这是因为重载始终被视为由可导航对象本身完成,即使在像parent.location.reload()这样的情况下也是如此。

为了应用遍历历史步骤,给定一个非负整数step到一个可遍历可导航对象traversable,以及源快照参数sourceSnapshotParams可导航对象initiatorToCheck用户导航参与userInvolvement

  1. 返回应用历史步骤steptraversable的结果,给定true、sourceSnapshotParamsinitiatorToCheckuserInvolvement和"遍历"。


现在来看看算法本身。

为了应用历史步骤,给定一个非负整数step到一个可遍历可导航对象traversable,以及布尔值checkForCancelation源快照参数或nullsourceSnapshotParams可导航对象或nullinitiatorToCheck用户导航参与或nulluserInvolvementForNavigateEvents,以及NavigationType或nullnavigationType,执行以下步骤。它们返回"initiator-disallowed"、"canceled-by-beforeunload"、"canceled-by-navigate"或"applied"。

  1. 断言:这是在traversable会话历史遍历队列中运行的。

  2. targetStep获取使用的步骤的结果,给定traversablestep

  3. 如果initiatorToCheck不是null,则

    1. 断言sourceSnapshotParams不是null。

    2. 对于navigable的每个获取所有当前会话历史条目将更改或重载的可导航对象:如果initiatorToCheck不是被沙盒允许导航navigable,给定sourceSnapshotParams,则返回"initiator-disallowed"。

  4. navigablesCrossingDocuments获取所有可能经历跨文档遍历的可导航对象的结果,给定traversabletargetStep

  5. 如果checkForCancelation为true,并且检查是否取消卸载的结果,给定navigablesCrossingDocumentstraversabletargetStepuserInvolvementForNavigateEvents,不是"continue",则返回该结果。

  6. changingNavigables获取所有当前会话历史条目将更改或重载的可导航对象的结果,给定traversabletargetStep

  7. nonchangingNavigablesThatStillNeedUpdates获取所有仅需要历史对象长度/索引更新的可导航对象的结果,给定traversabletargetStep

  8. 对于changingNavigables的每个navigable

    1. targetEntry获取目标历史条目的结果,给定navigabletargetStep

    2. navigable当前会话历史条目设置为targetEntry

    3. 设置正在进行的导航,对于navigable,设置为"traversal"。

  9. totalChangeJobschangingNavigables大小

  10. completedChangeJobs为0。

  11. changingNavigableContinuations为一个空的队列,包含更改可导航延续状态

    此队列用于将对changingNavigables的操作分成两部分。具体来说,changingNavigableContinuations保存了第二部分的数据。

  12. 对于changingNavigables的每个navigable在全局任务队列中添加一个任务navigable活动窗口导航和遍历任务源,以运行以下步骤:

    这组步骤被分成两部分,以便在文档卸载之前处理同步导航。状态保存在changingNavigableContinuations中,用于第二部分

    1. displayedEntrynavigable活动会话历史条目

    2. targetEntrynavigable当前会话历史条目

    3. changingNavigableContinuation为一个更改可导航延续状态,包含以下内容:

      显示的文档
      displayedEntry文档
      目标条目
      targetEntry
      可导航对象
      可导航对象
      仅更新
      false
    4. 如果displayedEntrytargetEntry,并且targetEntry文档状态重载挂起为false,则

      1. changingNavigableContinuation仅更新设置为true。

      2. changingNavigableContinuations添加changingNavigableContinuation

      3. 中止这些步骤。

      这种情况是由于一个同步导航,它已经更新了活动会话历史条目

    5. 根据navigationType进行切换

      "重载"

      断言targetEntry文档状态重载挂起为true。

      "遍历"

      断言targetEntry文档状态曾经填充过为true。

      "替换"

      断言: targetEntry步长 等于 displayedEntry步长targetEntry文档状态已填充 为 false。

      "push"

      断言: targetEntry步长 等于 displayedEntry步长 + 1 且 targetEntry文档状态已填充 为 false。

    6. oldOrigintargetEntry文档状态

    7. 如果以下条件全部为真

      1. 断言: userInvolvementForNavigateEvents 不为 null。

      2. navigationnavigable活动窗口导航 API

      3. 触发 traverse navigate 事件navigation,给定 targetEntryuserInvolvementForNavigateEvents

    8. 如果 targetEntry文档 为 null,或 targetEntry文档状态重载挂起 为 true,则

      1. navTimingType 为 "back_forward" 如果 targetEntry文档 为 null;否则为 "reload"。

      2. targetSnapshotParams快照目标快照参数 给定 navigable 的结果。

      3. potentiallyTargetSpecificSourceSnapshotParamssourceSnapshotParams

      4. 如果 potentiallyTargetSpecificSourceSnapshotParams 为 null,则将其设置为 快照源快照参数 给定 navigable活动文档 的结果。

        在这种情况下,没有明确的遍历/重载来源。我们将这种情况视为 navigable 自行导航,但要注意,targetEntry 的原始发起者的某些属性会保留在 targetEntry文档状态 中,例如 发起者源引用来源,这将适当地影响导航。

      5. targetEntry文档状态重载挂起 设置为 false。

      6. allowPOSTtargetEntry文档状态重载挂起

      7. 并行尝试填充历史记录条目的文档 对于 targetEntry,给定 navigablepotentiallyTargetSpecificSourceSnapshotParamstargetSnapshotParams,其中 allowPOST 设置为 allowPOSTcompletionSteps 设置为 在全局任务源上排队 给定 navigable活动窗口 以运行 afterDocumentPopulated

      否则,立即运行 afterDocumentPopulated

      在这两种情况下,令 afterDocumentPopulated 为以下步骤

      1. 如果 targetEntry文档 为 null,则将 changingNavigableContinuation仅更新 设置为 true。

        这意味着我们尝试填充文档,但无法做到,例如,由于服务器返回了 204。

        这些类型的失败导航或遍历不会被发送到 导航 API(例如,通过任何 导航 API 方法跟踪器 的承诺,或 navigateerror 事件)。这样做会泄露有关来自其他源的响应时间的敏感信息,在跨源情况下,在跨源与同源情况下提供不同的结果被认为过于混乱。

        但是,实现可以使用此机会来清除 navigation.transition.finished 承诺的任何承诺处理程序,因为它们保证此时永远不会运行。而且,他们可能希望 向控制台报告警告,如果导航 API 的任何部分启动了这些导航,以使 Web 开发人员清楚地了解为什么他们的承诺永远不会解决,并且事件永远不会触发。

      2. 如果 targetEntry文档 不等于 oldOrigin,则将 targetEntry经典历史 API 状态 设置为 StructuredSerializeForStorage(null)。

        这会在源发生更改时清除历史记录状态,而不会发生重定向,而之前会加载 targetEntry。这可能是由于 CSP 沙箱标题的更改造成的。

      3. 如果以下条件全部为真

        则将 targetEntry文档状态可导航目标名称 设置为空字符串。

      4. changingNavigableContinuation 排队changingNavigableContinuations 上。

        此作业的其余部分 稍后运行 在此算法中。

  13. navigablesThatMustWaitBeforeHandlingSyncNavigation 为一个空的 集合

  14. completedChangeJobs 不等于 totalChangeJobs

    1. 如果 traversable正在运行嵌套应用历史记录步骤 为 false,则

      1. traversable会话历史记录遍历队列算法集合 包含 一个或多个 同步导航步骤,其 目标可导航包含navigablesThatMustWaitBeforeHandlingSyncNavigation 中时

        1. stepstraversable会话历史记录遍历队列算法集合 中第一个 项目,其为 同步导航步骤,其 目标可导航包含navigablesThatMustWaitBeforeHandlingSyncNavigation 中。

        2. traversable会话历史记录遍历队列算法集合移除 steps

        3. traversable正在运行嵌套应用历史记录步骤 设置为 true。

        4. 运行 steps

        5. traversable正在运行嵌套应用历史记录步骤 设置为 false。

        旨在在此遍历之前发生的同步导航此时会跳过队列,以便它们可以被添加到 traversable会话历史记录条目 中的正确位置,在此遍历可能卸载它们的文档之前。 此处可以找到更多详细信息

    2. changingNavigableContinuation changingNavigableContinuations 出队 的结果。

    3. 如果 changingNavigableContinuation 为空,则 继续

    4. displayedDocumentchangingNavigableContinuation显示文档

    5. targetEntrychangingNavigableContinuation目标条目

    6. navigablechangingNavigableContinuation可导航

    7. 令 (scriptHistoryLengthscriptHistoryIndex) 为 获取历史记录对象长度和索引 给定 traversabletargetStep 的结果。

      这些值可能已在上次计算后发生更改。

    8. 追加 navigablenavigablesThatMustWaitBeforeHandlingSyncNavigation

      一旦可导航已到达遍历中的此位置,额外排队的同步导航步骤很可能旨在在此遍历之后而不是之前发生,因此它们不再跳过队列。 此处可以找到更多详细信息

    9. entriesForNavigationAPI获取导航 API 的会话历史条目 给定 navigabletargetStep 的结果。

    10. 如果 changingNavigableContinuation仅更新 为 true,或 targetEntry文档displayedDocument,那么

      这是一个同文档导航:我们无需卸载。

      1. 设置正在进行的导航navigable 到 null。

        这允许 navigable 的新的 导航 开始,而在遍历期间它们被阻止了。

      2. 在全局任务队列中导航和遍历任务源 给定 navigable活动窗口 上执行 afterPotentialUnloads

    11. 否则

      1. 断言navigationType 不为 null。

      2. 停用 displayedDocument,给定 userNavigationInvolvementtargetEntrynavigationTypeafterPotentialUnloads

    12. 在这两种情况下,令 afterPotentialUnloads 为以下步骤

      1. 如果 changingNavigableContinuation仅更新 为 false,那么 激活历史条目 targetEntrynavigable

      2. updateDocument 为一个算法步骤,它执行 更新文档以应用历史步骤 给定 targetEntry文档targetEntrychangingNavigableContinuation仅更新scriptHistoryLengthscriptHistoryIndexnavigationTypeentriesForNavigationAPIdisplayedEntry

      3. 如果 targetEntry文档 等于 displayedDocument,那么执行 updateDocument

      4. 否则,在全局任务队列中导航和遍历任务源 给定 targetEntry文档相关全局对象 上执行 updateDocument

      5. 递增 completedChangeJobs

  15. totalNonchangingJobsnonchangingNavigablesThatStillNeedUpdates大小

    从这一步开始,故意等待所有先前的操作完成,因为它们包括 处理同步导航,这也会发布任务来更新历史长度和索引。

  16. completedNonchangingJobs 为 0。

  17. 令 (scriptHistoryLengthscriptHistoryIndex) 为 获取历史对象长度和索引 给定 traversabletargetStep 的结果。

  18. 对于 nonchangingNavigablesThatStillNeedUpdates 的每个 navigable在全局任务队列中导航和遍历任务源 给定 navigable活动窗口 上运行以下步骤

    1. documentnavigable活动文档

    2. 设置 document历史对象索引scriptHistoryIndex

    3. 设置 document历史对象长度scriptHistoryLength

    4. 递增 completedNonchangingJobs

  19. 等待 completedNonchangingJobs 等于 totalNonchangingJobs

  20. 设置 traversable当前会话历史步骤targetStep

  21. 返回 "applied"。

停用跨文档导航的文档 给定一个 文档 displayedDocument,一个 用户导航参与 userNavigationInvolvement,一个 会话历史条目 targetEntry,一个 NavigationType navigationTypeafterPotentialUnloads,这是一个接收无参数的算法

  1. navigabledisplayedDocument节点可导航

  2. potentiallyTriggerViewTransition 为 false。

  3. isBrowserUINavigation 为 true,如果 userNavigationInvolvement 为 "浏览器 UI";否则为 false。

  4. 设置 potentiallyTriggerViewTransition 为调用 导航是否可以触发跨文档视图转换? 给定 displayedDocumenttargetEntry文档navigationTypeisBrowserUINavigation 的结果。

  5. 如果 potentiallyTriggerViewTransition 为 false,那么

    1. firePageSwapBeforeUnload 为以下步骤

      1. 触发 pageswap 事件 给定 displayedDocumenttargetEntrynavigationType 和 null。

    2. 设置正在进行的导航navigable 到 null。

      这允许 navigable 的新的 导航 开始,而在遍历期间它们被阻止了。

    3. 卸载文档及其后代 给定 displayedDocumenttargetEntry文档afterPotentialUnloadsfirePageSwapBeforeUnload

  6. 否则,在全局任务队列中导航和遍历任务源 给定 navigable活动窗口 上运行以下步骤

    1. proceedWithNavigationAfterViewTransitionCapture 为以下步骤

      1. 将以下会话历史遍历步骤追加navigable可遍历导航

        1. 设置正在进行的导航navigable 到 null。

          这允许 navigable 的新的 导航 开始,而在遍历期间它们被阻止了。

        2. 卸载文档及其后代 给定 displayedDocumenttargetEntry文档afterPotentialUnloads

    2. viewTransition设置跨文档视图转换 给定 displayedDocumenttargetEntry文档navigationTypeproceedWithNavigationAfterViewTransitionCapture 的结果。

    3. 触发 pageswap 事件 给定 displayedDocumenttargetEntrynavigationTypeviewTransition

    4. 如果 viewTransition 为 null,那么运行 proceedWithNavigationAfterViewTransitionCapture

      在视图转换开始的情况下,视图转换算法负责调用 proceedWithNavigationAfterViewTransitionCapture

触发 pageswap 事件 给定一个 文档 displayedDocument,一个 会话历史条目 targetEntry,一个 NavigationType navigationType 和一个 ViewTransition 或 null viewTransition

  1. 断言:这是作为在 displayedDocument相关代理事件循环 上排队的 任务 的一部分运行的。

  2. navigationdisplayedDocument相关全局对象导航 API

  3. activation 为 null。

  4. 如果以下条件全部为真

    1. destinationEntry 通过切换 navigationType 来确定

      "reload"

      navigation当前条目

      "traverse"

      navigation条目列表 中的 NavigationHistoryEntry,其 会话历史条目targetEntry

      "push"
      "replace"

      displayedDocument相关领域 中的一个新的 NavigationHistoryEntry,其 会话历史条目 设置为 targetEntry

    2. 设置 activation 为在 displayedDocument相关领域 中创建的 新的 NavigationActivation,具有

      旧条目
      navigation当前条目
      新条目
      destinationEntry
      导航类型
      navigationType

    这意味着,在导航期间跨域重定向会导致旧文档的activation为空,除非新文档是从bfcache恢复的。

  5. displayedDocument相关全局对象触发一个名为pageswap的事件,使用PageSwapEvent,将其activation设置为activation,并将viewTransition设置为viewTransition

要为可导航navigable 激活历史条目会话历史条目entry

  1. 持久状态保存可导航活动会话历史条目

  2. newDocument成为entry文档

  3. 断言newDocument初始about:blank为假,即,我们永远不会遍历回初始about:blank文档,因为它在我们离开它时总是会被替换

  4. navigable活动会话历史条目设置为entry

  5. 激活newDocument

获取使用的步骤,给定一个可遍历的可导航traversable和一个非负整数step,执行以下步骤。它们返回一个非负整数。

  1. steps成为获取traversable中所有已使用的历史步骤的结果。

  2. 返回steps中小于或等于step项目的最大值。

    这解决了由于可导航的移除,没有会话历史条目步骤step的情况。

获取历史对象长度和索引,给定一个可遍历的可导航traversable和一个非负整数step,执行以下步骤。它们返回两个非负整数的元组

  1. steps成为获取traversable中所有已使用的历史步骤的结果。

  2. scriptHistoryLength成为steps大小

  3. 断言steps包含step

    假设step已通过获取使用的步骤进行了调整。

  4. scriptHistoryIndex成为stepsstep的索引。

  5. 返回(scriptHistoryLengthscriptHistoryIndex)。

获取当前会话历史条目将更改或重新加载的所有可导航,给定一个可遍历的可导航traversable和一个非负整数targetStep,执行以下步骤。它们返回一个可导航列表

  1. results成为一个空的列表

  2. navigablesToCheck成为« traversable »。

    此列表在下面的循环中扩展。

  3. 对于navigablesToCheck中的每个navigable

    1. targetEntry成为获取给定navigabletargetStep的目标历史条目的结果。

    2. 如果targetEntry不是navigable当前会话历史条目targetEntry文档状态重新加载挂起为真,那么追加navigableresults

    3. 如果targetEntry文档navigable文档,并且targetEntry文档状态重新加载挂起为假,那么扩展navigablesToCheck,包括navigable子可导航

      子可导航添加到navigablesToCheck意味着这些可导航也将由此循环检查。只有在navigable活动文档不会作为此遍历的一部分更改时,才会检查子可导航

  4. 返回results

获取只需要历史对象长度/索引更新的所有可导航,给定一个可遍历的可导航traversable和一个非负整数targetStep,执行以下步骤。它们返回一个可导航列表

其他可导航可能不会受到遍历的影响。例如,如果响应是 204,当前活动的文档将保持不变。此外,在 204 之后“后退”将更改当前会话历史条目,但活动会话历史条目已经正确。

  1. results成为一个空的列表

  2. navigablesToCheck成为« traversable »。

    此列表在下面的循环中扩展。

  3. 对于navigablesToCheck中的每个navigable

    1. targetEntry成为获取给定navigabletargetStep的目标历史条目的结果。

    2. 如果targetEntrynavigable当前会话历史条目,并且targetEntry文档状态重新加载挂起为假,那么

      1. 追加navigableresults

      2. 扩展navigablesToCheck,包括navigable子可导航

        子可导航添加到navigablesToCheck意味着这些可导航也将由此循环检查。只有在navigable活动文档不会作为此遍历的一部分更改时,才会检查子可导航

  4. 返回results

获取目标历史条目,给定一个可导航navigable和一个非负整数step,执行以下步骤。它们返回一个会话历史条目

  1. entries成为获取navigable的会话历史条目的结果。

  2. 返回entries中具有小于或等于step的最大步骤项目

要了解为什么获取目标历史条目返回具有小于或等于输入步骤的最大步骤的条目,请考虑以下Jake 图

0123
顶部/t/t#foo
frames[0]/i-0-a/i-0-b

对于输入步骤 1,top 可导航的目标历史条目是/t 条目,其步骤为 0,而frames[0] 可导航的目标历史条目是/i-0-b 条目,其步骤为 1

0123
顶部/t/t#foo
frames[0]/i-0-a/i-0-b

类似地,给定输入步骤 3,我们得到top 条目,其步骤为 3,以及frames[0] 条目,其步骤为 1

0123
顶部/t/t#foo
frames[0]/i-0-a/i-0-b

获取可能经历跨文档遍历的所有可导航,给定一个可遍历的可导航traversable和一个非负整数targetStep,执行以下步骤。它们返回一个可导航列表

traversable会话历史遍历队列的角度来看,这些文档是targetStep所描述的遍历过程中进行跨文档遍历的候选者。如果它们目标文档的状态码是 HTTP 204 无内容,则它们不会经历跨文档遍历。

请注意,如果给定的可导航可能经历跨文档遍历,则此算法将返回可导航,但不会返回其子可导航。这些将最终卸载,而不是遍历。

  1. results 为一个空的 列表

  2. navigablesToCheck成为« traversable »。

    此列表在下面的循环中扩展。

  3. 对于每个 navigablesToCheck 中的 navigable

    1. targetEntry 为给定 navigabletargetStep获取目标历史条目 的结果。

    2. 如果 targetEntry文档 不是 navigable文档 或者 targetEntry文档状态重载待定 为真,则将 navigable 追加results 中。

      虽然 navigable活动历史条目 可以同步改变,新的条目将始终具有相同的 文档,因此访问 navigable文档 是可靠的。

    3. 否则,将 navigable子导航 扩展navigablesToCheck 中。

      子导航 添加到 navigablesToCheck 中意味着这些导航也将由此循环检查。仅当 navigable活动文档 不会在此遍历过程中改变时才会检查 子导航

  4. 返回results

7.4.6.2 更新文档

为了 更新用于历史步骤应用的文档,给定一个 文档 document,一个 会话历史条目 entry,一个布尔值 doNotReactivate,整数 scriptHistoryLengthscriptHistoryIndexNavigationType-或-null navigationType,一个可选的 列表,其中包含 会话历史条目 entriesForNavigationAPI,以及一个可选的 会话历史条目 previousEntryForActivation

  1. 如果 document最新条目 为 null,则令 documentIsNew 为真;否则为假。

  2. 如果 document最新条目 不是 entry,则令 documentsEntryChanged 为真;否则为假。

  3. document历史对象索引 设置为 scriptHistoryIndex

  4. document历史对象长度 设置为 scriptHistoryLength

  5. navigationhistory相关全局对象导航 API

  6. 如果 documentsEntryChanged 为真,则

    1. oldURLdocument最新条目URL

    2. document最新条目 设置为 entry

    3. 给定 documententry恢复历史对象状态

    4. 如果 documentIsNew 为假,则

      1. 断言: navigationType 不为 null。

      2. 给定 navigationentrynavigationType更新用于相同文档导航的导航 API 条目

      3. document相关全局对象触发一个名为 popstate 的事件,使用 PopStateEvent,其中 state 属性初始化为 document历史对象state,并且 hasUAVisualTransition 初始化为真,如果用户代理执行了一个可视化转换,以显示 最新条目 的已缓存渲染状态。

      4. 给定 entry恢复持久化状态

      5. 如果 oldURL片段 不等于 entryURL片段,则在 document相关全局对象 上,在 DOM 操作任务源排队一个全局任务,以便 触发一个名为 hashchange 的事件,使用 HashChangeEvent,其中 oldURL 属性初始化为 oldURL序列化,并且 newURL 属性初始化为 entryURL序列化

    5. 否则

      1. 断言: entriesForNavigationAPI 已给出。

      2. 给定 entry恢复持久化状态

      3. 给定 navigationentriesForNavigationAPIentry初始化用于新文档的导航 API 条目

  7. 如果以下所有条件都为真

    1. 如果 navigation激活 为 null,则将 navigation激活 设置为 navigation相关领域 中的一个新的 NavigationActivation 对象。

    2. previousEntryIndex 为在 navigation获取导航 API 条目索引previousEntryForActivation 的结果。

    3. 如果 previousEntryIndex 非负,则将 activation旧条目 设置为 navigation条目列表[previousEntryIndex]。

    4. 否则,如果以下所有条件都为真

      则将 activation旧条目 设置为 navigation相关领域 中的一个新的 NavigationHistoryEntry,其 会话历史条目previousEntryForActivation

    5. activation新条目 设置为 navigation当前条目

    6. activation导航类型 设置为 navigationType

  8. 如果 documentIsNew 为真,则

    1. 针对 document尝试滚动到片段

    2. 此时,脚本可能会针对新创建的文档 document 运行。

  9. 否则,如果 documentsEntryChanged 为假并且 doNotReactivate 为假,则

    1. 断言: entriesForNavigationAPI 已给出。

    2. 给定 entryentriesForNavigationAPI重新激活 document

    documentsEntryChanged 可能由于两种原因而为假:要么我们正在从 bfcache 中恢复,要么我们正在异步完成一个同步导航,该导航已同步设置了 document最新条目。参数 doNotReactivate 区分了这两种情况。

为了 恢复历史对象状态,给定一个 文档 document 和一个 会话历史条目 entry

  1. targetRealmdocument相关领域

  2. stateStructuredDeserialize(entry经典历史 API 状态targetRealm)。如果这引发了异常,则捕获它并令 state 为 null。

  3. document历史对象state 设置为 state

为了 激活 一个 文档 document

  1. windowdocument相关全局对象

  2. document浏览上下文WindowProxy[[Window]] 内部槽值设置为 window

  3. document可见性状态设置为document节点可导航可遍历导航系统可见性状态

  4. 排队一个新的VisibilityStateEntry,其可见性状态document可见性状态,其时间戳为零。

  5. 设置window相关设置对象执行就绪标志

为了重新激活一个Documentdocument,给定一个会话历史记录条目reactivatedEntry和一个列表会话历史记录条目entriesForNavigationAPI

此算法在documentbfcache中退出后更新document,即在document再次变为完全激活后。鼓励希望监视对完全激活状态更改的其他规范将步骤添加到此算法中,以便更改导致的事件顺序清晰。

  1. 对于document中具有自动填充字段名称为“off”的每个formControl,调用formControl重置算法

  2. 如果document挂起的计时器句柄不为空

    1. 断言document挂起时间不为零。

    2. suspendDuration当前高分辨率时间减去document挂起时间

    3. activeTimersdocument相关全局对象活动计时器映射

    4. 对于document挂起的计时器句柄中的每个handle,如果activeTimers[handle] 存在,则将activeTimers[handle]增加suspendDuration

  3. 更新重新激活的导航 API 条目,给定document相关全局对象导航 APIentriesForNavigationAPIreactivatedEntry

  4. 如果document当前文档就绪状态为“complete”,且document页面显示标志为假,则

    1. document页面显示标志设置为真。

    2. document已显示设置为假。

    3. 更新document的可见性状态为“visible”。

    4. 触发一个页面转换事件,其名称为pageshow,在document相关全局对象处,其值为真。

为了尝试滚动到片段,给定一个Documentdocument,执行以下步骤并行

  1. 等待实现定义的时间量。(目的是允许用户代理在性能问题的情况下优化用户体验。)

  2. document相关全局对象上,导航和遍历任务源排队一个全局任务,以运行这些步骤。

    1. 如果document没有解析器,或者其解析器已停止解析,或者用户代理有理由相信用户不再对滚动到片段感兴趣,则中止这些步骤。

    2. 滚动到片段,给定document

    3. 如果document指示部分仍然为空,则尝试滚动到片段,给定document

为了使文档不可恢复,给定一个Documentdocument和一个字符串reason

  1. details为一个新的未恢复原因详细信息,其原因reason

  2. details追加到documentbfcache 阻止详细信息

  3. document可恢复状态设置为假。

为了为文档状态构建未恢复原因,给定Documentdocument

  1. notRestoredReasonsForDocument为一个新的未恢复原因

  2. notRestoredReasonsForDocumentURL设置为documentURL

  3. 如果document节点可导航容器为一个iframe元素,则

    1. notRestoredReasonsForDocumentsrc设置为document节点可导航容器src属性的值。

    2. notRestoredReasonsForDocumentid设置为document节点可导航容器id属性的值。

    3. notRestoredReasonsForDocumentname设置为document节点可导航容器name属性的值。

  4. notRestoredReasonsForDocumentreasons设置为documentbfcache 阻止详细信息克隆

  5. 对于document文档树子级可导航中的每个navigable

    1. childDocumentnavigable活动文档

    2. 为文档状态构建未恢复原因,给定childDocument

    3. childDocument未恢复原因追加到notRestoredReasonsForDocumentchildren

  6. document节点可导航活动会话历史记录条目文档状态未恢复原因设置为notRestoredReasonsForDocument

为了为顶级可遍历及其后代构建未恢复原因,给定顶级可遍历topLevelTraversable

  1. 为文档状态构建未恢复原因,给定topLevelTraversable活动文档

  2. crossOriginDescendants为一个空的列表

  3. 对于topLevelTraversable活动文档后代可导航中的每个childNavigable

    1. 如果childNavigable活动文档topLevelTraversable活动文档同源,则childNavigable追加到crossOriginDescendants

  4. crossOriginDescendantsPreventsBfcache为假。

  5. 对于crossOriginDescendants中的每个crossOriginNavigable

    1. reasonsForCrossOriginChildcrossOriginNavigable活动文档文档状态未恢复原因

    2. 如果 reasonsForCrossOriginChild原因 不为空,则将 crossOriginDescendantsPreventsBfcache 设置为 true。

    3. reasonsForCrossOriginChildURL 设置为 null。

    4. reasonsForCrossOriginChild原因 设置为 null。

    5. reasonsForCrossOriginChild子节点 设置为 null。

  6. 如果 crossOriginDescendantsPreventsBfcache 为 true,则 使文档无法恢复,给定 topLevelTraversable活动文档 和 "遮罩"。

7.4.6.3 显示文档

一个 文档 具有一个布尔值 已被显示,初始值为 false。它用于确保 pagereveal 事件为每个 文档 的激活触发一次(在首次渲染时触发一次,以及在每个 重新激活 时触发一次)。

显示 一个 文档 document

  1. 如果 document已被显示 为 true,则返回。

  2. document已被显示 设置为 true。

  3. transition解析入站跨文档视图转换 的结果,针对 document

  4. 触发一个事件,名为 pagereveal,在 document相关全局对象 上,使用 PageRevealEvent,其 viewTransition 设置为 transition

  5. 如果 transition 不为空,则

    1. 准备运行脚本,给定 document

    2. 激活 transition

    3. 清理运行脚本后的操作,给定 document

    激活视图转换可能会解析/拒绝承诺,因此通过用准备/清理包裹激活,我们确保这些承诺在下一个渲染步骤之前得到处理。

虽然 pagereveal гарантированно будет вызываться во время первого шага обновления рендеринга, который отображает обновленную версию страницы, пользовательские агенты могут свободно отображать кэшированный кадр страницы, прежде чем вызывать его. Это предотвращает задержку представления такого кэшированного кадра из-за наличия обработчика pagereveal.

7.4.6.4 滚动到片段

滚动到片段,给定一个 文档 document

  1. 如果 document指示部分 为 null,则将 document目标元素 设置为 null。

  2. 否则,如果 document指示部分文档顶部,则

    1. document目标元素 设置为 null。

    2. 滚动到文档开头,针对 document[CSSOMVIEW]

    3. 返回。

  3. 否则

    1. 断言: document指示部分 是一个元素。

    2. targetdocument指示部分

    3. document目标元素 设置为 target

    4. 运行 祖先详细信息显示算法,针对 target

    5. 运行 祖先隐藏直至找到显示算法,针对 target

    6. 滚动 target 到视图中,其中 behavior 设置为 "auto",block 设置为 "start",inline 设置为 "nearest"。 [CSSOMVIEW]

    7. 运行 聚焦步骤,针对 target,其中 文档视窗 作为 备用目标

    8. 顺序焦点导航起点 移动到 target

一个 文档指示部分 是其 URL片段 所标识的部分,或者如果片段未标识任何内容,则为 null。片段在映射到节点方面的语义由定义 文档 使用的 MIME 类型 的规范定义(例如,处理 片段 针对 XML MIME 类型 是 RFC7303 的职责)。 [RFC7303]

每个 文档 还具有一个 目标元素,它用于定义 :target 伪类,并通过上述算法更新。它最初为 null。

对于一个 HTML 文档 document,其 指示部分选择指示部分 的结果,给定 documentdocumentURL

选择指示部分,给定一个 文档 document 和一个 URL url

  1. 如果 documentURL等于 url,其中 排除片段 设置为 true,则返回 null。

  2. fragmenturl片段

  3. 如果 fragment 为空字符串,则返回特殊值 文档顶部

  4. potentialIndicatedElement查找潜在的指示元素 的结果,给定 documentfragment

  5. 如果 potentialIndicatedElement 不为空,则返回 potentialIndicatedElement

  6. fragmentBytes百分比解码 fragment 的结果。

  7. decodedFragment 为在 fragmentBytes 上运行 UTF-8 解码(无 BOM) 的结果。

  8. potentialIndicatedElement 设置为 查找潜在的指示元素 的结果,给定 documentdecodedFragment

  9. 如果 potentialIndicatedElement 不为空,则返回 potentialIndicatedElement

  10. 如果 decodedFragment 与字符串 top ASCII 不区分大小写 匹配,则返回 文档顶部

  11. 返回 null。

查找潜在的指示元素,给定一个 文档 document 和一个字符串 fragment,运行以下步骤

  1. 如果在文档树中存在一个元素,其 根节点document,且其 ID 等于 fragment,则返回在 树序 中的第一个此类元素。

  2. 如果在文档树中存在一个 a 元素,其 根节点document,且其具有一个 name 属性,其值为 fragment,则返回在 树序 中的第一个此类元素。

  3. 返回 null。

7.4.6.5 持久历史条目状态

保存持久状态 到一个 会话历史条目 entry

  1. entry滚动位置数据 设置为包含 entry文档 的所有 可恢复的滚动区域 的滚动位置。

  2. 可选地,更新 entry持久用户状态,以反映用户代理希望持久化的任何状态,例如表单字段的值。

恢复持久状态 从一个 会话历史条目 entry

  1. 如果 entry滚动恢复模式 为 "auto",并且 entry文档相关全局对象导航 API在正在进行的导航期间抑制正常滚动恢复 为 false,则 恢复滚动位置数据,给定 entry

    用户代理不恢复滚动位置并不意味着滚动位置将保留在任何特定值(例如(0,0))。实际滚动位置取决于导航类型和用户代理的特定缓存策略。因此,Web 应用程序不能假设任何特定的滚动位置,而是被敦促将其设置为他们想要的值。

    如果 在进行中的导航期间抑制正常滚动恢复 为 true,则 恢复滚动位置数据 可能会在稍后某个时间点作为 完成 相关 NavigateEvent 的一部分,或者通过 navigateEvent.scroll() 方法调用发生。

  2. 可选地,更新 entry 的其他方面 document 及其渲染,例如表单字段的值,用户代理之前已记录在 entry持久用户状态 中。

    这甚至可以包括更新 dir 属性的 textarea 元素或 input 元素,其 type 属性处于 文本搜索电话URL电子邮件 状态,如果持久状态包含此类控件中用户输入的方向性。

    作为此过程的一部分恢复表单控件的值不会触发任何 inputchange 事件,但可以触发 与表单关联的自定义元素formStateRestoreCallback


每个 Document 都有一个布尔值 用户滚动过,最初为 false。如果用户滚动文档,用户代理必须将其文档的 用户滚动过 设置为 true。

Document document可恢复滚动区域document视窗,以及所有 document 的可滚动区域,除了任何 可导航容器

子可导航 滚动恢复作为这些 可导航Document会话历史条目 的状态恢复的一部分处理。

恢复滚动位置数据,给定 会话历史条目 entry

  1. documententrydocument

  2. 如果 document用户滚动过 为 true,则用户代理应返回。

  3. 用户代理应尝试使用 entry滚动位置数据 恢复 entrydocument可恢复滚动区域 的滚动位置。用户代理可以继续定期尝试这样做,直到 document用户滚动过 变成 true。

    这被描述为一次尝试,它可能重复进行,直到成功或直到用户滚动,因为由 滚动位置数据 指示的相关内容可能需要一些时间才能从网络加载。

    滚动恢复可能会受到滚动锚定的影响。 [CSSSCROLLANCHORING]