目的
-
標準仕様における定型的な記述の重複を排除します。
-
標準仕様間の規約・用語・データ構造の統一を図ります。
-
複数の標準仕様で用いられるが適切な場所がない概念の受け皿となります。
-
曖昧になりがちな概念を明確にし、分かりやすく読みやすいアルゴリズム記述の助けとなります。
追加の目的についての提案も歓迎します。
1. 利用方法
この標準をXというタイトルの文書で利用するには、以下のように記述します。
X は インフラ に依存する。 [Infra]
また、曖昧さを避けるため、すべての用語の相互参照を強く推奨します。
2. 規約
2.1. 適合性
すべてのアサーション、図、例、および注記は非規範的であり、明示的に非規範的と記載されたセクションも同様です。それ以外はすべて規範的です。
キーワード "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", "OPTIONAL" は RFC 2119 で記載されている通りに解釈されます。 [RFC2119]
これらのキーワードは小文字で書かれても同等の意味を持ち、非規範的な内容には使用できません。
これは、読みやすさやRFC 8174以前の多くの文書における長年の慣習を考慮した結果、意図的な違反としてRFC 8174に反していることに注意してください。 [RFC8174]
上記の内容は本標準だけでなく、本標準を利用する文書にも適用されます。本標準を利用する文書では "must", "must not", "should", "may" に限定し、小文字で用いることがより読みやすいと一般に考えられるため推奨します。
非規範的な内容では "strongly encouraged", "strongly discouraged", "encouraged", "discouraged", "can", "cannot", "could", "could not", "might", "might not" を代わりに用いることができます。
2.2. 他の仕様への準拠
一般に、仕様はさまざまな他の仕様と連携し依存しています。しかし残念ながら、要件が衝突し、他の仕様の要件に違反する必要が生じる場合があります。このような場合、インフラ現行標準を利用する文書では、その逸脱を意図的な違反として明記し、理由も記載してください。
前のセクション § 2.1 適合性 では 意図的な違反(RFC 8174に対するもの)がインフラによって記載されています。
2.3. 用語
「または(or)」という語は、包摂的(両方も可)の場合(例:「幅または高さが0の場合」)は「両方も含む」の意味であり、排他的な場合は明示的に「両方は不可」と記されます。
ユーザーエージェントとは、ユーザーに代わって動作するソフトウェア エンティティであり、 例えば Web コンテンツを取得してレンダリングし、エンドユーザーがそれと対話できるようにする。 Infra 標準を使用する仕様では、ユーザーエージェントは一般に、その仕様を実装するクライアント ソフトウェア のインスタンスである。クライアントソフトウェア自体は実装と呼ばれる。 人は、日常生活でさまざまな ユーザー エージェントを利用できる。これには、 実装を設定して、 一度に複数の ユーザーエージェントとして動作させることも含まれる。例えば、 複数のプロファイルを使用したり、 実装のプライベートブラウジングモードを使用したりする場合である。
何かが実装依存とされている場合、その詳細は実装依存の対象となる実装に委ねられます。そうした記載がない場合は逆に、本標準を利用するドキュメントでは実装は定められたルールに従わなければなりません。
input に U+000A (LF) コードポイントを挿入する際、各行が最大 width コードポイントとなるよう、実装依存の方法で処理します。この要件における「行」は input の開始、終了、および U+000A (LF) で区切られます。
2.4. プライバシーに関する懸念
インフラ現行標準を利用する文書で定義される一部の機能は、ユーザーの利便性と引き換えに、ある程度のプライバシーを犠牲にする場合があります。
一般的に、インターネットの構造上、ユーザーはIPアドレスによって識別されます。しかし、ユーザーがデバイスやネットワークを移動するとIPアドレスも変わり、逆にNATやプロキシ、共有PCにより、一つのIPアドレスから複数のユーザーのアクセスが発生する場合もあります。また、オニオンルーティング等の技術でリクエストの発信元を匿名化し、一つのユーザーのリクエストがネットワーク上の様々な場所から発信されているように見せることも可能です。[RFC791]
しかし、ユーザーのリクエストを結び付ける手段はIPアドレスだけではありません。たとえばCookieはまさにこの目的で設計されており、ウェブのセッション機能の多くはこれを基盤としています(アカウントでのログインなど)。より広くは、キャッシュや共有状態(HSTS、HTTPキャッシュ、コネクションのグルーピング、ストレージAPIなど)も悪用されうることを想定すべきです。[COOKIES] [RFC6797] [STORAGE]
さらに微妙な手法もあります。ユーザーのシステム固有の特徴を収集し、十分な情報が集まれば、個々のユーザーのブラウザの「デジタルフィンガープリント」を計算できます。これはIPアドレス以上に、同じユーザーからのリクエストを特定できる場合があります。
このようなリクエストのグルーピングは、特に複数サイト間で悪意のある目的に利用される恐れがあります。たとえば、ある人が経路検索した住所(自宅住所)と、参加しているフォーラムサイトから推測される政治的傾向を突き合わせて、その人の選挙での投票を妨害するなどです。
このような悪用が極めて深刻になり得るため、ユーザーエージェントの実装者や仕様策定者は、指紋付けや追跡に使われうる情報の漏洩を最小限に抑えるよう強く推奨します。
しかし、冒頭でも述べた通り、指紋付けや追跡に悪用されうるAPIの公開は大きな利便性をもたらす場合もあり、全ての情報漏洩を防ぐだけでは十分とは言えません。たとえば、特定のIDでサイトにログインして投稿するには、同一ユーザーからのリクエストであることを識別できる必要があります。さらに、キャンバス上でテキストに枠を描画するなど、テキストの幅を取得する機能も、フォント情報の推定によるユーザーのグルーピングにつながる可能性があります。
インフラ現行標準を利用する文書で定義される機能のうち、トラッキングベクトルとして利用され得るものは、この段落のように明示されます。
同様の目的で利用されうる他のプラットフォーム機能には、次のようなものがあります。
- ユーザーエージェントがサポートする機能の正確なリスト
- スクリプトにおける再帰の最大許可スタック深度
- ユーザー環境を記述する機能
- ユーザーのタイムゾーン
- HTTPリクエストヘッダ
3. アルゴリズム
3.1. 適合性
アルゴリズムや、アルゴリズムの一部として命令形で記述された要件(例:「先頭の空白を除去する」「falseを返す」など)は、そのアルゴリズムや手順の導入部で用いられているキーワード(例:"must")の意味で解釈されます。キーワードがない場合は "must" が暗黙的に適用されます。
例えば、仕様で次のように記載されていたとします:
オレンジを食べるには、ユーザーは次を行う:
- オレンジの皮をむく。
- オレンジを一房ずつ分ける。
- オレンジの房を食べる。
これは次の記述と同等です:
オレンジを食べるには:
- ユーザーはオレンジの皮をむかなければならない。
- ユーザーはオレンジを一房ずつ分けなければならない。
- ユーザーはオレンジの房を食べなければならない。
ここでのキーワードは "must" です。
上記の例を修正して、アルゴリズムの導入部が単に "To eat an orange:" であっても、"must" が暗黙的に適用されるため、意味は同じです。
アルゴリズムや個別の手順として記述された適合要件は、最終的な結果が同等である限り、どのような方法で実装しても構いません(特に、アルゴリズムは理解しやすいことを目的としており、性能を意図したものではありません)。
性能はユーザーの体感やコンピュータアーキテクチャ、入力の種類など、さまざまな要因に左右されるため取り扱いが難しいものです。例えば、JavaScriptエンジンは標準化された単一のアルゴリズムに対して複数の実装経路を持ち、速度やメモリ消費の最適化を図っています。すべての実装経路を標準化するのは現実的でなく、長期的な観点からも単一のアルゴリズムを標準化する方が望ましいため、性能面は各実装間の競争分野に委ねられます。
3.2. アルゴリズム入力の制限回避
インフラ現行標準を利用する文書では、アルゴリズムの入力に関して、そのサイズやリソース使用量などに明確な制限を設けないことが一般的です。これによりユーザーエージェント間の競争を促し、将来の計算需要も妨げません。
ただし、ユーザーエージェントは、他に制限がない場合でも
実装依存の制限を課すことができます。例えば、サービス拒否攻撃を防ぐため、メモリ不足を防ぐため、またはプラットフォーム固有の制約を回避するためなどです。
グローバルなリソース制限は、リソース枯渇攻撃の一形態として副次的なチャネルとなり得ます。攻撃者が被害者のアプリケーションがグローバル制限に達したかを観測できるためです。また、制限がユーザーエージェント固有の場合は、フィンガープリントの手段ともなり得ます(基盤となるハードウェア固有の場合など)。
メモリ上にビットマップを作成できるAPIは、任意の大きさ、またはJavaScriptの
Number.MAX_SAFE_INTEGER のような大きな上限まで許可すると仕様できるかもしれません。しかし、実装では巨大なメモリ割当てを避けるために、実装依存(つまり仕様としては未規定)の上限を設けても構いません。
あるプログラミング言語で最大コールスタックサイズが仕様として定められていない場合でも、実装では実用上の理由から上限を設けても構いません。
コードが特定の制限に依存する場合もあり、相互運用性のために上限を定義することが有用な場合もあります。将来的にも問題がなければ、それを受け入れることで、より多くのユーザーエージェントでコードが動作するようになります。
また、実装依存の上限に下限を設け、すべての実装が一定の最小サイズの入力を扱えるようにすることも有用です。
3.3. 宣言
アルゴリズム名は通常動詞句ですが、標準や読者がより慣用的に参照できるよう、その存在自体を強調する名前が付けられる場合もあります。
後者の例としては、「属性変更手順」「内部モジュールスクリプトグラフ取得手順」「オーバーロード解決アルゴリズム」などがあります。
アルゴリズムは、次の形式で名前・パラメーター・戻り値の型を宣言します:
[アルゴリズム名]するには、[型1] [parameter1]、[型2] [parameter2] … を与えて、次の手順を実行する。戻り値は[戻り値の型]である。
(動詞句でないアルゴリズム名では「[アルゴリズム名]を実行するには…」とします。より複雑なパラメーター宣言形式については§ 3.4 パラメーターも参照してください。)
バイト列 bytes を与えて 素晴らしいフォーマットをパースするには、次の手順を実行する。戻り値は 文字列 または null である。
値を返さないアルゴリズムでは、より短い形式を用います。返り値が手順から明らかな場合もこの短縮形を用いて構いません:
[アルゴリズム名]するには、[型1] [parameter1]、[型2] [parameter2] … を与えて:
バイト列 bytes を与えて 素晴らしいフォーマットをパースするには:
非常に短いアルゴリズムは、1文で宣言・記述できます:
バイト列 bytes を与えて 素晴らしいフォーマットをパースするには、bytesの等価デコードをASCII大文字化した結果を返す。
型はアルゴリズム宣言に含めるべきですが、パラメーター名が十分に明確な場合や文脈から明らかな場合は省略できます(たとえば、単に他のアルゴリズムのラッパーである場合など)。
クラシックスクリプトを読み込むには、urlを与えて、内部スクリプト読み込みアルゴリズムをurlと"classic"で実行した結果を返す。
3.4. パラメーター
アルゴリズムのパラメーターは通常、§ 3.3 宣言で説明したように順番に列挙されます。ただし、より複雑な場合もあります。
パラメーターはオプションにでき、その場合は宣言で明記し、必須パラメーターの後に記載します。デフォルト値を与える場合と、アルゴリズム本体で値が与えられたかどうかを判定する場合があります。具体的な記法は以下の通りです:
… オプションの[型] [parameter] …
… オプションの[型] [parameter](既定値 [default value])…
オプションのbooleanパラメーターは必ずデフォルト値を指定し、その値はfalseでなければなりません。
navigateを実行するには、リソースresource、オプションの文字列navigationType、オプションのboolean exceptionsEnabled(既定値false)を与えて:
- …
- navigationType が与えられていれば、それを使って何かを行う。
- …
このようなオプションの位置引数パラメーターを持つアルゴリズムを呼び出す際は、末尾のオプションの引数のみ省略できます。
上記アルゴリズムの呼び出し例:
- navigate to resource。
- navigate to resource with
"
form submission"。 - navigate to resource with
"
form submission" and true。
ただし、2番目の引数を省略して3番目に非デフォルト値を与えることはできません。また、最後の呼び出し例では "true" が「例外有効」であることが分かりづらく、宣言まで戻ってパラメーターを数える必要があります。これを解決する方法は後述します。
位置引数でなく名前付き引数を使うことで、呼び出し時の明確さと柔軟性が向上します。こうしたパラメーターは変数と定義の両方としてマークアップし、呼び出し元からリンクします。
navigateを実行するには、リソースresource、オプションの文字列navigationType、オプションのboolean exceptionsEnabled(既定値false)を与えて:
- …
- navigationType が与えられていれば、それを使って何かを行う。
- …
呼び出し例は下記のようになります:
- navigate to resource。
- navigate to resource with navigationType set to
"
form-submission"。 - navigate to resource with exceptionsEnabled set to true。
- navigate to resource with navigationType set to
"
form-submission" and exceptionsEnabled set to true。
アルゴリズム手順内では、引数値はパラメーター宣言へのリンクではなく、単なる変数参照として記載されます。パラメーター宣言へのリンクは呼び出し箇所でのみ行います。
必須の名前付きパラメーターも同様に、変数と定義の両方としてマークアップし、呼び出し元からリンクします。これにより呼び出し時の明確さが向上します。
Boolean型パラメーターは必須・オプションに関わらず名前付きにすることで呼び出し時の明確さが大きく向上します。詳しくはThe Pitfalls of Boolean Trapもご参照ください。
明確さを高める補完的な手法として、関連する値群を構造体にまとめてパラメーターとして渡すことも有効です。特に同じ値群を複数のアルゴリズムで入力として使う場合に適しています。
3.5. 変数
変数は "let" で宣言し、"set" で変更します。
list を新しい リストとする。
isActivationEvent が true で target がアクティベーション動作を持つ場合は target、そうでなければ null を activationTarget とする。
変数は宣言前に使用してはなりません。変数は ブロックスコープ です。1つのアルゴリズム内で同じ変数を複数回宣言してはなりません。
複数代入構文は、変数名を U+0028 LEFT PARENTHESIS および U+0029 RIGHT PARENTHESIS で囲み、各変数名を U+002C (,) で区切ることにより、複数の変数を タプルの 項目に代入するために使用できる。代入される変数の数は、項目の数と異なってはならない。これは タプル内のものとする。
-
statusInstance を status (200, `
OK`) とする。 -
(status, statusMessage) を statusInstance とする。
status と statusMessage への代入は、インデックスまたは名前でタプルの要素にアクセスして2段階で書くこともできます。
3.6. 制御フロー
アルゴリズムの制御フローは、「return」や「throw」要求によって、そのステートメントが属するアルゴリズムを終了させます。「return」は与えられた値(ある場合)を呼び出し元に返します。「throw」は、与えられた値(ある場合)で例外を発生させ、呼び出し元のアルゴリズムも自動的に例外を再スローして終了します。本文で明示すれば、呼び出し元は例外を「catch」して別の処理を実行できます。
3.7. 条件付き中断
ある条件が成立したときに手順の実行を中断したい場合があります。
その場合、特定の条件に達したらその手順を中断する(abort when)と記述します。これは、指定された手順のそれぞれの前に条件を評価し、真なら残りの手順をスキップするステップを挿入して評価することを示します。
このようなアルゴリズムでは、続く手順に「中断時(if aborted)」と注記でき、その場合は直前の中断条件が真になってスキップされた場合に必ず実行されます。
この構文を使う場合、実装は手順の実行中に条件を評価しても、各手順の前後で評価しても、最終的な結果が区別できなければどちらでも構いません。例えば、上記例で result が計算中に変更されなければ、ユーザーエージェントは計算を途中で停止できます。
3.8. 条件文
条件文を持つアルゴリズムでは "if"、"then"、"otherwise" キーワードを使うべきです。
-
value を null とする。
-
input が 文字列 であれば、value に input を設定する。
-
value を返す。
一度 "otherwise" キーワードが使われたら、"then" は省略します。
-
value を null とする。
-
input が 文字列 であれば、value に input を設定する。
-
それ以外の場合、value を failure に設定する。
-
value を返す。
3.9. 反復
条件に達するまで一連の手順を繰り返す方法はいくつかあります。
インフラ現行標準はこれについて(まだ)網羅的ではありません。必要な場合はissueを提出してください。
反復の流れは、continue や break 要求で制御できます。 continue は反復内の残りの手順をスキップして次の項目に進みます。次の項目がなければ反復は終了します。break は残りの手順と項目の両方をスキップし、反復を終了します。
example を リスト « 1, 2, 3, 4 » とする。次の記述は operation を1, 2, 3, 4 の順に実行します:
-
For each item of example:
- item に対して operation を実行する。
次の記述は operation を1, 2, 4 に実行し、3はスキップされます。
次の記述は operation を1, 2 に実行し、3と4はスキップされます。
3.10. アサーション
可読性を高めるために、アルゴリズムにアサーション(不変条件の明示)を追加することが有用な場合があります。その場合は「アサート:」に続けて、常に成り立つべき文を記述します。この文が偽になった場合は、インフラ現行標準を利用する文書に問題があることを意味し、報告・対応されるべきです。
アサーションは常に真でなければならないため、実装に影響はありません。
-
x を "
Aperture Science" とする。 -
アサート:x は "
Aperture Science" である。
3.11. 同一性と等価性
値 a が値 b である(または値 b と 同一である)とは、それらが同じ値である場合をいう。プリミティブデータ型の値の場合、これはそれらが 同じ内容を持つことを意味する。たとえば、2 つの 文字列は、 同じシーケンス の コード単位からなる場合に同一である。その他のデータ 型、たとえば リスト、 マップ、および 構造体の値の場合、これはそれらが同じインスタンスであることを意味する。そのような 2 つの 値は、 別々に作成された場合、その内容が 同じであっても、互いに同一となることはない。
データ型には 等価性があり、 これはそのデータ型の 2 つの値を受け取り、 真偽値を返すアルゴリズムである。 別途定義されていない限り、データ型の 等価性は、2 つの値が互いに 同一である場合は true を返し、それ以外の場合は false を返す。この標準では、リスト、 マップ、および タプルについて異なる 等価性を定義する。
値 a が値 b と 等しい(または値 b に 等しい)とは、 a が b であるか、または a と b が同じデータ型であり、そのデータ型の 等価性が a と b を与えられたとき true を返す場合をいう。
キー値は、キー と 値からなる タプルの例である。 (キーは 文字列)であり、値は 値(数値の リスト)である。
-
original をキー値 ("
x", « 1, 2, 3, 4 ») とする。 -
alsoOriginal を original とする。
-
copy をキー値 ("
x", « 1, 2, 3, 4 ») とする。 -
表明: original は copy と 等しい。これは、それらの キーが 互いに 同一であり、それらの値 が 等しいためである。
リスト、マップ、および タプルの 等価性は、 それらの内容を 等しいを用いて比較するため、 直接または 間接的に自身を含む値の比較は、無限ループになる可能性があるため避けるべきである。
最後のステップは決して終了しない。a と b は互いに 同一ではなく、 同じ サイズを持つため、それらが 等しいかどうかを決定するには、 a[0] が b[0] と 等しいかどうかを 決定する必要があり、これは同じ問いである。なぜなら a[0] は a であり、b[0] は b であるからである。
4. プリミティブデータ型
4.1. Null
null値は値が存在しないことを示すために用いられます。これはJavaScriptのnull値と相互に扱うことができます。[ECMA-262]
4.2. Boolean
Booleanは true または false のいずれかです。
4.3. 数値
数値は複雑です。詳細は issue #87 を参照してください。将来的には型や数学演算についてのガイダンスも追加したいと考えています。ご協力歓迎します!
8ビット符号なし整数は、0から255(0〜28 − 1)までの整数です(両端含む)。
16ビット符号なし整数は、0から65535(0〜216 − 1)までの整数です(両端含む)。
32ビット符号なし整数は、0から4294967295(0〜232 − 1)までの整数です(両端含む)。
64ビット符号なし整数は、0から18446744073709551615(0〜264 − 1)までの整数です(両端含む)。
128ビット符号なし整数は、0から340282366920938463463374607431768211455(0〜2128 − 1)までの整数です(両端含む)。
IPv6アドレスは128ビット符号なし整数です。
8ビット符号付き整数は、−128から127(−27〜27−1)までの整数です(両端含む)。
16ビット符号付き整数は、−32768から32767(−215〜215−1)までの整数です(両端含む)。
32ビット符号付き整数は、−2147483648から2147483647(−231〜231−1)までの整数です(両端含む)。
64ビット符号付き整数は、−9223372036854775808から9223372036854775807(−263〜263−1)までの整数です(両端含む)。
2 つの数が互いに 同一であるのは、それらが 同じ数学的値である場合である。
4.4. バイト
バイトは8ビットの並びであり、"0x"に2つのASCII大文字16進数字を続けて表記します。値の範囲は0x00〜0xFFです。バイトの値はその内部の数値です。
ASCIIバイトは、0x00(NUL)から0x7F(DEL)までのバイトです。0x28, 0x29 以外のASCIIバイトは、ASCII format for Network Interchangeの Standard Code セクションで定められた表記(括弧内)で続けて示すことができます。[RFC20]
0x28 の場合「(left parenthesis)」、0x29 の場合「(right parenthesis)」と続けます。
0x49 (I) を UTF-8デコードすると、符号位置 U+0049 (I) になります。
4.5. バイト列
ある バイト列とは、 バイトの列であり、 空白で区切られた バイトの列として表される。0x20 (SP) から 0x7E (~) までの範囲(両端を含む)のバイトからなるバイト列は、 引用符の代わりにバッククォートを使用することで、文字列として記述することもでき、 実際の 文字列との混同を避けられる。
文字列から バイト列を得るには、UTF-8 エンコードを Encoding から使用することが推奨される。まれな状況では 同型エンコードが必要になることもある。 [ENCODING]
バイト列を バイト小文字化するには、各 バイトのうち、 0x41 (A) から 0x5A (Z) までの範囲(両端を含む)にあるものを 0x20 増加させる。
バイト列を バイト大文字化するには、各 バイトのうち、 0x61 (a) から 0x7A (z) までの範囲(両端を含む)にあるものから 0x20 を減算する。
バイト列 A が バイト列 B に バイトの大文字・小文字を区別しない一致であるとは、 Aを バイト小文字化したものが Bを バイト小文字化したものと 同じであることをいう。
2 つの バイト列が互いに 同一であるのは、それらが 同じ バイトの列から構成される場合である。
バイト列 potentialPrefix が バイト列 input の 接頭辞であるのは、 次の手順が true を返す場合である。
-
i を 0 とする。
-
次の処理を true の間繰り返す。
「input が potentialPrefix で始まる」は、 「potentialPrefix は input の 接頭辞である」と 同義語として使用できる。
バイト列 a が バイト列 b より バイト順で小さいのは、次の手順が true を返す場合である。
-
b が a の 接頭辞である場合、false を返す。
-
a が b の 接頭辞である場合、true を返す。
-
a の n 番目の バイトが b の n 番目のバイトと異なるような最小のインデックス n とする。(どちらのバイト列ももう一方の接頭辞ではないため、そのような インデックスは必ず存在する。)
-
a の n 番目のバイトが b の n 番目のバイトより小さい場合、true を返す。
-
false を返す。
バイト 列 inputを 同型 デコードするには、 文字列を返す。その コードポイント長は inputの 長さと等しく、 その コードポイントは、inputの バイトの 値と同じ 値を 同じ順序で持つ。
4.6. 符号位置
ある コードポイントは Unicode コードポイントであり、 "U+" に続く 4~6 桁の ASCII 大文字 16 進数字で表され、その範囲は U+0000 から U+10FFFF まで(両端を含む)である。コードポイントの 値は、その 基となる数値である。
コードポイントの後には、その 名前、U+0028 または U+0029 でない場合は括弧で囲んだ表示形、 あるいはその両方を付けることができる。Infra 標準を使用する文書では、 コードポイントが 表示できない場合、または U+0028 か U+0029 の場合は名前を後に付け、それ以外の場合は、 読みやすさのため、括弧で囲んだ表示形を後に付けることが推奨される。
コードポイントの名前は Unicodeで定義され、 ASCII 大文字で表記される。 [UNICODE]
🤔 と表示される コードポイントは U+1F914 と表記される。
その コード ポイントを指す場合、追加の文脈を示すために "U+1F914 (🤔)" と表現することがある。 文書では "U+1F914 THINKING FACE (🤔)" も使用できるが、これはやや冗長である。
コードポイントのうち、明確に 表示することが難しいもの(U+000A など)は "U+000A LF" と表記できる。U+0029 は "U+0029 RIGHT PARENTHESIS" と表記できる。表示可能ではあるが、これにより対応しない括弧を避けられる。
コードポイントは、 文字と呼ばれることもあり、特定の 文脈では "U+" ではなく "0x" が接頭辞として付けられる。
ある 上位サロゲートとは、 コードポイントのうち、 U+D800 から U+DBFF までの範囲(両端を含む)にあるものである。
ある 下位サロゲート とは、コードポイントのうち、 U+DC00 から U+DFFF までの範囲(両端を含む)にあるものである。
ある サロゲートとは、上位サロゲートまたは 下位サロゲートである。
ある スカラー値とは、コードポイントのうち、サロゲートでないものである。
ある 非文字とは、コードポイントのうち、 U+FDD0 から U+FDEF までの範囲 (両端を含む)にあるもの、または U+FFFE、U+FFFF、U+1FFFE、U+1FFFF、U+2FFFE、U+2FFFF、U+3FFFE、U+3FFFF、U+4FFFE、 U+4FFFF, U+5FFFE, U+5FFFF, U+6FFFE, U+6FFFF, U+7FFFE, U+7FFFF, U+8FFFE, U+8FFFF, U+9FFFE, U+9FFFF, U+AFFFE, U+AFFFF, U+BFFFE, U+BFFFF, U+CFFFE, U+CFFFF, U+DFFFE, U+DFFFF, U+EFFFE, U+EFFFF, U+FFFFE, U+FFFFF, U+10FFFE, or U+10FFFF.
ある ASCII コードポイントとは、 U+0000 NULL から U+007F DELETE までの範囲(両端を含む)にあるコードポイントである。
ある ASCII タブまたは 改行とは、 U+0009 TAB、U+000A LF、または U+000D CR である。
ASCII 空白文字とは、 U+0009 TAB、U+000A LF、U+000C FF、U+000D CR、または U+0020 SPACE である。
"Whitespace" は不可算名詞である。
XML、JSON、および HTTP 仕様の一部では、U+000C FF を 空白文字の定義から除外している:
新しい機能には、Infra の ASCII 空白文字の定義を使用することが望ましい。ただし、仕様が XML/JSON/HTTP のみを扱う場合は除く。
ある C0 制御文字とは、コードポイントのうち、U+0000 NULL から U+001F INFORMATION SEPARATOR ONE までの範囲(両端を含む)にあるものである。
ある C0 制御文字または空白 とは、 C0 制御文字または U+0020 SPACE である。
ある 制御文字とは、C0 制御文字、または コードポイントのうち、 U+007F DELETE から U+009F APPLICATION PROGRAM COMMAND までの範囲(両端を含む)にあるものである。
ある ASCII 数字とは、コードポイントのうち、U+0030 (0) から U+0039 (9) までの範囲 (両端を含む)にあるものである。
ある ASCII 大文字 16 進 数字とは、ASCII 数字 または コードポイントのうち、 U+0041 (A) から U+0046 (F) までの範囲(両端を含む)にあるものである。
ある ASCII 小文字 16 進 数字とは、ASCII 数字 または コードポイントのうち、 U+0061 (a) から U+0066 (f) までの範囲(両端を含む)にあるものである。
ある ASCII 16 進数字とは、 ASCII 大文字 16 進 数字または ASCII 小文字 16 進 数字である。
ある ASCII 大文字英字とは、 コードポイントのうち、U+0041 (A) から U+005A (Z) までの範囲(両端を含む)にあるものである。
ある ASCII 小文字英字とは、 コードポイントのうち、U+0061 (a) から U+007A (z) までの範囲(両端を含む)にあるものである。
ある ASCII 英字とは、ASCII 大文字英字または ASCII 小文字英字である。
ある ASCII 英数字 とは、ASCII 数字または ASCII 英字である。
4.7. 文字列
ある 文字列とは、 16 ビット符号なし 整数の列であり、コード単位とも呼ばれる。 文字列は、JavaScript 文字列とも呼ばれる。 文字列は、二重引用符と 等幅フォントで表記される。
これは Unicode が「コード単位」を定義する方法とは異なる。特に これは Unicode が Unicode 16 ビット文字列について定義するものだけを指す。[UNICODE]
文字列は、 JavaScript 仕様の String 型の節で定義される変換に従って、 コードポイントを含むものとして解釈することもできる。[ECMA-262]
この変換処理はサロゲートペアを対応する スカラー値に変換し、残りの サロゲートを対応する コードポイントに対応付け、 実質的にそのまま残す。
コード単位 0xD83D、0xDCA9、および 0xD800 からなる 文字列を、コード ポイントを含むものとして解釈すると、 コードポイント U+1F4A9 と U+D800 からなる。
文字列の 長さ とは、それに含まれる コード単位の数である。
文字列の コードポイント長とは、それに含まれる コードポイントの数である。
含むことのできる コードポイントに追加の 制限がある 文字列を示すため、 この仕様では ASCII 文字列、同型 文字列、および スカラー値 文字列を定義する。これらを使用すると仕様の明確さが向上する。
ASCII 文字列とは、その 文字列の コードポイントがすべて ASCII コードポイントであるものをいう。
同型文字列とは、 文字列であって、その コードポイントがすべて U+0000 NULL から U+00FF (ÿ) までの範囲(両端を含む)にあるものをいう。
スカラー値文字列 とは、その 文字列の コードポイントがすべて スカラー値であるものをいう。
スカラー値文字列は、あらゆる種類の I/O や、 UTF-8 エンコードが関係するその他の種類の 操作に有用である。
文字列を スカラー値文字列に 変換するには、その中の サロゲートを U+FFFD (�) に置換する。
置換されるサロゲートはサロゲートペアの一部では決してない。これは、文字列を コード ポイントを含むものとして解釈する処理によって、サロゲートペアが スカラー値に変換済みだからである。
スカラー値 文字列は、常に暗黙に 文字列として使用できる。これは、すべての スカラー値 文字列が 文字列だからである。一方、 文字列を 暗黙に スカラー値文字列として使用できるのは、それが サロゲートを含まないことが分かっている場合だけであり、 そうでなければ 変換を行うことになる。
実装が実際に 文字列と スカラー値 文字列をどのように表現することになるかに応じて、明示的な変換を行わなければならない可能性が高い。 性能とメモリ上の 理由から、実装が 文字列だけでも複数の実装を持つことはごく一般的である。
文字列 a が である、すなわち 同一である 文字列 b とは、それらが同じ コード単位の列からなる場合をいう。
特に明記されている場合を除き、すべての文字列比較では であるを使用する。
この種類の 文字列 比較は、以前 HTML では「大文字・小文字を区別する」 比較として知られていた。互いに 同一であると比較される文字列は、 大文字と小文字(UPPER と lower case など)の違いだけでなく、正規化形式や結合文字の順序など、その他のコード ポイント符号化の選択にも影響される。Unicode に従って視覚的、さらには正準的に等価である 2 つの文字列であっても、 互いに 同一ではない場合がある。[HTML] [UNICODE]
文字列 potentialPrefix が、 文字列 input の コード単位接頭辞であるのは、次の 手順が true を返す場合である。
-
i を 0 とする。
-
次の処理を true の間繰り返す。
コード 単位が用いられていることが文脈から明らかな場合、たとえば、 文字列の一方が U+0020 SPACE から U+007E (~) までの範囲の文字だけを含むリテラルである場合、 「input が potentialPrefix で始まる」は、 「potentialPrefix は input の コード単位接頭辞である」の同義語として使用できる。
値が
不明な場合は、明示的にするのがよい。
targetString は userInput の コード単位接頭辞である。しかし
リテラルの場合は、より平易な言い方を使用できる。userInput は
"!" で始まる。
文字列 potentialSuffix が、 文字列 input の コード単位接尾辞であるのは、次の 手順が true を返す場合である。
-
i を 1 とする。
-
次の処理を true の間繰り返す。
-
potentialSuffixIndex を potentialSuffix の 長さ − i とする。
-
inputIndex を input の 長さ − i とする。
-
potentialSuffixIndex が 0 未満である場合、true を返す。
-
inputIndex が 0 未満である場合、false を返す。
-
potentialSuffixCodeUnit を potentialSuffix の potentialSuffixIndex 番目の コード単位とする。
-
inputCodeUnit を input の inputIndex 番目の コード単位とする。
-
potentialSuffixCodeUnit が inputCodeUnit でない場合、false を返す。
-
i を i + 1 に設定する。
-
コード 単位が用いられていることが文脈から明らかな場合、たとえば、 文字列の一方が U+0020 SPACE から U+007E (~) までの範囲の文字だけを含むリテラルである場合、 「input が potentialSuffix で終わる」は、 「potentialSuffix は input の コード単位接尾辞である」の同義語として使用できる。
値が
不明な場合は、明示的にするのがよい。
targetString は domain の コード単位接尾辞である。しかし
リテラルの場合は、より平易な言い方を使用できる。domain は "." で終わる。
文字列 a が、 文字列 b より コード単位順で小さいのは、次の手順が true を返す場合である。
-
b が a の コード単位接頭辞である場合、false を返す。
-
a が b の コード単位接頭辞である場合、true を返す。
-
a の n 番目の コード単位が b の n 番目のコード単位と異なるような最小のインデックス n とする。(どちらの文字列ももう一方の接頭辞ではないため、そのような インデックスは必ず存在する。)
-
a の n 番目のコード単位が b の n 番目のコード単位より 小さい場合、true を返す。
-
false を返す。
これは JavaScript の < 演算子、および文字列の配列に対する
sort()
メソッドで使用される順序と一致する。この順序付けでは各
文字列の 16 ビットコード単位を比較し、非常に効率的で、一貫性があり、決定的なソート順を生成する。その結果得られる
順序は、特にサロゲートペアで表される
コードポイントについて、特定のアルファベット順や辞書式順序とは一致しない。[ECMA-262]
たとえば、コードポイント U+FF5E FULLWIDTH TILDE (~) は明らかにコードポイント U+1F600 (😀) より小さいが、チルダは 1 つの コード単位 0xFF5E からなる一方、スマイリーは 2 つのコード単位 0xD83D と 0XDE00 からなるため、スマイリーのほうが チルダより コード単位順で小さい。
文字列 string 内で、 start から長さ length の コード単位 部分文字列は、 次のように決定される。
-
表明: start と length は非負である。
-
result を空文字列とする。
-
各 i について、 範囲 start から start + length まで(終端を含まない)の i ごとに、string の i 番目の コード単位を result に付加する。
-
result を返す。
文字列 string 内で start から end までの コード単位部分文字列とは、 string 内で start から長さ end − start の コード 単位部分文字列である。
文字列 string の start から末尾までの コード単位部分文字列とは、 string 内で start から string の 長さまでの コード単位部分文字列である。
"Hello world" 内の 1 から
長さ 3 の コード単位部分文字列は
"ell" である。これは、
1 から 4 までの コード単位部分文字列とも表現できる。
これらのアルゴリズムに与えられる数値は、コード単位自体のインデックスではなく、 コード単位の間の位置と考えるのが最もよい。返される部分文字列は その後、これらの位置の間にあるコード単位によって構成される。これにより、たとえば空文字列内の 0 から 0 までの コード単位部分文字列が 空文字列である理由を説明できる。空文字列内にはインデックス 0 のコード単位が存在しないにもかかわらずである。
文字列 string 内の start から長さ length の コードポイント 部分文字列は、次のように決定される。
-
表明: start と length は非負である。
-
result を空文字列とする。
-
各 i について、 範囲 start から start + length まで(終端を含まない)の i ごとに、string の i 番目の コードポイントを result に付加する。
-
result を返す。
文字列 string 内で start から end までの コードポイント部分文字列とは、 string 内で start から長さ end − start の コードポイント 部分文字列である。
文字列 string の start から末尾までの コードポイント部分文字列 とは、 string 内で start から string の コードポイント長までの コードポイント部分文字列である。
一般に、開発者が指定した位置または
長さを与えられた場合には、コード
単位部分文字列が使用される。これは JavaScript における文字列のインデックス付けがそのように機能するためである。たとえば、
CharacterData
クラスのメソッドを参照されたい。[DOM]
それ以外の場合は、コード
ポイント部分文字列のほうが適している可能性が高い。たとえば、
"👽" 内の 0 から長さ 1 の コードポイント
部分文字列は "👽" であるが、
"👽" 内の 0 から長さ 1 の コード
単位部分文字列は、単一の サロゲート U+D83B
を含む
文字列である。
同型文字列 inputを 同型 エンコードするには、バイト列を返す。その 長さは inputの コード ポイント長と等しく、その バイトは、 inputの コードポイントの 値と同じ 値を、 同じ順序で持つ。
文字列を ASCII 小文字化するには、 文字列内のすべての ASCII 大文字を、 ASCII 小文字の対応する コードポイントに置換する。
文字列を ASCII 大文字化するには、 文字列内のすべての ASCII 小文字を、 ASCII 大文字の対応する コードポイントに置換する。
文字列 A が、 文字列 B に ASCII の大文字・小文字を区別しない一致であるとは、 Aを ASCII 小文字化したものが Bを ASCII 小文字化したものと 同じであることをいう。
ASCII 文字列 inputを ASCII エンコードするには、 inputの 同型 エンコーディングを返す。
同型エンコードと UTF-8 エンコードは、 inputに対して同じ バイト 列を返す。
バイト列 inputを ASCII デコードするには、次の手順を実行する。
文字列から 改行を除去するには、 文字列から U+000A LF および U+000D CR の コードポイントをすべて削除する。
文字列内の 改行を正規化するには、 U+000D CR U+000A LF コードポイントの各ペアを 1 つの U+000A LF コードポイントに置換し、その後、 残っているすべての U+000D CR コードポイントを U+000A LF コードポイントに置換する。
文字列から 先頭および末尾の ASCII 空白文字を除去するには、文字列の 先頭または末尾にあるすべての ASCII 空白文字を削除する。
文字列内の ASCII 空白文字を除去して 折り畳むには、文字列内にある、1 つ以上連続する ASCII 空白文字である コード ポイントの各列を 1 つの U+0020 SPACE コード ポイントに置換し、その後、その文字列から先頭および末尾の ASCII 空白文字を削除する。
文字列 input から条件 condition を満たす コードポイントの列を収集するには、呼び出し元アルゴリズム内での input 内の位置を追跡する 位置変数 position が与えられたものとして、次を行う。
-
result を空の 文字列とする。
-
position が input の末尾を越した位置を指しておらず、かつ input 内の position にある コードポイントが 条件 condition を満たす間、次を行う。
-
その コード ポイントを result の末尾に付加する。
-
position を 1 進める。
-
-
result を返す。
このアルゴリズムは、収集した コードポイントを返すことに加えて、呼び出し元アルゴリズムの 位置 変数も更新する。
ASCII 空白文字を読み飛ばすには、文字列 input 内で、 位置 変数 position が与えられたとき、コードポイントの列を収集することにより、 position が与えられた input から ASCII 空白文字である コードポイントを収集する。収集された コードポイントは使用されないが、 position は引き続き更新される。
文字列 input を、特定の区切り文字である コードポイント delimiter で 厳密に分割するには、次を行う。
-
position を input の 位置変数とし、初期状態では input の先頭を指すようにする。
-
token を、position が与えられた input から delimiter と等しくない コードポイントの列を収集した結果とする。
-
token を tokens に 付加する。
-
position が input の末尾を越えていない間、次を行う。
-
position を 1 進める。
-
token を、position が与えられた input から delimiter と等しくない コードポイントの列を収集した結果とする。
-
token を tokens に 付加する。
-
tokens を返す。
このアルゴリズムは「厳密な」分割であり、下記の一般的に使用される ASCII 空白文字によるものや コンマによるものとは異なる。後者はいずれも、 間に挟まれた ASCII 空白文字に関するさまざまな点でより寛容である。
文字列 input を ASCII 空白文字で分割するには、次を行う。
-
position を input の 位置変数とし、初期状態では input の先頭を指すようにする。
-
position が与えられた input 内の ASCII 空白文字を読み飛ばす。
-
position が input の末尾を越えていない間、次を行う。
-
token を、position が与えられた input から ASCII 空白文字ではない コードポイントの列を収集した結果とする。
-
token を tokens に 付加する。
-
position が与えられた input 内の ASCII 空白文字を読み飛ばす。
-
-
tokens を返す。
文字列 input をコンマで分割するには、次を行う。
-
position を input の 位置変数とし、初期状態では input の先頭を指すようにする。
-
position が input の末尾を越えていない間、次を行う。
-
token を、position が与えられた input から U+002C (,) ではない コードポイントの列を収集した結果とする。
token は空文字列である可能性がある。
- token から先頭および末尾の ASCII 空白文字を除去する。
-
token を tokens に 付加する。
-
position が input の末尾を越えていない場合、次を行う。
-
-
tokens を返す。
リスト list 内の 文字列を、任意の区切り文字列 separator を使用して 連結するには、 次の手順を実行する。
-
list が 空で ある場合、空文字列を返す。
-
separator が与えられていない場合、separator を空文字列に設定する。
集合 set をシリアライズするには、 U+0020 SPACE を使用した set の 連結を返す。
4.8. 時間
時間は moment(瞬間) 型および duration(期間) 型で表現します。これらを定義したりJavaScriptとやりとりしたりする際は、High Resolution Time § 3 仕様策定者のためのツールの助言に従ってください。[HR-TIME]
4.9. シングルトン
以下の型は、理解を向上させるためにアルゴリズム記述の入出力として使用できます。 これらは、特定のアルゴリズムの流れに与える効果以外には可観測な表現を持ちません。また、“is”による比較のみが可能です。
- allowed
-
ある操作が許可されていることを示します。多くの場合、blockedと対比されて使われます。
- blocked
-
ある操作が許可されていないことを示します。多くの場合、allowedと対比されて使われます。
- failure
-
ある操作が予期通りに進行しなかったことを示します。多くの場合、successと対比、またはより具体的な型と組み合わせて使われます。
- success
-
ある操作が期待どおりに進行したことを示します。多くの場合、failureと対比されて使われます。
5. データ構造
従来、仕様では、その意味論についての共通理解に基づき、仕様レベルの曖昧なデータ 構造をさまざまに扱ってきた。これは概してうまく機能するが、 反復順序や、次のような場合に何が起こるかといった境界事例について曖昧さが生じることがある。 追加しようとする項目を、ある順序付き集合がすでに 含んでいる場合である。また、これにより、 特に多様な表記法や言い回しが生じており、 マップのような、より複雑なデータ構造で顕著である。
この標準は、共通の基盤を確立するため、少数の共通データ構造と、それらを扱うための表記法や言い回し を提供する。
5.1. リスト
リストとは、 有限の順序付きシーケンスからなる仕様上の型であり、 項目で構成される。
表記上の便宜のため、リストを表すリテラル構文を使用できる。これは、 リストを U+00AB («) と U+00BB (») で囲み、その項目を U+002C (,) で区切るものである。 角括弧内にリストのゼロ基点のインデックスを指定することで、インデックス構文を使用できる。 インデックスは範囲外であってはならない。ただし、存在するとともに使用する場合を除く。
exampleをリスト «
"a",
"b", "c", "a" » とする。このとき、example[1] は文字列
"b" である。
表記上の便宜のため、複数の変数を リストの項目に割り当てる複数代入構文を使用できる。これは、代入する変数を U+00AB («) と U+00BB (») で囲み(リストと同様)、各変数名を U+002C (,) で区切るものである。 リストのサイズは、代入される変数の数と同じでなければ ならない。指定された各 変数には、リストの対応するインデックスにある項目の値が 設定される。
リストの内容が完全に制御されていない場合、 例えばユーザー入力から得られたリストの場合、 複数代入構文を使用する 前に、リストのサイズを確認し、期待されるサイズであることを保証するべきである。
-
listのサイズが
3でない場合、失敗を返す。 -
« a, b, c » を list とする。
リストの等価性は、リスト aとbが与えられたとき、aの サイズがbのサイズと同じであり、かつ a[i] が aの各 i について b[i] と等しい場合に 真を返す。ここで i はaのインデックスであり、それ以外の場合は偽を返す。
順序付き集合ではない リストに追加するとは、 指定された項目をリストの末尾に 追加することである。
順序付き集合ではない リスト Aを、リスト Bで拡張するとは、 Bの各 item について反復し、itemを Aに追加することである。
順序付き集合ではない リストに先頭に追加するとは、 指定された項目をリストの先頭に 追加することである。
順序付き集合ではない リスト内で置換するとは、 リスト内の指定された条件に一致するすべての項目を、指定された項目で置き換えることであり、 一致する項目がない場合は何もしない。
上記の定義は、リストが順序付き集合である場合に変更される。 順序付き集合への追加、先頭への追加、および 置換については以下を参照。
リストのインデックスの前に 項目を挿入するとは、 指定されたインデックス − 1 と指定されたインデックスの間に項目を追加することである。 指定されたインデックスが 0 の場合、項目をリストの 先頭に追加する。
リスト « x, y, z, x » からxを削除するとは、 リストからxに等しいすべての項目を削除することである。この時点でリストは « y, z » と等価になる。
リストから
文字列 "a" で始まるすべての項目を
削除するとは、
« "a", "b",
"ab", "ba" » から
項目 "a" と "ab" を削除することである。この時点でリストは «
"b", "ba" » と等価になる。
リストを空にするとは、 そのすべての項目を削除することである。
リストが項目を含むとは、 リストの項目のいずれかが、指定された 項目と等しい場合をいう。また、 リスト listとインデックスindexについて、 "list[index] が存在する" と表現することもできる。
リストの インデックスを取得するには、 0 からリストのサイズまでの範囲(終端を含まない)を返す。
リストを反復するには、 各項目に対して順番に一連の手順を実行し、 次の形式の表現を使用する: "listの各itemについて"。 その後、後続の 文章でitemに対する操作を行う。
リスト listを切り出すには、任意の 整数from(既定値は 0)と任意の整数 to(既定値はlistのサイズ)を指定して、 次の手順を実行する。これらの手順は、 listと同じ種別のリストを返す。
リスト listに重複が あるかどうかを確認するには:
リスト listを複製するとは、 listの切り出し結果を返すことである。
これは「浅い複製」であり、項目自体はいかなる方法でも 複製されない。
originalを順序付き
集合 «
"a", "b", "c" » とする。originalを複製すると、
新しい順序付き集合
cloneが作成される。そのため、clone内で "a" を置換して
"foo" にすると、« "foo", "b", "c" » となるが、
original[0] は依然として文字列
"a" である。
リスト listを逆順にするとは、 同じ種別の新しいリスト reversedを作成し、listの各 itemについて、 itemをreversedの先頭に追加することである。
リスト listを、 小なり比較アルゴリズムlessThanAlgoを使用して昇順にソートするとは、 listと同じ項目を含む新しいリスト sortedを作成し、lessThanAlgoに従って、各項目がその次の項目(存在する場合)より 小さくなるように並べ替えることである。同じ順位になる項目 (つまり、lessThanAlgoが両方向の比較で偽を返す項目)については、 sorted内での相対的な順序はlist内での順序と同じでなければならない。
リスト listを、 小なり比較アルゴリズムlessThanAlgoを使用して降順に ソートするとは、 listと同じ項目を含む新しいリスト sortedを作成し、lessThanAlgoに従って、各項目がその前の項目(存在する場合)より 小さくなるように並べ替えることである。同じ順位になる項目 (つまり、lessThanAlgoが両方向の比較で偽を返す項目)については、 sorted内での相対的な順序はlist内での順序と同じでなければならない。
originalをリスト « (200,
"OK"),
(404, "Not Found"), (null, "OK") » とする。originalをソートする際、
aの 2 番目の項目が
bの 2 番目の項目よりコード単位で小さい場合にaがbより小さいとする。
昇順にソートした結果は « (404,
"Not Found"), (200, "OK"), (null, "OK") » となる。
リスト型は JavaScript 仕様に由来する(そこでは先頭が大文字の Listとして表記される)。参照の便宜のため、 ここではその定義の一部を繰り返し、 リストを操作するための用語を拡充している。 JavaScript が Listを期待する場合は常に、ここで定義したリストを使用できる。これらは同じ型である。 [ECMA-262]
5.1.1. スタック
一部の リストは、スタックとして指定される。スタックは リストであるが、 慣例上、これを操作するには、付加、先頭への付加、または 削除を使用する代わりに、次の操作が使用される。
スタックに プッシュする とは、それに 付加することである。
スタックから ポップする には、スタックが 空でない場合、その最後の 項目を 削除し、 それを返す。それ以外の場合は、何も返さない。
スタックを ピークする には、スタックが 空でない場合、その 最後の 項目を返す。それ以外の場合は、 何も返さない。
スタックは リストではあるが、各項目についてをそれらに使用してはならない。 代わりに、while と pop の組み合わせのほうが適切である。
5.1.2. キュー
一部の リストは、キューとして指定される。キューは リストであるが、 慣例上、これを操作するには、次の操作が使用され、 付加、先頭への付加、または 削除は使用されない。
キューに エンキューするとは、 それに 付加することである。
キューから デキューするとは、削除することである。 キューが 空でない場合、その最初の 項目を削除して返し、 空である場合は 何も返さない。
キューは リストではあるが、各項目についてをそれらに使用してはならない。 代わりに、while と dequeue の組み合わせのほうが適切である。
5.1.3. 集合
一部の リストは、順序付き 集合として指定される。 順序付き集合とは、リストであり、同じ 項目を 2 つ含んではならないという追加の 意味を持つ。ここで同じとは、項目が 等しいことをいう。
Web プラットフォーム上のほぼすべての場合で、順序なし集合ではなく順序付き集合が必要となる。これは、 相互運用性のため、開発者に公開される集合内容の列挙がブラウザー間で一貫している必要があるためである。順序が重要でない場合でも、 順序付き集合を使用する。実装は、順序が観測できないという事実に基づいて最適化できる。
順序付き集合に 付加する には、集合が指定された 項目を 含む場合は何もしない。 それ以外の場合は、通常の リストの 付加操作を行う。
順序付き集合 A を リスト B で 拡張するには、 B の item ごとに、 item を A に 付加する。
順序付き集合の 先頭に付加する には、集合が指定された 項目を 含む場合は何もしない。それ以外の場合は、 通常の リストの 先頭への付加操作を行う。
順序付き集合 set 内で、item と replacement が与えられたときに 置換するには、set が item または replacement を 含む場合、そのいずれかの最初の出現を replacement で置換し、その他のすべての出現を 削除する。
順序付き集合 « "a", "b", "c" » 内で "a" を "c" に 置換すると « "c", "b" » となる。 « "c", "b", "a" » 内でも同様に « "c", "b" » となる。
順序付き集合 set が、別の 順序付き集合 superset の 部分集合である(逆に、superset が set の 上位集合である)とは、 set の item ごとに、 superset が item を 含む場合をいう。
これは、順序付き集合が、それ自身の 部分集合でもあり、 上位集合でもあることを意味する。
集合 A が 集合 B と 順序を無視して等しいとは、A が B の 部分集合であり、かつ A が B の 上位集合である場合をいう。
順序付き集合 « 1, 2 » と « 2, 1 » は 順序を無視して等しいが、 等しくはない。これは、 リストの 等価性では、その 項目の順序が考慮されるためである。
順序付き集合 A と B の 共通部分とは、新しい 順序付き集合 set を作成し、A の item ごとに、 B が item を 含む場合、item を set に 付加した結果である。
順序付き集合 A と B の 和集合とは、 A を set として 複製し、B の item ごとに、 item を set に 付加した結果である。
順序付き集合 A と B の 差集合とは、新しい 順序付き集合 set を作成し、A の item ごとに、 B が item を 含まない場合、 item を set に 付加した結果である。
範囲 n から m まで(両端を含む)は、 m が n 以上である限り、n から m まで(m を含む)のすべての整数を連続する昇順で含む新しい 順序付き 集合を作成する。
範囲 n から m まで(終端を含まない)は、 m が n より大きい限り、n から m − 1 まで(m − 1 を含む)のすべての整数を連続する昇順で含む新しい 順序付き集合 を作成する。m が n と等しい場合は、空の 順序付き集合を作成する。
5.2. マップ
順序付きマップ、または単に「マップ」と呼ばれることもあるものは、 有限個の順序付けられた タプルの列からなる仕様型であり、各タプルは キーと 値からなり、 2 つのキーが 等しくなることはない。このような各タプルを エントリと呼ぶ。
順序付き集合と同様に、デフォルトでは、実装間の 相互運用性のためにマップは順序付けられている必要があるものとする。
順序付きマップを表現するにはリテラル構文を使用でき、順序付きマップを U+00AB («) と U+005B ([) で開始し、U+005D (]) と U+00BB (») で終了し、各 エントリの key と value を U+2192 (→) で区切り、エントリ同士を U+002C (,) で区切る。
次のように、
example を 順序付き
マップ «[
"a" → `x`, "b" → `y` ]» とする。このとき、
example["a"] は バイト列 `x` である。
順序付きマップの 等価性は、順序付きマップ a と b が与えられたとき、 次の場合に true を返す。 a の サイズが b の サイズと同じであり、a の各 エントリが、 同じ位置にある b の エントリの キーおよび 値とそれぞれ 等しい キー と 値を持つ場合であり、 それ以外の場合は false を返す。
エントリの値を取得するには、 順序付きマップ map、指定された キー key、および任意の defaultについて、次を行う。
-
map が key を 含まず、default が与えられている場合、default を返す。
エントリの値を取得することは、 マップの直後にある角括弧内に キーを指定する インデックス構文を使用して表すこともできる。 デフォルト値の後に デフォルト付きという句を付加することで、 デフォルトを指定できる。
map["test"] が
存在する場合、
map["test"] を返す。
example を 順序付きマップ
«[ "a" → "x", "b" → "y" ]» とする。このとき、
example["a"] は example["a"] デフォルト付き
"z" と同じであり、
すなわち "x" である。example["c"] は表明に失敗する。
example["c"] デフォルト付き "z" は "z" である。
エントリの値を設定するには、 順序付きマップに指定された 値を設定するとき、 既存の エントリについて、マップが 指定された キーを持つエントリを 含む場合は、その値を更新し、 そのようなものが存在しない場合は、指定されたキーと値を持つ新しいエントリをマップの末尾に追加する。また、 順序付きマップ map、キー key、および値 valueについて、 「設定する map[key] を value に」と表すこともできる。
エントリを削除するとは、順序付きマップから、 指定された条件に一致するすべての エントリをマップから 削除し、一致するものがない場合は何もしないことである。 条件が特定の キーを持つことである場合は、 次のように表すこともできる。 順序付きマップ map と キー key について、「削除する map[key]」。
順序付きマップを 空にするとは、 マップからすべての エントリを 削除することである。
順序付きマップが 指定されたキーを持つ エントリを含むとは、 その キーが指定されたキーと 等しいエントリが存在する場合をいう。また、 順序付きマップ map とキー key について、「map[key] が 存在する」と表すこともできる。
順序付きマップの キーを取得するには、新しい 順序付き集合を返す。その 項目はそれぞれ、 マップの エントリにある キーである。
順序付きマップの 値を取得するには、 新しい リストを返す。その 項目はそれぞれ、 マップの エントリにある 値である。
順序付きマップの サイズとは、 そのマップに対して キーを 取得するを実行した結果の サイズである。
順序付きマップを 反復処理する、すなわち 各 エントリに対して順番に 一連の手順を実行するには、次の形式の表現を使用する。 「map の key → value ごとに」。その後、 後続の文章で key と value に対して処理を行う。
順序付きマップ mapを 複製するとは、 新しい 順序付きマップ clone を作成し、 map の key → value ごとに、 clone[key] を value に 設定する ことである。
これは「浅い複製」であり、キーと 値 自体はいかなる方法でも複製されない。
original を 順序付き
マップ «[
"a" → «1, 2, 3», "b" → «» ]» とする。originalを 複製すると、
新しい 順序付きマップ clone
が作成され、
clone["a"] を 設定して
値を
«-1, -2, -3» にすると «[ "a" → «-1, -2, -3», "b" → «» ]» となり、
original は変更されない。しかし、clone["b"] に 4 を 付加すると、
clone と original の両方にある対応する 値が変更される。これは両方が
同じ リストを指しているためである。
昇順にソートする とは、小なり アルゴリズム lessThanAlgo を使用して マップ map を、新しい マップ sorted として作成することである。これは map と同じ エントリを含むが、 lessThanAlgo に従って各エントリが後続のエントリ(存在する場合)より小さくなるようにソートされる。同じ順序になるエントリについては 同じ (すなわち、両方向の比較について lessThanAlgo が false を返す場合)、その相対的な順序は sorted 内でも map 内での順序と同じでなければならない。
降順に ソートする とは、小なり アルゴリズム lessThanAlgo を使用して マップ map を、新しい マップ sorted として作成することである。これは map と同じ エントリを含むが、 lessThanAlgo に従って各エントリが先行するエントリ(存在する場合)より小さくなるようにソートされる。同じ順序になるエントリについては 同じ (すなわち、両方向の比較について lessThanAlgo が false を返す場合)、その相対的な順序は sorted 内でも map 内での順序と同じでなければならない。
5.3. 構造体
構造体とは、有限個の 項目からなる仕様型であり、各項目は一意で不変の 名前を持つ。項目は、定義された型の値を保持する。
メールは、構造体の例であり、 ローカル部(文字列)と ホスト(ホスト)からなる。
無意味なアルゴリズムでは、この定義を次のように使用するかもしれない。
- email を、ローカル部が "
hostmaster" であり、ホスト がinfra.exampleであるメールとする。 - …
その定義で別途指定されていない限り、タプルではない 構造体は、それ自身とのみ 等しい。その 等価性は、2 つの構造体が互いに 同一である場合に true を返し、それ以外の場合は false を返す。
構造体 a と b が与えられたとき、項目ごとの等価性は、 a の各 項目が、 同じ 名前を持つ b の 項目と 等しい場合に true を返し、それ以外の場合は false を返す。構造体の定義では、 その 等価性が 項目ごとの等価性であると指定できる。
上記のメールの定義を使用すると、次のようになる。
-
email を、ローカル部が "
hostmaster" であり、ホストがinfra.exampleであるメールとする。 -
sameEmail を email とする。
-
otherEmail を、ローカル部が "
hostmaster" であり、ホストがinfra.exampleであるメールとする。
代わりに、メールの定義でメールの 等価性が 項目ごとの 等価性であると指定されていた場合、email は otherEmail と 等しいことになる。これは、それらのローカル 部が互いに 同一であり、それらの ホストが 等しいためである。
したがって、その定義で 等価性が指定されていない 構造体が 順序付きマップの キーとして、または 順序付き集合の 項目として使用される場合、それとまったく同じ構造体を使用した場合にのみ 再び見つけることができる。それが望ましくない場合は、 その定義で 等価性を、たとえば 項目ごとの等価性として指定する必要がある。
5.3.1. タプル
タプルとは、構造体であり、その 項目には順序がある。表記上の 便宜のため、タプルを表現するためにリテラル構文を使用でき、これは タプルを丸括弧で囲み、その 項目を U+002C (,) で区切る。この 表記を使用するには、名前が 文脈から明らかである必要がある。これは、 最初のインスタンスの前に タプルに付けられた名前を置くことで行える。インデックス構文は、 角括弧内に タプルへのゼロ基準のインデックスを 指定することで使用できる。インデックスは 範囲外であってはならない。
ステータスは、コード( 数値)と テキスト(バイト列)からなる タプルの例である。
ステータスタプルの使用法を示す目的でそれらを操作する無意味なアルゴリズムは、 次のとおりである。
- statusInstance をステータス (200, `
OK`) とする。 - statusInstance を (301, `
FOO BAR`) に設定する。 - statusInstance のコードが 404 である場合、…
最後の手順は「statusInstance[0] が 404 である場合、…」と記述することもできる。これは、 タプルの 名前に明示的な 定義がない場合には、より望ましいことがある。
すべての 構造体が タプルではないのは意図的である。 Infra Standard を使用する文書では、依存先で使用されるリテラル構文を壊すことなく、構造体に新しい 名前を追加できる 柔軟性が必要になる場合がある。その場合、タプルは適切ではない。
タプルの 等価性は、その定義で 別途指定されていない限り、項目ごとの等価性である。
タプルを タプルではない 構造体に変更することは、その定義で指定しない限り、 項目ごとの等価性を持たなくなることも意味する。
6. JSON
この節のアルゴリズムで使用される規約は、JavaScript 仕様のものである。[ECMA-262]
文字列 string が与えられたとき、JSON 文字列を JavaScript 値に解析するには、次を行う。
-
? Call(%JSON.parse%, undefined, « string ») を返す。
バイト列 bytes が与えられたとき、JSON バイトを JavaScript 値に解析するには、次を行う。
-
string を、bytes に対して UTF-8 デコードを実行した結果とする。[ENCODING]
-
string を与えて JSON 文字列を JavaScript 値に解析した結果を返す。
JavaScript 値 value が与えられたとき、JavaScript 値を JSON 文字列にシリアライズするには、次を行う。
-
result を ? Call(%JSON.stringify%, undefined, « value ») とする。
%JSON.stringify% に追加の引数が渡されないため、結果の 文字列に空白文字は挿入されない。
-
result が undefined の場合、
TypeErrorをスローする。これは、value に JSON 表現がない場合、たとえば undefined または関数である場合に 起こり得る。
-
result を返す。
JavaScript 値 value が与えられたとき、JavaScript 値を JSON バイトにシリアライズするには、次を行う。
-
string を、value を与えて JavaScript 値を JSON 文字列にシリアライズした結果とする。
-
string に対して UTF-8 エンコードを実行した結果を返す。[ENCODING]
上記の操作は JavaScript 値を直接操作する。特に、これは 関係するオブジェクトまたは配列が特定の JavaScript レルムに結び付けられることを意味する。標準では、 JSON とレルムに依存しない マップ、 リスト、文字列、ブール値、数値、および null の間で変換するほうが便利なことが多い。
文字列 string が与えられたとき、JSON 文字列を Infra 値に解析するには、次を行う。
-
jsValue を ? Call(%JSON.parse%, undefined, « string ») とする。
-
jsValue を与えて JSON 由来の JavaScript 値を Infra 値に変換した結果を返す。
バイト列 bytes が与えられたとき、JSON バイトを Infra 値に解析するには、次を行う。
-
string を、bytes に対して UTF-8 デコードを実行した結果とする。[ENCODING]
-
string を与えて JSON 文字列を Infra 値に解析した結果を返す。
JavaScript 値 jsValue が与えられたとき、JSON 由来の JavaScript 値を Infra 値に変換するには、次を行う。
-
jsValue が
null であるか、jsValue が Boolean であるか、jsValue が String であるか、または jsValue が Number である場合、 jsValue を返す。 -
IsArray(jsValue) が true の場合、次を行う。
-
result を空の 順序付きマップとする。
-
! jsValue.[[OwnPropertyKeys]]() の key ごとに、次を行う。
-
jsValueAtKey を ! Get(jsValue, key) とする。
-
infraValueAtKey を、jsValueAtKey を与えて JSON 由来の JavaScript 値を Infra 値に変換した結果とする。
-
result[key] を infraValueAtKey に 設定する。
-
-
result を返す。
文字列、 ブール値、数値、null、リスト、または 文字列をキーとする マップ value が与えられたとき、Infra 値を JSON 文字列にシリアライズするには、次を行う。
-
jsValue を、value を与えて Infra 値を JSON 互換の JavaScript 値に変換した結果とする。
-
! Call(%JSON.stringify%, undefined, « jsValue ») を返す。
%JSON.stringify% に追加の引数が渡されないため、結果の 文字列に空白文字は挿入されない。
文字列、 ブール値、数値、null、リスト、または 文字列をキーとする マップ value が与えられたとき、Infra 値を JSON バイトにシリアライズするには、次を行う。
-
string を、value を与えて Infra 値を JSON 文字列にシリアライズした結果とする。
-
string に対して UTF-8 エンコードを実行した結果を返す。[ENCODING]
value が与えられたとき、Infra 値を JSON 互換の JavaScript 値に変換するには、次を行う。
-
value が リストの場合、次を行う。
-
jsValue を ! ArrayCreate(0) とする。
-
i を 0 とする。
-
value の listItem ごとに、次を行う。
-
listItemJSValue を、listItem を与えて Infra 値を JSON 互換の JavaScript 値に変換した結果とする。
-
! CreateDataPropertyOrThrow(jsValue, ! ToString(i), listItemJSValue) を実行する。
-
i を i + 1 に設定する。
-
-
jsValue を返す。
-
-
jsValue を ! OrdinaryObjectCreate(null) とする。
-
value の mapKey → mapValue ごとに、次を行う。
-
mapValueJSValue を、mapValue を与えて Infra 値を JSON 互換の JavaScript 値に変換した結果とする。
-
! CreateDataPropertyOrThrow(jsValue, mapKey, mapValueJSValue) を実行する。
-
jsValue を返す。
仕様で JavaScript 値を直接操作することが適切であることはまれなので、このアルゴリズムを使用する代わりに、 Infra 値を JSON 文字列にシリアライズするか、 Infra 値を JSON バイトにシリアライズする ことを推奨する。Infra 値を JSON 互換の JavaScript 値に変換するを使用する必要があると考える場合は、そのユースケースについて議論するため、 issue を提出してほしい。
7. 許容的base64
許容的base64エンコードは、バイト列 dataが与えられたとき、RFC 4648のセクション4で定義されたbase64アルゴリズムをdataに適用し、その結果を返す。 [RFC4648]
これは許容的base64エンコードと名付けられているが、これは 許容的base64デコードとの対称性のためであり、後者はRFCと異なり 特定の入力に対するエラー処理を定義している。
許容的base64デコードは、文字列dataが与えられたとき、次の手順を実行する:
-
dataからすべてのASCII空白を除去する。
-
もしdataの符号位置長が4で割り切れるなら:
-
もしdataが1個または2個のU+003D(=) 符号位置で終わっていれば、それらをdataから除去する。
-
-
もしdataの符号位置長を4で割った余りが1なら、失敗を返す。
-
もしdataが次のいずれでもない符号位置を含んでいれば:
- U+002B (+)
- U+002F (/)
- ASCII英数字
失敗を返す。
-
outputを空のバイト列とする。
-
bufferを、ビットを追加できる空のバッファとする。
-
positionを、dataの位置変数として、最初はdataの先頭を指すようにする。
-
positionがdataの末尾を越えない間、繰り返す:
-
もしbufferが空でなければ、12ビットまたは18ビットが入っている。 12ビットの場合は最後の4ビットを捨て、残り8ビットを8ビットビッグエンディアン数値とする。 18ビットの場合は最後の2ビットを捨て、残り16ビットを2つの8ビットビッグエンディアン数値とする。 その1つまたは2つの値をバイトとして順にoutputに追加する。
捨てられるビットにより、例えば"
YQ"や"YR"のどちらも`a`を返す。 -
outputを返す。
8. 名前空間
HTML名前空間は
"http://www.w3.org/1999/xhtml" である。
MathML名前空間は
"http://www.w3.org/1998/Math/MathML" である。
SVG名前空間は
"http://www.w3.org/2000/svg" である。
XLink名前空間は
"http://www.w3.org/1999/xlink" である。
XML名前空間は
"http://www.w3.org/XML/1998/namespace" である。
XMLNS名前空間は
"http://www.w3.org/2000/xmlns/" である。
謝辞
次の方々に多大な感謝を捧げます: Addison Phillips, Andreu Botella, Aryeh Gregor, Ben Kelly, Chris Rebert, Daniel Ehrenberg, Dominic Farolino, Gabriel Pivovarov, Ian Hickson, Jakob Ackermann, Jake Archibald, Jeff Hodges, Jeffrey Yasskin, Jungkee Song, Leonid Vasilyev, Maciej Stachowiak, Malika Aubakirova, Martin Thomson, Michael™ Smith, Mike West, Mike Taylor, Ms2ger, Noam Rosenthal, Pavel "Al Arz" Kurochkin, Philip Jägenstedt, Rashaun "Snuggs" Stovall, Sergey Shekyan, Simon Pieters, Tab Atkins, Tobie Langel, triple-underscore, Wolf Lammen, およびXue Fuqiao に心より敬意を表します!
本標準は Anne van Kesteren (Apple, annevk@annevk.nl) と Domenic Denicola (Google, d@domenic.me) によって執筆されています。
知的財産権
Copyright © WHATWG (Apple, Google, Mozilla, Microsoft)。本作業は Creative Commons Attribution 4.0 International License の下でライセンスされています。その一部がソースコードに組み込まれている場合、ソースコード内の該当部分は BSD 3-Clause License の下でライセンスされます。
これは現行標準です。 特許レビュー版に関心がある方は 現行標準レビュー草案をご覧ください。