编码

现行标准 — 最后更新

参与:
GitHub whatwg/encoding (新问题, 开放问题)
在 Matrix 上聊天
提交:
GitHub whatwg/encoding/commits
此提交的快照
@encodings
测试:
web-platform-tests encoding/ (正在进行的工作)
翻译 (非规范性)
日本語
简体中文

摘要

编码标准定义了编码及其 JavaScript API。

1. 前言

UTF-8 编码是交换 Unicode(通用编码字符集)最合适的编码。因此,对于新协议和格式,以及在新环境中部署的现有格式,本规范要求(并定义)使用 UTF-8 编码。

其他(旧)编码在过去某种程度上已经被定义。然而,用户代理并未始终以相同的方式实现它们,也未始终使用相同的标签,并且在处理编码的未定义和以前的专有区域时经常有所不同。本规范解决了这些差距,使得新的用户代理无需逆向工程编码实现,而现有的用户代理可以趋于一致。

特别是,本规范定义了所有这些编码、从字节到标量值及其返回的算法、它们的规范名称和识别标签。本规范还定义了一个 API,用于向 JavaScript 暴露部分编码算法。

用户代理在标签方面也显著偏离了 IANA 字符集注册表中列出的内容。为了阻止进一步传播旧编码,本规范对上述细节进行了详尽的定义,因此不需要注册表。特别是,本规范不提供扩展编码任何方面的机制。

2. 安全背景

当生产者和消费者对使用的编码或对给定编码的实现方式未达成一致时,会出现一系列编码安全问题。例如,2011 年报告了一次攻击,其中 Shift_JIS 的前导字节 0x82 被用来“掩盖” JSON 资源中某字段的尾随字节 0x22,该字段由攻击者控制。生产者未发现问题,尽管这是一个非法字节组合。消费者将其解码为单个 U+FFFD(�),因此改变了整体解释,因为 U+0022(")是一个重要的分隔符。现在,使用多个字节表示标量值的编码的解码器要求,在非法字节组合的情况下,范围 U+0000 到 U+007F(含)的标量值不能被“掩盖”。对于上述序列,输出将是 U+FFFD U+0022。(作为一个不幸的例外,gb18030 解码器将在 队列末尾最多“掩盖”一个这样的字节。)

对于将任何 ASCII 字节映射到非 ASCII 代码点的编码(当没有前导字节存在时),这是一个更大的问题。这些是“ASCII 不兼容”编码,除了由于已部署内容而必须支持的 ISO-2022-JPUTF-16BE/LE,它们不被支持。(正在 调查是否可以将更多此类编码的标签映射到 替代编码,而不是未知编码回退。)一个示例攻击是向资源注入精心设计的内容,然后鼓励用户覆盖编码,从而导致例如脚本执行。

HTML 和 HTML 表单功能中使用的 URL 编码器在使用无法表示所有标量值的编码时也可能导致轻微的信息丢失。例如,当资源使用 windows-1252 编码时,服务器将无法区分最终用户在表单中输入“💩”和“💩”。

当仅使用 UTF-8 时,这里概述的问题将消失,这也是现在所有事物必须使用 UTF-8 编码的众多原因之一。

另请参阅 浏览器 UI章节。

3. 术语

本规范依赖于 Infra 标准。[INFRA]

十六进制数字以 "0x" 为前缀。

在公式中,所有数字均为整数,加法用 "+" 表示,减法用 "−" 表示,乘法用 "×" 表示,整数除法用 "/" 表示(返回商),取模用 "%" 表示(返回整数除法的余数),逻辑左移用 "<<" 表示,逻辑右移用 ">>" 表示,按位与用 "&" 表示,按位或用 "|" 表示。

对于逻辑右移,操作数必须至少具有 21 位精度。


I/O 队列 是一种 列表,其 具有特定类型(例如 字节标量值)。队列末尾 是一种特殊的 ,可以存在于任何类型的 I/O 队列中,表示队列中没有更多的

使用 I/O 队列有两种方式:即时模式,用于表示存储在内存中的 I/O 数据;流模式,用于表示来自网络的数据。即时队列的最后一项是 队列末尾,而流队列不需要有它,因此它们的 读取操作可能会阻塞。

预计流式 I/O 队列将被创建为空,并且随着数据从网络进入,会将新的 推入队列。当底层网络流关闭时,应将一个 队列末尾推入队列。

由于从流式 I/O 队列读取可能会阻塞,因此流式 I/O 队列不应从 事件循环中使用,而应在 并行中使用。

要从 I/O 队列 ioQueue 读取一个 ,按以下步骤执行:

  1. 如果 ioQueue 为空,则等待直到其 长度 至少为 1。

  2. 如果 ioQueue[0] 是 队列结尾(end-of-queue),则返回 队列结尾

  3. 移除 ioQueue[0] 并返回它。

要从 ioQueue 中读取 number,请执行以下步骤:

  1. readItems 为 « »。

  2. 执行以下步骤 number 次:

    1. 追加readItems,结果为从 ioQueue 读取的一个项。

  3. 移除 队列末尾readItems

  4. 返回 readItems

要从 I/O 队列 ioQueue 窥视(peek) number,按以下步骤执行:

  1. 等待,直到 ioQueue长度等于或大于 number,或 ioQueue包含 队列结尾(end-of-queue),以先发生者为准。

  2. prefix 为 « »。

  3. 对于 区间 1 到 number(含),中的每个 n

    1. 如果 ioQueue[n] 是 队列结尾,则 跳出循环。

    2. 否则, ioQueue[n] 追加到 prefix

  4. 返回 prefix

要向 I/O 队列 ioQueue 推送一个 item,按以下步骤执行:

  1. 如果 ioQueue 的最后一个 队列结尾(end-of-queue)

    1. 如果 item 也是 队列结尾,则不做任何操作。

    2. 否则, ioQueue 的最后一个 之前插入 item

  2. 否则, item 追加到 ioQueue

I/O 队列 ioQueue 推送一系列项,是指按照给定顺序,将序列中的每一项依次推送到 ioQueue 中。

将一个 (非 队列结尾(end-of-queue)恢复I/O 队列中,即执行 列表前插(prepend)操作。将一个不含 队列结尾项列表恢复到 I/O 队列中,则按给定顺序将这些项插入到队列的第一个项之前。

如果向 I/O 队列 « 0x92 0xA9, 队列结尾 » 插入字节 « 0xF0, 0x9F », 则结果为 I/O 队列 « 0xF0, 0x9F, 0x92 0xA9, 队列结尾 »。下一个要读取的项是 0xF0。

转换一个 I/O 队列 ioQueue列表字符串字节序列,返回从 ioQueue 读取无限数量的结果。

转换一个列表字符串字节序列 inputI/O 队列,按照以下步骤操作:

  1. 断言input 不是 列表,或者其中不包含 队列结尾

  2. 返回一个 I/O 队列,其内容为 input 中的(按顺序),并在末尾加上 队列结尾

Infra 标准预计将定义一些关于类型转换的基础设施。详见 whatwg/infra issue #319[INFRA]

I/O 队列被定义为列表,而非队列,因为它们包含 恢复操作。然而,这一恢复操作仅是本规范算法的内部细节,不应被其他标准使用。实现可以采用其他方式来实现此类算法,细节见实现注意事项


要从代理对中获取一个 标量值,给定一个 前导代理 leading 和一个 尾随代理 trailing,返回 0x10000 + ((leading − 0xD800) << 10) + (trailing − 0xDC00)。


创建一个 Uint8Array 对象,给定一个 I/O 队列 ioQueuerealm realm

  1. bytes 为将 ioQueue 转换为字节序列的结果。

  2. 返回在 realm 中用 bytes 创建 Uint8Array 对象的结果。

4. 编码

编码定义了从标量值序列到字节序列(及其反向)的映射。每个编码都有一个名称,以及一个或多个标签

本规范定义了三个与 Unicode 标准中定义的编码方案同名的编码UTF-8UTF-16LEUTF-16BE。这些编码编码方案的不同之处在于字节顺序标记(也称为 BOM)的处理不是编码本身的一部分,而是本规范中包装算法的一部分,而字节顺序标记处理是 Unicode 标准中编码方案定义的一部分。UTF-8UTF-8 解码算法一起使用时,与同名的编码方案匹配。本规范不提供与UTF-16LEUTF-16BE结合以匹配类似名称的编码方案的包装算法。[UNICODE]

4.1. 编码器和解码器

每个编码都有一个关联的解码器,并且大多数都有一个关联的编码器解码器编码器的实例具有一个处理器算法,并可能具有状态。处理器算法接受一个输入I/O 队列和一个,并返回完成、一个或多个错误(可选地带有一个代码点),或继续

替代UTF-16BE/LE编码没有编码器

错误模式在以下使用中,对于解码器是"replacement"或"fatal",对于编码器是"fatal"或"html"。

XML 处理器会将错误模式设置为"fatal"。[XML]

由于 HTML 表单需要一个非终止的旧编码器,"html"作为错误模式存在。"html"错误模式会导致发出一个无法与合法输入区分的序列,因此可能导致静默的数据丢失。强烈建议开发人员使用UTF-8编码以防止这种情况发生。[HTML]


处理队列,给定一个编码解码器编码器实例encoderDecoderI/O 队列inputI/O 队列output错误模式mode

  1. 当条件为真时:

    1. result为通过以下步骤处理一个项的结果:从input读取encoderDecoderinputoutputmode

    2. 如果result不是继续,则返回result

处理一个项,给定一个item、一个编码编码器解码器实例encoderDecoderI/O 队列inputI/O 队列output错误模式mode

  1. 断言encoderDecoder不是一个编码器实例或mode不是"replacement"。

  2. 断言encoderDecoder不是一个解码器实例或mode不是"html"。

  3. 断言encoderDecoder不是一个编码器实例或item不是一个代理

  4. result为运行encoderDecoder处理器算法,输入为inputitem的结果。

  5. 如果result完成

    1. 推入队列末尾output

    2. 返回result

  6. 否则,如果result是一个或多个

    1. 断言encoderDecoder不是一个解码器实例或result不包含任何代理

    2. 推入resultoutput

  7. 否则,如果result是一个错误,根据mode运行相关步骤:

    "replacement"
    推入U+FFFD (�)到output
    "html"
    推入0x26 (&), 0x23 (#),后跟表示result代码点的最短十进制序列(范围为0x30 (0)到0x39 (9),含),最后是0x3B (;)到output
    "fatal"
    返回result
  8. 返回继续

4.2. 名称和标签

下表列出了所有编码及其标签,用户代理必须支持这些编码和标签。用户代理不得支持任何其他编码标签

对于每个编码,对其ASCII 小写化名称会生成其一个标签

作者必须使用UTF-8编码,并且必须使用其(ASCII 大小写不敏感)"utf-8"标签来标识它。

新协议和格式,以及在新环境中部署的现有格式,必须仅使用UTF-8编码。如果这些协议和格式需要公开编码名称标签,它们必须将其公开为"utf-8"。

要从字符串label获取编码,请执行以下步骤:

  1. 移除label中的任何前导和尾随ASCII 空白

  2. 如果label与下表中列出的任何标签ASCII 大小写不敏感匹配,则返回对应的编码;否则返回失败。

这是一个比Unicode 技术标准第 22 号第 1.4 节规定的更基本和更严格的将标签映射到编码的算法,因为这是与已部署内容兼容所必需的。

名称 标签
编码
UTF-8 "unicode-1-1-utf-8"
"unicode11utf8"
"unicode20utf8"
"utf-8"
"utf8"
"x-unicode20utf8"
旧单字节编码
IBM866 "866"
"cp866"
"csibm866"
"ibm866"
ISO-8859-2 "csisolatin2"
"iso-8859-2"
"iso-ir-101"
"iso8859-2"
"iso88592"
"iso_8859-2"
"iso_8859-2:1987"
"l2"
"latin2"
ISO-8859-3 "csisolatin3"
"iso-8859-3"
"iso-ir-109"
"iso8859-3"
"iso88593"
"iso_8859-3"
"iso_8859-3:1988"
"l3"
"latin3"
ISO-8859-4 "csisolatin4"
"iso-8859-4"
"iso-ir-110"
"iso8859-4"
"iso88594"
"iso_8859-4"
"iso_8859-4:1988"
"l4"
"latin4"
ISO-8859-5 "csisolatincyrillic"
"cyrillic"
"iso-8859-5"
"iso-ir-144"
"iso8859-5"
"iso88595"
"iso_8859-5"
"iso_8859-5:1988"
ISO-8859-6 "arabic"
"asmo-708"
"csiso88596e"
"csiso88596i"
"csisolatinarabic"
"ecma-114"
"iso-8859-6"
"iso-8859-6-e"
"iso-8859-6-i"
"iso-ir-127"
"iso8859-6"
"iso88596"
"iso_8859-6"
"iso_8859-6:1987"
ISO-8859-7 "csisolatingreek"
"ecma-118"
"elot_928"
"greek"
"greek8"
"iso-8859-7"
"iso-ir-126"
"iso8859-7"
"iso88597"
"iso_8859-7"
"iso_8859-7:1987"
"sun_eu_greek"
ISO-8859-8 "csiso88598e"
"csisolatinhebrew"
"hebrew"
"iso-8859-8"
"iso-8859-8-e"
"iso-ir-138"
"iso8859-8"
"iso88598"
"iso_8859-8"
"iso_8859-8:1988"
"visual"
ISO-8859-8-I "csiso88598i"
"iso-8859-8-i"
"logical"
ISO-8859-10 "csisolatin6"
"iso-8859-10"
"iso-ir-157"
"iso8859-10"
"iso885910"
"l6"
"latin6"
ISO-8859-13 "iso-8859-13"
"iso8859-13"
"iso885913"
ISO-8859-14 "iso-8859-14"
"iso8859-14"
"iso885914"
ISO-8859-15 "csisolatin9"
"iso-8859-15"
"iso8859-15"
"iso885915"
"iso_8859-15"
"l9"
ISO-8859-16 "iso-8859-16"
KOI8-R "cskoi8r"
"koi"
"koi8"
"koi8-r"
"koi8_r"
KOI8-U "koi8-ru"
"koi8-u"
macintosh "csmacintosh"
"mac"
"macintosh"
"x-mac-roman"
windows-874 "dos-874"
"iso-8859-11"
"iso8859-11"
"iso885911"
"tis-620"
"windows-874"
windows-1250 "cp1250"
"windows-1250"
"x-cp1250"
windows-1251 "cp1251"
"windows-1251"
"x-cp1251"
windows-1252

参见下文了解与历史上的“Latin1”和“ASCII”概念的关系。

"ansi_x3.4-1968"
"ascii"
"cp1252"
"cp819"
"csisolatin1"
"ibm819"
"iso-8859-1"
"iso-ir-100"
"iso8859-1"
"iso88591"
"iso_8859-1"
"iso_8859-1:1987"
"l1"
"latin1"
"us-ascii"
"windows-1252"
"x-cp1252"
windows-1253 "cp1253"
"windows-1253"
"x-cp1253"
windows-1254 "cp1254"
"csisolatin5"
"iso-8859-9"
"iso-ir-148"
"iso8859-9"
"iso88599"
"iso_8859-9"
"iso_8859-9:1989"
"l5"
"latin5"
"windows-1254"
"x-cp1254"
windows-1255 "cp1255"
"windows-1255"
"x-cp1255"
windows-1256 "cp1256"
"windows-1256"
"x-cp1256"
windows-1257 "cp1257"
"windows-1257"
"x-cp1257"
windows-1258 "cp1258"
"windows-1258"
"x-cp1258"
x-mac-cyrillic "x-mac-cyrillic"
"x-mac-ukrainian"
旧多字节中文(简体)编码
GBK "chinese"
"csgb2312"
"csiso58gb231280"
"gb2312"
"gb_2312"
"gb_2312-80"
"gbk"
"iso-ir-58"
"x-gbk"
gb18030 "gb18030"
旧多字节中文(繁体)编码
Big5 "big5"
"big5-hkscs"
"cn-big5"
"csbig5"
"x-x-big5"
旧多字节日语编码
EUC-JP "cseucpkdfmtjapanese"
"euc-jp"
"x-euc-jp"
ISO-2022-JP "csiso2022jp"
"iso-2022-jp"
Shift_JIS "csshiftjis"
"ms932"
"ms_kanji"
"shift-jis"
"shift_jis"
"sjis"
"windows-31j"
"x-sjis"
旧多字节韩语编码
EUC-KR "cseuckr"
"csksc56011987"
"euc-kr"
"iso-ir-149"
"korean"
"ks_c_5601-1987"
"ks_c_5601-1989"
"ksc5601"
"ksc_5601"
"windows-949"
旧杂项编码
replacement "csiso2022kr"
"hz-gb-2312"
"iso-2022-cn"
"iso-2022-cn-ext"
"iso-2022-kr"
"replacement"
UTF-16BE "unicodefffe"
"utf-16be"
UTF-16LE "csunicode"
"iso-10646-ucs-2"
"ucs-2"
"unicode"
"unicodefeff"
"utf-16"
"utf-16le"
x-user-defined "x-user-defined"

所有编码及其标签也可以作为非规范性的encodings.json资源获取。

支持的编码集主要基于本标准开发开始时主要浏览器引擎支持的编码集的交集,同时移除了那些很少被合法使用但可能被用于攻击的编码。从现有 Web 内容的使用水平的零散证据来看,某些编码的包含是值得怀疑的。也就是说,虽然这些编码被浏览器广泛支持,但尚不清楚它们是否被 Web 内容广泛使用。然而,并未积极移除那些被浏览器广泛支持或属于 ISO 8859 系列的单字节编码。特别是,IBM866macintoshx-mac-cyrillicISO-8859-3ISO-8859-10ISO-8859-14ISO-8859-16的必要性对于支持现有内容来说是值得怀疑的,但目前没有移除这些编码的计划。

windows-1252编码有多个标签,例如"latin1"、"iso-8859-1"和"ascii",这些标签在历史上对开发人员来说一直很困惑。在 Web 上以及任何希望通过实现本标准与 Web 兼容的软件中,这些标签是同义词:"latin1"和"ascii"只是windows-1252的标签,任何遵循本标准的软件,例如,在请求“Latin1”或“ASCII”解码该字节时,会将 0x80 解码为 U+20AC (€)。

不遵循本标准的软件并不总是给出相同的答案。这一问题的根源在于最初指定 Latin1 的文档(ISO/IEC 8859-1)未为字节范围 0x00 到 0x1F 或 0x7F 到 0x9F 提供任何映射。同样,最初指定 ASCII 的文档(ISO/IEC 646 等)未为字节范围 0x80 到 0xFF 提供任何映射。这意味着在请求使用 Latin1 或 ASCII 编码时,不同的软件为这些字节选择了不同的代码点映射。Web 浏览器和与浏览器兼容的软件选择根据windows-1252映射这些字节,windows-1252 是两者的超集,这一选择已在本标准中被规范化。其他软件会抛出错误,或使用同构解码或其他映射。[ISO8859-1][ISO646]

因此,实施者和开发人员在使用以“Latin1”或“ASCII”为术语的 API 的库时需要格外小心。如果这些库为原始规范中未定义的字节选择了其他行为,则它们很可能不会给出符合本标准的答案。

4.3. 输出编码

要从编码encoding获取输出编码,请执行以下步骤:

  1. 如果encoding替代UTF-16BE/LE,则返回UTF-8

  2. 返回encoding

获取输出编码算法对于 URL 解析和 HTML 表单提交非常有用,因为两者都需要完全符合此算法。

5. 索引

大多数旧的编码都使用索引。一个索引是一个有序的条目列表,每个条目由一个指针和一个对应的代码点组成。在一个索引中,指针是唯一的,而代码点可以重复。

一个高效的实现可能为每个编码提供两个索引。一个针对其解码器优化,另一个针对其编码器优化。

要在一个索引中找到指针及其对应的代码点,请执行以下步骤:令lines为将资源内容按 U+000A LF 分割的结果。然后移除lines中为空字符串或以 U+0023 (#) 开头的每一项。然后通过将lines中的每一项按 U+0009 TAB 分割来找到指针及其对应的代码点。第一个子项是指针(作为十进制数),第二个是对应的代码点(作为十六进制数)。其他子项不相关。

为了表示变化,一个索引包括一个标识符和一个日期。如果标识符发生变化,则索引也发生变化。

索引代码点indexpointer对应的代码点,如果pointer不在index中,则为 null。

索引指针indexcodePoint对应的第一个指针,如果codePoint不在index中,则为 null。

除了GB18030 范围索引ISO-2022-JP 片假名索引外,每个索引都有一个非规范性的可视化。JIS0208 索引也有一个替代的Shift_JIS可视化。此外,除了GB18030 范围索引ISO-2022-JP 片假名索引外,每个索引的基本多语言平面覆盖范围也有可视化。

可视化的图例如下:

以下是本规范定义的索引,不包括单字节索引,后者有自己的表格:

索引 备注
Big5 索引 index-big5.txt Big5 索引可视化 Big5 索引 BMP 覆盖范围 与 Big5 标准结合香港补充字符集及其他常见扩展相匹配。
EUC-KR 索引 index-euc-kr.txt EUC-KR 索引可视化 EUC-KR 索引 BMP 覆盖范围 与 KS X 1001 标准和统一韩文代码(通常称为 Windows 代码页 949)相匹配。完全覆盖 Unicode 的韩文音节块。可视化中左上角位于指针 9026 的韩文块按 Unicode 顺序排列。单独来看,此索引中的其余韩文音节也按 Unicode 顺序排列。
GB18030 索引 index-gb18030.txt GB18030 索引可视化 GB18030 索引 BMP 覆盖范围 与 GB18030-2022 标准中编码为两个字节的代码点相匹配,但 0xA3 0xA0 映射到 U+3000 IDEOGRAPHIC SPACE 以与已部署内容兼容。此索引完全覆盖 Unicode 的 CJK 统一表意文字块。可视化中位于(第一个)U+3000 上方或左侧的该块中的条目按 Unicode 顺序排列。
GB18030 范围索引 index-gb18030-ranges.txt 索引的工作方式与其他所有索引不同。列出所有代码点将导致超过一百万个条目,而它们可以整齐地表示为 207 个范围,并结合简单的限制检查。因此,它仅在表面上与 GB18030-2000 标准中编码为四个字节的代码点相匹配。GB18030-2005 修订版的更改由伴随此索引的下文GB18030 范围索引代码点GB18030 范围索引指针算法内联处理。而 GB18030-2022 修订版的更改则再次以不同方式处理,以避免进一步增加映射到专用使用代码点的字节序列数量。相关的专用使用代码点在GB18030 编码器中通过一个旁表直接映射,以保持与它们之前映射方式的兼容性。
JIS0208 索引 index-jis0208.txt JIS0208 索引可视化, Shift_JIS 可视化 JIS0208 索引 BMP 覆盖范围 这是 JIS X 0208 标准,包括以前来自 IBM 和 NEC 的专有扩展。
JIS0212 索引 index-jis0212.txt JIS0212 索引可视化 JIS0212 索引 BMP 覆盖范围 这是 JIS X 0212 标准。由于在其他地方缺乏广泛支持,它仅由EUC-JP 解码器使用。
ISO-2022-JP 片假名索引 index-iso-2022-jp-katakana.txt 根据 Unicode 规范化形式 KC,这将半角片假名映射到全角片假名,但 U+FF9E (゙) 和 U+FF9F (゚) 映射到 U+309B (゛) 和 U+309C (゜),而不是 U+3099 (◌゙) 和 U+309A (◌゚)。它仅由ISO-2022-JP 编码器使用。[UNICODE]

GB18030 范围索引代码点是针对pointer的以下步骤的返回值:

  1. 如果pointer大于 39419 且小于 189000,或者pointer大于 1237575,则返回 null。

  2. 如果pointer是 7457,则返回代码点 U+E7C7。

  3. offsetGB18030 范围索引中小于或等于pointer的最后一个指针,并令codePointOffset为其对应的代码点。

  4. 返回一个代码点,其值为codePointOffset + pointeroffset

GB18030 范围索引指针是针对codePoint的以下步骤的返回值:

  1. 如果codePoint是 U+E7C7,则返回指针 7457。

  2. offsetGB18030 范围索引中小于或等于codePoint的最后一个代码点,并令pointerOffset为其对应的指针。

  3. 返回一个指针,其值为pointerOffset + codePointoffset

Shift_JIS 索引指针是针对codePoint的以下步骤的返回值:

  1. indexJIS0208 索引,排除所有指针在 8272 到 8835(含)范围内的条目。

    JIS0208 索引包含重复的代码点,因此排除这些条目会导致使用后面的代码点。

  2. 返回indexcodePoint索引指针

Big5 索引指针是针对codePoint的以下步骤的返回值:

  1. indexBig5 索引,排除所有指针小于 (0xA1 - 0x81) × 157 的条目。

    避免直接返回香港增补字符集扩展。

  2. 如果codePoint是 U+2550 (═)、U+255E (╞)、U+2561 (╡)、U+256A (╪)、U+5341 (十) 或 U+5345 (卅),则返回index中与codePoint对应的最后一个指针。

    还有其他重复的代码点,但对于那些代码点,应使用第一个指针。

  3. 返回indexcodePoint索引指针


所有索引也可以作为非规范性的indexes.json资源获取。(GB18030 范围索引在此处采用稍有不同的格式,以便表示范围。)

6. 为标准提供的挂钩

下面定义的算法(UTF-8 解码不带 BOM 的 UTF-8 解码不带 BOM 或失败的 UTF-8 解码以及UTF-8 编码)旨在供其他标准使用。

对于解码,新格式应使用UTF-8 解码。对于格式或协议中的标识符或字节序列,请使用不带 BOM 的 UTF-8 解码不带 BOM 或失败的 UTF-8 解码

对于编码,应使用UTF-8 编码

标准应确保它们传递给UTF-8 编码(以及旧的编码)的输入 I/O 队列实际上是标量值的 I/O 队列,即它们不包含代理项

这些挂钩(以及解码编码)将阻塞,直到输入 I/O 队列被完全消耗。为了在使用输出令牌时将其推入流中,调用者应使用空的输出 I/O 队列调用挂钩,并并行地从中读取。请注意,在使用不带 BOM 或失败的 UTF-8 解码时需要小心,因为在解码过程中发现的任何错误都将阻止队列末尾项被推入输出 I/O 队列。

要对字节的 I/O 队列ioQueue进行UTF-8 解码,给定一个可选的标量值 I/O 队列output(默认为 « »),请执行以下步骤:

  1. buffer为从ioQueue窥视三个字节并转换为字节序列的结果。

  2. 如果buffer是 0xEF 0xBB 0xBF,则从ioQueue读取三个字节。(不对这些字节执行任何操作。)

  3. 使用UTF-8解码器实例、ioQueueoutput和"replacement"处理队列

  4. 返回output

要对字节的 I/O 队列ioQueue进行不带 BOM 的 UTF-8 解码,给定一个可选的标量值 I/O 队列output(默认为 « »),请执行以下步骤:

  1. 使用UTF-8解码器实例、ioQueueoutput和"replacement"处理队列

  2. 返回output

要对字节的 I/O 队列ioQueue进行不带 BOM 或失败的 UTF-8 解码,给定一个可选的标量值 I/O 队列output(默认为 « »),请执行以下步骤:

  1. potentialError为使用UTF-8解码器实例、ioQueueoutput和"fatal"处理队列的结果。

  2. 如果potentialError是一个错误,则返回失败。

  3. 返回output


要对标量值的 I/O 队列ioQueue进行UTF-8 编码,给定一个可选的字节 I/O 队列output(默认为 « »),返回使用UTF-8编码和output编码ioQueue的结果。

6.1. 为标准提供的旧版挂钩

强烈建议标准不要使用解码BOM 嗅探编码,除非为了兼容性需要。需要这些旧版挂钩的标准很可能还需要使用获取编码(将标签转换为编码)和获取输出编码(将一个编码转换为适合传递给编码的另一个编码)。

对于 URL 百分号编码这种极其特殊的情况,需要自定义编码器错误处理。应使用获取编码器编码或失败算法。其他算法不应直接使用。

要对字节的 I/O 队列ioQueue进行解码,给定一个备用编码encoding和一个可选的标量值 I/O 队列output(默认为 « »),请执行以下步骤:

  1. BOMEncoding为对ioQueue进行BOM 嗅探的结果。

  2. 如果BOMEncoding不为 null:

    1. encoding设置为BOMEncoding

    2. 如果BOMEncodingUTF-8,则从ioQueue读取三个字节;否则读取两个字节。(不对这些字节执行任何操作。)

    为了与已部署内容兼容,字节顺序标记比任何其他东西都更具权威性。在使用 HTTP 的上下文中,这违反了 `Content-Type` 标头的语义。

  3. 使用encoding解码器实例、ioQueueoutput和"replacement"处理队列

  4. 返回output

要对字节的 I/O 队列ioQueue进行BOM 嗅探,请执行以下步骤:

  1. BOM为从ioQueue窥视 3 个字节并转换为字节序列的结果。

  2. 对于下表中的每一行,从第一行开始向下,如果BOM第一列中给出的字节开头,则返回该行第二列单元格中给出的编码。否则,返回 null。

    字节顺序标记 编码
    0xEF 0xBB 0xBF UTF-8
    0xFE 0xFF UTF-16BE
    0xFF 0xFE UTF-16LE

此挂钩是一个变通方法,因为解码无法向调用者传达它已找到字节顺序标记,因此未使用提供的编码。此挂钩应在解码之前调用,它将返回与找到的字节顺序标记对应的编码,否则返回 null。


要对标量值的 I/O 队列ioQueue进行编码,给定一个编码encoding和一个可选的字节 I/O 队列output(默认为 « »),请执行以下步骤:

  1. encoder为从encoding获取编码器的结果。

  2. 使用encoderioQueueoutput和"html"处理队列

  3. 返回output

这是 HTML 表单的旧版挂钩。在其上层叠UTF-8 编码是安全的,因为它从不触发错误[HTML]


要从编码encoding获取编码器

  1. 断言encoding不是替代UTF-16BE/LE

  2. 返回encoding编码器实例。

要对标量值的 I/O 队列ioQueue进行编码或失败,给定一个编码器实例encoder和一个字节 I/O 队列output,请执行以下步骤:

  1. potentialError为使用encoderioQueueoutput和"fatal"处理队列的结果。

  2. 队列末尾推入output

  3. 如果potentialError是一个错误,则返回错误代码点

  4. 返回 null。

这是 URL 百分号编码的旧版挂钩。调用者必须保持一个编码器实例的活动状态,因为ISO-2022-JP 编码器在返回错误时可能处于两种不同状态之一。这也意味着,如果调用者以某种方式发出字节来编码错误,这些字节必须在 0x00 到 0x7F(含)的范围内,不包括 0x0E、0x0F、0x1B、0x5C 和 0x7E。[URL]

特别是,如果在返回错误时,ISO-2022-JP 编码器处于罗马状态,调用者不能输出 0x5C (\),因为它不会被解码为 U+005C (\)。因此,将编码或失败用于非预期目的的应用程序应注意防止将ISO-2022-JP 编码器与替换方案(例如 JavaScript 和 CSS 的替换方案)结合使用,这些方案使用 U+005C (\) 作为替换语法的一部分(例如,\u2603),或者确保将替换语法通过编码器传递(与 URL 百分号编码相反)。

返回值要么是表示无法编码的代码点的数字,要么是 null(如果没有错误)。当它返回非 null 时,调用者将必须再次调用它,提供相同的编码器实例和一个新的输出 I/O 队列。

7. API

本节使用 Web IDL 的术语。浏览器用户代理必须支持此 API。JavaScript 实现应支持此 API。鼓励其他用户代理或编程语言使用适合其需求的 API,可能不是这一个。[WEBIDL]

以下示例使用 TextEncoder 对象将字符串数组编码为 ArrayBuffer。结果是一个 Uint8Array,其中包含字符串的数量(作为 Uint32Array),后跟第一个字符串的长度(作为 Uint32Array)、UTF-8 编码的字符串数据、第二个字符串的长度(作为 Uint32Array)、字符串数据,依此类推。

function encodeArrayOfStrings(strings) {
          var encoder, encoded, len, bytes, view, offset;
        
          encoder = new TextEncoder();
          encoded = [];
        
          len = Uint32Array.BYTES_PER_ELEMENT;
          for (var i = 0; i < strings.length; i++) {
            len += Uint32Array.BYTES_PER_ELEMENT;
            encoded[i] = encoder.encode(strings[i]);
            len += encoded[i].byteLength;
          }
        
          bytes = new Uint8Array(len);
          view = new DataView(bytes.buffer);
          offset = 0;
        
          view.setUint32(offset, strings.length);
          offset += Uint32Array.BYTES_PER_ELEMENT;
          for (var i = 0; i < encoded.length; i += 1) {
            len = encoded[i].byteLength;
            view.setUint32(offset, len);
            offset += Uint32Array.BYTES_PER_ELEMENT;
            bytes.set(encoded[i], offset);
            offset += len;
          }
          return bytes.buffer;
        }

以下示例将包含由前一个示例生成的格式编码的数据的 ArrayBuffer(或用于非 UTF-8 编码的等效算法)解码回字符串数组。

function decodeArrayOfStrings(buffer, encoding) {
          var decoder, view, offset, num_strings, strings, len;
        
          decoder = new TextDecoder(encoding);
          view = new DataView(buffer);
          offset = 0;
          strings = [];
        
          num_strings = view.getUint32(offset);
          offset += Uint32Array.BYTES_PER_ELEMENT;
          for (var i = 0; i < num_strings; i++) {
            len = view.getUint32(offset);
            offset += Uint32Array.BYTES_PER_ELEMENT;
            strings[i] = decoder.decode(
              new DataView(view.buffer, offset, len));
            offset += len;
          }
          return strings;
        }

7.1. 接口混入 TextDecoderCommon

interface mixin TextDecoderCommon {
          readonly attribute DOMString encoding;
          readonly attribute boolean fatal;
          readonly attribute boolean ignoreBOM;
        };
        

TextDecoderCommon 接口混入定义了 TextDecoderTextDecoderStream 对象共享的通用 getter。这些对象有关联的:

编码
一个编码
解码器
一个解码器实例。
I/O 队列
一个字节的I/O 队列
忽略 BOM
一个布尔值,初始为 false。
已见 BOM
一个布尔值,初始为 false。
错误模式
一个错误模式,初始为 "replacement"。

序列化 I/O 队列算法,给定一个 TextDecoderCommon decoder 和一个标量值的I/O 队列 ioQueue,运行以下步骤:

  1. output 为空字符串。

  2. 当为真时:

    1. item 为从 ioQueue 读取的结果。

    2. 如果 item队列末尾,则返回 output

    3. 如果 decoder编码UTF-8UTF-16BE/LE,并且 decoder忽略 BOM已见 BOM均为 false:

      1. decoder已见 BOM设置为 true。

      2. 如果 item 是 U+FEFF BOM,则继续

    4. item 附加到 output

该算法在 BOM 处理方面与平台其余部分使用的解码算法故意不同,以便为 API 用户提供更多控制。


encoding getter 的步骤是返回this编码名称,并ASCII 小写化

fatal getter 的步骤是:如果this错误模式是 "fatal",则返回 true;否则返回 false。

ignoreBOM getter 的步骤是返回this忽略 BOM

7.2. 接口 TextDecoder

dictionary TextDecoderOptions {
  boolean fatal = false;
  boolean ignoreBOM = false;
};

dictionary TextDecodeOptions {
  boolean stream = false;
};

[Exposed=*]
interface TextDecoder {
  constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options = {});

  USVString decode(optional AllowSharedBufferSource input, optional TextDecodeOptions options = {});
};
TextDecoder includes TextDecoderCommon;

一个 TextDecoder 对象拥有一个关联的不刷新标志(do not flush flag),它是一个布尔值, 初始为 false。

decoder = new TextDecoder([label = "utf-8" [, options]])

返回一个新的 TextDecoder 对象。

如果 label 不是一个有效的标签,或者是用于 replacement 的标签,则抛出一个 RangeError

decoder . encoding

返回编码名称,小写形式。

decoder . fatal

如果错误模式是 "fatal",则返回 true;否则返回 false。

decoder . ignoreBOM

返回忽略 BOM 标志的值。

decoder . decode([input [, options]])

返回运行编码解码器的结果。 该方法可以被多次调用,并将 optionsstream 属性设置为 true,然后最后一次调用时不再设置 optionsstream(或设为 false),以处理分段的输入。如果最后一次调用(`stream` 未设置或为 false)时没有 input,最清晰的做法是省略这两个参数。

var string = "", decoder = new TextDecoder(encoding), buffer;
while(buffer = next_chunk()) {
  string += decoder.decode(buffer, {stream:true});
}
string += decoder.decode(); // 队列末尾

如果错误模式是 "fatal" 且编码解码器返回错误, 则抛出一个 TypeError

new TextDecoder(label, options) 构造函数的步骤如下:

  1. encoding 为从 label 获取编码的结果。

  2. 如果 encoding 是 failure 或 replacement,则抛出一个 RangeError

  3. 设置当前对象编码encoding

  4. 如果 options["fatal"] 为 true,则设置当前对象错误模式为 "fatal"。

  5. 设置当前对象忽略 BOM 标志options["ignoreBOM"]。

decode(input, options) 方法的步骤如下:

  1. 如果当前对象不刷新标志为 false,则设置当前对象解码器为一个新的当前对象编码解码器实例,当前对象I/O 队列为字节的I/O 队列 « 队列末尾 », 以及当前对象BOM 已见标志为 false。

  2. 设置当前对象不刷新标志options["stream"]。

  3. 如果给定了 input,则将 input一个副本 推入当前对象I/O 队列中。

    强烈建议实现者采用 避免此次复制的实现策略。这样做时,必须确保对 input 的更改 不会影响未来对 decode() 的调用。

    SharedArrayBuffer 对象暴露的内存不符合通常用于实现的编程语言内存模型所需的数据竞争自由属性。在实现时,访问由 SharedArrayBuffer 对象暴露的内存时务必使用适当的设施。

  4. output 为标量值的I/O 队列 « 队列末尾 »。

  5. 循环执行:

    1. item 为从当前对象I/O 队列读取的结果。

    2. 如果 item队列末尾当前对象不刷新标志为 true,则返回 序列化 I/O 队列(以当前对象output 为参数)的结果。

      流式处理的工作方式是,当当前对象不刷新标志为 true 时,此处不处理队列末尾,也不将其设为 false。这样一来, 在后续调用中,当前对象解码器不会在算法的第一步被重新设置,其状态得以保留。

    3. 否则:

      1. result处理一个项目(以 item当前对象解码器当前对象I/O 队列output当前对象错误模式为参数)的结果。

      2. 如果 result完成,则返回 序列化 I/O 队列(以当前对象output 为参数)的结果。

      3. 否则,如果 result错误,则抛出一个TypeError

7.3. 接口混入 TextEncoderCommon

interface mixin TextEncoderCommon {
  readonly attribute DOMString encoding;
};

TextEncoderCommon 接口混入定义了 TextEncoderTextEncoderStream 对象共享的通用 getter。

encoding getter 的步骤是返回 "utf-8"。

7.4. 接口 TextEncoder

dictionary TextEncoderEncodeIntoResult {
  unsigned long long read;
  unsigned long long written;
};

[Exposed=*]
interface TextEncoder {
  constructor();

  [NewObject] Uint8Array encode(optional USVString input = "");
  TextEncoderEncodeIntoResult encodeInto(USVString source, [AllowShared] Uint8Array destination);
};
TextEncoder includes TextEncoderCommon;

一个 TextEncoder 对象不提供 label 参数,因为它只支持 UTF-8。它也不提供 stream 选项,因为没有编码器需要缓冲标量值。


encoder = new TextEncoder()

返回一个新的 TextEncoder 对象。

encoder . encoding

返回 "utf-8"。

encoder . encode([input = ""])

返回运行 UTF-8 编码器的结果。

encoder . encodeInto(source, destination)

source 上运行UTF-8 编码器,将该操作的结果存入 destination,并以一个对象的形式返回进度,其中 readsource 中已转换的代码单元数,而 writtendestination 中已修改的字节数。

new TextEncoder() 构造函数的步骤是:不执行任何操作。

encode(input) 方法的步骤如下:

  1. input 转换为标量值的I/O 队列

  2. output 为字节的I/O 队列 « 队列末尾 »。

  3. 循环执行:

    1. item 为从 input 读取的结果。

    2. result 为使用 item、一个 UTF-8 编码器实例、inputoutput 和 "fatal" 处理一个项目的结果。

    3. 断言result 不是一个错误

      UTF-8 编码器不会返回错误

    4. 如果 result完成,则返回根据 output当前对象相关领域创建一个 Uint8Array 对象的结果。

encodeInto(source, destination) 方法的步骤如下:

  1. read 为 0。

  2. written 为 0。

  3. encoder 为一个UTF-8 编码器的实例。

  4. unused 为标量值的I/O 队列 « 队列末尾 »。

    下面调用的处理程序算法需要此参数,但 UTF-8 编码器并未使用它。

  5. source 转换为标量值的I/O 队列

  6. 循环执行:

    1. item 为从 source 读取的结果。

    2. result 为在 unuseditem 上运行 encoder处理程序的结果。

    3. 如果 result完成,则跳出循环

    4. 否则:

      1. 如果 destination字节长度减去 written 大于或等于 result 中的字节数:

        1. 如果 item 大于 U+FFFF,则将 read 增加 2。

        2. 否则,将 read 增加 1。

        3. result 中的字节写入 destination起始偏移量 设为 written

          参见上方 关于 SharedArrayBuffer 对象的警告

        4. written 增加 result 中的字节数。

      2. 否则,跳出循环

  7. 返回 «[ "read" → read, "written" → written ]»。

encodeInto() 方法可用于将字符串编码到一个已存在的 ArrayBuffer 对象中。以下示例中的一些细节留给读者作为练习,但它展示了使用此方法的一种可行方式:

function convertString(buffer, input, callback) {
  let bufferSize = 256,
      bufferStart = malloc(buffer, bufferSize),
      writeOffset = 0,
      readOffset = 0;
  while (true) {
    const view = new Uint8Array(buffer, bufferStart + writeOffset, bufferSize - writeOffset),
          {read, written} = cachedEncoder.encodeInto(input.substring(readOffset), view);
    readOffset += read;
    writeOffset += written;
    if (readOffset === input.length) {
      callback(bufferStart, writeOffset);
      free(buffer, bufferStart);
      return;
    }
    bufferSize *= 2;
    bufferStart = realloc(buffer, bufferStart, bufferSize);
  }
}

7.5. 接口 TextDecoderStream

[Exposed=*]
interface TextDecoderStream {
  constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options = {});
};
TextDecoderStream includes TextDecoderCommon;
TextDecoderStream includes GenericTransformStream;
decoder = new TextDecoderStream([label = "utf-8" [, options]])

返回一个新的 TextDecoderStream 对象。

如果 label 不是一个有效的标签,或者是用于replacement的标签,则抛出一个 RangeError

decoder . encoding

返回编码名称,小写形式。

decoder . fatal

如果错误模式是 "fatal",则返回 true,否则返回 false。

decoder . ignoreBOM

返回忽略 BOM 标志的值。

decoder . readable

返回一个可读流,其是通过在写入到 writable的块上运行编码解码器而产生的字符串。

decoder . writable

返回一个可写流,它接受 AllowSharedBufferSource 块,并通过编码解码器运行它们,然后才使它们对readable可用。

通常这将通过在一个 ReadableStream 源上使用 pipeThrough() 方法来完成。

var decoder = new TextDecoderStream(encoding);
byteReadable
  .pipeThrough(decoder)
  .pipeTo(textWritable);

如果错误模式是 "fatal" 并且编码解码器返回错误,那么 readablewritable 都将因一个 TypeError 而出错。

new TextDecoderStream(label, options) 构造函数的步骤如下:

  1. encoding 为从 label 获取编码的结果。

  2. 如果 encoding 是 failure 或 replacement,则抛出一个 RangeError

  3. 设置当前对象编码encoding

  4. 如果 options["fatal"] 为 true,则设置当前对象错误模式为 "fatal"。

  5. 设置当前对象忽略 BOM 标志options["ignoreBOM"]。

  6. 设置当前对象解码器为一个当前对象编码解码器的新实例,并设置当前对象I/O 队列为一个新的I/O 队列

  7. transformAlgorithm 为一个接受 chunk 参数的算法,并使用当前对象chunk 运行解码并入队一个块算法。

  8. flushAlgorithm 为一个不接受参数的算法,并使用当前对象运行刷新并入队算法。

  9. transformStream 为一个新的 TransformStream

  10. 设置 transformStreamtransformAlgorithm 设为 transformAlgorithmflushAlgorithm 设为 flushAlgorithm

  11. 设置当前对象transformtransformStream

解码并入队一个块算法,给定一个 TextDecoderStream 对象 decoder 和一个 chunk,运行以下步骤:

  1. bufferSource 为将 chunk 转换为 AllowSharedBufferSource 的结果。

  2. bufferSource一个副本 推入 decoderI/O 队列

    参见上方 关于 SharedArrayBuffer 对象的警告

  3. output 为标量值的I/O 队列 « 队列末尾 »。

  4. 循环执行:

    1. item 为从 decoderI/O 队列读取的结果。

    2. 如果 item队列末尾

      1. outputChunk 为使用 decoderoutput 运行序列化 I/O 队列的结果。

      2. 如果 outputChunk 不是空字符串,则 在 decodertransform入队 outputChunk

      3. 返回。

    3. result 为使用 itemdecoder解码器decoderI/O 队列outputdecoder错误模式处理一个项目的结果。

    4. 如果 result错误,则抛出一个 TypeError

刷新并入队算法,用于处理来自输入 ReadableStream 对象的数据结束,给定一个 TextDecoderStream 对象 decoder,运行以下步骤:

  1. output 为标量值的I/O 队列 « 队列末尾 »。

  2. 循环执行:

    1. item 为从 decoderI/O 队列读取的结果。

    2. result 为使用 itemdecoder解码器decoderI/O 队列outputdecoder错误模式处理一个项目的结果。

    3. 如果 result完成

      1. outputChunk 为使用 decoderoutput 运行序列化 I/O 队列的结果。

      2. 如果 outputChunk 不是空字符串,则 在 decodertransform入队 outputChunk

      3. 返回。

    4. 否则,如果 result错误,则抛出一个 TypeError

7.6. 接口 TextEncoderStream

[Exposed=*]
interface TextEncoderStream {
  constructor();
};
TextEncoderStream includes TextEncoderCommon;
TextEncoderStream includes GenericTransformStream;

一个 TextEncoderStream 对象拥有一个关联的:

编码器(encoder)
一个编码器实例。
前导代理项(leading surrogate)
null 或一个前导代理项,初始为 null。

一个 TextEncoderStream 对象不提供 label 参数,因为它只支持 UTF-8

encoder = new TextEncoderStream()

返回一个新的 TextEncoderStream 对象。

encoder . encoding

返回 "utf-8"。

encoder . readable

返回一个可读流,其是通过在写入到 writable 的块上运行 UTF-8编码器而产生的 Uint8Array

encoder . writable

返回一个可写流,它接受字符串块,并通过 UTF-8编码器运行它们,然后才使它们对 readable 可用。

通常这将通过在一个 ReadableStream 源上使用 pipeThrough() 方法来完成。

textReadable
  .pipeThrough(new TextEncoderStream())
  .pipeTo(byteWritable);

new TextEncoderStream() 构造函数的步骤如下:

  1. 设置当前对象编码器为一个 UTF-8 编码器的实例。

  2. transformAlgorithm 为一个接受 chunk 参数的算法,并使用当前对象chunk 运行编码并入队一个块算法。

  3. flushAlgorithm 为一个使用当前对象运行编码并刷新算法的算法。

  4. transformStream 为一个新的 TransformStream

  5. 设置 transformStreamtransformAlgorithm 设为 transformAlgorithmflushAlgorithm 设为 flushAlgorithm

  6. 设置当前对象transformtransformStream


编码并入队一个块算法,给定一个 TextEncoderStream 对象 encoderchunk,运行以下步骤:

  1. input 为将 chunk 转换为 DOMString 的结果。

  2. input 转换为代码单元I/O 队列

    DOMString 以及代码单元而非标量值的I/O 队列在此处被使用,以便在块之间分割的代理对可以被重新组装成 适当的标量值。除此以外,其行为与 USVString 相同。特别地, 孤立的代理项将被替换为 U+FFFD ()。

  3. output 为字节的I/O 队列 « 队列末尾 »。

  4. 循环执行:

    1. item 为从 input 读取的结果。

    2. 如果 item队列末尾

      1. output 转换为一个 字节序列。

      2. 如果 output 不为空

        1. chunk 为根据 outputencoder相关领域创建一个 Uint8Array 对象的结果。

        2. chunk 入队encodertransform 中。

      3. 返回。

    3. result 为使用 encoderiteminput 执行将代码单元转换为标量值算法的结果。

    4. 如果 result 不是继续,则使用 resultencoder编码器inputoutput 和 "fatal" 处理一个项目

将代码单元转换为标量值算法,给定一个 TextEncoderStream 对象 encoder、一个代码单元 item 和一个代码单元的I/O 队列 input,运行以下步骤:

  1. 如果 encoder前导代理项非空:

    1. leadingSurrogateencoder前导代理项

    2. 设置 encoder前导代理项为 null。

    3. 如果 item 是一个后尾代理项,则返回一个根据 leadingSurrogateitem 从代理对得到的标量值

    4. item 恢复input

    5. 返回 U+FFFD ()。

  2. 如果 item 是一个前导代理项,则设置 encoder前导代理项item 并返回继续

  3. 如果 item 是一个后尾代理项,则返回 U+FFFD ()。

  4. 返回 item

这相当于 Infra 标准中的“一个字符串转换为一个 标量值字符串”算法,但允许 代理对在字符串之间被分割。 [INFRA]

编码并刷新算法,给定一个 TextEncoderStream 对象 encoder,运行以下步骤:

  1. 如果 encoder前导代理项非空:

    1. chunk 为根据 « 0xEF, 0xBF, 0xBD » 和 encoder相关领域创建一个 Uint8Array 对象的结果。

      这是 U+FFFD () 在UTF-8中的字节表示。

    2. chunk 入队encodertransform 中。

8. 编码

8.1. UTF-8

8.1.1. UTF-8 解码器

字节顺序标记(BOM)的优先级高于标签,因为在已部署的内容中发现它更为准确。因此,它不属于 UTF-8 解码器算法的一部分,而是属于 decodeUTF-8 decode 算法。

UTF-8解码器拥有一个关联的:

UTF-8 码点
已见 UTF-8 字节数
所需 UTF-8 字节数
均为数字,初始为 0。
UTF-8 下界
一个字节,初始为 0x80。
UTF-8 上界
一个字节,初始为 0xBF。

UTF-8 解码器处理程序,给定 ioQueuebyte,运行以下步骤:

  1. 如果 byte队列末尾所需 UTF-8 字节数不为 0,则将 所需 UTF-8 字节数设为 0 并返回错误

  2. 如果 byte队列末尾,则返回完成

  3. 如果所需 UTF-8 字节数为 0,则根据 byte

    0x00 到 0x7F

    返回一个码点,其值为 byte

    0xC2 到 0xDF
    1. 所需 UTF-8 字节数设为 1。

    2. UTF-8 码点设为 byte & 0x1F。

      byte 的最低五位。

    0xE0 到 0xEF
    1. 如果 byte 是 0xE0,则将UTF-8 下界设为 0xA0。

    2. 如果 byte 是 0xED,则将UTF-8 上界设为 0x9F。

    3. 所需 UTF-8 字节数设为 2。

    4. UTF-8 码点设为 byte & 0xF。

      byte 的最低四位。

    0xF0 到 0xF4
    1. 如果 byte 是 0xF0,则将UTF-8 下界设为 0x90。

    2. 如果 byte 是 0xF4,则将UTF-8 上界设为 0x8F。

    3. 所需 UTF-8 字节数设为 3。

    4. UTF-8 码点设为 byte & 0x7。

      byte 的最低三位。

    其他情况

    返回错误

    返回继续

  4. 如果 byte 不在UTF-8 下界UTF-8 上界(含)的范围内:

    1. UTF-8 码点所需 UTF-8 字节数已见 UTF-8 字节数设为 0, 将UTF-8 下界设为 0x80,并将 UTF-8 上界设为 0xBF。

    2. byte 恢复ioQueue

    3. 返回错误

  5. UTF-8 下界设为 0x80,并将 UTF-8 上界设为 0xBF。

  6. UTF-8 码点设为 (UTF-8 码点 << 6) | (byte & 0x3F)

    UTF-8 码点的现有位左移六位,并将新空出的最低六位设置为 byte 的最低六位。

  7. 已见 UTF-8 字节数增加一。

  8. 如果已见 UTF-8 字节数不等于所需 UTF-8 字节数,则返回 继续

  9. codePointUTF-8 码点

  10. UTF-8 码点所需 UTF-8 字节数已见 UTF-8 字节数设为 0。

  11. 返回一个码点,其值为 codePoint

上述UTF-8 解码器中的约束与 Unicode 标准中的“使用 U+FFFD 的最佳实践”相匹配。根据编码标准,不允许有其他行为(实现相同结果的其他算法是允许的,甚至是被鼓励的)。 [UNICODE]

8.1.2. UTF-8 编码器

UTF-8编码器处理程序,给定 unusedcodePoint,执行以下步骤:

  1. 如果 codePoint队列末尾,则返回完成

  2. 如果 codePoint 是一个ASCII 码点,则返回一个值为 codePoint 的字节。

  3. 根据 codePoint 所在的范围设置 countoffset

    U+0080 到 U+07FF(含)
    1 和 0xC0
    U+0800 到 U+FFFF(含)
    2 和 0xE0
    U+10000 到 U+10FFFF(含)
    3 和 0xF0
  4. bytes 为一个字节序列,其第一个字节是 (codePoint >> (6 × count)) + offset

  5. count 大于 0 时:

    1. temp 设置为 codePoint >> (6 × (count − 1))。

    2. bytes 追加 0x80 | (temp & 0x3F)。

    3. count 减一。

  6. 按顺序返回字节序列 bytes

该算法的结果与 Unicode 标准中描述的算法相同。 此处包含它是为了完整性。[UNICODE]

9. 旧式单字节编码

一个编码,其中每个字节要么是一个单独的码点,要么什么都不是,这就是单字节编码单字节编码共享 解码器编码器单字节索引,由单字节解码器单字节编码器引用,由下表定义,并取决于所使用的单字节编码。除了两种 单字节编码外,所有单字节编码都有一个唯一的索引

IBM866 index-ibm866.txt IBM866 索引可视化 IBM866 索引 BMP 覆盖范围
ISO-8859-2 index-iso-8859-2.txt ISO-8859-2 索引可视化 ISO-8859-2 索引 BMP 覆盖范围
ISO-8859-3 index-iso-8859-3.txt ISO-8859-3 索引可视化 ISO-8859-3 索引 BMP 覆盖范围
ISO-8859-4 index-iso-8859-4.txt ISO-8859-4 索引可视化 ISO-8859-4 索引 BMP 覆盖范围
ISO-8859-5 index-iso-8859-5.txt ISO-8859-5 索引可视化 ISO-8859-5 索引 BMP 覆盖范围
ISO-8859-6 index-iso-8859-6.txt ISO-8859-6 索引可视化 ISO-8859-6 索引 BMP 覆盖范围
ISO-8859-7 index-iso-8859-7.txt ISO-8859-7 索引可视化 ISO-8859-7 索引 BMP 覆盖范围
ISO-8859-8 index-iso-8859-8.txt ISO-8859-8 索引可视化 ISO-8859-8 索引 BMP 覆盖范围
ISO-8859-8-I
ISO-8859-10 index-iso-8859-10.txt ISO-8859-10 索引可视化 ISO-8859-10 索引 BMP 覆盖范围
ISO-8859-13 index-iso-8859-13.txt ISO-8859-13 索引可视化 ISO-8859-13 索引 BMP 覆盖范围
ISO-8859-14 index-iso-8859-14.txt ISO-8859-14 索引可视化 ISO-8859-14 索引 BMP 覆盖范围
ISO-8859-15 index-iso-8859-15.txt ISO-8859-15 索引可视化 ISO-8859-15 索引 BMP 覆盖范围
ISO-8859-16 index-iso-8859-16.txt ISO-8859-16 索引可视化 ISO-8859-16 索引 BMP 覆盖范围
KOI8-R index-koi8-r.txt KOI8-R 索引可视化 KOI8-R 索引 BMP 覆盖范围
KOI8-U index-koi8-u.txt KOI8-U 索引可视化 KOI8-U 索引 BMP 覆盖范围
macintosh index-macintosh.txt macintosh 索引可视化 macintosh 索引 BMP 覆盖范围
windows-874 index-windows-874.txt windows-874 索引可视化 windows-874 索引 BMP 覆盖范围
windows-1250 index-windows-1250.txt windows-1250 索引可视化 windows-1250 索引 BMP 覆盖范围
windows-1251 index-windows-1251.txt windows-1251 索引可视化 windows-1251 索引 BMP 覆盖范围
windows-1252 index-windows-1252.txt windows-1252 索引可视化 windows-1252 索引 BMP 覆盖范围
windows-1253 index-windows-1253.txt windows-1253 索引可视化 windows-1253 索引 BMP 覆盖范围
windows-1254 index-windows-1254.txt windows-1254 索引可视化 windows-1254 索引 BMP 覆盖范围
windows-1255 index-windows-1255.txt windows-1255 索引可视化 windows-1255 索引 BMP 覆盖范围
windows-1256 index-windows-1256.txt windows-1256 索引可视化 windows-1256 索引 BMP 覆盖范围
windows-1257 index-windows-1257.txt windows-1257 索引可视化 windows-1257 索引 BMP 覆盖范围
windows-1258 index-windows-1258.txt windows-1258 索引可视化 windows-1258 索引 BMP 覆盖范围
x-mac-cyrillic index-x-mac-cyrillic.txt x-mac-cyrillic 索引可视化 x-mac-cyrillic 索引 BMP 覆盖范围

ISO-8859-8ISO-8859-8-I是 不同的编码名称,因为 ISO-8859-8 会影响布局方向。尽管 历史上ISO-8859-6和 “ISO-8859-6-I”也可能存在这种情况,但现在已不再如此。

9.1. 单字节解码器

单字节编码解码器处理程序,给定 unusedbyte,执行以下步骤:

  1. 如果 byte队列末尾,则返回完成

  2. 如果 byte 是一个ASCII 字节,则返回一个值为 byte 的码点。

  3. codePoint单字节索引byte − 0x80 对应的索引码点

  4. 如果 codePoint 为 null,则返回错误

  5. 返回一个值为 codePoint 的码点。

9.2. 单字节编码器

单字节编码编码器处理程序,给定 unusedcodePoint,执行以下步骤:

  1. 如果 codePoint队列末尾,则返回完成

  2. 如果 codePoint 是一个ASCII 码点,则返回一个值为 codePoint 的字节。

  3. pointer单字节索引codePoint 对应的索引指针

  4. 如果 pointer 为 null,则返回带 codePoint错误

  5. 返回一个值为 pointer + 0x80 的字节。

10. 旧式多字节简体中文编码

10.1. GBK

10.1.1. GBK 解码器

GBK解码器gb18030解码器

10.1.2. GBK 编码器

GBK编码器gb18030编码器,并将其 is GBK 标志设置为 true。

不将 GBKgb18030 完全别名化是一种保守的做法,旨在减少破坏使用 GBK 编码器生成的旧式服务器和其他内容消费者的可能性。

10.2. gb18030

10.2.1. gb18030 解码器

gb18030解码器拥有一个关联的:

gb18030 第一个字节
gb18030 第二个字节
gb18030 第三个字节
均为字节,初始值为 0x00。

gb18030解码器处理程序,给定 ioQueuebyte,执行以下步骤:

  1. 如果 byte队列末尾,并且gb18030 第一个字节gb18030 第二个字节gb18030 第三个字节均为 0x00,则返回完成

  2. 如果 byte队列末尾,并且gb18030 第一个字节gb18030 第二个字节gb18030 第三个字节不为 0x00,则将gb18030 第一个字节gb18030 第二个字节gb18030 第三个字节设为 0x00,并返回错误

  3. 如果gb18030 第三个字节不为 0x00:

    1. 如果 byte 不在 0x30 到 0x39(含)的范围内:

      1. 将 « gb18030 第二个字节, gb18030 第三个字节, byte » 恢复ioQueue

      2. gb18030 第一个字节gb18030 第二个字节gb18030 第三个字节设为 0x00。

      3. 返回错误

    2. codePoint 为 ((gb18030 第一个字节 − 0x81) × (10 × 126 × 10)) + ((gb18030 第二个字节 − 0x30) × (10 × 126)) + ((gb18030 第三个字节 − 0x81) × 10) + byte − 0x30 对应的gb18030 范围索引码点

    3. gb18030 第一个字节gb18030 第二个字节gb18030 第三个字节设为 0x00。

    4. 如果 codePoint 为 null,则返回错误

    5. 返回一个值为 codePoint 的码点。

  4. 如果gb18030 第二个字节不为 0x00:

    1. 如果 byte 在 0x81 到 0xFE(含)的范围内,则将gb18030 第三个字节设为 byte 并返回继续

    2. 将 « gb18030 第二个字节, byte » 恢复ioQueue,将 gb18030 第一个字节gb18030 第二个字节设为 0x00,并返回错误

  5. 如果gb18030 第一个字节不为 0x00:

    1. 如果 byte 在 0x30 到 0x39(含)的范围内,则将gb18030 第二个字节设为 byte 并返回继续

    2. leadinggb18030 第一个字节

    3. gb18030 第一个字节设为 0x00。

    4. pointer 为 null。

    5. 如果 byte 小于 0x7F,则令 offset 为 0x40;否则为 0x41。

    6. 如果 byte 在 0x40 到 0x7E(含)或 0x80 到 0xFE(含)的范围内, 则将 pointer 设为 (leading − 0x81) × 190 + (byteoffset)。

    7. 如果 pointer 为 null,则令 codePoint 为 null;否则为gb18030 索引pointer 对应的 索引码点

    8. 如果 codePoint 不为 null,则返回一个值为 codePoint 的码点。

    9. 如果 byte 是一个ASCII 字节,则将 byte 恢复ioQueue

    10. 返回错误

  6. 如果 byte 是一个ASCII 字节,则返回一个值为 byte 的码点。

  7. 如果 byte 是 0x80,则返回码点 U+20AC (€)。

  8. 如果 byte 在 0x81 到 0xFE(含)的范围内,则将gb18030 第一个字节设为 byte 并返回继续

  9. 返回错误

10.2.2. gb18030 编码器

gb18030编码器有一个关联的 is GBK 标志,它是一个布尔值, 初始为 false。

gb18030编码器处理程序,给定 unusedcodePoint,执行以下步骤:

  1. 如果 codePoint队列末尾,则返回完成

  2. 如果 codePoint 是一个ASCII 码点,则返回一个值为 codePoint 的字节。

  3. 如果 codePoint 是 U+E5E5,则返回带 codePoint错误

    gb18030 索引将 0xA3 0xA0 映射到 U+3000 表意空格,而不是 U+E5E5, 以兼容已部署的内容。因此它不能往返。

  4. 如果is GBK为 true 且 codePoint 是 U+20AC (€),则返回字节 0x80。

  5. 如果下表中有某行的第一列是 codePoint,则返回该行第二列中列出的两个字节:

    码点 字节
    U+E78D 0xA6 0xD9
    U+E78E 0xA6 0xDA
    U+E78F 0xA6 0xDB
    U+E790 0xA6 0xDC
    U+E791 0xA6 0xDD
    U+E792 0xA6 0xDE
    U+E793 0xA6 0xDF
    U+E794 0xA6 0xEC
    U+E795 0xA6 0xED
    U+E796 0xA6 0xF3
    U+E81E 0xFE 0x59
    U+E826 0xFE 0x61
    U+E82B 0xFE 0x66
    U+E82C 0xFE 0x67
    U+E832 0xFE 0x6D
    U+E843 0xFE 0x7E
    U+E854 0xFE 0x90
    U+E864 0xFE 0xA0

    这个不对称的编码器表保留了与 GB18030-2005 标准的兼容性。另请参见gb18030 范围索引处的解释。

  6. pointergb18030 索引codePoint 对应的索引指针

  7. 如果 pointer 不为 null:

    1. leadingpointer / 190 + 0x81。

    2. trailingpointer % 190。

    3. 如果 trailing 小于 0x3F,则令 offset 为 0x40, 否则为 0x41。

    4. 返回两个字节,其值分别为 leadingtrailing + offset

  8. 如果is GBK为 true,则返回带 codePoint错误

  9. pointer 设为 codePoint 对应的gb18030 范围索引指针

  10. byte1pointer / (10 × 126 × 10)。

  11. pointer 设为 pointer % (10 × 126 × 10)。

  12. byte2pointer / (10 × 126)。

  13. pointer 设为 pointer % (10 × 126)。

  14. byte3pointer / 10。

  15. byte4pointer % 10。

  16. 返回四个字节,其值分别为 byte1 + 0x81、 byte2 + 0x30、byte3 + 0x81、 byte4 + 0x30。

11. 旧式多字节繁体中文编码

11.1. Big5

11.1.1. Big5 解码器

Big5解码器有一个关联的 Big5 前导字节,它是一个字节,初始值为 0x00。

Big5解码器处理程序,给定 ioQueuebyte,执行以下步骤:

  1. 如果 byte队列末尾Big5 前导字节不为 0x00,则将 Big5 前导字节设为 0x00 并返回错误

  2. 如果 byte队列末尾Big5 前导字节为 0x00,则返回 完成

  3. 如果Big5 前导字节不为 0x00:

    1. leadingBig5 前导字节

    2. Big5 前导字节设为 0x00。

    3. pointer 为 null。

    4. 如果 byte 小于 0x7F,则令 offset 为 0x40;否则为 0x62。

    5. 如果 byte 在 0x40 到 0x7E(含)或 0xA1 到 0xFE(含)的范围内, 则将 pointer 设为 (leading − 0x81) × 157 + (byteoffset)。

    6. 如果下表中存在第一列为 pointer 的行,则返回其第二列中列出的两个码点(第三列无关):

      指针 码点 备注
      1133 U+00CA U+0304 Ê̄ (带扬抑符和长音符的拉丁大写字母 E)
      1135 U+00CA U+030C Ê̌ (带扬抑符和抑扬符的拉丁大写字母 E)
      1164 U+00EA U+0304 ê̄ (带扬抑符和长音符的拉丁小写字母 e)
      1166 U+00EA U+030C ê̌ (带扬抑符和抑扬符的拉丁小写字母 e)

      由于索引仅限于 单个码点,因此对这些指针使用此表。

    7. 如果 pointer 为 null,则令 codePoint 为 null;否则为Big5 索引pointer 对应的 索引码点

    8. 如果 codePoint 不为 null,则返回一个值为 codePoint 的码点。

    9. 如果 byte 是一个ASCII 字节,则将 byte 恢复ioQueue

    10. 返回错误

  4. 如果 byte 是一个ASCII 字节,则返回一个值为 byte 的码点。

  5. 如果 byte 在 0x81 到 0xFE(含)的范围内,则将 Big5 前导字节设为 byte 并返回继续

  6. 返回错误

11.1.2. Big5 编码器

Big5编码器处理程序,给定 unusedcodePoint,执行以下步骤:

  1. 如果 codePoint队列末尾,则返回完成

  2. 如果 codePoint 是一个ASCII 码点,则返回一个值为 codePoint 的字节。

  3. pointercodePoint 对应的Big5 索引指针

  4. 如果 pointer 为 null,则返回带 codePoint错误

  5. leadingpointer / 157 + 0x81。

  6. trailingpointer % 157。

  7. 如果 trailing 小于 0x3F,则令 offset 为 0x40, 否则为 0x62。

  8. 返回两个字节,其值分别为 leadingtrailing + offset

12. 旧式多字节日文编码

12.1. EUC-JP

12.1.1. EUC-JP 解码器

EUC-JP解码器有一个关联的:

EUC-JP jis0212
一个布尔值,初始为 false。
EUC-JP 前导字节
一个字节,初始为 0x00。

EUC-JP解码器处理程序,给定 ioQueuebyte,执行以下步骤:

  1. 如果 byte队列末尾EUC-JP 前导字节不为 0x00,则将 EUC-JP 前导字节设为 0x00 并返回错误

  2. 如果 byte队列末尾EUC-JP 前导字节为 0x00,则返回 完成

  3. 如果EUC-JP 前导字节为 0x8E 且 byte 在 0xA1 到 0xDF(含)的范围内,则将EUC-JP 前导字节设为 0x00 并返回一个值为 0xFF61 − 0xA1 + byte 的码点。

  4. 如果EUC-JP 前导字节为 0x8F 且 byte 在 0xA1 到 0xFE(含)的范围内,则将EUC-JP jis0212 设为 true,将EUC-JP 前导字节设为 byte, 并返回继续

  5. 如果EUC-JP 前导字节不为 0x00:

    1. leadingEUC-JP 前导字节

    2. EUC-JP 前导字节设为 0x00。

    3. codePoint 为 null。

    4. 如果 leadingbyte 都在 0xA1 到 0xFE(含)的范围内,则 如果EUC-JP jis0212为 false,则将 codePoint 设为jis0208 索引中 (leading − 0xA1) × 94 + byte − 0xA1 对应的索引码点;否则设为jis0212 索引中对应的码点。

    5. EUC-JP jis0212 设为 false。

    6. 如果 codePoint 不为 null,则返回一个值为 codePoint 的码点。

    7. 如果 byte 是一个ASCII 字节,则将 byte 恢复ioQueue

    8. 返回错误

  6. 如果 byte 是一个ASCII 字节,则返回一个值为 byte 的码点。

  7. 如果 byte 是 0x8E、0x8F 或在 0xA1 到 0xFE(含)的范围内,则将 EUC-JP 前导字节设为 byte 并返回继续

  8. 返回错误

12.1.2. EUC-JP 编码器

EUC-JP编码器处理程序,给定 unusedcodePoint,执行以下步骤:

  1. 如果 codePoint队列末尾,则返回完成

  2. 如果 codePoint 是一个ASCII 码点,则返回一个值为 codePoint 的字节。

  3. 如果 codePoint 是 U+00A5 (¥),则返回字节 0x5C。

  4. 如果 codePoint 是 U+203E (‾),则返回字节 0x7E。

  5. 如果 codePoint 在 U+FF61 (。) 到 U+FF9F (゚)(含)的范围内,则返回两个 字节,其值分别为 0x8E 和 codePoint − 0xFF61 + 0xA1。

  6. 如果 codePoint 是 U+2212 (−),则将其设为 U+FF0D (-)。

  7. pointerjis0208 索引codePoint 对应的索引指针

    如果 pointer 不为 null,则由于 jis0208 索引索引指针 操作的性质,它将小于 8836。

  8. 如果 pointer 为 null,则返回带 codePoint错误

  9. leadingpointer / 94 + 0xA1。

  10. trailingpointer % 94 + 0xA1。

  11. 返回两个字节,其值分别为 leadingtrailing

12.2. ISO-2022-JP

12.2.1. ISO-2022-JP 解码器

ISO-2022-JP解码器有一个关联的:

ISO-2022-JP 解码器状态
一个状态,初始为ASCII
ISO-2022-JP 解码器输出状态
一个状态,初始为ASCII
ISO-2022-JP 前导字节
一个字节,初始为 0x00。
ISO-2022-JP 输出标志
一个布尔值,初始为 false。

ISO-2022-JP解码器处理程序,给定 ioQueuebyte,根据 ISO-2022-JP 解码器状态执行以下步骤:

ASCII

根据 byte

0x1B

ISO-2022-JP 解码器状态设为 转义开始并返回 继续

0x00 到 0x7F,不包括 0x0E、0x0F 和 0x1B

ISO-2022-JP 输出标志设为 false 并返回一个值为 byte 的码点。

队列末尾

返回完成

其他情况

ISO-2022-JP 输出标志设为 false 并返回错误

罗马字

根据 byte

0x1B

ISO-2022-JP 解码器状态设为 转义开始并返回 继续

0x5C

ISO-2022-JP 输出标志设为 false 并返回码点 U+00A5 (¥)。

0x7E

ISO-2022-JP 输出标志设为 false 并返回码点 U+203E (‾)。

0x00 到 0x7F,不包括 0x0E、0x0F、0x1B、0x5C 和 0x7E

ISO-2022-JP 输出标志设为 false 并返回一个值为 byte 的码点。

队列末尾

返回完成

其他情况

ISO-2022-JP 输出标志设为 false 并返回错误

片假名

根据 byte

0x1B

ISO-2022-JP 解码器状态设为 转义开始并返回 继续

0x21 到 0x5F

ISO-2022-JP 输出标志设为 false 并返回一个值为 0xFF61 − 0x21 + byte 的码点。

队列末尾

返回完成

其他情况

ISO-2022-JP 输出标志设为 false 并返回错误

前导字节

根据 byte

0x1B

ISO-2022-JP 解码器状态设为 转义开始并返回 继续

0x21 到 0x7E

ISO-2022-JP 输出标志设为 false,将ISO-2022-JP 前导字节设为 byte, 将ISO-2022-JP 解码器状态设为尾随字节, 并返回继续

队列末尾

返回完成

其他情况

ISO-2022-JP 输出标志设为 false 并返回错误

尾随字节

根据 byte

0x1B

ISO-2022-JP 解码器状态设为 转义开始并返回错误

0x21 到 0x7E
  1. ISO-2022-JP 解码器状态设为 前导字节

  2. pointer 为 (ISO-2022-JP 前导字节 − 0x21) × 94 + byte − 0x21。

  3. codePointjis0208 索引pointer 对应的 索引码点

  4. 如果 codePoint 为 null,则返回错误

  5. 返回一个值为 codePoint 的码点。

队列末尾

ISO-2022-JP 解码器状态设为 前导字节并返回错误

其他情况

ISO-2022-JP 解码器状态设为 前导字节并返回 错误

转义开始
  1. 如果 byte 是 0x24 或 0x28,则将 ISO-2022-JP 前导字节设为 byte,将ISO-2022-JP 解码器状态设为 转义,并返回继续

  2. 如果 byte 不是队列末尾,则将 byte 恢复ioQueue

  3. ISO-2022-JP 输出标志设为 false,将ISO-2022-JP 解码器状态设为 ISO-2022-JP 解码器输出状态,并返回错误

转义
  1. leadingISO-2022-JP 前导字节并设 ISO-2022-JP 前导字节为 0x00。

  2. state 为 null。

  3. 如果 leading 是 0x28 且 byte 是 0x42,则将 state 设为ASCII

  4. 如果 leading 是 0x28 且 byte 是 0x4A,则将 state 设为罗马字

  5. 如果 leading 是 0x28 且 byte 是 0x49,则将 state 设为片假名

  6. 如果 leading 是 0x24 且 byte 是 0x40 或 0x42, 则将 state 设为前导字节

  7. 如果 state 不为 null:

    1. ISO-2022-JP 解码器状态ISO-2022-JP 解码器输出状态设为 state

    2. outputISO-2022-JP 输出标志的值。

    3. ISO-2022-JP 输出标志设为 true。

    4. 如果 output 为 false,则返回继续; 否则返回错误

  8. 如果 byte队列末尾,则将 leading 恢复ioQueue;否则,将 « leading, byte » 恢复ioQueue

  9. ISO-2022-JP 输出标志设为 false, 将ISO-2022-JP 解码器状态设为ISO-2022-JP 解码器输出状态 并返回错误

12.2.2. ISO-2022-JP 编码器

ISO-2022-JP 编码器是唯一一个当多个输出连接起来并通过相应的解码器运行时可能导致错误编码器

编码 U+00A5 (¥) 会得到 0x1B 0x28 0x4A 0x5C 0x1B 0x28 0x42。执行两次,连接结果,然后解码会得到 U+00A5 U+FFFD U+00A5。

ISO-2022-JP编码器有一个关联的 ISO-2022-JP 编码器状态,可以是ASCII罗马字jis0208,初始为 ASCII

ISO-2022-JP编码器处理程序,给定 ioQueuecodePoint,执行以下步骤:

  1. 如果 codePoint队列末尾ISO-2022-JP 编码器状态不为 ASCII,则将ISO-2022-JP 编码器状态设为 ASCII 并返回三个字节 0x1B 0x28 0x42。

  2. 如果 codePoint队列末尾ISO-2022-JP 编码器状态ASCII,则返回完成

  3. 如果ISO-2022-JP 编码器状态ASCII罗马字,且 codePoint 为 U+000E、U+000F 或 U+001B,则返回带 U+FFFD () 的错误

    这里返回 U+FFFD () 而不是 codePoint 是为了防止攻击。

  4. 如果ISO-2022-JP 编码器状态ASCIIcodePoint 是一个ASCII 码点,则返回一个值为 codePoint 的字节。

  5. 如果ISO-2022-JP 编码器状态罗马字codePoint 是一个ASCII 码点(不包括 U+005C (\) 和 U+007E (~)),或者是 U+00A5 (¥) 或 U+203E (‾):

    1. 如果 codePoint 是一个ASCII 码点,则返回一个值为 codePoint 的字节。

    2. 如果 codePoint 是 U+00A5 (¥),则返回字节 0x5C。

    3. 如果 codePoint 是 U+203E (‾),则返回字节 0x7E。

  6. 如果 codePoint 是一个ASCII 码点,且ISO-2022-JP 编码器状态不为ASCII,则将 codePoint 恢复ioQueue,将ISO-2022-JP 编码器状态设为 ASCII,并返回三个字节 0x1B 0x28 0x42。

  7. 如果 codePoint 是 U+00A5 (¥) 或 U+203E (‾),且 ISO-2022-JP 编码器状态不为罗马字,则将 codePoint 恢复ioQueue, 将ISO-2022-JP 编码器状态设为 罗马字,并返回三个字节 0x1B 0x28 0x4A。

  8. 如果 codePoint 是 U+2212 (−),则将其设为 U+FF0D (-)。

  9. 如果 codePoint 在 U+FF61 (。) 到 U+FF9F (゚)(含)的范围内,则将其设为 ISO-2022-JP 片假名索引codePoint − 0xFF61 对应的索引码点

  10. pointerjis0208 索引codePoint 对应的索引指针

    如果 pointer 不为 null,则由于 jis0208 索引索引指针 操作的性质,它将小于 8836。

  11. 如果 pointer 为 null:

    1. 如果ISO-2022-JP 编码器状态jis0208, 则将 codePoint 恢复ioQueue,将 ISO-2022-JP 编码器状态设为ASCII,并返回三个 字节 0x1B 0x28 0x42。

    2. 返回带 codePoint错误

  12. 如果ISO-2022-JP 编码器状态不为jis0208, 则将 codePoint 恢复ioQueue, 将 ISO-2022-JP 编码器状态设为jis0208,并返回 三个字节 0x1B 0x24 0x42。

  13. leadingpointer / 94 + 0x21。

  14. trailingpointer % 94 + 0x21。

  15. 返回两个字节,其值分别为 leadingtrailing

12.3. Shift_JIS

12.3.1. Shift_JIS 解码器

Shift_JIS解码器有一个关联的 Shift_JIS 前导字节,它是一个字节,初始值为 0x00。

Shift_JIS解码器处理程序,给定 ioQueuebyte,执行以下步骤:

  1. 如果 byte队列末尾Shift_JIS 前导字节不为 0x00,则将 Shift_JIS 前导字节设为 0x00 并返回错误

  2. 如果 byte队列末尾Shift_JIS 前导字节为 0x00,则返回 完成

  3. 如果Shift_JIS 前导字节不为 0x00:

    1. leadingShift_JIS 前导字节

    2. Shift_JIS 前导字节设为 0x00。

    3. pointer 为 null。

    4. 如果 byte 小于 0x7F,则令 offset 为 0x40;否则为 0x41。

    5. 如果 leading 小于 0xA0,则令 leadingOffset 为 0x81;否则为 0xC1。

    6. 如果 byte 在 0x40 到 0x7E(含)或 0x80 到 0xFC(含)的范围内, 则将 pointer 设为 (leadingleadingOffset) × 188 + byteoffset

    7. 如果 pointer 在 8836 到 10715(含)的范围内,则返回一个值为 0xE000 − 8836 + pointer 的码点。

      这是来自 Windows 的可互操作的旧式传统,称为 EUDC。

    8. 如果 pointer 为 null,则令 codePoint 为 null;否则为jis0208 索引pointer 对应的 索引码点

    9. 如果 codePoint 不为 null,则返回一个值为 codePoint 的码点。

    10. 如果 byte 是一个ASCII 字节,则将 byte 恢复ioQueue

    11. 返回错误

  4. 如果 byte 是一个ASCII 字节或 0x80,则返回一个值为 byte 的码点。

  5. 如果 byte 在 0xA1 到 0xDF(含)的范围内,则返回一个值为 0xFF61 − 0xA1 + byte 的码点。

  6. 如果 byte 在 0x81 到 0x9F(含)或 0xE0 到 0xFC(含)的范围内,则 将Shift_JIS 前导字节设为 byte 并返回继续

  7. 返回错误

12.3.2. Shift_JIS 编码器

Shift_JIS编码器处理程序,给定 unusedcodePoint,执行以下步骤:

  1. 如果 codePoint队列末尾,则返回完成

  2. 如果 codePoint 是一个ASCII 码点或 U+0080,则返回一个值为 codePoint 的字节。

  3. 如果 codePoint 是 U+00A5 (¥),则返回字节 0x5C。

  4. 如果 codePoint 是 U+203E (‾),则返回字节 0x7E。

  5. 如果 codePoint 在 U+FF61 (。) 到 U+FF9F (゚)(含)的范围内,则返回一个 值为 codePoint − 0xFF61 + 0xA1 的字节。

  6. 如果 codePoint 是 U+2212 (−),则将其设为 U+FF0D (-)。

  7. pointercodePoint 对应的Shift_JIS 索引指针

  8. 如果 pointer 为 null,则返回带 codePoint错误

  9. leadingpointer / 188。

  10. 如果 leading 小于 0x1F,则令 leadingOffset 为 0x81;否则为 0xC1。

  11. trailingpointer % 188。

  12. 如果 trailing 小于 0x3F,则令 offset 为 0x40;否则为 0x41。

  13. 返回两个字节,其值分别为 leading + leadingOffsettrailing + offset

13. 旧版多字节韩文编码

13.1. EUC-KR

13.1.1. EUC-KR 解码器

EUC-KR解码器有一个关联的 EUC-KR 前导字节,它是一个字节,初始值为 0x00。

EUC-KR解码器处理程序,给定 ioQueuebyte,执行以下步骤:

  1. 如果 byte队列末尾EUC-KR 前导字节不为 0x00,则将 EUC-KR 前导字节设为 0x00 并返回错误

  2. 如果 byte队列末尾EUC-KR 前导字节为 0x00,则返回 完成

  3. 如果EUC-KR 前导字节不为 0x00:

    1. leadingEUC-KR 前导字节

    2. EUC-KR 前导字节设为 0x00。

    3. pointer 为 null。

    4. 如果 byte 在 0x41 到 0xFE(含)的范围内,则将 pointer 设为 (leading − 0x81) × 190 + (byte − 0x41)。

    5. 如果 pointer 为 null,则令 codePoint 为 null;否则为EUC-KR 索引pointer 对应的 索引码点

    6. 如果 codePoint 不为 null,则返回一个值为 codePoint 的码点。

    7. 如果 byte 是一个ASCII 字节,则将 byte 恢复ioQueue

    8. 返回错误

  4. 如果 byte 是一个ASCII 字节,则返回一个值为 byte 的码点。

  5. 如果 byte 在 0x81 到 0xFE(含)的范围内,则将EUC-KR 前导字节设为 byte 并返回继续

  6. 返回错误

13.1.2. EUC-KR 编码器

EUC-KR编码器处理程序,给定 unusedcodePoint,执行以下步骤:

  1. 如果 codePoint队列末尾,则返回完成

  2. 如果 codePoint 是一个ASCII 码点,则返回一个值为 codePoint 的字节。

  3. pointerEUC-KR 索引codePoint 对应的索引指针

  4. 如果 pointer 为 null,则返回带 codePoint错误

  5. leadingpointer / 190 + 0x81。

  6. trailingpointer % 190 + 0x41。

  7. 返回两个字节,其值分别为 leadingtrailing

14. 旧式杂项编码

14.1. replacement

replacement 编码的存在是为了防止滥用服务器与客户端支持的 编码不一致造成的某些攻击。

14.1.1. replacement 解码器

replacement解码器有一个关联的 replacement error returned,它是一个布尔值,初始为 false。

replacement解码器处理程序,给定 unusedbyte,执行以下步骤:

  1. 如果 byte队列末尾,则返回完成

  2. 如果 replacement error returned 为 false,则将 replacement error returned 设为 true,并返回错误

  3. 返回完成

14.2. UTF-16BE/LE 的通用基础设施

UTF-16BE/LEUTF-16BEUTF-16LE

14.2.1. 共享 UTF-16 解码器

字节顺序标记优先于标签,因为在实际内容中它被发现更为准确。因此它不是共享 UTF-16 解码器算法的一部分,而属于解码算法。

共享 UTF-16 解码器有一个关联的:

UTF-16 前导字节
为空或一个字节,初始为 null。
UTF-16 前导代理项
为空或前导代理项,初始为 null。
是否 UTF-16BE 解码器
布尔值,初始为 false。

共享 UTF-16 解码器处理程序,给定 ioQueuebyte,执行以下步骤:

  1. 如果 byte队列末尾,且 UTF-16 前导字节UTF-16 前导代理项非空,则将 UTF-16 前导字节UTF-16 前导代理项设为 null,并返回错误

  2. 如果 byte队列末尾,且UTF-16 前导字节UTF-16 前导代理项均为空,则返回完成

  3. 如果UTF-16 前导字节为空,则将UTF-16 前导字节设为 byte,并返回继续

  4. codeUnit 为以下结果之一:

    是否 UTF-16BE 解码器为 true

    (UTF-16 前导字节 << 8) + byte

    是否 UTF-16BE 解码器为 false

    (byte << 8) + UTF-16 前导字节

  5. UTF-16 前导字节设为 null。

  6. 如果UTF-16 前导代理项非空:

    1. leadingSurrogateUTF-16 前导代理项

    2. UTF-16 前导代理项设为 null。

    3. 如果 codeUnit尾随代理项,则返回由代理项组成的标量值,参数为 leadingSurrogatecodeUnit

    4. byte1codeUnit >> 8。

    5. byte2codeUnit & 0x00FF。

    6. 是否 UTF-16BE 解码器为 true,则 bytes 为 [byte1, byte2],否则为 [byte2, byte1]。

    7. 恢复 bytesioQueue 并返回错误

  7. 如果 codeUnit前导代理项,则将UTF-16 前导代理项设为 codeUnit 并返回继续

  8. 如果 codeUnit尾随代理项,则返回错误

  9. 返回码点 codeUnit

14.3. UTF-16BE

14.3.1. UTF-16BE 解码器

UTF-16BE解码器共享 UTF-16 解码器,其 是否 UTF-16BE 解码器 设为 true。

14.4. UTF-16LE

"utf-16" 是 UTF-16LE标签,用于兼容已部署的内容。

14.4.1. UTF-16LE 解码器

UTF-16LE解码器共享 UTF-16 解码器

14.5. x-user-defined

虽然技术上这是单字节编码,但它被单独定义,因为它可以算法化实现。

14.5.1. x-user-defined 解码器

x-user-defined解码器处理程序,给定 unusedbyte,执行以下步骤:

  1. 如果 byte队列末尾,则返回完成

  2. 如果 byte 是一个ASCII 字节,则返回一个值为 byte 的码点。

  3. 返回一个值为 0xF780 + byte − 0x80 的码点。

14.5.2. x-user-defined 编码器

x-user-defined编码器处理程序,给定 unusedcodePoint,执行以下步骤:

  1. 如果 codePoint队列末尾,则返回完成

  2. 如果 codePoint 是一个ASCII 码点,则返回一个值为 codePoint 的字节。

  3. 如果 codePoint 在 U+F780 到 U+F7FF(含)的范围内,则返回一个值为 codePoint − 0xF780 + 0x80 的字节。

  4. 返回带 codePoint错误

15. 浏览器 UI

建议浏览器不要启用覆盖资源编码的选项。如果此功能仍然存在,浏览器不应将 UTF-16BE/LE 作为选项提供,因为上述安全问题。若资源已用 UTF-16BE/LE 解码,浏览器也应该禁用该功能。

实现注意事项

对于本标准中的编码,其解码器可以用如下方式实现,无需支持具有任意I/O 队列和任意恢复

  1. 能够反读当前字节。

  2. gb18030(一个 ASCII 字节)和 ISO-2022-JP(0x24 或 0x28)提供单字节缓冲区。

    对于 gb18030,当 gb18030 third 不为 0x00 时遇到非法字节,可以将 gb18030 second 移入单字节缓冲区,作为下一个字节返回,并将 gb18030 third 作为新的 gb18030 first,在单字节缓冲区被返回并清空后检查其是否不为 0x00。因为 gb18030 的第一个字节和第三个字节的取值范围是相同的,所以这是可行的。

ISO-2022-JP 编码器需要 ISO-2022-JP 编码器状态 作为额外状态,但除此之外,本标准中其他编码编码器不需要额外状态或缓冲区。

致谢

多年来,许多人帮助提升了编码的互操作性,从而推动了本标准的目标。同样,许多人也帮助本标准成为今天的样子。

在此,衷心感谢 Adam Rice, Alan Chaney, Alexander Shtuchkin, Allen Wirfs-Brock, Andreu Botella, Aneesh Agrawal, Arkadiusz Michalski, Asmus Freytag, Ben Noordhuis, Bnaya Peretz, Boris Zbarsky, Bruno Haible, Cameron McCormack, Charles McCathieNeville, Christopher Foo, CodifierNL, David Carlisle, Domenic Denicola, Dominique Hazaël-Massieux, Doug Ewell, Erik van der Poel, 譚永鋒 (Frank Yung-Fong Tang), Glenn Maynard, Gordon P. Hemsley, Henri Sivonen, Ian Hickson, J. King, James Graham, Jeffrey Yasskin, John Tamplin, Joshua Bell, 村井純 (Jun Murai), 신정식 (Jungshik Shin), Jxck, 강 성훈 (Kang Seonghoon), 川幡太一 (Kawabata Taichi), Ken Lunde, Ken Whistler, Kenneth Russell, 田村健人 (Kent Tamura), Leif Halvard Silli, Luke Wagner, Maciej Hirsz, Makoto Kato, Mark Callow, Mark Crispin, Mark Davis, Martin Dürst, Masatoshi Kimura, Mattias Buelens, Ms2ger, Nigel Megitt, Nigel Tao, Norbert Lindenberg, Øistein E. Andersen, Peter Krefting, Philip Jägenstedt, Philip Taylor, Richard Ishida, Robbert Broersma, Robert Mustacchi, Ryan Dahl, Sam Sneddon, Shawn Steele, Simon Montagu, Simon Pieters, Simon Sapin, Stephen Checkoway, 寺田健 (Takeshi Terada), Vyacheslav Matva, Wolf Lammen,以及 成瀬ゆい (Yui Naruse) 的卓越贡献。

本标准由 Anne van Kesteren (Apple, [email protected]) 编写。 API 章节最初由 Joshua Bell (Google) 编写。

知识产权声明

Copyright © WHATWG (Apple, Google, Mozilla, Microsoft)。本作品采用 知识共享署名 4.0 国际许可协议 (CC BY 4.0) 许可。若其中部分内容被纳入源代码,则该部分在源代码中改为采用 BSD 3-Clause License 许可。

这是 Living Standard 版本。如需专利审查版本,请参见 Living Standard Review Draft

索引

本规范定义的术语

引用定义的术语

参考文献

规范性引用

[ECMASCRIPT]
ECMAScript 语言规范。URL:https://tc39.es/ecma262/multipage/
[HTML]
Anne van Kesteren 等。HTML 标准。 Living Standard。URL:https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren;Domenic Denicola。Infra 标准。Living Standard。URL:https://infra.spec.whatwg.org/
[STREAMS]
Adam Rice 等。Streams 标准。Living Standard。URL:https://streams.spec.whatwg.org/
[UNICODE]
Unicode 标准。URL:https://www.unicode.org/versions/latest/
[WEBIDL]
Edgar Chen;Timothy Gu。Web IDL 标准。Living Standard。URL:https://webidl.spec.whatwg.org/

参考性引用

[ISO646]
信息技术 — 信息交换用 ISO 7 位编码字符集。1991年12月。已发布。URL:https://www.iso.org/standard/4777.html
[ISO8859-1]
信息技术 — 8位单字节编码图形字符集 — 第1部分:拉丁字母1号。1998年4月。已发布。URL:https://www.iso.org/standard/28245.html
[URL]
Anne van Kesteren。URL 标准。Living Standard。 URL:https://url.spec.whatwg.org/
[XML]
Tim Bray 等。可扩展标记语言 (XML) 1.0(第五版)。2008年11月26日。REC。URL:https://www.w3.org/TR/xml/

IDL 索引

interface mixin TextDecoderCommon {
  readonly attribute DOMString encoding;
  readonly attribute boolean fatal;
  readonly attribute boolean ignoreBOM;
};

dictionary TextDecoderOptions {
  boolean fatal = false;
  boolean ignoreBOM = false;
};

dictionary TextDecodeOptions {
  boolean stream = false;
};

[Exposed=*]
interface TextDecoder {
  constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options = {});

  USVString decode(optional AllowSharedBufferSource input, optional TextDecodeOptions options = {});
};
TextDecoder includes TextDecoderCommon;

interface mixin TextEncoderCommon {
  readonly attribute DOMString encoding;
};

dictionary TextEncoderEncodeIntoResult {
  unsigned long long read;
  unsigned long long written;
};

[Exposed=*]
interface TextEncoder {
  constructor();

  [NewObject] Uint8Array encode(optional USVString input = "");
  TextEncoderEncodeIntoResult encodeInto(USVString source, [AllowShared] Uint8Array destination);
};
TextEncoder includes TextEncoderCommon;

[Exposed=*]
interface TextDecoderStream {
  constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options = {});
};
TextDecoderStream includes TextDecoderCommon;
TextDecoderStream includes GenericTransformStream;

[Exposed=*]
interface TextEncoderStream {
  constructor();
};
TextEncoderStream includes TextEncoderCommon;
TextEncoderStream includes GenericTransformStream;

MDN

TextDecoder/TextDecoder

In all current engines.

Firefox19+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js11.0.0+
MDN

TextDecoder/decode

In all current engines.

Firefox19+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js11.0.0+
MDN

TextDecoder/encoding

In all current engines.

Firefox19+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js8.3.0+
MDN

TextDecoder/fatal

In all current engines.

Firefox36+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js8.3.0+
MDN

TextDecoder/ignoreBOM

In all current engines.

Firefox63+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js8.3.0+
MDN

TextDecoder

In all current engines.

Firefox19+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js11.0.0+
MDN

TextDecoderStream/TextDecoderStream

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js16.6.0+
MDN

TextDecoderStream/encoding

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js16.6.0+
MDN

TextDecoderStream/fatal

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js16.6.0+
MDN

TextDecoderStream/ignoreBOM

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js16.6.0+
MDN

TextDecoderStream

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+
MDN

TextEncoder/TextEncoder

In all current engines.

Firefox18+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js11.0.0+
MDN

TextEncoder/encode

In all current engines.

Firefox18+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js8.3.0+
MDN

TextEncoder/encodeInto

In all current engines.

Firefox66+Safari14.1+Chrome74+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile50+
Node.js12.11.0+
MDN

TextEncoder/encoding

In all current engines.

Firefox18+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js8.3.0+

TextEncoderStream/encoding

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js16.6.0+
MDN

TextEncoder

In all current engines.

Firefox18+Safari10.1+Chrome38+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js11.0.0+
MDN

TextEncoderStream/TextEncoderStream

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js16.6.0+
MDN

TextEncoderStream

In all current engines.

Firefox105+Safari14.1+Chrome71+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+