WebDriver BiDi

W3C 工作草案,

关于本文档的更多细节
此版本:
https://www.w3.org/TR/2026/WD-webdriver-bidi-20260511/
最新发布版本:
https://www.w3.org/TR/webdriver-bidi/
编辑草案:
https://w3c.github.io/webdriver-bidi/
先前版本:
历史:
https://www.w3.org/standards/history/webdriver-bidi/
实现报告:
https://wpt.fyi/results/webdriver/tests/bidi
测试套件:
https://github.com/web-platform-tests/wpt/tree/master/webdriver/tests/bidi
反馈:
GitHub
规范内联
编辑者:
James Graham (Mozilla)
Alex Rudenko (Google)
Maksim Sadym (Google)
频道:
irc.w3.org 上的 #webdriver
维基:
W3C WebDriver 维基

摘要

本文档定义了双向 WebDriver 协议,这是一种用于远程控制用户代理的机制。

本文档状态

本节描述了本文档在其发布时的状态。当前 W3C 出版物列表,以及本技术报告的最新修订版本,可在 W3C 标准与草案索引中找到。

讨论本规范时首选使用 GitHub Issues。或者,你也可以将评论发送到 Browser Testing and Tools Working Group 的 邮件列表 public-browser-tools-testing@w3.org归档)。

本文档由 Browser Testing and Tools Working Group 作为工作草案发布,并使用 推荐 标准轨道

作为工作草案发布并不意味着 W3C 及其成员对其背书。

这是一份草案文档,可能会在任何时候由其他文档更新、替换或废弃。 除作为进行中的工作外,不宜引用本文档。

本文档由一个根据 W3C 专利政策运作的小组制作。 W3C 维护了一份与该小组交付物相关的任何 专利披露的公开列表;该页面还包括 披露专利的说明。实际知晓某项专利且认为该专利包含必要权利要求的个人, 必须按照 W3C 专利政策第 6 节披露该信息。

本文档受 2025 年 8 月 18 日 W3C 流程文档管辖。

1. 引言

本节是非规范性的。

WebDriver 定义了一种用于 自省和 远程控制用户代理的协议。本规范通过 引入双向通信来扩展 WebDriver。相较于 WebDriver 严格的 命令/响应格式,这允许事件从 用户代理流式传输到控制软件,从而更好地匹配浏览器 DOM 的事件驱动本质。

2. 基础设施

本规范依赖 Infra Standard。[INFRA]

网络协议消息使用 CDDL 定义。[RFC8610]

本规范定义了一个等待 队列,它是一个映射

肯定有更好的 机制来做这种“等待事件”的事情。

当一个并行运行的算法 algorithm 等待一组 事件 eventsresume id 时:

  1. 暂停 algorithm 的执行。

  2. 断言:等待 队列不包含 resume id

  3. 等待 队列[resume id] 设置为(events, algorithm)。

要用给定的 nameidparameters恢复
  1. 如果等待队列不 包含 id,则返回。

  2. 令(events, algorithm)为等待队列[id]

  3. events 中的每个 event

    1. 如果 event 等于 name

      1. 等待队列中移除 id

      2. algorithm 被暂停的 位置恢复运行其中的步骤,并将 nameparameters 作为 等待的结果传入。

        我们是否应该有类似微任务的东西,以 确保它在事件循环上的任何其他任务之前 运行?

WebDriver 配置是一个具有以下内容的结构体

WebDriver 配置具有一个关联类型, 它 是一个类型。

WebDriver 配置要么是一个 其类型为该配置的关联类型的值,要么是 unset

Unset 是一个值,表示某个特定配置 尚未被设置。

注:此算法允许访问给定navigableWebDriver 配置,方式是依次检查 navigables、然后是 user contexts,最后是 global 中的值。 如果配置未设置,则返回 unset

要获取 WebDriver 配置 configuration 对于 navigable navigableWebDriver 配置值

  1. top-level traversablenavigable顶级 traversable

  2. 如果 configurationnavigables 包含 top-level traversable

    1. navigable configuration valueconfigurationnavigables[top-level traversable]。

    2. 如果 navigable configuration value 不是 unset,则返回 navigable configuration value

  3. user contextnavigable关联用户 上下文

  4. 如果 configurationuser contexts 包含 user context

    1. user context configuration valueconfigurationuser contexts[user context]。

    2. 如果 user context configuration value 不是 unset,则返回 user context configuration value

  5. 返回 configurationglobal

注:这是一个用于按 target 存储 WebDriver 配置的通用算法,target 可以是 navigable用户上下文,或者如果 target 为 null 或被省略,则全局存储。

要将 WebDriver 配置 configuration value 存储到可选 target 中, 其中 target 是一个navigable、 一个用户上下文,或在未提供时为 null:

  1. 如果 target 为 null,则将 configurationglobal 设置为 value

  2. 如果 target 是一个用户上下文,则将 configurationuser contexts[target] 设置为 value

  3. 如果 target 是一个navigable,则将 configurationnavigables[target] 设置为 value

注:此通用算法将 WebDriver 配置 存储在 globaluser contextsnavigables 中,具体取决于 command parameters 中是否存在 "userContexts" 和 "contexts"。这些 参数 是互斥的。如果两者都未提供,则配置会全局存储。

要针对给定的 command parameters 存储 WebDriver 配置 WebDriver 配置 configuration value

  1. 如果 command parameters 包含 "userContexts",且 command parameters 包含 "contexts",则返回带有错误 代码 invalid argument错误

  2. affected navigables 为空集合

  3. 如果 command parameters 包含 "contexts":

    1. navigables尝试command parameters["contexts"] 通过 id 获取有效顶级 traversables 的结果。

    2. 对于 navigables 中的每个 navigable

      1. navigable 追加affected navigables

      2. configurationvalue 存储navigable 中。

  4. 否则,如果 command parameters 包含 "userContexts":

    1. user contexts尝试command parameters["userContexts"] 获取有效用户上下文的结果。

    2. 对于 user contexts 中的每个 user context

      1. 对于所有其 关联用户上下文user context顶级 traversable列表中的每个 top-level traversable

        1. top-level traversable 追加affected navigables

      2. configurationvalue 存储user context 中。

  5. 否则:

    1. 对于所有顶级 traversable中的每个 top-level traversable,将 top-level traversable 追加affected navigables

    2. 存储 configurationvalue

  6. 返回 affected navigables

3. 协议

本节定义 WebDriver BiDi 协议的基本概念。这些术语不同于其在 传输层的表示。

协议使用 CDDL 定义来定义。为方便实现者,定义了两个单独的 CDDL 定义; 远端定义定义了 在本地端生成并由远端消费的消息格式,而 本地端 定义定义了在远端 生成并由本地端消费的消息格式

3.1. 定义

这是否应该作为 附录?

本节给出了 远端定义本地端定义的初始内容。 这些内容由本规范其余部分中定义的定义片段 进行扩充。

Remote end definition

Command = {
  id: js-uint,
  CommandData,
  Extensible,
}

CommandData = (
  BrowserCommand //
  BrowsingContextCommand //
  EmulationCommand //
  InputCommand //
  NetworkCommand //
  ScriptCommand //
  SessionCommand //
  StorageCommand //
  WebExtensionCommand
)

EmptyParams = {
   Extensible
}

Local end definition

Message = (
  CommandResponse /
  ErrorResponse /
  Event
)

CommandResponse = {
  type: "success",
  id: js-uint,
  result: ResultData,
  Extensible
}

ErrorResponse = {
  type: "error",
  id: js-uint / null,
  error: ErrorCode,
  message: text,
  ? stacktrace: text,
  Extensible
}

ResultData = (
  BrowserResult /
  BrowsingContextResult /
  EmulationResult /
  InputResult /
  NetworkResult /
  ScriptResult /
  SessionResult /
  StorageResult /
  WebExtensionResult
)

EmptyResult = {
  Extensible
}

Event = {
  type: "event",
  EventData,
  Extensible
}

EventData = (
  BrowsingContextEvent //
  InputEvent //
  LogEvent //
  NetworkEvent //
  ScriptEvent
)

远端定义本地端定义

Extensible = (*text => any)

js-int = -9007199254740991..9007199254740991
js-uint = 0..9007199254740991

3.2. 会话

WebDriver BiDi 扩展了 会话概念,该概念来自 WebDriver

会话具有一个 BiDi 标志,除非另有 说明,否则为 false。

BiDi 会话是一个 会话,其 BiDi 标志 被设为 true。

活动 BiDi 会话列表由以下步骤给出:
  1. BiDi sessions 为一个新的列表

  2. 对于活动会话中的每个 session

    1. 如果 session 是一个 BiDi 会话,则将 session 追加到 BiDi sessions

  3. 返回 BiDi sessions

3.3. 模块

WebDriver BiDi 协议被组织为多个模块。

每个模块表示与用户 代理某一方面有关的一组相关 命令事件。例如,模块可能包含用于检查和 操作 DOM,或用于脚本执行的功能。

每个模块都有一个模块名称,它是一个字符串。模块中定义的命令 和事件的命令名称事件名称模块名称开头,后跟一个句点 "."。

包含命令的模块定义 远端定义 片段。它们会为该模块的命令CommandData 组中提供选择项,也可以定义 额外的定义属性。它们 也可以定义 本地端定义 片段,为该模块中命令的结果 在 ResultData 组中提供额外选择项。

包含事件的模块定义 本地端定义 片段,这些片段是该模块事件Event 组中的 选择项。

实现可以定义扩展模块。这些扩展模块必须具有一个 包含单个冒号 ":" 字符的模块名称。 冒号之前的 部分是前缀;对于给定实现专用的所有 扩展模块, 这通常是相同的,并且对于 给定实现应当是唯一的。

其他规范可以定义自己的 WebDriver-BiDi 模块来扩展该协议。 这类模块的名称不得包含冒号(:)字符, 也不得定义包含该字符的命令名称事件名称或属性 名称。

鼓励外部规范的作者添加新模块,而不是扩展 现有模块。如果希望扩展某个现有模块,最好将该 扩展直接整合到包含原始模块定义的规范中。

3.4. 命令

命令是一种异步 操作,由 本地端请求,并在远端运行, 最终将 结果或错误返回给本地端。 多个 命令可以同时运行,并且命令可能会 长时间运行。因此,命令可能会乱序完成。

每个命令由以下内容定义:

可以在没有活动会话的情况下运行的命令是静态 命令。除非在其定义中说明,否则命令不是静态命令。

当命令从本地端发送时,它们 具有命令 id。这是一个 标识符,本地端用它来识别来自特定 命令的响应。从远端 的角度看, 该标识符是不透明的,不能在内部用于识别命令。

注:这是因为命令 id 完全由本地端 控制,并且在一个会话的过程中不一定唯一。例如,一个本地端如果 忽略所有响应,就可以对每个命令使用相同的命令 id。

所有命令 名称的集合是一个集合,包含 所有已定义的命令名称,包括任何属于扩展模块的命令名称。

3.5. 错误

WebDriver BiDi 使用以下额外代码扩展了来自 WebDriver错误代码集合:

invalid web extension
尝试安装无效的 Web 扩展。
no such client window
尝试与未知的客户端窗口交互。
no such handle
尝试反序列化未知的 RemoteObjectReference
no such history entry
尝试导航到未知的会话历史条目
no such network collector
尝试移除未知的收集器
no such intercept
尝试移除未知的网络拦截
no such network data
尝试引用未知的网络数据
no such node
尝试反序列化未知的 SharedReference
no such request
尝试继续处理未知的请求
no such script
尝试移除未知的预加载脚本
no such storage partition
尝试访问不存在的存储分区中的数据。
no such user context
尝试引用未知的用户上下文
no such web extension
尝试引用未知的 Web 扩展。
unable to close browser
尝试关闭浏览器,但未能做到。
unable to set cookie
尝试创建 cookie,但用户代理拒绝了它。
underspecified storage partition
尝试与未充分指定的存储分区中的数据交互。
unable to set file input
尝试设置文件输入,但未能做到。
unavailable network data
尝试获取未被收集或已被逐出的网络数据。
ErrorCode = "invalid argument" /
            "invalid selector" /
            "invalid session id" /
            "invalid web extension" /
            "move target out of bounds" /
            "no such alert" /
            "no such network collector" /
            "no such element" /
            "no such frame" /
            "no such handle" /
            "no such history entry" /
            "no such intercept" /
            "no such network data" /
            "no such node" /
            "no such request" /
            "no such script" /
            "no such storage partition" /
            "no such user context" /
            "no such web extension" /
            "session not created" /
            "unable to capture screen" /
            "unable to close browser" /
            "unable to set cookie" /
            "unable to set file input" /
            "unavailable network data" /
            "underspecified storage partition" /
            "unknown command" /
            "unknown error" /
            "unsupported operation"

3.6. 事件

事件是一个通知,由 远端 发送给本地端,表示远端上发生了值得关注的事情。

BiDi 会话具有订阅,它是一个列表,包含订阅

BiDi 会话具有一个已知订阅 id,它是一个集合,包含 已发布给本地端但尚未被取消订阅的所有 订阅 id

订阅是一个结构体,由一个 订阅 id(一个字符串)、 事件名称(一个事件名称的集合)、 顶级 traversable id(一个集合,包含顶级 traversable的 ID) 和 用户上下文 id(一个集合,包含用户上下文的 ID)。

如果 subscription顶级 traversable id是空集合, 且 subscription用户上下文 id是空集合,则订阅 subscription全局的

给定 event namenavigables启用了某个事件的会话 集合为:

  1. sessions 为一个新的集合

  2. 对于活动 BiDi 会话中的每个 session

    1. 如果对于 sessionevent namenavigables事件 已启用, 则将 session 追加到 sessions

  3. 返回 sessions

要在给定 sessionevent namenavigables 的情况下判断某个事件 是否已启用

注:navigables 是一个集合,因为共享 worker 可以关联 多个上下文。

  1. top-level traversables 为使用 navigables 调用获取顶级 traversable 的结果。

  2. 对于 session订阅中的每个 subscription

    1. 如果 subscription事件名称包含 event name,则继续

    2. 如果 subscription全局的,则返回 true。

    3. 如果用户上下文 id不为空:

      1. 对于 top-level traversables 中的每个 navigable

        1. 如果 subscription用户上下文 id包含 navigable关联用户上下文用户上下文 id, 则返回 true。

    4. 否则:

      1. subscription top-level traversables 为用 subscription顶级 traversable id 调用通过 id 获取 navigables 的结果。

      2. 如果 top-level traversablessubscription top-level traversables交集不是,则返回 true。

  3. 返回 false。

给定 event namesession启用了某个事件的顶级 traversable 集合 为:

  1. result 为一个新的集合

  2. 对于 session订阅中的每个 subscription

    1. 如果 subscription事件名称不 包含 event name, 则继续

    2. 如果 subscription全局的

      1. 对于远端的顶级 traversable中的每个 traversable

        1. traversable 追加result

      2. 中断

    3. 否则,如果用户上下文 id不为空:

      1. 对于远端的顶级 traversable中的每个 traversable

        1. 如果 subscription用户上下文 id包含 traversable关联用户上下文用户上下文 id,则将 traversable 追加result

    4. 否则:

      1. top-level traversables 为用 subscription顶级 traversable id 调用通过 id 获取 navigables 的结果。

      2. top-level traversables 中的每一项追加result

  3. 返回 result

要在给定 name 的情况下获得一组 事件名称
  1. events 为空集合

  2. 如果 name 包含 U+002E(句点):

    1. 如果 name 是某个事件的事件名称,则将 name 追加到 events 并返回带有数据 events成功

    2. 返回一个带有错误代码 invalid argument错误

  3. 否则,将 name 解释为表示某个模块中的所有事件。 如果 name 不是模块名称,则返回一个错误,其 错误代码invalid argument

  4. 将名称为 name 的模块中每个事件事件 名称 追加到 events

  5. 返回带有数据 events成功

4. 传输

消息传输使用 WebSocket 协议提供。 [RFC6455]

注:按 WebSocket 协议的术语,本地端是 客户端,而远端是服务器 / 远程主机。

注:命令事件编码为消息的方式 类似于 JSON-RPC,但本规范并未规范性地 引用它。[JSON-RPC]远端的规范性要求 改为以精确处理模型的形式给出,而不对 本地端给出规范性要求。

WebSocket 监听器 是一个能够 接受传入 WebSocket 连接的网络端点。

WebSocket 监听器 具有一个host、一个port、一个secure flag,以及一个 WebSocket 资源 列表

当创建 WebSocket 监听器 listener 时,远端 必须开始在 listenerhostport 所给定的主机和端口上监听 WebSocket 连接。如果 listenersecure flag 已设置,则从 listener 建立的连接必须经过 TLS 加密。

远端具有一个集合,其中包含 WebSocket 监听器 活动 监听器,其初始为空。

远端具有一个集合,其中包含未与 会话关联的 WebSocket 连接,其初始为空。

WebSocket 连接是遵循 WebSocket 协议要求的网络连接

BiDi 会话具有一个集合,其中包含会话 WebSocket 连接,其元素是WebSocket 连接。这 初始为空。

BiDi 会话 session 与连接 关联 connection,如果 session会话 WebSocket 连接包含 connection

注:每个 WebSocket 连接至多与一个 BiDi 会话关联。

当客户端通过连接到活动监听器集合之一的 listener建立 WebSocket 连接 connection 时, 实现必须按照 WebSocket 服务器端要求继续进行,并在决定是否 接受传入连接时运行以下步骤:

  1. resource name读取客户端开启握手所得的资源名称。如果 resource name 不在 listenerWebSocket 资源列表中,则停止 运行这些步骤,并表现为所请求的服务不可 用。

  2. 如果 resource name 是字节字符串 "/session", 且实现支持仅 BiDi 会话

    1. 运行任何其他实现定义的步骤,以决定是否应当接受 该连接;如果不接受,则停止运行这些 步骤,并表现为所请求的服务不可用。

    2. 将该连接添加到未与会话关联的 WebSocket 连接

    3. 返回。

  3. resource name 获取 WebSocket 资源的会话 ID, 并令 session id 为该值。如果 session id 为 null,则 停止运行这些步骤,并表现为所请求的服务不可 用。

  4. 如果活动会话列表中存在一个会话,其 会话 IDsession id,则令 session 为该 会话。否则停止运行这些步骤,并表现为所 请求的服务不可用。

  5. 运行任何其他实现定义的步骤,以决定是否 应接受该连接;如果不接受,则停止运行这些 步骤,并表现为所请求的服务不可用。

  6. 否则,将 connection 追加到 session会话 WebSocket 连接,并在服务器选择接受传入连接时,继续执行 WebSocket 服务器端要求

我们是否支持单个会话使用多于 1 个 连接?

当为 WebSocket 连接 connection 接收到 WebSocket 消息,其类型为 type 且数据为 data 时,远端 必须在给定 connectiontypedata 的情况下处理传入消息

当对 WebSocket 连接 connection 开始 WebSocket 关闭握手,或当该WebSocket 连接关闭时, 远端必须在给定 connection 的情况下处理连接 关闭

注:需要这两个条件,因为 WebSocket 连接可能在没有关闭握手的情况下被关闭。

要在给定会话 session 的情况下构造 WebSocket 资源名称

  1. 如果 session 为 null,则返回 "/session"

  2. 返回将字符串 "/session/" 与 session会话 ID连接所得的结果。

要在给定 WebSocket 监听器 listener会话 session 的情况下构造 WebSocket URL

  1. resource name 为用 session 调用构造 WebSocket 资源名称 的结果。

  2. 返回一个构造出的 WebSocket URI,其中 host 设置为 listenerhost,port 设置为 listenerport,path 设置为 resource name;如果 listenersecure flag 已设置,则遵循 wss-URI 构造,否则遵循 ws-URL 构造。

要在给定 resource name 的情况下获取 WebSocket 资源的会话 ID

  1. 如果 resource name 不是以字节字符串 "/session/" 开头,则返回 null。

  2. session idresource name 中位于 "/session/" 前缀之后的字节。

  3. 如果 session id 不是 UUID 的字符串表示,则返回 null。

  4. 返回 session id

要在给定会话 session 的情况下开始监听 WebSocket 连接
  1. 如果活动监听器中存在一个已有的WebSocket 监听器, 且远端想要复用它,则令 listener 为该 监听器。否则,令 listener 为一个新的 WebSocket 监听器,具有 实现定义的hostportsecure flag,以及一个空的WebSocket 资源列表

  2. resource name 为用 session 调用构造 WebSocket 资源名称 的结果。

  3. resource name 追加到 listenerWebSocket 资源 列表

  4. listener 追加远端活动监听器

  5. 返回 listener

注:处理多个会话的中介节点可以使用一个 或多个 WebSocket 监听器。WebDriver 定义 端点节点一次最多支持一个会话,因此预期 它只会有单个监听器。

注:对于端点 节点,上述步骤中的host 通常会是 "localhost"。

要在给定 WebSocket 连接 connection、类型 type 和数据 data 的情况下处理 传入消息
  1. 如果 type 不是text,则在给定 connection、 null 和invalid argument 的情况下发送错误响应,最后 返回。

  2. 断言data 是一个标量值字符串,因为 WebSocket 处理 UTF-8 编码数据中的错误否则已经 会使 WebSocket 连接失败

    似乎没有内容 定义 UTF-8 错误使用什么状态码

  3. 如果存在一个BiDi 会话与连接关联 connection, 则令 session 为该会话。否则,如果 connection未与会话关联的 WebSocket 连接中,则令 session 为 null。否则,返回。

  4. parsed 为在给定 data 的情况下将 JSON 解析为 Infra 值的结果。如果这抛出异常,则在给定 connection、 null 和invalid argument 的情况下发送错误响应,并 最后返回。

  5. 如果 session 非 null 且不在活动会话中,则返回。

  6. parsed远端定义匹配。 如果这产生 匹配:

    1. matched 为表示匹配数据的映射

    2. 断言:matched 包含 "id"、"method" 和 "params"。

    3. command idmatched["id"]。

    4. methodmatched["method"]

    5. command命令名称method 的命令。

    6. 如果 session 为 null 且 command 不是静态命令,则 在给定 connectioncommand idinvalid session id 的情况下发送错误响应,并返回。

    7. 并行运行以下步骤:

      1. result 为对于 command,在给定 session命令参数 matched["params"] 的情况下运行远端步骤所得的结果

      2. 如果 result 是一个错误,则在给定 connectioncommand idresult错误代码的情况下发送 错误响应,并最后 返回。

      3. valueresult 的数据。

      4. 断言:value结果类型的定义匹配, 该结果类型对应于命令 名称method 的命令。

      5. 如果 method 是 "session.new",则令 session活动会话列表中的条目,其会话 ID等于 value 的 "sessionId" 属性;将 connection 追加session会话 WebSocket 连接,并 从未与会话关联的 WebSocket 连接中移除 connection

      6. response 为一个新的映射,它与 CommandResponse 产生式匹配,该产生式在 本地端定义 中,其 id 字段设置为 command idvalue 字段设置为 value

      7. serialized 为在给定 response 的情况下将 infra 值序列化为 JSON 字节的结果。

      8. connection发送 WebSocket 消息,该消息由 serialized 组成。

  7. 否则:

    1. command id 为 null。

    2. 如果 parsed 是一个映射, 且 parsed["id"] 存在并且是一个 大于或等于零的整数,则将 command id 设置为该整数。

    3. error codeinvalid argument

    4. 如果 parsed 是一个映射, 且 parsed["method"] 存在并且是一个 字符串,但 parsed["method"] 不在所有命令名称的集合中,则将 error code 设置为unknown command

    5. 在给定 connectioncommand iderror code 的情况下发送错误响应

要在给定设置对象 settings 的情况下获取相关 navigables

  1. related navigables 为空集合

  2. 如果 settings相关全局对象是一个 Window

    1. navigable相关全局对象关联 Document节点 navigable

    2. 如果 navigable 非 null,则将 navigable 追加到 related navigables

  3. 否则,如果 settings 所指定的全局对象是一个 WorkerGlobalScope, 则对于该全局对象所有者集合中的每个 owner

    1. navigable 为 null。

    2. 如果 owner 是一个Document,则将 navigable 设置为 owner节点 navigable

    3. 如果 navigable 非 null,则将 navigable 追加到 related navigables

  4. 返回 related navigables

要在给定一个 context id navigable ids列表的情况下通过 id 获取 navigables

  1. result 为空集合

  2. 对于 navigable ids 中的每个 navigable id

    1. 如果存在 id 为 navigable idnavigable,则令 navigable 为该 navigable,否则为 null。

    2. 如果 navigable 非 null,则将 navigable 追加result

  3. 返回 result

要在给定navigables navigables列表的情况下获取 顶级 traversables

  1. result 为空集合

  2. 对于 navigables 中的每个 navigable

    1. navigable追加顶级 traversableresult

  3. 返回 result

要在给定 context id navigable ids列表的情况下通过 id 获取有效 navigables

  1. result 为空集合

  2. 对于 navigable ids 中的每个 navigable id

    1. navigable尝试navigable id 获取 navigable的结果。

    2. navigable 追加result

  3. 返回带有数据 result成功

要在给定 context id navigable ids列表的情况下通过 id 获取有效顶级 traversables

  1. result 为空集合

  2. 对于 navigable ids 中的每个 navigable id

    1. navigable尝试navigable id 获取 navigable的结果。

    2. 如果 navigable 不是顶级 traversable,则返回带有错误代码 invalid argument错误

    3. navigable 追加result

  3. 返回带有数据 result成功

要在给定 sessionbody 的情况下发出事件
  1. 断言bodyEvent 产生式匹配。

  2. serialized 为在给定 body 的情况下将 infra 值序列化为 JSON 字节的结果。

  3. 对于 session会话 WebSocket 连接中的每个 connection

    1. connection发送 WebSocket 消息,该消息由 serialized 组成。

要在给定 WebSocket 连接 connectioncommand iderror code 的情况下发送错误 响应
  1. error data 为一个新的映射,与 本地端定义中的 ErrorResponse 产生式匹配, 其中 id 字段 设置为 command iderror 字段设置为 error codemessage 字段设置为一个实现定义的字符串, 包含对所发生错误的人类可读定义,并且 stacktrace 字段可选地设置为一个实现定义的 字符串,包含错误发生时活动栈帧的栈跟踪报告。

  2. response 为在给定 error data 的情况下将 infra 值序列化为 JSON 字节 的结果。

    注:command id 可以为 null,在 这种情况下,id 字段也会 被设置为 null,而不会从 response 中省略。

  3. connection发送 WebSocket 消息,该消息由 response 组成。

要在给定 WebSocket 连接 connection 的情况下处理连接 关闭

  1. 如果存在一个BiDi 会话与连接关联 connection

    1. session与连接关联 connectionBiDi 会话

    2. session会话 WebSocket 连接中移除 connection

  2. 否则,如果未与会话关联的 WebSocket 连接 包含 connection,则从该集合中移除 connection

注:这不会结束任何会话

需要挂接到 会话结束,以允许 UA 在需要时关闭 监听器。

要在给定 session 的情况下关闭 WebSocket 连接

  1. 对于 session会话 WebSocket 连接中的每个 connection

    1. 使用 connection 开始 WebSocket 关闭握手

      注:这将导致 对 connection 运行处理连接关闭中的步骤, 这些步骤将清理与 connection 关联的资源。

4.1. 建立连接

WebDriver 客户端通过请求值为 true 的 WebSocket URL 能力,选择加入双向连接。

本规范定义的 WebDriver 新会话算法, 其参数为 sessioncapabilitiesflags,如下:
  1. 如果 flags 包含 "bidi",则返回。

  2. webSocketUrl 为从 capabilities 获取名为 "webSocketUrl" 的属性的结果。

  3. 如果 webSocketUrl 是 undefined,则返回。

  4. 断言webSocketUrl 为 true。

  5. listener 为在给定 session 的情况下开始监听 WebSocket 连接的结果。

  6. webSocketUrl 设置为用 listenersession 构造 WebSocket URL的结果。

  7. capabilities设置名为 "webSocketUrl" 的属性为 webSocketUrl

  8. sessionBiDi 标志设置为 true。

  9. 将 "bidi" 追加到 flags。

实现还应允许客户端建立一个 不是 HTTP 会话BiDi 会话。在这种情况下,WebSocket 服务器的 URL 通过带外方式传达。允许这样做的实现支持 仅 BiDi 会话。当这样的实现准备好接受 启动 WebDriver 会话的请求时,它必须:

  1. 在给定 null 的情况下开始监听 WebSocket 连接

5. 沙盒化脚本执行

自动化工具的一个常见需求是执行这样的脚本:它们可以 访问某个文档的 DOM,但没有关于包含该 文档的 navigable 中运行的脚本对 DOM API 所做任何更改的信息。

BiDi 会话具有一个沙盒映射,它是一个弱 映射,其中 键是 Window 对象,值是字符串与 SandboxWindowProxy 对象之间的映射。

注:这里对沙盒的定义,是试图 将现有实现的行为编纂成规范。它暴露了实现中 以前被规范视为内部的部分,尤其是 平台对象的内部状态(通常以浏览器 引擎主要实现语言中的原生对象来实现)与 ECMAScript 可见状态之间的 区别。由于现有沙盒 实现发生在引擎的低层,实现要在 所有细节上收敛到本规范可能是一个缓慢过程。在 此期间,鼓励实现者提供有关其与规范 差异的详细文档,并鼓励此特性的用户 显式测试在沙盒中运行的脚本是否能在所有实现中工作。

5.1. 沙盒 Realm

每个沙盒都是一个唯一的 ECMAScript Realm。但是,沙盒 realm 通过 SandboxProxy 对象提供对现有 Window realm 中平台对象的访问。

要在给定 namenavigable 的情况下获取或 创建沙盒 realm
  1. 如果 name 为空字符串,则返回带有 错误代码 invalid argument错误

  2. windownavigable活动窗口

  3. 如果沙盒映射不 包含 window,则将沙盒映射[window] 设置为新的映射

  4. sandboxes沙盒映射[window]。

  5. 如果 sandboxes 不包含 name,则将 sandboxes[name] 设置为用 navigable 调用创建沙盒 realm的结果。

  6. 返回带有数据 sandboxes[name] 的成功

要用 window 创建沙盒 realm

定义 沙盒 realm 的创建。这将返回一个 SandboxWindowProxy, 其包装 window

要在给定 target realm 的情况下获取沙盒 名称

  1. realms maps获取沙盒映射的值所得的结果。

  2. 对于 realms maps 中的每个 realms map

    1. 对于 realms map 中的每个 namerealm

      1. 如果 realmtarget realm,则返回 name

  3. 返回 null。

5.2. 沙盒代理对象

SandboxProxy 对象是一个特异对象,用于调解对 另一个 realm 中对象的沙盒化 访问。沙盒代理对象被设计为强制执行 以下限制:

不存在 SandboxProxy 接口对象。

详细定义 SandboxProxy 如何工作

要获取解包装的 object
  1. 只要 objectSandboxProxySandboxWindowProxy, 就将 object 设置为它的 被包装对象。

  2. 返回 object

5.3. SandboxWindowProxy

SandboxWindowProxy 是一个特异对象,表示由 SandboxProxy 对象包装的 Window 对象。这提供了对 Window 全局中该数据的沙盒化 访问。

定义它如何工作。

6. 用户上下文

用户上下文表示 远端内零个或多个 顶级 traversable的集合。 每个用户上下文都有 一个关联的存储 分区,因此远端数据不会在不同的用户上下文之间 共享。

目前还不清楚这是不是 正式定义用户上下文概念或其与存储交互的 最佳方式。

注:Infra 规范使用术语“user agent”来指代 与用户上下文相同的概念。然而,这与 “user agent”用来表示包含多个用户上下文的整个 Web 客户端这一用法 不兼容。虽然这种差异对 Web 内容不可见, 但它可通过 WebDriver 被观察到,因此我们避免使用该术语。

用户上下文具有一个用户上下文 id, 它是在用户上下文创建时设置的唯一字符串。

navigable 具有一个关联用户上下文,它是一个用户上下文

当新的顶级 traversable被创建时,其关联用户上下文 被设置为用户上下文集合中的某个用户上下文。

注:在某些情况下,用户上下文会在 顶级 traversable创建时由规范设置;但是在不存在此类 要求的情况下,关联用户上下文对于顶级 traversable是实现定义的。

我们是否应指定具有非 null opener 的顶级 traversable具有与其 opener 相同的关联用户上下文? 需要检查这是否是现有实现会强制执行的内容。

子 navigable关联用户上下文是 其 父级关联用户上下文

如果某个用户上下文不是任何 顶级 traversable关联 用户上下文,则它是一个空用户上下文

默认用户 上下文是一个用户 上下文,其用户上下文 id"default"

实现具有一个用户上下文集合,它是一个由用户上下文组成的集合。初始时,它 包含默认 用户上下文

实现可以在任何时候将新的用户上下文追加用户上下文集合, 例如响应用户操作。

注:这里的“任何时候”包括实现 启动期间,因此给定 实现可能总是在用户上下文集合中有多个条目。

实现可以在任何 时候从用户上下文集合移除任何空用户上下文,但 默认用户 上下文除外。然而,它们并非必须移除这类用户上下文。不是空用户上下文用户上下文不得从 用户 上下文集合中移除。

BiDi 会话具有一个 用户上下文到接受不安全 证书覆盖映射,它是 用户上下文与 boolean 之间的映射

BiDi 会话具有一个用户 上下文到代理配置映射,它是 用户上下文代理配置之间的映射

模拟网络条件结构体是一个具有以下内容的结构体

BiDi 会话具有模拟网络条件,它是 一个结构体,具有 一个名为 default network conditions,它是 一个 模拟网络条件结构体或 null;一个 名为 user context network conditions, 它 是用户 上下文模拟网络条件结构体之间的弱映射; 以及一个名为 navigable network conditions, 它是 navigable模拟 网络条件结构体之间的 弱映射。

用户上下文用户 上下文集合中被移除时,移除用户上下文订阅

移除 用户上下文订阅

  1. 对于活动会话中的每个 session

    1. subscriptions to remove 为一个集合

    2. 对于 session订阅中的每个 subscription

      1. 如果 subscription用户上下文 id 包含 navigable关联用户上下文用户上下文 id

        1. subscription用户上下文 id移除 navigable关联用户上下文用户上下文 id

        2. 如果 subscription用户上下文 id 为空:

          1. subscription 追加subscriptions to remove

    3. session订阅移除 subscriptions to remove

要在给定 user context id 的情况下获取用户上下文
  1. 对于用户上下文集合中的每个 user context

  2. 如果 user context用户上下文 id等于 user context id

    1. 返回 user context

  3. 返回 null。

要在给定 user context ids 的情况下获取有效用户 上下文

  1. result 为空集合

  2. 对于 user context ids 中的每个 user context id

    1. user context 设置为用 user context id 调用获取用户上下文的结果。

    2. 如果 user context 为 null,则返回带有 错误代码 no such user context错误

    3. user context 追加result

  3. 返回 result

7. 模块

7.1. session 模块

session 模块包含用于监控远端状态的命令和 事件。

7.1.1. 定义

远端定义

SessionCommand = (
  session.End //
  session.New //
  session.Status //
  session.Subscribe //
  session.Unsubscribe
)

本地端定义

SessionResult = (
  session.EndResult /
  session.NewResult /
  session.StatusResult /
  session.SubscribeResult /
  session.UnsubscribeResult
)
要在给定 session 的情况下结束会话
  1. 活动会话中移除 session

  2. 如果活动会话,则将 webdriver-active 标志 设置为 false。

要在给定 session 的情况下清理 会话

  1. 使用 session 关闭 WebSocket 连接

  2. 对于用户上下文集合中的每个 user context

    1. 移除 session用户上下文到接受不安全证书覆盖映射[user context]。

    2. 移除 session用户上下文到代理配置映射[user context]。

  3. 对于 session已阻塞请求映射中的每个 request id →(requestphaseresponse):

    1. 使用 "continue request"、request id 和(response、"incomplete")恢复

  4. 对于 session网络收集器中的每个 collector

    1. collector idcollector收集器

    2. 对于已收集的网络 数据中的每个 collected data,使用 collected datacollector id 从数据中移除收集器

  5. 如果活动会话,则清理远端状态

  6. 执行任何特定于实现的清理步骤。

清理远端 状态
  1. 清空发送请求前映射

  2. 默认缓存行为设置为 "default"。

  3. 清空navigable 缓存行为映射

  4. 执行实现定义的步骤,以启用当前远端配置中通常启用的任何 特定于实现的资源缓存。

7.1.2. 类型

7.1.2.1. session.CapabilitiesRequest 类型
session.CapabilitiesRequest = {
  ? alwaysMatch: session.CapabilityRequest,
  ? firstMatch: [*session.CapabilityRequest]
}

session.CapabilitiesRequest 类型表示为会话请求的能力。

7.1.2.2. session.CapabilityRequest 类型

远端定义本地端定义

session.CapabilityRequest = {
  ? acceptInsecureCerts: bool,
  ? browserName: text,
  ? browserVersion: text,
  ? platformName: text,
  ? proxy: session.ProxyConfiguration,
  ? unhandledPromptBehavior: session.UserPromptHandler,
  Extensible
}

session.CapabilityRequest 类型表示一组特定的 请求能力。

WebDriver BiDi 定义了额外的 WebDriver 能力。下表列举了每个实现都必须为 WebDriver BiDi 支持的能力。

能力: WebSocket URL
键: "webSocketUrl"
值类型: boolean
描述: 定义当前会话对双向连接的支持。
"webSocketUrl" 能力的额外能力反序列化 算法,参数为 value,如下:
  1. 如果 value 不是 boolean,则返回带有代码 invalid argument错误

  2. 返回带有数据 value成功

"webSocketUrl" 能力的匹配能力序列化 算法, 参数为 value,如下:
  1. 如果 value 为 false,则返回带有数据 null 的成功

  2. 返回带有数据 true 的成功

7.1.2.3. session.ProxyConfiguration 类型

远端定义本地端定义

session.ProxyConfiguration = {
   session.AutodetectProxyConfiguration //
   session.DirectProxyConfiguration //
   session.ManualProxyConfiguration //
   session.PacProxyConfiguration //
   session.SystemProxyConfiguration
}

session.AutodetectProxyConfiguration = (
   proxyType: "autodetect",
   Extensible
)

session.DirectProxyConfiguration = (
   proxyType: "direct",
   Extensible
)

session.ManualProxyConfiguration = (
   proxyType: "manual",
   ? httpProxy: text,
   ? sslProxy: text,
   ? session.SocksProxyConfiguration,
   ? noProxy: [*text],
   Extensible
)

session.SocksProxyConfiguration = (
   socksProxy: text,
   socksVersion: 0..255,
)

session.PacProxyConfiguration = (
   proxyType: "pac",
   proxyAutoconfigUrl: text,
   Extensible
)

session.SystemProxyConfiguration = (
   proxyType: "system",
   Extensible
)

7.1.2.4. session.UserPromptHandler 类型

远端定义本地端定义

session.UserPromptHandler = {
  ? alert: session.UserPromptHandlerType,
  ? beforeUnload: session.UserPromptHandlerType,
  ? confirm: session.UserPromptHandlerType,
  ? default: session.UserPromptHandlerType,
  ? file: session.UserPromptHandlerType,
  ? prompt: session.UserPromptHandlerType,
}

session.UserPromptHandler 类型表示 用户提示处理程序的配置。

注:file 处理文件选择器。"accept" 和 "dismiss" 会关闭 选择器。"ignore" 会保持选择器打开。

7.1.2.5. session.UserPromptHandlerType 类型

远端定义本地端定义

session.UserPromptHandlerType = "accept" / "dismiss" / "ignore";

session.UserPromptHandlerType 类型表示 用户提示处理程序的行为。

7.1.2.6. session.Subscription 类型
session.Subscription = text

session.Subscription 类型表示唯一的订阅标识符。

7.1.2.7. session.SubscribeParameters 类型
session.SubscribeParameters = {
  events: [+text],
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

session.SubscribeParameters 类型表示 订阅一组特定事件的请求。

7.1.2.8. session.UnsubscribeByIDRequest 类型
session.UnsubscribeByIDRequest = {
  subscriptions: [+session.Subscription],
}

session.UnsubscribeByIDRequest 类型表示 移除由订阅 ID 标识的事件订阅的请求。

7.1.2.9. session.UnsubscribeByAttributesRequest 类型
session.UnsubscribeByAttributesRequest = {
  events: [+text],
}

session.UnsubscribeByAttributesRequest 类型表示 使用订阅属性取消订阅的请求。

7.1.3. 命令

7.1.3.1. session.status 命令

session.status 命令返回关于 远端是否处于可创建新会话状态的信息, 但也可以另外包含特定于实现的任意元信息。

这是一个静态命令

命令类型
session.Status = (
  method: "session.status",
  params: EmptyParams,
)
返回类型
session.StatusResult = {
  ready: bool,
  message: text,
}

给定 sessioncommand parameters 时,远端步骤为:

  1. body 为一个具有以下属性的新映射

    "ready"
    远端就绪状态
    "message"
    一个实现定义的字符串,用于解释远端就绪状态
  2. 返回带有数据 body成功

7.1.3.2. session.new 命令

session.new 命令允许创建新的 BiDi 会话

注:以这种方式创建的会话将不能 通过 HTTP 访问。

这是一个静态命令

命令类型
session.New = (
  method: "session.new",
  params: session.NewParameters
)

session.NewParameters = {
  capabilities: session.CapabilitiesRequest
}
返回类型
session.NewResult = {
  sessionId: text,
  capabilities: {
    acceptInsecureCerts: bool,
    browserName: text,
    browserVersion: text,
    platformName: text,
    setWindowRect: bool,
    userAgent: text,
    ? proxy: session.ProxyConfiguration,
    ? unhandledPromptBehavior: session.UserPromptHandler,
    ? webSocketUrl: text,
    Extensible
  }
}

给定 sessioncommand parameters 时,远端步骤为:

  1. 如果 session 不是 null,则返回一个错误,错误 代码为 session not created

  2. 如果实现因任何原因无法启动新会话,则返回 一个错误,错误代码为 session not created

  3. flags 为一个包含 "bidi" 的集合

  4. capabilities json 为使用 command parametersflags 尝试处理能力 所得的结果。

  5. capabilities 为用 capabilities json 调用将 JSON 派生的 JavaScript 值转换为 Infra 值的结果。

  6. session 为使用 capabilitiesflags 尝试创建会话所得的结果。

  7. sessionBiDi 标志设置为 true。

    注:此会话的连接将由调用者设置为当前连接。

  8. body 为一个新的映射, 它与 session.NewResult 产生式匹配, 其 sessionId 字段设置为 session会话 ID,并且 capabilities 字段设置为 capabilities

  9. 返回带有数据 body成功

7.1.3.3. session.end 命令

session.end 命令结束当前 会话

命令类型
session.End = (
  method: "session.end",
  params: EmptyParams
)

返回类型
session.EndResult = EmptyResult

给定 sessioncommand parameters 时,远端步骤为:

  1. 使用 session 结束会话

  2. 返回带有数据 null 的成功,并并行运行以下 步骤:

    1. 等到发送 WebSocket 消息步骤已使用 对此命令的 响应被调用。

      这 是相当不精确的语言,但希望意图很清楚: 在开始关闭连接之前,我们要先发送命令响应。

    2. 使用 session 清理会话

7.1.3.4. session.subscribe 命令

session.subscribe 命令会全局地或针对一组 navigable 启用某些事件。

这需要 泛化,以便也适用于 realm。

命令类型
session.Subscribe = (
  method: "session.subscribe",
  params: session.SubscribeParameters
)
返回类型
session.SubscribeResult = {
  subscription: session.Subscription,
}
给定 sessioncommand parameters 时,远端步骤为:
  1. event names 为空集合

  2. 对于 command parameters["events"] 中的每个条目 name,令 event namesevent names尝试name 获得一组 事件名称的结果的并集

  3. input user context ids 为用 command parameters[userContexts] 创建集合所得的结果。

  4. input context ids 为用 command parameters[contexts] 创建集合所得的结果。

  5. 如果 input user context ids 非空且 input context ids 非空, 则返回带有错误 代码 invalid argument错误

  6. subscription navigables 为一个集合

  7. top-level traversable context ids 为一个集合

  8. 如果 input context ids 非空:

    1. navigables尝试input context ids 通过 id 获取有效 navigables的结果。

    2. subscription navigables 设置为用 navigables 调用获取 顶级 traversables的结果。

    3. 对于 subscription navigables 中的每个 navigable

      1. navigablenavigable id 追加top-level traversable context ids

  9. 否则,如果 input user context ids 非空:

    1. 对于 input user context ids 中的每个 user context id

      1. user context 为用 user context id 调用获取用户上下文的结果。

      2. 如果 user context 为 null,则返回带有错误代码 no such user context错误

      3. 对于所有其关联用户上下文user context顶级 traversable列表中的每个 top-level traversable

        1. top-level traversable 追加subscription navigables

  10. 否则,将 subscription navigables 设置为远端中所有 顶级 traversable组成的集合

  11. subscription 为一个订阅,其 订阅 id设置为 UUID 的字符串表示, 事件名称设置为 event names顶级 traversable id设置为 top-level traversable context ids,并且 用户上下文 id设置为 input user context ids

  12. subscribe step events 为一个新的映射

  13. 对于 event names 中的每个 event name

    1. 如果事件(其事件 名称event name)没有定义远端订阅步骤, 则继续;

    2. existing navigables 为使用 sessionevent name 调用启用了某个事件的顶级 traversable 集合的结果。

    3. subscribe step events[event name] 设置为 subscription navigablesexisting navigables差集

  14. subscription 追加到 session订阅

  15. subscription订阅 id追加到 session已知订阅 id

  16. 使用以下小于算法,按升序排序 subscribe step events;给定两个键为 event name oneevent name two 的条目:

    1. event one 为名称为 event name one事件

    2. event two 为名称为 event name two事件

    3. 如果 event one订阅 优先级小于 event two 的订阅优先级,则返回 true,否则返回 false。

  17. 如果 subscription全局的,则令 include global 为 true, 否则令 include global 为 false。

  18. 对于 subscribe step events 中的每个 event namenavigables

    1. 事件(其事件 名称event name)运行远端订阅步骤,给定 sessionnavigablesinclude global

  19. body 为一个新的映射, 它与 session.SubscribeResult 产生式匹配, 其 subscription 字段设置为 subscription订阅 id

  20. 返回带有数据 body成功

7.1.3.5. session.unsubscribe 命令

session.unsubscribe 命令会全局地或针对一组 navigable 禁用事件。

这需要 泛化,以便也适用于 realm。

命令类型
session.Unsubscribe = (
  method: "session.unsubscribe",
  params: session.UnsubscribeParameters,
)

session.UnsubscribeParameters = session.UnsubscribeByAttributesRequest / session.UnsubscribeByIDRequest
返回类型
session.UnsubscribeResult = EmptyResult
给定 sessioncommand parameters 时,远端步骤为:
  1. 如果 command parameters包含 "subscriptions":

    注:该条件意味着 command parameters 与 session.UnsubscribeByAttributesRequest 产生式匹配。

    1. event names 为空集合

    2. 对于 command parameters["events"] 中的每个条目 name, 令 event namesevent names尝试name 获得 一组事件名称所得结果的并集

    3. new subscriptions 为一个列表

    4. matched events 为一个集合

    5. 对于 session订阅中的每个 subscription

      1. 如果 subscription事件名称event names交集是一个空集合

        1. subscription 追加new subscriptions

        2. 继续

      2. 如果 subscription 不是全局的

        1. subscription 追加new subscriptions

        2. 继续

      3. subscription event namessubscription事件名称克隆

      4. 对于 event names 中的每个 event name

        1. 如果 subscription event names 包含 event name

          1. event name 追加matched events

          2. subscription event names移除 event name

      5. 如果 subscription event names 非空:

        1. cloned subscription 为一个订阅,其 订阅 id设置 为 subscription订阅 id事件名称设置为一个新的 集合,其中包含 subscription event names

        2. cloned subscription 追加new subscriptions

    6. 如果 matched events等于 event names,则返回带有 错误代码 invalid argument错误

    7. session订阅设置为 new subscriptions

  2. 否则:

    1. subscriptions 为用 command parameters[subscriptions] 创建 集合所得的结果。

    2. unknown subscription idssubscriptionssession已知订阅 id之间的差集

    3. 如果 unknown subscription ids 非空:

      1. 返回带有错误代码 invalid argument错误

    4. subscriptions to remove 为空集合

    5. 对于 session订阅中的每个 subscription

      1. 如果 subscriptions 包含 subscription订阅 id

        1. subscription 追加subscriptions to remove

    6. session已知订阅 id设置为 session已知订阅 idsubscriptions之间的差集

    7. session订阅移除 subscriptions to remove 中的每一项。

  3. 返回带有数据 null 的成功

7.2. browser 模块

browser 模块包含用于 管理远端浏览器进程的命令。

7.2.1. 定义

远端定义

BrowserCommand = (
  browser.Close //
  browser.CreateUserContext //
  browser.GetClientWindows //
  browser.GetUserContexts //
  browser.RemoveUserContext //
  browser.SetClientWindowState //
  browser.SetDownloadBehavior
)

本地端定义

BrowserResult = (
  browser.CloseResult /
  browser.CreateUserContextResult /
  browser.GetClientWindowsResult /
  browser.GetUserContextsResult /
  browser.RemoveUserContextResult /
  browser.SetClientWindowStateResult /
  browser.SetDownloadBehaviorResult
)

7.2.2. 窗口

每个顶级 traversable都关联到单个客户端 窗口,该窗口表示一个矩形区域,其中包含 用于在其可见性状态为 "visible" 时渲染该顶级 traversable活动文档视口,以及与显示该 traversable 相关联的任何浏览器特定用户界面元素 (例如任何 URL 栏、工具栏或 OS 窗口装饰)。

客户端窗口具有一个客户端窗口 id,它是唯一 标识该窗口的字符串。

客户端窗口具有一个x 坐标,它是 Web 暴露屏幕区域左边缘与窗口左边缘之间的 CSS 像素数,若这对于某个 特定窗口没有意义则为零。

客户端窗口具有一个y 坐标,它是 Web 暴露屏幕区域上边缘与窗口上边缘之间的 CSS 像素数,若这对于某个 特定窗口没有意义则为零。

客户端窗口具有一个宽度,它是 窗口矩形的宽度,以 CSS 像素计。

客户端窗口具有一个高度,它是 窗口矩形的高度,以 CSS 像素计。

最大化 客户端窗口 window,实现应当要么 执行与平台最大化 window 概念相对应的步骤,要么 定位 window,使其x 坐标尽可能接近 0,其y 坐标尽可能接近 0, 其宽度尽可能接近 Web 暴露屏幕区域的宽度,且其高度尽可能接近 Web 暴露屏幕区域的高度。如果支持这两个选项中的任一个, 则支持最大化客户端窗口

最小化 客户端窗口 window,实现应当要么 执行与平台最小化 window 概念相对应的步骤,要么 以其他方式隐藏 window,使得与 window 关联的 顶级 traversable中的所有活动文档都具有 "hidden" 的可见性状态,并且 window宽度高度都尽可能接近 0。如果支持这两个 选项中的任一个,则支持最小化客户端窗口

还原 客户端窗口 window,实现应确保它 既不处于平台定义的最大化状态,也不处于平台定义的 最小化状态,并且如果存在一个或多个与 window 关联的顶级 traversable, 其中至少一个具有处于 "visible" 状态的活动文档。如果支持这一点,则支持还原客户端 窗口

要在给定 window 的情况下获取 客户端窗口状态

  1. documents 为空列表

  2. visible documents 为空列表

  3. 对于每个顶级 traversable traversable

    1. 如果 traversable客户端窗口不是 window,则 继续。

    2. documenttraversable活动文档

    3. document 追加documents

    4. 如果 document可见性状态为 "visible", 则将 document 追加visible documents

  4. 对于 visible documents 中的每个 document

    1. 如果 document全屏元素不是 null,则返回 "fullscreen"。

  5. 如果 visible documentsdocuments 不是 ,或者如果 window 以其他方式处于特定于 OS 的 最小化状态,则返回 "minimized"。

    注:这通常但不一定意味着 window宽度高度等于 0。

  6. 如果 window 处于特定于 OS 的最大化状态,则返回 "maximized"。

    注:这通常但不一定意味着 window宽度等于Web 暴露屏幕区域的宽度,并且 window高度等于 Web 暴露屏幕区域的高度。

  7. 返回 "normal"。

要在给定 windowstate 的情况下设置 客户端窗口状态

  1. current state 为使用 window 获取客户端窗口状态的结果。

  2. 如果 current state 是 "fullscreen"、"maximized" 或 "minimized",且等于 state,则返回带有数据 null 的成功

  3. 在以下条件及其关联步骤列表中,运行第一个关联条件为 true 的步骤集:

    "fullscreen"
    如果不支持全屏,则返回带有错误代码 unsupported operation错误
    "normal"
    如果对于 window支持还原客户端窗口, 则返回带有 错误代码 unsupported operation错误
    "maximize"
    如果对于 window支持最大化客户端窗口, 则返回带有 错误代码 unsupported operation错误
    "minimize"
    如果对于 window支持最小化客户端窗口, 则返回带有 错误代码 unsupported operation错误
  4. documents 为空列表

  5. 对于每个顶级 traversable traversable

    1. 如果 traversable 的关联客户端窗口不是 window,则 继续。

    2. documenttraversable活动文档

    3. document 追加到 documents

  6. 如果 documents,则返回 带有错误 代码 no such client window错误

  7. 如果 current state 是 "fullscreen":

    1. 对于 documents 中的每个 document

      1. 使用 document 完全退出全屏

        注:对于窗口中并非全屏的 文档,这是无操作。

  8. 如果 current state 是 "maximized" 或 "minimized":

    1. 还原客户端窗口 window

  9. 根据 state 的值进行切换:

    "fullscreen"
    1. 对于 documents 中的每个 document

      1. 如果 document可见性状态为 "visible", 则使用 documentdocument element使元素全屏

      2. 中断

    "maximize"
    1. 最大化客户端窗口 window
    "minimize"
    1. 最小化客户端窗口 window
  10. 返回带有数据 null 的成功

7.2.3. 类型

7.2.3.1. browser.ClientWindow 类型
browser.ClientWindow = text;

browser.ClientWindow 唯一标识一个客户端窗口

7.2.3.2. browser.ClientWindowInfo 类型
browser.ClientWindowInfo = {
  active: bool,
  clientWindow: browser.ClientWindow,
  height: js-uint,
  state: "fullscreen" / "maximized" / "minimized" / "normal",
  width: js-uint,
  x: js-int,
  y: js-int,
}

browser.ClientWindowInfo 类型表示 客户端窗口的属性。

要在给定 client window 的情况下获取客户端 窗口信息
  1. client window idclient window客户端窗口 id

  2. state 为使用 client window 调用获取客户端窗口状态的结果。

  3. 如果 client window 能够接收从操作系统传送来的键盘输入, 则令 active 为 true,否则令 active 为 false。

    注:这可能意味着某个顶级 traversable(其客户端窗口client window)具有系统焦点,也可能意味着浏览器自身的 用户界面当前具有焦点。

  4. client window info 为一个映射, 它与 browser.ClientWindowsInfo 产生式匹配,其 clientWindow 字段设置为 client window idstate 字段设置为 statex 字段设置为 client windowx 坐标y 字段设置为 client windowy 坐标width 字段设置 为 client window宽度height 字段 设置为 client window高度,且 active 字段设置为 active

  5. 返回 client window info

7.2.3.3. browser.UserContext 类型
browser.UserContext = text;

browser.UserContext 唯一标识一个用户 上下文

7.2.3.4. browser.UserContextInfo 类型
browser.UserContextInfo = {
  userContext: browser.UserContext
}

browser.UserContextInfo 类型表示用户上下文的属性。

7.2.4. 命令

7.2.4.1. browser.close 命令

browser.close 命令终止所有 WebDriver 会话,并清理远程浏览器实例中的自动化状态。

命令类型
browser.Close = (
  method: "browser.close",
  params: EmptyParams,
)
返回类型
browser.CloseResult = EmptyResult
给定 sessioncommand parameters 时,远端步骤为:
  1. 使用 session 结束会话

  2. 如果活动会话不是,实现可以 返回带有错误 代码 unable to close browser错误,然后 并行运行以下步骤:

    1. 等到发送 WebSocket 消息步骤已使用 对此命令的 响应被调用。

    2. 使用 session 清理会话

    注:当浏览器具有多个自动化 会话时的行为目前未指定。可能是任何会话都可以关闭 浏览器,也可能只有最后一个打开的会话才能实际关闭浏览器, 或者只有第一个启动的会话可以。此行为可能会在本规范的未来版本中 完全指定。

  3. 对于活动会话中的每个 active session

    1. 结束 会话 active session

    2. 使用 active session 清理会话

  4. 返回带有数据 null 的成功,并并行运行以下步骤。

    1. 等到发送 WebSocket 消息步骤已使用 对此命令的 响应被调用。

    2. 使用 session 清理会话

    3. 在不提示卸载的情况下关闭任何顶级 traversable

    4. 执行实现定义的步骤,以清理与自动化控制下的远端关联的资源。

      注:例如,这可能包括 干净地关闭与自动化控制下的浏览器关联的任何 OS 级 进程、移除临时 状态(例如远端在自动化控制期间创建的用户配置文件数据), 或关闭WebSocket 监听器。由于 浏览器和操作系统之间存在差异,无法在这里详细 指定本地端可依赖的精确不变式。

7.2.4.2. browser.createUserContext 命令

browser.createUserContext 命令创建一个 用户上下文

命令类型
browser.CreateUserContext = (
  method: "browser.createUserContext",
  params: browser.CreateUserContextParameters,
)

browser.CreateUserContextParameters = {
  ? acceptInsecureCerts: bool,
  ? proxy: session.ProxyConfiguration,
  ? unhandledPromptBehavior: session.UserPromptHandler
}
返回类型
browser.CreateUserContextResult = browser.UserContextInfo

给定 sessioncommand parameters 时,远端步骤为:

  1. user context 为一个新的用户上下文

  2. 如果 command parameters 包含 "acceptInsecureCerts":

    注:如果设置了 "acceptInsecureCerts", 它会覆盖 接受不安全 TLS 标志的行为。

    1. acceptInsecureCertscommand parameters["acceptInsecureCerts"]:

    2. 如果 acceptInsecureCerts 为 true,且端点节点不支持 接受不安全 TLS 连接,则返回带有 错误代码 unsupported operation错误

    3. session用户上下文到接受不安全证书覆盖映射[user context] 设置acceptInsecureCerts

  3. 如果 command parameters 包含 "unhandledPromptBehavior", 则将未处理提示行为覆盖 映射[user context] 设置command parameters["unhandledPromptBehavior"]。

  4. 如果 command parameters 包含 "proxy":

    1. proxy configurationcommand parameters["proxy"]。

    2. 如果远端无法按用户 上下文配置代理设置, 或无法用 proxy configuration 配置代理,则返回带有 错误代码 unsupported operation错误

    3. session用户上下文到代理 配置映射[user context] 设置proxy configuration

  5. user context 追加用户上下文集合

  6. user context info 为一个映射, 它与 browser.UserContextInfo 产生式匹配,其 userContext 字段设置为 user context用户上下文 id

  7. 返回带有数据 user context info成功

7.2.4.3. browser.getClientWindows 命令

browser.getClientWindows 命令返回 客户端窗口列表。

命令类型
browser.GetClientWindows = (
  method: "browser.getClientWindows",
  params: EmptyParams,
)
返回类型
browser.GetClientWindowsResult = {
  clientWindows: [ * browser.ClientWindowInfo]
}

远端步骤为:

  1. client window ids 为空集合

  2. client windows 为空列表

  3. 对于每个顶级 traversable traversable

    1. client windowtraversable 的关联客户端 窗口

    2. client window idclient window客户端窗口 id

    3. 如果 client window ids 包含 client window id,则继续。

    4. client window id 追加client window ids

    5. client window info 为使用 client window 调用获取 客户端窗口信息的结果。

    6. client window info 追加client windows

  4. result 为一个映射, 它与 browser.GetClientWindowsResult 产生式匹配,其 clientWindows 字段设置为 client windows

  5. 返回带有数据 result成功

7.2.4.4. browser.getUserContexts 命令

browser.getUserContexts 命令返回 用户上下文列表。

命令类型
browser.GetUserContexts = (
  method: "browser.getUserContexts",
  params: EmptyParams,
)
返回类型
browser.GetUserContextsResult = {
  userContexts: [ + browser.UserContextInfo]
}

远端步骤为:

  1. user contexts 为空列表

  2. 对于用户上下文集合中的每个 user context

    1. user context info 为一个映射, 它与 browser.UserContextInfo 产生式匹配,其 userContext 字段设置为 user context用户 上下文 id

    2. user context info 追加user contexts

  3. result 为一个映射, 它与 browser.GetUserContextsResult 产生式匹配,其 userContexts 字段设置为 user contexts

  4. 返回带有数据 result成功

7.2.4.5. browser.removeUserContext 命令

browser.removeUserContext 命令关闭一个 用户上下文及其中的所有 navigable,且不运行 beforeunload 处理程序。

命令类型
browser.RemoveUserContext = (
  method: "browser.removeUserContext",
  params: browser.RemoveUserContextParameters
)

browser.RemoveUserContextParameters = {
  userContext: browser.UserContext
}
返回类型
browser.RemoveUserContextResult = EmptyResult

给定 command parameters 时,远端步骤为:

  1. user context idcommand parameters["userContext"]。

  2. 如果 user context id"default",则返回带有错误代码 invalid argument错误

  3. user context 设置为用 user context id 调用获取用户上下文的结果。

  4. 如果 user context 为 null,则返回带有错误代码 no such user context错误

  5. 对于每个顶级 traversable navigable

    1. 如果 navigable关联用户上下文user context

      1. 在不提示卸载的情况下关闭 navigable

  6. 用户上下文集合移除 user context

  7. 返回带有数据 null 的成功

7.2.4.6. browser.setClientWindowState 命令

browser.setClientWindowState 命令设置 客户端 窗口的尺寸。

命令类型
browser.SetClientWindowState = (
  method: "browser.setClientWindowState",
  params: browser.SetClientWindowStateParameters
)

browser.SetClientWindowStateParameters = {
  clientWindow: browser.ClientWindow,
  (browser.ClientWindowNamedState // browser.ClientWindowRectState)
}

browser.ClientWindowNamedState = (
  state: "fullscreen" / "maximized" / "minimized"
)

browser.ClientWindowRectState = (
  state: "normal",
  ? width: js-uint,
  ? height: js-uint,
  ? x: js-int,
  ? y: js-int,
)
返回类型
browser.SetClientWindowStateResult = browser.ClientWindowInfo

给定 sessioncommand parameters 时,远端步骤为:

  1. 如果实现完全不支持设置客户端窗口状态, 则返回带有错误 代码 unsupported operation错误

  2. 如果存在一个客户端 窗口,其客户端窗口 idcommand parameters["clientWindow"],则令 client window 为该客户端窗口。 否则返回带有错误 代码 no such client window错误

  3. 尝试使用 client windowcommand parameters["state"] 设置客户端窗口状态

  4. 如果 command parameters["state"] 是 "normal":

    1. 如果 command parameters 包含 "x",并且 实现支持定位客户端窗口,则将 client windowx 坐标设置为尽可能接近 command parameters["x"] 的值。

    2. 如果 command parameters 包含 "y",并且 实现支持定位客户端窗口,则将 client windowy 坐标设置为尽可能接近 command parameters["y"] 的值。

    3. 如果 command parameters 包含 "width",并且 实现支持调整客户端窗口大小,则将 client window宽度设置为尽可能接近 command parameters["width"] 的值。

    4. 如果 command parameters 包含 "width",并且 实现支持调整客户端窗口大小,则将 client window宽度设置为尽可能接近 command parameters["width"] 的值。

  5. client window info 为使用 client window 调用获取客户端窗口信息的结果。

  6. 返回带有数据 client window info成功

注:为简单起见,这里将所有客户端窗口 操作都建模为 同步。因此,返回的客户端窗口尺寸预期是 窗口达到其新状态之后的尺寸。

7.2.4.7. browser.setDownloadBehavior 命令

下载行为 结构体是一个具有以下内容的结构体

远端具有一个下载行为,它是一个结构体,具有一个 名为 default download behavior,它是一个 下载 行为结构体或 null,以及一个名为 user context download behavior,它是 用户上下文下载 行为结构体之间的弱映射。

命令类型
browser.SetDownloadBehavior = (
  method: "browser.setDownloadBehavior",
  params: browser.SetDownloadBehaviorParameters
)

browser.SetDownloadBehaviorParameters = {
  downloadBehavior: browser.DownloadBehavior / null,
  ? userContexts: [+browser.UserContext]
}

browser.DownloadBehavior = {
  (
    browser.DownloadBehaviorAllowed //
    browser.DownloadBehaviorDenied
  )
}

browser.DownloadBehaviorAllowed = (
  type: "allowed",
  destinationFolder: text
)

browser.DownloadBehaviorDenied = (
  type: "denied"
)
返回类型
browser.SetDownloadBehaviorResult = EmptyResult
要在给定 navigable 的情况下获取下载 行为
  1. user contextnavigable关联用户 上下文

  2. 如果下载 行为user context download behavior 包含 user context,则返回下载行为user context download behavior[user context]。

  3. 返回下载 行为default download behavior

给定 sessioncommand parameters 时,远端步骤为:

  1. 如果 command parameters["downloadBehavior"] 为 null,则令 download behavior 为 null。

  2. 否则:

    1. 如果 command parameters["downloadBehavior"]["type"] 是 "allowed",则令 allowed 为 true,否则令 allowed 为 false。

    2. 如果 command parameters["downloadBehavior"] 包含 "destinationFolder",则令 destinationFoldercommand parameters["downloadBehavior"]["destinationFolder"], 否则令 destinationFolder 为 null。

    3. download behavior 为一个下载 行为结构体,其 allowed 设置为 allowed, 且 destinationFolder 设置 为 destinationFolder

  3. 如果实现不支持所需的 download behavior,则返回 带有错误 代码 unsupported operation错误

  4. 如果 command parametersuserContexts 字段存在:

    1. user contexts尝试command parameters["userContexts"] 获取有效用户上下文 所得的结果。

    2. 对于 user contexts 中的每个 user context

      1. 如果 download behavior 为 null,则从下载行为user context download behavior移除 user context

      2. 否则,将下载 行为user context download behavior[user context] 设置download behavior

  5. 否则,将下载行为default download behavior设置为 download behavior

  6. 返回带有数据 null 的成功

7.3. browsingContext 模块

browsingContext 模块包含与navigable相关的命令和 事件。

注:由于历史原因,此模块称为 browsingContext 而不是 navigable,并且协议使用术语 context 来指代 navigable,尤其是作为命令 和响应参数中的字段时。

导航进度使用一个不可变结构体 WebDriver BiDi 导航状态来传达,它具有以下

id
该导航的导航 id,或者当导航在取得进展前被 取消时为 null。
status
一个状态码,其值为 "canceled"、 "pending" 或 "complete"。
url
导航中正在加载的 URL
suggestedFilename
如果导航是下载,则为建议的文件名,否则为 null。
downloadedFilepath
如果导航是已完成的下载,且下载文件可用,则为已下载文件的 绝对文件路径,否则为 null。

7.3.1. 定义

远端定义

BrowsingContextCommand = (
  browsingContext.Activate //
  browsingContext.CaptureScreenshot //
  browsingContext.Close //
  browsingContext.Create //
  browsingContext.GetTree //
  browsingContext.HandleUserPrompt //
  browsingContext.LocateNodes //
  browsingContext.Navigate //
  browsingContext.Print //
  browsingContext.Reload //
  browsingContext.SetBypassCSP //
  browsingContext.SetViewport //
  browsingContext.TraverseHistory
)

本地端定义

BrowsingContextResult = (
  browsingContext.ActivateResult /
  browsingContext.CaptureScreenshotResult /
  browsingContext.CloseResult /
  browsingContext.CreateResult /
  browsingContext.GetTreeResult /
  browsingContext.HandleUserPromptResult /
  browsingContext.LocateNodesResult /
  browsingContext.NavigateResult /
  browsingContext.PrintResult /
  browsingContext.ReloadResult /
  browsingContext.SetBypassCSPResult /
  browsingContext.SetViewportResult /
  browsingContext.TraverseHistoryResult
)

BrowsingContextEvent = (
  browsingContext.ContextCreated //
  browsingContext.ContextDestroyed //
  browsingContext.DomContentLoaded //
  browsingContext.DownloadEnd //
  browsingContext.DownloadWillBegin //
  browsingContext.FragmentNavigated //
  browsingContext.HistoryUpdated //
  browsingContext.Load //
  browsingContext.NavigationAborted //
  browsingContext.NavigationCommitted //
  browsingContext.NavigationFailed //
  browsingContext.NavigationStarted //
  browsingContext.UserPromptClosed //
  browsingContext.UserPromptOpened
)

远端具有device pixel ratio 覆盖,它是 navigable与 device pixel ratio 覆盖之间的弱映射。其初始为空。

注:此映射不会在最终会话 结束时清除;即 device pixel ratio 覆盖会比任何 WebDriver 会话存活更久。

viewport 尺寸是一个具有以下内容的结构体

viewport 配置是一个具有以下内容的结构体

未处理 提示行为结构体是一个具有以下内容的结构体

远端具有viewport 覆盖映射,它是用户上下文viewport 配置之间的弱映射。

远端具有locale 覆盖映射,它是 navigable用户上下文与字符串之间的弱映射。

screen settings 是一个 结构体,具有 一个名为 height,它是整数; 一个名为 width,它是整数; 一个名为 x,它是整数; 一个名为 y,它是整数。

远端具有screen settings 覆盖,它是一个结构体,具有 一个名为 user context screen settings, 它是用户 上下文screen settings之间的弱映射, 以及一个名为 navigable screen settings, 它是navigablescreen settings之间的弱映射。

远端具有timezone 覆盖映射,它是 navigable用户上下文与字符串之间的弱映射。

远端具有一个未处理提示行为覆盖映射, 它是 用户上下文未处理提示行为结构体之间的 弱映射。

远端具有scripting enabled 覆盖映射,它是 navigable用户上下文与 boolean 之间的弱映射。

7.3.2. 类型

7.3.2.1. browsingContext.BrowsingContext 类型

远端定义本地端定义

browsingContext.BrowsingContext = text;

每个navigable都具有一个关联的navigable id, 它是唯一标识该 navigable 的字符串。它会在 navigable 创建时被隐式设置。对于具有关联 WebDriver 窗口句柄的 navigable,navigable id 必须与 窗口句柄相同。

每个navigable还具有一个关联存储分区, 它是其用于持久化数据的存储 分区

每个navigable还具有一个关联的original opener, 它是导致该 navigable 打开的navigable 或 null,初始设置为 null。

要在给定 navigable id 的情况下获取 navigable
  1. 如果 navigable id 为 null,则返回带有数据 null 的成功

  2. 如果不存在navigable idnavigable id 的 navigable,则返回 带有错误 代码 no such frame错误

  3. navigable 为 id 为 navigable idnavigable

  4. 返回带有数据 navigable成功

7.3.2.2. browsingContext.Info 类型

本地端定义

browsingContext.InfoList = [*browsingContext.Info]

browsingContext.Info = {
  children: browsingContext.InfoList / null,
  clientWindow: browser.ClientWindow,
  context: browsingContext.BrowsingContext,
  originalOpener: browsingContext.BrowsingContext / null,
  url: text,
  userContext: browser.UserContext,
  ? parent: browsingContext.BrowsingContext / null,
}

browsingContext.Info 类型表示 navigable 的属性。

要在给定 navigable 的情况下获取子 navigable

TODO:使其按文档顺序返回列表

  1. child navigables 为一个集合, 包含所有作为 navigable子 navigable的 navigable。

  2. 返回 child navigables

要在给定 navigablemax depthinclude parent id 的情况下获取 navigable 信息
  1. navigable idnavigablenavigable id

  2. parent navigablenavigable父级

  3. 如果 parent navigable 非 null,则令 parent idparent navigablenavigable id。否则令 parent id 为 null。

  4. documentnavigable活动文档

  5. url 为在给定 documentURL的情况下运行 URL 序列化器所得的结果。

    注:这包括 URL 的片段组成部分。

  6. child infos 为 null。

  7. 如果 max depth 为 null,或 max depth 大于 0:

    1. child navigables 为给定 navigable 时调用获取子 navigable的结果。

    2. 如果 max depth 非 null,则令 child depthmax depth - 1, 否则为 null。

    3. child infos 设置为空列表

    4. 对于 child navigables 中的每个 child navigable

      1. info 为给定 child navigablechild depth 和 false 时调用获取 navigable 信息的结果。

      2. info 追加到 child infos

  8. user contextnavigable关联用户 上下文

  9. 如果 navigableoriginal opener 非 null, 则令 opener idnavigableoriginal openernavigable id, 否则为 null。

  10. top-level traversablenavigable顶级 traversable

  11. client window idtop-level traversable 的关联客户端窗口客户端窗口 id

  12. navigable info 为一个映射, 它与 browsingContext.Info 产生式匹配,其中 context 字段设置为 navigable id;如果 include parent idtrue,则 parent 字段设置为 parent id,否则不设置; url 字段设置为 urluserContext 字段设置 为 user context用户上下文 idoriginalOpener 字段 设置为 opener idchildren 字段设置为 child infos;且 clientWindow 字段设置为 client window id

  13. 返回 navigable info

要在给定 navigablerequestwait condition, 以及可选的 history handling(默认值:"default")和 ignore cache(默认值:false)的情况下 等待导航
  1. navigation id 为一个基于真正随机数或 伪随机数的 UUID 的字符串表示。

  2. 用资源 request 导航 navigable, 并使用 navigable活动文档作为来源 Document, 导航时使用 navigation id navigation id历史处理行为 history handling。如果 ignore cache 为 true, 则该导航不得从 HTTP 缓存加载资源。

    准确 指定 ignore cache 标志如何工作。这需要 考虑是否只有资源的首次加载会绕过缓存 (即这是否类似于最初清除缓存然后像 通常一样继续),或者不是由 HTML 解析器直接加载的资源 (例如由脚本或样式表发起的加载)是否也会绕过缓存。

  3. 令(event receivednavigation status)为在给定 «"navigation started", "navigation failed", "fragment navigated"» 和 navigation id 的情况下进行 await 的结果。

  4. 断言:navigation statusidnavigation id

  5. 如果 navigation statusstatus 是 "complete":

    1. body 为一个映射, 它与 browsingContext.NavigateResult 产生式匹配,其中 navigation 字段设置为 navigation id,且 url 字段设置为在给定 navigation statusurl时运行 URL 序列化器所得的结果。

    2. 返回带有数据 body成功

    注:如果导航仅导致片段 改变,就是这种情况。

  6. 如果 navigation statusstatus 是 "canceled", 则返回带有错误 代码 unknown error错误

    TODO:这是在这里处理错误的正确方式吗?

  7. 断言:navigation statusstatus 是 "pending",并且 navigation id 不是 null。

  8. 如果 wait condition 是 "committed",则令 event name 为 "committed"。

  9. 否则,如果 wait condition 是 "interactive",则令 event name 为 "domContentLoaded"。

  10. 否则,令 event name 为 "load"。

  11. 令(event receivedstatus)为在给定 «event name, "download started", "navigation aborted", "navigation failed"» 和 navigation id 的情况下进行 await 的结果。

  12. 如果 event received 是 "navigation failed", 则返回带有错误 代码 unknown error错误

    我们在这里用 错误暴露了足够多关于失败内容和原因的信息吗? 我们想要什么错误代码?本地端是否会解析实现定义的字符串 来弄清楚实际出了什么问题,从而造成问题?

  13. body 为一个映射, 它与 browsingContext.NavigateResult 产生式匹配,其中 navigation 字段设置为 status 的 id,且 url 字段设置为在给定 status 的 url 时运行 URL 序列化器所得的结果。

  14. 返回带有数据 body成功

7.3.2.3. browsingContext.Locator 类型

远端定义本地端定义

browsingContext.Locator = (
   browsingContext.AccessibilityLocator /
   browsingContext.CssLocator /
   browsingContext.ContextLocator /
   browsingContext.InnerTextLocator /
   browsingContext.XPathLocator
)

browsingContext.AccessibilityLocator = {
   type: "accessibility",
   value: {
    ? name: text,
    ? role: text,
   }
}

browsingContext.CssLocator = {
   type: "css",
   value: text
}

browsingContext.ContextLocator = {
  type: "context",
  value: {
    context: browsingContext.BrowsingContext,
  }
}

browsingContext.InnerTextLocator = {
   type: "innerText",
   value: text,
   ? ignoreCase: bool
   ? matchType: "full" / "partial",
   ? maxDepth: js-uint,
}

browsingContext.XPathLocator = {
   type: "xpath",
   value: text
}

browsingContext.Locator 类型提供关于在文档中 定位节点的策略的详细信息。

7.3.2.4. browsingContext.Navigation 类型

远端定义本地端定义

browsingContext.Navigation = text;

browsingContext.Navigation 类型是唯一标识正在进行的 导航的字符串。

TODO:链接到 HTML 规范中的定义。

7.3.2.5. browsingContext.NavigationInfo 类型

本地端定义

browsingContext.BaseNavigationInfo = (
  context: browsingContext.BrowsingContext,
  navigation: browsingContext.Navigation / null,
  timestamp: js-uint,
  url: text,
  ? userContext: browser.UserContext,
)

browsingContext.NavigationInfo = {
  browsingContext.BaseNavigationInfo
}

browsingContext.NavigationInfo 类型提供正在进行的导航的详细信息。

要在给定navigable navigable导航状态 navigation status 的情况下 获取 导航信息
  1. navigable idnavigablenavigable id

  2. navigation idnavigation statusid

  3. timestamp 为表示当前 UTC 日期和 时间的时间值

  4. urlnavigation statusurl

  5. user context idnavigable关联用户上下文用户上下文 id

  6. 返回一个与 browsingContext.NavigationInfo 产生式匹配的映射,其中 context 字段设置为 navigable idnavigation 字段设置为 navigation idtimestamp 字段设置为 timestampurl 字段设置为在给定 url 的情况下运行 URL 序列化器所得的结果,且 userContext 字段设置为 user context id

7.3.2.6. browsingContext.ReadinessState 类型
browsingContext.ReadinessState = "none" / "interactive" / "complete"

browsingContext.ReadinessState 类型表示导航命令将返回时 文档加载所处的阶段。

7.3.2.7. browsingContext.UserPromptType 类型

远端定义本地端定义

browsingContext.UserPromptType = "alert" / "beforeunload" / "confirm" / "prompt";

browsingContext.UserPromptType 类型表示可能的用户 提示类型。

7.3.3. 命令

7.3.3.1. browsingContext.activate 命令

browsingContext.activate 命令会激活并聚焦给定的 顶级 traversable

命令类型
browsingContext.Activate = (
  method: "browsingContext.activate",
  params: browsingContext.ActivateParameters
)

browsingContext.ActivateParameters = {
  context: browsingContext.BrowsingContext
}
返回类型
browsingContext.ActivateResult = EmptyResult

给定 command parameters 时,远端步骤为:

  1. navigable idcommand parameters["context"] 字段的值。

  2. navigable 为使用 navigable id 尝试获取 navigable的结果。

  3. 如果 navigable 不是顶级 traversable,则返回带有错误 代码 invalid argument错误

  4. 返回使用 navigable 调用激活 navigable的结果。

要在给定 navigable 的情况下激活 navigable
  1. 运行特定于实现的步骤,使 navigable系统可见性状态变为visible。如果这不可能,则返回带有错误代码 unsupported operation错误

    注:这可能会产生副作用,使当前 visiblenavigable变为hidden

    注:这可能会通过导致窗口取消最小化, 或通过与改变系统可见性状态相关的其他副作用,来改变底层 OS 状态。

  2. 运行特定于实现的步骤,在 navigable 未聚焦时将系统焦点设置到 navigable 上。

    注:除非其他规范强制要求,否则这不会改变文档的聚焦区域

  3. 返回带有数据 null 的成功

7.3.3.2. browsingContext.captureScreenshot 命令

browsingContext.captureScreenshot 命令 捕获给定 navigable 的图像,并以 Base64 编码字符串形式返回。

命令类型
browsingContext.CaptureScreenshot = (
  method: "browsingContext.captureScreenshot",
  params: browsingContext.CaptureScreenshotParameters
)

browsingContext.CaptureScreenshotParameters = {
  context: browsingContext.BrowsingContext,
  ? origin: ("viewport" / "document") .default "viewport",
  ? format: browsingContext.ImageFormat,
  ? clip: browsingContext.ClipRectangle,
}

browsingContext.ImageFormat = {
   type: text,
   ? quality: 0.0..1.0,
}

browsingContext.ClipRectangle = (
  browsingContext.BoxClipRectangle /
  browsingContext.ElementClipRectangle
)

browsingContext.ElementClipRectangle = {
  type: "element",
  element: script.SharedReference
}

browsingContext.BoxClipRectangle = {
   type: "box",
   x: float,
   y: float,
   width: float,
   height: float
}
返回类型
browsingContext.CaptureScreenshotResult = {
  data: text
}
要在给定 rect 的情况下规范化矩形

注:这确保所得矩形具有 正的宽度尺寸高度尺寸

  1. xrectx 坐标

  2. yrecty 坐标

  3. widthrect宽度尺寸

  4. heightrect高度尺寸

  5. 如果 width 小于 0,则将 x 设置为 x + width,然后 将 width 设置为 -width

  6. 如果 height 小于 0,则将 y 设置为 y + height,然后 将 height 设置为 -height

  7. 返回一个新的 DOMRectReadOnly, 其x 坐标xy 坐标y宽度尺寸width,且高度尺寸height

要在给定 rect1rect2 的情况下求矩形 交集
  1. rect1 为用 rect1 调用规范化矩形的结果。

  2. rect2 为用 rect2 调用规范化矩形的结果。

  3. x1_0rect1x 坐标

  4. x2_0rect2x 坐标

  5. x1_1rect1x 坐标加上 rect1宽度尺寸

  6. x2_1rect2x 坐标加上 rect2宽度尺寸

  7. x_0 为 «x1_0, x2_0» 的最大元素。

  8. x_1 为 «x1_1, x2_1» 的最小元素。

  9. y1_0rect1y 坐标

  10. y2_0rect2y 坐标

  11. y1_1rect1y 坐标加上 rect1高度尺寸

  12. y2_1rect2y 坐标加上 rect2高度尺寸

  13. y_0 为 «y1_0, y2_0» 的最大元素。

  14. y_1 为 «y1_1, y2_1» 的最小元素。

  15. 如果 x_1 小于 x_0,则令 width 为 0。否则令 widthx_1 - x_0

  16. 如果 y_1 小于 y_0,则令 height 为 0。否则令 heighty_1 - y_0

  17. 返回一个新的 DOMRectReadOnly, 其x 坐标x_0y 坐标y_0宽度尺寸width,且高度尺寸height

要在给定 documentrect 的情况下将 document 渲染到 canvas
  1. ratio 为在给定 document默认视图的情况下确定 device pixel ratio所得的结果。

  2. paint widthrect宽度尺寸乘以 ratio, 四舍五入到最接近的整数,使其与 rect 在设备像素中的宽度 相匹配。

  3. paint heightrect高度尺寸乘以 ratio, 四舍五入到最接近的整数,使其与 rect 在设备像素中的高度 相匹配。

  4. canvas 为新的 HTMLCanvasElement, 其 widthpaint widthheightpaint height

  5. canvas context 为用 canvas 和 null 运行 2D 上下文创建算法 所得的结果。

  6. canvas上下文模式设置为2D

  7. 完成特定于实现的步骤,其等价于将 framebuffer 中表示 documentrect 覆盖区域的区域绘制到 canvas context,使 framebuffer 中的每个像素对应于 canvas context 中的一个像素,其中视口坐标中的(rectx 坐标recty 坐标)对应于 canvas context 中的 (0,0),而(rectx 坐标 + rect宽度尺寸recty 坐标 + rect高度尺寸)对应于(paint widthpaint height)。

  8. 返回 canvas

要在给定 canvasformat 的情况下将 canvas 编码为 Base64
  1. 如果 format 不是 null,则令 typeformattype 字段,且令 qualityformatquality 字段。

  2. 否则,令 type 为 "image/png",并令 qualityundefined

  3. filecanvas 在给定 typequality 的情况下的位图作为文件的序列化

  4. encoded stringfileforgiving-base64 编码

  5. 返回带有数据 encoded string 的成功。

要在给定 documentorigin 的情况下获取 origin 矩形
  1. 如果 origin"viewport"

    1. viewportdocument视觉视口

    2. viewport rect 为一个 DOMRectReadOnly, 其x 坐标viewportpage lefty 坐标viewportpage top宽度尺寸viewport width,且高度尺寸viewport height。

    3. 返回带有数据 viewport rect成功

  2. 断言:origin"document"

  3. document elementdocumentdocument element

  4. document rect 为一个 DOMRectReadOnly, 其x 坐标为 0,y 坐标为 0,宽度尺寸document elementscroll height, 且高度尺寸document elementscroll width

  5. 返回带有数据 document rect成功

给定 sessioncommand parameters 时,远端步骤为:

  1. navigable idcommand parameterscontext 字段的值, 如果存在的话;否则为 null。

  2. navigable 为使用 navigable id 尝试获取 navigable 所得的结果。

  3. 如果实现因任何原因无法捕获 navigable 的屏幕截图, 则返回带有错误 代码 unsupported operation错误

  4. documentnavigable活动文档

  5. 在下次为 document 调用运行动画帧回调算法之后立即:

    这应当 以某种更明确的方式集成到更新渲染算法中。

  6. origincommand parameterscontext 字段的值,如果存在的话;否则为 "viewport"。

  7. origin rect 为在给定 origindocument 的情况下 尝试获取 origin 矩形 所得的结果。

  8. clip rectorigin rect

  9. 如果 command parameters 包含 "clip":

    1. clipcommand parameters["clip"]。

    2. 运行第一个匹配条件下的步骤:

      clipbrowsingContext.ElementClipRectangle 产生式匹配:
      1. environment settings环境设置对象, 其 相关全局对象关联 Documentdocument

      2. realmenvironment settingsrealm 执行上下文的 Realm 组件。

      3. element 为用 clip["element"]、realmsession 尝试反序列化远程 引用所得的结果。

      4. 如果 element 没有实现 Element, 则返回带有错误代码 no such element错误

      5. 如果 element节点文档不是 document,则返回带有 错误代码 no such element错误

      6. viewport rect 为在给定 "viewport" 和 document 的情况下调用获取 origin 矩形的结果。

      7. element rect 为针对 element 获取边界框所得的结果。

      8. clip rect 为一个 DOMRectReadOnly, 其x 坐标element rect["x"] + viewport rect["x"], y 坐标element rect["y"] + viewport rect["y"],width 为 element rect["width"], 且 height 为 element rect["height"]。

      clipbrowsingContext.BoxClipRectangle 产生式匹配:
      1. clip xclip["x"] 加上 origin rectx 坐标

      2. clip yclip["y"] 加上 origin recty 坐标

      3. clip rect 为一个 DOMRectReadOnly, 其x 坐标clip xy 坐标clip y,width 为 clip["width"],且 height 为 clip["height"]。

  10. 注:所有坐标现在都从文档的 origin 开始测量。

  11. rectorigin rectclip rect矩形交集

  12. 如果 rect宽度尺寸为 0,或 rect高度尺寸为 0, 则返回带有错误代码 unable to capture screen错误

  13. canvas 为用 documentrect 将 document 渲染到 canvas所得的结果。

  14. formatcommand parametersformat 字段。

  15. encoding result 为用 canvasformat 尝试将 canvas 编码为 Base64所得的结果。

  16. body 为一个与 browsingContext.CaptureScreenshotResult 产生式匹配的映射,其中 data 字段设置为 encoding result

  17. 返回带有数据 body成功

7.3.3.3. browsingContext.close 命令

browsingContext.close 命令会关闭一个 顶级 traversable

命令类型
browsingContext.Close = (
  method: "browsingContext.close",
  params: browsingContext.CloseParameters
)

browsingContext.CloseParameters = {
  context: browsingContext.BrowsingContext,
  ? promptUnload: bool .default false
}
返回类型
browsingContext.CloseResult = EmptyResult
给定 command parameters 时,远端步骤为:
  1. navigable idcommand parameterscontext 字段的值。

  2. prompt unloadcommand parameterspromptUnload 字段的值。

  3. navigable 为用 navigable id 尝试获取 navigable 所得的结果。

  4. 断言:navigable 不是 null。

  5. 如果 navigable 不是顶级 traversable,则返回带有 错误代码 invalid argument错误

  6. 如果 prompt unload 为 true:

    1. 关闭 navigable

  7. 否则:

    1. 在不提示卸载的情况下关闭 navigable

  8. 返回带有数据 null 的成功

关于关闭最后一个 顶级 traversable时的行为,目前有一个开放的 讨论。我们可以预期关闭浏览器、关闭会话,或将其留给实现决定。[w3c/webdriver-bidi Issue #170]

7.3.3.4. browsingContext.create 命令

browsingContext.create 命令会创建一个新的 navigable,位于新标签页或新窗口中,并返回其 navigable id

命令类型
browsingContext.Create = (
  method: "browsingContext.create",
  params: browsingContext.CreateParameters
)

browsingContext.CreateType = "tab" / "window"

browsingContext.CreateParameters = {
  type: browsingContext.CreateType,
  ? referenceContext: browsingContext.BrowsingContext,
  ? background: bool .default false,
  ? userContext: browser.UserContext
}
返回类型
browsingContext.CreateResult = {
  context: browsingContext.BrowsingContext,
  ? userContext: browser.UserContext
}
给定 command parameters 时,远端步骤为:
  1. typecommand parameterstype 字段的值。

  2. reference navigable idcommand parametersreferenceContext 字段的值,如果存在的话;否则为 null。

  3. 如果 reference navigable id 不是 null,则令 reference navigable 为 用 reference navigable id 尝试获取 navigable所得的结果。否则令 reference navigable 为 null。

  4. 如果 reference navigable 不是 null 且不是顶级 traversable, 则返回带有错误 代码 invalid argument错误

  5. 如果实现因任何原因无法创建新的顶级 traversable,则返回带有错误 代码 unsupported operation错误

  6. 如果 reference navigable 为 null,则令 user context默认用户上下文,否则为 reference navigable关联用户 上下文

  7. user context idcommand parametersuserContext 字段的值, 如果存在的话;否则为 null。

  8. 如果 user context id 不是 null,则将 user context 设置为用 user context id 尝试获取用户上下文所得的结果。

  9. 如果 user context 为 null,则返回带有错误代码 no such user context错误

  10. 如果实现因任何原因无法用关联用户上下文 user context 创建新的顶级 traversable,则返回 带有错误 代码 unsupported operation错误

  11. traversable 为尝试用 null 和空字符串执行创建新的顶级 traversable 步骤,并将新创建顶级 traversable关联用户上下文设置为 user context 所得的结果。 新的顶级 traversable创建在哪个 OS 窗口中取决于 typereference navigable

  12. 如果 command parametersbackground 字段的值为 false:

    1. activate result 为用新创建的navigable 调用激活 navigable所得的结果。

    2. 如果 activate result 是一个错误, 则返回 activate result

    注:如果 background 为 true,不要为创建的 navigable 调用聚焦步骤

  13. body 为一个与 browsingContext.CreateResult 产生式匹配的映射, 其中 context 字段设置为 traversablenavigable id,且 userContext 属性设置为 traversable关联用户上下文用户 上下文 id

  14. 返回带有数据 body成功

7.3.3.5. browsingContext.getTree 命令

browsingContext.getTree 命令返回一个 包含给定父级本身在内的所有后代 navigable 的树, 或在未提供父级时返回所有顶级 context。

命令类型
browsingContext.GetTree = (
  method: "browsingContext.getTree",
  params: browsingContext.GetTreeParameters
)

browsingContext.GetTreeParameters = {
  ? maxDepth: js-uint,
  ? root: browsingContext.BrowsingContext,
}
返回类型
browsingContext.GetTreeResult = {
  contexts: browsingContext.InfoList
}
给定 sessioncommand parameters 时,远端步骤为:
  1. root idcommand parametersroot 字段的值, 如果存在的话;否则为 null。

  2. max depthcommand parametersmaxDepth 字段的值,如果存在的话;否则为 null。

  3. navigables 为空列表

  4. 如果 root id 不是 null,则将给定 root id尝试获取 navigable所得的结果追加到 navigables。 否则将所有顶级 traversable追加到 navigables

  5. navigables infos 为空列表

  6. 对于 navigables 中的每个 navigable

    1. info 为给定 navigablemax depth 和 true 时调用获取 navigable 信息所得的结果。

    2. info 追加到 navigables infos

  7. body 为一个与 browsingContext.GetTreeResult 产生式匹配的映射, 其中 contexts 字段设置为 navigables infos

  8. 返回带有数据 body成功

7.3.3.6. browsingContext.handleUserPrompt 命令

browsingContext.handleUserPrompt 命令允许关闭打开的提示

命令类型
browsingContext.HandleUserPrompt = (
  method: "browsingContext.handleUserPrompt",
  params: browsingContext.HandleUserPromptParameters
)

browsingContext.HandleUserPromptParameters = {
  context: browsingContext.BrowsingContext,
  ? accept: bool,
  ? userText: text,
}
返回类型
browsingContext.HandleUserPromptResult = EmptyResult

给定 sessioncommand parameters 时,远端步骤为:

  1. navigable idcommand parameterscontext 字段的值。

  2. navigable 为用 navigable id 尝试获取 navigable 所得的结果。

  3. acceptcommand parametersaccept 字段的值,如果存在的话;否则为 true。

  4. userTextcommand parametersuserText 字段的值,如果存在的话;否则为空字符串。

  5. 如果 navigable 当前显示的是由调用 alert 产生的简单对话框,则 确认该提示。

    否则,如果 navigable 当前显示的是由调用 confirm 产生的简单对话框,则当 accept 为 true 时肯定响应, 或当 accept 为 false 时 否定响应。

    否则,如果 navigable 当前显示的是由调用 prompt 产生的简单对话框,则当 accept 为 true 时用字符串值 userText 响应,或当 accept 为 false 时中止。

    否则,如果 navigable 当前显示的是作为提示卸载步骤的一部分的提示,则当 accept 为 true 时确认该 导航,否则 拒绝该导航。

    否则,返回带有错误 代码 no such alert错误

  6. 返回带有数据 null 的成功

7.3.3.7. browsingContext.locateNodes 命令

browsingContext.locateNodes 命令返回 与指定定位器匹配的所有节点列表。

命令类型
browsingContext.LocateNodes = (
  method: "browsingContext.locateNodes",
  params: browsingContext.LocateNodesParameters
)

browsingContext.LocateNodesParameters = {
   context: browsingContext.BrowsingContext,
   locator: browsingContext.Locator,
   ? maxNodeCount: (js-uint .ge 1),
   ? serializationOptions: script.SerializationOptions,
   ? startNodes: [ + script.SharedReference ]
}
返回类型
browsingContext.LocateNodesResult = {
    nodes: [ * script.NodeRemoteValue ]
}
要在给定 navigablecontext nodesselectormaximum returned node countsession 的情况下使用 CSS 定位节点
  1. returned nodes 为空列表

  2. parse result 为给定 selector解析选择器所得的结果。

  3. 如果 parse result 为 failure,则返回带有错误代码 invalid selector错误

  4. 对于 context nodes 中的每个 context node

    1. elements 为用 parse resultnavigable活动文档,并使用 作用域根 context node针对树匹配选择器所得的结果。

    2. 对于 elements 中的每个 element

      1. element 追加returned nodes

      2. 如果 maximum returned node count 不是 null,且 returned nodes大小等于 maximum returned node count, 则返回带有数据 returned nodes成功

  5. 返回带有数据 returned nodes成功

要在给定 navigable 的情况下定位容器 元素
  1. returned nodes 为空列表

  2. 如果 navigable容器不是 null, 则将 navigable容器追加到 returned nodes

  3. 返回 returned nodes

要在给定 navigablecontext nodesselectormaximum returned node count 的情况下使用 XPath 定位节点

注:由于 XPath 规范处于无人维护状态,本算法被表述为像是在调用 XPath DOM API。 然而,应将其理解为等价于直接访问底层算法的规范内部调用, 而不经过 ECMAScript 运行时。

  1. returned nodes 为空列表

  2. 对于 context nodes 中的每个 context node

    1. evaluate result 为在 navigable活动文档上调用 evaluate,并以 selectorcontext node、null、 ORDERED_NODE_SNAPSHOT_TYPE 和 null 作为实参所得的结果。如果这抛出一个 "SyntaxError" DOMException,则返回带有 错误代码 invalid selector错误; 否则,如果这抛出任何其他异常,则返回带有 错误代码 unknown error错误

    2. index 为 0。

    3. length 为从 evaluate result 获取 snapshotLength 属性所得的结果。

    4. index 小于 length 时,重复:

      1. node 为以 evaluate result 作为 this、以 index 作为实参调用 snapshotItem所得的结果。

      2. node 追加returned nodes

      3. 如果 maximum returned node count 不是 null,且 returned nodes大小等于 maximum returned node count, 则返回带有数据 returned nodes成功

      4. index 设置为 index + 1。

  3. 返回带有数据 returned nodes成功

要在给定 context nodesselectormax depthmatch typeignore casemaximum returned node count 的情况下使用 inner text 定位节点
  1. 如果 selector 是空字符串,则返回带有错误代码 invalid selector错误

  2. returned nodes 为空列表

  3. 如果 ignore case 为 false,则令 search textselector。否则, 令 search text 为按 Unicode 默认大小写转换算法selector 执行 toUppercase所得的结果。

  4. 对于 context nodes 中的每个 context node

    1. 如果 context node 实现了 DocumentDocumentFragment

      注:遍历 document 或 document fragment 时,max depth 有意不减少,以使使用 documentdocument.documentElement 的搜索结果等价。

      1. child nodes 为空列表

      2. 对于 context node子节点中的每个节点 child

        1. child 追加child nodes

      3. 用在给定 child nodesselectormax depthmatch typeignore casemaximum returned node count 的情况下尝试使用 inner text 定位节点 所得的结果扩展 returned nodes

    2. 如果 context node 没有实现 HTMLElement, 则继续

    3. node inner text 为以 context node 作为 this 值调用 innerText getter 步骤所得的结果。

    4. 如果 ignore case 为 false,则令 node textnode inner text。否则, 令 node text 为按 Unicode 默认大小写转换算法node inner text 执行 toUppercase所得的结果。

    5. 如果 search textnode text码点子字符串, 则执行以下步骤:

      1. child nodes 为空列表,并且 对于 context node子节点中的每个节点 child

        1. child 追加child nodes

      2. 如果 child nodes大小等于 0,或 max depth 等于 0, 则执行以下步骤:

        1. 如果 match type"full"node text search text, 则将 context node 追加returned nodes

        2. 否则,如果 match type"partial",则将 context node 追加returned nodes

      3. 否则,执行以下步骤:

        1. 如果 max depth 为 null,则令 child max depth 为 null, 否则为 max depth - 1。

        2. child node matches 为用 child nodesselectorchild max depthmatch typeignore casemaximum returned node count 调用使用 inner text 定位节点所得的结果。

        3. 如果 child node matches大小等于 0 且 match type"partial",则将 context node 追加到 returned nodes。否则,用 child node matches 扩展 returned nodes

  5. 如果 maximum returned node count 不是 null,则移除 returned nodes 中索引大于或等于 maximum returned node count 的所有条目。

  6. 返回带有数据 returned nodes成功

要在给定 context nodesselectormaximum returned node countreturned nodes 的情况下使用无障碍属性收集节点
  1. 如果 returned nodes 为 null:

    1. returned nodes 设置为空列表

  2. 对于 context nodes 中的每个 context node

    1. match 为 true。

    2. 如果 context node 实现了 Element

      1. 如果 selector 包含 "role":

        1. rolecontext node计算角色

        2. 如果 selector["role"] 不是 role

          1. match 设置为 false。

      2. 如果 selector 包含 "name":

        1. namecontext node可访问名称

        2. 如果 selector["name"] 不是 name

          1. match 设置为 false。

    3. 否则,将 match 设置为 false。

    4. 如果 match 为 true:

      1. 如果 maximum returned node count 不是 null,且 returned nodes大小等于 maximum returned node count, 则中断

      2. context node 追加returned nodes

    5. child nodes 为空列表,并且对于 context node子节点中的每个节点 child

      1. 如果 child 实现了 Element, 则将 child 追加child nodes

    6. 尝试child nodesselectormaximum returned node countreturned nodes 使用无障碍属性收集节点

  3. 返回 returned nodes

要在给定 context nodesselectormaximum returned node count 的情况下使用无障碍属性定位节点
  1. 如果 selector包含 "role",且 selector包含 "name",则返回 带有错误 代码 invalid selector错误

  2. 返回用 context nodesselectormaximum returned node count 和 null 调用使用无障碍属性收集节点所得的结果。

给定 sessioncommand parameters 时,远端步骤为:
  1. navigable idcommand parameters["context"]。

  2. navigable 为用 navigable id 尝试获取 navigable 所得的结果。

  3. 断言:navigable 不是 null。

  4. realm 为用 navigablenavigable id 和 null 尝试从 navigable 获取 realm 所得的结果。

  5. locatorcommand parameters["locator"]。

  6. 如果 command parameters 包含 "startNodes",则令 start nodes parametercommand parameters["startNodes"]。 否则令 start nodes parameter 为 null。

  7. 如果 command parameters 包含 "maxNodeCount",则令 maximum returned node countcommand parameters["maxNodeCount"]。 否则,令 maximum returned node count 为 null。

  8. context nodes 为空列表

  9. 如果 start nodes parameter 为 null,则将 navigable活动文档追加context nodes。否则,对于 start nodes parameter 中的每个 serialized start node

    1. start node 为给定 serialized start noderealmsession尝试反序列化共享引用所得的结果。

    2. start node 追加context nodes

  10. 断言 context nodes大小大于 0。

  11. typelocator["type"]。

  12. 在以下条件及其关联步骤列表中,运行第一个其关联条件为 true 的 步骤集合:

    type 是字符串 "css"
    1. selectorlocator["value"]。

    2. result nodes 为给定 navigablecontext nodesselectormaximum returned nodes尝试使用 css 定位节点所得的结果。

    type 是字符串 "xpath"
    1. selectorlocator["value"]。

    2. result nodes 为给定 navigablecontext nodesselectormaximum returned nodes尝试使用 xpath 定位节点所得的结果。

    type 是字符串 "innerText"
    1. selectorlocator["value"]。

    2. 如果 locator 包含 maxDepth,则令 max depthlocator["maxDepth"]。否则,令 max depth 为 null。

    3. 如果 locator 包含 ignoreCase,则令 ignore caselocator["ignoreCase"]。否则,令 ignore case 为 false。

    4. 如果 locator 包含 matchType,则令 match typelocator["matchType"]。否则,令 match type 为 "full"。

    5. result nodes 为给定 context nodesselectormax depthmatch typeignore casemaximum returned node count尝试使用 inner text 定位节点所得的结果。

    type 是字符串 "accessibility"
    1. selectorlocator["value"]。

    2. result nodes 为给定 context nodesselectormaximum returned node count使用无障碍属性定位节点所得的结果。

    type 是字符串 "context"
    1. 如果 start nodes parameter 不是 null, 则返回带有错误代码 "invalid argument" 的错误

    2. selectorlocator["value"]。

    3. context idselector["context"]。

    4. child navigable 为用 context id 尝试获取 navigable 所得的结果。

    5. 如果 child navigable父级不是 navigable, 则返回带有错误代码 "invalid argument" 的错误

    6. result nodes 为给定 child navigable定位容器元素所得的结果。

    7. 断言:对于 result nodes 中的每个 nodenode节点 navigablenavigable

  13. 断言:maximum returned node count 为 null,或 result nodes大小小于或等于 maximum returned node count

  14. 如果 command parameters 包含 "serializationOptions", 则令 serialization optionscommand parameters["serializationOptions"]。 否则,令 serialization options 为一个与 script.SerializationOptions 产生式匹配、且各字段 设置为其默认值的映射

  15. result ownership 为 "none"。

  16. serialized nodes 为空列表

  17. 对于 result nodes 中的每个 result node

    1. serialized node 为用 result nodeserialization optionsresult ownership、一个新的映射作为 serialization internal map、realmsession 序列化为远程值所得的结果。

    2. serialized node 追加serialized nodes

  18. result 为一个与 browsingContext.LocateNodesResult 产生式匹配的映射, 其 nodes 字段设置为 serialized nodes

  19. 返回带有数据 result成功

7.3.3.8. browsingContext.navigate 命令

browsingContext.navigate 命令将一个 navigable 导航到给定 URL。

命令类型
browsingContext.Navigate = (
  method: "browsingContext.navigate",
  params: browsingContext.NavigateParameters
)

browsingContext.NavigateParameters = {
  context: browsingContext.BrowsingContext,
  url: text,
  ? wait: browsingContext.ReadinessState,
}
返回类型
browsingContext.NavigateResult = {
  navigation: browsingContext.Navigation / null,
  url: text,
}
给定 sessioncommand parameters 时,远端步骤为:
  1. navigable idcommand parameterscontext 字段的值。

  2. navigable 为用 navigable id 尝试获取 navigable 所得的结果。

  3. 断言:navigable 不是 null。

  4. wait condition 为 "committed"。

  5. 如果 command parameters 包含 waitcommand parameters[wait] 不是 "none", 则将 wait condition 设置为 command parameters[wait]。

  6. urlcommand parametersurl 字段的值。

  7. documentnavigable活动文档

  8. basedocument基 URL

  9. url record 为以 基 URL baseURL 解析器应用于 url所得的结果。

  10. 如果 url record 为 failure,则返回带有错误代码 invalid argument错误

  11. request 为一个新的 request,其 URL 为 url record

  12. 返回用 navigablerequestwait condition 调用等待导航所得的结果。

7.3.3.9. browsingContext.print 命令

browsingContext.print 命令 创建文档的分页表示,并将其作为 表示为 Base64 编码字符串的 PDF 文档返回。

命令类型
browsingContext.Print = (
  method: "browsingContext.print",
  params: browsingContext.PrintParameters
)

browsingContext.PrintParameters = {
  context: browsingContext.BrowsingContext,
  ? background: bool .default false,
  ? margin: browsingContext.PrintMarginParameters,
  ? orientation: ("portrait" / "landscape") .default "portrait",
  ? page: browsingContext.PrintPageParameters,
  ? pageRanges: [*(js-uint / text)],
  ? scale: (0.1..2.0) .default 1.0,
  ? shrinkToFit: bool .default true,
}

browsingContext.PrintMarginParameters = {
  ? bottom: (float .ge 0.0) .default 1.0,
  ? left: (float .ge 0.0) .default 1.0,
  ? right: (float .ge 0.0) .default 1.0,
  ? top: (float .ge 0.0) .default 1.0,
}

; Minimum size is 1pt x 1pt. Conversion follows from
; https://www.w3.org/TR/css3-values/#absolute-lengths
browsingContext.PrintPageParameters = {
  ? height: (float .ge 0.0352) .default 27.94,
  ? width: (float .ge 0.0352) .default 21.59,
}
返回类型
browsingContext.PrintResult = {
  data: text
}

给定 sessioncommand parameters 时,远端步骤为:

  1. navigable idcommand parameterscontext 字段的值。

  2. navigable 为用 navigable id 尝试获取 navigable 所得的结果。

  3. 如果实现因任何原因无法提供 navigable 的分页表示, 则返回带有 错误代码 unsupported operation错误

  4. margincommand parametersmargin 字段的值(如果存在),否则为一个与 browsingContext.PrintMarginParameters 匹配且字段设置为 其默认值的映射

  5. page sizecommand parameterspage 字段的值(如果存在),否则为一个与 browsingContext.PrintPageParameters 匹配且字段设置为 其默认值的映射

注:最小页面尺寸为 1 点, 根据绝对长度,即 (2.54 / 72) cm。

  1. page rangescommand parameterspageRanges 字段的值, 如果存在的话;否则为空列表

  2. documentnavigable活动文档

  3. 在下次为 document 调用运行动画帧回调 算法之后立即:

    这应当 以某种更明确的方式集成到更新渲染算法中。

    1. pdf data 为采取 UA 特定步骤生成 document 的分页表示的结果,其中 CSS 媒体类型设置为 print,编码为 PDF,并使用以下纸张设置:

      属性
      宽度,单位为 cm 如果 command parameters["orientation"] 是 "portrait",则为 page size["width"], 否则为 page size["height"]
      高度,单位为 cm 如果 command parameters["orientation"] 是 "portrait",则为 page size["height"], 否则为 page size["width"]
      上边距,单位为 cm margin["top"]
      下边距,单位为 cm margin["bottom"]
      左边距,单位为 cm margin["left"]
      右边距,单位为 cm margin["right"]

      此外,UA 应应用以下格式化提示:

      如果 command parameters["scale"] 不等于 1
      按因子 command parameters["scale"] 缩放内容尺寸
      如果 command parameters["background"] 为 false:
      抑制背景图像的输出
      如果 command parameters["shrinkToFit"] 为 true:
      调整内容尺寸以匹配页面宽度,并覆盖内容中指定的任何页面 宽度
    2. 如果 page ranges 不是, 则令 pages 为用 page rangespdf data 中包含的页数尝试解析页面范围所得的结果, 然后从 pdf data 中移除其从一开始的索引未包含在 pages 中的任何页面。

    3. encoding result 为在 pdf data 上调用 Base64 Encode所得的结果。

    4. encoded dataencoding result 的 data。

    5. body 为一个与 browsingContext.PrintResult 产生式匹配的映射, 其 data 字段设置为 encoded data

    6. 返回带有数据 body成功

7.3.3.10. browsingContext.reload 命令

browsingContext.reload 命令重载一个 navigable。

命令类型
browsingContext.Reload = (
  method: "browsingContext.reload",
  params: browsingContext.ReloadParameters
)

browsingContext.ReloadParameters = {
  context: browsingContext.BrowsingContext,
  ? ignoreCache: bool,
  ? wait: browsingContext.ReadinessState,
}
返回类型
browsingContext.ReloadResult = browsingContext.NavigateResult
给定 command parameters 时,远端步骤为:
  1. navigable idcommand parameterscontext 字段的值。

  2. navigable 为用 navigable id 尝试获取 navigable 所得的结果。

  3. 断言:navigable 不是 null。

  4. ignore cachecommand parametersignoreCache 字段的值(如果存在),否则为 false。

  5. wait condition 为 "committed"。

  6. 如果 command parameters 包含 waitcommand parameters[wait] 不是 "none", 则将 wait condition 设置为 command parameters[wait]。

  7. documentnavigable活动文档

  8. urldocumentURL

  9. request 为一个新的 request,其 URL 为 url

  10. 返回用 navigablerequestwait condition、历史处理 "reload" 和 ignore cache ignore cache 调用等待导航所得的结果。

7.3.3.11. browsingContext.setBypassCSP 命令

browsingContext.setBypassCSP 命令允许绕过 Content Security Policy 的强制执行。

注:启用 CSP 绕过时,所有 CSP 指令都会被 绕过,包括通常会阻止 eval()、new Function()、内联脚本和资源 加载的指令。

命令类型
browsingContext.SetBypassCSP = (
  method: "browsingContext.setBypassCSP",
  params: browsingContext.SetBypassCSPParameters
)

browsingContext.SetBypassCSPParameters = {
  bypass: true / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
browsingContext.SetBypassCSPResult = EmptyResult

远端具有一个绕过 CSP 配置,它是 WebDriver 配置,其关联类型为 boolean。

给定 navigable navigable 时,WebDriver BiDi CSP 被绕过步骤为:

  1. top-level traversablenavigable顶级 traversable

  2. bypass CSP enabled 为针对 top-level traversable绕过 CSP 配置调用获取 WebDriver 配置值所得的结果。

  3. 断言:bypass CSP enabledtrueunset

  4. 如果 bypass CSP enabledunset,则返回 false。

  5. 返回 true。

给定 command parameters 时,远端步骤为:

  1. bypasscommand parameters["bypass"]。

  2. 如果 bypass 为 null,则将 bypass 设置为 unset

  3. 尝试command parameters 存储 WebDriver 配置 绕过 CSP 配置 bypass

  4. 返回带有数据 null 的成功

7.3.3.12. browsingContext.setViewport 命令

browsingContext.setViewport 命令修改给定顶级 traversable 上的特定 viewport 特征(例如 viewport width 和 viewport height)。

命令类型
browsingContext.SetViewport = (
  method: "browsingContext.setViewport",
  params: browsingContext.SetViewportParameters
)

browsingContext.SetViewportParameters = {
  ? context: browsingContext.BrowsingContext,
  ? viewport: browsingContext.Viewport / null,
  ? devicePixelRatio: (float .gt 0.0) / null,
  ? userContexts: [+browser.UserContext],
}

browsingContext.Viewport = {
  width: js-uint,
  height: js-uint,
}
返回类型
browsingContext.SetViewportResult = EmptyResult
要在给定 navigabledevice pixel ratio 的情况下设置 device pixel ratio 覆盖
  1. 如果 device pixel ratio 不是 null:

    1. 对于当前加载在指定 navigable 中的document

      1. 当运行从 source set 选择图像源步骤时, 在选择图像时,表现得如同实现的像素密度被设置为 device pixel ratio

      2. resolution 媒体特性而言,表现得如同 实现的 resolution 是按页面缩放缩放的 device pixel ratio dppx。

    2. device pixel ratio 覆盖[navigable] 设置device pixel ratio

      注:这会因 § 8.3.1 确定 device pixel ratio 的补丁而生效。

  2. 否则:

    1. 对于当前加载在指定 navigable 中的document

      1. 当运行从 source set 选择图像源步骤时,使用实现的默认行为, 不带有这些步骤先前调用所作的任何更改。

      2. resolution 媒体特性而言,使用 实现的默认行为, 不带有这些步骤先前调用所作的任何更改。

    2. device pixel ratio 覆盖移除 navigable

  3. 对当前加载在指定 navigable 中的document运行求值媒体查询并报告变化

要在给定 navigable navigableviewport viewport 的情况下 设置 viewport
  1. 如果 viewport 不是 null,则将 navigable布局视口的宽度设置为 viewportwidth(以 CSS 像素计),并且 将 navigable布局视口的高度设置为 viewportheight(以 CSS 像素计)。

  2. 否则,将 navigable布局视口设置为 实现定义的默认值。

在新的 navigable navigable 中创建 document 之后, 且在调用运行 WebDriver BiDi 预加载脚本算法之前:

TODO:改为将其移作 html 规范中的一个钩子。

  1. user contextnavigable关联用户 上下文

  2. 如果 navigable顶级 traversable

    1. navigable 更新 geolocation 覆盖

    2. navigable 更新模拟 forced colors 主题

    3. 如果 screen orientation 覆盖映射 包含 user context, 则用 navigablescreen orientation 覆盖 映射[user context] 设置模拟 screen orientation

  3. 如果 viewport 覆盖映射 包含 user context

    1. 如果 navigable顶级 traversable,且 viewport 覆盖映射[user context] 的 viewport 不是 null:

      1. navigableviewport 覆盖映射[user context] 的 viewport 设置 viewport

    2. 如果 viewport 覆盖映射[user context] 的devicePixelRatio 不是 null:

      1. navigableviewport 覆盖映射[user context] 的 devicePixelRatio 设置 device pixel ratio 覆盖

  4. navigable 更新 scrollbar type 覆盖

给定 command parameters 时,远端步骤为:

  1. 如果实现因任何原因无法用给定 command parameters 调整布局视口 参数,则返回带有错误 代码 unsupported operation错误

  2. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "context", 则返回带有错误 代码 invalid argument错误

  3. navigables 为一个集合

  4. 如果 command parameterscontext 字段存在:

    1. navigable idcommand parameterscontext 字段的值。

    2. navigable 为用 navigable id 尝试获取 navigable所得的结果。

    3. 如果 navigable 不是顶级 traversable,则返回带有 错误代码 invalid argument错误

    4. navigable 追加navigables

  5. 否则,如果 command parametersuserContexts 字段存在:

    1. user contexts 为用 command parameters["userContexts"] 尝试获取有效用户上下文所得的结果。

    2. 对于 user contexts 中的每个 user context

      1. viewport 覆盖映射[user context] 设置为一个结构体。

      2. 如果 command parameters 包含 "viewport":

        1. viewport 覆盖 映射[user context] 的viewport 设置为 command parameters["viewport"]。

      3. 如果 command parameters 包含 "devicePixelRatio":

        1. viewport 覆盖 映射[user context] 的devicePixelRatio 设置为 command parameters["devicePixelRatio"]。

      4. 对于所有顶级 traversable的列表中 其关联用户上下文user context 的每个 top-level traversable

        1. top-level traversable 追加navigables

  6. 否则,返回带有错误 代码 invalid argument错误

  7. 如果 command parameters 包含 viewport 字段:

    1. viewportcommand parameters["viewport"]。

    2. 对于 navigables 中的每个 navigable

      1. navigableviewport 设置 viewport

      2. navigable活动文档运行 CSSOM View § 13.1 Resizing viewports 步骤。

  8. 如果 command parameters 包含 devicePixelRatio 字段:

    1. device pixel ratiocommand parameters["devicePixelRatio"]。

    2. 对于 navigables 中的每个 navigable

      1. 对于 navigable 和所有后代 navigable

        1. navigabledevice pixel ratio 设置 device pixel ratio 覆盖

  9. 返回带有数据 null 的成功

7.3.3.13. browsingContext.traverseHistory 命令

browsingContext.traverseHistory 命令 按 delta 遍历给定 navigable 的历史。

命令类型
browsingContext.TraverseHistory = (
  method: "browsingContext.traverseHistory",
  params: browsingContext.TraverseHistoryParameters
)

browsingContext.TraverseHistoryParameters = {
  context: browsingContext.BrowsingContext,
  delta: js-int,
}
返回类型
browsingContext.TraverseHistoryResult = EmptyResult
给定 command parameters 时,远端步骤为:
  1. navigable 为用 command parameters["context"] 尝试获取 navigable 所得的结果。

  2. 如果 navigable 不是顶级 traversable,则返回带有 错误代码 invalid argument错误

  3. 断言:navigable 不是 null。

  4. deltacommand parameters["delta"]。

  5. resume id 为唯一字符串。

  6. navigable会话历史遍历队列排入一个任务,以运行以下步骤:

    1. all steps 为针对 navigable 获取所有已使用历史步骤所得的结果。

    2. current indexnavigable当前会话历史步骤all steps 中的索引。

    3. target indexcurrent indexdelta

    4. 如果 all steps[target index] 不存在, 则令 valid entry 为 false;否则为 true。

    5. 用 "check history"、resume idvalid entry 恢复

  7. is valid entry 为用 «"check history"» 和 resume id 等待所得的结果。

  8. 如果 is valid entry 为 false,则返回带有错误 代码 no such history entry错误

  9. 给定 deltanavigable 按 delta 遍历历史

    按写出的算法存在 竞态条件,因为到我们尝试导航时,目标会话历史条目可能已经不存在。 一旦我们支持等待历史进行导航,就可以更稳健地处理这个问题。

  10. TODO:支持等待历史遍历完成。

  11. body 为一个与 browsingContext.TraverseHistoryResult 产生式匹配的映射

  12. 返回带有数据 body成功

给定 contextnavigation status navigation status 时,WebDriver BiDi page show 步骤为:

我们是否想暴露 `browsingContext.pageShow 事件?在这种情况下,我们需要 每当即将发出 `pageshow` 时调用它,而不仅仅是在 bfcache 恢复时调用,并且还要向数据中添加 persisted 状态。

  1. navigation idnavigation statusid

  2. 用 "page show"、navigation idnavigation status 恢复

给定 contextnavigation status navigation status 时,WebDriver BiDi pop state 步骤为:

  1. navigation idnavigation statusid

  2. 用 "pop state"、navigation idnavigation status 恢复

7.3.4. 事件

7.3.4.1. browsingContext.contextCreated 事件
事件类型
browsingContext.ContextCreated = (
 method: "browsingContext.contextCreated",
 params: browsingContext.Info
)

要在给定 sessionnavigable 的情况下递归发出 context created 事件

  1. sessionnavigable 发出 context created 事件

  2. 对于 navigable 的每个子 navigable child

    1. 给定 sessionchild 递归发出 context created 事件

要在给定 sessionnavigable 的情况下发出 context created 事件

  1. params 为给定 navigable、0 和 true 时调用获取 navigable 信息所得的结果。

  2. body 为一个与 browsingContext.ContextCreated 产生式匹配的映射, 其 params 字段设置为 params

  3. sessionbody 发出事件

远端事件触发器是给定 navigable navigablenavigable opener navigable 时的WebDriver BiDi navigable created 步骤:

  1. 如果提供了 opener navigable,则将 navigable原始 opener设置为 opener navigable

  2. 如果以 navigable 调用的navigable 缓存行为为 "bypass", 则执行实现定义的步骤,以禁用源自 navigable 的网络请求的任何实现特定资源缓存。

  3. related navigables 为一个包含 navigable集合

  4. 对于给定 "browsingContext.contextCreated" 和 related navigables事件已启用的会话集合 中的每个 session

    1. 给定 sessionnavigable 发出 context created 事件

给定 sessionnavigablesinclude global 时,远端订阅步骤(其 订阅优先级为 1)为:

  1. 对于 navigables 中的每个 navigable

    1. 给定 sessionnavigable 递归发出 context created 事件

7.3.4.2. browsingContext.contextDestroyed 事件
事件类型
browsingContext.ContextDestroyed = (
 method: "browsingContext.contextDestroyed",
 params: browsingContext.Info
)
远端事件触发器为:

远端事件触发器是给定 navigable navigable 时的WebDriver BiDi navigable destroyed 步骤:

  1. params 为给定 navigable、null 和 true 时调用获取 navigable 信息所得的结果。

  2. body 为一个与 browsingContext.ContextDestroyed 产生式匹配的映射, 其 params 字段设置为 params

  3. related navigables 为一个集合, 如果 navigable父级不是 null,则包含该父级; 否则为空集合

  4. 对于给定 "browsingContext.contextDestroyed" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

    2. subscriptions to remove 为一个集合

    3. 对于 session订阅中的每个 subscription

      1. 如果 subscription顶级 traversable ids 包含 navigablenavigable id

        1. subscription顶级 traversable ids移除 navigablenavigable id

        2. 如果 subscription顶级 traversable ids为空:

          1. subscription 追加subscriptions to remove

    4. session订阅移除 subscriptions to remove

尚不清楚我们是否 应当只针对具有活动文档的 browsing context 触发此事件;导航也可能导致 context 变得不可访问,但由于 bfcache 尚未被丢弃。

7.3.4.3. browsingContext.navigationStarted 事件
事件类型
browsingContext.NavigationStarted = (
 method: "browsingContext.navigationStarted",
 params: browsingContext.NavigationInfo
)
远端事件触发器是 给定 navigable navigablenavigation status navigation status 时的WebDriver BiDi navigation started 步骤:
  1. params 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. body 为一个与 browsingContext.NavigationStarted 产生式匹配的映射, 其 params 字段设置为 params

  3. navigation idnavigation statusid

  4. related navigables 为一个包含 navigable集合

  5. 用 "navigation started"、navigation idnavigation status 恢复

  6. 对于给定 "browsingContext.navigationStarted" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.4. browsingContext.fragmentNavigated 事件
事件类型
browsingContext.FragmentNavigated = (
 method: "browsingContext.fragmentNavigated",
 params: browsingContext.NavigationInfo
)
远端事件触发器是 给定 navigable navigablenavigation status navigation status 时的WebDriver BiDi fragment navigated 步骤:
  1. params 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. body 为一个与 browsingContext.FragmentNavigated 产生式匹配的映射, 其 params 字段设置为 params

  3. navigation idnavigation statusid

  4. related navigable 为一个包含 navigable集合

  5. 用 "fragment navigated"、navigation idnavigation status 恢复

  6. 对于给定 "browsingContext.fragmentNavigated" 和 related navigable事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.5. browsingContext.historyUpdated 事件
事件类型
browsingContext.HistoryUpdated = (
  method: "browsingContext.historyUpdated",
  params: browsingContext.HistoryUpdatedParameters
)

browsingContext.HistoryUpdatedParameters = {
  context: browsingContext.BrowsingContext,
  timestamp: js-uint,
  url: text,
  ? userContext: browser.UserContext
}
远端事件触发器是 给定 navigable navigable 时的WebDriver BiDi history updated 步骤:
  1. url 为给定 navigable活动浏览上下文活动文档URL 运行 URL 序列化器所得的结果。

  2. user context idnavigable关联用户 上下文用户 上下文 id

  3. timestamp 为表示当前 UTC 日期和时间的时间值

  4. params 为一个与 browsingContext.HistoryUpdatedParameters 产生式匹配的映射, 其中 url 字段设置为 urltimestamp 字段设置为 timestampcontext 字段设置为 navigablenavigable id,且 userContext 字段设置为 user context id

  5. body 为一个与 browsingContext.HistoryUpdated 产生式匹配的映射, 其 params 字段设置为 params

  6. related browsing contexts 为一个包含 navigable活动浏览上下文集合

  7. 对于给定 "browsingContext.historyUpdated" 和 related browsing contexts事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.6. browsingContext.domContentLoaded 事件
事件类型
browsingContext.DomContentLoaded = (
 method: "browsingContext.domContentLoaded",
 params: browsingContext.NavigationInfo
)
远端事件触发器是 给定 navigable navigablenavigation status navigation status 时的WebDriver BiDi DOM content loaded 步骤:
  1. params 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. body 为一个与 browsingContext.DomContentLoaded 产生式匹配的映射, 其 params 字段设置为 params

  3. related navigables 为一个包含 navigable集合

  4. navigation idnavigation statusid

  5. 用 "domContentLoaded"、navigation idnavigation status 恢复

  6. 对于给定 "browsingContext.domContentLoaded" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.7. browsingContext.load 事件
事件类型
browsingContext.Load = (
 method: "browsingContext.load",
 params: browsingContext.NavigationInfo
)
远端事件触发器是给定 navigable navigablenavigation status navigation status 时的WebDriver BiDi load complete 步骤:
  1. params 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. body 为一个与 browsingContext.Load 产生式匹配的映射, 其 params 字段设置为 params

  3. related navigables 为一个包含 navigable集合

  4. navigation idnavigation statusid

  5. 用 "load"、navigation idnavigation status 恢复

  6. 对于给定 "browsingContext.load" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.8. browsingContext.downloadWillBegin 事件
事件类型
browsingContext.DownloadWillBegin = (
 method: "browsingContext.downloadWillBegin",
 params: browsingContext.DownloadWillBeginParams
)

browsingContext.DownloadWillBeginParams = {
  suggestedFilename: text,
  browsingContext.BaseNavigationInfo
}
远端事件触发器是 给定 navigable navigablenavigation status navigation status 时的 WebDriver BiDi download will begin 步骤:
  1. navigation info 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. params 为一个与 browsingContext.DownloadWillBeginParams 产生式匹配的映射, 其中 context 字段设置为 navigation info["context"], navigation 字段设置为 navigation info["navigation"], timestamp 字段设置为 navigation info["timestamp"],url 字段设置为 navigation info["url"],且 suggestedFilename 字段设置 为 navigation statussuggestedFilename

  3. body 为一个与 browsingContext.DownloadWillBegin 产生式匹配的映射, 其 params 字段设置为 params

  4. navigation idnavigation statusid

  5. related navigables 为一个包含 navigable集合

  6. 用 "download started"、navigation idnavigation status 恢复

  7. 对于给定 "browsingContext.downloadWillBegin" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

  8. download behavior 为以 navigable 调用获取下载行为所得的结果。

  9. 返回 download behavior

7.3.4.9. browsingContext.downloadEnd 事件
事件类型
browsingContext.DownloadEnd = (
  method: "browsingContext.downloadEnd",
  params: browsingContext.DownloadEndParams
)

browsingContext.DownloadEndParams = {
  (
    browsingContext.DownloadCanceledParams //
    browsingContext.DownloadCompleteParams
  )
}

browsingContext.DownloadCanceledParams = (
  status: "canceled",
  browsingContext.BaseNavigationInfo
)

browsingContext.DownloadCompleteParams = (
  status: "complete",
  filepath: text / null,
  browsingContext.BaseNavigationInfo
)
远端事件触发器是给定 navigable navigablenavigation status navigation status 时的WebDriver BiDi download end 步骤:
  1. navigation info 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. 断言 navigation info["status"] 等于 "complete" 或 "canceled"。

  3. 如果 navigation info["status"] 是 "complete",则令 params 为一个与 browsingContext.DownloadCompleteParams 产生式匹配的映射,其中 filepath 字段设置为 navigation statusdownloadedFilepathcontext 字段设置为 navigation info["context"], navigation 字段设置为 navigation info["navigation"], timestamp 字段设置为 navigation info["timestamp"],且 url 字段设置为 navigation info["url"]。

    注:如果由于任何原因无法获得 filepath, 则对于已完成的下载,filepath 可以为 null。

  4. 否则,令 params 为一个与 browsingContext.DownloadCanceledParams 产生式匹配的映射, 其中 context 字段设置为 navigation info["context"], navigation 字段设置为 navigation info["navigation"], timestamp 字段设置为 navigation info["timestamp"],且 url 字段设置为 navigation info["url"]。

  5. body 为一个与 browsingContext.DownloadEnd 产生式匹配的映射, 其 params 字段设置为 params

  6. related navigables 为一个包含 navigable集合

  7. 对于给定 "browsingContext.downloadEnd" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.10. browsingContext.navigationAborted 事件
事件类型
browsingContext.NavigationAborted = (
 method: "browsingContext.navigationAborted",
 params: browsingContext.NavigationInfo
)
远端事件触发器是 给定 navigable navigablenavigation status navigation status 时的WebDriver BiDi navigation aborted 步骤:
  1. params 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. body 为一个与 browsingContext.NavigationAborted 产生式匹配的映射, 其 params 字段设置为 params

  3. navigation idnavigation statusid

  4. related navigables 为一个包含 navigable集合

  5. 用 "navigation aborted"、navigation idnavigation status 恢复

  6. 对于给定 "browsingContext.navigationAborted" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.11. browsingContext.navigationCommitted 事件
事件类型
browsingContext.NavigationCommitted = (
 method: "browsingContext.navigationCommitted",
 params: browsingContext.NavigationInfo
)
远端事件触发器是 给定 navigable navigablenavigation status navigation status 时的WebDriver BiDi navigation committed 步骤:
  1. params 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. body 为一个与 browsingContext.NavigationCommitted 产生式匹配的映射, 其 params 字段设置为 params

  3. related navigables 为一个包含 navigable集合

  4. navigation idnavigation statusid

  5. 用 "navigation committed"、navigation idnavigation status 恢复

  6. 对于给定 "browsingContext.navigationCommitted" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.12. browsingContext.navigationFailed 事件
事件类型
browsingContext.NavigationFailed = (
 method: "browsingContext.navigationFailed",
 params: browsingContext.NavigationInfo
)
远端事件触发器是 给定 navigable navigablenavigation status navigation status 时的WebDriver BiDi navigation failed 步骤:
  1. params 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. body 为一个与 browsingContext.NavigationFailed 产生式匹配的映射, 其 params 字段设置为 params

  3. navigation idnavigation statusid

  4. related navigables 为一个包含 navigable集合

  5. 用 "navigation failed"、navigation idnavigation status 恢复

  6. 对于给定 "browsingContext.navigationFailed" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.13. browsingContext.userPromptClosed 事件
事件类型
browsingContext.UserPromptClosed = (
  method: "browsingContext.userPromptClosed",
  params: browsingContext.UserPromptClosedParameters
)

browsingContext.UserPromptClosedParameters = {
  context: browsingContext.BrowsingContext,
  accepted: bool,
  type: browsingContext.UserPromptType,
  ? userContext: browser.UserContext,
  ? userText: text
}
远端事件触发器是给定 Window window、字符串 type、boolean accepted 和可选 text user text (默认值:null)时的WebDriver BiDi user prompt closed 步骤。
  1. navigablewindownavigable

  2. navigable idnavigablenavigable id

  3. user context idnavigable关联用户 上下文用户 上下文 id

  4. params 为一个与 browsingContext.UserPromptClosedParameters 产生式匹配的映射,其 context 字段设置为 navigable iduserContext 字段设置为 user context idaccepted 字段设置为 acceptedtype 字段设置为 type,且如果 user text 不是 null,则将 userText 字段设置为 user text,否则省略。

  5. body 为一个与 BrowsingContextUserPromptClosedEvent 产生式匹配的映射, 其 params 字段设置为 params

  6. related navigables 为一个包含 navigable集合

  7. 对于给定 "browsingContext.userPromptClosed" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.14. browsingContext.userPromptOpened 事件
事件类型
browsingContext.UserPromptOpened = (
  method: "browsingContext.userPromptOpened",
  params: browsingContext.UserPromptOpenedParameters
)

browsingContext.UserPromptOpenedParameters = {
  context: browsingContext.BrowsingContext,
  handler: session.UserPromptHandlerType,
  message: text,
  type: browsingContext.UserPromptType,
  ? userContext: browser.UserContext,
  ? defaultValue: text
}
要在给定 typenavigable 的情况下获取 navigable 的用户提示处理器
  1. user contextnavigable关联用户 上下文

  2. 如果 未处理提示行为覆盖 映射 包含 user context

    1. unhandled prompt behavior override未处理提示行为 覆盖映射[user context]。

    2. 如果 unhandled prompt behavior override[type] 不是 null,则返回 unhandled prompt behavior override[type]。

    3. 如果 unhandled prompt behavior override["default"] 不是 null, 则返回 unhandled prompt behavior override["default"]。

  3. handler configuration 为以 type 调用获取提示处理器所得的结果。

  4. 返回 handler configurationhandler

远端事件触发器是给定 Window window、字符串 type、字符串 message 和可选 text default value (默认值:null)时的WebDriver BiDi user prompt opened 步骤。
  1. navigablewindownavigable

  2. navigable idnavigablenavigable id

  3. user context idnavigable关联用户 上下文用户 上下文 id

  4. handler 为以 typenavigable 调用获取 navigable 的用户提示处理器所得的结果。

  5. params 为一个与 browsingContext.UserPromptOpenedParameters 产生式匹配的映射,其 context 字段设置为 navigable iduserContext 字段设置为 user context idtype 字段设置为 typemessage 字段设置为 message,如果 default value 不是 null,则将 defaultValue 字段设置为 default value,否则省略, 并将 handler 字段设置为 handler

  6. body 为一个与 browsingContext.UserPromptOpened 产生式匹配的映射, 其 params 字段设置为 params

  7. related navigables 为一个包含 navigable集合

  8. 对于给定 "browsingContext.userPromptOpened" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

  9. 如果 handler 是 "ignore",则将 handler 设置为 "none"。

  10. 返回 handler

7.4. emulation 模块

emulation 模块包含与浏览器 API 模拟相关的命令和事件。

7.4.1. 定义

remote end definition

EmulationCommand = (
  emulation.SetForcedColorsModeThemeOverride //
  emulation.SetGeolocationOverride //
  emulation.SetLocaleOverride //
  emulation.SetNetworkConditions //
  emulation.SetScreenOrientationOverride //
  emulation.SetScreenSettingsOverride //
  emulation.SetScriptingEnabled //
  emulation.SetScrollbarTypeOverride //
  emulation.SetTimezoneOverride //
  emulation.SetTouchOverride //
  emulation.SetUserAgentOverride
)

EmulationResult = (
  emulation.SetForcedColorsModeThemeOverrideResult /
  emulation.SetGeolocationOverrideResult /
  emulation.SetLocaleOverrideResult /
  emulation.SetScreenOrientationOverrideResult /
  emulation.SetScriptingEnabledResult /
  emulation.SetScrollbarTypeOverrideResult /
  emulation.SetTimezoneOverrideResult /
  emulation.SetTouchOverrideResult /
  emulation.SetUserAgentOverrideResult
)

BiDi 会话具有一个模拟 user agent,它是一个 结构体,带有 一个名为 default user agent,其为字符串或 null; 一个名为 user context user agent,其为 用户上下文与 字符串之间的弱映射;以及一个名为 navigable user agent,其为 navigables 与字符串之间的弱映射。

BiDi 会话具有模拟 maxTouchPoints,它是一个结构体,带有 一个名为 default,其为整数或 null,初始为 null; 一个名为 user contexts,其为 用户上下文与整数之间的弱映射, 初始为空; 以及一个名为 navigables,其为 navigables 与整数之间的弱映射,初始为空。

screen orientation 覆盖是一个带有以下内容的结构体

远端具有一个screen orientation 覆盖映射,它是 用户上下文screen orientation 覆盖之间的弱映射。

7.4.2. 命令

7.4.2.1. emulation.setForcedColorsModeThemeOverride 命令

emulation.setForcedColorsModeThemeOverride 命令修改给定顶级 traversables 或用户上下文上的 forced colors mode 主题特征。

命令类型
emulation.SetForcedColorsModeThemeOverride = (
  method: "emulation.setForcedColorsModeThemeOverride",
  params: emulation.SetForcedColorsModeThemeOverrideParameters
)

emulation.SetForcedColorsModeThemeOverrideParameters = {
  theme: emulation.ForcedColorsModeTheme / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.ForcedColorsModeTheme = "light" / "dark"
返回类型
emulation.SetForcedColorsModeThemeOverrideResult = EmptyResult

注:对应的 CSS 规范中的枚举映射,请查看 ForcedColorsModeAutomationTheme

远端具有一个forced colors mode theme override 配置,它是 WebDriver 配置,其关联类型为字符串。

要为 navigable navigable 更新模拟 forced colors 主题
  1. theme 为针对 navigableforced colors mode theme override 配置调用获取 WebDriver 配置值所得的结果。

  2. 断言:theme 是 "light"、"dark" 或 unset

  3. 如果 themeunset,则将 theme 设置为 "none"。

  4. navigabletheme 设置模拟 forced colors 主题数据

给定 command parameters 时,远端步骤为:

  1. themecommand parameters["theme"]。

  2. 如果 theme 为 null,则将 theme 设置为 unset

  3. 如果实现不支持设置 theme,则返回带有错误 代码 unsupported operation错误

  4. affected navigables 为为 command parameters 尝试存储 WebDriver 配置 forced colors mode theme override 配置 theme 所得的结果。

  5. 对于 affected navigables 中的每个 navigable

    1. navigable 更新模拟 forced colors 主题

  6. 返回带有数据 null 的成功

7.4.2.2. emulation.setGeolocationOverride 命令

emulation.setGeolocationOverride 命令修改 给定顶级 traversables 或用户上下文上的 geolocation 特征。

命令类型
emulation.SetGeolocationOverride = (
  method: "emulation.setGeolocationOverride",
  params: emulation.SetGeolocationOverrideParameters
)

emulation.SetGeolocationOverrideParameters = {
  (
    (coordinates: emulation.GeolocationCoordinates / null) //
    (error: emulation.GeolocationPositionError)
  ),
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.GeolocationCoordinates = {
   latitude: -90.0..90.0,
   longitude: -180.0..180.0,
   ? accuracy: (float .ge 0.0) .default 1.0,
   ? altitude: float / null .default null,
   ? altitudeAccuracy: (float .ge 0.0) / null .default null,
   ? heading: (0.0...360.0) / null .default null,
   ? speed: (float .ge 0.0) / null .default null,
}

emulation.GeolocationPositionError = {
   type: "positionUnavailable"
}
返回类型
emulation.SetGeolocationOverrideResult = EmptyResult

geolocation 覆盖是一个带有以下内容的结构体

远端具有一个geolocation 覆盖配置,它是 WebDriver 配置,其关联类型geolocation 覆盖

要为 navigable navigable 更新 geolocation 覆盖
  1. emulated position data 为针对 navigablegeolocation 覆盖配置调用获取 WebDriver 配置值所得的结果。

  2. 如果 emulated position dataunset,则将 emulated position data 设置为 null。

  3. navigableemulated position data 设置模拟位置数据

给定 command parameters 时,远端步骤为:

  1. 如果 command parameters 包含 "coordinates",且 command parameters["coordinates"] 包含 "altitudeAccuracy",且 command parameters["coordinates"] 不包含 "altitude",则返回带有错误代码 invalid argument错误

  2. 如果 command parameters 包含 "error":

    1. 断言 command parameters["error"]["type"] 等于 "positionUnavailable"。

    2. emulated position data 为一个与 GeolocationPositionError 产生式匹配的映射, 其 code 字段设置为 POSITION_UNAVAILABLE, 并且 message 字段设置为空字符串。

      注:根据 geolocation 规范, message 将被实现忽略。

  3. 否则,令 emulated position datacommand parameters["coordinates"]。

  4. 如果 emulated position data 为 null,则将 emulated position data 设置为 unset

  5. affected navigables 为为 command parameters 尝试存储 WebDriver 配置 geolocation 覆盖配置 emulated position data 所得的结果。

  6. 对于 affected navigables 中的每个 navigable

    1. navigable 更新 geolocation 覆盖

  7. 返回带有数据 null 的成功

7.4.2.3. emulation.setLocaleOverride 命令

emulation.setLocaleOverride 命令修改 给定顶级 traversables 或用户上下文上的 locale。

命令类型
emulation.SetLocaleOverride = (
  method: "emulation.setLocaleOverride",
  params: emulation.SetLocaleOverrideParameters
)

emulation.SetLocaleOverrideParameters = {
  locale: text / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetLocaleOverrideResult = EmptyResult

给定环境设置对象 environment settings 时,WebDriver BiDi 模拟语言步骤为:

  1. related navigables 为给定 environment settings 时调用获取相关 navigables所得的结果。

  2. 对于 related navigables 中的每个 navigable

    1. top-level traversablenavigable顶级 traversable

    2. user contexttop-level traversable关联 用户上下文

    3. 如果 locale 覆盖映射 包含 top-level traversable,则返回 locale 覆盖映射[top-level traversable]。

    4. 如果 locale 覆盖映射 包含 user context,则返回 locale 覆盖映射[user context]。

  3. 返回 null

给定 command parameters 时,远端步骤为:

  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 代码 invalid argument错误

  2. 如果 command parameters包含 "userContexts" 且 command parameters包含 "contexts", 则返回带有错误 代码 invalid argument错误

  3. emulated localecommand parameters["locale"]。

  4. 如果 emulated locale 不是 null 且 IsStructurallyValidLanguageTag(emulated locale) 返回 false,则返回带有错误 代码 invalid argument错误

  5. navigables 为一个集合

  6. 如果 command parameterscontexts 字段存在:

    1. navigables 为以 command parameters["contexts"] 尝试通过 id 获取有效顶级 traversables所得的结果。

  7. 否则:

    1. 断言 command parametersuserContexts 字段存在。

    2. user contexts 为以 command parameters["userContexts"] 尝试获取有效用户上下文 所得的结果。

    3. 对于 user contexts 中的每个 user context

      1. 如果 emulated locale 为 null,则从 locale 覆盖映射移除 user context

      2. 否则,将 locale 覆盖映射[user context] 设置emulated locale

      3. 对于所有 顶级 traversable的列表中 其关联用户上下文user context 的每个 top-level traversable

        1. top-level traversable 追加navigables

  8. 对于 navigables 中的每个 navigable

    1. 如果 emulated locale 为 null,则从 locale 覆盖映射移除 navigable

    2. 否则,将 locale 覆盖映射[navigable] 设置emulated locale

  9. 返回带有数据 null 的成功

7.4.2.4. emulation.setNetworkConditions 命令

emulation.setNetworkConditions 命令 为给定浏览上下文或用户上下文模拟特定的网络条件。

命令类型
emulation.SetNetworkConditions = (
  method: "emulation.setNetworkConditions",
  params: emulation.SetNetworkConditionsParameters
)

emulation.SetNetworkConditionsParameters = {
  networkConditions: emulation.NetworkConditions / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.NetworkConditions = emulation.NetworkConditionsOffline

emulation.NetworkConditionsOffline = {
  type: "offline"
}
返回类型
emulation.SetNetworkConditionsResult = EmptyResult

应用网络 条件

  1. 对于每个 WebSocket 对象 webSocket

    1. realmwebSocket相关 Realm

    2. environment settings 为其 realm execution context 的 Realm 组件 是 realm环境设置对象

    3. 如果以 environment settings 调用WebDriver BiDi 网络离线 所得的结果为 true:

      1. 使 WebSocket 连接失败 webSocket

  2. 对于每个 WebTransport 对象 webTransport

    1. realmwebSocket相关 Realm

    2. environment settings 为其 realm execution context 的 Realm 组件 是 realm环境设置对象

    3. 如果以 environment settings 调用WebDriver BiDi 网络 离线所得的结果为 true:

      1. 清理 WebTransport webTransport

给定 command parameterssession 时,远端步骤为:

  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "context", 则返回带有错误 代码 invalid argument错误

  2. emulated network conditions 为 null。

  3. 如果 command parameters["networkConditions"] 不是 null,且 command parameters["networkConditions"]["type"] 等于 "offline",则将 emulated network conditions 设置为一个新的 模拟网络条件结构体,其 offline 设置为 true。

  4. 如果 command parameterscontexts 字段存在:

    1. navigables 为以 command parameters["contexts"] 尝试通过 id 获取有效顶级 traversables所得的结果。

    2. 对于 navigables 中的每个 navigable

      1. 如果 emulated network conditions 为 null,则从 session模拟网络 条件navigable network conditions移除 navigable

      2. 否则,将 session模拟网络 条件navigable network conditions[navigable] 设置emulated network conditions

  5. 如果 command parametersuserContexts 字段存在:

    1. user contexts 为以 command parameters["userContexts"] 尝试获取有效用户上下文 所得的结果。

    2. 对于 user contexts 中的每个 user context

      1. 如果 emulated network conditions 为 null,则从 session模拟网络 条件user context network conditions移除 user context

      2. 否则,将 session模拟网络 条件user context network conditions[user context] 设置emulated network conditions

  6. 如果 command parameters包含 "userContexts" 且 command parameters包含 "context", 则将 session模拟网络条件default network conditions 设置emulated network conditions

  7. 应用网络条件

  8. 返回带有数据 null 的成功

7.4.2.5. emulation.setScreenSettingsOverride 命令

emulation.setScreenSettingsOverride 命令 模拟给定顶级 traversables 或用户上下文的Web 暴露屏幕区域Web 暴露可用屏幕区域

命令类型
emulation.SetScreenSettingsOverride = (
  method: "emulation.setScreenSettingsOverride",
  params: emulation.SetScreenSettingsOverrideParameters
)

emulation.ScreenArea = {
  width: js-uint,
  height: js-uint
}

emulation.SetScreenSettingsOverrideParameters = {
  screenArea: emulation.ScreenArea / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetScreenSettingsOverrideResult = EmptyResult

给定 navigable navigable 时,WebDriver BiDi 模拟可用屏幕 区域步骤为:

  1. top-level traversablenavigable顶级 traversable

  2. user contexttop-level traversable关联用户 上下文

  3. 如果 screen settings 覆盖 包含 top-level traversable,则返回 screen settings 覆盖[top-level traversable]。

  4. 如果 screen settings 覆盖 包含 user context,则返回 screen settings 覆盖[user context]。

  5. 返回 null

给定 navigable navigable 时,WebDriver BiDi 模拟总屏幕区域步骤为:

  1. top-level traversablenavigable顶级 traversable

  2. user contexttop-level traversable关联用户 上下文

  3. 如果 screen settings 覆盖 包含 top-level traversable,则返回 screen settings 覆盖[top-level traversable]。

  4. 如果 screen settings 覆盖 包含 user context,则返回 screen settings 覆盖[user context]。

  5. 返回 null

给定 command parameters 时,远端步骤为:

  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 代码 invalid argument错误

  2. 如果 command parameters包含 "userContexts" 且 command parameters包含 "contexts", 则返回带有错误 代码 invalid argument错误

  3. emulated screen areacommand parameters["screenArea"]。

  4. 如果 emulated screen area 不是 null:

    1. emulated screen area["x"] 设置为 0。

    2. emulated screen area["y"] 设置为 0。

  5. navigables 为一个集合

  6. 如果 command parameterscontexts 字段存在:

    1. navigables 为以 command parameters["contexts"] 尝试通过 id 获取有效顶级 traversables所得的结果。

    2. targetnavigable screen settings

    3. 对于 navigables 中的每个 navigable

      1. 如果 emulated screen area 为 null,则从 target移除 navigable

      2. 否则,将 target[navigable] 设置emulated screen area

    4. 返回带有数据 null 的成功

  7. 否则:

    1. 断言 command parametersuserContexts 字段存在。

    2. user contexts 为以 command parameters["userContexts"] 尝试获取有效用户上下文 所得的结果。

    3. targetuser context screen settings

    4. 对于 user contexts 中的每个 user context

      1. 如果 emulated screen area 为 null,则从 target移除 user context

      2. 否则,将 target[user context] 设置emulated screen area

    5. 返回带有数据 null 的成功

7.4.2.6. emulation.setScreenOrientationOverride 命令

emulation.setScreenOrientationOverride 命令 模拟给定顶级 traversables 或用户上下文的screen orientation

命令类型
emulation.SetScreenOrientationOverride = (
  method: "emulation.setScreenOrientationOverride",
  params: emulation.SetScreenOrientationOverrideParameters
)

emulation.ScreenOrientationNatural = "portrait" / "landscape"
emulation.ScreenOrientationType = "portrait-primary" / "portrait-secondary" / "landscape-primary" / "landscape-secondary"

emulation.ScreenOrientation = {
  natural: emulation.ScreenOrientationNatural,
  type: emulation.ScreenOrientationType
}

emulation.SetScreenOrientationOverrideParameters = {
  screenOrientation: emulation.ScreenOrientation / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetScreenOrientationOverrideResult = EmptyResult

要在给定 navigableemulated screen orientation 的情况下设置 模拟 screen orientation

将此算法移至 screen orientation 规范。

  1. 如果 emulated screen orientation 为 null:

    1. navigable当前方向角设置为 实现定义的默认值。

    2. navigable当前方向类型设置为 实现定义的默认值。

  2. 否则:

    1. emulated orientation typeemulated screen orientation["type"]。

    2. emulated orientation angle 为针对具有 emulated screen orientation["natural"] 方向的屏幕, 按screen orientation values lists 中定义的、与 emulated orientation type 关联的角度。

    3. 当前方向角设置为 emulated orientation angle

    4. 当前方向类型设置为 emulated orientation type

  3. navigable活动文档运行 screen orientation change steps

给定 command parameters 时,远端步骤为:

  1. 如果实现因任何原因无法用给定 command parameters 调整 screen orientations 参数,则返回带有错误 代码 unsupported operation错误

  2. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 代码 invalid argument错误

  3. 如果 command parameters包含 "userContexts" 且 command parameters包含 "contexts", 则返回带有错误 代码 invalid argument错误

  4. emulated screen orientationcommand parameters["screenOrientation"]。

  5. navigables 为一个集合

  6. 如果 command parameterscontexts 字段存在:

    1. navigables 为以 command parameters["contexts"] 尝试通过 id 获取有效顶级 traversables所得的结果。

  7. 否则,如果 command parametersuserContexts 字段存在:

    1. user contexts 为以 command parameters["userContexts"] 尝试获取有效用户上下文 所得的结果。

    2. 对于 user contexts 中的每个 user context

      1. 如果 emulated screen orientation 为 null,则从 screen orientation 覆盖 映射移除 user context

      2. 否则,将 screen orientation 覆盖 映射[user context] 设置emulated screen orientation

      3. 对于所有 顶级 traversable的列表中 其关联用户上下文user context 的每个 top-level traversable

        1. top-level traversable 追加navigables

  8. 对于 navigables 中的每个 navigable

    1. user contextnavigable关联 用户上下文

    2. 如果 emulated screen orientation 为 null,且 screen orientation 覆盖映射 包含 user context,则用 navigablescreen orientation 覆盖 映射[user context] 设置模拟 screen orientation

    3. 否则,用 navigableemulated screen orientation 设置模拟 screen orientation

  9. 返回带有数据 null 的成功

7.4.2.7. emulation.setUserAgentOverride 命令

emulation.setUserAgentOverride 命令修改 给定顶级 traversables、用户上下文或全局的 User-Agent。

命令类型
emulation.SetUserAgentOverride = (
  method: "emulation.setUserAgentOverride",
  params: emulation.SetUserAgentOverrideParameters
)

emulation.SetUserAgentOverrideParameters = {
  userAgent: text / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetUserAgentOverrideResult = EmptyResult
给定 环境设置对象 environment settings 时,WebDriver BiDi 模拟 User-Agent步骤为:
  1. related navigables 为以 environment settings 调用获取相关 navigables所得的结果。

  2. 对于 related navigables 中的每个 navigable

    1. top-level navigablenavigable顶级 traversable

    2. user contexttop-level navigable关联 用户上下文

    3. 对于 活动 BiDi 会话中的每个 session

      1. 如果 session模拟 user agentnavigable user agent 包含 top-level navigable,则返回 session模拟 user agentnavigable user agent[top-level navigable]。

    4. 对于 活动 BiDi 会话中的每个 session

      1. 如果 session模拟 user agentuser context user agent 包含 user context,则返回 session模拟 user agentuser context user agent[user context]。

  3. 对于 活动 BiDi 会话中的每个 session

    1. default emulated user agentsession模拟 user agentdefault user agent

    2. 如果 default emulated user agent 不是 null,则返回 default emulated user agent

  4. 返回 null。

给定 sessioncommand parameters 时,远端步骤为:

  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 代码 invalid argument错误

  2. emulated user agentcommand parameters["userAgent"]。

  3. 如果 command parameters 包含 "contexts":

    1. navigables 为以 command parameters["contexts"] 尝试通过 id 获取有效顶级 traversables所得的结果。

    2. 对于 navigables 中的每个 navigable

      1. 如果 emulated user agent 为 null,则从 session模拟 user agentnavigable user agent移除 navigable

      2. 否则,将 session模拟 user agentnavigable user agent[navigable] 设置emulated user agent

    3. 返回带有数据 null 的成功

  4. 如果 command parameters 包含 "userContexts":

    1. user contexts 为以 command parameters["userContexts"] 尝试获取有效用户上下文 所得的结果。

    2. 对于 user contexts 中的每个 user context

      1. 如果 emulated user agent 为 null,则从 session模拟 user agentuser context user agent移除 user context

      2. 否则,将 session模拟 user agentuser context user agent[user context] 设置emulated user agent

    3. 返回带有数据 null 的成功

  5. session模拟 user agentdefault user agent 设置emulated user agent

  6. 返回带有数据 null 的成功

7.4.2.8. emulation.setScriptingEnabled 命令

emulation.setScriptingEnabled 命令模拟 在网页上禁用 JavaScript。

命令类型
emulation.SetScriptingEnabled = (
  method: "emulation.setScriptingEnabled",
  params: emulation.SetScriptingEnabledParameters
)

emulation.SetScriptingEnabledParameters = {
  enabled: false / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetScriptingEnabledResult = EmptyResult

注:仅支持模拟已禁用的 JavaScript。

给定 环境设置对象 settings 时,WebDriver BiDi scripting is enabled步骤为:
  1. navigablesettings相关全局对象关联 Documentnode navigable

  2. top-level traversablenavigable顶级 traversable

  3. 如果 scripting enabled 覆盖映射包含 top-level traversable,则返回 scripting enabled 覆盖 映射[top-level traversable]

  4. user contexttop-level traversable关联用户 上下文

  5. 如果 scripting enabled 覆盖映射包含 user context,则返回 scripting enabled 覆盖映射[user context]。

  6. 返回 true。

给定 command parameters 时,远端步骤为:

  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 代码 invalid argument错误

  2. 如果 command parameters包含 "userContexts" 且 command parameters包含 "contexts", 则返回带有错误 代码 invalid argument错误

  3. emulated scripting enabled statuscommand parameters["enabled"]。

  4. 如果 command parameterscontexts 字段存在:

    1. navigables 为以 command parameters["contexts"] 尝试通过 id 获取有效顶级 traversables所得的结果。

    2. 对于 navigables 中的每个 navigable

      1. 如果 emulated scripting enabled status 为 null,则从 scripting enabled 覆盖 映射移除 navigable

      2. 否则,将 scripting enabled 覆盖 映射[navigable] 设置emulated scripting enabled status

  5. 如果 command parametersuserContexts 字段存在:

    1. user contexts 为以 command parameters["userContexts"] 尝试获取有效用户上下文 所得的结果。

    2. 对于 user contexts 中的每个 user context

      1. 如果 emulated scripting enabled status 为 null,则从 scripting enabled 覆盖 映射移除 user context

      2. 否则,将 scripting enabled 覆盖 映射[user context] 设置emulated scripting enabled status

  6. 返回带有数据 null 的成功

7.4.2.9. emulation.setScrollbarTypeOverride 命令

emulation.setScrollbarTypeOverride 命令 修改给定顶级 traversables、用户上下文或全局的 scrollbar type。

命令类型
emulation.SetScrollbarTypeOverride = (
  method: "emulation.setScrollbarTypeOverride",
  params: emulation.SetScrollbarTypeOverrideParameters
)

emulation.SetScrollbarTypeOverrideParameters = {
  scrollbarType: "classic" / "overlay" / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetScrollbarTypeOverrideResult = EmptyResult

远端具有一个scrollbar type 覆盖配置, 它是 WebDriver 配置,其关联类型为字符串。

要为 navigable navigable 更新 scrollbar type 覆盖
  1. scrollbar type override 为针对 navigablescrollbar type 覆盖配置调用获取 WebDriver 配置值所得的结果。

  2. 断言:scrollbar type override 是 "classic"、 "overlay" 或 unset

  3. 如果 scrollbar type override 是 "classic",则运行实现定义的步骤, 使 navigable活动文档使用classic scrollbars,并返回。

  4. 如果 scrollbar type override 是 "overlay",则运行实现定义的 步骤,使 navigable活动文档使用overlay scrollbars,并返回。

  5. 断言:scrollbar type overrideunset

  6. 运行实现定义的步骤,使 navigable活动文档 使用实现定义的默认 scrollbar type。

给定 command parameters 时,远端步骤为:

  1. scrollbar type overridecommand parameters["scrollbarType"]。

  2. 如果 scrollbar type override 为 null,则将 scrollbar type override 设置为 unset

  3. 如果实现不支持设置 scrollbar type override,则返回带有错误代码 unsupported operation错误

  4. affected navigables 为为 command parameters 尝试存储 WebDriver 配置 scrollbar type 覆盖 配置 scrollbar type override 所得的结果。

  5. 对于 affected navigables 中的每个 navigable

    1. navigable 更新 scrollbar type 覆盖

  6. 返回带有数据 null 的成功

7.4.2.10. emulation.setTimezoneOverride 命令

emulation.setTimezoneOverride 命令修改 给定顶级 traversables 或用户上下文上的 timezone。

命令类型
emulation.SetTimezoneOverride = (
  method: "emulation.setTimezoneOverride",
  params: emulation.SetTimezoneOverrideParameters
)

emulation.SetTimezoneOverrideParameters = {
  timezone: text / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetTimezoneOverrideResult = EmptyResult
SystemTimeZoneIdentifier 算法是实现定义的。一个 WebDriver-BiDi 远端必须具有运行以下 步骤的实现:
  1. emulated timezone 为 null。

  2. realm当前 Realm Record

  3. environment settings 为其 realm execution context 的 Realm 组件为 realm环境设置对象

  4. related navigables 为给定 environment settings 时调用获取相关 navigables所得的结果。

  5. 对于 related navigables 中的每个 navigable

    1. top-level traversablenavigable顶级 traversable

    2. user contexttop-level traversable关联 用户上下文

    3. 如果 timezone 覆盖映射 包含 top-level traversable,则将 emulated timezone 设置为 timezone 覆盖映射[top-level traversable]。

    4. 否则,如果 timezone 覆盖映射 包含 user context,则将 emulated timezone 设置为 timezone 覆盖映射[user context]。

  6. 如果 emulated timezone 不是 null,则返回 emulated timezone

  7. 返回依照 SystemTimeZoneIdentifier 规范要求的 实现定义步骤的结果。

给定 command parameters 时,远端步骤为:

  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 代码 invalid argument错误

  2. 如果 command parameters包含 "userContexts" 且 command parameters包含 "contexts", 则返回带有错误 代码 invalid argument错误

  3. emulated timezonecommand parameters["timezone"]。

  4. 如果 emulated timezone 不是 null,且 IsTimeZoneOffsetString(emulated timezone) 返回 false,且 AvailableNamedTimeZoneIdentifiers包含 emulated timezone,则返回带有错误代码 invalid argument错误

  5. navigables 为一个集合

  6. 如果 command parameterscontexts 字段存在:

    1. navigables 为以 command parameters["contexts"] 尝试通过 id 获取有效顶级 traversables所得的结果。

  7. 否则:

    1. 断言 command parametersuserContexts 字段存在。

    2. user contexts 为以 command parameters["userContexts"] 尝试获取有效用户上下文 所得的结果。

    3. 对于 user contexts 中的每个 user context

      1. 如果 emulated timezone 为 null,则从 timezone 覆盖映射移除 user context

      2. 否则,将 timezone 覆盖映射[user context] 设置emulated timezone

      3. 对于所有 顶级 traversable的列表中 其关联用户上下文user context 的每个 top-level traversable

        1. top-level traversable 追加navigables

  8. 对于 navigables 中的每个 navigable

    1. 如果 emulated timezone 为 null,则从 timezone 覆盖映射移除 navigable

    2. 否则,将 timezone 覆盖映射[navigable] 设置emulated timezone

  9. 返回带有数据 null 的成功

7.4.2.11. emulation.setTouchOverride 命令

emulation.setTouchOverride 命令模拟 网页上启用的触摸输入。

命令类型
emulation.SetTouchOverride = (
  method: "emulation.setTouchOverride",
  params: emulation.SetTouchOverrideParameters
)

emulation.SetTouchOverrideParameters = {
  maxTouchPoints: (js-uint .ge 1) / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetTouchOverrideResult = EmptyResult
给定 环境设置对象 environment settings 时,WebDriver BiDi 模拟最大触点数步骤为:
  1. related navigables 为以 environment settings 调用获取相关 navigables所得的结果。

  2. 对于 related navigables 中的每个 navigable

    1. top-level navigablenavigable顶级 traversable

    2. user contexttop-level navigable关联 用户上下文

    3. 对于 活动 BiDi 会话中的每个 session

      1. 如果 session模拟 maxTouchPointsnavigables 包含 top-level navigable,则返回 session模拟 maxTouchPointsnavigables[top-level navigable]。

    4. 对于 活动 BiDi 会话中的每个 session

      1. 如果 session模拟 maxTouchPointsuser contexts 包含 user context,则返回 session模拟 maxTouchPointsuser contexts[user context]。

  3. 对于 活动 BiDi 会话中的每个 session

    1. emulated maxTouchPointssession模拟 maxTouchPointsdefault

    2. 如果 emulated maxTouchPoints 不是 null,则返回 emulated maxTouchPoints

  4. 返回 null。

给定 sessioncommand parameters 时,远端步骤为:

注:存在一个遗留的暴露遗留 touch event API, 它仍可被某些现有 Web 内容用作用户代理是启用了触摸的“移动”设备的信号。即使该 API 是遗留的,用户代理也可以运行实现定义的步骤,以便在暴露遗留 touch event API中遵循 模拟 maxTouchPoints 状态。

  1. 如果 command parameters 包含 "userContexts",且 command parameters 包含 "contexts",则返回带有错误 代码 invalid argument错误

  2. maxTouchPointscommand parameters["maxTouchPoints"]。

  3. 如果 command parameterscontexts 字段存在:

    1. navigables 为以 command parameters["contexts"] 尝试通过 id 获取有效顶级 traversables 所得的结果。

    2. 对于 navigables 中的每个 navigable

      1. 如果 maxTouchPoints 为 null,则从 session模拟 maxTouchPointsnavigables移除 navigable

      2. 否则,将 session模拟 maxTouchPointsnavigables[navigable] 设置maxTouchPoints

    3. 返回带有数据 null 的成功

  4. 如果 command parametersuserContexts 字段存在:

    1. user contexts 为以 command parameters["userContexts"] 尝试获取有效用户上下文所得的结果。

    2. 对于 user contexts 中的每个 user context

      1. 如果 maxTouchPoints 为 null,则从 session模拟 maxTouchPointsuser contexts移除 user context

      2. 否则,将 session模拟 maxTouchPointsuser contexts[user context] 设置maxTouchPoints

    3. 返回带有数据 null 的成功

  5. session模拟 maxTouchPointsdefault 设置为 maxTouchPoints

  6. 返回带有数据 null 的成功

7.5. network 模块

network 模块包含与网络请求相关的命令和事件。

7.5.1. 定义

远端定义

NetworkCommand = (
  network.AddDataCollector //
  network.AddIntercept //
  network.ContinueRequest //
  network.ContinueResponse //
  network.ContinueWithAuth //
  network.DisownData //
  network.FailRequest //
  network.GetData //
  network.ProvideResponse //
  network.RemoveDataCollector //
  network.RemoveIntercept //
  network.SetCacheBehavior //
  network.SetExtraHeaders
)

本地端定义

NetworkResult = (
  network.AddDataCollectorResult /
  network.AddInterceptResult /
  network.ContinueRequestResult /
  network.ContinueResponseResult /
  network.ContinueWithAuthResult /
  network.DisownDataResult /
  network.FailRequestResult /
  network.GetDataResult /
  network.ProvideResponseResult /
  network.RemoveDataCollectorResult /
  network.RemoveInterceptResult /
  network.SetCacheBehaviorResult /
  network.SetExtraHeadersResult
)

NetworkEvent = (
    network.AuthRequired //
    network.BeforeRequestSent //
    network.FetchError //
    network.ResponseCompleted //
    network.ResponseStarted
)

远端具有一个before request sent 映射,其初始为一个 空映射。它用于跟踪已经发送过 network.beforeRequestSent 事件的网络事件。

远端具有一个default cache behavior,它是一个字符串。其初始为 "default"。

远端具有一个navigable cache behavior 映射,它是 顶级 traversables与表示 cache behavior 的字符串之间的弱映射。其初始为空。

BiDi 会话具有extra headers,它是一个 结构体,带有 一个名为 default headers,其为一个 header list(初始设置为空 header list),一个名为 user context headers,其为 用户上下文header lists之间的弱映射,以及一个名为 navigable headers,其为 navigablesheader lists 之间的弱映射。

7.5.2. 网络数据收集

network data 是一个带有以下内容的结构体

collector 是一个带有以下内容的结构体

注:max encoded item size 定义每个项(响应或请求)的限制, 并不限制特定 collector 收集的大小。所有已收集资源的总大小 由 max total collected size 限制。

BiDi 会话具有network collectors, 它是 network.Collectorcollector 之间的映射。其初始为空。

远端具有collected network data,它是 network data 的列表。其初始 为空。

远端具有一个max total collected size,它是表示 在 collected network data 中分配给收集 network data 的大小的 js-uint。其值是实现定义的。

注:这允许实现设置资源使用限制。 这些限制预期足够大,以便用户可以依赖于 收集由浏览器完全解码和处理的数据, 例如网页上使用的图像和字体。

要在给定 request 的情况下获取 request 的 navigable
  1. navigable 为 null。

  2. 如果 requestclient 是一个环境设置对象

    1. environment settingsrequestclient

    2. 如果存在一个navigable,其活动 windowenvironment settings全局对象,则将 navigable 设置为该 navigable。

  3. 返回 navigable

要在给定 collectornavigable 的情况下匹配 navigable 的 collector
  1. 如果 collectorcontexts 不是

    1. 如果 collectorcontexts 包含 navigablenavigable id,则返回 true。

    2. 否则,返回 false。

  2. 如果 collectoruser contexts 不是

    1. user contextnavigable关联 用户上下文

    2. 如果 collectoruser contexts 包含 user context用户上下文 id,则返回 true。

    3. 否则,返回 false。

  3. 返回 true。

给定 request request 时,WebDriver BiDi 克隆网络请求 body步骤为:
  1. 如果 requestbody 为 null,则返回。

  2. 对于 活动 BiDi 会话中的每个 session

    1. 如果 sessionnetwork collectors 不是

      1. collected data 为一个network data,其中 bytes 设置为 null, cloned body 设置为 requestbody克隆collectors 设置为空列表, pending 设置为 true, request 设置为 requestrequest idsize 设置为 null, type 设置为 "request"。

      2. collected data 追加collected network data

      3. 返回。

给定 requestresponse body 时,WebDriver BiDi 克隆网络响应 body步骤为:
  1. 如果 response body 为 null,则返回。

  2. 对于 活动 BiDi 会话中的每个 session

    1. 如果 sessionnetwork collectors 不是

      1. collected data 为一个network data,其中 bytes 设置为 null, cloned body 设置为 response body克隆collectors 设置为空列表, pending 设置为 true, request 设置为 requestrequest idsize 设置为 null, type 设置为 "response"。

      2. collected data 追加collected network data

      3. 返回。

要在给定 request iddata type 的情况下获取 collected data
  1. 对于 collected network data 中的每个 collected data

    1. 如果 collected datarequestrequest id,且 collected datatypedata type,则返回 collected data

  2. 返回 null。

要在给定 request 的情况下可能中止网络响应 body 收集
  1. collected data 为以 requestrequest id 和 "response" 调用获取 collected data所得的结果。

  2. 如果 collected data 为 null,则返回。

  3. collected datapending 设置为 false。

  4. 用 "network data collected" 和 (requestrequest id, "response") 恢复

要在给定 request 的情况下可能 收集网络请求 body
  1. collected data 为以 requestrequest id 和 "request" 调用获取 collected data所得的结果。

  2. 如果 collected data 为 null,则返回。

    注:如果在创建请求时没有设置 collectors, 且 WebDriver BiDi 克隆网络请求 body未克隆对应的 body, 或者 body 一开始就是 null,则可能发生这种情况。

  3. requestcollected data、null 和 "request" 调用可能收集 network data

要在给定 requestresponse 的情况下可能 收集网络响应 body
  1. 如果 responsestatusredirect status,则返回。

    注:对于重定向,仅存储最终响应 body。

  2. collected data 为以 requestrequest id 和 "response" 调用获取 collected data所得的结果。

  3. 如果 collected data 为 null,则返回。

    注:如果在创建响应时没有设置 collectors, 且 WebDriver BiDi 克隆网络 响应 body未克隆对应的 body, 或者 body 一开始就是 null,则可能发生这种情况。

  4. sizeresponseresponse body infoencoded size

    注:从 fetch stream 检索的 bytes 对应于已解码数据这一事实与为了计算大小限制而使用编码(网络)大小之间存在差异。 实现可以决定使用这样的存储模型:只要在 getData 中返回给客户端的数据与已解码数据相同, 其使用的大小就可以小于存储已解码数据所需的大小。存储与性能之间的潜在 取舍由实现决定。

  5. requestcollected datasize 和 "response" 调用可能收集 network data

要在给定 request requestnetwork data collected data、js-uint sizenetwork.DataType data type 的情况下可能收集 network data
  1. collected datapending 设置为 false。

  2. navigable 为以 request 调用获取 request 的 navigable所得的结果。

  3. 如果 navigable 为 null:

    1. collected network data移除 collected data

    2. 用 "network data collected" 和 (requestrequest id, data type) 恢复

    3. 返回。

    这会阻止 收集与 navigable 无关的数据。 我们仍然需要检索 navigable 以对照 collector 配置进行检查,但这里仍可接受 null。

  4. top-level navigablenavigable顶级 traversable

  5. collectors 为空列表。

  6. 对于 活动 BiDi 会话中的每个 session

    1. 对于 sessionnetwork collectors 中的每个 collector

      1. 如果 collectordata types 包含 data type,且以 collectortop-level navigable 调用匹配 navigable 的 collector所得的结果为 true:

        1. collector 追加collectors

  7. 如果 collectors

    1. collected network data移除 collected data

    2. 用 "network data collected" 和 (requestrequest id, data type) 恢复

    3. 返回。

  8. bytes 为 null。

  9. 令给定 nullOrBytesprocessBody 为此步骤:

    1. 如果 nullOrBytes 不是 null:

      1. bytes 设置为用 nullOrBytes 调用序列化协议 bytes所得的结果。

      2. 如果 size 为 null,则将 size 设置为 bytes长度

  10. processBodyError 为此步骤:不执行任何操作。

  11. 给定 processBodyprocessBodyError完全读取 collected datacloned body

  12. 如果 bytes 不是 null:

    1. 对于 collectors 中的每个 collector

      1. 如果 size 小于或等于 collectormax encoded item size, 则将 collectorcollector 追加collected datacollectors

    2. 如果 collected datacollectors 不是

      1. 给定 size 分配大小以记录数据

      2. collected databytes 设置为 bytes

      3. collected datasize 设置为 size

    3. 否则,从 collected network data移除 collected data

  13. 用 "network data collected" 和 (requestrequest id, data type) 恢复

要在给定 size 的情况下分配 大小以记录数据
  1. available sizemax total collected size

  2. already collected data 为空列表。

  3. 对于 collected network data 中的每个 collected data

    1. 如果 collected databytes 不是 null:

      1. available size 减少 collected datasize

      2. collected data 追加already collected data

  4. 如果 size 大于 available size

    1. 对于 already collected data 中的每个 collected data

      1. available size 增加 collected datasize

      2. collected databytes 字段 设置为 null。

      3. collected datasize 字段设置为 null。

      4. 如果 available size 大于或等于 size,则返回。

要在给定 collected datacollector id 的情况下从数据中移除 collector
  1. 如果 collected datacollectors 包含 collector id

    1. collected datacollectors移除 collector id

    2. 如果 collected datacollectors

      1. collected network data移除 collected data

7.5.3. 网络拦截

网络拦截 是一种机制,允许远端拦截 并修改网络请求和响应。

BiDi 会话具有一个 拦截映射,它是 intercept id 与一个映射 之间的 结构体,该结构体带有字段 url patternsphasescontexts,定义活动网络拦截的属性。 其初始为空。

BiDi 会话具有一个 被阻塞请求 映射,用于跟踪 正在被主动阻塞的请求。它是 映射,位于 request id 和一个带有字段 requestphase 以及 response结构体 之间。其初始为空。

要在给定 sessioneventrequestnavigable id 的情况下获取 网络拦截

  1. session interceptssession拦截映射

  2. intercepts 为空列表。

  3. 运行第一个匹配条件下的步骤:

    event 为 "network.beforeRequestSent"
    phase 设置为 "beforeRequestSent"。
    event 为 "network.responseStarted"
    phase 设置为 "responseStarted"。
    event 为 "network.authRequired"
    phase 设置为 "authRequired"。
    event 为 "network.responseCompleted"
    返回 intercepts
  4. url 为以 requestURL 运行 URL 序列化器所得的结果。

  5. 对于 session intercepts 中的每个 intercept idintercept

    1. 如果 interceptcontexts 不是 null:

      1. 如果 interceptcontexts包含 navigable id

        1. 继续。

    2. 如果 interceptphases 包含 phase

      1. url patternsintercepturl patterns

      2. 如果 url patterns

        1. intercept id 追加intercepts

        2. 继续。

      3. 对于 url patterns 中的每个 url pattern

        1. 如果以 url patternurl 调用匹配 URL pattern

          1. intercept id 追加intercepts

          2. 中断。

  6. 返回 intercepts

要在给定 sessioncommandcommand parameters 的情况下更新 response
  1. blocked requestssession被阻塞请求映射

  2. request idcommand parameters["request"]。

  3. 如果 blocked requests包含 request id,则返回带有错误 代码 no such request错误

  4. 令 (request, phase, response) 为 blocked requests[request id]。

  5. 如果 phase 为 "beforeRequestSent" 且 command 为 "continueResponse",则返回带有错误代码 "invalid argument" 的错误

    TODO:考虑不同的错误

  6. 如果 response 为 null:

    1. 断言:phase 为 "beforeRequestSent"。

    2. response 设置为一个新的response

  7. 如果 command parameters 包含 "statusCode":

    1. responsesstatus 设置为 command parameters["statusCode"]。

  8. 如果 command parameters 包含 "reasonPhrase":

    1. responsesstatus message 设置为以 command parameters["reasonPhrase"] 调用UTF-8 encode所得的结果。

  9. 如果 command parameters 包含 "headers":

    1. headers 为以 command parameters["headers"] 尝试创建 headers list所得的结果。

    2. responseheader list设置为 headers

  10. 如果 command parameters 包含 "cookies":

    1. 如果 command parameters 包含 "headers",令 headersresponseheader list

      否则:

      1. headers 为空 header list

      2. 对于 responseheaders list中的每个 header

        1. nameheader 的 name。

        2. 如果 namebyte-lowercase 不是 `set-cookie`:

          1. header 追加到 headers

    2. 对于 command parameters["cookies"] 中的 cookie

      1. header value 为以 cookie 调用序列化 set-cookie header所得的结果。

      2. 将 (`Set-Cookie`, header value) 追加到 headers

      3. responseheader list设置为 headers

  11. 如果 command parameters 包含 "credentials":

    这没有 取消 auth 的方式。

    1. credentialscommand parameters["credentials"]。

    2. 断言:credentials["type"] 为 "password"。

    3. response 的认证凭据设置为 (credentials["username"], credentials["password"])

  12. 返回 response

7.5.4. 类型

7.5.4.1. network.AuthChallenge 类型
network.AuthChallenge = {
  scheme: text,
  realm: text,
}

要在给定 response 的情况下提取 challenges

是否应包含 realm 之外的参数?

  1. 如果 responsestatus 为 401,则令 header name 为 `WWW-Authenticate`。否则,如果 responsestatus 为 407,则令 header name 为 `Proxy-Authenticate`。否则返回 null。

  2. challenges 为一个新的列表

  3. 对于 responseheader list中的每个 (name, value):

    与 Fetch 中一样, 尚不清楚这是否是处理多个 headers、解析问题等的正确方式。

    1. 如果 nameheader name 按字节大小写不敏感匹配:

      1. header challenges 为将 value 解析为 challenges 列表的结果,每个 challenge 由一个 scheme 和一个参数列表组成, 每个参数均为元组 (name, value),按照 [RFC9110] 的规则解析。

      2. 对于 header challenges 中的每个 header challenge

        1. schemeheader challenge 的 scheme。

        2. realm 为空字符串。

        3. 对于 header challenge 的 parameters 中的每个 (param name, param value):

          1. 如果 param name 等于 `realm`,则令 realm 为 对 param value 进行UTF-8 decode所得的结果。

        4. challenge 为一个新的映射,匹配 network.AuthChallenge 产生式,其中 scheme 字段设置为 scheme,且 realm 字段设置为 realm

      3. challenge 追加challenges

  4. 返回 challenges

7.5.4.2. network.AuthCredentials 类型
network.AuthCredentials = {
  type: "password",
  username: text,
  password: text,
}

network.AuthCredentials 类型表示对授权凭据请求的响应。

7.5.4.3. network.BaseParameters 类型
network.BaseParameters = (
    context: browsingContext.BrowsingContext / null,
    isBlocked: bool,
    navigation: browsingContext.Navigation / null,
    redirectCount: js-uint,
    request: network.RequestData,
    timestamp: js-uint,
    ? userContext: browser.UserContext / null,
    ? intercepts: [+network.Intercept]
)

network.BaseParameters 类型是一个抽象类型,表示 所有网络事件共有的数据。

考虑除 context 之外, 还包含发起请求的 document 节点的 `sharedId`。

要在给定 sessioneventrequest 的情况下处理 network event
  1. request data 为以 request 调用获取 request data所得的结果。

  2. navigationrequestnavigation id

  3. navigable id 为 null。

  4. top-level navigable id 为 null。

  5. user context id 为 null。

  6. 如果 requestclient 是一个环境设置对象

    1. environment settingsrequestclient

    2. 如果存在一个navigable,其活动 windowenvironment settings全局对象,则将 navigable id 设置为该 navigable 的navigable id,将 top-level navigable id 设置为 该 navigable 的顶级 traversablenavigable id,并 将 user context id 设置为该 navigable 的 关联用户上下文用户上下文 id

  7. intercepts 为以 sessioneventrequesttop-level navigable id 调用获取网络 拦截所得的结果。

  8. redirect countrequestredirect count

  9. timestamp 为一个时间值,表示 UTC 中的当前日期 和时间。

  10. 如果 intercepts 不是,则令 is blocked 为 true,否则 令 is blocked 为 false。

  11. params映射, 匹配 network.BaseParameters 产生式,其中 request 字段设置为 request datanavigation 字段设置为 navigationcontext 字段设置为 navigable iduserContext 字段设置为 user context idtimestamp 字段设置为 timestampredirectCount 字段设置为 redirect countisBlocked 字段设置为 is blocked,且如果 is blocked 为 true, 则 intercepts 字段设置为 intercepts,否则省略。

  12. 返回 params

7.5.4.4. network.BytesValue 类型
network.BytesValue = network.StringValue / network.Base64Value;

network.StringValue = {
  type: "string",
  value: text,
}

network.Base64Value = {
  type: "base64",
  value: text,
}

network.BytesValue 类型表示通过网络发送的二进制数据。有效的 UTF-8 用 network.StringValue 类型表示,任何其他数据均以 Base64 编码形式表示为 network.Base64Value

要在给定 protocol bytes 的情况下反序列化 协议 bytes

注:这接收编码为 network.BytesValue 的 bytes,并返回 字节序列

  1. 如果 protocol bytes 匹配 network.StringValue 产生式, 则令 bytes 为对 protocol bytes["value"] 进行 UTF-8 encode所得的结果。

  2. 否则,如果 protocol bytes 匹配 network.Base64Value 产生式。令 bytes 为对 protocol bytes["value"] 进行forgiving-base64 decode所得的结果。

  3. 返回 bytes

要在给定 bytes 的情况下序列化 协议 bytes

注:这接收一个字节序列 并返回一个 network.BytesValue

  1. text 为对 bytes 进行UTF-8 decode without BOM or fail所得的结果。

  2. 如果 text 为 failure,则返回一个匹配 network.Base64Value 产生式的映射, 其中 value 设置为以 bytes 调用 forgiving-base64 encode所得的结果。

  3. 返回一个匹配 network.StringValue 产生式的映射, 其中 value 设置为 text

7.5.4.5. network.Collector 类型

远端定义本地端定义

network.Collector = text

network.Collector 类型表示一个 collector 的 id。

7.5.4.6. network.CollectorType 类型

远端定义本地端定义

network.CollectorType = "blob"

注:未来我们也可能支持 "stream" collector type,供希望通过流读取给定 collector 所收集数据的客户端使用。

network.CollectorType 类型表示可以添加的不同类型的数据收集器。

远端定义本地端定义

network.SameSite = "strict" / "lax" / "none" / "default"


network.Cookie = {
    name: text,
    value: network.BytesValue,
    domain: text,
    path: text,
    size: js-uint,
    httpOnly: bool,
    secure: bool,
    sameSite: network.SameSite,
    ? expiry: js-uint,
    Extensible,
}

network.Cookie 类型表示一个 cookie。

要在给定 stored cookie 的情况下序列化 cookie
  1. name 为以 stored cookie 的 name 字段调用UTF-8 decode所得的结果。

  2. value 为以 stored cookie 的 value 调用序列化协议 bytes所得的结果。

  3. domainstored cookie 的 domain 字段。

  4. pathstored cookie 的 path 字段。

  5. expirystored cookie 的 expiry-time 字段,表示为 unix timestamp(如果已设置);否则为 null。

  6. size 为将 stored cookie 按其在 Cookie header 中的表示方式序列化所得结果的字节长度。

  7. 如果 stored cookie 的 http-only-flag 为 true,则令 http only 为 true; 否则为 false。

  8. 如果 stored cookie 的 secure-only-flag 为 true,则令 secure 为 true; 否则为 false。

  9. 如果 stored cookie 的 same-site-flag 为 "None",则令 same site 为 "none";如果为 "Lax",则为 "lax"; 如果为 "Strict",则为 "strict";如果为 "Default",则为 "default"

  10. 返回一个匹配 network.Cookie 产生式的映射, 其中 name 字段设置为 namevalue 字段 设置为 valuedomain 字段设置为 domainpath 字段设置为 path,如果 expiry 不是 null,则 expiry 字段设置为 expiry,否则省略;size 字段 设置为 sizehttpOnly 字段设置为 http onlysecure 字段设置为 secure,且 sameSite 字段设置为 same site

7.5.4.8. network.CookieHeader 类型

远端定义

network.CookieHeader = {
    name: text,
    value: network.BytesValue,
}

network.CookieHeader 类型表示 Cookie 请求 header 中的 cookie 数据子集。

要在给定 protocol cookie 的情况下序列化 cookie header
  1. name 为对 protocol cookie["name"] 进行UTF-8 encode所得的结果。

  2. value 为以 protocol cookie["value"] 调用反序列化协议 bytes所得的结果。

  3. header value 为通过连接 name、 `=` 和 value 形成的字节 序列

  4. 返回 header value

7.5.4.9. network.DataType 类型

远端定义本地端定义

network.DataType = "request" / "response"

network.DataType 类型表示可以收集的不同类型的网络数据。

7.5.4.10. network.FetchTimingInfo 类型

远端定义本地端定义

network.FetchTimingInfo = {
    timeOrigin: float,
    requestTime: float,
    redirectStart: float,
    redirectEnd: float,
    fetchStart: float,
    dnsStart: float,
    dnsEnd: float,
    connectStart: float,
    connectEnd: float,
    tlsStart: float,

    requestStart: float,
    responseStart: float,

    responseEnd: float,
}

network.FetchTimingInfo 类型表示请求各个部分的时间, 相对于 时间原点,该时间原点属于requestclient

要在给定 request 的情况下获取 fetch timings
  1. globalrequestclient

  2. 如果 global 为 null,则返回一个匹配 network.FetchTimingInfo 产生式的映射,所有字段均设置为 0。

  3. time origin 为以 global 调用获取时间原点时间戳所得的结果。

  4. timingsrequestfetch timing info

  5. 如果 timingsfinal connection timing info 不为 null,则令 connection timing 为它,否则令其为一个新的connection timing info

  6. request time 为给定 timingsstart timeglobal,调用转换 fetch 时间戳所得的结果。

  7. redirect start 为给定 timingsredirect start timeglobal,调用转换 fetch 时间戳所得的结果。

  8. redirect end 为给定 timingsredirect end timeglobal,调用转换 fetch 时间戳所得的结果。

  9. fetch start 为给定 timingspost-redirect start timeglobal,调用转换 fetch 时间戳所得的结果。

  10. DNS start 为给定 connection timingdomain lookup start timeglobal,调用转换 fetch 时间戳所得的结果。

  11. DNS end 为给定 connection timingdomain lookup end timeglobal,调用转换 fetch 时间戳所得的结果。

  12. TLS start 为给定 connection timingsecure connection start timeglobal,调用转换 fetch 时间戳所得的结果。

  13. connect start 为给定 connection timingconnection start timeglobal,调用转换 fetch 时间戳所得的结果。

  14. connect end 为给定 connection timingconnection end timeglobal,调用转换 fetch 时间戳所得的结果。

  15. request start 为给定 timingsfinal network-request start timeglobal,调用转换 fetch 时间戳所得的结果。

  16. response start 为给定 timingsfinal network-response start timeglobal,调用转换 fetch 时间戳所得的结果。

  17. response end 为给定 timingsend timeglobal,调用转换 fetch 时间戳所得的结果。

  18. 返回一个匹配 network.FetchTimingInfo 产生式的映射, 其中 timeOrigin 字段设置为 time originrequestTime 字段设置为 request timeredirectStart 字段设置为 redirect startredirectEnd 字段设置为 redirect endfetchStart 字段设置为 fetch startdnsStart 字段设置为 DNS startdnsEnd 字段设置为 DNS endconnectStart 字段设置为 connect startconnectEnd 字段设置为 connect endtlsStart 字段设置为 TLS startrequestStart 字段设置为 request startresponseStart 字段设置为 response start,并且 responseEnd 字段设置为 response end

TODO:添加 service worker 字段

7.5.4.11. network.Header 类型

远端定义本地端定义

network.Header = {
  name: text,
  value: network.BytesValue,
}

network.Header 类型表示单个请求 header。

要在给定 name bytesvalue bytes 的情况下序列化 header
  1. name 为以 name bytes 调用UTF-8 解码所得的结果。

    断言:由于 header 名称被约束为仅 ASCII,因此这不会失败。

  2. value 为以 value bytes 调用序列化协议 bytes所得的结果。

  3. 返回一个匹配 network.Header 产生式的映射,其中 name 字段设置为 name,并且 value 字段 设置为 value

要在给定 protocol header 的情况下反序列化 header
  1. name 为对 protocol header["name"] 进行UTF-8 编码所得的结果。

  2. value 为以 protocol header["value"] 调用反序列化协议 bytes所得的结果。

  3. 返回一个headername, value)。

要在给定 protocol headers 的情况下创建 headers list
  1. headers 为空header list

  2. 对于 protocol headers 中的每个 header

    1. deserialized header 为以 header 调用反序列化 header所得的结果。

    2. 如果 deserialized header 的 name 不匹配field-name token 产生式,则返回带有错误代码 "invalid argument" 的错误

    3. 如果 deserialized header 的 value 不匹配header value 产生式,则返回带有错误代码 "invalid argument" 的错误

    4. deserialized header 追加到 headers

  3. 返回带有数据 headers成功

7.5.4.12. network.Initiator 类型

远端定义本地端定义

network.Initiator = {
    ? columnNumber: js-uint,
    ? lineNumber: js-uint,
    ? request: network.Request,
    ? stackTrace: script.StackTrace,
    ? type: "parser" / "script" / "preflight" / "other"
}

network.Initiator 类型表示网络请求的来源。

注:type 字段被包含在 定义中是为了向后兼容,但它不再由获取 initiator 步骤设置,并且会在此规范的未来修订版中 移除。预期它的用途会由 network.RequestData 上的 initiatorTypedestination 取代。

注:request 字段被包含在 定义中是为了向后兼容,但它不再由获取 initiator 步骤设置,并且会 在此规范的未来修订版中移除。 network.Initiator 被包含在 network.BeforeRequestSentParameters 中,后者也包含相同的 request id,使得此信息变得冗余。参见 § 7.5.4.3 network.BaseParameters 类型

要在给定 request 的情况下获取 initiator
  1. 如果 requestinitiator type 是 "fetch" 或 "xmlhttprequest":

    1. stack trace当前 stack trace

    2. 如果 stack trace 的大小为 1 或更大,则令 line numberstack trace[0] 中 lineNumber 字段的值,并令 column numberstack trace[0] 中 columnNumber 字段的值。否则 令 line numbercolumn number 为 0。

    否则,令 stack tracecolumn numberline number 均为 null。

    TODO:对于 parser 插入的资源,Chrome 会将当前解析器位置作为 column number / line number。

  2. 返回一个匹配 network.Initiator 产生式的映射, 如果 column number 不为 null,则将 columnNumber 字段设置为 column number,否则省略; 如果 line number 不为 null,则将 lineNumber 字段设置为 line number,否则省略;并且如果 stack trace 不为 null,则将 stackTrace 字段设置为 stack trace,否则省略。

7.5.4.13. network.Intercept 类型

远端定义本地端定义

network.Intercept = text

network.Intercept 类型表示network intercept 的 id。

7.5.4.14. network.Request 类型

远端定义本地端定义

network.Request = text;

每个网络请求都有一个关联的request id,它是一个 唯一标识该请求的字符串。由重定向产生的请求的标识符与发起它的请求的标识符匹配。

7.5.4.15. network.RequestData 类型

远端定义本地端定义

network.RequestData = {
    request: network.Request,
    url: text,
    method: text,
    headers: [*network.Header],
    cookies: [*network.Cookie],
    headersSize: js-uint,
    bodySize: js-uint / null,
    destination: text,
    initiatorType: text / null,
    timings: network.FetchTimingInfo,
}

network.RequestData 类型表示一个进行中的网络请求。

要在给定 request 的情况下获取请求 数据

  1. request id 为 request 的request id

  2. url 为以 requestURL 调用URL 序列化器所得的结果。

  3. methodrequestmethod

  4. body size 为 null。

  5. body 为 request 的body

  6. 如果 body字节 序列,则将 body size 设置为该序列的长度。否则,如果 bodybody,则 将 body size 设置为该 body 的长度

  7. headers sizerequestheaders list 按照 [HTTP11] 要求序列化时的字节大小。

    注:对于允许 header 压缩的协议,这是通过网络发送时 headers 的压缩后大小。

  8. headers 为空列表。

  9. cookies 为空列表。

  10. 对于 requestheaders list 中的每个 (name, value):

    1. 将以 namevalue 调用序列化 header所得的结果追加到 headers

    2. 如果 name 与 "Cookie" 为字节大小写不敏感匹配,则:

      1. 对于用户代理的cookie store 中被包含在 request 中的每个 cookie

        注:[COOKIES] 定义了存储中哪些 cookie 可以包含在请求中的一些基线要求,但用户代理可以自由地 施加额外约束。

        1. 将给定 cookie 调用序列化 cookie所得的结果追加到 cookies

  11. destinationrequestdestination

  12. initiator typerequestinitiator type

  13. timings 为以 request 调用获取 fetch timings所得的结果。

  14. 返回一个匹配 network.RequestData 产生式的映射,其中 request 字段设置为 request idurl 字段 设置为 urlmethod 字段设置为 methodheaders 字段设置为 headerscookies 字段设置为 cookiesheadersSize 字段设置为 headers sizebodySize 字段设置为 body sizedestination 字段设置为 destinationinitiatorType 字段设置为 initiator type,并且 timings 字段设置为 timings

7.5.4.16. network.ResponseContent 类型

远端定义本地端定义

network.ResponseContent = {
    size: js-uint
}

network.ResponseContent 类型表示对网络请求的已解码响应。

要在给定 response 的情况下获取 response content info
  1. 返回一个匹配 network.ResponseContent 产生式的新映射,其中 size 字段设置为 responseresponse body infodecoded size

7.5.4.17. network.ResponseData 类型

远端定义本地端定义

network.ResponseData = {
    url: text,
    protocol: text,
    status: js-uint,
    statusText: text,
    fromCache: bool,
    headers: [*network.Header],
    mimeType: text,
    bytesReceived: js-uint,
    headersSize: js-uint / null,
    bodySize: js-uint / null,
    content: network.ResponseContent,
    ?authChallenges: [*network.AuthChallenge],
}

network.ResponseData 类型表示对网络请求的响应。

要在给定 response 的情况下获取 protocol

  1. protocol 为空字符串。

  2. 如果 responsefinal connection timing info 不为 null,则将 protocol 设置为 responsefinal connection timing infoALPN negotiated protocol

  3. 如果 protocol 是空字符串,或等于 "unknown":

    1. protocol 设置为 responseurlscheme

    2. 如果 protocol 等于 "http" 或 "https",并且 response 具有关联的 HTTP Response。

      注:[FETCH] 未明确说明 HTTP 网络响应与 response 对象之间的关系。

      1. http version 为 HTTP Response 的状态行中的 HTTP-version [HTTP11]

      2. 如果 http version 以 "HTTP/" 开头:

        1. versionhttp version 从 5 到 http version长度之间的码元子字符串

        2. 如果 version 是 "0.9",则将 protocol 设置为 "http/0.9";否则如果 version 是 "1.0", 则将 protocol 设置为 "http/1.0";否则如果 version 是 "1.1",则将 protocol 设置为 "http/1.1"。

  4. 返回 protocol

要在给定 response 的情况下获取 response data
  1. url 为以 responseURL 调用URL 序列化器所得的结果。

  2. protocol 设置为给定 response 调用获取 protocol所得的结果。

  3. statusresponsestatus

  4. status textresponsestatus message

  5. 如果 responsecache state 是 "local", 则令 from cache 为 true,否则令其为 false。

  6. headers 为空列表。

  7. mime typeresponse计算 MIME 类型实质

    注:这就是浏览器实际使用的 MIME 类型, 即使它没有遵循 [MIMESNIFF] 规范中的确切算法。

  8. 对于 responseheaders list 中的每个 (name, value):

    1. 将以 namevalue 调用序列化 header所得的结果追加到 headers

  9. bytes received 为作为与 response 关联的 HTTP 响应的一部分传输的总字节数。

  10. headers size 为作为 HTTP 响应的 header fields section 的一部分传输的字节数。

  11. body sizeresponseresponse body infoencoded size

  12. content 为以 response 调用获取 response content info所得的结果。

  13. auth challenges 为以 response 调用提取 challenges所得的结果。

  14. 返回一个匹配 network.ResponseData 产生式的映射, 其中 url 字段设置为 urlprotocol 字段 设置为 protocolstatus 字段设置为 statusstatusText 字段设置为 status textfromCache 字段设置为 from cacheheaders 字段设置为 headersmimeType 字段设置为 mime typebytesReceived 字段设置为 bytes receivedheadersSize 字段设置为 headers sizebodySize 字段设置为 body sizecontent 字段设置为 content,并且如果 auth challenges 不为 null, 则将 authChallenges 字段设置为 auth challenges,否则省略。

7.5.4.18. network.SetCookieHeader 类型

远端定义

network.SetCookieHeader = {
    name: text,
    value: network.BytesValue,
    ? domain: text,
    ? httpOnly: bool,
    ? expiry: text,
    ? maxAge: js-int,
    ? path: text,
    ? sameSite: network.SameSite,
    ? secure: bool,
}

network.SetCookieHeader 表示 Set-Cookie 响应 header 中的数据。

要在给定作为整数的 input 的情况下序列化 整数

注:这会生成 input 作为十进制数字字符串的最短表示。

  1. serialized 为空字符串。

  2. valueinput

  3. value 大于 0 时:

    1. xvalue 除以 10。

    2. most significant digitsx 的整数部分。

    3. ymost significant digits 乘以 10。

    4. least significant digitvalue - y

    5. 断言:least significant digit 是 0 到 9(含)范围内的整数。

    6. codepoint 为一个码 点,其为 U+0030 DIGIT ZERO 的 + least significant digit

    7. codepoint 前置到 serialized

    8. value 设置为 most significant digits

  4. 返回 serialized

要在给定 protocol cookie 的情况下序列化 set-cookie header
  1. name 为对 protocol cookie["name"] 进行UTF-8 编码所得的结果。

  2. value 为以 protocol cookie["value"] 调用反序列化协议 bytes所得的结果。

  3. header value 为通过连接 name、 `=` 和 value 形成的字节 序列

  4. 如果 protocol cookie 包含 "expiry":

    1. attribute 为 `;Expires=`

    2. protocol cookie["expiry"] 的UTF-8 编码追加到 attribute

    3. attribute 追加到 header value

  5. 如果 protocol cookie 包含 "maxAge":

    1. attribute 为 `;Max-Age=`

    2. max age string 为对 protocol cookie["maxAge"] 调用序列化整数所得的结果。

    3. max age stringUTF-8 编码追加到 attribute

    4. attribute 追加到 header value

  6. 如果 protocol cookie 包含 "domain":

    1. attribute 为 `;Domain=`

    2. protocol cookie["domain"] 的UTF-8 编码追加到 attribute

    3. attribute 追加到 header value

  7. 如果 protocol cookie 包含 "path":

    1. attribute 为 `;Path=`

    2. protocol cookie["path"] 的UTF-8 编码追加到 attribute

    3. attribute 追加到 header value

  8. 如果 protocol cookie 包含 "secure" 且 protocol cookie["secure"] 为 true:

    1. 将 `;Secure` 追加到 header value

  9. 如果 protocol cookie 包含 "httpOnly" 且 protocol cookie["httpOnly"] 为 true:

    1. 将 `;HttpOnly` 追加到 header value

  10. 如果 protocol cookie 包含 "sameSite":

    1. attribute 为 `;SameSite=`

    2. protocol cookie["sameSite"] 的UTF-8 编码追加到 attribute

    3. attribute 追加到 header value

  11. 返回 header value

7.5.4.19. network.UrlPattern 类型

远端定义

network.UrlPattern = (
  network.UrlPatternPattern /
  network.UrlPatternString
)

network.UrlPatternPattern = {
    type: "pattern",
    ?protocol: text,
    ?hostname: text,
    ?port: text,
    ?pathname: text,
    ?search: text,
}


network.UrlPatternString = {
    type: "string",
    pattern: text,
}

network.UrlPattern 表示用于为网络 拦截匹配请求 URL 的模式。

当 URL 与 network.UrlPattern 匹配时,会解析该 URL, 并在模式中存在对应字段时,将每个组成部分与该字段按相等性进行比较。 模式中缺失的字段始终匹配。

注:此语法在设计时考虑了未来的可扩展性。 特别是,该语法禁止在 [URLPattern] 规范中被特殊处理的字符。这些字符可以通过在其前面加上 U+005C (\) 字符进行转义。

要在给定 pattern 的情况下反转义 URL pattern
  1. forbidden characters 为码点 «U+0028 ((), U+0029 ()), U+002A (*), U+007B ({), U+007D (})» 的集合

  2. result 为空字符串。

  3. is escaped character 为 false。

  4. 对于 pattern 中的每个 codepoint

    1. 如果 is escaped character 为 false:

      1. 如果 forbidden characters 包含 codepoint,则返回带有错误代码 invalid argument错误

      2. 如果 codepoint 是 U+005C (\):

        1. is escaped character 设置为 true。

        2. 继续。

    2. codepoint 追加到 result。

    3. is escaped character 设置为 false。

  5. 返回带有数据 result成功

要在给定 pattern 的情况下解析 URL pattern
  1. has protocol 为 true。

  2. has hostname 为 true。

  3. has port 为 true。

  4. has pathname 为 true。

  5. has search 为 true。

  6. 如果 pattern 匹配 network.UrlPatternPattern 产生式:

    1. pattern url 为空字符串。

    2. 如果 pattern 包含 "protocol":

      1. 如果 pattern["protocol"] 是空字符串,则返回带有错误代码 invalid argument错误

      2. protocol尝试pattern["protocol"] 调用反转义 URL Pattern所得的结果。

      3. 对于 protocol 中的每个 codepoint

        1. 如果 codepoint 不是 ASCII 字母数字,且 «U+002B (+), U+002D (-), U+002E (.)» 不包含 codepoint

          1. 返回带有错误代码 invalid argument 的错误

      4. protocol 追加到 pattern url

    3. 否则:

      1. has protocol 设置为 false。

      2. 将 "http" 追加到 pattern url

    4. scheme 为以 pattern url 调用ASCII 小写化所得的结果。

    5. 将 ":" 追加到 pattern url

    6. 如果 scheme 为 special,则将 "//" 追加到 pattern url

    7. 如果 pattern 包含 "hostname":

      1. 如果 pattern["hostname"] 是空字符串,则返回带有错误代码 invalid argument错误

      2. 如果 scheme 是 "file",则返回带有错误代码 invalid argument错误

      3. hostname尝试pattern["hostname"] 调用反转义 URL Pattern所得的结果。

      4. inside brackets 为 false。

      5. 对于 hostname 中的每个 codepoint

        1. 如果 «U+002F (/), U+003F (?), U+0023 (#)» 包含 codepoint

          1. 返回带有错误代码 invalid argument错误

        2. 如果 inside brackets 为 false 且 codepoint 是 U+003A (:):

          1. 返回带有错误代码 invalid argument错误

        3. 如果 codepoint 是 U+005B ([),则将 inside brackets 设置为 true。

        4. 如果 codepoint 是 U+005D (]),则将 inside brackets 设置为 false。

      6. hostname 追加到 pattern url

    8. 否则:

      1. 如果 scheme 不是 "file",则将 "placeholder" 追加到 pattern url

      2. has hostname 设置为 false。

    9. 如果 pattern 包含 "port":

      1. 如果 pattern["port"] 是空字符串,则返回带有错误代码 invalid argument错误

      2. port尝试pattern["port"] 调用反转义 URL Pattern所得的结果。

      3. 将 ":" 追加到 pattern url

      4. 对于 port 中的每个 codepoint

        1. 如果 codepoint 不是 ASCII 数字

          1. 返回带有错误代码 invalid argument错误

      5. port 追加到 pattern url

    10. 否则:

      1. has port 设置为 false。

    11. 如果 pattern 包含 "pathname":

      1. pathname尝试pattern["pathname"] 调用反转义 URL Pattern所得的结果。

      2. 如果 pathname 不是以 U+002F (/) 开头,则 将 "/" 追加到 pattern url

      3. 对于 pathname 中的每个 codepoint

        1. 如果 «U+003F (?), U+0023 (#)» 包含 codepoint

          1. 返回带有错误代码 invalid argument错误

      4. pathname 追加到 pattern url

    12. 否则:

      1. has pathname 设置为 false。

    13. 如果 pattern 包含 "search":

      1. search尝试pattern["search"] 调用反转义 URL pattern所得的结果。

      2. 如果 search 不是以 U+003F (?) 开头,则 将 "?" 追加到 pattern url

      3. 对于 search 中的每个 codepoint

        1. 如果 codepoint 是 U+0023 (#):

          1. 返回带有错误代码 invalid argument错误

      4. search 追加到 pattern url

    14. 否则:

      1. has search 设置为 false。

  7. 否则,如果 pattern 匹配 network.UrlPatternString 产生式:

    1. pattern url尝试pattern["pattern"] 调用反转义 URL pattern所得的结果。

  8. url解析 pattern url 所得的结果。

  9. 如果 url 是 failure,则返回带有错误代码 invalid argument错误

  10. parsed 为具有以下字段的结构体:

    protocol
    如果 has protocol 为 true,则为 urlscheme;否则为 null。
    hostname
    如果 has hostname 为 true,则为 urlhost;否则为 null。
    port
    1. 如果 has port 为 false:

      1. null。

    2. 否则:

      1. 如果 urlscheme 为 special,且 urlscheme默认端口不为 null,并且 urlport 为 null 或 等于 scheme默认端口

        1. 空字符串。

      2. 否则,如果 urlport 不为 null:

        1. urlport 调用序列化整数

      3. 否则:

        1. null。

    pathname
    1. 如果 has pathname 为 false:

      1. null。

    2. 否则:

      1. 如果 urlpath 不是空字符串且 不是, 则为以 url 调用URL path 序列化器所得的结果; 否则为 null。

    search
    1. 如果 has search 为 false:

      1. null。

    2. 否则:

      1. 如果 urlquery 为 null,则为空字符串; 否则为 urlquery

  11. 返回带有数据 parsed成功

要在给定 url patternurl string 的情况下匹配 URL pattern
  1. url解析 url string 所得的结果。

  2. 如果 url pattern 的 protocol 不为 null 且不等于 urlscheme,则返回 false。

  3. 如果 url pattern 的 hostname 不为 null 且不等于 urlhost,则返回 false。

  4. 如果 url pattern 的 port 不为 null:

    1. port 为 null。

    2. 如果 urlscheme 为 special,且 urlscheme默认 port不为 null,并且 urlport 为 null 或等于 scheme默认 port

      1. port 设置为空字符串。

    3. 否则,如果 urlport 不为 null:

      1. port 设置为以 urlport 调用序列化整数所得的结果。

    4. 如果 url pattern 的 port 不等于 port,则返回 false。

  5. 如果 url pattern 的 pathname 不为 null,且不等于 以 url 运行URL path 序列化器的结果,则返回 false。

  6. 如果 url pattern 的 search 不为 null:

    1. url queryurlquery

    2. 如果 url query 为 null,则将 url query 设置为空字符串。

    3. 如果 url pattern 的 search 不等于 url query,则返回 false。

  7. 返回 true。

7.5.5. 命令

7.5.5.1. network.addDataCollector 命令

network.addDataCollector 会添加一个 collector

命令类型
network.AddDataCollector = (
  method: "network.addDataCollector",
  params: network.AddDataCollectorParameters
)

network.AddDataCollectorParameters = {
  dataTypes: [+network.DataType],
  maxEncodedDataSize: js-uint,
  ? collectorType: network.CollectorType .default "blob",
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
network.AddDataCollectorResult = {
  collector: network.Collector
}
给定 sessioncommand parameters 时,远端步骤为:
  1. collector idUUID 的字符串表示。

  2. input context ids 为空集合

  3. 如果 command parameterscontexts 字段存在, 则将 input context ids 设置为用 command parameters[contexts] 创建集合

  4. data types 为用 command parameters["dataTypes"] 创建集合

  5. max encoded item sizecommand parameters ["maxEncodedDataSize"]。

    注:maxEncodedDataSize 参数表示 max encoded item size,并限制由给定 collector 收集的每个请求的大小,而不是该 collector 收集到的数据总大小。

    注:不同实现可能支持不同编码,这意味着 编码后的大小可能在不同浏览器之间不同。因此,对于同一个数据 collector 配置,某些网络数据可能只在某些实现中适合 max encoded item size

  6. collector typecommand parameters ["collectorType"]。

  7. input user context ids 为空集合

  8. 如果 command parametersuserContexts 字段存在, 则将 input user context ids 设置为用 command parameters[userContexts] 创建集合

  9. 如果 input user context ids 非空且 input context ids 非空, 则返回带有错误 代码 invalid argument错误

  10. 如果 max encoded item size 为 0,或 max encoded item size 大于 max total collected size,则返回带有错误 代码 invalid argument错误

  11. 如果 input context ids 不是

    1. navigables尝试input context ids 调用通过 id 获取有效 navigables所得的结果。

    2. 对于 navigables 中的每个 navigable

      1. 如果 navigable 不是顶级 traversable,则返回带有错误代码 invalid argument错误

  12. 否则,如果 input user context ids 不是

    1. 对于 input user context ids 的每个 user context id

      1. user context 为以 user context id 调用获取用户上下文所得的结果。

      2. 如果 user context 为 null,则返回带有错误代码 no such user context错误

  13. collector 为一个collector,其 max encoded item size 字段设置为 max encoded item sizedata types 字段设置为 data typescollector 字段设置为 collector idcollector type 字段设置为 collector typecontexts 字段设置为 input context idsuser contexts 字段设置为 input user context ids

  14. sessionnetwork collectors[collector id] 设置为 collector

  15. 返回一个新的映射,其匹配 network.AddDataCollectorResult 产生式,并且 collector 字段设置为 collector id

7.5.5.2. network.addIntercept 命令

network.addIntercept 命令会添加一个 网络拦截

命令类型
network.AddIntercept = (
  method: "network.addIntercept",
  params: network.AddInterceptParameters
)

network.AddInterceptParameters = {
  phases: [+network.InterceptPhase],
  ? contexts: [+browsingContext.BrowsingContext],
  ? urlPatterns: [*network.UrlPattern],
}

network.InterceptPhase = "beforeRequestSent" / "responseStarted" /
                         "authRequired"
返回类型
network.AddInterceptResult = {
  intercept: network.Intercept
}
给定 sessioncommand parameters 时,远端步骤为:
  1. interceptUUID 的字符串表示。

  2. url patternscommand parametersurlPatterns 字段(如果存在),否则为空列表

  3. navigables 为 null。

  4. 如果 command parameterscontexts 字段存在:

    1. navigables 设置为空集合

    2. 对于 command parameters["contexts"] 的每个 navigable id

      1. navigable尝试navigable id 调用获取 navigable 所得的结果。

      2. 如果 navigable 不是顶级 traversable,则返回带有错误代码 invalid argument错误

      3. navigable 追加到 navigables

    3. 如果 navigables 是空集合,则返回带有 错误代码 invalid argument错误

  5. intercept mapsessionintercept map

  6. parsed patterns 为空列表

  7. 对于 url patterns 中的每个 url pattern

    1. parsed尝试url pattern 调用解析 url pattern所得的结果。

    2. parsed 追加parsed patterns

  8. intercept map[intercept] 设置为一个结构体,其 url patternsparsed patternsphasescommand parameters["phases"],以及 browsingContextsnavigables

  9. 返回一个新的映射,其匹配 network.AddInterceptResult 产生式,并且 intercept 字段设置为 intercept

7.5.5.3. network.continueRequest 命令

network.continueRequest 命令会继续一个 被网络拦截阻塞的请求。

命令类型
network.ContinueRequest = (
  method: "network.continueRequest",
  params: network.ContinueRequestParameters
)

network.ContinueRequestParameters = {
  request: network.Request,
  ?body: network.BytesValue,
  ?cookies: [*network.CookieHeader],
  ?headers: [*network.Header],
  ?method: text,
  ?url: text,
}
返回类型
network.ContinueRequestResult = EmptyResult
给定 sessioncommand parameters 时,远端步骤为:
  1. blocked requestssessionblocked request map

  2. request idcommand parameters["request"]。

  3. 如果 blocked requests包含 request id,则返回带有错误 代码 no such request错误

  4. 令 (request, phase, response) 为 blocked requests[request id]。

  5. 如果 phase 不是 "beforeRequestSent",则返回带有错误代码 invalid argument错误

    考虑 "request already sent" 错误。

  6. 如果 command parameters 包含 "url":

    1. url record 为将 URL 解析器应用于 command parameters["url"],且基础 URL 为 null 所得的结果。

    2. 如果 url record 是 failure,则返回带有 错误代码 invalid argument错误

      TODO:我们是否也应该在这里恢复?

    3. requesturlurl record

  7. 如果 command parameters 包含 "method":

    1. methodcommand parameters["method"]。

    2. 如果 method 不匹配 method token 产生式,则返回带有 错误代码 "invalid argument" 的错误

    3. requestmethodmethod

  8. 如果 command parameters 包含 "headers":

    1. headers 为空header list

    2. 对于 command parameters["headers"] 中的 header

      1. deserialized header 为以 header 调用反序列化 header所得的结果。

      2. 如果 deserialized header 的 name 不匹配 field-name token 产生式,则返回带有错误代码 "invalid argument" 的错误

      3. 如果 deserialized header 的 value 不匹配 header value 产生式,则返回带有错误代码 "invalid argument" 的错误

      4. deserialized header 追加到 headers

    3. requestheaders list 设置为 headers

  9. 如果 command parameters 包含 "cookies":

    1. cookie header 为空字节 序列

    2. 对于 command parameters["cookies"] 中的每个 cookie

      1. 如果 cookie header 非空,则将 `;` 追加到 cookie header

      2. 将以 cookie 调用序列化 cookie header所得的结果追加到 cookie header

    3. found cookie header 为 false。

    4. 对于 requestheaders list 中的每个 header

      1. nameheader 的 name。

      2. 如果对 name 进行 byte-lowercase 的结果为 `cookie`:

        1. header 的 value 设置为 cookie header

        2. found cookie header 设置为 true。

        3. 中断。

    5. 如果 found cookie header 为 false:

      1. header (`Cookie`, cookie header) 追加到 requestheaders list

  10. 如果 command parameters 包含 "body":

    1. body 为以 command parameters["body"] 调用反序列化 protocol bytes所得的结果。

    2. requestbody 设置为 body

  11. 以 "continue request"、request id 和 (null, "incomplete") 恢复

  12. 返回带有数据 null 的成功

7.5.5.4. network.continueResponse 命令

network.continueResponse 命令会继续一个 被网络拦截阻塞的响应。它可以在 responseStarted 阶段调用,以修改响应的状态和头部, 但仍提供网络响应体。

命令类型
network.ContinueResponse = (
  method: "network.continueResponse",
  params: network.ContinueResponseParameters
)

network.ContinueResponseParameters = {
  request: network.Request,
  ?cookies: [*network.SetCookieHeader]
  ?credentials: network.AuthCredentials,
  ?headers: [*network.Header],
  ?reasonPhrase: text,
  ?statusCode: js-uint,
}
返回类型
network.ContinueResponseResult = EmptyResult
给定 sessioncommand parameters 时,远端步骤为:
  1. request idcommand parameters["request"]。

  2. response尝试session、"continueResponse" 和 command parameters 调用更新 response所得的结果。

  3. 以 "continue request"、request id 和 (response, "incomplete") 恢复

  4. 返回带有数据 null 的成功

7.5.5.5. network.continueWithAuth 命令

network.continueWithAuth 命令会继续一个在 authRequired 阶段被网络拦截阻塞的响应。

命令类型
network.ContinueWithAuth = (
  method: "network.continueWithAuth",
  params: network.ContinueWithAuthParameters
)

network.ContinueWithAuthParameters = {
  request: network.Request,
  (network.ContinueWithAuthCredentials // network.ContinueWithAuthNoCredentials)
}

network.ContinueWithAuthCredentials = (
  action: "provideCredentials", 
  credentials: network.AuthCredentials
)

network.ContinueWithAuthNoCredentials = (
  action: "default" / "cancel"
)
返回类型
network.ContinueWithAuthResult = EmptyResult
给定 sessioncommand parameters 时,远端步骤为:
  1. blocked requestssessionblocked request map

  2. request idcommand parameters["request"]。

  3. 如果 blocked requests包含 request id,则返回带有错误 代码 no such request错误

  4. 令 (request, phase, response) 为 blocked requests[request id]。

  5. 如果 phase 不是 "authRequired",则返回带有错误代码 invalid argument错误

  6. 如果 command parameters "action" 是 "cancel",则将 response 的 authentication credentials 设置为 "cancelled"。

  7. 如果 command parameters "action" 是 "provideCredentials":

    1. credentialscommand parameters["credentials"]。

    2. 断言:credentials["type"] 是 "password"。

    3. response 的 authentication credentials 设置为 (credentials["username"], credentials["password"])

  8. 以 "continue request"、request id 和 (response, "incomplete") 恢复

  9. 返回带有数据 null 的成功

7.5.5.6. network.disownData 命令

network.disownData 命令会为给定collector释放收集到的网络数据。

命令类型
network.DisownData = (
  method: "network.disownData",
  params: network.DisownDataParameters
)

network.DisownDataParameters = {
  dataType: network.DataType,
  collector: network.Collector,
  request: network.Request,
}
返回类型
network.DisownDataResult = EmptyResult
给定 sessioncommand parameters 时,远端步骤为:
  1. data typecommand parameters 中 "dataType" 字段的值。

  2. collector idcommand parameters 中 "collector" 字段的值。

  3. request idcommand parameters 中 "request" 字段的值。

  4. collectorssessionnetwork collectors

  5. 如果 collectors包含 collector id,则返回带有错误 代码 no such network collector错误

  6. collected data 为以 request iddata type 调用获取 collected data所得的结果。

  7. 如果 collected data 为 null,则返回带有错误代码 no such network data错误

  8. collected datacollector id 调用从 data 中移除 collector

  9. 返回带有数据 null成功

7.5.5.7. network.failRequest 命令

network.failRequest 命令会使一个被网络拦截阻塞的 fetch 失败。

命令类型
network.FailRequest = (
  method: "network.failRequest",
  params: network.FailRequestParameters
)

network.FailRequestParameters = {
  request: network.Request,
}
返回类型
network.FailRequestResult = EmptyResult
给定 sessioncommand parameters 时,远端步骤为:
  1. blocked requestssessionblocked request map

  2. request idcommand parameters["request"]。

  3. 如果 blocked requests包含 request id,则返回带有错误 代码 no such request错误

  4. 令 (request, phase, response) 为 blocked requests[request id]。

  5. 如果 phase 是 "authRequired",则返回带有错误代码 invalid argument错误

  6. response 为新的网络错误

    允许设置 精确的错误种类 [Issue #508]

  7. 以 "continue request"、request id 和 (response, "complete") 恢复

  8. 返回带有数据 null 的成功

7.5.5.8. network.getData 命令

network.getData 命令会在网络数据可用时检索该 网络数据。

命令类型
network.GetData = (
  method: "network.getData",
  params: network.GetDataParameters
)

network.GetDataParameters = {
  dataType: network.DataType,
  ? collector: network.Collector,
  ? disown: bool .default false,
  request: network.Request,
}
返回类型
network.GetDataResult = {
  bytes: network.BytesValue,
}
给定 sessioncommand parameters 时,远端步骤为:
  1. data typecommand parameters["dataType"]。

  2. request idcommand parameters["request"]。

  3. collector id 为 null。

  4. 如果 command parameters 包含 "collector":

    1. collectorssessionnetwork collectors

    2. 如果 collectors包含 collector id,则返回 带有错误代码 no such network collector错误

    3. collector id 设置为 command parameters["collector"]。

  5. disowncommand parameters["disown"]。

  6. 如果 disown 为 true 且 collector id 为 null,则返回带有 错误代码 invalid argument错误

  7. collected data 为给定 request iddata type获取 collected data所得的结果。

  8. 如果 collected data 为 null:

    1. 返回带有错误代码 no such network data错误

  9. 如果 collected datapending 为 true:

    1. 以 "network data collected" 和 (request id, data type) 等待

  10. 如果 collector id 不是 null,并且如果 collected datacollectors包含 collector id

    1. 返回带有错误代码 no such network data错误

  11. bytescollected databytes

  12. 如果 bytes 为 null,

    1. 返回带有错误代码 unavailable network data错误

  13. body 为一个匹配 network.GetDataResult 产生式的 映射, 其 bytes 字段设置为 bytes

  14. 如果 disown 为 true,则以 collected datacollector id 调用从 data 中移除 collector

  15. 返回带有数据 body成功

7.5.5.9. network.provideResponse 命令

network.provideResponse 命令通过提供完整 响应,继续一个被网络拦截阻塞的请求。

注:这不会阻止该请求经历正常的请求 生命周期,因此在其推进过程中仍会发出其他事件。

命令类型
network.ProvideResponse = (
  method: "network.provideResponse",
  params: network.ProvideResponseParameters
)

network.ProvideResponseParameters = {
  request: network.Request,
  ?body: network.BytesValue,
  ?cookies: [*network.SetCookieHeader],
  ?headers: [*network.Header],
  ?reasonPhrase: text,
  ?statusCode: js-uint,
}
返回类型
network.ProvideResponseResult = EmptyResult
给定 sessioncommand parameters 时,远端步骤为:
  1. request idcommand parameters["request"]。

  2. response尝试session、"provideResponse" 和 command parameters 调用更新 response所得的结果。

  3. 如果 command parameters 包含 "body":

    1. body 为以 command parameters["body"] 调用反序列化 protocol bytes所得的结果。

    2. responsebody 设置为作为 body 的 body as a body

  4. 以 "continue request"、request id 和 (response,"complete") 恢复

  5. 返回带有数据 null 的成功

7.5.5.10. network.removeDataCollector 命令

network.removeDataCollector 命令会移除一个 collector

命令类型
network.RemoveDataCollector = (
  method: "network.removeDataCollector",
  params: network.RemoveDataCollectorParameters
)

network.RemoveDataCollectorParameters = {
  collector: network.Collector
}
返回类型
network.RemoveDataCollectorResult = EmptyResult
给定 sessioncommand parameters 时,远端步骤为:
  1. collector idcommand parameters 中 "collector" 字段的值。

  2. collectorssessionnetwork collectors

  3. 如果 collectors包含 collector id,则返回 带有错误 代码 no such network collector错误

  4. sessionnetwork collectors移除 collector id

  5. 对于 collected network data 中的 collected data, 以 collected datacollector id 调用从 data 中移除 collector

  6. 返回带有数据 null成功

7.5.5.11. network.removeIntercept 命令

network.removeIntercept 命令会移除一个 网络拦截

命令类型
network.RemoveIntercept = (
  method: "network.removeIntercept",
  params: network.RemoveInterceptParameters
)

network.RemoveInterceptParameters = {
  intercept: network.Intercept
}
返回类型
network.RemoveInterceptResult = EmptyResult
给定 sessioncommand parameters 时,远端步骤为:
  1. interceptcommand parameters 中 "intercept" 字段的值。

  2. intercept mapsessionintercept map

  3. 如果 intercept map包含 intercept,则返回 带有错误 代码 no such intercept错误

  4. intercept map移除 intercept

注:移除某个拦截不会影响已被此拦截 阻塞的请求。只有未来的请求或现有请求的未来阶段 会受到影响。

  1. 返回带有数据 null成功

7.5.5.12. network.setCacheBehavior 命令

network.setCacheBehavior 命令会为某些请求配置 网络缓存行为。

命令类型
network.SetCacheBehavior = (
  method: "network.setCacheBehavior",
  params: network.SetCacheBehaviorParameters
)

network.SetCacheBehaviorParameters = {
  cacheBehavior: "default" / "bypass",
  ? contexts: [+browsingContext.BrowsingContext]
}
返回类型
network.SetCacheBehaviorResult = EmptyResult
给定request request 时,WebDriver BiDi cache behavior 步骤为:
  1. navigable 为 null。

  2. 如果 requestclient环境设置对象

    1. environment settingsrequestclient

    2. 如果存在一个navigable,其活动 windowenvironment settings全局对象,则将 navigable 设置为该 navigable 的顶级 traversable

  3. 如果 navigable 不是 null,且 navigable cache behavior map 包含 navigable,则返回 navigable cache behavior map[navigable]。

  4. 返回 default cache behavior

给定 navigable 时,navigable cache behavior 步骤为:
  1. top-level navigablenavigable顶级 traversable

  2. 如果 navigable cache behavior map 包含 top-level navigable,则返回 navigable cache behavior map[top-level navigable]。

  3. 返回 default cache behavior

给定 sessioncommand parameters 时,远端步骤为:
  1. behaviorcommand parameters["cacheBehavior"]。

  2. 如果 command parameters包含 "contexts":

    1. default cache behavior 设置为 behavior

    2. 清空 navigable cache behavior map

    3. 根据 behavior 的值切换:

      "bypass"
      执行实现定义步骤,以禁用任何 实现特定的资源缓存。
      "default"
      执行实现定义步骤,以启用当前远端配置中通常启用的任何 实现特定的资源缓存。
    4. 返回带有数据 null 的成功

  3. navigables 为空集合

  4. 对于 command parameters["contexts"] 的每个 navigable id

    1. context尝试navigable id 调用获取 navigable所得的结果。

    2. 如果 context 不是顶级浏览上下文,则返回带有 错误代码 invalid argument错误

    3. context 追加navigables

  5. 对于 navigables 中的每个 navigable

    1. 如果 navigable cache behavior map 包含 navigable,且 navigable cache behavior map[navigable] 等于 behavior,则 继续。

    2. 根据 behavior 的值切换:

      "bypass"
      执行实现定义步骤,以禁用源自任何浏览 上下文(其顶级浏览上下文navigable)的网络请求的任何实现特定 资源缓存。
      "default"
      执行实现定义步骤,以启用当前远端配置中通常启用的任何 实现特定资源缓存,用于源自任何浏览上下文(其 顶级浏览上下文navigable)的网络请求。
    3. 如果 behavior 等于 default cache behavior

      1. 如果 navigable cache behavior map 包含 navigable, 则移除 navigable cache behavior map[navigable]。

    4. 否则:

      1. navigable cache behavior map[navigable] 设置为 behavior

  6. 返回带有数据 null 的成功

7.5.5.13. network.setExtraHeaders 命令

network.setExtraHeaders 命令允许 指定将扩展或覆盖现有请求头的头部。

命令类型
network.SetExtraHeaders = (
  method: "network.setExtraHeaders",
  params: network.SetExtraHeadersParameters
)

network.SetExtraHeadersParameters = {
  headers: [*network.Header]
  ? contexts: [+browsingContext.BrowsingContext]
  ? userContexts: [+browser.UserContext]
}
返回类型
network.SetExtraHeadersResult = EmptyResult
给定 requestheaders 时,要更新 headers
  1. request headersrequestheader list

  2. 对于 headers 中的每个 header

    1. request headers设置 header

      注:这总是会覆盖现有值(如果有)。特别是它 不会将 cookie 追加到现有的 `Set-Cookie` header。

给定 sessionrequestrelated navigables 时,要更新 request headers
  1. 断言:related navigables大小为 0 或 1。

    注:这意味着它不适用于与多个 navigables 关联的 worker。在这种情况下,不清楚应按什么顺序覆盖 headers。

  2. requestsessionextra headersdefault headers 调用更新 headers

  3. user context headerssessionextra headersuser context headers

  4. 对于 related navigables 中的 navigable

    1. user contextnavigable关联 用户上下文

    2. 如果 user context headers 包含 user context, 则以 requestuser context headers[user context] 调用更新 headers

  5. navigable headerssessionextra headersnavigable headers

  6. 对于 related navigables 中的 navigable

    1. top-level traversablenavigable顶级 traversable

    2. 如果 navigable headers 包含 top-level traversable, 则以 requestnavigable headers[top-level traversable] 调用更新 headers

给定 sessioncommand parameters 时,远端步骤为:
  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 代码 invalid argument错误

  2. headers尝试command parameters["headers"] 调用创建 headers list所得的结果。

  3. 如果 command parameters 包含 "userContexts":

    1. user contexts 为空列表

    2. 对于 command parameters["userContexts"] 中的 user context id

      1. user context 为以 user context id 调用获取用户上下文所得的结果。

      2. 如果 user context 为 null,则返回带有错误代码 no such user context错误

      3. user context 追加user contexts

    3. targetsessionextra headersuser context headers

    4. 对于 user contexts 中的 user context

      1. target[user context] 设置为 headers

    5. 返回带有数据 null 的成功

  4. 如果 command parameters 包含 "contexts":

    1. navigables尝试command parameters["contexts"] 调用通过 id 获取有效顶级 traversables所得的结果。

    2. targetsessionextra headersnavigable headers

    3. 对于 navigables 中的 navigable

      1. target[navigable] 设置为 headers

    4. 返回带有数据 null 的成功

  5. sessionextra headersdefault headers 设置为 headers

  6. 返回带有数据 null 的成功

7.5.6. 事件

7.5.6.1. network.authRequired 事件
事件类型
network.AuthRequired = (
  method: "network.authRequired",
  params: network.AuthRequiredParameters
)

network.AuthRequiredParameters = {
  network.BaseParameters,
  response: network.ResponseData
}

此事件会在用户代理即将提示输入授权 凭据时发出。

远端事件触发器是给定request requestresponse response 时的 WebDriver BiDi auth required 步骤:
  1. redirect countrequestredirect count

  2. 断言:before request sent map[request] 等于 redirect count

    注:这意味着每个调用者都需要确保在这些步骤之前, 先以 request 调用 WebDriver BiDi before request sent 步骤。

  3. 如果 requestclient 不是 null,则令 related navigables 为以 requestclient 调用获取相关 navigables所得的结果。否则令 related navigables 为空集合。

  4. 对于给定 "network.authRequired" 和 related navigables 时的事件已启用的会话集合中的每个 session

    1. params 为以 session、 "network.authRequired" 和 request 调用处理 network event所得的结果。

    2. response data 为以 response 调用获取 response data所得的结果。

    3. 断言:response data 包含 "authChallenge"。

    4. paramsresponse 字段设置为 response data

    5. 断言:params 匹配 network.AuthRequiredParameters 产生式。

    6. body 为一个匹配 network.AuthRequired 产生式的映射,其 params 字段设置为 params

    7. sessionbody 发出 事件

    8. 如果 params["isBlocked"] 为 true:

      1. blocked requestssessionblocked request map

      2. request idrequestrequest id

      3. blocked requests[request id] 设置为 (request, "authRequired", response)。

      4. 以 «"continue request"» 和 request id 等待

      5. 移除 blocked requests[request id]。

7.5.6.2. network.beforeRequestSent 事件
事件类型
network.BeforeRequestSent = (
  method: "network.beforeRequestSent",
  params: network.BeforeRequestSentParameters
 )

network.BeforeRequestSentParameters = {
  network.BaseParameters,
  ? initiator: network.Initiator,
}

此事件会在请求被发送之前发出(无论是通过网络发送,还是 在由 serviceworker 或本地缓存处理之前)。

给定 requestuser context 时,用于检查请求是否源自用户上下文的步骤为:
  1. settingsrequestclient

  2. related navigables 为以 settings 调用获取相关 navigables所得的结果。

  3. 对于 related navigables 中的 navigable

    1. 如果 navigable关联用户上下文user context,则返回 true。

  4. 返回 false。

给定 related navigables 时,用于获取模拟网络条件的步骤为:
  1. 对于 related navigables 的每个 navigable

    1. top-level traversablenavigable顶级 traversable

    2. user contexttop-level traversable关联 用户上下文

    3. 对于 活动 BiDi 会话中的每个 session

      1. 如果 session模拟网络 条件navigable network conditions 包含 top-level traversable, 则返回 session模拟网络 条件navigable network conditions[top-level traversable]。

    4. 对于 活动 BiDi 会话中的每个 session

      1. 如果 session模拟网络 条件user context network conditions 包含 user context,则返回 session模拟网络 条件user context network conditions[user context]。

    5. 对于 活动 BiDi 会话中的每个 session

      1. 如果 session模拟网络 条件default network conditions 不是 null, 则返回 session模拟网络 条件default network conditions

  2. 返回 null。

给定 环境设置对象 settings 时,WebDriver BiDi 网络离线步骤为:
  1. navigablesettings相关全局对象关联 Documentnode navigable

  2. emulated network conditions 为以 [navigable] 调用 获取模拟网络条件所得的结果。

  3. 如果 emulated network conditions 不是 null,且 emulated network conditionsoffline 为 true,则返回 true。

  4. 返回 false。

远端事件触发器是给定request request 时的 WebDriver BiDi before request sent 步骤:
  1. 对于用户上下文集合中的每个 user context

    1. 如果以 requestuser context 执行请求是否源自用户 上下文步骤返回 true:

      1. 对于 活动 BiDi 会话中的每个 session

        注:user context 最多只能位于一个 user context to accept insecure certificates override map 中。

        1. 如果 sessionuser context to accept insecure certificates override map 包含 user context

          1. accept insecure certificatessessionuser context to accept insecure certificates override map[user context]。

          2. 如果 accept insecure certificates 为 true:

            1. 断言端点节点 支持接受不安全的 TLS 连接。

            2. request 运行 Basic Certificate Processing 步骤时,跳过步骤 a,以及任何其他 实现定义的证书验证步骤。

          3. 否则,为 request 运行 Basic Certificate Processing 步骤时,执行所有步骤以及任何实现定义的 证书验证步骤。

        注:user context 最多只能位于一个 user context to proxy configuration map 中。

        1. 如果 sessionuser context to proxy configuration map 包含 user context

          1. proxy configurationsessionuser context to proxy configuration map[user context]。

          2. 采取实现定义步骤,以确保 request 使用由 proxy configuration 定义的代理设置。

            注:这些 设置在创建用户上下文时已经过验证,因此 在此阶段假定其有效;访问代理时的任何错误 都会在处理请求时作为网络错误报告。

  2. request 调用可能收集网络请求体

  3. 如果 before request sent map 不包含 request,则将 before request sent map[request] 设置为新的 集合。

  4. redirect countrequestredirect count

  5. redirect count 添加到 before request sent map[request]。

  6. 如果 requestclient 不是 null,则令 related navigables 为以 requestclient 调用获取相关 navigables所得的结果。否则令 related navigables 为空 集合。

  7. response 为 null。

  8. response status 为 "incomplete"。

  9. 对于 活动 BiDi 会话中的每个 session

    1. sessionrequestrelated navigables 调用更新 request headers

  10. 对于给定 "network.beforeRequestSent" 和 related navigables 时的事件已启用的会话集合中的每个 session

    1. params 为以 session、 "network.beforeRequestSent" 和 request 调用处理 network event所得的结果。

    2. initiator 为以 request 调用获取 initiator所得的结果。

    3. 如果 initiator 不是,则将 paramsinitiator 字段 设置为 initiator

    4. 断言:params 匹配 network.BeforeRequestSentParameters 产生式。

    5. body 为一个匹配 network.BeforeRequestSent 产生式的映射,其 params 字段设置为 params

    6. sessionbody 发出 事件

    7. 如果 params["isBlocked"] 为 true,则:

      1. blocked requestssessionblocked request map

      2. request idrequestrequest id

      3. blocked requests[request id] 设置为 (request, "beforeRequestSent", null)。

      4. 令 (response, status) 为以 «"continue request"» 和 requestrequest id 等待所得的结果。

      5. 如果 status 是 "complete",则将 response status 设置为 status

      6. 移除 blocked requests[request id]。

      注:在等待期间,不会对该请求进行进一步处理。

  11. emulated network conditions 为以 related navigables 调用 获取模拟网络条件所得的结果。

  12. 如果 emulated network conditions 不是 null,且 emulated network conditionsoffline 为 true,则返回 (网络错误, "complete")。

  13. 返回 (response, response status)。

遵守 Fetch 的 "HTTP-network-or-cache fetch" 算法中的返回值。

7.5.6.3. network.fetchError 事件
事件类型
network.FetchError = (
  method: "network.fetchError",
  params: network.FetchErrorParameters
 )

network.FetchErrorParameters = {
  network.BaseParameters,
  errorText: text,
}

此事件会在网络请求以错误结束时发出。

远端事件触发器是给定 request request 时的 WebDriver BiDi fetch error 步骤:
  1. 如果 before request sent map[request] 不包含 requestredirect count,则以 request 运行 WebDriver BiDi before request sent 步骤。

    注:这确保了 network.beforeRequestSent 总是可以在 network.fetchError 之前发出,而无需调用者在每条错误路径上显式调用 WebDriver BiDi before request sent 步骤。

  2. 如果 requestclient 不是 null,则令 related navigables 为以 requestclient 调用获取相关 navigables所得的结果。否则令 related navigables 为空 集合。

  3. request 调用可能中止网络响应体 收集

  4. 对于给定 "network.fetchError" 和 related navigables 时的事件已启用的会话集合中的每个 session

    1. params 为以 session、 "network.fetchError" 和 request 调用处理 network event所得的结果。

    2. paramserrorText 字段设置为一个实现定义的 字符串, 用于描述导致请求中止的错误。

    3. 断言:params 匹配 network.FetchErrorParameters 产生式。

    4. body 为一个匹配 network.FetchError 产生式的映射,其 params 字段设置为 params

    5. sessionbody 发出 事件

7.5.6.4. network.responseCompleted 事件
事件类型
network.ResponseCompleted = (
  method: "network.responseCompleted",
  params: network.ResponseCompletedParameters
 )

network.ResponseCompletedParameters = {
  network.BaseParameters,
  response: network.ResponseData,
}

此事件会在接收到完整响应体之后发出。

远端事件触发器是给定 request requestresponse response 时的 WebDriver BiDi response completed 步骤:
  1. redirect countrequestredirect count

  2. 断言:before request sent map[request] 包含 redirect count

    注:这意味着每个调用者都需要确保在这些步骤之前, 先以 request 调用 WebDriver BiDi before request sent 步骤。

  3. 如果 requestclient 不是 null,则令 related navigables 为以 requestclient 调用获取相关 navigables所得的结果。否则令 related navigables 为空 集合。

  4. requestresponse 调用可能收集网络响应体

  5. sessions 为给定 "network.responseCompleted" 和 related navigables 时的事件已启用的会话集合

  6. 对于 sessions 中的每个 session

    1. params 为以 session、 "network.responseCompleted" 和 request 调用处理 network event所得的结果。

    2. 断言:params["isBlocked"] 为 false。

    3. response data 为以 response 调用获取 response data所得的结果。

    4. paramsresponse 字段设置为 response data

    5. 断言:params 匹配 network.ResponseCompletedParameters 产生式。

    6. body 为一个匹配 network.ResponseCompleted 产生式的映射,其 params 字段设置为 params

    7. sessionbody 发出 事件

7.5.6.5. network.responseStarted 事件
事件类型
network.ResponseStarted = (
  method: "network.responseStarted",
  params: network.ResponseStartedParameters
 )

network.ResponseStartedParameters = {
  network.BaseParameters,
  response: network.ResponseData,
}

此事件会在接收到响应头之后、响应体完成之前发出。

远端事件触发器是给定 request requestresponse response 时的 WebDriver BiDi response started 步骤:
  1. redirect countrequestredirect count

  2. 断言:before request sent map[request] 等于 redirect count

    注:这意味着每个调用者都需要确保在这些步骤之前, 先以 request 调用 WebDriver BiDi before request sent 步骤。

  3. 如果 requestclient 不是 null,则令 related navigables 为以 requestclient 调用获取相关 navigables所得的结果。否则令 related navigables 为空 集合。

  4. response status 为 "incomplete"。

  5. sessions 为给定 "network.responseStarted" 和 related navigables 时的事件已启用的会话集合

  6. 对于 sessions 中的每个 session

    1. params 为以 session、 "network.responseStarted" 和 request 调用处理 network event所得的结果。

    2. response data 为以 response 调用获取 response data所得的结果。

    3. paramsresponse 字段设置为 response data

    4. 断言:params 匹配 network.ResponseStartedParameters 产生式。

    5. body 为一个匹配 network.ResponseStarted 产生式的映射,其 params 字段设置为 params

    6. sessionbody 发出 事件

    7. 如果 params["isBlocked"] 为 true:

      1. blocked requestssessionblocked request map

      2. request idrequestrequest id

      3. blocked requests[request id] 设置为 (request, "beforeRequestSent", response)。

      4. 令 (response, status) 为以 «"continue request"» 和 request id 等待所得的结果。

      5. 如果 status 为 "complete",则将 response status 设置为 status

      6. 移除 blocked requests[request id]。

  7. 返回 (response, response status)。

7.6. script 模块

script 模块包含与 script realm 和执行相关的命令与事件。

7.6.1. 定义

远端定义

ScriptCommand = (
  script.AddPreloadScript //
  script.CallFunction //
  script.Disown //
  script.Evaluate //
  script.GetRealms //
  script.RemovePreloadScript
)

本地端定义

ScriptResult = (
  script.AddPreloadScriptResult /
  script.CallFunctionResult /
  script.DisownResult /
  script.EvaluateResult /
  script.GetRealmsResult /
  script.RemovePreloadScriptResult
)

ScriptEvent = (
  script.Message //
  script.RealmCreated //
  script.RealmDestroyed
)

7.6.2. 预加载脚本

预加载脚本是在创建新的 Window 时运行, 且在任何作者定义的脚本运行之前运行的脚本。

TODO: 将其扩展到其他种类 realm 中的脚本。

BiDi 会话有一个 preload script map, 它是一个映射,其中键是 UUID,值是带有如下项目的结构体: 一个名为 function declaration项目,它是字符串; 一个名为 arguments项目,它是列表; 一个名为 contexts项目,它是列表或 null; 一个名为 sandbox项目,它是字符串或 null; 以及一个名为 user contexts项目,它是一个集合

注:如果执行预加载脚本失败,无论是由于语法 错误还是 运行时异常,都会在其被执行所在的 realm 中报告一个 [ECMAScript] 异常,并且其他预加载脚本会照常运行。

给定 environment settings 时,要运行 WebDriver BiDi 预加载脚本
  1. documentenvironment settings相关全局对象关联 Document

  2. navigabledocumentnavigable

  3. user contextnavigable关联用户 上下文

  4. user context iduser contextuser context id

  5. 对于 活动 BiDi 会话中的每个 session

    1. 对于 sessionpreload script map中的每个 preload script

      1. 如果 preload scriptuser contexts大小不是零:

        1. 如果 preload scriptuser contexts包含 user context id, 则继续

      2. 如果 preload scriptcontexts 不是 null:

        1. navigable idnavigable顶级 traversable的 id。

        2. 如果 preload scriptcontexts包含 navigable id, 则继续

      3. 如果 preload scriptsandbox 不是 null,则令 realm 为以 preload scriptsandboxnavigable 调用获取或创建 sandbox realm所得的结果。否则令 realmenvironment settingsrealm 执行上下文的 Realm 组件。

      4. exception reporting global be be environment settingsrealm 执行上下文的 Realm 组件的全局对象

      5. argumentspreload scriptarguments

      6. deserialized arguments 为空列表。

      7. 对于 arguments 中的每个 argument

        1. channel 为以 sessionrealmargument 调用创建 channel所得的结果。

        2. channel 追加到 deserialized arguments

      8. base URLenvironment settingsAPI base URL

      9. options默认脚本获取选项

      10. function declarationpreload scriptfunction declaration

      11. function body evaluation status 为以 function declarationenvironment settingsbase URLoptions 调用求值 function body所得的结果。

      12. 如果 function body evaluation status突然完成, 则为 exception reporting global 报告异常,该异常由 function body evaluation status.[[Value]] 给出。

      13. function objectfunction body evaluation status.[[Value]]。

      14. 如果 IsCallable(function object) 为 false

        1. errorrealm 中的一个新的 TypeError 对象。

        2. exception reporting global 报告异常 error

      15. environment settings 准备运行脚本

      16. evaluation status 设置为 Call(function object, null, deserialized arguments)。

      17. environment settings 运行脚本后清理

      18. 如果 evaluation status突然 完成,则为 exception reporting global 报告异常,该异常由 evaluation status.[[Value]] 给出。

7.6.3. 类型

7.6.3.1. script.Channel 类型

远端定义本地端定义

script.Channel = text;

script.Channel 类型表示用于将自定义消息从远端发送到 本地端的特定 channel 的 id。

7.6.3.2. script.ChannelValue 类型

远端定义

script.ChannelValue = {
  type: "channel",
  value: script.ChannelProperties,
}

script.ChannelProperties = {
  channel: script.Channel,
  ? serializationOptions: script.SerializationOptions,
  ? ownership: script.ResultOwnership,
}

script.ChannelValue 类型表示一个 ArgumentValue,它可以被反序列化为一个函数,该函数会将消息从远端发送到本地端

要在给定 sessionrealmprotocol value 的情况下创建 channel

  1. channel propertiesprotocol value["value"]。

  2. steps 为给定参数 message 时的以下步骤:

    1. current realm当前 Realm Record

    2. sessioncurrent realmchannel propertiesmessage 发出 script message

  3. 返回 CreateBuiltinFunction(steps, 1, "", « », realm)。

7.6.3.3. script.EvaluateResult 类型

远端定义本地端定义

script.EvaluateResult = (
  script.EvaluateResultSuccess /
  script.EvaluateResultException
)

script.EvaluateResultSuccess = {
  type: "success",
  result: script.RemoteValue,
  realm: script.Realm
}

script.EvaluateResultException = {
  type: "exception",
  exceptionDetails: script.ExceptionDetails
  realm: script.Realm
}

script.EvaluateResult 类型指示执行脚本的命令的返回值。 script.EvaluateResultSuccess 变体用于脚本正常完成的情况,而 script.EvaluateResultException 变体用于脚本以抛出异常完成的情况。

7.6.3.4. script.ExceptionDetails 类型

远端定义本地端定义

script.ExceptionDetails = {
  columnNumber: js-uint,
  exception: script.RemoteValue,
  lineNumber: js-uint,
  stackTrace: script.StackTrace,
  text: text,
}

script.ExceptionDetails 类型表示 JavaScript 异常。

要在给定 realm完成记录 recordownership typesession 的情况下获取 exception details

  1. 断言:record.[[Type]] 为 throw

  2. text 为由实现定义的、对 record 所表示错误的文本描述。

    TODO: 收紧这里的要求;人们可能会尝试用 regex 或同样糟糕的东西来解析 此数据。

  3. serialization options 为一个匹配 script.SerializationOptions 产生式的映射, 其字段设置为它们的默认值。

  4. exception 为以 record.[[Value]]、serialization optionsownership type、 一个新的映射作为 serialization internal map、realmsession 调用序列化为 remote value所得的结果。

  5. stack trace 为给定 record 时的异常的 stack trace

  6. 如果 stack trace 的大小为 1 或更大,则令 line numberstack trace[0] 中 lineNumber 字段的值,并令 column numberstack trace[0] 中 columnNumber 字段的值。否则 令 line numbercolumn number 为 0。

  7. exception details 为一个匹配 script.ExceptionDetails 产生式的映射, 其 text 字段设置为 textexception 字段设置为 exceptionlineNumber 字段设置为 line numbercolumnNumber 字段设置为 column number,且 stackTrace 字段设置为 stack trace

  8. 返回 exception details

7.6.3.5. script.Handle 类型

远端定义本地端定义

script.Handle = text;

script.Handle 类型表示由 ECMAScript 运行时拥有的对象的句柄。 该句柄只在特定 Realm 中有效。

每个 ECMAScript Realm 都有一个对应的 handle object map。这是一个从 handle id 到其对应对象的强 映射

7.6.3.6. script.InternalId 类型

远端定义本地端定义

script.InternalId = text;

script.InternalId 类型表示在 序列化期间, 先前序列化的 script.RemoteValue 的 id。

7.6.3.7. script.LocalValue 类型

远端定义

script.LocalValue = (
  script.RemoteReference /
  script.PrimitiveProtocolValue /
  script.ChannelValue /
  script.ArrayLocalValue /
  { script.DateLocalValue } /
  script.MapLocalValue /
  script.ObjectLocalValue /
  { script.RegExpLocalValue } /
  script.SetLocalValue
)

script.ListLocalValue = [*script.LocalValue];

script.ArrayLocalValue = {
  type: "array",
  value: script.ListLocalValue,
}

script.DateLocalValue = (
  type: "date",
  value: text
)

script.MappingLocalValue = [*[(script.LocalValue / text), script.LocalValue]];

script.MapLocalValue = {
  type: "map",
  value: script.MappingLocalValue,
}

script.ObjectLocalValue = {
  type: "object",
  value: script.MappingLocalValue,
}

script.RegExpValue = {
  pattern: text,
  ? flags: text,
}

script.RegExpLocalValue = (
  type: "regexp",
  value: script.RegExpValue,
)

script.SetLocalValue = {
  type: "set",
  value: script.ListLocalValue,
}

script.LocalValue 类型表示可以被反序列化到 ECMAScript 中的值。这包括原始值和非原始值, 以及远程引用channels

要在给定 serialized key-value listrealmsession 的情况下反序列化 key-value list

  1. deserialized key-value list 为一个新的列表。

  2. 对于 serialized key-value list 中的每个 serialized key-value

    1. 如果 serialized key-value大小不是 2, 则返回错误,其错误代码invalid argument

    2. serialized keyserialized key-value[0]。

    3. 如果 serialized keystring, 则令 deserialized keyserialized key

    4. 否则,令 deserialized key尝试serialized keyrealmsession 给定反序列化 local value所得的结果。

    5. serialized valueserialized key-value[1]。

    6. deserialized value尝试serialized valuerealmsession 给定反序列化 local value所得的结果。

    7. CreateArrayFromListdeserialized key, deserialized value») 追加到 deserialized key-value list

  3. 返回成功,数据为 deserialized key-value list

要在给定 serialized value listrealmsession 的情况下反序列化 value list

  1. deserialized values 为一个新的列表。

  2. 对于 serialized value list 中的每个 serialized value

    1. deserialized value尝试serialized valuerealmsession 给定反序列化 local value所得的结果。

    2. deserialized value 追加到 deserialized values

  3. 返回成功,数据为 deserialized values

要在给定 local protocol valuerealmsession 的情况下反序列化 local value

  1. 如果 local protocol value 匹配 script.RemoteReference 产生式,则返回以给定 local protocol valuerealmsession 反序列化 remote reference所得的结果。

  2. 如果 local protocol value 匹配 script.PrimitiveProtocolValue 产生式, 则返回以 local protocol value 调用反序列化 primitive protocol value所得的结果。

  3. 如果 local protocol value 匹配 script.ChannelValue 产生式, 则返回以 sessionrealmlocal protocol value 调用创建 channel所得的结果。

  4. typelocal protocol valuetype 字段的值;如果 不存在这样的字段,则为 undefined。

  5. valuelocal protocol valuevalue 字段的值;如果 不存在这样的字段,则为 undefined。

  6. 在以下条件及关联步骤的列表中,运行第一个关联条件为 true 的步骤集:

    type 是字符串 "array"
    1. deserialized value list尝试valuerealmsession 给定反序列化 value list所得的结果。

    2. 返回成功,数据为 CreateArrayFromList(deserialized value list)。

    type 是字符串 "date"
    1. 如果 value 不匹配 Date Time String Format,则返回 错误,其 错误代码invalid argument

    2. date resultConstruct(Date, value)。

    3. 断言:date result 不是突然 完成

    4. 返回成功,数据为 date result

    type 是字符串 "map"
    1. deserialized key-value list尝试valuerealmsession 调用反序列化 key-value list所得的结果。

    2. iterableCreateArrayFromList(deserialized key-value list)

    3. 返回成功,数据为 Map(iterable)。

    type 是字符串 "object"
    1. deserialized key-value list尝试valuerealmsession 调用反序列化 key-value list所得的结果。

    2. iterableCreateArrayFromList(deserialized key-value list)

    3. 返回成功,数据为 Object.fromEntries(iterable)。

    type 是字符串 "regexp"
    1. patternlocal protocol valuepattern 字段的值。

    2. flagslocal protocol valueflags 字段的值; 如果不存在这样的字段,则为 undefined。

    3. regex_resultRegexp(pattern, flags)。如果这抛出异常,则返回错误, 其错误代码invalid argument

    4. 返回成功,数据为 regex_result

    type 是字符串 "set"
    1. deserialized value list尝试valuerealmsession 给定反序列化 value list所得的结果。

    2. iterableCreateArrayFromList(deserialized key-value list)

    3. 返回成功,数据为 Set object(iterable)。

    否则
    返回错误,其错误代码invalid argument
7.6.3.8. script.PreloadScript 类型

远端定义本地端定义

script.PreloadScript = text;

script.PreloadScript 类型表示一个指向将在 realm 创建时运行的脚本的句柄。

7.6.3.9. script.Realm 类型

远端定义本地端定义

script.Realm = text;

每个 realm 都有一个关联的 realm id,它是一个唯一标识该 realm 的字符串。 这会在创建 realm 时隐式设置。

realm 的 realm id 是不透明的,且 不得能从 handle object map 中对应全局对象的 handle id 推导出来;在相关时,也不得从任何 navigable id 推导出来,该 id 属于某个 navigable

注:这是为了确保用户不依赖不同 id 之间的 实现特定关系。

给定 realm id 时,要获取 realm
  1. 如果 realm id 为 null,则返回成功, 数据为 null。

  2. 如果不存在 realm,其 idrealm id,则返回 错误,其错误 代码no such frame

  3. realmrealm, 其 idrealm id

  4. 返回成功,数据为 realm

此处使用了错误的 错误代码

7.6.3.10. script.PrimitiveProtocolValue 类型

远端定义本地端定义

script.PrimitiveProtocolValue = (
  script.UndefinedValue /
  script.NullValue /
  script.StringValue /
  script.NumberValue /
  script.BooleanValue /
  script.BigIntValue
)

script.UndefinedValue = {
  type: "undefined",
}

script.NullValue = {
  type: "null",
}

script.StringValue = {
  type: "string",
  value: text,
}

script.SpecialNumber = "NaN" / "-0" / "Infinity" / "-Infinity";

script.NumberValue = {
  type: "number",
  value: number / script.SpecialNumber,
}

script.BooleanValue = {
  type: "boolean",
  value: bool,
}

script.BigIntValue = {
  type: "bigint",
  value: text,
}

script.PrimitiveProtocolValue 表示只能 由值表示、绝不能由引用表示的值。

要在给定 value序列化 primitive protocol value

  1. remote value 为 undefined。

  2. 在以下条件及关联步骤的列表中,运行第一个关联条件为 true 的步骤集(如果有):

    Type(value) 为 undefined
    remote value 为一个映射, 它匹配 script.UndefinedValue 产生式,该产生式位于 本地端定义中。
    Type(value) 为 Null
    remote value 为一个映射, 它匹配 script.NullValue 产生式,该产生式位于 本地端定义中。
    Type(value) 为 String
    remote value 为一个映射, 它匹配 script.StringValue 产生式,该产生式位于 本地端定义中, 且其 value property 设置为 value

    这 不处理孤立代理项

    Type(value) 为 Number
    1. 根据 value 的值切换:

      NaN
      serialized"NaN"
      -0
      serialized"-0"
      Infinity
      serialized"Infinity"
      -Infinity
      serialized"-Infinity"
      否则:
      serializedvalue
    2. remote value 为一个映射,它匹配 script.NumberValue 产生式,该产生式位于 本地端定义中, 且其 value property 设置为 serialized

    Type(value) 为 Boolean
    remote value 为一个映射, 它匹配 script.BooleanValue 产生式,该产生式位于 本地端定义中, 且其 value property 设置为 value
    Type(value) 为 BigInt
    remote value 为一个映射, 它匹配 script.BigIntValue 产生式,该产生式位于 本地端定义中, 且其 value property 设置为对 value 运行 ToString 操作所得的结果。
  3. 返回 remote value

要在给定 primitive protocol value反序列化 primitive protocol value

  1. typeprimitive protocol valuetype 字段的值。

  2. value 为 undefined。

  3. 如果 primitive protocol valuevalue 字段:

    1. valueprimitive protocol valuevalue 字段的值。

  4. 在以下条件及关联步骤的列表中,运行第一个关联条件为 true 的步骤集:

    type 是字符串 "undefined"
    返回成功,数据为 undefined
    type 是字符串 "null"
    返回成功,数据为 null
    type 是字符串 "string"
    返回成功,数据为 value
    type 是字符串 "number"
    1. 如果 Type(value) 为 Number,则返回成功,数据为 value

    2. 断言:Type(value) 为 String。

    3. 如果 value 是字符串 "NaN",则返回成功, 数据为 NaN。

    4. number_resultStringToNumber(value)。

    5. 如果 number_result 为 NaN,则返回错误,其错误代码invalid argument

    6. 返回成功,数据为 number_result

    type 是字符串 "boolean"
    返回成功,数据为 value
    type 是字符串 "bigint"
    1. bigint_resultStringToBigInt(value)。

    2. 如果 bigint_result 为 undefined,则返回错误,其错误代码invalid argument

    3. 返回成功,数据为 bigint_result

  5. 返回错误,其错误 代码invalid argument

7.6.3.11. script.RealmInfo 类型

本地端定义

script.RealmInfo = (
  script.WindowRealmInfo /
  script.DedicatedWorkerRealmInfo /
  script.SharedWorkerRealmInfo /
  script.ServiceWorkerRealmInfo /
  script.WorkerRealmInfo /
  script.PaintWorkletRealmInfo /
  script.AudioWorkletRealmInfo /
  script.WorkletRealmInfo
)

script.BaseRealmInfo = (
  realm: script.Realm,
  origin: text
)

script.WindowRealmInfo = {
  script.BaseRealmInfo,
  type: "window",
  context: browsingContext.BrowsingContext,
  ? userContext: browser.UserContext,
  ? sandbox: text
}

script.DedicatedWorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "dedicated-worker",
  owners: [script.Realm]
}

script.SharedWorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "shared-worker"
}

script.ServiceWorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "service-worker"
}

script.WorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "worker"
}

script.PaintWorkletRealmInfo = {
  script.BaseRealmInfo,
  type: "paint-worklet"
}

script.AudioWorkletRealmInfo = {
  script.BaseRealmInfo,
  type: "audio-worklet"
}

script.WorkletRealmInfo = {
  script.BaseRealmInfo,
  type: "worklet"
}

注: script.RealmInfo 变体与 script.RealmType 的值之间存在 1:1 关系。

script.RealmInfo 类型表示 realm 的属性。

要以给定 realm 获取 navigable
  1. global objectrealm全局对象

  2. global object解包装后的 global object

  3. 如果 global object 不是 Window 对象,则返回 null

  4. documentglobal object 的已包装 Window关联 Document

  5. 返回 documentnode navigable

要以给定 global object 获取 worker 的 owners
  1. 断言:global object 是一个 WorkerGlobalScope 对象。

  2. owners 为空列表

  3. 对于 global object 的关联owner set 中的每个 owner

    1. owner environment settingsowner相关设置对象

    2. owner realm info 为给定 owner environment settings 时调用获取 realm info 所得的结果。

    3. 如果 owner realm info 为 null,则继续。

    4. owner realm info["id"] 追加到 owners

  4. 返回 owners

给定 environment settings 时,要获取 realm info
  1. realmenvironment settingsrealm 执行上下文的 Realm 组件。

  2. realm idrealmrealm id

  3. origin 为给定 environment settingsorigin 时的origin 序列化

  4. global objectenvironment settings 指定的全局对象

  5. 运行第一个匹配条件下的步骤:

    global object 是一个 Window 对象
    1. documentenvironment settings相关全局对象关联 Document

    2. navigabledocumentnode navigable

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

    4. navigable idnavigablenavigable id

    5. user context idnavigable关联用户上下文user context id

    6. realm info 为一个映射,它匹配 script.WindowRealmInfo 产生式, 其中 realm 字段设置为 realm idorigin 字段设置为 origincontext 字段设置为 navigable id,且 userContext 字段设置为 user context id

    global objectSandboxWindowProxy 对象
    TODO: 尚不清楚这是否是处理 sandboxes 的正确表述。
    1. documentglobal object 的已包装 Window关联 Document

    2. navigabledocumentnode navigable

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

    4. navigable idnavigablenavigable id

    5. user context idnavigable关联用户上下文user context id

    6. sandbox name 为给定 realm 时调用获取 sandbox name所得的结果。

    7. 断言:sandbox name 不是 null。

    8. realm info 为一个映射,它匹配 script.WindowRealmInfo 产生式, 其中 realm 字段设置为 realm idorigin 字段设置为 origincontext 字段设置为 navigable iduserContext 字段设置为 user context id,并且 sandbox 字段设置为 sandbox name

    global object 是一个 DedicatedWorkerGlobalScope 对象
    1. owners 为给定 global object 时调用获取 worker 的 owners所得的结果。

    2. 断言:owners 精确地有一项。

    3. realm info 为一个映射,它匹配 script.DedicatedWorkerRealmInfo 产生式, 其中 realm 字段设置为 realm idorigin 字段 设置为 origin,并且 owners 字段设置为 owners

    global object 是一个 SharedWorkerGlobalScope 对象
    1. realm info 为一个映射,它匹配 script.SharedWorkerRealmInfo 产生式, 其中 realm 字段设置为 realm id,且 origin 字段 设置为 origin

    global object 是一个 ServiceWorkerGlobalScope 对象
    1. realm info 为一个映射,它匹配 script.ServiceWorkerRealmInfo 产生式, 其中 realm 字段设置为 realm id,且 origin 字段 设置为 origin

    global object 是一个 WorkerGlobalScope 对象
    1. realm info 为一个映射,它匹配 script.WorkerRealmInfo 产生式, 其中 realm 字段设置为 realm id,且 origin 字段设置为 origin

    global object 是一个 PaintWorkletGlobalScope 对象
    1. realm info 为一个映射,它匹配 script.PaintWorkletRealmInfo 产生式, 其中 realm 字段设置为 realm id,且 origin 字段设置为 origin

    global object 是一个 AudioWorkletGlobalScope 对象
    1. realm info 为一个映射,它匹配 script.AudioWorkletRealmInfo 产生式, 其中 realm 字段设置为 realm id,且 origin 字段设置为 origin

    global object 是一个 WorkletGlobalScope 对象
    1. realm info 为一个映射,它匹配 script.WorkletRealmInfo 产生式, 其中 realm 字段设置为 realm id,且 origin 字段设置为 origin

    否则:
    1. realm info 为 null。

  6. 返回 realm info

注:此规范未来的变体将保留以下不变量: 在按 "-" 拆分类型名称后, 类型名称的最后一个组成部分,对于实现 WorkerGlobalScope 的 globals 始终为 "worker", 而对于实现 WorkletGlobalScope 的 globals 始终为 "worklet"。

7.6.3.12. script.RealmType 类型

远端定义本地端定义

script.RealmType = "window" / "dedicated-worker" / "shared-worker" / "service-worker" /
                   "worker" / "paint-worklet" / "audio-worklet" / "worklet"

script.RealmType 类型表示 Realm 的不同类型。

7.6.3.13. script.RemoteReference 类型

远端定义

script.RemoteReference = (
  script.SharedReference /
  script.RemoteObjectReference
)

script.SharedReference = {
   sharedId: script.SharedId

   ? handle: script.Handle,
   Extensible
}

script.RemoteObjectReference = {
   handle: script.Handle,

   ? sharedId: script.SharedId
   Extensible
}

script.RemoteReference 类型要么是 script.RemoteObjectReference,表示对给定 Realmhandle object map 内已有 ECMAScript 对象的远程引用;要么 是 script.SharedReference,表示对某个 node 的引用。

处理 "stale object reference" 情况。

注:如果所提供的引用同时具有 handlesharedId,该算法将忽略 handle,而只遵循 sharedId

要在给定 remote referencerealmsession反序列化 remote reference
  1. 断言 remote reference 匹配 script.RemoteReference 产生式。

  2. 如果 remote reference 匹配 script.SharedReference 产生式,则返回 以 remote referencerealmsession 调用反序列化 shared reference 的结果。

  3. 返回以 remote referencerealm 调用反序列化 remote object reference 的结果。

要在给定 remote object referencerealm反序列化 remote object reference
  1. handle idremote object referencehandle 字段的值。

  2. handle maprealmhandle object map

  3. 如果 handle map 不包含 handle id,则返回错误,其 错误代码no such handle

  4. 返回成功,数据为 handle map[handle id]。

要在给定 shared referencerealmsession反序列化 shared reference
  1. 断言 shared reference 匹配 script.SharedReference 产生式。

  2. navigable 为以 realm 调用获取 navigable 的结果。

  3. 如果 navigablenull,则返回错误,其错误代码no such node

    注:当 realm 不是 Window global 时会发生这种情况。

  4. shared idshared referencesharedId 字段的值。

  5. node 为以 sessionnavigableshared id 调用尝试 获取 node 的结果。

  6. 如果 nodenull,则返回错误,其错误代码no such node

  7. environment settings 为其 realm 执行上下文的 Realm 组件是 realm环境设置对象

  8. 如果 nodenode documentoriginenvironment settingsorigin 不是same origin domain, 则返回错误,其错误 代码no such node

    注:这会确保 WebDriver-BiDi 不能被用来在本来不允许脚本访问的 realms 之间传递对象。

  9. realm global objectrealm全局对象

  10. 如果 realm global objectSandboxWindowProxy 对象,则将 node 设置为在 realm 中包装 nodeSandboxProxy

  11. 返回成功,数据为 node

7.6.3.14. script.RemoteValue 类型

远端定义本地端定义

script.RemoteValue = (
  script.PrimitiveProtocolValue /
  script.SymbolRemoteValue /
  script.ArrayRemoteValue /
  script.ObjectRemoteValue /
  script.FunctionRemoteValue /
  script.RegExpRemoteValue /
  script.DateRemoteValue /
  script.MapRemoteValue /
  script.SetRemoteValue /
  script.WeakMapRemoteValue /
  script.WeakSetRemoteValue /
  script.GeneratorRemoteValue /
  script.ErrorRemoteValue /
  script.ProxyRemoteValue /
  script.PromiseRemoteValue /
  script.TypedArrayRemoteValue /
  script.ArrayBufferRemoteValue /
  script.NodeListRemoteValue /
  script.HTMLCollectionRemoteValue /
  script.NodeRemoteValue /
  script.WindowProxyRemoteValue
)

script.ListRemoteValue = [*script.RemoteValue];

script.MappingRemoteValue = [*[(script.RemoteValue / text), script.RemoteValue]];

script.SymbolRemoteValue = {
  type: "symbol",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ArrayRemoteValue = {
  type: "array",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.ObjectRemoteValue = {
  type: "object",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.MappingRemoteValue,
}

script.FunctionRemoteValue = {
  type: "function",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.RegExpRemoteValue = {
  script.RegExpLocalValue,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.DateRemoteValue = {
  script.DateLocalValue,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.MapRemoteValue = {
  type: "map",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.MappingRemoteValue,
}

script.SetRemoteValue = {
  type: "set",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue
}

script.WeakMapRemoteValue = {
  type: "weakmap",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.WeakSetRemoteValue = {
  type: "weakset",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.GeneratorRemoteValue = {
  type: "generator",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ErrorRemoteValue = {
  type: "error",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ProxyRemoteValue = {
  type: "proxy",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.PromiseRemoteValue = {
  type: "promise",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.TypedArrayRemoteValue = {
  type: "typedarray",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ArrayBufferRemoteValue = {
  type: "arraybuffer",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.NodeListRemoteValue = {
  type: "nodelist",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.HTMLCollectionRemoteValue = {
  type: "htmlcollection",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.NodeRemoteValue = {
  type: "node",
  ? sharedId: script.SharedId,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.NodeProperties,
}

script.NodeProperties = {
  nodeType: js-uint,
  childNodeCount: js-uint,
  ? attributes: {*text => text},
  ? children: [*script.NodeRemoteValue],
  ? localName: text,
  ? mode: "open" / "closed",
  ? namespaceURI: text,
  ? nodeValue: text,
  ? shadowRoot: script.NodeRemoteValue / null,
}

script.WindowProxyRemoteValue = {
  type: "window",
  value: script.WindowProxyProperties,
  ? handle: script.Handle,
  ? internalId: script.InternalId
}

script.WindowProxyProperties = {
  context: browsingContext.BrowsingContext
}

添加 WASM 类型?

WindowProxy 是否应该以类似 Node 的样式 获取属性?

是否要特殊处理 String / Number / 等包装器对象?

可从 ECMAScript 运行时访问的值由一个镜像对象表示, 其指定为 script.RemoteValue。值的类型由 type 属性指定。对于可用 JSON 表示的 原始值,它会在 value 属性中包含该值;对于 不可用 JSON 表示的原始值,value 属性 包含该值的字符串表示。

对于非原始对象,handle 属性在存在时 包含指向该对象的唯一字符串 handle。该 handle 对于每次 序列化都是唯一的。远端会让具有对应 handle 的对象 保持存活,直到以该 handle 调用 script.disown, 或 realm 本身将被丢弃(例如由于导航)。

对于某些非原始类型,value 属性包含 ECMAScript 对象中数据的表示;对于容器类型,这 可以包含更多 script.RemoteValue 实例。 如果存在重复对象,即该对象已经在当前 script.RemoteValue 中被序列化过(也许作为循环的一部分), 或者在达到最大序列化深度时,value 属性可以为 null 或被省略。

在同一 script.RemoteValue 中存在重复对象的情况下, 只为其中一个 remote value 提供 value,而 对于给定序列化中的所有重复对象,都会提供按 ECMAScript 对象唯一的 internalId

Nodes 也由 script.RemoteValue 实例表示。它们在 value 属性中具有 node 的部分序列化。

重新考虑镜像对象的 生命周期。

注:镜像对象不会让运行时中的原始对象 保持存活。如果某个对象在运行时中被丢弃,随后尝试通过 协议访问它将导致错误。

要在给定 realmownership typeobject 时,获取对象的 handle
  1. 如果 ownership type 等于 "none",返回 null

  2. handle idobject 的新的、唯一的字符串 handle。

  3. handle maprealmhandle object map

  4. handle map[handle id] 设置为 object

  5. 返回 handle id 作为结果。

要在给定 nodesession获取 node 的 shared id
  1. node解包装的 node

  2. 如果 node 未实现 Node, 返回 null。

  3. navigablenodenode navigable

  4. 如果 navigable 为 null,返回 null。

  5. 返回以 sessionnavigablenode 调用获取或创建 node 引用的结果。

要在给定 serialization internal mapremote valueobject必要时设置 internal ids
  1. 如果 serialization internal map 不包含 object,则将 serialization internal map[object] 设置为 remote value

  2. 否则,运行以下步骤:

    1. previously serialized remote valueserialization internal map[object]。

    2. 如果 previously serialized remote value 没有 internalId 字段,则运行以下步骤:

      1. internal id 为基于真正随机或伪随机数字的 UUID 的字符串表示。

      2. previously serialized remote valueinternalId 字段设置为 internal id

    3. remote valueinternalId 字段设置为 previously serialized remote value 中的 internalId 字段。

要在给定 valueserialization options、 一个 ownership type、一个 serialization internal map、一个 realm 和一个 session序列化为 remote value

  1. remote value 为给定 value 调用序列化 primitive protocol value 的结果。

  2. 如果 remote value 不是 undefined,返回 remote value

  3. handle id 为以 realmownership typevalue 调用对象的 handle所得的结果。

  4. ownership type 设置为 "none"。

  5. 如果 valueserialization internal map 中,则令 known objecttrue, 否则为 false

  6. 在以下条件及其关联步骤列表中,运行第一个关联条件为 true 的步骤集:

    Type(value) is Symbol
    remote value 为一个映射, 其匹配 本地端定义中的 script.SymbolRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。
    IsArray(value)
    remote value 为以 sessionscript.ArrayRemoteValuehandle idknown objectvalueserialization optionsownership typeserialization internal maprealmsession 调用序列化 Array-like所得的结果。
    IsRegExp(value)
    1. patternToString(Get(value, "source"))。

    2. flagsToString(Get(value, "flags"))。

    3. serialized 为一个映射,其匹配 本地端定义中的 script.RegExpValue 产生式, 并将 pattern 属性设置为 pattern,将 flags 属性设置为 flags

    4. remote value 为一个映射,其匹配 本地端定义中的 script.RegExpRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略,并将 value 属性设置为 serialized

    value 具有 [[DateValue]] 内部槽
    1. serialized 设置为 Call(Date.prototype.toISOString, value)。

    2. 断言:serialized 不是throw completion

    3. remote value 为一个映射,其匹配 本地端定义中的 script.DateRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略,并将 value 设置为 serialized

    value 具有 [[MapData]] 内部槽
    1. remote value 为一个映射,其匹配 本地端定义中的 script.MapRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。

    2. serialization internal mapremote valuevalue 调用必要时设置 internal ids

    3. serialized 为 null。

    4. 如果 known objectfalse,且 serialization options["maxObjectDepth"] 不为 0,则运行以下 步骤:

      1. serialized 为以 CreateMapIterator(value, key+value)、serialization optionsownership typeserialization internal maprealmsession 调用序列化为 mapping的结果。

    5. 如果 serialized 不为 null,则将 remote value 的字段 value 设置为 serialized

    value 具有 [[SetData]] 内部槽
    1. remote value 为一个映射,其匹配 本地端定义中的 script.SetRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。

    2. serialization internal mapremote valuevalue 调用必要时设置 internal ids

    3. serialized 为 null。

    4. 如果 known objectfalse,且 serialization options["maxObjectDepth"] 不为 0,则运行以下 步骤:

      1. serialized 为以 CreateSetIterator(value, value)、serialization optionsownership typeserialization internal maprealmsession 调用序列化为 list的结果。

    5. 如果 serialized 不为 null,则将 remote value 的字段 value 设置为 serialized

    value 具有 [[WeakMapData]] 内部槽
    remote value 为一个映射, 其匹配 本地端定义中的 script.WeakMapRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。
    value 具有 [[WeakSetData]] 内部槽
    remote value 为一个映射, 其匹配 本地端定义中的 script.WeakSetRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。
    value 具有 [[GeneratorState]] 内部槽或 [[AsyncGeneratorState]] 内部槽
    remote value 为一个映射, 其匹配 本地端定义中的 script.GeneratorRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。
    value 具有 [[ErrorData]] 内部槽
    remote value 为一个映射, 其匹配 本地端定义中的 script.ErrorRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。
    value 具有 [[ProxyHandler]] 内部槽和 [[ProxyTarget]] 内部槽
    remote value 为一个映射, 其匹配 本地端定义中的 script.ProxyRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。
    IsPromise(value)
    remote value 为一个映射, 其匹配 本地端定义中的 script.PromiseRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。
    value 具有 [[TypedArrayName]] 内部槽
    remote value 为一个映射, 其匹配 本地端定义中的 script.TypedArrayRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。
    value 具有 [[ArrayBufferData]] 内部槽
    remote value 为一个映射, 其匹配 本地端定义中的 script.ArrayBufferRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。
    value 是实现了 NodeList平台对象
    remote value 为以 script.NodeListRemoteValuehandle idknown objectvalueserialization optionsownership typeserialization internal maprealmsession 调用序列化 Array-like所得的结果。
    value 是实现了 HTMLCollection平台对象
    remote value 为以 script.HTMLCollectionRemoteValuehandle idknown objectvalueserialization optionsownership typeknown objectserialization internal maprealmsession 调用序列化 Array-like所得的结果。
    value 是实现了 Node平台对象
    1. shared id 为以 valuesession 调用获取 node 的 shared id所得的结果。

    2. remote value 为一个映射,其匹配 本地端定义中的 script.NodeRemoteValue 产生式,并将 sharedId 属性设置为 shared id(如果它不为 null),否则省略,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。

    3. serialization internal mapremote valuevalue 调用必要时设置 internal ids

    4. serialized 为 null。

    5. 如果 known objectfalse,则运行以下步骤:

      1. serialized 为一个映射

      2. serialized["nodeType"] 设置为 Get(value, "nodeType")。

      3. node value 设置为 Get(value, "nodeValue")。

      4. 如果 node value 不为 null,则将 serialized["nodeValue"] 设置为 node value

      5. 如果 value 实现了 ElementAttr

        1. serialized["localName"] 设置为 Get(value, "localName")。

        2. serialized["namespaceURI"] 设置为 Get(value, "namespaceURI")

      6. child node countvalue子节点大小

      7. serialized["childNodeCount"] 设置为 child node count

      8. 如果 serialization options["maxDomDepth"] 等于 0,或者如果 value 实现了 ShadowRootserialization options["includeShadowTree"] 为 "none", 或者如果 serialization options["includeShadowTree"] 为 "open" 且 valuemode 为 "closed",则令 children 为 null。

        否则,令 children 为空 列表,并且对于 value子节点中的每个 node child

        1. child serialization optionsserialization options克隆

        2. 如果 child serialization options["maxDomDepth"] 不为 null,则将 child serialization options["maxDomDepth"] 设置为 child serialization options["maxDomDepth"] - 1。

        3. serialized 为以 childchild serialization optionsownership typeserialization internal maprealmsession 调用序列化为 remote value的结果。

        4. serialized 追加到 children

      9. 如果 children 不为 null,则将 serialized["children"] 设置为 children

      10. 如果 value 实现了 Element

        1. attributes 为一个新的映射

        2. 对于 valueattribute list中的每个 attribute

          1. nameattribute限定 名

          2. valueattribute

          3. attributes[name] 设置为 value

        3. serialized["attributes"] 设置为 attributes

        4. shadow rootvalueshadow root

        5. 如果 shadow root 为 null,则令 serialized shadow 为 null。 否则运行以下子步骤:

          1. serialized shadow 为以 shadow rootserialization optionsownership typeserialization internal maprealmsession 调用 序列化为 remote value的结果。

        6. serialized["shadowRoot"] 设置为 serialized shadow

      11. 如果 value 实现了 ShadowRoot, 则将 serialized["mode"] 设置为 valuemode

    6. 如果 serialized 不为 null,则将 remote value 的字段 value 设置为 serialized

    value 是实现了 WindowProxy平台对象
    1. windowvalue 的 [[WindowProxy]] 内部 槽的值。

    2. navigablewindownavigable

    3. navigable idnavigablenavigable id

    4. serialized 为一个映射,其匹配 本地端定义中的 script.WindowProxyProperties 产生式, 并将 context 属性设置为 navigable id

    5. remote value 为一个映射,其匹配 本地端定义中的 script.WindowProxyRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略,并将 value 属性设置为 serialized

    value平台对象
    1. 令 remote value 为一个映射, 其匹配 本地端定义中的 script.ObjectRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。
    IsCallable(value)
    remote value 为一个映射, 其匹配 本地端定义中的 script.FunctionRemoteValue 产生式,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。
    否则:
    1. 断言Type(value) is Object

    2. remote value 为一个映射,其匹配 本地端定义中的 script.ObjectRemoteValue 产生式, 并将 handle 属性设置为 handle id(如果它不为 null),否则省略。

    3. serialization internal mapremote valuevalue 调用必要时设置 internal ids

    4. serialized 为 null。

    5. 如果 known objectfalse,且 serialization options["maxObjectDepth"] 不为 0,则运行以下 步骤:

      1. serialized 为以 EnumerableOwnPropertyNames(value, key+value)、serialization optionsownership typeserialization internal maprealmsession 调用序列化为 mapping的结果。

    6. 如果 serialized 不为 null,则将 remote value 的字段 value 设置为 serialized

  7. 返回 remote value

children 和 child nodes 是不同的东西。要么 childNodeCount 应该 引用 childNodes,要么它应该重命名为 childrenCount

要在给定 productionhandle idknown objectvalueserialization optionsownership typeserialization internal maprealmsession序列化 Array-like
  1. remote value 为一个映射, 其匹配 production,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。

  2. serialization internal mapremote valuevalue 调用必要时设置 internal ids

  3. 如果 known objectfalse,且 serialization options["maxObjectDepth"] 不为 0:

    1. serialized 为以 CreateArrayIterator(value, value)、serialization optionsownership typeserialization internal maprealmsession 调用序列化为 list的结果。

    2. 如果 serialized 不为 null,则将 remote value 的字段 value 设置为 serialized

  4. 返回 remote value

要在给定 iterableserialization optionsownership typeserialization internal maprealmsession序列化为 list
  1. 如果 serialization options["maxObjectDepth"] 不为 null, 断言:serialization options["maxObjectDepth"] 大于 0。

  2. serialized 为一个新列表。

  3. 对于 IteratorToList(GetIterator(iterable, sync)) 中的每个 child value

    1. child serialization optionsserialization options克隆

    2. 如果 child serialization options["maxObjectDepth"] 不为 null,则将 child serialization options["maxObjectDepth"] 设置为 child serialization options["maxObjectDepth"] - 1。

    3. serialized child 为以 child valuechild serialization optionsownership typeserialization internal maprealmsession 调用序列化为 remote value的结果。

    4. serialized child 追加到 serialized

  4. 返回 serialized

要在给定 iterableserialization optionsownership typeserialization internal maprealmsession序列化为 mapping

  1. 如果 serialization options["maxObjectDepth"] 不为 null, 断言:serialization options["maxObjectDepth"] 大于 0。

  2. serialized 为一个新列表。

  3. 对于 IteratorToList(GetIterator(iterable, sync)) 中的 item

    1. 断言:IsArray(item)

    2. propertyCreateListFromArrayLike(item)

    3. 断言:property 是一个大小为 2 的列表

    4. keyproperty[0],令 valueproperty[1]

    5. child serialization optionsserialization options克隆

    6. 如果 child serialization options["maxObjectDepth"] 不为 null,则将 child serialization options["maxObjectDepth"] 设置为 child serialization options["maxObjectDepth"] - 1。

    7. 如果 Type(key) is String,则令 serialized keychild key, 否则令 serialized key 为以 child keychild serialization optionsownership typeserialization internal maprealmsession 调用序列化为 remote value的结果。

    8. serialized value 为以 valuechild serialization optionsownership typeserialization internal maprealmsession 调用序列化为 remote value的结果。

    9. serialized child 为(«serialized key, serialized value»)。

    10. serialized child 追加到 serialized

  4. 返回 serialized

7.6.3.15. script.ResultOwnership 类型
script.ResultOwnership = "root" / "none"

script.ResultOwnership 指定如何处理已序列化值的 所有权。

7.6.3.16. script.SerializationOptions 类型

远端定义

script.SerializationOptions = {
  ? maxDomDepth: (js-uint / null) .default 0,
  ? maxObjectDepth: (js-uint / null) .default null,
  ? includeShadowTree: ("none" / "open" / "all") .default "none",
}

script.SerializationOptions 允许指定如何序列化 ECMAScript 对象。

7.6.3.17. script.SharedId 类型

远端定义本地端定义

script.SharedId = text;

script.SharedId 类型表示对 DOM Node 的引用, 该引用可在任何 realm 中使用(包括 Sandbox Realms)。

7.6.3.18. script.StackFrame 类型

远端定义本地端定义

script.StackFrame = {
  columnNumber: js-uint,
  functionName: text,
  lineNumber: js-uint,
  url: text,
}

栈跟踪中的一个帧由 StackFrame 对象表示。它具有一个 url 属性,表示 脚本的 URL;一个 functionName 属性,表示 正在执行的函数的名称;以及 lineNumbercolumnNumber 属性,表示已执行代码的行号和列号。

7.6.3.19. script.StackTrace 类型

远端定义本地端定义

script.StackTrace = {
  callFrames: [*script.StackFrame],
}

script.StackTrace 类型表示脚本执行中某一点的 javascript 栈。

注:如何获取 stack frames 列表及 该列表的属性的细节未充分规定,因此这里的细节由实现定义。

假定实现能够生成一个stack frames 列表,该列表对于 javascript 调用栈中的每一项都有一个条目,从最近的一项开始。每个条目都是一个单独的stack frame,对应于脚本 script 中某条语句或表达式的执行,并包含以下字段:

script url
包含 script 的资源的 url
function
正在执行的函数的名称
line number
已执行代码的从零开始的行号,相对于包含 script 的资源顶部。
column number
已执行代码的从零开始的列号,相对于包含 script 的资源中该行的起始位置。

要使用 stack frames 列表 stack构造 stack trace

  1. call frames 为一个新列表。

  2. 对于 stack 中的每个 stack frame frame, 从最近执行的 frame 开始,运行以下步骤:

    1. url 为在给定 framescript urlURL 时运行 URL 序列化器的结果。

    2. frame info 为一个新的映射,其匹配 script.StackFrame 产生式,并将 url 字段设置为 url,将 functionName 字段设置为 framefunction, 将 lineNumber 字段设置为 frameline number, 并将 columnNumber 字段设置为 framecolumn number

  3. frame info 追加到 call frames

  4. stack trace 为一个新的映射, 其匹配 script.StackTrace 产生式,并将 callFrames 属性设置为 call frames

  5. 返回 stack trace

当前 stack trace 是在给定一个stack frames 列表(表示正在运行的 执行上下文的 callstack)时调用构造 stack trace所得的结果。

带有一个 exception 或一个类型为 throwCompletion Record exceptionexception 的 stack trace,由以下给出:

  1. 如果 exception 是一个已作为 exception 抛出的值,则令 record 为为抛出 exception 而创建的 Completion Record。否则令 recordexception

  2. stack 为对应于 record 被创建时的执行点的stack frames 列表

  3. 返回给定 stack 调用构造 stack trace所得的结果。

7.6.3.20. script.Source 类型

本地端定义

script.Source = {
  realm: script.Realm,
  ? context: browsingContext.BrowsingContext,
  ? userContext: browser.UserContext
}

script.Source 类型表示一个 script.Realm, 以及可选的 browsingContext.BrowsingContext 和相关的 browser.UserContext,在其中发生了与 script 相关的事件。

要在给定 source realm获取 source
  1. realmsource realmrealm id

  2. environment settings 为其 realm execution context 的 Realm component 是 source realmenvironment settings object

  3. 如果 environment settings 具有一个关联的 Document

    1. document 为 environment settings 的关联的 Document

    2. navigabledocumentnode navigable

    3. 如果 navigable 不为 null,则令 navigable idnavigablenavigable id

    4. user context idnavigableassociated user contextuser context id

    否则令 navigable 为 null。

  4. source 为一个映射, 其匹配 script.Source 产生式,并将 realm 字段设置为 realm,如果 navigable 不为 null,则将 context 字段设置 为 navigable id,否则不设置, 并且如果 |navigable 不为 null,则将 userContext 字段设置为 user context id, 否则不设置。

  5. 返回 source

7.6.3.21. script.Target 类型

远端定义

script.RealmTarget = {
  realm: script.Realm
}

script.ContextTarget = {
  context: browsingContext.BrowsingContext,
  ? sandbox: text
}

script.Target = (
  script.ContextTarget /
  script.RealmTarget
)

script.Target 类型表示一个值,其要么是 script.Realm,要么是 browsingContext.BrowsingContext。 这在 navigable 标识符可以代表与该 navigable 的 active document 关联的 realm 的情况下很有用。

要在给定 navigable idsandbox从 navigable 获取 realm
  1. navigable尝试navigable id 调用获取 navigable所得的结果。

  2. 如果 sandbox 为 null 或为空字符串:

    1. documentnavigableactive document

    2. environment settings 为其 relevant global object关联的 Documentdocumentenvironment settings object

    3. realmenvironment settingsrealm execution context 的 Realm component。

  3. 否则:令 realm尝试给定 sandboxnavigable 调用 获取或创建 sandbox realm所得的结果。

  4. 返回带有数据 realm成功

这里使用了错误的 错误代码

要在给定 target从 target 获取 realm
  1. 如果 target 匹配 script.ContextTarget 产生式:

    1. sandbox 为 null。

    2. 如果 target 包含 "sandbox",则将 sandbox 设置为 target["sandbox"]。

    3. realm 为以 target["context"] 和 sandbox 调用从 navigable 获取 realm所得的结果。

  2. 否则:

    1. 断言:target 匹配 script.RealmTarget 产生式。

    2. realm idtargetrealm 字段的值。

    3. realm 为给定 realm id 调用获取 realm所得的结果。

  3. 返回带有数据 realm成功

这里使用了错误的 错误代码

7.6.4. 命令

7.6.4.1. script.addPreloadScript 命令

script.addPreloadScript 命令会添加一个preload script

命令类型
script.AddPreloadScript = (
  method: "script.addPreloadScript",
  params: script.AddPreloadScriptParameters
)

script.AddPreloadScriptParameters = {
  functionDeclaration: text,
  ? arguments: [*script.ChannelValue],
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
  ? sandbox: text
}
返回类型
script.AddPreloadScriptResult = {
  script: script.PreloadScript
}
给定 sessioncommand parameters远端步骤为:
  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 代码 invalid argument错误

  2. function declarationcommand parametersfunctionDeclaration 字段。

  3. 如果存在,则令 argumentscommand parametersarguments 字段;否则为空列表

  4. user contexts 为一个集合

  5. navigables 为 null。

  6. 如果 command parameterscontexts 字段存在:

    1. navigables 设置为空集合

    2. 对于 command parameters["contexts"] 中的每个 navigable id

      1. navigable尝试navigable id 调用获取 navigable 所得的结果。

      2. 如果 navigable 不是顶级 traversable,则返回带有错误代码 invalid argument错误

      3. navigable 追加到 navigables

  7. 否则,如果 command parameters 包含 userContexts

    1. user contexts 设置为以 command parameters["userContexts"] 调用创建 集合所得的结果。

    2. 对于 user contexts 中的每个 user context id

      1. user context 设置为以 user context id 调用获取 user context所得的结果。

      2. 如果 user context 为 null,则返回带有错误代码 no such user context错误

  8. 如果存在,则令 sandboxcommand parameters 中 "sandbox" 字段的值;否则为 null。

  9. scriptUUID 的字符串表示。

  10. preload script mapsessionpreload script map

  11. preload script map[script] 设置为一个结构体,其 function declarationfunction declarationargumentsargumentscontextsnavigablessandboxsandbox,并且 user contextsuser contexts

  12. 返回一个新的映射,其匹配 script.AddPreloadScriptResult, 并将 script 字段设置为 script

7.6.4.2. script.disown 命令

script.disown 命令会 disown 给定的 handles。 这并不保证被 handle 的对象会被垃圾回收,因为可能存在 其他 handles 或强 ECMAScript 引用。

命令类型
script.Disown = (
  method: "script.disown",
  params: script.DisownParameters
)

script.DisownParameters = {
  handles: [*script.Handle]
  target: script.Target;
}
返回类型
script.DisownResult = EmptyResult
带有 command parameters远端步骤为:
  1. realm尝试给定 command parameterstarget 字段的值调用从 target 获取 realm所得的结果。

  2. handlescommand parametershandles 字段的值。

  3. 对于 handles 中的每个 handle id

    1. handle maprealmhandle object map

    2. 如果 handle map 包含 handle id,则从 handle map 中移除 handle id

  4. 返回带有数据 null 的成功

7.6.4.3. script.callFunction 命令

script.callFunction 命令会在给定 realm 中用给定参数调用 所提供的函数。

RealmInfo 可以是一个 realm 或 navigable。

注:functionDeclaration 中是箭头函数时, this 参数不会影响函数的 this 绑定。

命令类型
script.CallFunction = (
  method: "script.callFunction",
  params: script.CallFunctionParameters
)

script.CallFunctionParameters = {
  functionDeclaration: text,
  awaitPromise: bool,
  target: script.Target,
  ? arguments: [*script.LocalValue],
  ? resultOwnership: script.ResultOwnership,
  ? serializationOptions: script.SerializationOptions,
  ? this: script.LocalValue,
  ? userActivation: bool .default false,
}
返回类型
script.CallFunctionResult = script.EvaluateResult

TODO:添加 timeout 参数, 如 script.evaluate 中所述。

要在给定 realmserialized arguments listsession 的情况下反序列化 arguments

  1. deserialized arguments list 为空列表

  2. 对于 serialized arguments list 的每个 serialized argument

    1. deserialized argument尝试给定 serialized argumentrealmsession 调用 反序列化 local value 所得的结果。

    2. deserialized argument 追加到 deserialized arguments list

  3. 返回带有数据 deserialized arguments list成功

要在给定 function declarationenvironment settingsbase URLoptions求值 function body

注:function declaration 会被 加括号并求值。

  1. bypassDisabledScripting 为 true。

  2. parenthesized function declaration拼接 «"(", function declaration, ")"» 所得的结果

  3. function script 为以 parenthesized function declarationenvironment settingsbase URLoptionsbypassDisabledScripting 调用创建 classic script所得的结果。

  4. environment settings 调用准备运行 script

  5. function body evaluation statusScriptEvaluation(function script 的 record)。

  6. environment settings 调用运行 script 后清理

  7. 返回 function body evaluation status

带有 sessioncommand parameters远端步骤为:

  1. realm尝试给定 command parameterstarget 字段的值调用从 target 获取 realm所得的结果。

  2. realm idrealmrealm id

  3. environment settings 为其 realm execution context 的 Realm component 是 realmenvironment settings object

  4. command argumentscommand parametersarguments 字段的值。

  5. deserialized arguments 为空列表

  6. 如果 command arguments 不为 null,则将 deserialized arguments 设置为 尝试给定 realmcommand argumentssession 调用 反序列化 arguments所得的结果。

  7. this parametercommand parametersthis 字段的值。

  8. this object 为 null。

  9. 如果 this parameter 不为 null,则将 this object 设置为尝试给定 this parameterrealmsession 调用 反序列化 local value所得的结果。

  10. function declarationcommand parametersfunctionDeclaration 字段的值。

  11. await promisecommand parametersawaitPromise 字段的值。

  12. 如果存在,则令 serialization optionscommand parametersserializationOptions 字段的值, 否则为一个匹配 script.SerializationOptions 产生式且字段被设置为其默认值的映射

  13. 如果存在,则令 result ownershipcommand parametersresultOwnership 字段的值,否则为 none

  14. base URLenvironment settingsAPI base URL

  15. options默认 script fetch options

  16. function body evaluation status 为以 function declarationenvironment settingsbase URLoptions 调用求值 function body所得的结果。

  17. 如果 function body evaluation status.[[Type]] 为 throw

    1. exception details 为给定 realmfunction body evaluation statusresult ownershipsession 调用获取 exception details所得的结果。

    2. 返回一个新的映射,其匹配 script.EvaluateResultException 产生式,并将 exceptionDetails 字段设置为 exception details

  18. function objectfunction body evaluation status.[[Value]]。

  19. 如果 IsCallable(function object) 为 false

    1. 返回一个带有错误代码 invalid argument错误

  20. 如果 command parameters["userActivation"] 为 true,则运行activation notification 步骤。

  21. environment settings 调用准备运行 script

  22. evaluation status 设置为 Call(function object, this object, deserialized arguments)。

  23. 如果 evaluation status.[[Type]] 为 normal,且 await promisetrue,且 IsPromise(evaluation status.[[Value]]):

    1. evaluation status 设置为 Await(evaluation status.[[Value]])。

  24. environment settings 调用运行 script 后清理

  25. 如果 evaluation status.[[Type]] 为 throw

    1. exception details 为给定 realmevaluation statusresult ownershipsession 调用获取 exception details所得的结果。

    2. 返回一个新的映射,其匹配 script.EvaluateResultException 产生式,并将 exceptionDetails 字段设置为 exception details

  26. 断言:evaluation status.[[Type]] 为 normal

  27. result 为以 evaluation status.[[Value]]、serialization optionsresult ownership、 一个新的映射作为 serialization internal map、realmsession 调用序列化为 remote value所得的结果。

  28. 返回一个新的映射,其匹配 script.EvaluateResultSuccess 产生式,并将 realm 字段设置为 realm id, 且将 result 字段设置为 result

7.6.4.4. script.evaluate 命令

script.evaluate 命令会在给定 realm 中求值所提供的 script。为方便起见,可以提供一个 navigable 来代替 realm;在这种情况下, 所使用的 realm 是该 browsing context 的 active document 的 realm。

该方法返回执行所提供 script 的值,除非它返回一个 promise 且 awaitPromise 为 true,在这种情况下会返回该 promise 的已解决值。

命令类型
script.Evaluate = (
  method: "script.evaluate",
  params: script.EvaluateParameters
)

script.EvaluateParameters = {
  expression: text,
  target: script.Target,
  awaitPromise: bool,
  ? resultOwnership: script.ResultOwnership,
  ? serializationOptions: script.SerializationOptions,
  ? userActivation: bool .default false,
}
返回类型
script.EvaluateResult

TODO:添加 timeout 参数。尚不完全清楚这应该如何工作;在 Chrome 中,timeout 似乎并不适用于 promise resolve 步骤,但 这可能并不是客户端想要的行为。

给定 sessioncommand parameters 时,远端步骤为:

  1. realm尝试给定 command parameterstarget 字段的值调用从 target 获取 realm 所得的结果。

  2. realm idrealmrealm id

  3. environment settings 为其 realm execution context 的 Realm component 是 realmenvironment settings object

  4. sourcecommand parametersexpression 字段的值。

  5. await promisecommand parametersawaitPromise 字段的值。

  6. 如果存在,则令 serialization optionscommand parametersserializationOptions 字段的值, 否则为一个映射,其匹配 script.SerializationOptions 产生式,并且字段被设置为其默认值。

  7. 如果存在,则令 result ownershipcommand parametersresultOwnership 字段的值,否则为 none

  8. options默认 script fetch options

  9. base URLenvironment settingsAPI base URL

  10. bypassDisabledScripting 为 true。

  11. script 为以 sourceenvironment settingsbase URLoptionsbypassDisabledScripting 调用创建 classic script所得的结果。

  12. 如果 command parameters["userActivation"] 为 true,则运行 activation notification 步骤。

  13. environment settings 调用准备运行 script

  14. evaluation status 设置为 ScriptEvaluation(script 的 record)。

  15. 如果 evaluation status.[[Type]] 为 normalawait promise 为 true,且 IsPromise(evaluation status.[[Value]]):

    1. evaluation status 设置为 Await(evaluation status.[[Value]])。

  16. environment settings 调用运行 script 后清理

  17. 如果 evaluation status.[[Type]] 为 throw

    1. exception details 为以 realmevaluation statusresult ownershipsession 调用获取 exception details所得的结果。

    2. 返回一个新的映射,其匹配 script.EvaluateResultException 产生式,并将 realm 字段设置为 realm id,且将 exceptionDetails 字段设置为 exception details

  18. 断言:evaluation status.[[Type]] 为 normal

  19. result 为以 evaluation status.[[Value]]、serialization optionsresult ownership、 一个新的映射作为 serialization internal map、realmsession 调用序列化为 remote value所得的结果。

  20. 返回一个新的映射,其匹配 script.EvaluateResultSuccess 产生式,并将 realm 字段设置为 realm id,且 将 result 字段设置为 result

7.6.4.5. script.getRealms 命令

script.getRealms 命令会返回所有 realms 的列表,可选地筛选为特定类型的realms,或筛选为与某个 navigableactive document 关联的 realm。

命令类型
script.GetRealms = (
  method: "script.getRealms",
  params: script.GetRealmsParameters
)

script.GetRealmsParameters = {
  ? context: browsingContext.BrowsingContext,
  ? type: script.RealmType,
}
返回类型
script.GetRealmsResult = {
  realms: [*script.RealmInfo]
}
带有 sessioncommand parameters远端步骤为:
  1. environment settings 为所有其 execution ready flag 已设置的 environment settings objects列表

  2. 如果 command parameters 包含 context

    1. navigable尝试command parameters["context"] 调用 获取 navigable 所得的结果。

    2. documentnavigableactive document

    3. navigable environment settings 为一个列表

    4. 对于 environment settings 中的每个 settings

      1. 如果满足以下任一条件:

        settings 追加到 navigable environment settings

    5. environment settings 设置为 navigable environment settings

  3. realms 为一个列表。

  4. 对于 environment settings 中的每个 settings

    1. realm info 为给定 settings 调用获取 realm info 所得的结果。

    2. 如果 command parameters 包含 type,且 realm info["type"] 不等于 command parameters["type"],则继续

    3. 如果 realm info 不为 null,则将 realm info 追加到 realms

  5. body 为一个映射, 其匹配 script.GetRealmsResult 产生式, 并将 realms 字段设置为 realms

  6. 返回带有数据 body成功

将其扩展为也 允许 realm parents,例如用于嵌套 workers?或者获取所有祖先 workers。

我们可能想要一个 比单纯字面匹配更复杂的筛选系统。

7.6.4.6. script.removePreloadScript 命令

script.removePreloadScript 命令会移除一个 preload script

命令类型
script.RemovePreloadScript = (
  method: "script.removePreloadScript",
  params: script.RemovePreloadScriptParameters
)

script.RemovePreloadScriptParameters = {
  script: script.PreloadScript
}
返回类型
script.RemovePreloadScriptResult = EmptyResult
给定 sessioncommand parameters 时,远端步骤为:
  1. scriptcommand parameters 中 "script" 字段的值。

  2. preload script mapsessionpreload script map

  3. 如果 preload script map包含 script,则返回带有错误 代码 no such script错误

  4. preload script map移除 script

  5. 返回 null

7.6.5. 事件

7.6.5.1. script.message 事件
事件类型
script.Message = (
  method: "script.message",
  params: script.MessageParameters
 )

script.MessageParameters = {
  channel: script.Channel,
  data: script.RemoteValue,
  source: script.Source,
}
远端事件触发器是 在给定 sessionrealmchannel propertiesmessage 时的发出 script message 步骤:
  1. environment settings 为其 realm execution context 的 Realm component 是 realmenvironment settings object

  2. related navigables 为给定 environment settings 调用获取相关 navigables所得的结果。

  3. 如果给定 session、"script.message" 和 related navigables事件已启用

    1. 如果 channel properties 包含 "serializationOptions",则令 serialization optionschannel propertiesserializationOptions 字段的值。 否则令 serialization options 为一个映射, 其匹配 script.SerializationOptions 产生式,并且 字段被设置为其默认值。

    2. 如果 channel properties 包含 "ownership",则令 ownership typechannel properties["ownership"]。 否则令 ownership type 为 "none"。

    3. data 为给定 messageserialization optionsownership type、一个新的 映射作为 serialization internal map 和 realm 调用序列化为 remote value所得的结果。

    4. source 为以 realm 调用获取 source所得的结果。

    5. params 为一个映射,其匹配 script.MessageParameters 产生式,并将 channel 字段设置为 channel properties["channel"], 将 data 字段设置为 data,并将 source 字段设置为 source

    6. body 为一个映射,其匹配 script.Message 产生式,并将 params 字段设置为 params

    7. sessionbody 发出 事件

7.6.5.2. script.realmCreated 事件
事件类型
script.RealmCreated = (
 method: "script.realmCreated",
 params: script.RealmInfo
)
远端事件触发器是:

当调用任何 设置 window environment settings object设置 worker environment settings object设置 worklet environment settings object 算法时,在返回该 settings object 之前立即执行:

  1. environment settings 为新创建的environment settings object

  2. realm info 为给定 environment settings 调用获取 realm info所得的结果。

  3. 如果 realm info 为 null,则返回。

  4. related navigables 为给定 environment settings 调用获取相关 navigables所得的结果。

  5. body 为一个映射, 其匹配 script.RealmCreated 产生式,并将 params 字段设置为 realm info

  6. 对于给定 "script.realmCreated" 和 related navigables 时,启用了事件的 session 集合中的每个 session

    1. sessionbody 发出 事件

给定 sessionnavigablesinclude global 时,带有订阅优先级 2 的远端订阅步骤为:

  1. environment settings 为所有其 execution ready flag 已设置的 environment settings objects的列表。

  2. 对于 environment settings 中的每个 settings

    1. related navigables 为一个新的集合

    2. 如果 settingsrelevant global object关联的 Document 是一个Document

      1. navigablesettingsrelevant global object关联的 Documentnode navigable

      2. 如果 navigable 为 null,则继续。

      3. top-level traversiblenavigable顶级 traversable

      4. 如果 top-level traversible 不在 navigables 中,则继续。

      5. top-level traversible 追加到 related navigables

      否则,如果 include global 为 false,则继续。

    3. realm info 为给定 settings 调用获取 realm info 所得的结果。

    4. 如果 realm info 为 null,则继续。

    5. body 为一个映射,其匹配 script.RealmCreated 产生式,并将 params 字段设置为 realm info

    6. 如果给定 session、 "script.realmCreated" 和 related navigables事件 已启用

      1. sessionbody 发出 事件

这里的顺序是否 应该定义得更好?

7.6.5.3. script.realmDestroyed 事件
事件类型
script.RealmDestroyed = (
  method: "script.realmDestroyed",
  params: script.RealmDestroyedParameters
)

script.RealmDestroyedParameters = {
  realm: script.Realm
}

远端事件触发器是:
定义以下以 document 为参数的卸载 document 清理步骤
  1. related navigables 为空集合

  2. documentnavigable 追加到 related navigables

  3. 对于 documentworklet global scopes 中的每个 worklet global scope

    1. realmworklet global scoperelevant Realm

    2. realm idrealmrealm id

    3. params 为一个映射,其匹配 script.RealmDestroyedParameters 产生式,并将 realm 字段设置为 realm id

    4. body 为一个映射,其匹配 script.RealmDestroyed 产生式,并将 params 字段设置为 params

    5. 对于给定 "script.realmDestroyed" 和 related navigables 时,启用了事件的 session 集合中的每个 session

      1. sessionbody 发出 事件

  4. environment settings 为其 relevant global object关联的 Documentdocumentenvironment settings object

  5. realmenvironment settingsrealm execution context 的 Realm component。

  6. realm idrealmrealm id

  7. params 为一个映射, 其匹配 script.RealmDestroyedParameters 产生式,并将 realm 字段设置为 realm id

  8. body 为一个映射, 其匹配 script.RealmDestroyed 产生式,并将 params 字段设置为 params

  9. 对于给定 "script.realmDestroyed" 和 related navigables 时,启用了事件的 session 集合中的每个 session

    1. sessionbody 发出 事件

每当一个 worker event loop event loop 被销毁时,不论是因为 worker 到达其生命周期末尾,还是通过 终止 worker 算法提前销毁:

  1. environment settings 为其 event loopresponsible event loopenvironment settings object

  2. related navigables 为给定 environment settings 调用获取相关 navigables所得的结果。

  3. realmenvironment settingsenvironment settings object 的 Realm

  4. realm idrealmrealm id

  5. params 为一个映射, 其匹配 script.RealmDestroyedParameters 产生式,并将 realm 字段设置为 realm id

  6. body 为一个映射, 其匹配 script.RealmDestroyed 产生式,并将 params 字段设置为 params

7.7. storage 模块

storage 模块包含与存储相关的功能和 事件。

storage partition 是一个命名空间,用户代理可在其中组织诸如 cookies 和 local storage 之类的持久化数据。

storage partition key 是一个映射,它唯一标识一个 storage partition

7.7.1. 定义

远端定义

StorageCommand = (
  storage.DeleteCookies //
  storage.GetCookies //
  storage.SetCookie
)

本地端定义

StorageResult = (
  storage.DeleteCookiesResult /
  storage.GetCookiesResult /
  storage.SetCookieResult
)

7.7.2. 类型

7.7.2.1. storage.PartitionKey 类型

本地端定义

storage.PartitionKey = {
  ? userContext: text,
  ? sourceOrigin: text,
  Extensible,
}

storage.PartitionKey 类型表示一个 storage partition key

以下标准 storage partition key 属性表 枚举了具有公认含义、remote end 可以选择支持的属性。实现可以定义额外的扩展 storage partition key 属性

属性 定义
"userContext" 一个 user context id
"sourceOrigin" 可以访问该 storage partition 的资源的 origin 的序列化

Remote ends 可以支持任意数量的扩展 storage partition key 属性。为了避免与其他实现冲突,这些 属性必须以供应商和用户代理的唯一标识符开头, 后跟 U+003A (:)。

remote end 具有一个映射,即storage partition key 属性的默认值,其中包含零个或多个条目。每个键必须是 标准 storage partition key 属性表中的成员(当该 storage partition key 对应于标准 storage partition 时),或是一个 扩展 storage partition key 属性 (当它不对应标准 storage partition 时);其值 表示当用户没有提供显式值时要使用的该 partition key 的默认值。 精确的条目是实现定义的,并由实现采用的 storage partitioning 决定。

remote end 具有一个列表,即必需 partition key 属性,其中包含零个或多个条目。每个键必须是 标准 storage partition key 属性表中的成员(当该 storage partition key 对应于标准 storage partition 时),或是一个 扩展 storage partition key 属性 (当它不对应标准 storage partition 时)。精确的 条目是实现定义的,并由实现采用的 storage partitioning 决定。该列表只包含没有可用默认值的 partition keys。因此,该列表不得与storage partition key 属性的默认值的键共享任何条目。

要在给定 filter 的情况下反序列化 filter
  1. deserialized filter 为空映射

  2. 对于 filter 中的每个 namevalue

    1. deserialized namecookie conversion 表中与 JSON 键 name 对应的字段名称。

    2. 如果 name 是 "value",则将 deserialized value 设置为以 value 调用反序列化 protocol bytes所得的结果, 否则令 deserialized valuevalue

    3. deserialized filter[deserialized name] 设置deserialized value

  3. 返回 deserialized filter

要在给定 partition spec 的情况下展开 storage partition spec
  1. 如果 partition spec 为 null:

    1. partition spec 设置为空映射

  2. 否则,如果 partition spec["type"] 是 "context":

    1. navigable尝试给定 partition spec["context"] 调用获取 navigable所得的结果。

    2. partition keynavigable关联的 storage partitionkey

    3. 返回带有数据 partition key成功

  3. partition key 为空映射

  4. 对于storage partition key 属性的默认值中的每个 namedefault value

    1. valuepartition spec[name](如果它存在),否则为 default value

    2. partition key[name] 设置value

  5. 对于 remote end 的必需 partition key 属性中的每个 name

    1. 如果 partition spec[name] 存在

      1. partition key][name] 设置partition spec[name]。

    2. 否则:

      1. 返回带有错误代码 underspecified storage partition错误

  6. 返回带有数据 partition key成功

要在给定 storage partition key 的情况下获取 cookie store
  1. 如果 storage partition key 唯一标识一个现存的 storage partition

    1. store 为该 storage partitioncookie store

    2. 返回带有数据 store成功

  2. 返回带有错误 代码 no such storage partition错误

要在给定 stored cookiefilter 的情况下匹配 cookie
  1. 对于 filter 中的每个 namevalue

    1. 如果 stored cookie[name] 不等于 value

      1. 返回 false。

  2. 返回 true。

要在给定 cookie storefilter 的情况下获取匹配的 cookies
  1. cookies 为一个新列表。

  2. deserialized filter 设置为以 filter 调用反序列化 filter所得的结果。

  3. 对于 cookie store 中的每个 stored cookie

    1. 如果以 stored cookiedeserialized filter 调用匹配 cookie所得的结果为 true:

      1. stored cookie 追加到 cookies

  4. 返回 cookies

7.7.3. 命令

7.7.3.1. storage.getCookies 命令

storage.getCookies 命令会检索零个或多个 cookies, 这些 cookies 匹配一组提供的 参数。

命令类型
storage.GetCookies = (
  method: "storage.getCookies",
  params: storage.GetCookiesParameters
)


storage.CookieFilter = {
  ? name: text,
  ? value: network.BytesValue,
  ? domain: text,
  ? path: text,
  ? size: js-uint,
  ? httpOnly: bool,
  ? secure: bool,
  ? sameSite: network.SameSite,
  ? expiry: js-uint,
  Extensible,
}

storage.BrowsingContextPartitionDescriptor = {
  type: "context",
  context: browsingContext.BrowsingContext
}

storage.StorageKeyPartitionDescriptor = {
  type: "storageKey",
  ? userContext: text,
  ? sourceOrigin: text,
  Extensible,
}

storage.PartitionDescriptor = (
  storage.BrowsingContextPartitionDescriptor /
  storage.StorageKeyPartitionDescriptor
)

storage.GetCookiesParameters = {
  ? filter: storage.CookieFilter,
  ? partition: storage.PartitionDescriptor,
}
返回类型
storage.GetCookiesResult = {
  cookies: [*network.Cookie],
  partitionKey: storage.PartitionKey,
}
带有 sessioncommand parameters远端步骤为:
  1. 如果存在,则令 filtercommand parametersfilter 字段的值; 否则令其为空映射

  2. 如果存在,则令 partition speccommand parameterspartition 字段的值;否则为 null。

  3. partition key尝试partition spec 调用展开 storage partition spec所得的结果。

  4. store尝试partition key 调用获取 cookie store所得的结果。

  5. cookies 为以 storefilter 调用获取匹配 cookies所得的结果。

  6. serialized cookies 为一个新列表。

  7. 对于 cookies 中的每个 cookie

    1. serialized cookie 为给定 cookie 调用序列化 cookie所得的结果。

    2. serialized cookie 追加到 serialized cookies

  8. body 为一个映射, 其匹配 storage.GetCookiesResult 产生式, 并将 cookies 字段设置为 serialized cookies,将 partitionKey 字段设置为 partition key

  9. 返回带有数据 body成功

7.7.3.2. storage.setCookie 命令

storage.setCookie 命令会在 cookie store 中创建一个新的 cookie, 替换该 store 中根据 [COOKIES] 匹配的任何 cookie。

命令类型
storage.SetCookie = (
  method: "storage.setCookie",
  params: storage.SetCookieParameters,
)


storage.PartialCookie = {
  name: text,
  value: network.BytesValue,
  domain: text,
  ? path: text,
  ? httpOnly: bool,
  ? secure: bool,
  ? sameSite: network.SameSite,
  ? expiry: js-uint,
  Extensible,
}

storage.SetCookieParameters = {
  cookie: storage.PartialCookie,
  ? partition: storage.PartitionDescriptor,
}
返回类型
storage.SetCookieResult = {
  partitionKey: storage.PartitionKey
}
带有 sessioncommand parameters远端步骤为:
  1. cookie speccommand parameterscookie 字段的值。

  2. 如果存在,则令 partition speccommand parameterspartition 字段的值;否则为 null。

  3. partition key尝试partition spec 调用展开 storage partition spec所得的结果。

  4. store尝试partition key 调用获取 cookie store所得的结果。

  5. deserialized value 为以 cookie spec["value"] 调用反序列化 protocol bytes所得的结果。

  6. 使用 cookie name cookie spec["name"]、 cookie value deserialized valuecookie domain cookie spec["domain"],以及下列在 cookie conversion 表中列出的 cookie 概念的属性-值列表,在 store创建 cookie

    Cookie path

    如果 cookie spec["path"] 存在,则为它;否则为 "/"。

    Cookie secure only

    如果 cookie spec["secure"] 存在,则为它;否则为 false。

    Cookie HTTP only

    如果 cookie spec["httpOnly"] 存在,则为它;否则为 false。

    Cookie expiry time

    如果 cookie spec["expiry"] 存在,则为它;否则保持未设置以 表示这是一个 session cookie。

    注:cookie 的 expiry 值 可能会由 remote end 按照 Cookie Lifetime Limits 进行限制。

    Cookie same site

    如果 cookie spec["sameSite"] 存在,则为它;否则保持未设置以 表示未定义 same site 策略。

    如果此步骤在未向 cookie store 插入 cookie 的情况下中止,则返回带有错误 代码 unable to set cookie错误

  7. body 为一个映射, 其匹配 storage.SetCookieResult 产生式, 并将 partitionKey 字段设置为 partition key

  8. 返回带有数据 body成功

7.7.3.3. storage.deleteCookies 命令

storage.deleteCookies 命令会移除零个或多个 cookies, 这些 cookies 匹配一组提供的 参数。

命令类型
storage.DeleteCookies = (
  method: "storage.deleteCookies",
  params: storage.DeleteCookiesParameters,
)

storage.DeleteCookiesParameters = {
  ? filter: storage.CookieFilter,
  ? partition: storage.PartitionDescriptor,
}
返回类型
storage.DeleteCookiesResult = {
  partitionKey: storage.PartitionKey
}
带有 sessioncommand parameters远端步骤为:
  1. 如果存在,则令 filtercommand parametersfilter 字段的值;否则令其为空映射

  2. 如果存在,则令 partition speccommand parameterspartition 字段的值;否则为 null。

  3. partition key尝试partition spec 调用展开 storage partition spec所得的结果。

  4. store尝试partition key 调用获取 cookie store所得的结果。

  5. cookies 为以 storefilter 调用获取匹配 cookies所得的结果。

  6. 对于 cookies 中的每个 cookie

    1. store 中移除 cookie

  7. body 为一个映射, 其匹配 storage.DeleteCookiesResult 产生式, 并将 partitionKey 字段设置为 partition key

  8. 返回带有数据 body成功

7.8. log 模块

log 模块包含与日志记录相关的功能和事件。

BiDi Session 有一个 log event buffer, 它是一个从 navigable id 到该 context 中尚未被 发出的 log events 列表的映射。用户代理可以对此 buffer 施加最大大小限制, 但须满足以下条件:如果事件 A 和 B 在同一 context 中发生,且 A 发生在 B 之前,并且二者都被添加到 buffer 中,则 B 的条目不得在 A 的条目之前被移除。

要在给定 sessionnavigablesevent 的情况下缓冲 log event

  1. buffersessionlog event buffer

  2. navigable ids 为一个新列表。

  3. 对于 navigables 中的每个 navigable

    1. navigablenavigable id 追加到 navigable ids

  4. 对于 navigable ids 中的每个 navigable id

    1. other navigables 为空列表

    2. 对于 navigable ids 中的每个 other id

    3. 如果 other id 不等于 navigable id,则将 other id 追加到 other navigables

    4. 如果 buffer 不包含 navigable id,则令 buffer[navigable id] 为一个新列表。

    5. 将 (event, other navigables) 追加到 buffer[navigable id]。

注:我们在这里存储其他 navigables,是为了让 每个 event 只被发出一次。实践中,这只与能够关联到 多个 navigables 的 workers 有关。

我们是否要以 browsing context 或 top-level traversable 作为键? 二者的区别在于:如果某个 event 发生在 frame 中,且该 frame 在本地端订阅顶层 navigable 的 log events 之前发生导航,会产生什么结果。

7.8.1. 定义

本地端定义

LogEvent = (
  log.EntryAdded
)

7.8.2. 类型

7.8.2.1. log.LogEntry

本地端定义

log.Level = "debug" / "info" / "warn" / "error"

log.Entry = (
  log.GenericLogEntry /
  log.ConsoleLogEntry /
  log.JavascriptLogEntry
)

log.BaseLogEntry = (
  level: log.Level,
  source: script.Source,
  text: text / null,
  timestamp: js-uint,
  ? stackTrace: script.StackTrace,
)

log.GenericLogEntry = {
  log.BaseLogEntry,
  type: text,
}

log.ConsoleLogEntry = {
  log.BaseLogEntry,
  type: "console",
  method: text,
  args: [*script.RemoteValue],
}

log.JavascriptLogEntry = {
  log.BaseLogEntry,
  type: "javascript",
}

每个 log event 都由一个 log.Entry 对象表示。它具有 type 属性,表示所添加 log entry 的类型;具有 level 属性,表示严重性;具有 source 属性,表示 log entry 的来源;具有 text 属性, 表示日志消息字符串本身;并具有 timestamp 属性, 对应于生成该 log entry 的时间。log.Entry 的特定变体 用于表示来自不同来源的日志,并提供特定于该 entry 类型的附加字段。

7.8.3. 事件

7.8.3.1. log.entryAdded 事件
事件类型
log.EntryAdded = (
 method: "log.entryAdded",
 params: log.Entry,
)

远端事件触发器为:

定义以下带有 methodargsoptionsconsole 步骤

  1. 对于 活动 BiDi 会话中的每个 session

    1. 如果 method 是 "error" 或 "assert",则令 level 为 "error"。如果 method 是 "debug" 或 "trace", 则令 level 为 "debug"。如果 method 是 "warn",则令 level 为 "warn"。否则令 level 为 "info"。

    2. timestamp 为表示当前 UTC 日期和时间的 time value

    3. text 为空字符串。

    4. 如果 args[0] 的 Type 是 String,且 args[0] 包含一个 formatting specifier,则令 formatted argsFormatter(args)。否则 令 formatted argsargs

      注:Formatter 操作在 console 规范中 未充分定义,不同实现之间的格式化可能不一致。

    5. 对于 formatted args 中的每个 arg

      1. 如果 arg 不是 args 中的第一个条目,则向 text 追加一个 U+0020 SPACE。

      2. 如果 arg 是一个原始 ECMAScript 值,则将 ToString(arg) 追加到 text。否则将一个实现定义的字符串追加到 text

    6. realm当前 Realm Recordrealm id

    7. serialized args 为一个新列表。

    8. serialization options 为一个映射,其匹配 script.SerializationOptions 产生式,且各字段设置为 其默认值。

    9. 对于 args 中的每个 arg

      1. serialized arg 为以 arg 作为 value、serialization optionsnone 作为 ownership type、一个新的映射作为 serialization internal map、 realmsession 调用序列化为 remote value所得的结果。

      2. serialized arg 添加到 serialized args

    10. source 为给定当前 Realm Record 调用获取 source所得的结果。

    11. stack当前 stack trace

    12. entry 为一个映射,其匹配 log.ConsoleLogEntry 产生式, 并将 level 字段设置为 level,将 text 字段设置为 text,将 timestamp 字段设置为 timestamp,将 stackTrace 字段设置为 stack,将 method 字段设置 为 method, 将 source 字段设置为 source, 并将 args 字段设置为 serialized args

    13. body 为一个映射,其匹配 log.EntryAdded 产生式,并将 params 字段设置为 entry

    14. settings当前 settings object

    15. related navigables 为给定 settings 调用获取相关 navigables所得的结果。

    16. 如果以 session、"log.entryAdded" 和 related navigables 调用event is enabled所得的结果为 true,则以 sessionbody 调用发出事件

      否则,以 sessionrelated browsing contextsbody 调用缓冲 log event

定义以下带有参数 scriptline numbercolumn numbermessagehandled错误报告步骤

  1. 如果 handled 为 true,则返回。

  2. settingsscriptsettings object

  3. timestamp 为表示当前 UTC 日期和时间的 time value

  4. stack 为以对应于所报告错误的 exception 调用exception 的 stack trace所得的结果。

  5. source 为给定当前 Realm Record 调用获取 source所得的结果。

  6. entry 为一个映射, 其匹配 log.JavascriptLogEntry 产生式, 并将 level 设置为 "error",将 text 设置为 message,将 source 设置为 source,将 timestamp 设置为 timestamp,并将 stackTrace 字段设置为 stack

  7. body 为一个映射, 其匹配 log.EntryAdded 产生式,并将 params 字段设置为 entry

  8. related navigables 为给定 settings 调用获取相关 navigables所得的结果。

  9. 对于 活动 BiDi 会话中的每个 session

    1. 如果以 session、"log.entryAdded" 和 related navigables 调用event is enabled所得的结果为 true,则以 sessionbody 调用发出事件

      否则,以 sessionrelated browsing contextsbody 调用缓冲 log event

还有许多东西 需要日志记录。CDP 有 LogEntryAdded 类型 xml、 javascript、network、storage、appcache、rendering、security、deprecation、 worker、violation、intervention、recommendation、other。这些是在由不同方法表示的 js exception 和 console API 类型之外的类型。

允许 实现定义的 log 类型

带有 订阅优先级 10,且给定 sessionnavigablesinclude global 时,远端订阅步骤为:

  1. 对于 sessionlog event buffer 中的每个 navigable idevents

    1. maybe context 为给定 navigable id 获取 navigable所得的结果。

    2. 如果 maybe context 是一个错误, 则从 log event buffer 中移除 navigable id 并继续。

    3. navigablemaybe context 的 data

    4. top level navigablenavigabletop-level traversable

    5. 如果 include global 为 true 且 top level navigable 不在 navigables 中, 或者如果 include global 为 false 且 top level navigablenavigables 中:

      1. 对于 events 中的每个 (event, other navigables):

        1. sessionevent 发出事件

        2. 对于 other navigables 中的每个 other context id

          1. 如果 log event buffer 包含 other context id,则从 log event buffer[other context id] 中移除 event

7.9. input 模块

input 模块包含用于 模拟用户输入的功能。

7.9.1. 定义

远端定义

InputCommand = (
  input.PerformActions //
  input.ReleaseActions //
  input.SetFiles
)
InputResult = (
  input.PerformActionsResult /
  input.ReleaseActionsResult /
  input.SetFilesResult
)

本地端定义

InputEvent = (
  input.FileDialogOpened
)

7.9.2. 类型

7.9.2.1. input.ElementOrigin

input.ElementOrigin 类型表示将用作坐标原点的一个 Element

input.ElementOrigin = {
  type: "element",
  element: script.SharedReference
}
给定 object 时,is input.ElementOrigin 步骤为:
  1. 如果 object 是一个匹配 input.ElementOrigin 产生式的映射, 则返回 true。

  2. 返回 false。

给定 session 时,要获取 get Element from input.ElementOrigin steps
  1. 返回以下给定 originnavigable 的步骤:

    1. 断言:origin 匹配 input.ElementOrigin

    2. documentnavigable活动文档

    3. referenceorigin["element"]

    4. environment settings环境设置对象,其 相关全局对象关联 Documentdocument

    5. realmenvironment settingsrealm execution context 的 Realm 组件。

    6. element尝试referencerealmsession 调用 反序列化 remote reference所得的结果。

    7. 如果 element 没有实现 Element, 则返回带有错误代码 no such element错误

    8. 返回带有数据 element成功

7.9.3. 命令

7.9.3.1. input.performActions 命令

input.performActions 命令会执行指定的用户输入 actions 序列。

注:有关此命令行为的详细描述,请参见 actions section of [WEBDRIVER]

命令类型
input.PerformActions = (
  method: "input.performActions",
  params: input.PerformActionsParameters
)

input.PerformActionsParameters = {
  context: browsingContext.BrowsingContext,
  actions: [*input.SourceActions]
}

input.SourceActions = (
  input.NoneSourceActions /
  input.KeySourceActions /
  input.PointerSourceActions /
  input.WheelSourceActions
)

input.NoneSourceActions = {
  type: "none",
  id: text,
  actions: [*input.NoneSourceAction]
}

input.NoneSourceAction = input.PauseAction

input.KeySourceActions = {
  type: "key",
  id: text,
  actions: [*input.KeySourceAction]
}

input.KeySourceAction = (
  input.PauseAction /
  input.KeyDownAction /
  input.KeyUpAction
)

input.PointerSourceActions = {
  type: "pointer",
  id: text,
  ? parameters: input.PointerParameters,
  actions: [*input.PointerSourceAction]
}

input.PointerType = "mouse" / "pen" / "touch"

input.PointerParameters = {
  ? pointerType: input.PointerType .default "mouse"
}

input.PointerSourceAction = (
  input.PauseAction /
  input.PointerDownAction /
  input.PointerUpAction /
  input.PointerMoveAction
)

input.WheelSourceActions = {
  type: "wheel",
  id: text,
  actions: [*input.WheelSourceAction]
}

input.WheelSourceAction = (
  input.PauseAction /
  input.WheelScrollAction
)

input.PauseAction = {
  type: "pause",
  ? duration: js-uint
}

input.KeyDownAction = {
  type: "keyDown",
  value: text
}

input.KeyUpAction = {
  type: "keyUp",
  value: text
}

input.PointerUpAction = {
  type: "pointerUp",
  button: js-uint,
}

input.PointerDownAction = {
  type: "pointerDown",
  button: js-uint,
  input.PointerCommonProperties
}

input.PointerMoveAction = {
  type: "pointerMove",
  x: float,
  y: float,
  ? duration: js-uint,
  ? origin: input.Origin,
  input.PointerCommonProperties
}

input.WheelScrollAction = {
  type: "scroll",
  x: js-int,
  y: js-int,
  deltaX: js-int,
  deltaY: js-int,
  ? duration: js-uint,
  ? origin: input.Origin .default "viewport",
}

input.PointerCommonProperties = (
  ? width: js-uint,
  ? height: js-uint,
  ? pressure: (0.0..1.0),
  ? tangentialPressure: (-1.0..1.0),
  ? twist: (0..359),
  ; 0 .. Math.PI / 2
  ? altitudeAngle: (0.0..1.5707963267948966),
  ; 0 .. 2 * Math.PI
  ? azimuthAngle: (0.0..6.283185307179586),
)

input.Origin = "viewport" / "pointer" / input.ElementOrigin
返回类型
input.PerformActionsResult = EmptyResult

带有 sessioncommand parameters 时,远端步骤为:

  1. navigable idcommand parameterscontext 字段的值。

  2. navigable尝试navigable id 调用获取 navigable所得的结果。

  3. input state 为以 sessionnavigable顶级 traversable 调用获取 input state所得的结果。

  4. actions options 为一个新的 actions options,其中 is element origin 步骤设置为 is input.ElementOrigin,且 get element origin 步骤设置为给定 session 调用get Element from input.ElementOrigin steps所得的结果。

  5. actions by tick 为尝试以 input statecommand parametersactions options 提取 action sequence所得的结果。

  6. 尝试input stateactions by ticknavigableactions options dispatch actions

  7. 返回带有数据 null 的成功

7.9.3.2. input.releaseActions 命令

input.releaseActions 命令会重置与当前 session 关联的 input state。

命令类型
input.ReleaseActions = (
  method: "input.releaseActions",
  params: input.ReleaseActionsParameters
)

input.ReleaseActionsParameters = {
  context: browsingContext.BrowsingContext,
}
返回类型
input.ReleaseActionsResult = EmptyResult

给定 sessioncommand parameters 时,远端步骤为:

  1. navigable idcommand parameterscontext 字段的值。

  2. navigable尝试navigable id 调用获取 navigable所得的结果。

  3. top-level traversablenavigable顶级 traversable

  4. input state 为以 sessiontop-level traversable 调用获取 input state所得的结果。

  5. actions options 为一个新的 actions options,其中 is element origin 步骤设置为 is input.ElementOrigin,且 get element origin 步骤设置为给定 session 调用get Element from input.ElementOrigin steps所得的结果。

  6. undo actionsinput stateinput cancel list 的逆序。

  7. 尝试undo actions、0、navigableactions options dispatch tick actions

  8. sessiontop-level traversable 调用重置 input state

  9. 返回带有数据 null 的成功

7.9.3.3. input.setFiles 命令

input.setFiles 命令会将给定 input 元素(其 type 为 file)的 files 属性 设置为一组文件路径。

命令类型
input.SetFiles = (
  method: "input.setFiles",
  params: input.SetFilesParameters
)

input.SetFilesParameters = {
  context: browsingContext.BrowsingContext,
  element: script.SharedReference,
  files: [*text]
}
返回类型
input.SetFilesResult = EmptyResult

给定 sessioncommand parameters 时,远端步骤为:

  1. navigable idcommand parameters["context"] 字段的值。

  2. navigable尝试navigable id 调用获取 navigable所得的结果。

  3. documentnavigable活动文档

  4. environment settings环境设置对象,其 相关全局对象关联 Documentdocument

  5. realmenvironment settingsrealm execution context 的 Realm 组件。

  6. element尝试command parameters["element"]、realmsession 调用反序列化 remote reference所得的结果。

  7. 如果 element 没有实现 Element, 则返回带有错误 代码 no such element错误

  8. 如果 element 没有实现 HTMLInputElementelementtype 不处于 File Upload 状态,或者 elementdisabled, 则返回带有错误 代码 unable to set file input错误

  9. 如果 files大小大于 1,且 elementmultiple 属性未设置,则返回带有错误代码 unable to set file input错误

  10. filescommand parameters["files"] 字段的值。

  11. selected fileselementselected files

  12. 如果 filesselected files交集大小等于 selected files大小,且等于 files大小,则在用户交互任务源上,给定 element 排入一个元素任务,以在 element 上触发名为 cancel 的事件,并将 bubbles 属性初始化为 true。

    注:浏览器中的取消通常由文件选择的变化来 确定。换句话说,如果没有变化,则会发送一个 "cancel" 事件。

  13. 否则,以 files 作为 用户的选择,更新文件选择

  14. 如果出于任何原因,远端无法将 elementselected files 设置为 files 中给出的路径对应的文件, 则返回带有错误代码 unsupported operation 的错误。

    注:例如,远端可能 无法将 selected files 设置为文件系统中当前不存在的文件。

  15. 返回带有数据 null 的成功

7.9.4. 事件

7.9.4.1. input.fileDialogOpened 事件
事件类型
input.FileDialogOpened = (
   method: "input.fileDialogOpened",
   params: input.FileDialogInfo
)

input.FileDialogInfo = {
   context: browsingContext.BrowsingContext,
   ? userContext: browser.UserContext,
   ? element: script.SharedReference,
   multiple: bool,
}

WebDriver BiDi file picker options 是一个结构体,带有一个名为 multiple项目, 它是一个布尔值。

远端事件触发器是给定 element element 和 可选的 WebDriver BiDi file picker options file picker options(默认:null)时的 WebDriver BiDi file dialog opened 步骤:

注:与其他用户提示处理器不同,默认 行为是允许文件对话框被 打开。

  1. navigableelementnode documentnavigable

  2. navigable idnavigablenavigable id

  3. user context idnavigable关联用户 上下文user context id

  4. multiplefalse

  5. 如果 element 不是 null 且 elementmultiple 属性已设置, 则将 multiple 设置为 true

  6. 如果 file picker options 不是 null 且 file picker optionsmultiple 为 true,则将 multiple 设置为 true

  7. related navigables 为一个包含 navigable集合

  8. 对于给定 "input.fileDialogOpened" 和 related navigables 时的事件已启用的会话集合中的每个 session

    1. params 为一个匹配 input.FileDialogInfo 产生式的映射,其中 context 字段设置为 navigable iduserContext 字段设置为 user context id,且 multiple 字段设置为 multiple

    2. 如果 element 不是 null:

      1. shared id 为以 elementsession 调用获取 node 的 shared id所得的结果。

      2. params["element"] 设置为 shared id

    3. body 为一个匹配 input.fileDialogOpened 产生式的映射,其 params 字段设置为 params

    4. sessionbody 发出 事件

  9. dismissed 为 false。

  10. 对于 活动 BiDi 会话中的每个 session

    1. user prompt handlersessionuser prompt handler

    2. 如果 user prompt handler 不是 null:

    3. 断言:user prompt handler 是一个映射

    4. 如果 user prompt handler 包含 "file":

      1. 如果 user prompt handler["file"] 不等于 "ignore",则将 dismissed 设置为 true。

    5. 否则,如果 user prompt handler 包含 "default" 且 user prompt handler["default"] 不等于 "ignore",则将 dismissed 设置为 true。

  11. 返回 dismissed

7.10. webExtension 模块

webExtension 模块包含用于 管理 Web 扩展以及与其交互的功能。

7.10.1. 定义

远端定义

WebExtensionCommand = (
  webExtension.Install //
  webExtension.Uninstall
)

本地端定义

WebExtensionResult = (
  webExtension.InstallResult /
  webExtension.UninstallResult
)

7.10.2. 类型

7.10.2.1. webExtension.Extension 类型
webExtension.Extension = text

webExtension.Extension 类型表示远端内的 Web 扩展 id。

7.10.3. 命令

7.10.3.1. webExtension.install 命令

webExtension.install 命令会在远端中安装一个 Web 扩展。

命令类型
webExtension.Install = (
   method: "webExtension.install",
   params: webExtension.InstallParameters
)

webExtension.InstallParameters = {
   extensionData: webExtension.ExtensionData,
}

webExtension.ExtensionData = (
   webExtension.ExtensionArchivePath /
   webExtension.ExtensionBase64Encoded /
   webExtension.ExtensionPath
)

webExtension.ExtensionPath = {
   type: "path",
   path: text,
}

webExtension.ExtensionArchivePath = {
   type: "archivePath",
   path: text,
}

webExtension.ExtensionBase64Encoded = {
   type: "base64",
   value: text,
}
返回类型
webExtension.InstallResult = {
  extension: webExtension.Extension
}
给定 bytes 时,要提取 zip 归档
  1. 执行实现定义的步骤,使用 zip 压缩 算法解码 bytes。TODO:为 zip 解码找到更好的引用。

  2. 如果前一步失败(例如,因为 bytes 并不表示有效的 zip 压缩 数据),则返回带有错误代码 invalid web extension错误。否则令 entry 为一个目录条目, 其中包含提取出的文件系统条目。

  3. 返回 entry

给定 extension data spec 时,要展开 web extension data spec
  1. typeextension data spec["type"]。

  2. 如果不支持使用 type 安装 Web 扩展,则返回带有错误 代码 unsupported operation错误

  3. 在以下条件及关联步骤列表中,运行其关联条件为 true 的第一组步骤:

    type 是字符串 "path"
    1. pathextension data spec["path"]。

    2. locator 为一个目录定位器,其路径path,且其root 对应于文件 系统的根。

    3. entry 为给定 locator 调用定位条目所得的结果。

    type 是字符串 "archivePath"
    1. archive pathextension data spec["path"]。

    2. locator 为一个文件定位器,其路径archive path,且其root 对应于文件 系统的根。

    3. archive entry 为给定 locator 调用定位条目所得的结果。

    4. 如果 archive entry 为 null,则返回 null。

    5. bytesarchive entry二进制数据

    6. entry尝试给定 bytes 调用提取 zip 归档所得的结果。

    type 是字符串 "base64"
    1. bytesforgiving-base64 解码 extension data spec["value"] 所得的结果。

    2. 如果 bytes 为 failure,则返回 null。

    3. entry尝试给定 bytes 调用提取 zip 归档所得的结果。

  4. 返回 entry

带有 command parameters 时,远端步骤为:
  1. 如果不支持安装 Web 扩展,则返回带有错误 代码 unsupported operation错误

  2. extension data speccommand parameters["extensionData"]。

  3. extension directory entry尝试extension data spec 调用展开 web extension data spec所得的结果。

  4. 如果 extension directory entry 为 null,则返回带有错误代码 invalid web extension错误

  5. 执行实现定义的步骤,以从 extension directory entry 安装 Web 扩展。如果这失败,则返回带有错误代码 invalid web extension错误。否则令 extension id 为新安装的 Web 扩展的唯一标识符。

  6. result 为一个匹配 webExtension.InstallResult 产生式的映射,其中 extension 字段设置为 extension id

  7. 返回带有数据 result成功

注:浏览器默认可能只是临时安装 Web 扩展, 以便它们会在下次关闭时自动卸载。

7.10.3.2. webExtension.uninstall 命令

webExtension.uninstall 命令会为 远端卸载一个 Web 扩展。

命令类型
webExtension.Uninstall = (
   method: "webExtension.uninstall",
   params: webExtension.UninstallParameters
)

webExtension.UninstallParameters = {
   extension: webExtension.Extension,
}
返回类型
webExtension.UninstallResult = EmptyResult
带有 command parameters 时,远端步骤为:
  1. extensioncommand parameters["extension"]。

  2. 如果远端没有 id 等于 extension 的 Web 扩展,则返回带有错误代码 no such web extension错误

  3. 执行任何实现定义的步骤,以从远端移除该 Web 扩展。如果这失败,则返回带有错误代码 unknown error错误

  4. 返回带有数据 null 的成功

8. 对其他规范的补丁

本规范要求对外部规范进行一些更改,以提供必要的 集成点。假定这些补丁将作为标准化流程的一部分提交到其他规范中。

8.1. HTML

report an error 算法被修改,在末尾增加一个步骤:

  1. 调用外部规范中定义的任何 error reporting steps,传入 scriptlinecolmessage,以及如果错误已 处理则为 true,否则为 false。

8.2. Console

其他规范可以定义 console steps

  1. 在以 参数 nameprinterArgsoptions(如果未提供该参数则为 undefined)调用 Printer 操作时,调用 外部规范中定义的任何 console steps,并传入参数 nameprinterArgsoptions

8.3. CSS

8.3.1. 确定设备像素比

determine the device pixel ratio 算法的开头插入以下步骤:

  1. 如果 device pixel ratio overrides 包含 windownavigable,则返回 device pixel ratio overrides[windownavigable]。

9. 附录

本节为非规范性内容。

9.1. 外部规范

注:该列表并不详尽,且可能不是最新的。

以下外部规范定义了额外的 WebDriver BiDi 模块:

  1. Digital Credentials API

  2. Permissions

  3. nav-speculation

  4. User-Agent Client Hints

  5. Web Bluetooth

索引

由本规范定义的术语

由引用定义的术语

参考文献

规范性参考文献

[ACCNAME-1.1]
Joanmarie Diggs; Bryan Garaventa; Michael Cooper. 可访问 名称与描述计算 1.1. URL: https://w3c.github.io/accname/
[CONSOLE]
Dominic Farolino; Robert Kowalski; Terin Stock. Console 标准. 现行标准. URL: https://console.spec.whatwg.org/
[COOKIES]
A. Barth. HTTP 状态管理机制. 2011 年 4 月. 提议标准. URL: https://httpwg.org/specs/rfc6265.html
[CORE-AAM-1.1]
Joanmarie Diggs; et al. 核心可访问性 API 映射 1.1. URL: https://w3c.github.io/core-aam/
[CSS-COLOR-ADJUST-1]
Elika Etemad; et al. CSS 颜色调整 模块 Level 1. URL: https://drafts.csswg.org/css-color-adjust-1/
[CSS-OVERFLOW-3]
Elika Etemad; Florian Rivoal. CSS Overflow 模块 Level 3. URL: https://drafts.csswg.org/css-overflow-3/
[CSS-PAINT-API-1]
Ian Kilpatrick; Dean Jackson. CSS Painting API Level 1. URL: https://drafts.css-houdini.org/css-paint-api-1/
[CSS2]
Bert Bos; et al. 层叠样式表 Level 2 Revision 1 (CSS 2.1) 规范. URL: https://drafts.csswg.org/css2/
[CSSOM-VIEW-1]
Simon Fraser; Emilio Cobos Álvarez. CSSOM View 模块. URL: https://drafts.csswg.org/cssom-view/
[DOM]
Anne van Kesteren. DOM 标准. 现行标准. URL: https://dom.spec.whatwg.org/
[ECMA-402]
ECMAScript 国际化 API 规范. URL: https://tc39.es/ecma402/
[ECMAScript]
ECMAScript 语言规范. URL: https://tc39.es/ecma262/multipage/
[ENCODING]
Anne van Kesteren. Encoding 标准. 现行标准. URL: https://encoding.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch 标准. 现行标准. URL: https://fetch.spec.whatwg.org/
[FS]
Austin Sullivan. File System 标准. 现行标准. URL: https://fs.spec.whatwg.org/
[FULLSCREEN]
Philip Jägenstedt. Fullscreen API 标准. 现行标准. URL: https://fullscreen.spec.whatwg.org/
[GEOLOCATION]
Marcos Caceres; Reilly Grant. Geolocation. URL: https://w3c.github.io/geolocation/
[GEOMETRY-1]
Sebastian Zartner; Yehonatan Daniv. Geometry Interfaces Module Level 1. URL: https://drafts.csswg.org/geometry/
[HR-TIME-3]
Yoav Weiss. High Resolution Time. URL: https://w3c.github.io/hr-time/
[HTML]
Anne van Kesteren; et al. HTML 标准. 现行标准. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 标准. 现行标准. URL: https://infra.spec.whatwg.org/
[MIMESNIFF]
Gordon P. Hemsley. MIME Sniffing 标准. 现行标准. URL: https://mimesniff.spec.whatwg.org/
[RESOURCE-TIMING]
Yoav Weiss; Noam Rosenthal. Resource Timing. URL: https://w3c.github.io/resource-timing/
[RFC4648]
S. Josefsson. Base16、Base32 和 Base64 数据 编码. 2006 年 10 月. 提议标准. URL: https://www.rfc-editor.org/rfc/rfc4648
[RFC5280]
D. Cooper; et al. Internet X.509 公钥 基础设施证书和证书吊销列表 (CRL) 配置文件. 2008 年 5 月. 提议标准. URL: https://www.rfc-editor.org/rfc/rfc5280
[RFC6455]
I. Fette; A. Melnikov. WebSocket 协议. 2011 年 12 月. 提议标准. URL: https://www.rfc-editor.org/rfc/rfc6455
[RFC8610]
H. Birkholz; C. Vigano; C. Bormann. Concise Data Definition Language (CDDL):用于表达 Concise Binary Object Representation (CBOR) 和 JSON 数据结构的记号约定. 2019 年 6 月. 提议标准. URL: https://www.rfc-editor.org/rfc/rfc8610
[RFC9110]
R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed.. HTTP 语义. 2022 年 6 月. Internet 标准. URL: https://httpwg.org/specs/rfc9110.html
[RFC9562]
K. Davis; B. Peabody; P. Leach. Universally Unique IDentifiers (UUIDs). 2024 年 5 月. 提议标准. URL: https://www.rfc-editor.org/rfc/rfc9562
[SCREEN-ORIENTATION]
Marcos Caceres. Screen Orientation. URL: https://w3c.github.io/screen-orientation/
[SELECTORS-4]
Elika Etemad; Tab Atkins Jr.. Selectors Level 4. URL: https://drafts.csswg.org/selectors/
[SERVICE-WORKERS]
Monica CHINTALA; Yoshisato Yanagisawa. Service Workers Nightly. URL: https://w3c.github.io/ServiceWorker/
[SVG2]
Amelia Bellamy-Royds; et al. Scalable Vector Graphics (SVG) 2. URL: https://w3c.github.io/svgwg/svg2-draft/
[UNICODE]
Unicode 标准. URL: https://www.unicode.org/versions/latest/
[URL]
Anne van Kesteren. URL 标准. 现行标准. URL: https://url.spec.whatwg.org/
[WEBAUDIO-1.0]
Paul Adenot; Hongchan Choi. Web Audio API. URL: https://webaudio.github.io/web-audio-api/
[WEBDRIVER]
Simon Stewart; David Burns. WebDriver. URL: https://w3c.github.io/webdriver/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 标准. 现行标准. URL: https://webidl.spec.whatwg.org/
[WEBSOCKETS]
Adam Rice. WebSockets 标准. 现行标准. URL: https://websockets.spec.whatwg.org/
[WEBTRANSPORT]
Nidhi Jaju; Victor Vasiliev; Jan-Ivar Bruaroey. WebTransport. URL: https://w3c.github.io/webtransport/

资料性参考文献

[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 3. URL: https://drafts.csswg.org/css-values-3/
[HTTP11]
R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed.. HTTP/1.1. 2022 年 6 月. Internet 标准. URL: https://httpwg.org/specs/rfc9112.html
[JSON-RPC]
JSON-RPC Working Group. JSON-RPC 2.0 规范. 2013 年 1 月 4 日. URL: https://www.jsonrpc.org/specification
[RFC6265BIS]
Cookies:HTTP 状态 管理机制. 编辑草案. URL: https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis
[TOUCH-EVENTS]
Doug Schepers; et al. Touch Events. URL: https://w3c.github.io/touch-events/
[URLPattern]
Ben Kelly; Jeremy Roman; 宍戸俊哉 (Shunya Shishido). URL Pattern 标准. 现行标准. URL: https://urlpattern.spec.whatwg.org/

CDDL 索引

远端定义

Command = {
  id: js-uint,
  CommandData,
  Extensible,
}

CommandData = (
  BrowserCommand //
  BrowsingContextCommand //
  EmulationCommand //
  InputCommand //
  NetworkCommand //
  ScriptCommand //
  SessionCommand //
  StorageCommand //
  WebExtensionCommand
)

EmptyParams = {
   Extensible
}

Extensible = (*text => any)

js-int = -9007199254740991..9007199254740991
js-uint = 0..9007199254740991

SessionCommand = (
  session.End //
  session.New //
  session.Status //
  session.Subscribe //
  session.Unsubscribe
)

session.CapabilitiesRequest = {
  ? alwaysMatch: session.CapabilityRequest,
  ? firstMatch: [*session.CapabilityRequest]
}

session.CapabilityRequest = {
  ? acceptInsecureCerts: bool,
  ? browserName: text,
  ? browserVersion: text,
  ? platformName: text,
  ? proxy: session.ProxyConfiguration,
  ? unhandledPromptBehavior: session.UserPromptHandler,
  Extensible
}

session.ProxyConfiguration = {
   session.AutodetectProxyConfiguration //
   session.DirectProxyConfiguration //
   session.ManualProxyConfiguration //
   session.PacProxyConfiguration //
   session.SystemProxyConfiguration
}

session.AutodetectProxyConfiguration = (
   proxyType: "autodetect",
   Extensible
)

session.DirectProxyConfiguration = (
   proxyType: "direct",
   Extensible
)

session.ManualProxyConfiguration = (
   proxyType: "manual",
   ? httpProxy: text,
   ? sslProxy: text,
   ? session.SocksProxyConfiguration,
   ? noProxy: [*text],
   Extensible
)

session.SocksProxyConfiguration = (
   socksProxy: text,
   socksVersion: 0..255,
)

session.PacProxyConfiguration = (
   proxyType: "pac",
   proxyAutoconfigUrl: text,
   Extensible
)

session.SystemProxyConfiguration = (
   proxyType: "system",
   Extensible
)


session.UserPromptHandler = {
  ? alert: session.UserPromptHandlerType,
  ? beforeUnload: session.UserPromptHandlerType,
  ? confirm: session.UserPromptHandlerType,
  ? default: session.UserPromptHandlerType,
  ? file: session.UserPromptHandlerType,
  ? prompt: session.UserPromptHandlerType,
}

session.UserPromptHandlerType = "accept" / "dismiss" / "ignore";

session.Subscription = text

session.SubscribeParameters = {
  events: [+text],
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

session.UnsubscribeByIDRequest = {
  subscriptions: [+session.Subscription],
}

session.UnsubscribeByAttributesRequest = {
  events: [+text],
}

session.Status = (
  method: "session.status",
  params: EmptyParams,
)

session.New = (
  method: "session.new",
  params: session.NewParameters
)

session.NewParameters = {
  capabilities: session.CapabilitiesRequest
}

session.End = (
  method: "session.end",
  params: EmptyParams
)


session.Subscribe = (
  method: "session.subscribe",
  params: session.SubscribeParameters
)

session.Unsubscribe = (
  method: "session.unsubscribe",
  params: session.UnsubscribeParameters,
)

session.UnsubscribeParameters = session.UnsubscribeByAttributesRequest / session.UnsubscribeByIDRequest

BrowserCommand = (
  browser.Close //
  browser.CreateUserContext //
  browser.GetClientWindows //
  browser.GetUserContexts //
  browser.RemoveUserContext //
  browser.SetClientWindowState //
  browser.SetDownloadBehavior
)

browser.ClientWindow = text;

browser.ClientWindowInfo = {
  active: bool,
  clientWindow: browser.ClientWindow,
  height: js-uint,
  state: "fullscreen" / "maximized" / "minimized" / "normal",
  width: js-uint,
  x: js-int,
  y: js-int,
}

browser.UserContext = text;

browser.UserContextInfo = {
  userContext: browser.UserContext
}

browser.Close = (
  method: "browser.close",
  params: EmptyParams,
)

browser.CreateUserContext = (
  method: "browser.createUserContext",
  params: browser.CreateUserContextParameters,
)

browser.CreateUserContextParameters = {
  ? acceptInsecureCerts: bool,
  ? proxy: session.ProxyConfiguration,
  ? unhandledPromptBehavior: session.UserPromptHandler
}

browser.GetClientWindows = (
  method: "browser.getClientWindows",
  params: EmptyParams,
)

browser.GetUserContexts = (
  method: "browser.getUserContexts",
  params: EmptyParams,
)

browser.RemoveUserContext = (
  method: "browser.removeUserContext",
  params: browser.RemoveUserContextParameters
)

browser.RemoveUserContextParameters = {
  userContext: browser.UserContext
}

browser.SetClientWindowState = (
  method: "browser.setClientWindowState",
  params: browser.SetClientWindowStateParameters
)

browser.SetClientWindowStateParameters = {
  clientWindow: browser.ClientWindow,
  (browser.ClientWindowNamedState // browser.ClientWindowRectState)
}

browser.ClientWindowNamedState = (
  state: "fullscreen" / "maximized" / "minimized"
)

browser.ClientWindowRectState = (
  state: "normal",
  ? width: js-uint,
  ? height: js-uint,
  ? x: js-int,
  ? y: js-int,
)

browser.SetDownloadBehavior = (
  method: "browser.setDownloadBehavior",
  params: browser.SetDownloadBehaviorParameters
)

browser.SetDownloadBehaviorParameters = {
  downloadBehavior: browser.DownloadBehavior / null,
  ? userContexts: [+browser.UserContext]
}

browser.DownloadBehavior = {
  (
    browser.DownloadBehaviorAllowed //
    browser.DownloadBehaviorDenied
  )
}

browser.DownloadBehaviorAllowed = (
  type: "allowed",
  destinationFolder: text
)

browser.DownloadBehaviorDenied = (
  type: "denied"
)

BrowsingContextCommand = (
  browsingContext.Activate //
  browsingContext.CaptureScreenshot //
  browsingContext.Close //
  browsingContext.Create //
  browsingContext.GetTree //
  browsingContext.HandleUserPrompt //
  browsingContext.LocateNodes //
  browsingContext.Navigate //
  browsingContext.Print //
  browsingContext.Reload //
  browsingContext.SetBypassCSP //
  browsingContext.SetViewport //
  browsingContext.TraverseHistory
)

browsingContext.BrowsingContext = text;

browsingContext.Locator = (
   browsingContext.AccessibilityLocator /
   browsingContext.CssLocator /
   browsingContext.ContextLocator /
   browsingContext.InnerTextLocator /
   browsingContext.XPathLocator
)

browsingContext.AccessibilityLocator = {
   type: "accessibility",
   value: {
    ? name: text,
    ? role: text,
   }
}

browsingContext.CssLocator = {
   type: "css",
   value: text
}

browsingContext.ContextLocator = {
  type: "context",
  value: {
    context: browsingContext.BrowsingContext,
  }
}

browsingContext.InnerTextLocator = {
   type: "innerText",
   value: text,
   ? ignoreCase: bool
   ? matchType: "full" / "partial",
   ? maxDepth: js-uint,
}

browsingContext.XPathLocator = {
   type: "xpath",
   value: text
}

browsingContext.Navigation = text;

browsingContext.ReadinessState = "none" / "interactive" / "complete"

browsingContext.UserPromptType = "alert" / "beforeunload" / "confirm" / "prompt";

browsingContext.Activate = (
  method: "browsingContext.activate",
  params: browsingContext.ActivateParameters
)

browsingContext.ActivateParameters = {
  context: browsingContext.BrowsingContext
}

browsingContext.CaptureScreenshot = (
  method: "browsingContext.captureScreenshot",
  params: browsingContext.CaptureScreenshotParameters
)

browsingContext.CaptureScreenshotParameters = {
  context: browsingContext.BrowsingContext,
  ? origin: ("viewport" / "document") .default "viewport",
  ? format: browsingContext.ImageFormat,
  ? clip: browsingContext.ClipRectangle,
}

browsingContext.ImageFormat = {
   type: text,
   ? quality: 0.0..1.0,
}

browsingContext.ClipRectangle = (
  browsingContext.BoxClipRectangle /
  browsingContext.ElementClipRectangle
)

browsingContext.ElementClipRectangle = {
  type: "element",
  element: script.SharedReference
}

browsingContext.BoxClipRectangle = {
   type: "box",
   x: float,
   y: float,
   width: float,
   height: float
}

browsingContext.Close = (
  method: "browsingContext.close",
  params: browsingContext.CloseParameters
)

browsingContext.CloseParameters = {
  context: browsingContext.BrowsingContext,
  ? promptUnload: bool .default false
}

browsingContext.Create = (
  method: "browsingContext.create",
  params: browsingContext.CreateParameters
)

browsingContext.CreateType = "tab" / "window"

browsingContext.CreateParameters = {
  type: browsingContext.CreateType,
  ? referenceContext: browsingContext.BrowsingContext,
  ? background: bool .default false,
  ? userContext: browser.UserContext
}

browsingContext.GetTree = (
  method: "browsingContext.getTree",
  params: browsingContext.GetTreeParameters
)

browsingContext.GetTreeParameters = {
  ? maxDepth: js-uint,
  ? root: browsingContext.BrowsingContext,
}

browsingContext.HandleUserPrompt = (
  method: "browsingContext.handleUserPrompt",
  params: browsingContext.HandleUserPromptParameters
)

browsingContext.HandleUserPromptParameters = {
  context: browsingContext.BrowsingContext,
  ? accept: bool,
  ? userText: text,
}

browsingContext.LocateNodes = (
  method: "browsingContext.locateNodes",
  params: browsingContext.LocateNodesParameters
)

browsingContext.LocateNodesParameters = {
   context: browsingContext.BrowsingContext,
   locator: browsingContext.Locator,
   ? maxNodeCount: (js-uint .ge 1),
   ? serializationOptions: script.SerializationOptions,
   ? startNodes: [ + script.SharedReference ]
}

browsingContext.Navigate = (
  method: "browsingContext.navigate",
  params: browsingContext.NavigateParameters
)

browsingContext.NavigateParameters = {
  context: browsingContext.BrowsingContext,
  url: text,
  ? wait: browsingContext.ReadinessState,
}

browsingContext.Print = (
  method: "browsingContext.print",
  params: browsingContext.PrintParameters
)

browsingContext.PrintParameters = {
  context: browsingContext.BrowsingContext,
  ? background: bool .default false,
  ? margin: browsingContext.PrintMarginParameters,
  ? orientation: ("portrait" / "landscape") .default "portrait",
  ? page: browsingContext.PrintPageParameters,
  ? pageRanges: [*(js-uint / text)],
  ? scale: (0.1..2.0) .default 1.0,
  ? shrinkToFit: bool .default true,
}

browsingContext.PrintMarginParameters = {
  ? bottom: (float .ge 0.0) .default 1.0,
  ? left: (float .ge 0.0) .default 1.0,
  ? right: (float .ge 0.0) .default 1.0,
  ? top: (float .ge 0.0) .default 1.0,
}

; Minimum size is 1pt x 1pt. Conversion follows from
; https://www.w3.org/TR/css3-values/#absolute-lengths
browsingContext.PrintPageParameters = {
  ? height: (float .ge 0.0352) .default 27.94,
  ? width: (float .ge 0.0352) .default 21.59,
}

browsingContext.Reload = (
  method: "browsingContext.reload",
  params: browsingContext.ReloadParameters
)

browsingContext.ReloadParameters = {
  context: browsingContext.BrowsingContext,
  ? ignoreCache: bool,
  ? wait: browsingContext.ReadinessState,
}

browsingContext.SetBypassCSP = (
  method: "browsingContext.setBypassCSP",
  params: browsingContext.SetBypassCSPParameters
)

browsingContext.SetBypassCSPParameters = {
  bypass: true / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

browsingContext.SetViewport = (
  method: "browsingContext.setViewport",
  params: browsingContext.SetViewportParameters
)

browsingContext.SetViewportParameters = {
  ? context: browsingContext.BrowsingContext,
  ? viewport: browsingContext.Viewport / null,
  ? devicePixelRatio: (float .gt 0.0) / null,
  ? userContexts: [+browser.UserContext],
}

browsingContext.Viewport = {
  width: js-uint,
  height: js-uint,
}

browsingContext.TraverseHistory = (
  method: "browsingContext.traverseHistory",
  params: browsingContext.TraverseHistoryParameters
)

browsingContext.TraverseHistoryParameters = {
  context: browsingContext.BrowsingContext,
  delta: js-int,
}

EmulationCommand = (
  emulation.SetForcedColorsModeThemeOverride //
  emulation.SetGeolocationOverride //
  emulation.SetLocaleOverride //
  emulation.SetNetworkConditions //
  emulation.SetScreenOrientationOverride //
  emulation.SetScreenSettingsOverride //
  emulation.SetScriptingEnabled //
  emulation.SetScrollbarTypeOverride //
  emulation.SetTimezoneOverride //
  emulation.SetTouchOverride //
  emulation.SetUserAgentOverride
)


emulation.SetForcedColorsModeThemeOverride = (
  method: "emulation.setForcedColorsModeThemeOverride",
  params: emulation.SetForcedColorsModeThemeOverrideParameters
)

emulation.SetForcedColorsModeThemeOverrideParameters = {
  theme: emulation.ForcedColorsModeTheme / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.ForcedColorsModeTheme = "light" / "dark"

emulation.SetGeolocationOverride = (
  method: "emulation.setGeolocationOverride",
  params: emulation.SetGeolocationOverrideParameters
)

emulation.SetGeolocationOverrideParameters = {
  (
    (coordinates: emulation.GeolocationCoordinates / null) //
    (error: emulation.GeolocationPositionError)
  ),
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.GeolocationCoordinates = {
   latitude: -90.0..90.0,
   longitude: -180.0..180.0,
   ? accuracy: (float .ge 0.0) .default 1.0,
   ? altitude: float / null .default null,
   ? altitudeAccuracy: (float .ge 0.0) / null .default null,
   ? heading: (0.0...360.0) / null .default null,
   ? speed: (float .ge 0.0) / null .default null,
}

emulation.GeolocationPositionError = {
   type: "positionUnavailable"
}

emulation.SetLocaleOverride = (
  method: "emulation.setLocaleOverride",
  params: emulation.SetLocaleOverrideParameters
)

emulation.SetLocaleOverrideParameters = {
  locale: text / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.SetNetworkConditions = (
  method: "emulation.setNetworkConditions",
  params: emulation.SetNetworkConditionsParameters
)

emulation.SetNetworkConditionsParameters = {
  networkConditions: emulation.NetworkConditions / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.NetworkConditions = emulation.NetworkConditionsOffline

emulation.NetworkConditionsOffline = {
  type: "offline"
}

emulation.SetScreenSettingsOverride = (
  method: "emulation.setScreenSettingsOverride",
  params: emulation.SetScreenSettingsOverrideParameters
)

emulation.ScreenArea = {
  width: js-uint,
  height: js-uint
}

emulation.SetScreenSettingsOverrideParameters = {
  screenArea: emulation.ScreenArea / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.SetScreenOrientationOverride = (
  method: "emulation.setScreenOrientationOverride",
  params: emulation.SetScreenOrientationOverrideParameters
)

emulation.ScreenOrientationNatural = "portrait" / "landscape"
emulation.ScreenOrientationType = "portrait-primary" / "portrait-secondary" / "landscape-primary" / "landscape-secondary"

emulation.ScreenOrientation = {
  natural: emulation.ScreenOrientationNatural,
  type: emulation.ScreenOrientationType
}

emulation.SetScreenOrientationOverrideParameters = {
  screenOrientation: emulation.ScreenOrientation / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.SetUserAgentOverride = (
  method: "emulation.setUserAgentOverride",
  params: emulation.SetUserAgentOverrideParameters
)

emulation.SetUserAgentOverrideParameters = {
  userAgent: text / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.SetScriptingEnabled = (
  method: "emulation.setScriptingEnabled",
  params: emulation.SetScriptingEnabledParameters
)

emulation.SetScriptingEnabledParameters = {
  enabled: false / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.SetScrollbarTypeOverride = (
  method: "emulation.setScrollbarTypeOverride",
  params: emulation.SetScrollbarTypeOverrideParameters
)

emulation.SetScrollbarTypeOverrideParameters = {
  scrollbarType: "classic" / "overlay" / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.SetTimezoneOverride = (
  method: "emulation.setTimezoneOverride",
  params: emulation.SetTimezoneOverrideParameters
)

emulation.SetTimezoneOverrideParameters = {
  timezone: text / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.SetTouchOverride = (
  method: "emulation.setTouchOverride",
  params: emulation.SetTouchOverrideParameters
)

emulation.SetTouchOverrideParameters = {
  maxTouchPoints: (js-uint .ge 1) / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

NetworkCommand = (
  network.AddDataCollector //
  network.AddIntercept //
  network.ContinueRequest //
  network.ContinueResponse //
  network.ContinueWithAuth //
  network.DisownData //
  network.FailRequest //
  network.GetData //
  network.ProvideResponse //
  network.RemoveDataCollector //
  network.RemoveIntercept //
  network.SetCacheBehavior //
  network.SetExtraHeaders
)


network.AuthCredentials = {
  type: "password",
  username: text,
  password: text,
}

network.BytesValue = network.StringValue / network.Base64Value;

network.StringValue = {
  type: "string",
  value: text,
}

network.Base64Value = {
  type: "base64",
  value: text,
}

network.Collector = text

network.CollectorType = "blob"

network.SameSite = "strict" / "lax" / "none" / "default"


network.Cookie = {
    name: text,
    value: network.BytesValue,
    domain: text,
    path: text,
    size: js-uint,
    httpOnly: bool,
    secure: bool,
    sameSite: network.SameSite,
    ? expiry: js-uint,
    Extensible,
}

network.CookieHeader = {
    name: text,
    value: network.BytesValue,
}

network.DataType = "request" / "response"

network.Header = {
  name: text,
  value: network.BytesValue,
}

network.Intercept = text

network.Request = text;

network.SetCookieHeader = {
    name: text,
    value: network.BytesValue,
    ? domain: text,
    ? httpOnly: bool,
    ? expiry: text,
    ? maxAge: js-int,
    ? path: text,
    ? sameSite: network.SameSite,
    ? secure: bool,
}

network.UrlPattern = (
  network.UrlPatternPattern /
  network.UrlPatternString
)

network.UrlPatternPattern = {
    type: "pattern",
    ?protocol: text,
    ?hostname: text,
    ?port: text,
    ?pathname: text,
    ?search: text,
}


network.UrlPatternString = {
    type: "string",
    pattern: text,
}


network.AddDataCollector = (
  method: "network.addDataCollector",
  params: network.AddDataCollectorParameters
)

network.AddDataCollectorParameters = {
  dataTypes: [+network.DataType],
  maxEncodedDataSize: js-uint,
  ? collectorType: network.CollectorType .default "blob",
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

network.AddIntercept = (
  method: "network.addIntercept",
  params: network.AddInterceptParameters
)

network.AddInterceptParameters = {
  phases: [+network.InterceptPhase],
  ? contexts: [+browsingContext.BrowsingContext],
  ? urlPatterns: [*network.UrlPattern],
}

network.InterceptPhase = "beforeRequestSent" / "responseStarted" /
                         "authRequired"

network.ContinueRequest = (
  method: "network.continueRequest",
  params: network.ContinueRequestParameters
)

network.ContinueRequestParameters = {
  request: network.Request,
  ?body: network.BytesValue,
  ?cookies: [*network.CookieHeader],
  ?headers: [*network.Header],
  ?method: text,
  ?url: text,
}

network.ContinueResponse = (
  method: "network.continueResponse",
  params: network.ContinueResponseParameters
)

network.ContinueResponseParameters = {
  request: network.Request,
  ?cookies: [*network.SetCookieHeader]
  ?credentials: network.AuthCredentials,
  ?headers: [*network.Header],
  ?reasonPhrase: text,
  ?statusCode: js-uint,
}

network.ContinueWithAuth = (
  method: "network.continueWithAuth",
  params: network.ContinueWithAuthParameters
)

network.ContinueWithAuthParameters = {
  request: network.Request,
  (network.ContinueWithAuthCredentials // network.ContinueWithAuthNoCredentials)
}

network.ContinueWithAuthCredentials = (
  action: "provideCredentials", 
  credentials: network.AuthCredentials
)

network.ContinueWithAuthNoCredentials = (
  action: "default" / "cancel"
)

network.DisownData = (
  method: "network.disownData",
  params: network.DisownDataParameters
)

network.DisownDataParameters = {
  dataType: network.DataType,
  collector: network.Collector,
  request: network.Request,
}

network.FailRequest = (
  method: "network.failRequest",
  params: network.FailRequestParameters
)

network.FailRequestParameters = {
  request: network.Request,
}

network.GetData = (
  method: "network.getData",
  params: network.GetDataParameters
)

network.GetDataParameters = {
  dataType: network.DataType,
  ? collector: network.Collector,
  ? disown: bool .default false,
  request: network.Request,
}

network.ProvideResponse = (
  method: "network.provideResponse",
  params: network.ProvideResponseParameters
)

network.ProvideResponseParameters = {
  request: network.Request,
  ?body: network.BytesValue,
  ?cookies: [*network.SetCookieHeader],
  ?headers: [*network.Header],
  ?reasonPhrase: text,
  ?statusCode: js-uint,
}

network.RemoveDataCollector = (
  method: "network.removeDataCollector",
  params: network.RemoveDataCollectorParameters
)

network.RemoveDataCollectorParameters = {
  collector: network.Collector
}

network.RemoveIntercept = (
  method: "network.removeIntercept",
  params: network.RemoveInterceptParameters
)

network.RemoveInterceptParameters = {
  intercept: network.Intercept
}

network.SetCacheBehavior = (
  method: "network.setCacheBehavior",
  params: network.SetCacheBehaviorParameters
)

network.SetCacheBehaviorParameters = {
  cacheBehavior: "default" / "bypass",
  ? contexts: [+browsingContext.BrowsingContext]
}

network.SetExtraHeaders = (
  method: "network.setExtraHeaders",
  params: network.SetExtraHeadersParameters
)

network.SetExtraHeadersParameters = {
  headers: [*network.Header]
  ? contexts: [+browsingContext.BrowsingContext]
  ? userContexts: [+browser.UserContext]
}

ScriptCommand = (
  script.AddPreloadScript //
  script.CallFunction //
  script.Disown //
  script.Evaluate //
  script.GetRealms //
  script.RemovePreloadScript
)

script.Channel = text;

script.ChannelValue = {
  type: "channel",
  value: script.ChannelProperties,
}

script.ChannelProperties = {
  channel: script.Channel,
  ? serializationOptions: script.SerializationOptions,
  ? ownership: script.ResultOwnership,
}

script.EvaluateResult = (
  script.EvaluateResultSuccess /
  script.EvaluateResultException
)

script.EvaluateResultSuccess = {
  type: "success",
  result: script.RemoteValue,
  realm: script.Realm
}

script.EvaluateResultException = {
  type: "exception",
  exceptionDetails: script.ExceptionDetails
  realm: script.Realm
}

script.ExceptionDetails = {
  columnNumber: js-uint,
  exception: script.RemoteValue,
  lineNumber: js-uint,
  stackTrace: script.StackTrace,
  text: text,
}

script.Handle = text;

script.InternalId = text;

script.LocalValue = (
  script.RemoteReference /
  script.PrimitiveProtocolValue /
  script.ChannelValue /
  script.ArrayLocalValue /
  { script.DateLocalValue } /
  script.MapLocalValue /
  script.ObjectLocalValue /
  { script.RegExpLocalValue } /
  script.SetLocalValue
)

script.ListLocalValue = [*script.LocalValue];

script.ArrayLocalValue = {
  type: "array",
  value: script.ListLocalValue,
}

script.DateLocalValue = (
  type: "date",
  value: text
)

script.MappingLocalValue = [*[(script.LocalValue / text), script.LocalValue]];

script.MapLocalValue = {
  type: "map",
  value: script.MappingLocalValue,
}

script.ObjectLocalValue = {
  type: "object",
  value: script.MappingLocalValue,
}

script.RegExpValue = {
  pattern: text,
  ? flags: text,
}

script.RegExpLocalValue = (
  type: "regexp",
  value: script.RegExpValue,
)

script.SetLocalValue = {
  type: "set",
  value: script.ListLocalValue,
}

script.PreloadScript = text;

script.Realm = text;

script.PrimitiveProtocolValue = (
  script.UndefinedValue /
  script.NullValue /
  script.StringValue /
  script.NumberValue /
  script.BooleanValue /
  script.BigIntValue
)

script.UndefinedValue = {
  type: "undefined",
}

script.NullValue = {
  type: "null",
}

script.StringValue = {
  type: "string",
  value: text,
}

script.SpecialNumber = "NaN" / "-0" / "Infinity" / "-Infinity";

script.NumberValue = {
  type: "number",
  value: number / script.SpecialNumber,
}

script.BooleanValue = {
  type: "boolean",
  value: bool,
}

script.BigIntValue = {
  type: "bigint",
  value: text,
}

script.RealmType = "window" / "dedicated-worker" / "shared-worker" / "service-worker" /
                   "worker" / "paint-worklet" / "audio-worklet" / "worklet"

script.RemoteReference = (
  script.SharedReference /
  script.RemoteObjectReference
)

script.SharedReference = {
   sharedId: script.SharedId

   ? handle: script.Handle,
   Extensible
}

script.RemoteObjectReference = {
   handle: script.Handle,

   ? sharedId: script.SharedId
   Extensible
}

script.RemoteValue = (
  script.PrimitiveProtocolValue /
  script.SymbolRemoteValue /
  script.ArrayRemoteValue /
  script.ObjectRemoteValue /
  script.FunctionRemoteValue /
  script.RegExpRemoteValue /
  script.DateRemoteValue /
  script.MapRemoteValue /
  script.SetRemoteValue /
  script.WeakMapRemoteValue /
  script.WeakSetRemoteValue /
  script.GeneratorRemoteValue /
  script.ErrorRemoteValue /
  script.ProxyRemoteValue /
  script.PromiseRemoteValue /
  script.TypedArrayRemoteValue /
  script.ArrayBufferRemoteValue /
  script.NodeListRemoteValue /
  script.HTMLCollectionRemoteValue /
  script.NodeRemoteValue /
  script.WindowProxyRemoteValue
)

script.ListRemoteValue = [*script.RemoteValue];

script.MappingRemoteValue = [*[(script.RemoteValue / text), script.RemoteValue]];

script.SymbolRemoteValue = {
  type: "symbol",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ArrayRemoteValue = {
  type: "array",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.ObjectRemoteValue = {
  type: "object",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.MappingRemoteValue,
}

script.FunctionRemoteValue = {
  type: "function",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.RegExpRemoteValue = {
  script.RegExpLocalValue,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.DateRemoteValue = {
  script.DateLocalValue,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.MapRemoteValue = {
  type: "map",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.MappingRemoteValue,
}

script.SetRemoteValue = {
  type: "set",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue
}

script.WeakMapRemoteValue = {
  type: "weakmap",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.WeakSetRemoteValue = {
  type: "weakset",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.GeneratorRemoteValue = {
  type: "generator",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ErrorRemoteValue = {
  type: "error",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ProxyRemoteValue = {
  type: "proxy",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.PromiseRemoteValue = {
  type: "promise",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.TypedArrayRemoteValue = {
  type: "typedarray",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ArrayBufferRemoteValue = {
  type: "arraybuffer",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.NodeListRemoteValue = {
  type: "nodelist",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.HTMLCollectionRemoteValue = {
  type: "htmlcollection",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.NodeRemoteValue = {
  type: "node",
  ? sharedId: script.SharedId,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.NodeProperties,
}

script.NodeProperties = {
  nodeType: js-uint,
  childNodeCount: js-uint,
  ? attributes: {*text => text},
  ? children: [*script.NodeRemoteValue],
  ? localName: text,
  ? mode: "open" / "closed",
  ? namespaceURI: text,
  ? nodeValue: text,
  ? shadowRoot: script.NodeRemoteValue / null,
}

script.WindowProxyRemoteValue = {
  type: "window",
  value: script.WindowProxyProperties,
  ? handle: script.Handle,
  ? internalId: script.InternalId
}

script.WindowProxyProperties = {
  context: browsingContext.BrowsingContext
}

script.ResultOwnership = "root" / "none"

script.SerializationOptions = {
  ? maxDomDepth: (js-uint / null) .default 0,
  ? maxObjectDepth: (js-uint / null) .default null,
  ? includeShadowTree: ("none" / "open" / "all") .default "none",
}

script.SharedId = text;

script.StackFrame = {
  columnNumber: js-uint,
  functionName: text,
  lineNumber: js-uint,
  url: text,
}

script.StackTrace = {
  callFrames: [*script.StackFrame],
}

script.RealmTarget = {
  realm: script.Realm
}

script.ContextTarget = {
  context: browsingContext.BrowsingContext,
  ? sandbox: text
}

script.Target = (
  script.ContextTarget /
  script.RealmTarget
)

script.AddPreloadScript = (
  method: "script.addPreloadScript",
  params: script.AddPreloadScriptParameters
)

script.AddPreloadScriptParameters = {
  functionDeclaration: text,
  ? arguments: [*script.ChannelValue],
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
  ? sandbox: text
}

script.Disown = (
  method: "script.disown",
  params: script.DisownParameters
)

script.DisownParameters = {
  handles: [*script.Handle]
  target: script.Target;
}

script.CallFunction = (
  method: "script.callFunction",
  params: script.CallFunctionParameters
)

script.CallFunctionParameters = {
  functionDeclaration: text,
  awaitPromise: bool,
  target: script.Target,
  ? arguments: [*script.LocalValue],
  ? resultOwnership: script.ResultOwnership,
  ? serializationOptions: script.SerializationOptions,
  ? this: script.LocalValue,
  ? userActivation: bool .default false,
}

script.Evaluate = (
  method: "script.evaluate",
  params: script.EvaluateParameters
)

script.EvaluateParameters = {
  expression: text,
  target: script.Target,
  awaitPromise: bool,
  ? resultOwnership: script.ResultOwnership,
  ? serializationOptions: script.SerializationOptions,
  ? userActivation: bool .default false,
}

script.GetRealms = (
  method: "script.getRealms",
  params: script.GetRealmsParameters
)

script.GetRealmsParameters = {
  ? context: browsingContext.BrowsingContext,
  ? type: script.RealmType,
}

script.RemovePreloadScript = (
  method: "script.removePreloadScript",
  params: script.RemovePreloadScriptParameters
)

script.RemovePreloadScriptParameters = {
  script: script.PreloadScript
}

StorageCommand = (
  storage.DeleteCookies //
  storage.GetCookies //
  storage.SetCookie
)

storage.PartitionKey = {
  ? userContext: text,
  ? sourceOrigin: text,
  Extensible,
}

storage.GetCookies = (
  method: "storage.getCookies",
  params: storage.GetCookiesParameters
)


storage.CookieFilter = {
  ? name: text,
  ? value: network.BytesValue,
  ? domain: text,
  ? path: text,
  ? size: js-uint,
  ? httpOnly: bool,
  ? secure: bool,
  ? sameSite: network.SameSite,
  ? expiry: js-uint,
  Extensible,
}

storage.BrowsingContextPartitionDescriptor = {
  type: "context",
  context: browsingContext.BrowsingContext
}

storage.StorageKeyPartitionDescriptor = {
  type: "storageKey",
  ? userContext: text,
  ? sourceOrigin: text,
  Extensible,
}

storage.PartitionDescriptor = (
  storage.BrowsingContextPartitionDescriptor /
  storage.StorageKeyPartitionDescriptor
)

storage.GetCookiesParameters = {
  ? filter: storage.CookieFilter,
  ? partition: storage.PartitionDescriptor,
}

storage.SetCookie = (
  method: "storage.setCookie",
  params: storage.SetCookieParameters,
)


storage.PartialCookie = {
  name: text,
  value: network.BytesValue,
  domain: text,
  ? path: text,
  ? httpOnly: bool,
  ? secure: bool,
  ? sameSite: network.SameSite,
  ? expiry: js-uint,
  Extensible,
}

storage.SetCookieParameters = {
  cookie: storage.PartialCookie,
  ? partition: storage.PartitionDescriptor,
}

storage.DeleteCookies = (
  method: "storage.deleteCookies",
  params: storage.DeleteCookiesParameters,
)

storage.DeleteCookiesParameters = {
  ? filter: storage.CookieFilter,
  ? partition: storage.PartitionDescriptor,
}

InputCommand = (
  input.PerformActions //
  input.ReleaseActions //
  input.SetFiles
)

input.ElementOrigin = {
  type: "element",
  element: script.SharedReference
}

input.PerformActions = (
  method: "input.performActions",
  params: input.PerformActionsParameters
)

input.PerformActionsParameters = {
  context: browsingContext.BrowsingContext,
  actions: [*input.SourceActions]
}

input.SourceActions = (
  input.NoneSourceActions /
  input.KeySourceActions /
  input.PointerSourceActions /
  input.WheelSourceActions
)

input.NoneSourceActions = {
  type: "none",
  id: text,
  actions: [*input.NoneSourceAction]
}

input.NoneSourceAction = input.PauseAction

input.KeySourceActions = {
  type: "key",
  id: text,
  actions: [*input.KeySourceAction]
}

input.KeySourceAction = (
  input.PauseAction /
  input.KeyDownAction /
  input.KeyUpAction
)

input.PointerSourceActions = {
  type: "pointer",
  id: text,
  ? parameters: input.PointerParameters,
  actions: [*input.PointerSourceAction]
}

input.PointerType = "mouse" / "pen" / "touch"

input.PointerParameters = {
  ? pointerType: input.PointerType .default "mouse"
}

input.PointerSourceAction = (
  input.PauseAction /
  input.PointerDownAction /
  input.PointerUpAction /
  input.PointerMoveAction
)

input.WheelSourceActions = {
  type: "wheel",
  id: text,
  actions: [*input.WheelSourceAction]
}

input.WheelSourceAction = (
  input.PauseAction /
  input.WheelScrollAction
)

input.PauseAction = {
  type: "pause",
  ? duration: js-uint
}

input.KeyDownAction = {
  type: "keyDown",
  value: text
}

input.KeyUpAction = {
  type: "keyUp",
  value: text
}

input.PointerUpAction = {
  type: "pointerUp",
  button: js-uint,
}

input.PointerDownAction = {
  type: "pointerDown",
  button: js-uint,
  input.PointerCommonProperties
}

input.PointerMoveAction = {
  type: "pointerMove",
  x: float,
  y: float,
  ? duration: js-uint,
  ? origin: input.Origin,
  input.PointerCommonProperties
}

input.WheelScrollAction = {
  type: "scroll",
  x: js-int,
  y: js-int,
  deltaX: js-int,
  deltaY: js-int,
  ? duration: js-uint,
  ? origin: input.Origin .default "viewport",
}

input.PointerCommonProperties = (
  ? width: js-uint,
  ? height: js-uint,
  ? pressure: (0.0..1.0),
  ? tangentialPressure: (-1.0..1.0),
  ? twist: (0..359),
  ; 0 .. Math.PI / 2
  ? altitudeAngle: (0.0..1.5707963267948966),
  ; 0 .. 2 * Math.PI
  ? azimuthAngle: (0.0..6.283185307179586),
)

input.Origin = "viewport" / "pointer" / input.ElementOrigin

input.ReleaseActions = (
  method: "input.releaseActions",
  params: input.ReleaseActionsParameters
)

input.ReleaseActionsParameters = {
  context: browsingContext.BrowsingContext,
}

input.SetFiles = (
  method: "input.setFiles",
  params: input.SetFilesParameters
)

input.SetFilesParameters = {
  context: browsingContext.BrowsingContext,
  element: script.SharedReference,
  files: [*text]
}

WebExtensionCommand = (
  webExtension.Install //
  webExtension.Uninstall
)

webExtension.Extension = text

webExtension.Install = (
   method: "webExtension.install",
   params: webExtension.InstallParameters
)

webExtension.InstallParameters = {
   extensionData: webExtension.ExtensionData,
}

webExtension.ExtensionData = (
   webExtension.ExtensionArchivePath /
   webExtension.ExtensionBase64Encoded /
   webExtension.ExtensionPath
)

webExtension.ExtensionPath = {
   type: "path",
   path: text,
}

webExtension.ExtensionArchivePath = {
   type: "archivePath",
   path: text,
}

webExtension.ExtensionBase64Encoded = {
   type: "base64",
   value: text,
}

webExtension.Uninstall = (
   method: "webExtension.uninstall",
   params: webExtension.UninstallParameters
)

webExtension.UninstallParameters = {
   extension: webExtension.Extension,
}

Local end definition

Message = (
  CommandResponse /
  ErrorResponse /
  Event
)

CommandResponse = {
  type: "success",
  id: js-uint,
  result: ResultData,
  Extensible
}

ErrorResponse = {
  type: "error",
  id: js-uint / null,
  error: ErrorCode,
  message: text,
  ? stacktrace: text,
  Extensible
}

ResultData = (
  BrowserResult /
  BrowsingContextResult /
  EmulationResult /
  InputResult /
  NetworkResult /
  ScriptResult /
  SessionResult /
  StorageResult /
  WebExtensionResult
)

EmptyResult = {
  Extensible
}

Event = {
  type: "event",
  EventData,
  Extensible
}

EventData = (
  BrowsingContextEvent //
  InputEvent //
  LogEvent //
  NetworkEvent //
  ScriptEvent
)

Extensible = (*text => any)

js-int = -9007199254740991..9007199254740991
js-uint = 0..9007199254740991

ErrorCode = "invalid argument" /
            "invalid selector" /
            "invalid session id" /
            "invalid web extension" /
            "move target out of bounds" /
            "no such alert" /
            "no such network collector" /
            "no such element" /
            "no such frame" /
            "no such handle" /
            "no such history entry" /
            "no such intercept" /
            "no such network data" /
            "no such node" /
            "no such request" /
            "no such script" /
            "no such storage partition" /
            "no such user context" /
            "no such web extension" /
            "session not created" /
            "unable to capture screen" /
            "unable to close browser" /
            "unable to set cookie" /
            "unable to set file input" /
            "unavailable network data" /
            "underspecified storage partition" /
            "unknown command" /
            "unknown error" /
            "unsupported operation"

SessionResult = (
  session.EndResult /
  session.NewResult /
  session.StatusResult /
  session.SubscribeResult /
  session.UnsubscribeResult
)

session.CapabilitiesRequest = {
  ? alwaysMatch: session.CapabilityRequest,
  ? firstMatch: [*session.CapabilityRequest]
}

session.CapabilityRequest = {
  ? acceptInsecureCerts: bool,
  ? browserName: text,
  ? browserVersion: text,
  ? platformName: text,
  ? proxy: session.ProxyConfiguration,
  ? unhandledPromptBehavior: session.UserPromptHandler,
  Extensible
}

session.ProxyConfiguration = {
   session.AutodetectProxyConfiguration //
   session.DirectProxyConfiguration //
   session.ManualProxyConfiguration //
   session.PacProxyConfiguration //
   session.SystemProxyConfiguration
}

session.AutodetectProxyConfiguration = (
   proxyType: "autodetect",
   Extensible
)

session.DirectProxyConfiguration = (
   proxyType: "direct",
   Extensible
)

session.ManualProxyConfiguration = (
   proxyType: "manual",
   ? httpProxy: text,
   ? sslProxy: text,
   ? session.SocksProxyConfiguration,
   ? noProxy: [*text],
   Extensible
)

session.SocksProxyConfiguration = (
   socksProxy: text,
   socksVersion: 0..255,
)

session.PacProxyConfiguration = (
   proxyType: "pac",
   proxyAutoconfigUrl: text,
   Extensible
)

session.SystemProxyConfiguration = (
   proxyType: "system",
   Extensible
)


session.UserPromptHandler = {
  ? alert: session.UserPromptHandlerType,
  ? beforeUnload: session.UserPromptHandlerType,
  ? confirm: session.UserPromptHandlerType,
  ? default: session.UserPromptHandlerType,
  ? file: session.UserPromptHandlerType,
  ? prompt: session.UserPromptHandlerType,
}

session.UserPromptHandlerType = "accept" / "dismiss" / "ignore";

session.Subscription = text

session.StatusResult = {
  ready: bool,
  message: text,
}

session.NewResult = {
  sessionId: text,
  capabilities: {
    acceptInsecureCerts: bool,
    browserName: text,
    browserVersion: text,
    platformName: text,
    setWindowRect: bool,
    userAgent: text,
    ? proxy: session.ProxyConfiguration,
    ? unhandledPromptBehavior: session.UserPromptHandler,
    ? webSocketUrl: text,
    Extensible
  }
}

session.EndResult = EmptyResult

session.SubscribeResult = {
  subscription: session.Subscription,
}

session.UnsubscribeResult = EmptyResult

BrowserResult = (
  browser.CloseResult /
  browser.CreateUserContextResult /
  browser.GetClientWindowsResult /
  browser.GetUserContextsResult /
  browser.RemoveUserContextResult /
  browser.SetClientWindowStateResult /
  browser.SetDownloadBehaviorResult
)

browser.ClientWindow = text;

browser.ClientWindowInfo = {
  active: bool,
  clientWindow: browser.ClientWindow,
  height: js-uint,
  state: "fullscreen" / "maximized" / "minimized" / "normal",
  width: js-uint,
  x: js-int,
  y: js-int,
}

browser.UserContext = text;

browser.UserContextInfo = {
  userContext: browser.UserContext
}

browser.CloseResult = EmptyResult

browser.CreateUserContextResult = browser.UserContextInfo

browser.GetClientWindowsResult = {
  clientWindows: [ * browser.ClientWindowInfo]
}

browser.GetUserContextsResult = {
  userContexts: [ + browser.UserContextInfo]
}

browser.RemoveUserContextResult = EmptyResult

browser.SetClientWindowStateResult = browser.ClientWindowInfo

browser.SetDownloadBehaviorResult = EmptyResult

BrowsingContextResult = (
  browsingContext.ActivateResult /
  browsingContext.CaptureScreenshotResult /
  browsingContext.CloseResult /
  browsingContext.CreateResult /
  browsingContext.GetTreeResult /
  browsingContext.HandleUserPromptResult /
  browsingContext.LocateNodesResult /
  browsingContext.NavigateResult /
  browsingContext.PrintResult /
  browsingContext.ReloadResult /
  browsingContext.SetBypassCSPResult /
  browsingContext.SetViewportResult /
  browsingContext.TraverseHistoryResult
)

BrowsingContextEvent = (
  browsingContext.ContextCreated //
  browsingContext.ContextDestroyed //
  browsingContext.DomContentLoaded //
  browsingContext.DownloadEnd //
  browsingContext.DownloadWillBegin //
  browsingContext.FragmentNavigated //
  browsingContext.HistoryUpdated //
  browsingContext.Load //
  browsingContext.NavigationAborted //
  browsingContext.NavigationCommitted //
  browsingContext.NavigationFailed //
  browsingContext.NavigationStarted //
  browsingContext.UserPromptClosed //
  browsingContext.UserPromptOpened
)

browsingContext.BrowsingContext = text;

browsingContext.InfoList = [*browsingContext.Info]

browsingContext.Info = {
  children: browsingContext.InfoList / null,
  clientWindow: browser.ClientWindow,
  context: browsingContext.BrowsingContext,
  originalOpener: browsingContext.BrowsingContext / null,
  url: text,
  userContext: browser.UserContext,
  ? parent: browsingContext.BrowsingContext / null,
}

browsingContext.Locator = (
   browsingContext.AccessibilityLocator /
   browsingContext.CssLocator /
   browsingContext.ContextLocator /
   browsingContext.InnerTextLocator /
   browsingContext.XPathLocator
)

browsingContext.AccessibilityLocator = {
   type: "accessibility",
   value: {
    ? name: text,
    ? role: text,
   }
}

browsingContext.CssLocator = {
   type: "css",
   value: text
}

browsingContext.ContextLocator = {
  type: "context",
  value: {
    context: browsingContext.BrowsingContext,
  }
}

browsingContext.InnerTextLocator = {
   type: "innerText",
   value: text,
   ? ignoreCase: bool
   ? matchType: "full" / "partial",
   ? maxDepth: js-uint,
}

browsingContext.XPathLocator = {
   type: "xpath",
   value: text
}

browsingContext.Navigation = text;

browsingContext.BaseNavigationInfo = (
  context: browsingContext.BrowsingContext,
  navigation: browsingContext.Navigation / null,
  timestamp: js-uint,
  url: text,
  ? userContext: browser.UserContext,
)

browsingContext.NavigationInfo = {
  browsingContext.BaseNavigationInfo
}

browsingContext.UserPromptType = "alert" / "beforeunload" / "confirm" / "prompt";

browsingContext.ActivateResult = EmptyResult

browsingContext.CaptureScreenshotResult = {
  data: text
}

browsingContext.CloseResult = EmptyResult

browsingContext.CreateResult = {
  context: browsingContext.BrowsingContext,
  ? userContext: browser.UserContext
}

browsingContext.GetTreeResult = {
  contexts: browsingContext.InfoList
}

browsingContext.HandleUserPromptResult = EmptyResult

browsingContext.LocateNodesResult = {
    nodes: [ * script.NodeRemoteValue ]
}

browsingContext.NavigateResult = {
  navigation: browsingContext.Navigation / null,
  url: text,
}

browsingContext.PrintResult = {
  data: text
}

browsingContext.ReloadResult = browsingContext.NavigateResult

browsingContext.SetBypassCSPResult = EmptyResult

browsingContext.SetViewportResult = EmptyResult

browsingContext.TraverseHistoryResult = EmptyResult

browsingContext.ContextCreated = (
 method: "browsingContext.contextCreated",
 params: browsingContext.Info
)

browsingContext.ContextDestroyed = (
 method: "browsingContext.contextDestroyed",
 params: browsingContext.Info
)

browsingContext.NavigationStarted = (
 method: "browsingContext.navigationStarted",
 params: browsingContext.NavigationInfo
)

browsingContext.FragmentNavigated = (
 method: "browsingContext.fragmentNavigated",
 params: browsingContext.NavigationInfo
)

browsingContext.HistoryUpdated = (
  method: "browsingContext.historyUpdated",
  params: browsingContext.HistoryUpdatedParameters
)

browsingContext.HistoryUpdatedParameters = {
  context: browsingContext.BrowsingContext,
  timestamp: js-uint,
  url: text,
  ? userContext: browser.UserContext
}

browsingContext.DomContentLoaded = (
 method: "browsingContext.domContentLoaded",
 params: browsingContext.NavigationInfo
)

browsingContext.Load = (
 method: "browsingContext.load",
 params: browsingContext.NavigationInfo
)

browsingContext.DownloadWillBegin = (
 method: "browsingContext.downloadWillBegin",
 params: browsingContext.DownloadWillBeginParams
)

browsingContext.DownloadWillBeginParams = {
  suggestedFilename: text,
  browsingContext.BaseNavigationInfo
}

browsingContext.DownloadEnd = (
  method: "browsingContext.downloadEnd",
  params: browsingContext.DownloadEndParams
)

browsingContext.DownloadEndParams = {
  (
    browsingContext.DownloadCanceledParams //
    browsingContext.DownloadCompleteParams
  )
}

browsingContext.DownloadCanceledParams = (
  status: "canceled",
  browsingContext.BaseNavigationInfo
)

browsingContext.DownloadCompleteParams = (
  status: "complete",
  filepath: text / null,
  browsingContext.BaseNavigationInfo
)

browsingContext.NavigationAborted = (
 method: "browsingContext.navigationAborted",
 params: browsingContext.NavigationInfo
)

browsingContext.NavigationCommitted = (
 method: "browsingContext.navigationCommitted",
 params: browsingContext.NavigationInfo
)

browsingContext.NavigationFailed = (
 method: "browsingContext.navigationFailed",
 params: browsingContext.NavigationInfo
)

browsingContext.UserPromptClosed = (
  method: "browsingContext.userPromptClosed",
  params: browsingContext.UserPromptClosedParameters
)

browsingContext.UserPromptClosedParameters = {
  context: browsingContext.BrowsingContext,
  accepted: bool,
  type: browsingContext.UserPromptType,
  ? userContext: browser.UserContext,
  ? userText: text
}

browsingContext.UserPromptOpened = (
  method: "browsingContext.userPromptOpened",
  params: browsingContext.UserPromptOpenedParameters
)

browsingContext.UserPromptOpenedParameters = {
  context: browsingContext.BrowsingContext,
  handler: session.UserPromptHandlerType,
  message: text,
  type: browsingContext.UserPromptType,
  ? userContext: browser.UserContext,
  ? defaultValue: text
}

EmulationResult = (
  emulation.SetForcedColorsModeThemeOverrideResult /
  emulation.SetGeolocationOverrideResult /
  emulation.SetLocaleOverrideResult /
  emulation.SetScreenOrientationOverrideResult /
  emulation.SetScriptingEnabledResult /
  emulation.SetScrollbarTypeOverrideResult /
  emulation.SetTimezoneOverrideResult /
  emulation.SetTouchOverrideResult /
  emulation.SetUserAgentOverrideResult
)

emulation.SetForcedColorsModeThemeOverrideResult = EmptyResult

emulation.SetGeolocationOverrideResult = EmptyResult

emulation.SetLocaleOverrideResult = EmptyResult

emulation.SetNetworkConditionsResult = EmptyResult

emulation.SetScreenSettingsOverrideResult = EmptyResult

emulation.SetScreenOrientationOverrideResult = EmptyResult

emulation.SetUserAgentOverrideResult = EmptyResult

emulation.SetScriptingEnabledResult = EmptyResult

emulation.SetScrollbarTypeOverrideResult = EmptyResult

emulation.SetTimezoneOverrideResult = EmptyResult

emulation.SetTouchOverrideResult = EmptyResult

NetworkResult = (
  network.AddDataCollectorResult /
  network.AddInterceptResult /
  network.ContinueRequestResult /
  network.ContinueResponseResult /
  network.ContinueWithAuthResult /
  network.DisownDataResult /
  network.FailRequestResult /
  network.GetDataResult /
  network.ProvideResponseResult /
  network.RemoveDataCollectorResult /
  network.RemoveInterceptResult /
  network.SetCacheBehaviorResult /
  network.SetExtraHeadersResult
)

NetworkEvent = (
    network.AuthRequired //
    network.BeforeRequestSent //
    network.FetchError //
    network.ResponseCompleted //
    network.ResponseStarted
)


network.AuthChallenge = {
  scheme: text,
  realm: text,
}

network.BaseParameters = (
    context: browsingContext.BrowsingContext / null,
    isBlocked: bool,
    navigation: browsingContext.Navigation / null,
    redirectCount: js-uint,
    request: network.RequestData,
    timestamp: js-uint,
    ? userContext: browser.UserContext / null,
    ? intercepts: [+network.Intercept]
)

network.BytesValue = network.StringValue / network.Base64Value;

network.StringValue = {
  type: "string",
  value: text,
}

network.Base64Value = {
  type: "base64",
  value: text,
}

network.Collector = text

network.CollectorType = "blob"

network.SameSite = "strict" / "lax" / "none" / "default"


network.Cookie = {
    name: text,
    value: network.BytesValue,
    domain: text,
    path: text,
    size: js-uint,
    httpOnly: bool,
    secure: bool,
    sameSite: network.SameSite,
    ? expiry: js-uint,
    Extensible,
}

network.DataType = "request" / "response"

network.FetchTimingInfo = {
    timeOrigin: float,
    requestTime: float,
    redirectStart: float,
    redirectEnd: float,
    fetchStart: float,
    dnsStart: float,
    dnsEnd: float,
    connectStart: float,
    connectEnd: float,
    tlsStart: float,

    requestStart: float,
    responseStart: float,

    responseEnd: float,
}

network.Header = {
  name: text,
  value: network.BytesValue,
}

network.Initiator = {
    ? columnNumber: js-uint,
    ? lineNumber: js-uint,
    ? request: network.Request,
    ? stackTrace: script.StackTrace,
    ? type: "parser" / "script" / "preflight" / "other"
}

network.Intercept = text

network.Request = text;

network.RequestData = {
    request: network.Request,
    url: text,
    method: text,
    headers: [*network.Header],
    cookies: [*network.Cookie],
    headersSize: js-uint,
    bodySize: js-uint / null,
    destination: text,
    initiatorType: text / null,
    timings: network.FetchTimingInfo,
}

network.ResponseContent = {
    size: js-uint
}

network.ResponseData = {
    url: text,
    protocol: text,
    status: js-uint,
    statusText: text,
    fromCache: bool,
    headers: [*network.Header],
    mimeType: text,
    bytesReceived: js-uint,
    headersSize: js-uint / null,
    bodySize: js-uint / null,
    content: network.ResponseContent,
    ?authChallenges: [*network.AuthChallenge],
}

network.AddDataCollectorResult = {
  collector: network.Collector
}

network.AddInterceptResult = {
  intercept: network.Intercept
}

network.ContinueRequestResult = EmptyResult

network.ContinueResponseResult = EmptyResult

network.ContinueWithAuthResult = EmptyResult

network.DisownDataResult = EmptyResult

network.FailRequestResult = EmptyResult

network.GetDataResult = {
  bytes: network.BytesValue,
}

network.ProvideResponseResult = EmptyResult

network.RemoveDataCollectorResult = EmptyResult

network.RemoveInterceptResult = EmptyResult

network.SetCacheBehaviorResult = EmptyResult

network.SetExtraHeadersResult = EmptyResult

network.AuthRequired = (
  method: "network.authRequired",
  params: network.AuthRequiredParameters
)

network.AuthRequiredParameters = {
  network.BaseParameters,
  response: network.ResponseData
}

network.BeforeRequestSent = (
  method: "network.beforeRequestSent",
  params: network.BeforeRequestSentParameters
 )

network.BeforeRequestSentParameters = {
  network.BaseParameters,
  ? initiator: network.Initiator,
}

network.FetchError = (
  method: "network.fetchError",
  params: network.FetchErrorParameters
 )

network.FetchErrorParameters = {
  network.BaseParameters,
  errorText: text,
}

network.ResponseCompleted = (
  method: "network.responseCompleted",
  params: network.ResponseCompletedParameters
 )

network.ResponseCompletedParameters = {
  network.BaseParameters,
  response: network.ResponseData,
}

network.ResponseStarted = (
  method: "network.responseStarted",
  params: network.ResponseStartedParameters
 )

network.ResponseStartedParameters = {
  network.BaseParameters,
  response: network.ResponseData,
}

ScriptResult = (
  script.AddPreloadScriptResult /
  script.CallFunctionResult /
  script.DisownResult /
  script.EvaluateResult /
  script.GetRealmsResult /
  script.RemovePreloadScriptResult
)

ScriptEvent = (
  script.Message //
  script.RealmCreated //
  script.RealmDestroyed
)

script.Channel = text;

script.ChannelValue = {
  type: "channel",
  value: script.ChannelProperties,
}

script.ChannelProperties = {
  channel: script.Channel,
  ? serializationOptions: script.SerializationOptions,
  ? ownership: script.ResultOwnership,
}

script.EvaluateResult = (
  script.EvaluateResultSuccess /
  script.EvaluateResultException
)

script.EvaluateResultSuccess = {
  type: "success",
  result: script.RemoteValue,
  realm: script.Realm
}

script.EvaluateResultException = {
  type: "exception",
  exceptionDetails: script.ExceptionDetails
  realm: script.Realm
}

script.ExceptionDetails = {
  columnNumber: js-uint,
  exception: script.RemoteValue,
  lineNumber: js-uint,
  stackTrace: script.StackTrace,
  text: text,
}

script.Handle = text;

script.InternalId = text;

script.LocalValue = (
  script.RemoteReference /
  script.PrimitiveProtocolValue /
  script.ChannelValue /
  script.ArrayLocalValue /
  { script.DateLocalValue } /
  script.MapLocalValue /
  script.ObjectLocalValue /
  { script.RegExpLocalValue } /
  script.SetLocalValue
)

script.ListLocalValue = [*script.LocalValue];

script.ArrayLocalValue = {
  type: "array",
  value: script.ListLocalValue,
}

script.DateLocalValue = (
  type: "date",
  value: text
)

script.MappingLocalValue = [*[(script.LocalValue / text), script.LocalValue]];

script.MapLocalValue = {
  type: "map",
  value: script.MappingLocalValue,
}

script.ObjectLocalValue = {
  type: "object",
  value: script.MappingLocalValue,
}

script.RegExpValue = {
  pattern: text,
  ? flags: text,
}

script.RegExpLocalValue = (
  type: "regexp",
  value: script.RegExpValue,
)

script.SetLocalValue = {
  type: "set",
  value: script.ListLocalValue,
}

script.PreloadScript = text;

script.Realm = text;

script.PrimitiveProtocolValue = (
  script.UndefinedValue /
  script.NullValue /
  script.StringValue /
  script.NumberValue /
  script.BooleanValue /
  script.BigIntValue
)

script.UndefinedValue = {
  type: "undefined",
}

script.NullValue = {
  type: "null",
}

script.StringValue = {
  type: "string",
  value: text,
}

script.SpecialNumber = "NaN" / "-0" / "Infinity" / "-Infinity";

script.NumberValue = {
  type: "number",
  value: number / script.SpecialNumber,
}

script.BooleanValue = {
  type: "boolean",
  value: bool,
}

script.BigIntValue = {
  type: "bigint",
  value: text,
}

script.RealmInfo = (
  script.WindowRealmInfo /
  script.DedicatedWorkerRealmInfo /
  script.SharedWorkerRealmInfo /
  script.ServiceWorkerRealmInfo /
  script.WorkerRealmInfo /
  script.PaintWorkletRealmInfo /
  script.AudioWorkletRealmInfo /
  script.WorkletRealmInfo
)

script.BaseRealmInfo = (
  realm: script.Realm,
  origin: text
)

script.WindowRealmInfo = {
  script.BaseRealmInfo,
  type: "window",
  context: browsingContext.BrowsingContext,
  ? userContext: browser.UserContext,
  ? sandbox: text
}

script.DedicatedWorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "dedicated-worker",
  owners: [script.Realm]
}

script.SharedWorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "shared-worker"
}

script.ServiceWorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "service-worker"
}

script.WorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "worker"
}

script.PaintWorkletRealmInfo = {
  script.BaseRealmInfo,
  type: "paint-worklet"
}

script.AudioWorkletRealmInfo = {
  script.BaseRealmInfo,
  type: "audio-worklet"
}

script.WorkletRealmInfo = {
  script.BaseRealmInfo,
  type: "worklet"
}

script.RealmType = "window" / "dedicated-worker" / "shared-worker" / "service-worker" /
                   "worker" / "paint-worklet" / "audio-worklet" / "worklet"

script.RemoteReference = (
  script.SharedReference /
  script.RemoteObjectReference
)

script.SharedReference = {
   sharedId: script.SharedId

   ? handle: script.Handle,
   Extensible
}

script.RemoteObjectReference = {
   handle: script.Handle,

   ? sharedId: script.SharedId
   Extensible
}

script.RemoteValue = (
  script.PrimitiveProtocolValue /
  script.SymbolRemoteValue /
  script.ArrayRemoteValue /
  script.ObjectRemoteValue /
  script.FunctionRemoteValue /
  script.RegExpRemoteValue /
  script.DateRemoteValue /
  script.MapRemoteValue /
  script.SetRemoteValue /
  script.WeakMapRemoteValue /
  script.WeakSetRemoteValue /
  script.GeneratorRemoteValue /
  script.ErrorRemoteValue /
  script.ProxyRemoteValue /
  script.PromiseRemoteValue /
  script.TypedArrayRemoteValue /
  script.ArrayBufferRemoteValue /
  script.NodeListRemoteValue /
  script.HTMLCollectionRemoteValue /
  script.NodeRemoteValue /
  script.WindowProxyRemoteValue
)

script.ListRemoteValue = [*script.RemoteValue];

script.MappingRemoteValue = [*[(script.RemoteValue / text), script.RemoteValue]];

script.SymbolRemoteValue = {
  type: "symbol",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ArrayRemoteValue = {
  type: "array",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.ObjectRemoteValue = {
  type: "object",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.MappingRemoteValue,
}

script.FunctionRemoteValue = {
  type: "function",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.RegExpRemoteValue = {
  script.RegExpLocalValue,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.DateRemoteValue = {
  script.DateLocalValue,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.MapRemoteValue = {
  type: "map",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.MappingRemoteValue,
}

script.SetRemoteValue = {
  type: "set",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue
}

script.WeakMapRemoteValue = {
  type: "weakmap",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.WeakSetRemoteValue = {
  type: "weakset",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.GeneratorRemoteValue = {
  type: "generator",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ErrorRemoteValue = {
  type: "error",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ProxyRemoteValue = {
  type: "proxy",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.PromiseRemoteValue = {
  type: "promise",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.TypedArrayRemoteValue = {
  type: "typedarray",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ArrayBufferRemoteValue = {
  type: "arraybuffer",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.NodeListRemoteValue = {
  type: "nodelist",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.HTMLCollectionRemoteValue = {
  type: "htmlcollection",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.NodeRemoteValue = {
  type: "node",
  ? sharedId: script.SharedId,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.NodeProperties,
}

script.NodeProperties = {
  nodeType: js-uint,
  childNodeCount: js-uint,
  ? attributes: {*text => text},
  ? children: [*script.NodeRemoteValue],
  ? localName: text,
  ? mode: "open" / "closed",
  ? namespaceURI: text,
  ? nodeValue: text,
  ? shadowRoot: script.NodeRemoteValue / null,
}

script.WindowProxyRemoteValue = {
  type: "window",
  value: script.WindowProxyProperties,
  ? handle: script.Handle,
  ? internalId: script.InternalId
}

script.WindowProxyProperties = {
  context: browsingContext.BrowsingContext
}

script.ResultOwnership = "root" / "none"

script.SerializationOptions = {
  ? maxDomDepth: (js-uint / null) .default 0,
  ? maxObjectDepth: (js-uint / null) .default null,
  ? includeShadowTree: ("none" / "open" / "all") .default "none",
}

script.SharedId = text;

script.StackFrame = {
  columnNumber: js-uint,
  functionName: text,
  lineNumber: js-uint,
  url: text,
}

script.StackTrace = {
  callFrames: [*script.StackFrame],
}

script.Source = {
  realm: script.Realm,
  ? context: browsingContext.BrowsingContext,
  ? userContext: browser.UserContext
}

script.AddPreloadScriptResult = {
  script: script.PreloadScript
}

script.DisownResult = EmptyResult

script.CallFunctionResult = script.EvaluateResult

script.GetRealmsResult = {
  realms: [*script.RealmInfo]
}

script.RemovePreloadScriptResult = EmptyResult

script.Message = (
  method: "script.message",
  params: script.MessageParameters
 )

script.MessageParameters = {
  channel: script.Channel,
  data: script.RemoteValue,
  source: script.Source,
}

script.RealmCreated = (
 method: "script.realmCreated",
 params: script.RealmInfo
)

script.RealmDestroyed = (
  method: "script.realmDestroyed",
  params: script.RealmDestroyedParameters
)

script.RealmDestroyedParameters = {
  realm: script.Realm
}


StorageResult = (
  storage.DeleteCookiesResult /
  storage.GetCookiesResult /
  storage.SetCookieResult
)

storage.PartitionKey = {
  ? userContext: text,
  ? sourceOrigin: text,
  Extensible,
}

storage.GetCookiesResult = {
  cookies: [*network.Cookie],
  partitionKey: storage.PartitionKey,
}

storage.SetCookieResult = {
  partitionKey: storage.PartitionKey
}

storage.DeleteCookiesResult = {
  partitionKey: storage.PartitionKey
}

LogEvent = (
  log.EntryAdded
)

log.Level = "debug" / "info" / "warn" / "error"

log.Entry = (
  log.GenericLogEntry /
  log.ConsoleLogEntry /
  log.JavascriptLogEntry
)

log.BaseLogEntry = (
  level: log.Level,
  source: script.Source,
  text: text / null,
  timestamp: js-uint,
  ? stackTrace: script.StackTrace,
)

log.GenericLogEntry = {
  log.BaseLogEntry,
  type: text,
}

log.ConsoleLogEntry = {
  log.BaseLogEntry,
  type: "console",
  method: text,
  args: [*script.RemoteValue],
}

log.JavascriptLogEntry = {
  log.BaseLogEntry,
  type: "javascript",
}

log.EntryAdded = (
 method: "log.entryAdded",
 params: log.Entry,
)

InputResult = (
  input.PerformActionsResult /
  input.ReleaseActionsResult /
  input.SetFilesResult
)

InputEvent = (
  input.FileDialogOpened
)

input.PerformActionsResult = EmptyResult

input.ReleaseActionsResult = EmptyResult

input.SetFilesResult = EmptyResult

input.FileDialogOpened = (
   method: "input.fileDialogOpened",
   params: input.FileDialogInfo
)

input.FileDialogInfo = {
   context: browsingContext.BrowsingContext,
   ? userContext: browser.UserContext,
   ? element: script.SharedReference,
   multiple: bool,
}

WebExtensionResult = (
  webExtension.InstallResult /
  webExtension.UninstallResult
)

webExtension.Extension = text

webExtension.InstallResult = {
  extension: webExtension.Extension
}

webExtension.UninstallResult = EmptyResult

议题索引

肯定有更好的机制来做这种“等待事件”的事情。
我们是否应该有类似 microtasks 的东西,以确保它在事件循环上的任何其他任务之前运行?
这应该作为附录吗?
我们是否支持单个 session 有 > 1 个连接?
似乎没有任何东西定义 UTF-8 错误使用什么状态码
需要挂接到 session 结束,以允许 UA 在想要时关闭 listener。
定义 sandbox realm 的创建。这将返回一个包装 windowSandboxWindowProxy
详细定义 SandboxProxy 如何工作
定义其工作方式。
尚不清楚这是否是正式定义 user context 概念或其与 storage 交互的最佳方式。
我们是否应该规定具有非 null opener 的顶级 traversables 与其 opener 具有相同的关联用户上下文? 需要检查这是否是现有实现所强制执行的内容。
这是一种相当不精确的表述,但希望它清楚表达了这样的意图: 我们会在开始关闭连接之前把命令响应发送出去。
这也需要泛化为适用于 realms。
这也需要泛化为适用于 realms。
property 规定 ignore cache 标志如何工作。这需要 考虑是否只有资源的首次加载会绕过缓存 (即这是否类似于最初清空缓存然后照常继续),或者不是由 HTML parser 直接加载的资源(例如由脚本或样式表发起的加载)是否也绕过缓存。
我们在这里通过错误暴露了足够多关于失败内容和原因的信息吗? 我们想要什么错误代码?是否会出现这样的问题:local ends 解析 implementation-defined 字符串来弄清实际出了什么问题?
这应当以更明确的方式集成到 update rendering 算法中。
关于关闭最后一个顶级 traversable 时的行为,存在一个开放讨论。我们可以预期关闭 浏览器、关闭 session,或将其留给实现决定。 [w3c/webdriver-bidi 议题 #170]
这应当以更明确的方式集成到 update rendering 算法中。
按当前写法,该算法存在竞争条件,因为当我们尝试导航时, 目标 session history entry 可能已经不存在。一旦我们支持等待历史记录进行导航, 就可以更稳健地处理这一点。
我们是否想暴露 `browsingContext.pageShow 事件?那样的话, 不仅是在 bfcache restore 时,而是每当 `pageshow` 将要被发出时都需要调用它, 并且还要把 persisted 状态添加到数据中。
尚不清楚我们是否应只对具有 active documents 的 browsing contexts 触发此事件;navigation 也可能导致 contexts 变得不可访问, 但由于 bfcache 尚未被丢弃。
将此算法移动到 screen orientation 规范。
这会防止收集与 navigable 无关的数据。 我们仍然需要检索 navigable 来检查 collector 配置, 但这里仍可以接受 null。
这没有取消 auth 的方式。
我们是否应包含 realm 以外的参数?
和 Fetch 中一样,尚不清楚这是否是处理多个 headers、解析问题等的正确方式。
考虑除了 context 之外,还包括发起请求的 document node 的 `sharedId`。
考虑一个“request already sent”错误。
允许设置精确的错误种类 [议题 #508]
遵循 Fetch 的 “HTTP-network-or-cache fetch” 算法中的返回值。
这里的错误代码不对
这未处理孤立代理项
处理 “stale object reference” 情况。
添加 WASM 类型?
WindowProxy 是否应以类似 Node 的风格获得 attributes?
特殊处理 String / Number / 等包装对象?
重新考虑 mirror objects 的生命周期。
children 和 child nodes 是不同的东西。childNodeCount 要么应 引用 childNodes,要么应重命名为 childrenCount
这里的错误代码不对
这里的错误代码不对
TODO:添加 script.evaluate 中描述的 timeout 参数。
扩展此项以同样允许 realm parents,例如用于嵌套 workers?或者获取所有祖先 workers。
我们可能想要比只是 literal match 更复杂的过滤系统。
这里的顺序是否应该定义得更好?
我们想按 browsing context 还是 top-level traversable 来作为键? 差异在于:如果某个事件发生在 frame 中,而该 frame 在 local end 订阅顶级 navigable 的 log events 之前发生了导航,会发生什么。
很多其他东西也需要 logging。CDP 有 LogEntryAdded 类型:xml、 javascript、network、storage、appcache、rendering、security、deprecation、 worker、violation、intervention、recommendation、other。除了由不同方法表示的 js exception 和 console API 类型之外,还有这些类型。
允许 implementation-defined log 类型