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 会话历史的集中式修改

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

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

一个会话历史遍历并行队列算法集中的项目要么是算法步骤,要么是同步导航步骤,同步导航步骤是涉及目标可导航(一个可导航)的特定算法步骤。

要将会话历史遍历步骤附加到给定算法步骤steps的可遍历可导航traversable(一个可遍历可导航),将steps附加traversable会话历史遍历队列算法集

要将涉及可导航targetNavigable(一个可导航)的会话历史同步导航步骤附加到可遍历可导航traversable(一个可遍历可导航),将steps作为针对目标可导航targetNavigable同步导航步骤附加traversable会话历史遍历队列算法集

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

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

  2. 并行运行以下步骤

    1. 当真时

      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

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

      此时,URL 为 /b#fooDocument卸载,我们完成移动到我们的目标历史步骤 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. 对于每个 docStatedocStates

    1. 对于每个 nestedHistorydocState嵌套历史

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

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

  7. 断言:未达到此步骤。

为导航 API 获取会话历史条目 的一个 可导航 navigable,给定一个整数 targetStep

  1. rawEntries获取会话历史条目 的结果,用于 navigable

  2. entriesForNavigationAPI 为一个新的空 列表

  3. startingIndex会话历史条目rawEntries 中的索引,该条目具有小于或等于 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. 对于每个 entryListentryLists

    1. 移除 entryList 中每个 会话历史条目,该条目的 步骤 大于 step

    2. 对于每个 entryentryList

      1. 对于每个 nestedHistoryentry文档状态嵌套历史追加 nestedHistory条目列表entryLists

获取所有已使用历史步骤,它们是 可遍历可导航 traversable 的一部分

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

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

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

  4. 对于每个 entryListentryLists

    1. 对于每个 entryentryList

      1. 追加 entry步骤steps

      2. 对于每个 nestedHistoryentry文档状态嵌套历史追加 nestedHistory条目列表entryLists

  5. 返回 steps排序

某些操作会导致 可导航 导航 到新的资源。

例如,跟随超链接表单提交 以及 window.open()location.assign() 方法都可能导致导航。

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

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

源快照参数 结构 用于捕获启动导航的 Document 的数据。它在导航开始时进行快照,并在整个导航的生命周期中使用。它具有以下 项目

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

快照源快照参数,给定一个Document sourceDocument,返回一个新的源快照参数,其中

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

The 目标快照参数 结构用于捕获从要导航的可导航对象中获取的数据。与源快照参数类似,它在导航开始时进行快照,并在整个导航生命周期内使用。它具有以下

沙箱标志
一个沙箱标志集

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


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

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

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


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


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

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

一个历史处理行为是一个NavigationHistoryBehavior,它既是"push",又是"replace",即,它已经从任何初始的"auto"值中解析出来。

导航必须是替换,给定一个URL url 和一个Document document,如果以下任何一项为真

其他通常(但不总是)强制执行"replace" 导航的情况是


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

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

为了在某些调用站点方便起见,用户导航参与,对于一个Event event,定义如下

  1. 断言:此算法正在作为激活行为定义的一部分被调用。

  2. 断言eventtype是"click"。

  3. 如果eventisTrusted被初始化为真,则返回"activation"。

  4. 返回"none"。

7.4.2.2 开始导航

导航一个可导航对象 navigable 到一个URL url,使用一个Document sourceDocument,并使用可选的POST 资源、字符串或 null documentResource(默认值为 null)、可选的响应或 null response(默认值为 null)、可选的布尔值exceptionsEnabled(默认值为 false)、可选的NavigationHistoryBehavior historyHandling(默认值为"auto")、可选的序列化状态或 null navigationAPIState(默认值为 null)、可选的条目列表或 null formDataEntryList(默认值为 null)、可选的推荐人策略 referrerPolicy(默认为空字符串)以及可选的用户导航参与 userInvolvement(默认值为"none")

  1. 如果 formDataEntryList 不为空,则将 cspNavigationType 设置为 "form-submission";否则设置为 "other"。

  2. sourceSnapshotParams 设置为 快照源快照参数 的结果,该结果基于 sourceDocument

  3. initiatorOriginSnapshot 设置为 sourceDocument来源

  4. initiatorBaseURLSnapshot 设置为 sourceDocument文档基准 URL

  5. navigationId 设置为 生成一个随机 UUID 的结果。 [WEBCRYPTO]

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

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

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

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

  8. container 设置为 navigable容器

  9. 如果 container 是一个 iframe 元素,并且 将惰性加载元素步骤 在给定 container 的情况下返回 true,则 停止观察惰性加载元素的交叉点 container,并将 container惰性加载恢复步骤 设置为 null。

  10. 如果 导航必须是替换,在给定 urlnavigable活动文档 的情况下,则将 historyHandling 设置为 "replace"。

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

  12. targetBrowsingContext 设置为 navigable活动浏览上下文

  13. targetSnapshotParams 设置为 快照目标快照参数 的结果,该结果基于 navigable

  14. 调用 WebDriver BiDi 导航已开始,使用 targetBrowsingContext 和一个新的 WebDriver BiDi 导航状态,其 IDnavigationId状态 为 "待定",URLurl

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

    1. 调用 WebDriver BiDi 导航失败,使用 targetBrowsingContext 和一个新的 WebDriver BiDi 导航状态,其 IDnavigationId状态 为 "已取消",URLurl

    2. 返回。

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

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

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

  17. 如果 url方案 为 "javascript",则

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

    2. 返回。

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

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

    2. 如果 documentResourcePOST 资源,则将 entryListForFiring 设置为 formDataEntryList;否则设置为 null。

    3. 如果 navigationAPIState 不为空,则将 navigationAPIStateForFiring 设置为 navigationAPIState;否则设置为 StructuredSerializeForStorage(undefined)。

    4. continue 设置为 navigation 上触发 push/replace/reload navigate 事件 的结果,其中 navigationType 设置为 historyHandlingisSameDocument 设置为 false,userInvolvement 设置为 userInvolvementformDataEntryList 设置为 entryListForFiringdestinationURL 设置为 urlnavigationAPIState 设置为 navigationAPIStateForFiring

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

    如果导航的 userInvolvement 为 "浏览器 UI",或由 跨源域 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. documentState关于基本 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 为给定 responseURLfinalSandboxFlagsdocumentState发起者来源 确定来源 的结果。

      4. coop 为一个新的 打开者策略

      5. coopEnforcementResult 为一个新的 打开者策略执行结果,其拥有

        URL
        responseURL
        起源
        responseOrigin
        打开程序策略
        coop
      6. navigationParams 设置为一个新的 导航参数,其拥有

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

      1. 追加会话历史遍历步骤 追加到 navigable可遍历对象,以 完成跨文档导航,给定 navigablehistoryHandlinghistoryEntry

7.4.2.3 结束导航

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

7.4.2.3.1 通常的跨文档导航情况

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

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

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

  3. 如果 historyEntry文档 为 null,则返回。

    这意味着 尝试填充历史条目的文档 最终没有创建文档,例如,导航被后续导航取消、出现 204 无内容响应等。

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

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

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

  6. traversablenavigable可遍历导航对象

  7. targetStep 为 null。

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

  9. 如果 entryToReplace 为 null,则

    1. traversable 清除前向会话历史

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

    3. historyEntry步骤 设置为 targetStep

    4. historyEntry 追加targetEntries

    否则

    1. targetEntries 中将 entryToReplace 替换historyEntry

    2. historyEntry步骤 设置为 entryToReplace步骤

    3. 如果 historyEntry文档状态来源entryToReplace文档状态来源 同源,则将 historyEntry导航 API 密钥 设置为 entryToReplace导航 API 密钥

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

  10. traversable 应用推送/替换历史步骤 targetStep,给定 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活动文档来源 非同源域,则返回。

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

    这是一个为下一步处理而创建的合成 请求。它永远不会命中网络。

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

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

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

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

  8. 断言: initiatorOriginnewDocument来源

  9. entryToReplacetargetNavigable活动会话历史记录条目

  10. oldDocStateentryToReplace文档状态

  11. documentState 为一个新的 文档状态,其中包含

    文档
    newDocument
    历史策略容器
    如果 oldDocState历史策略容器 非空,则为其 克隆;否则为 null
    请求引用
    oldDocState请求引用
    请求引用者策略
    oldDocState请求引用策略 或者这应该是传递给 navigatereferrerPolicy 吗?
    发起者来源
    发起者来源
    起源
    发起者来源
    关于基本 URL
    oldDocStateabout 基地址
    资源
    null
    已填充
    true
    可导航目标名称
    oldDocState可导航目标名称
  12. historyEntry 为一个新的 会话历史记录条目,其中包含

    URL
    entryToReplaceURL
    文档状态
    documentState

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

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

给定 可导航 targetNavigableURL url来源 newDocumentOrigin 评估 javascript: URL

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

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

  3. scriptSourceencodedScriptSource百分比解码UTF-8 解码

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

  5. baseURLsettingsAPI 基地址

  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
    起源
    newDocumentOrigin
    打开程序策略
    coop
  16. navigationParams 为一个新的 导航参数,其中包含

    id
    navigationId
    可导航
    targetNavigable
    请求
    null 这将导致结果 Document 的引用为 null;正确吗?
    响应
    响应
    获取控制器
    null
    提交早期提示
    null
    COOP 执行结果
    coopEnforcementResult
    保留的环境
    null
    起源
    newDocumentOrigin
    策略容器
    policyContainer
    最终沙箱标志集
    finalSandboxFlags
    打开程序策略
    coop
    导航计时类型
    "navigate"
    关于基本 URL
    targetNavigable活动文档about 基地址
  17. 返回给定 navigationParams 加载 HTML 文档 的结果。

7.4.2.3.3 片段导航

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

  1. navigationnavigable活动窗口导航 API

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

  3. 如果 navigationAPIState 非空,则将 destinationNavigationAPIState 设置为 navigationAPIState

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

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

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

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

    对于使用 navigation.navigate() 执行的导航,由 state 选项提供的 value 用于新的 导航 API 状态。(如果该选项没有提供 value,则会将其设置为 undefined 的序列化。)对于其他片段导航,包括用户发起的导航,导航 API 状态 会从上一个条目中继承。

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

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

  8. historynavigable活动文档历史记录对象

  9. scriptHistoryIndexhistory索引

  10. scriptHistoryLengthhistory长度

  11. 如果 historyHandling 为 "push",则

    1. history状态 设置为 null。

    2. scriptHistoryIndex 加 1。

    3. scriptHistoryLength 设置为 scriptHistoryIndex + 1。

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

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

  14. 更新文档以应用历史记录步骤,其中 navigable活动文档historyEntry、true、scriptHistoryIndexscriptHistoryLengthhistoryHandling

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

  15. 根据 navigable活动文档滚动到片段

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

  16. traversablenavigable可遍历导航器

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

    1. 根据 traversablenavigablehistoryEntryentryToReplacehistoryHandling完成一次同文档导航

    2. 使用 navigable活动浏览上下文 和一个新的 WebDriver BiDi 导航状态,其 idnavigationIdurlurl,以及 status 为 "complete",来调用 WebDriver BiDi 片段导航

根据一个 可遍历导航器 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. targetEntry 追加targetEntries 中。

    否则

    1. targetEntries 中将 entryToReplace 替换targetEntry

    2. targetEntry步骤 设置为 entryToReplace步骤

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

  6. 根据 historyHandling,将 应用推送/替换历史步骤 targetSteptraversable 中。

    即使对于 "替换" 导航,也执行此操作,因为它解决了跨多个同步导航的竞争条件。

7.4.2.3.4 非提取方案和外部软件

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

id
null 或 导航 ID
可导航
正在经历导航的 导航器
URL
URL
目标快照沙箱标志
导航期间存在的 目标快照参数沙箱标志
源快照具有瞬态激活
激活期间存在的 源快照参数具有瞬态激活 布尔值
发起者来源

可能用于在用户界面提示中确认外部软件包调用的 来源

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

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

根据 非提取方案导航参数 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 中导航到外部软件可能会被用户视为新弹出窗口或新的顶级导航。 这就是为什么只有在指定了 allow-popupsallow-top-navigationallow-top-navigation-by-user-activationallow-top-navigation-to-custom-protocols 之一的情况下,才允许在沙盒化 iframe 中进行导航。

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

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

7.4.2.4 阻止导航

导航过程的早期可能会有几种情况介入并使整个过程停止。 当多个 可导航对象 由于会话历史记录遍历而同时导航时,这尤其令人兴奋。

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

  1. 如果 source 等于 target,则返回 true。

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

  3. 如果 targetsource 的祖先,则

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

    2. 如果 sourceSnapshotParamshas transient activation 为 true,并且 sourceSnapshotParams沙盒标志带用户激活的沙盒顶级导航浏览上下文标志 已设置,则返回 false。

    3. 如果 sourceSnapshotParamshas transient activation 为 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. documentsToFireBeforeunloadnavigablesThatNeedBeforeUnload 中每个 项目活动文档

  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. navigationtraversable活动窗口导航 API

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

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

        6. eventsFired 设置为 true。

      6. 等待 eventsFired 为 true。

      7. 如果 finalStatus 不为 "continue",则返回 finalStatus

  5. totalTasksdocumentsThatNeedBeforeunload大小

  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. eventFiringResultdocument相关全局对象 上触发名为 beforeunload 的事件 的结果,使用 BeforeUnloadEvent,并将 cancelable 属性初始化为 true。

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

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

    1. unloadPromptShown 设置为 true。

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

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

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

    4. 如果用户未确认页面导航,则将 unloadPromptCanceled 设置为 true。

    5. 使用 document相关全局对象unloadPromptCanceled 为 false 时的 true 或 false 时的 false 调用 WebDriver BiDi 用户提示已关闭

  7. document卸载计数器 减少 1。

  8. 返回 (unloadPromptShownunloadPromptCanceled)。

7.4.2.5 中止导航

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

设置可导航对象可导航对象 navigablenewValue

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

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

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

7.4.3 重新加载和遍历

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

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

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

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

    3. 如果 navigationAPIState 非空,则将 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. traversable 设为 navigable可遍历的可导航对象

  4. 将以下会话历史记录遍历步骤 追加到 traversable

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

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

  1. sourceSnapshotParamsinitiatorToCheck 设为 null。

  2. userInvolvement 设为 "浏览器 UI"。

  3. 如果给出了 sourceDocument,则

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

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

    3. userInvolvement 设为 "none"。

  4. 将以下会话历史记录遍历步骤 追加到 traversable

    1. allSteps 设为 获取所有已使用的历史记录步骤 的结果,用于 traversable

    2. currentStepIndex 设为 traversable当前会话历史记录步骤allSteps 中的索引。

    3. targetStepIndex 设为 currentStepIndex 加上 delta

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

    5. 将遍历历史记录步骤 allSteps[targetStepIndex] 应用于 traversable,给定 sourceSnapshotParamsinitiatorToCheckuserInvolvement

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

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

  1. navigable 设为 document节点可导航对象

  2. activeEntry 设为 navigable活动会话历史记录条目

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

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

    这意味着对 初始 about:blank DocumentpushState() 调用行为类似于 replaceState() 调用。

  5. entryToReplace 设为 activeEntry,如果 historyHandling 为 "replace",否则为 null。

  6. 如果 historyHandling 为 "push",则

    1. 递增 document历史记录对象index

    2. document历史记录对象length 设置为其 index + 1。

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

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

  8. documentURL 设置为 newURL

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

  9. document最新条目 设置为 newEntry

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

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

  12. traversable 设为 navigable可遍历的可导航对象

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

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

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

7.4.5 填充会话历史记录条目

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

这包括以下几种情况:使用已经提供的响应;使用存储在会话历史条目中的srcdoc资源;或者获取。这个过程有几种失败模式,可能会导致什么也不做(将可导航对象保留在其当前活动Document上),也可能导致将会话历史条目填充为错误文档

为了尝试填充历史条目的文档,对于会话历史条目entry,给定可导航对象navigableNavigationTimingTypenavTimingType源快照参数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设置为从 srcdoc 资源创建导航参数的结果,给定entrynavigabletargetSnapshotParamsnavigationIdnavTimingType

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

      则将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. 调用WebDriver BiDi 导航失败,使用currentBrowsingContext和一个新的WebDriver BiDi 导航状态,其IDnavigationId状态为 "canceled",以及URLnavigationParams响应URL

    5. 否则,如果 navigationParams响应状态 不为 204 且不为 205,则将 entry文档状态文档 设置为 加载文档 的结果,该结果基于 navigationParamssourceSnapshotParams 以及 entry文档状态发起者来源

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

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

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

      2. 如果 saveExtraDocumentState 为 true

        1. documententry文档状态文档

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

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

          1. 断言navigationParams导航参数(即,既不为 null,也不为 非 Fetch 方案导航参数)。

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

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

        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`) »
    正文
    documentResource 进行 UTF-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文档状态关于基本 URL

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

此算法会修改 entry

  1. 断言:这是在 并行 中运行的。

  2. documentResourceentry文档状态资源

  3. request 为一个新的 请求,具有以下内容:

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

    1. request方法 设为 `POST`。

    2. request正文 设为 documentResource请求正文

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

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

  6. 否则,如果 entry文档状态曾经填充 为真,则将 request历史导航标志 设置为真。

  7. 如果 sourceSnapshotParams具有瞬态激活 为真,则将 request用户激活 设置为真。

  8. 如果 navigable容器 非空

    1. 如果 navigable容器 具有 浏览上下文作用域源,则将 request 设置为该 浏览上下文作用域源

    2. request目标 设置为 navigable容器本地名称

    3. 如果 sourceSnapshotParams获取客户端navigable容器文档相关设置对象,则将 request发起者类型 设置为 navigable容器本地名称

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

  9. response 为 null。

  10. responseOrigin 为 null。

  11. fetchController 为 null。

  12. coopEnforcementResult 为一个新的 打开者策略执行结果,其

    URL
    navigable活动文档URL
    起源
    navigable活动文档
    打开程序策略
    navigable活动文档打开者策略
    当前上下文是导航来源
    如果 navigable活动文档entry文档状态发起者源 同源,则为真,否则为假
  13. finalSandboxFlags 为一个空的 沙盒标志集

  14. responsePolicyContainer 为 null。

  15. responseCOOP 为一个新的 打开者策略

  16. locationURL 为 null。

  17. currentURLrequest当前 URL

  18. commitEarlyHints 为 null。

  19. 当真时

    1. 如果 request保留客户端 非空,且 currentURLrequest保留客户端创建 URL 相同,则

      1. request保留客户端 运行 环境丢弃步骤

      2. request保留客户端 设置为 null。

      3. commitEarlyHints 设置为 null。

        来自 早期提示标头 的预加载链接在 同源 重定向后仍然保留在预加载缓存中,但在跨源重定向时会被丢弃。

    2. 如果 request保留客户端 为 null,则

      1. topLevelCreationURLcurrentURL

      2. topLevelOrigin 为 null。

      3. 如果 navigable 不是一个 顶级可遍历,则

        1. parentEnvironmentnavigable父级活动文档相关设置对象

        2. topLevelCreationURL 设置为 parentEnvironment顶级创建 URL

        3. topLevelOrigin 设置为 parentEnvironment顶级源

      4. request保留客户端 设置为一个新的 环境,其 id 为一个唯一的不可见字符串,目标浏览上下文navigable活动浏览上下文创建 URLcurrentURL顶级创建 URLtopLevelCreationURL顶级源topLevelOrigin

        创建的环境的 活动服务工作者 在获取期间由 处理获取 算法设置,如果请求 URL 与服务工作者注册匹配。 [SW]

    3. 如果给定 requestcspNavigationType 为 "Blocked" 的 是否应通过内容安全策略阻止类型为的导航请求? 的结果为 "Blocked",则将 response 设置为一个 网络错误,并 退出循环[CSP]

    4. response 设置为 null。

    5. 如果 fetchController 为 null,则将 fetchController 设置为 获取 request 的结果,其中 processEarlyHintsResponse 设置为下面定义的 processEarlyHintsResponseprocessResponse 设置为下面定义的 processResponseuseParallelQueue 设置为真。

      processEarlyHintsResponse 为以下算法,给定一个 响应 earlyResponse

      1. 如果 commitEarlyHints 为 null,则将 commitEarlyHints 设置为给定 earlyResponserequest保留客户端处理早期提示标头 的结果。

      processResponse 为以下算法,给定一个 响应 fetchedResponse

      1. response 设置为 fetchedResponse

    6. 否则,对 fetchController 处理下一个手动重定向

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

      导航手动处理重定向,因为导航是网络平台中唯一关心重定向到 mailto: URL 以及其他类似 URL 的地方。

    7. 等待 response 非空,或 navigable正在进行的导航 更改为不再等于 navigationId

      如果发生后者,则 中止 fetchController,并返回。

      否则,继续进行。

    8. 如果 request主体 为 null,则将 entry文档状态资源 设置为 null。

      获取会取消某些重定向的 主体

    9. responsePolicyContainer 设置为给定 responserequest保留客户端从获取响应创建策略容器 的结果。

    10. finalSandboxFlags 设置为 targetSnapshotParams沙盒标志responsePolicyContainerCSP 列表CSP 派生的沙盒标志并集

    11. responseOrigin 设置为给定 responseURLfinalSandboxFlagsentry文档状态发起者源确定源 的结果。

      如果 response 是重定向,则 responseURL 将是导致重定向到 responselocation URL 的 URL;它不会是 location URL 本身。

    12. 如果 navigable 是一个 顶级可遍历,则

      1. responseCOOP 设置为给定 responserequest保留的客户端获取 opener 策略的结果。

      2. coopEnforcementResult 设置为给定 navigable活动浏览上下文responseURLresponseOriginresponseCOOPcoopEnforcementResultrequestreferrer执行 response 的 opener 策略的结果。

      3. 如果 finalSandboxFlags 不为空,且 responseCOOP 不是 "unsafe-none",则将 response 设置为一个合适的 网络错误,并 跳出循环.

        这将导致一个网络错误,因为不能同时使用 opener 策略为 response 提供一个空白页面,并对导航到该 response 的结果进行沙盒化。

    13. 如果 response 不是一个 网络错误navigable 是一个 子 navigable,且执行 跨域资源策略检查 的结果(使用 navigable容器文档navigable容器文档相关设置对象request目标response 和 true)是 **被阻止**,则将 response 设置为一个 网络错误,并 跳出循环.

      这里我们正在对 父 navigable 而不是 navigable 本身运行 跨域资源策略检查。这是因为我们关心嵌入内容相对于父上下文的同源性,而不是导航源。

    14. locationURL 设置为给定 currentURL片段responselocation URL.

    15. 如果 locationURL 是失败或 null,则 跳出循环.

    16. 断言locationURL 是一个 URL.

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

    18. oldDocState 成为 entry文档状态.

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

      历史策略容器
      如果 oldDocState历史策略容器 不为空,则为其 克隆;否则为 null
      请求引用
      oldDocState请求 referrer
      请求引用者策略
      oldDocState请求 referrer 策略
      发起者来源
      oldDocState发起者源
      起源
      oldDocState
      关于基本 URL
      oldDocStateabout 基础 URL
      资源
      oldDocState资源
      已填充
      oldDocState曾经填充
      可导航目标名称
      oldDocStatenavigable 目标名称

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

      oldDocState历史策略容器 只有在遍历情况中才可能不为空,在我们已经填充了它之后,这是在导航到一个 需要将策略容器存储在历史记录中 的 URL 时进行的。

      以下 Jake 图表 给出了设置

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

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

      现在考虑这种情况,我们向后遍历到步骤 2,但这一次当获取 /a 时,服务器使用一个指向 /c 的 `Location` 标头进行响应。也就是说,locationURL 指向 /c,所以我们到达了这一步,而不是 跳出循环

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

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

      请注意,即使我们最终进入一个重定向链回到原始 URL,我们也会执行此替换,例如,如果 /c 本身有一个指向 /a 的 `Location` 标头。这种情况最终将如下所示

      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 是一个 网络错误,要么是因为我们成功地获取了一个非 网络错误 的 HTTP(S) 响应,并且没有 `Location` 标头。

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

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

    id
    navigationId
    可导航
    可导航
    URL
    locationURL
    目标快照沙箱标志
    targetSnapshotParams沙盒化标志
    源快照具有瞬态激活
    sourceSnapshotParams是否具有瞬态激活
    发起者来源
    responseOrigin
    导航计时类型
    navTimingType

    此时,request当前 URL 是重定向链中最后一个具有 fetch 方案URL,在重定向到一个非 fetch 方案 URL 之前。它将作为导航到非 fetch 方案 URL 的发起者源被使用。

  21. 如果以下任何一项为真

    则返回 null。

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

  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 类型
    返回 加载 HTML 文档 的结果,给定 navigationParams
    一个 XML MIME 类型,它不是一个 显式支持的 XML MIME 类型
    返回 加载 XML 文档 的结果,给定 navigationParamstype
    一个 JavaScript MIME 类型
    一个 JSON MIME 类型,它不是一个 显式支持的 JSON MIME 类型
    "text/css"
    "text/plain"
    "text/vtt"
    返回 加载文本文档 的结果,给定 navigationParamstype
    "multipart/x-mixed-replace"
    返回 加载 multipart/x-mixed-replace 文档 的结果,给定 navigationParamssourceSnapshotParamsinitiatorOrigin
    一个受支持的图像、视频或音频类型
    返回 加载媒体文档 的结果,给定 navigationParamstype
    "application/pdf"
    "text/pdf"
    如果用户代理的 PDF 查看器支持 为真,则返回 为没有 DOM 的内联内容创建文档 的结果,给定 navigationParams可导航

    否则,继续进行。

    一个 显式支持的 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 更新可遍历

确保 可遍历 最终位于正确的会话历史步骤中特别复杂,因为它可能涉及跨可遍历的多个 可导航 后代进行协调,填充 它们,然后同步回来以确保每个人对结果都有相同的视图。同步相同的文档导航与跨文档导航混合在一起,以及网页如何拥有某些相对的定时期望,使得这一点更加复杂。

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

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

虽然对 可遍历可导航 的所有更新最终都在同一个 应用历史步骤 算法中,但每个可能的入口点都伴随着一些小的定制

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

  1. steptraversable当前会话历史步骤

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

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

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

应用 push/replace 历史步骤 永远不会传递 源快照参数 或发起者 可导航对象应用历史步骤。这是因为这些检查是在 导航 算法中的较早阶段完成的。

要将 应用重载历史步骤 应用于 可遍历可导航对象 traversable

  1. steptraversable当前会话历史步骤

  2. 返回将 应用历史步骤 step 应用于 traversable(给定 true、null、null、null 和 "reload")的结果。

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

要将 应用遍历历史步骤 应用于给定的非负整数 step可遍历可导航对象 traversable,以及 源快照参数 sourceSnapshotParams可导航对象 initiatorToCheck用户导航参与度 userInvolvement

  1. 返回将 应用历史步骤 step 应用于 traversable(给定 true、sourceSnapshotParamsinitiatorToCheckuserInvolvement 和 "traverse")的结果。


现在介绍算法本身。

要将 应用历史步骤 应用于给定的非负整数 step可遍历可导航对象 traversable,以及布尔值 checkForCancelation源快照参数-或-null sourceSnapshotParams可导航对象-或-null initiatorToCheck用户导航参与度-或-null userInvolvementForNavigateEventsNavigationType-或-null navigationType,请执行以下步骤。它们将返回 "initiator-disallowed"、"canceled-by-beforeunload"、"canceled-by-navigate" 或 "applied"。

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

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

  3. 如果 initiatorToCheck 不是 null,则

    1. 断言sourceSnapshotParams 不是 null。

    2. 对于 获取所有当前会话历史条目将发生更改或重载的可导航对象 的每个 navigable:如果 initiatorToCheck 未被沙箱 允许 通过沙箱 sourceSnapshotParams 导航 navigable,则返回 "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. changingNavigableContinuation 排入 changingNavigableContinuations

      3. 中止这些步骤。

      此情况是由于 同步导航 已经更新了 活动会话历史条目 而发生的。

    5. 根据 navigationType 切换

      "reload"

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

      "traverse"

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

      "replace"

      断言targetEntry步骤displayedEntry步骤,并且 targetEntry文档状态曾经填充过 为 false。

      "push"

      断言targetEntry步骤displayedEntry步骤 + 1,并且 targetEntry文档状态曾经填充过 为 false。

    6. oldOrigintargetEntry文档状态来源

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

      1. 断言userInvolvementForNavigateEvents 不是 null。

      2. navigationnavigable活动窗口导航 API。

      3. navigation触发一个遍历 navigate 事件,给定 targetEntryuserInvolvementForNavigateEvents

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

      1. 如果 targetEntrydocument 为 null,则将 navTimingType 设置为 "back_forward";否则设置为 "reload"。

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

      3. potentiallyTargetSpecificSourceSnapshotParams 设置为 sourceSnapshotParams

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

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

      5. targetEntry文档状态reload pending 设置为 false。

      6. allowPOST 设置为 targetEntry文档状态reload pending

      7. 并行尝试填充历史条目文档,对于 targetEntry,给定 navigablepotentiallyTargetSpecificSourceSnapshotParamstargetSnapshotParamsallowPOST 设置为 allowPOSTcompletionSteps 设置为在给定 navigable活动窗口导航和遍历任务源排队一个全局任务 以运行 afterDocumentPopulated

      否则,立即运行 afterDocumentPopulated

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

      1. 如果 targetEntrydocument 为 null,则将 changingNavigableContinuationupdate-only 设置为 true。

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

        这些类型的失败导航或遍历不会向 导航 API(例如,通过任何 导航 API 方法跟踪器 的 promise 或 navigateerror 事件)发出信号。这样做会泄漏有关跨来源情况下其他来源响应时间的信息,并且跨来源与同来源情况下的不同结果被认为过于混乱。

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

      2. 如果 targetEntrydocument来源 不是 oldOrigin,则将 targetEntry经典历史 API 状态 设置为 StructuredSerializeForStorage(null)。

        这会在来源发生变化时清除历史状态,而不是在没有发生重定向的情况下之前加载 targetEntry。这可能是由于 CSP 沙盒头部的更改而发生的。

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

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

      4. changingNavigableContinuation 排队changingNavigableContinuations 上。

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

  13. navigablesThatMustWaitBeforeHandlingSyncNavigation 设置为一个空的 集合

  14. completedChangeJobs 不等于 totalChangeJobs

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

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

        1. steps 设置为 traversable会话历史遍历队列算法集合 中的第一个 ,它是 同步导航步骤,其 目标可导航包含navigablesThatMustWaitBeforeHandlingSyncNavigation 中。

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

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

        4. 运行steps

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

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

    2. changingNavigableContinuation 设置为 changingNavigableContinuations 出队 的结果。

    3. 如果 changingNavigableContinuation 为 nothing,则 继续

    4. displayedDocument 设置为 changingNavigableContinuation显示的文档

    5. targetEntry 设置为 changingNavigableContinuation目标条目

    6. navigable 设置为 changingNavigableContinuation可导航

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

      这些值可能已自上次计算以来发生变化。

    8. navigable 追加navigablesThatMustWaitBeforeHandlingSyncNavigation 中。

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

    9. entriesForNavigationAPI 设置为给定 navigabletargetStep获取会话历史条目以供导航 API 使用 的结果。

    10. 如果 changingNavigableContinuationupdate-only 为 true,或者 targetEntrydocumentdisplayedDocument,则

      这是同一个文档导航:我们继续进行,而不进行卸载。

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

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

      2. 给定 navigable活动窗口导航和遍历任务源排队一个全局任务 以执行 afterPotentialUnloads

    11. 否则

      1. 断言navigationType 不为 null。

      2. 停用 displayedDocument,给定 userNavigationInvolvementtargetEntrynavigationTypeafterPotentialUnloads

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

      1. 如果 changingNavigableContinuationupdate-only 为 false,则 激活历史条目 targetEntry,用于 navigable

      2. updateDocument 设置为一个算法步骤,它执行给定 targetEntrydocumenttargetEntrychangingNavigableContinuationupdate-onlyscriptHistoryLengthscriptHistoryIndexnavigationTypeentriesForNavigationAPIdisplayedEntry更新文档以进行历史步骤应用

      3. 如果 targetEntrydocument 等于 displayedDocument,则执行 updateDocument

      4. 否则,在给定 targetEntrydocument相关全局对象导航和遍历任务源排队一个全局任务 以执行 updateDocument

      5. 递增 completedChangeJobs

  15. totalNonchangingJobs 设置为 nonchangingNavigablesThatStillNeedUpdates大小

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

  16. completedNonchangingJobs 为 0。

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

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

    1. documentnavigable活动文档

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

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

    4. completedNonchangingJobs 加 1。

  19. 等待 completedNonchangingJobs 等于 totalNonchangingJobs

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

  21. 返回 "applied"。

为了 为跨文档导航停用文档,给定一个 Document displayedDocument,一个 用户导航参与度 userNavigationInvolvement,一个 会话历史条目 targetEntry,一个 NavigationType navigationType,以及 afterPotentialUnloads,它是一个不接收参数的算法

  1. navigabledisplayedDocument节点可导航

  2. potentiallyTriggerViewTransition 为 false。

  3. 如果 userNavigationInvolvement 为 "浏览器 UI",则令 isBrowserUINavigation 为 true;否则为 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 事件,给定一个 Document displayedDocument,一个 会话历史条目 targetEntry,一个 NavigationType navigationType,以及一个 ViewTransition 或 null viewTransition

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

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

  3. activation 为 null。

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

    1. destinationEntrynavigationType 的切换决定

      "reload"

      navigation当前条目

      "traverse"

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

      "push"
      "replace"

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

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

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

    这意味着在导航期间的跨源重定向将导致旧文档的 PageSwapEvent 中的 activation 为 null,除非新文档是从 bfcache 中恢复的。

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

为了 激活历史条目 会话历史条目 entry,对于 可导航 navigable

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

  2. newDocumententry文档

  3. 断言newDocument是否为初始 about:blank 为 false,即我们从不遍历回 初始 about:blank Document,因为它在我们从它导航出去时总是会被 替换

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

  5. 使 newDocument 变为活动

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

  1. steps获取在 traversable 内所有使用的历史步骤 的结果。

  2. 返回 steps 中小于或等于 step 的最大的

    这适用于由于 可导航 的移除而没有 会话历史条目 具有 步骤 step 的情况。

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

  1. steps获取在 traversable 内所有使用的历史步骤 的结果。

  2. scriptHistoryLengthsteps大小

  3. 断言steps 包含 step

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

  4. scriptHistoryIndexstepsteps 中的索引。

  5. 返回 (scriptHistoryLength, scriptHistoryIndex).

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

  1. results 为一个空的列表

  2. navigablesToCheck 为 « traversable »。

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

  3. 对于 navigablesToCheck 中的每个 navigable

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

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

    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. navigable 附加results

      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 导航对象的步数 为 0 的 /t 条目是目标历史条目,而 frames[0] 导航对象的步数 为 1 的 /i-0-b 条目是目标历史条目

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

类似地,给定输入步数 3,我们得到步数 为 3 的 top 条目和步数 为 1 的 frames[0] 条目

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活动历史条目 可以同步更改,但新条目将始终具有相同的 Document,因此访问 navigable文档 是可靠的。

    3. 否则, navigablesToCheck 扩展navigable子导航对象

      子导航对象 添加到 navigablesToCheck 表示这些导航对象也将被此循环检查。子导航对象 仅在 navigable活动文档 不会作为此遍历的一部分发生更改时才会被检查。

  4. 返回 results

7.4.6.2 更新文档

给定一个 Document document、一个会话历史条目 entry、一个布尔值 doNotReactivate、整数 scriptHistoryLengthscriptHistoryIndexNavigationType-or-null navigationType、一个可选的列表,包含会话历史条目 entriesForNavigationAPI 以及一个可选的会话历史条目 previousEntryForActivation,要更新文档以应用历史步骤,执行以下步骤。

  1. 如果 document最新条目 为空,则令 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 不为空。

      2. 更新同文档导航的导航 API 条目,给定 navigationentry 以及 navigationType

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

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

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

    5. 否则

      1. 断言:给定 entriesForNavigationAPI

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

      3. 为新文档初始化导航 API 条目,给定 navigationentriesForNavigationAPIentry

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

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

    2. previousEntryIndex获取导航 API 条目索引 的结果,该索引在 navigation 中指向 previousEntryForActivation

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

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

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

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

    6. activation导航类型 设置为 navigationType

  8. 如果 documentIsNew 为 true,则

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

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

  9. 否则,如果 documentsEntryChanged 为 false 且 doNotReactivate 为 false,则

    1. 断言:给定 entriesForNavigationAPI

    2. 重新激活 document,给定 entryentriesForNavigationAPI

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

恢复历史对象状态,给定 Document document会话历史条目 entry

  1. targetRealmdocument相关领域

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

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

激活 Document document

  1. windowdocument相关全局对象

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

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

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

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

重新激活 Document document,给定一个 会话历史条目 reactivatedEntry 和一个 列表,包含 会话历史条目 entriesForNavigationAPI

此算法更新 document,在它从 bfcache 中出来之后,即在它再次被设为 完全激活 之后。其他希望观察这种 完全激活 状态变化的规范被鼓励将步骤添加到此算法中,以便清楚地显示发生在变化影响下的事件的顺序。

  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页面显示 标志为 false,则

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

    2. document已显示 设置为 false。

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

    4. 触发一个页面转换事件,名为 pageshow,在 document相关全局对象 上,并传入 true。

尝试滚动到片段,针对 Document document,执行以下步骤,并行

  1. 等待 实现定义的 一段时间。(这旨在允许用户代理在面对性能问题时优化用户体验。)

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

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

    2. 滚动到片段,给定 document

    3. 如果 document指示部分 仍然为 null,则 尝试滚动到片段,针对 document

使文档不可恢复,给定 Document document 和一个字符串 reason

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

  2. 追加 detailsdocumentbfcache 阻止详情

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

给定Document document,构建文档状态的未恢复原因

  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未恢复原因notRestoredReasonsForDocument子节点

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

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

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

  2. crossOriginDescendants 为一个空的列表

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

    1. 如果 childNavigable活动文档来源topLevelTraversable活动文档来源 不是同一个来源,则追加 childNavigablecrossOriginDescendants

  4. crossOriginDescendantsPreventsBfcache 为 false。

  5. 对于 crossOriginDescendants 中的每一个 crossOriginNavigable

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

    2. 如果 reasonsForCrossOriginChildreasons 不是空的,则将 crossOriginDescendantsPreventsBfcache 设置为 true。

    3. reasonsForCrossOriginChildURL 设置为 null。

    4. reasonsForCrossOriginChildreasons 设置为 null。

    5. reasonsForCrossOriginChild子节点 设置为 null。

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

7.4.6.3 显示文档

一个Document 有一个布尔值已被显示,最初为 false。它用于确保pagereveal 事件对每个Document 的激活只触发一次(第一次渲染时触发一次,每次重新激活时触发一次)。

显示Document document

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

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

  3. transition解析传入跨文档视图过渡document 的结果。

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

  5. 如果 transition 不是 null,则

    1. 准备运行脚本 给定 document

    2. 激活 transition

    3. 清理运行脚本后 给定 document

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

尽管pagereveal 保证在第一个更新渲染步骤中触发,该步骤显示页面的最新版本,但用户代理可以在触发它之前自由显示页面的缓存帧。这可以防止pagereveal 处理程序的存在延迟此类缓存帧的呈现。

7.4.6.4 滚动到片段

滚动到Document 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 运行聚焦步骤,其中 Document视窗 作为备用目标

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

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

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

对于 HTML 文档 document,其 指示部分 是在给定 documentdocumentURL 的情况下, 选择指示部分 的结果。

选择指示部分,请给定一个 Document document 和一个 URL url

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

  2. fragmenturl片段

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

  4. potentialIndicatedElement 为在给定 documentfragment 的情况下 查找潜在的指示元素 的结果。

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

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

  7. decodedFragment 为对 fragmentBytes 运行 无 BOM 的 UTF-8 解码 的结果。

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

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

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

  11. 返回 null。

查找潜在的指示元素,请给定一个 Document 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文档 及其呈现的其他方面,例如表单字段的值,这些值是用户代理先前记录在 entry持久用户状态 中的。

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

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


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

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

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

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

  1. documententry文档

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

  3. 用户代理应尝试使用 entry滚动位置数据 来恢复 entry文档可恢复的滚动区域 的滚动位置。用户代理可能会继续定期尝试这样做,直到 document用户已滚动 变为 true。

    这是以尝试的形式制定的,可能会重复进行,直到成功或用户滚动,这是因为由 滚动位置数据 指示的相关内容可能需要一些时间从网络加载。

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