Web IDL

現行標準 — 最終更新

参加方法:
GitHub whatwg/webidl(新しい課題、未解決の課題)
Matrixでチャット
コミット履歴:
GitHub whatwg/webidl/commits
このコミット時点のスナップショット
テスト:
web-platform-tests webidl/ (進行中の作業)
翻訳 (参考):
日本語
简体中文
한국어

概要

この標準は、Webブラウザーで実装されることを目的としたインターフェースを記述するためのインターフェース定義言語であるWeb IDLを定義します。

1. はじめに

この節は参考情報です。

この現行標準は、Webブラウザーで実装されることを目的としたインターフェースを記述するためのインターフェース定義言語、Web IDLを定義します。Web IDLは、Webプラットフォームにおける一般的なスクリプトオブジェクトの振る舞いをより容易に指定できるようにする、さまざまな機能を備えたIDLのバリエーションです。Web IDLで記述されたインターフェースがJavaScript実行環境内の構造にどのように対応するかも、ここで詳述します。

具体的には、Web IDLはWebプラットフォームオブジェクトの表面APIを定義するための構文と、APIがJavaScriptの構造としてどのように現れるかを詳細に定義するJavaScriptバインディングを提供します。これにより、グローバルプロパティの追加、数値入力の処理、イテレーション動作の公開などの一般的な作業が、Webプラットフォーム仕様間で一貫性を保てるようになります。各仕様はWeb IDLでインターフェースを記述し、API固有の詳細は文章で規定します。

「JavaScript」という用語は、公式のECMAScriptという名称ではなく、より広く知られているECMA-262を指すために使用しています。

2. インターフェース定義言語

この節では、Web IDLという言語について説明します。これはWebプラットフォームのAPIのインターフェースを定義するために使用できます。Web APIを定義する仕様は、定義しているAPIのインターフェース(オブジェクトが持つ状態や振る舞い)を記述するIDLフラグメントを1つ以上含めることができます。 IDLフラグメントは、Definitions文法記号に一致する定義の列です。 実装がサポートするIDLフラグメントの集合に順序はありません。 完全な文法と記法の説明についてはIDL文法を参照してください。

IDLフラグメントに現れることができる 定義の種類は以下の通りです: インターフェース、 パーシャルインターフェース定義、 インターフェースミックスイン、 パーシャルミックスイン定義、 コールバック関数、 コールバックインターフェース、 名前空間、 パーシャル名前空間定義、 辞書、 パーシャル辞書定義、 型定義、 includes文です。 これらはすべて以下の節で定義されています。

定義(Definitionに一致するもの)は、 拡張属性(ExtendedAttributeListに一致するもの)のリストを前置することができ、 言語バインディングでの定義の扱い方を制御します。 この仕様で定義されている言語バインディング非依存の拡張属性については§ 2.14 拡張属性で、 JavaScriptバインディング固有のものについては§ 3.3 拡張属性で説明します。

[extended_attributes]
interface identifier {
  /* interface_members... */
};
Definitions ::
    ExtendedAttributeList Definition Definitions
    ε
Definition ::
    CallbackOrInterfaceOrMixin
    Namespace
    Partial
    Dictionary
    Enum
    Typedef
    IncludesStatement

以下はIDLフラグメントの例です。

[Exposed=Window]
interface Paint { };

[Exposed=Window]
interface SolidColor : Paint {
  attribute double red;
  attribute double green;
  attribute double blue;
};

[Exposed=Window]
interface Pattern : Paint {
  attribute DOMString imageURL;
};

[Exposed=Window]
interface GraphicalWindow {
  constructor();
  readonly attribute unsigned long width;
  readonly attribute unsigned long height;

  attribute Paint currentPaint;

  undefined drawRectangle(double x, double y, double width, double height);

  undefined drawText(double x, double y, DOMString text);
};

ここでは4つのインターフェースが定義されています。 GraphicalWindowインターフェースには、 2つの読み取り専用 属性、 1つの書き込み可能属性、および2つの操作が定義されています。 GraphicalWindowインターフェースを実装するオブジェクトは、使用する言語に応じて、これらの属性と操作を適切な形で公開します。

JavaScriptでは、IDLインターフェースの属性はアクセサプロパティとして、操作はプロトタイプオブジェクト上の組み込み関数オブジェクトとしてデータプロパティとして公開されます。GraphicalWindowを実装する各JavaScriptオブジェクトは、そのプロトタイプオブジェクトをプロトタイプチェーン上に持ちます。

GraphicalWindowに現れるコンストラクター操作によって、JavaScript実装ではコンストラクターが存在し、new GraphicalWindow()と呼び出すことでそのインターフェースを実装する新しいオブジェクトが返されます。

すべてのインターフェースは、[Exposed] 拡張属性を持ち、この属性によってインターフェースがWindowオブジェクトであるレルムのグローバルオブジェクトでのみ利用可能となります。

2.1. 名前

すべてのインターフェース、 パーシャルインターフェース定義、 名前空間、 パーシャル名前空間定義、 辞書、 パーシャル辞書定義、 列挙型、 コールバック関数、 コールバックインターフェースおよび 型定義(まとめて名前付き定義と呼ぶ)、 そしてすべての定数、 属性、 辞書メンバーには 識別子があり、一部の 操作にも識別子がある。 識別子は宣言内のどこかにidentifierトークンとして現れることで決まる:

注: 操作は、getterやsetterなど特殊な操作を宣言する際には識別子を持たない場合がある。

これらすべての構造において、識別子はidentifierトークンの値から 先頭のU+005F(_)を除いたものとなる。

注: 先頭のU+005F(_)は、識別子が予約語のように見えるのを回避するために使用される。たとえば「interface」という名前のインターフェースを定義できるようにするためである。識別子を元に戻すために先頭のU+005F(_)は削除される。

操作の引数は識別子としてやや広い範囲を取ることができる。操作宣言において、引数の識別子は型の直後に指定され、identifierトークンか、 ArgumentNameKeyword記号に一致するキーワードのいずれかで与えられる。これらのキーワードが使われる場合、先頭のアンダースコアでエスケープする必要はない。

interface interface_identifier {
  return_type operation_identifier(argument_type argument_identifier /* , ... */);
};
ArgumentNameKeyword ::
    attribute
    callback
    const
    constructor
    deleter
    dictionary
    enum
    getter
    includes
    inherit
    interface
    iterable
    maplike
    mixin
    namespace
    partial
    readonly
    required
    setlike
    setter
    static
    stringifier
    typedef
    unrestricted

もしidentifierトークンが使われた場合、 操作引数の識別子はそのトークンの値から 先頭のU+005F(_)を除いたものとなる。 代わりにArgumentNameKeywordキーワードトークンが使われた場合、 操作引数の識別子はそのトークンそのものとなる。

上記IDL構造の識別子(操作引数以外)は "constructor"、"toString" であってはならず、 またU+005F(_)で始まってはならない。これらは予約済み識別子と呼ばれる。

「toJSON」識別子は予約済み識別子ではないが、 通常の操作でのみ、 オブジェクトをJSON型に変換するために使用しなければならない。 詳細は§ 2.5.3.1 toJSONで説明する。

注: 特定の構造に対する識別子名のさらなる制限は後続の節で規定される場合がある。

ある実装がサポートするIDLフラグメント集合内では、 すべてのインターフェース、 名前空間、 辞書、 列挙型、 コールバック関数、 コールバックインターフェース、 型定義の識別子は、 他のインターフェース、 名前空間、 辞書、 列挙型、 コールバック関数、 コールバックインターフェース、 型定義の識別子と同じであってはならない。

IDLフラグメント内では、 定義への参照は 参照先定義の宣言より後に現れる必要はない。参照はIDLフラグメントをまたいで行うこともできる。

したがって、次のIDLフラグメントは有効です:

[Exposed=Window]
interface B : A {
  undefined f(SequenceOfLongs x);
};

[Exposed=Window]
interface A {
};

typedef sequence<long> SequenceOfLongs;

次のIDLフラグメントは 定義やインターフェースメンバーへの識別子の付与方法を示しています。

// 型定義の識別子: "number"
typedef double number;

// インターフェースの識別子: "System"
[Exposed=Window]
interface System {

  // 操作の識別子:          "createObject"
  // 操作引数の識別子: "interface"
  object createObject(DOMString _interface);

  // 操作引数の識別子: "interface"
  sequence<object> getObjects(DOMString interface);

  // 操作は識別子なし; getterを宣言
  getter DOMString (DOMString keyName);
};

// インターフェースの識別子: "TextField"
[Exposed=Window]
interface TextField {

  // 属性の識別子: "const"
  attribute boolean _const;

  // 属性の識別子: "value"
  attribute DOMString? _value;
};

なお、TextFieldインターフェース上の2番目の属性は(IDL文法のキーワードではないため)アンダースコアでエスケープする必要はありませんが、 識別子として属性の識別子を得るためにはアンダースコアが除去されます。

2.2. インターフェース

IDLフラグメントはオブジェクト指向システムの記述に用いられます。このようなシステムでは、オブジェクトは同一性を持ち、状態と振る舞いのカプセル化である実体です。 インターフェースは (interface InterfaceRestに一致)、 そのインターフェースを実装するオブジェクトが公開する状態と振る舞いを宣言する定義です。

[extended_attributes]
interface identifier {
  /* interface_members... */
};

インターフェースは インターフェースメンバー (InterfaceMembersに一致)として 一連のメンバーを仕様します。これらはインターフェース宣言の中括弧内に現れるメンバーです。

Web IDLのインターフェースは、そのインターフェースを実装するオブジェクトがどのように振る舞うかを記述します。オブジェクト指向言語のバインディングでは、特定のIDLインターフェースを実装するオブジェクトは、その状態の参照・変更、およびインターフェースで記述された振る舞いの呼び出し手段を提供することが期待されます。

インターフェースは他のインターフェースを継承するよう定義できます。 インターフェースの識別子の後に U+003A(:)と識別子が続く場合、 その識別子が継承元インターフェースです。 あるインターフェースが別のインターフェースを継承している場合、そのオブジェクトは継承元インターフェースも実装します。したがって、継承元インターフェースのメンバーも備えます。

interface identifier : identifier_of_inherited_interface {
  /* interface_members... */
};

メンバーの出現順はJavaScriptバインディングのプロパティ列挙に影響します。

インターフェースは、継承元インターフェースと同じ名前のメンバーを指定することもできます。派生インターフェースを実装するオブジェクトは、派生インターフェース上のそのメンバーを公開します。言語バインディングによっては、上書きされたメンバーがオブジェクト上でアクセス可能かどうかは異なります。

次の2つのインターフェースを考えます。

[Exposed=Window]
interface A {
  undefined f();
  undefined g();
};

[Exposed=Window]
interface B : A {
  undefined f();
  undefined g(DOMString x);
};

JavaScriptバインディングでは、Bのインスタンスのプロトタイプチェーンは以下のようになります:

[Object.prototype: the Object prototype object]
     ↑
[A.prototype: interface prototype object for A]
     ↑
[B.prototype: interface prototype object for B]
     ↑
[instanceOfB]

JavaScriptでinstanceOfB.f()を呼び出すと、Bで定義されたfが呼び出されます。ただし、AのfもA.prototype.f.call(instanceOfB)によって呼び出すことが可能です。

あるインターフェースAの継承インターフェースは、 Aが直接または間接的に継承するすべてのインターフェースの集合です。Aが他のインターフェースを継承しない場合、その集合は空です。そうでなければ、その集合にはAが継承するインターフェースBと、Bの継承インターフェースすべてが含まれます。

インターフェースの継承階層に循環があってはなりません。つまり、インターフェースAは自分自身を継承できず、 またAを継承するBを継承することもできません(そしてその先も同様)。

リストとしての 包含的継承インターフェースは、インターフェースIについて次のように定義されます:
  1. resultを« »とする。

  2. interfaceをIとする。

  3. interfaceがnullでない間:

    1. resultにinterfaceを追加する。

    2. interfaceを、もしあればIが継承するインターフェースに、なければnullに設定する。

  4. resultを返す。

一般的なインターフェースの多重継承はサポートされません。また、オブジェクトが任意のインターフェース集合を実装することもできません。オブジェクトは単一のインターフェースAを実装すると定義でき、その場合Aの継承インターフェースすべても実装します。 さらに、includes文を用いることで、 インターフェースAを実装するオブジェクトが、 Aがincludeする インターフェースミックスインのメンバーも常に含むものとできます。

各インターフェースメンバーには、拡張属性(ExtendedAttributeListに一致)のリストを 前置することができ、言語バインディングでの扱い方を制御します。

[extended_attributes]
interface identifier {

  [extended_attributes]
  const type constant_identifier = 42;

  [extended_attributes]
  attribute type identifier;

  [extended_attributes]
  return_type identifier(/* arguments... */);
};

インターフェースのIDLは、 パーシャルインターフェース 定義(partial interface PartialInterfaceRestに一致)によって複数の部分に分割できます。 パーシャルインターフェース定義の識別子は、 インターフェース定義の識別子と一致しなければなりません。各パーシャルインターフェース上のメンバーはすべて、そのインターフェース自体のメンバーとみなされます。

interface SomeInterface {
  /* interface_members... */
};

partial interface SomeInterface {
  /* interface_members... */
};

注: パーシャルインターフェース定義は、仕様の編集上の補助として意図されており、インターフェース定義を文書の複数箇所や複数文書に分割するために利用されます。

インターフェース定義とそのパーシャルインターフェース定義の出現順は問いません。

注: パーシャルインターフェース定義では他のインターフェースの継承を指定できません。継承は元のインターフェース定義で指定します。

インターフェースが言語の構造にどう対応するかは、該当言語バインディングで定まります。

インターフェースに適用可能な拡張属性は以下の通りです: [CrossOriginIsolated]、 [Exposed]、 [Global]、 [LegacyFactoryFunction]、 [LegacyNoInterfaceObject]、 [LegacyOverrideBuiltIns]、 [LegacyWindowAlias]、 [SecureContext]。

パーシャルインターフェースに適用可能な拡張属性は以下の通りです: [CrossOriginIsolated]、 [Exposed]、 [LegacyOverrideBuiltIns]、 [SecureContext]。

インターフェースは必ず[Exposed] 拡張属性で注釈されていなければなりません。

インターフェース interfaceの修飾名は以下のように定義されます:

  1. identifierをinterfaceの識別子とする。

  2. interfaceが[LegacyNamespace] 拡張属性を持つ場合:

    1. namespaceを[LegacyNamespace] 拡張属性の識別子引数とする。

    2. « namespace, identifier »をU+002E(.)区切りで連結したものを返す。

  3. identifierを返す。

CallbackOrInterfaceOrMixin ::
    callback CallbackRestOrInterface
    interface InterfaceOrMixin
InterfaceOrMixin ::
    InterfaceRest
    MixinRest
InterfaceRest ::
    identifier Inheritance { InterfaceMembers } ;
Partial ::
    partial PartialDefinition
PartialDefinition ::
    interface PartialInterfaceOrPartialMixin
    PartialDictionary
    Namespace
PartialInterfaceOrPartialMixin ::
    PartialInterfaceRest
    MixinRest
PartialInterfaceRest ::
    identifier { PartialInterfaceMembers } ;
InterfaceMembers ::
    ExtendedAttributeList InterfaceMember InterfaceMembers
    ε
InterfaceMember ::
    PartialInterfaceMember
    Constructor
PartialInterfaceMembers ::
    ExtendedAttributeList PartialInterfaceMember PartialInterfaceMembers
    ε
PartialInterfaceMember ::
    Const
    Operation
    Stringifier
    StaticMember
    Iterable
    AsyncIterable
    ReadOnlyMember
    ReadWriteAttribute
    ReadWriteMaplike
    ReadWriteSetlike
    InheritAttribute
Inheritance ::
    : identifier
    ε

次のIDLフラグメントは、相互参照する2つのインターフェースの定義例です。 HumanとDogはどちらもAnimalを継承します。これらいずれかのインターフェースを実装するオブジェクトはname属性を持ちます。

[Exposed=Window]
interface Animal {
  attribute DOMString name;
};

[Exposed=Window]
interface Human : Animal {
  attribute Dog? pet;
};

[Exposed=Window]
interface Dog : Animal {
  attribute Human? owner;
};

次のIDLフラグメントは、 DOMのインターフェースとコールバックインターフェースの簡易版を定義しています。

[Exposed=Window]
interface Node {
  readonly attribute DOMString nodeName;
  readonly attribute Node? parentNode;
  Node appendChild(Node newChild);
  undefined addEventListener(DOMString type, EventListener listener);
};

callback interface EventListener {
  undefined handleEvent(Event event);
};

プレーンなオブジェクトは、EventListenerのようなコールバックインターフェースを実装することができます:

var node = getNode();                                // Nodeのインスタンス取得

var listener = {
  handleEvent: function(event) {
    // ...
  }
};
node.addEventListener("click", listener);            // これは動作する。

node.addEventListener("click", function() { ... });  // これも同様に動作する。

しかし、このようなオブジェクトはNodeのようなインターフェースを実装することはできません:

var node = getNode();  // Nodeのインスタンス取得

var newNode = {
  nodeName: "span",
  parentNode: null,
  appendChild: function(newchild) {
    // ...
  },
  addEventListener: function(type, listener) {
    // ...
  }
};
node.appendChild(newNode);  // これはTypeError例外になる。

2.3. インターフェースミックスイン

インターフェースミックスインは (interface MixinRestに一致する)定義であり、 1つ以上のインターフェースにincludeされることができる状態や振る舞いを宣言し、 そのミックスインをincludeしたインターフェースを実装するオブジェクトによって公開されます。

interface mixin identifier {
  /* mixin_members... */
};

注: インターフェースミックスインはパーシャルインターフェース同様、 仕様の編集補助として意図されており、機能のまとまりをグループ化し、複数のインターフェース(場合によっては複数文書)にincludeできるようにします。 これらは言語バインディングを介して公開されることを目的としたものではありません。 § 2.3.1 ミックスインとパーシャルの利用で、 パーシャルインターフェース、 インターフェースミックスイン、 パーシャルインターフェースミックスイン の使い分けについて案内しています。

インターフェースミックスインは、 インターフェースミックスインメンバー (MixinMembersに一致)を定義します。 これらは、定数、 通常の操作、 通常の属性、 ストリギファイア であり、ミックスイン宣言の中括弧内に現れます。

これらの定数、 通常の操作、 通常の属性、 ストリギファイアは、 それらをincludeした インターフェース上に定義された場合と同様に、 オブジェクトが持つ振る舞いを記述します。

静的属性、 静的操作、 特殊操作、 イテラブル宣言、 非同期イテラブル宣言、 Maplike宣言、 Setlike宣言 は、インターフェースミックスイン宣言には現れません。

インターフェース同様、インターフェースミックスインのIDLは、 パーシャルインターフェースミックスイン 定義(partial interface MixinRestに一致)によって複数部分に分割できます。 パーシャルインターフェースミックスイン定義の識別子は、 インターフェースミックスイン定義の 識別子と一致しなければなりません。 各パーシャルインターフェースミックスイン定義に現れるメンバーは、インターフェースミックスイン自体のメンバーとみなされ、 さらにそのインターフェースミックスインをincludeするインターフェースのメンバーともみなされます。

interface mixin SomeMixin {
  /* mixin_members... */
};

partial interface mixin SomeMixin {
  /* mixin_members... */
};

メンバーの出現順はJavaScriptバインディングのプロパティ列挙に影響します。

なお、インターフェースや辞書とは異なり、 インターフェースミックスインは型を生成しません。

この仕様で定義されている拡張属性のうち、 インターフェースミックスインに適用できるのは [CrossOriginIsolated]、 [Exposed]、 [SecureContext] のみです。

includes文は (IncludesStatementに一致)定義であり、 すべてのインターフェースI (最初の識別子で特定)を実装するオブジェクトが インターフェースミックスインM(2番目の識別子で特定)のメンバーを 追加で含むことを宣言するために使われます。 インターフェースIは インターフェースミックスインM をincludeすると言います。

interface_identifier includes mixin_identifier;

最初の識別子はインターフェースIを参照しなければなりません。 2番目の識別子はインターフェースミックスインMを参照しなければなりません。

Mの各メンバーは、 Mをincludeするすべての インターフェースI、J、K…の メンバーとみなされ、 まるで各メンバーのコピーが作られたかのように扱われます。 つまり、Mのメンバーmについて、インターフェースIはmIという メンバーを持ち、 インターフェースJはメンバーmJを、 インターフェースKはメンバーmKを持つことになります。 ホストインターフェースは、 mI、mJ、mKに対して、それぞれI、J、Kです。

注: JavaScriptでは、インターフェースミックスインMのメンバーとして宣言され、組み込み関数オブジェクトを値とするデータプロパティとして公開される各通常の操作は、関連付けられたインターフェースがMをincludeする各インターフェースプロトタイプオブジェクトにおいて、互いに異なる組み込み関数オブジェクトになります。同様に、属性についても、アクセサプロパティの各コピーのgetterとsetterはそれぞれ異なる組み込み関数オブジェクトを持ちます。

includes文の出現順は、ホストインターフェースがどの順で インターフェースミックスインをincludeするかに影響します。

メンバーの順序は明確に規定されていません。 特にインターフェースミックスインが複数文書で定義される場合は未定義です。 issue #432で議論されています。

この仕様で定義される拡張属性のうち、includes文に適用できるものはありません。

次のIDLフラグメントは インターフェースEntryと、 インターフェースミックスインObservableを定義しています。 includes文によって、 Entryを実装するオブジェクトは常にObservableの メンバーを持つことが指定されています。

interface Entry {
  readonly attribute unsigned short entryType;
  // ...
};

interface mixin Observable {
  undefined addEventListener(DOMString type,
                        EventListener listener,
                        boolean useCapture);
  // ...
};

Entry includes Observable;

JavaScript実装では、すべてのEntryのプロトタイプチェーン上に addEventListenerプロパティが存在します:

var e = getEntry();          // Entryのインスタンス取得
typeof e.addEventListener;   // "function"になる
CallbackOrInterfaceOrMixin ::
    callback CallbackRestOrInterface
    interface InterfaceOrMixin
InterfaceOrMixin ::
    InterfaceRest
    MixinRest
Partial ::
    partial PartialDefinition
PartialDefinition ::
    interface PartialInterfaceOrPartialMixin
    PartialDictionary
    Namespace
MixinRest ::
    mixin identifier { MixinMembers } ;
MixinMembers ::
    ExtendedAttributeList MixinMember MixinMembers
    ε
MixinMember ::
    Const
    RegularOperation
    Stringifier
    OptionalReadOnly AttributeRest
IncludesStatement ::
    identifier includes identifier ;

2.3.1. ミックスインとパーシャルの利用

この節は参考情報です。

インターフェースミックスインは、属性、定数、操作を 複数のインターフェース間で共有できます。 単一のインターフェースのみ拡張する予定なら、 パーシャルインターフェースの利用を検討してください。

例えば、次のような方法の代わりに:

interface mixin WindowSessionStorage {
  readonly attribute Storage sessionStorage;
};
Window includes WindowSessionStorage;

こうしてください:

partial interface Window {
  readonly attribute Storage sessionStorage;
};

さらに、他の仕様が提供するインターフェースミックスイン を拡張することで、ウィンドウとワーカーの両方のコンテキストで属性、定数、または操作の集合を 公開するといった、一般的なユースケースに対応することもできます。

例えば、よくある冗長な方法の代わりに:

interface mixin GlobalCrypto {
  readonly attribute Crypto crypto;
};

Window includes GlobalCrypto;
WorkerGlobalScope includes GlobalCrypto;

WindowOrWorkerGlobalScope インターフェースミックスインを パーシャルインターフェースミックスインで拡張できます:

partial interface mixin WindowOrWorkerGlobalScope {
  readonly attribute Crypto crypto;
};

2.4. コールバックインターフェース

コールバックインターフェースは、定義であり、 callback interface identifier { CallbackInterfaceMembers } ;に一致します。 § 2.12 インターフェースを実装するオブジェクトで述べるように、どんなオブジェクトでも実装できます。

注: コールバックインターフェースはインターフェースではありません。名前や構文は、以前の規格バージョンでこれらの概念がより共通していた名残です。

コールバックインターフェースは コールバックインターフェースメンバー (CallbackInterfaceMembersに一致)を仕様します。 これはインターフェース宣言の中括弧内に現れるメンバーです。

callback interface identifier {
  /* interface_members... */
};

注: よく似た名前のコールバック関数定義も参照してください。

コールバックインターフェースは、正確に1つの通常の操作を定義しなければなりません。

仕様策定者は、既存APIの要件記述に必要な場合以外は コールバックインターフェース を定義しないようにしてください。 代わりにコールバック関数を使うべきです。

EventListener をコールバックインターフェースとして定義するのは、 既存APIで特定のプロパティ(この場合handleEvent)を持つオブジェクトがそのインターフェースを実装したものとして扱える必要がある例です。 新しいAPIや互換性の問題がないAPIでは、 コールバック関数を使うことで (JavaScriptバインディングでは)関数オブジェクトのみ許可できます。

コールバックインターフェースが定数を宣言する場合は、必ず[Exposed] 拡張属性で注釈しなければなりません。

CallbackRestOrInterface ::
    CallbackRest
    interface identifier { CallbackInterfaceMembers } ;
CallbackInterfaceMembers ::
    ExtendedAttributeList CallbackInterfaceMember CallbackInterfaceMembers
    ε
CallbackInterfaceMember ::
    Const
    RegularOperation

2.5. メンバー

インターフェース、インターフェースミックスイン、名前空間は、それぞれ メンバー (それぞれInterfaceMembers、 MixinMembers、 NamespaceMembersに一致)を仕様します。 これらは中括弧内に現れる定数、 属性、 操作やその他の宣言です。 属性は、その インターフェース、 インターフェースミックスイン、 名前空間を実装するオブジェクトが公開する状態を記述し、 操作はオブジェクト上で呼び出せる振る舞いを記述します。 定数は、システムのオブジェクト利用者に便宜的に公開される名前付き定数値を宣言します。

あるインターフェースがインターフェースミックスインをincludeすると、 ミックスインの各メンバーはそのインターフェースのメンバーとみなされます。 対照的に、継承されたインターフェースメンバーは そのインターフェースのメンバーとはみなされません。

各種インターフェースやインターフェースミックスインで定義されるメンバーの コンストラクタ手順、 getter手順、 setter手順、 メソッド手順は、 this値(そのメンバーが宣言されるインターフェース型、またはそのメンバーが宣言されるミックスインをincludeするインターフェース型のIDL値)にアクセスできます。

setter手順は、 与えられた値にもアクセスでき、 これは属性が宣言された型のIDL値です。

インターフェース、 インターフェースミックスイン、 コールバックインターフェース、 名前空間は それぞれ異なるセットのメンバーをサポートします。 詳細は§ 2.2 インターフェース、 § 2.3 インターフェースミックスイン、 § 2.4 コールバックインターフェース、 § 2.6 名前空間で規定されており、次の参考表にまとめます:

インターフェース コールバックインターフェース インターフェースミックスイン 名前空間
定数 ● ● ●
通常の属性 ● ● 読み取り専用属性のみ
静的属性 ●
通常の操作 ● ● ● ●
ストリギファイア ● ●
特殊操作 ●
静的操作 ●
イテラブル宣言 ●
非同期イテラブル宣言 ●
Maplike宣言 ●
Setlike宣言 ●

2.5.1. 定数

定数は、 (Constに一致)名前に定数値を束縛するための宣言です。 定数はインターフェースやコールバックインターフェース上に現れます。

定数はこれまで主に、列挙型スタイルの名前付き整数コードの定義に使われてきましたが、Webプラットフォームではこの設計パターンから文字列の利用へと移行しています。 この機能を使用したい編集者は、進める前に issueを提出 して議論することが強く推奨されます。

const type constant_identifier = 42;

定数の識別子は、 同じインターフェースメンバーやコールバックインターフェースメンバーの識別子と重複してはなりません(同じインターフェース、 またはコールバックインターフェース上)。 また、"length"、"name"、"prototype"であってはなりません。

注: これら3つの名前はJavaScriptバインディングのインターフェースオブジェクト上のプロパティ名です。

定数の型(ConstTypeに一致)は、 プリミティブ型以外であってはなりません。 識別子が使われる場合、それはプリミティブ型の型を持つ型定義を参照しなければなりません。

定数宣言のConstValue部分は定数値を与えます。値は 2つのbooleanリテラルトークン(trueとfalse)、 integerトークン、 decimalトークン、 もしくは3つの浮動小数点定数値(-Infinity、Infinity、NaN)のいずれかです。

注: これらの値(文字列と空のシーケンスも含む)は、辞書メンバーのデフォルト値やオプション引数のデフォルト値にも使えます。 ただし、文字列、空のシーケンス[]、デフォルト辞書{}は定数値にはできません。

booleanリテラルトークンtrue、falseの値はIDLのboolean 値trueとfalseです。

integerトークンの値は、以下の通り決まる整数です:

  1. Sをintegerトークンで一致したスカラー値の列とする。

  2. SがU+002D(-)で始まる場合signは−1、そうでなければ1。

  3. 先頭のU+002D(-)後に続くスカラー値によって基数baseを決める:

    U+0030 (0), U+0058 (X)
    U+0030 (0), U+0078 (x)

    基数は16。

    U+0030 (0)

    基数は8。

    その他

    基数は10。

  4. 任意の先頭のU+002D (-)文字と基数を示すスカラー値に続く、残りの全てのスカラー値を 基数baseの整数として解釈した結果をnumberとする。

  5. sign × numberを返す。

integerトークンの型は、定数・辞書メンバー・オプション引数の型と同じです。 integerトークンの値は、§ 2.13 型に示される型の有効範囲を外れてはなりません。

decimalトークンの値は、 使われる型(定数・辞書メンバー・オプション引数)に応じてIEEE 754単精度/倍精度浮動小数点数のいずれかです:
  1. Sをdecimalトークンで一致したスカラー値の列とする。

  2. SをJavaScriptのNumericLiteralとしてパースした結果をresultとする。

  3. 型がfloatまたはunrestricted floatの場合、 resultに最も近いIEEE 754単精度浮動小数点数が値となる。

  4. それ以外の場合(型がdoubleまたはunrestricted double)、 resultに最も近いIEEE 754倍精度浮動小数点数が値となる。[IEEE-754]

定数値としてInfinity、-Infinity、NaNを指定した場合も、 型に応じてIEEE 754単精度/倍精度浮動小数点値となります:

型unrestricted float、値Infinity

値はIEEE 754単精度正の無限大。

型unrestricted double、値Infinity

値はIEEE 754倍精度正の無限大。

型unrestricted float、値-Infinity

値はIEEE 754単精度負の無限大。

型unrestricted double、値-Infinity

値はIEEE 754倍精度負の無限大。

型unrestricted float、値NaN

値はIEEE 754単精度NaN(ビットパターン0x7fc00000)。

型unrestricted double、値NaN

値はIEEE 754倍精度NaN(ビットパターン0x7ff8000000000000)。

decimalトークンの型は、使われる定数・辞書メンバー・オプション引数の型と同じです。 decimalトークンの値は型の有効範囲を超えてはならず(§ 2.13 型参照)、 Infinity、-Infinity、NaNはfloatやdoubleの値として使えません。

nullトークンの値は、nullというヌラブル型の特別な値です。 nullトークンの型は、使われる定数・辞書メンバー・オプション引数の型と同じです。

定数に割り当てる値の型VTと、定数・辞書メンバー・オプション引数自体の型DTについて、型が互換でなければなりません。 互換とは、DTとVTが一致するか、DTがVTを内包するヌラブル型であり、その内側の型がVTである場合です。

定数は、現れるインターフェースやコールバックインターフェースの特定インスタンスとは関連付けられません。インスタンス上で定数が公開されるかは言語バインディング依存です。

ただしJavaScriptバインディングでは、定数は、その定数が宣言されているIDLインターフェースを実装するオブジェクトを通してアクセスできます。 例えば、次のIDLでは:

[Exposed=Window]
interface A {
  const short rambaldi = 47;
};

JavaScriptでは定数値はA.rambaldiまたはinstanceOfA.rambaldiでアクセスできます。

定数に適用可能な拡張属性は以下の通りです: [CrossOriginIsolated]、 [Exposed]、 [SecureContext]。

Const ::
    const ConstType identifier = ConstValue ;
ConstValue ::
    BooleanLiteral
    FloatLiteral
    integer
BooleanLiteral ::
    true
    false
FloatLiteral ::
    decimal
    -Infinity
    Infinity
    NaN
ConstType ::
    PrimitiveType
    identifier

次のIDLフラグメントは、 上記型の定数の定義例です。

[Exposed=Window]
interface Util {
  const boolean DEBUG = false;
  const octet LF = 10;
  const unsigned long BIT_MASK = 0x0000fc00;
  const double AVOGADRO = 6.022e23;
};

2.5.2. 属性

属性は、 インターフェースメンバーまたは 名前空間メンバー (inherit AttributeRest、 static OptionalReadOnly AttributeRest、 stringifier OptionalReadOnly AttributeRest、 OptionalReadOnly AttributeRest、 またはAttributeRestに一致)であり、 指定された型と識別子を持つデータフィールドを宣言するために使われます。その値は取得でき、(場合によっては)変更できます。属性には2種類あります:

  1. 通常の属性:オブジェクトがそのインターフェースを実装する際、指定された識別子のデータフィールドメンバーを持つことを宣言します。

    interface interface_identifier {
      attribute type identifier;
    };
    
  2. 静的属性:インターフェースを実装する特定のオブジェクトとは関連しない属性を宣言するために使われます。

    interface interface_identifier {
      static attribute type identifier;
    };
    

属性にstaticキーワードがなければ 通常の属性を宣言し、ある場合は静的属性となります。 また、インターフェースメンバーだけでなく、 読み取り専用通常の属性は名前空間メンバーにもなり得ます。

属性attrのgetter手順は、「attr getter手順は次の通り:」という文+リスト、または「attr getter手順は...」という文+インライン説明で記述します。

属性attrのsetter手順は、「attr setter手順は次の通り:」という文+リスト、または「attr setter手順は...」という文+インライン説明で記述します。

注: getter手順を定義するときは、暗黙的にthisにアクセスできます。 setter手順の場合は、暗黙的にthisと与えられた値にアクセスできます。

属性の識別子は、 同じインターフェース上の他のインターフェースメンバーと重複してはなりません。 静的属性の識別子は"prototype"であってはなりません。

属性の型は、attributeキーワードの後に現れる型(Typeに一致)で指定されます。 Typeが識別子か、識別子+?の場合、 その識別子はインターフェース、列挙型、コールバック関数、コールバックインターフェース、型定義を識別しなければなりません。

typedefを解決した後の属性の型は、以下のいずれかの型(ヌラブル/非ヌラブル)であってはなりません:

readonlyキーワードがattributeキーワードの前に現れる場合、その属性は読み取り専用です。 この属性を持つインターフェースを実装するオブジェクトは、その属性への代入を許可しません。代入が単に拒否されるか、無視されるか、例外となるかは言語バインディング依存です。

interface interface_identifier {
  readonly attribute type identifier;
};

型がPromise型の属性は必ず読み取り専用でなければなりません。また、[LegacyLenientSetter]、 [PutForwards]、 [Replaceable]、 [SameObject]の いずれの拡張属性も持てません。

通常の属性で読み取り専用でないものは、 祖先インターフェースからgetterを継承するよう宣言できます。これにより、祖先インターフェースで読み取り専用の属性を派生インターフェースで書き込み可能にできます。 属性がinherit付きで宣言されていればgetterを継承します。 getterを継承する元の読み取り専用属性は、継承する属性が定義されているインターフェースの最も近い祖先インターフェースにある、同じ識別子の属性です。getterの継承元と継承先の属性の型は一致していなければなりません。

注: 文法によりinheritは読み取り専用属性や静的属性には使えません。

[Exposed=Window]
interface Ancestor {
  readonly attribute TheType theIdentifier;
};

[Exposed=Window]
interface Derived : Ancestor {
  inherit attribute TheType theIdentifier;
};

通常の属性宣言にstringifierキーワードが使われている場合、 そのインターフェースを実装するオブジェクトは属性値でストリング化されることを示します。詳細は§ 2.5.5 ストリギファイア参照。

interface interface_identifier {
  stringifier attribute DOMString identifier;
};

通常・静的属性に適用可能な拡張属性は以下の通りです: [CrossOriginIsolated]、 [Exposed]、 [SameObject]、 [SecureContext]。

通常属性にのみ適用可能な拡張属性は以下の通りです: [LegacyLenientSetter]、 [LegacyLenientThis]、 [PutForwards]、 [Replaceable]、 [LegacyUnforgeable]。

ReadOnlyMember ::
    readonly ReadOnlyMemberRest
ReadOnlyMemberRest ::
    AttributeRest
    MaplikeRest
    SetlikeRest
ReadWriteAttribute ::
    AttributeRest
InheritAttribute ::
    inherit AttributeRest
AttributeRest ::
    attribute TypeWithExtendedAttributes AttributeName ;
AttributeName ::
    AttributeNameKeyword
    identifier
AttributeNameKeyword ::
    required
OptionalReadOnly ::
    readonly
    ε

次のIDLフラグメントは、 インターフェース上で属性を宣言する方法を示しています:

[Exposed=Window]
interface Animal {

  // 任意の文字列値を設定できるシンプルな属性
  readonly attribute DOMString name;

  // 値を代入できる属性
  attribute unsigned short age;
};

[Exposed=Window]
interface Person : Animal {

  // Animalからgetter動作を継承する属性。Personの説明に記載不要。
  inherit attribute DOMString name;
};

2.5.3. 操作

操作は、 インターフェースメンバー、 コールバックインターフェースメンバー、 名前空間メンバー (static RegularOperation、 stringifier、 RegularOperationまたは SpecialOperationに一致)であり、 インターフェースを実装するオブジェクト上で呼び出せる振る舞いを定義します。操作には3種類あります:

  1. 通常の操作: インターフェースを実装するオブジェクトが、指定された識別子のメソッドを持つことを宣言します。

    interface interface_identifier {
      return_type identifier(/* arguments... */);
    };
    
  2. 特殊操作: インターフェースを実装するオブジェクト上で、インデックス付きやストリング化などの特殊な振る舞いを宣言します。

    interface interface_identifier {
      /* special_keyword */ return_type identifier(/* arguments... */);
      /* special_keyword */ return_type (/* arguments... */);
    };
    
  3. 静的操作: インターフェースを実装する特定のオブジェクトとは関連しない操作を宣言します。

    interface interface_identifier {
      static return_type identifier(/* arguments... */);
    };
    

操作に識別子があり、staticキーワードがない場合は通常の操作となります。 宣言に特殊キーワード (Specialやstringifierキーワード)を使っていれば、特殊操作となります。1つの操作で通常操作と特殊操作両方を宣言できます。 詳細は§ 2.5.6 特殊操作参照。 通常操作はインターフェースメンバーだけでなく、 コールバックインターフェースメンバーや名前空間メンバーにもなり得ます。

操作に識別子がない場合、特殊キーワードを用いて特殊操作として宣言しなければなりません。

通常の操作や静的操作の識別子は、 同じインターフェース、 コールバックインターフェース、 名前空間上の定数や属性と重複してはなりません。 静的操作の識別子は"prototype"であってはなりません。

注: 識別子は同じインターフェース内の他の操作と重複しても構いません。 これが操作のオーバーロード指定方法です。

注: 静的操作の識別子は、 同じインターフェース上の通常の操作と重複しても構いません。

操作の戻り値型は、 宣言で識別子の前に現れる型(Typeに一致)で指定されます。 戻り値型が識別子+?の場合、その識別子は インターフェース、 辞書、 列挙型、 コールバック関数、 コールバックインターフェース、 型定義 のいずれかを識別しなければなりません。

操作の引数(ArgumentListに一致)は宣言の括弧内で指定します。各引数は型(Typeに一致)+識別子 (ArgumentNameに一致)で指定します。

注: 表現力のため、操作引数の識別子はArgumentNameKeywordキーワードでも指定でき、その場合エスケープ不要です。

操作引数の型が識別子+?の場合、その識別子は インターフェース、 列挙型、 コールバック関数、 コールバックインターフェース、 型定義 を識別しなければなりません。 操作引数の型が?の続かない識別子の場合は、これらに加えて辞書も識別可能です。

typedef解決後、引数型がヌラブル型なら、 内側の型は辞書型であってはなりません。

interface interface_identifier {
  return_type identifier(type identifier, type identifier /* , ... */);
};

各引数の識別子は、同じ操作宣言内の他の引数の識別子と重複してはなりません。

各引数には、拡張属性(ExtendedAttributeListに一致)を前置でき、 引数として渡された値の言語バインディングでの扱い方を制御できます。

interface interface_identifier {
  return_type identifier([extended_attributes] type identifier, [extended_attributes] type identifier /* , ... */);
};

次のIDLフラグメントは、 インターフェース上で通常の操作を宣言する方法を示しています:

[Exposed=Window]
interface Dimensions {
  attribute unsigned long width;
  attribute unsigned long height;
};

[Exposed=Window]
interface Button {

  // 引数なし・booleanを返す操作
  boolean isMouseOver();

  // オーバーロードされた操作
  undefined setDimensions(Dimensions size);
  undefined setDimensions(unsigned long width, unsigned long height);
};

操作やコンストラクター操作は、 最後の引数に...トークンを型の直後に使った場合、可変長とみなされます。 可変長操作は、宣言された最後の引数以降に任意個の追加引数を受け取れます。暗黙の追加仮引数は宣言された最後の引数と同じ型です。呼び出し時は最後の引数を省略しても構いません。...は引数リストの最後の引数でのみ使えます。

interface interface_identifier {
  return_type identifier(type... identifier);
  return_type identifier(type identifier, type... identifier);
};

本仕様で定義される拡張属性のうち、引数リストを取るもの ([LegacyFactoryFunction])や コールバック関数も、 引数リストに...トークンが使われている場合は可変長とみなされます。

次のIDLフラグメントは、2つの可変長操作を持つインターフェースの例です:

[Exposed=Window]
interface IntegerSet {
  readonly attribute unsigned long cardinality;

  undefined union(long... ints);
  undefined intersection(long... ints);
};

JavaScriptバインディングでは、可変長操作は引数を可変個受け付ける関数として実装されます:

var s = getIntegerSet();  // IntegerSetのインスタンス取得

s.union();                // 'ints'に対応する引数なし
s.union(1, 4, 7);         // 'ints'に3引数

可変長関数非対応の言語バインディングでは、明示的な配列やリストを渡す仕様となる場合もあります。

引数がoptionalキーワードで宣言されている場合、その引数はオプション引数です。 可変長操作の最後の引数もオプション引数とみなされます。オプション引数の宣言は、操作呼び出し時にその引数を省略できることを示します。可変長操作では最後の引数を明示的にoptionalと宣言してはなりません。

interface interface_identifier {
  return_type identifier(type identifier, optional type identifier);
};

オプション引数にはデフォルト値も指定できます。引数識別子の後にU+003D(=)と値(DefaultValue に一致)を続けて指定します。 可変長操作の暗黙的オプション引数にはデフォルト値を指定できません。デフォルト値は、操作呼び出し時に該当引数が省略された場合に仮定される値です。

interface interface_identifier {
  return_type identifier(type identifier, optional type identifier = "value");
};

デフォルト値としてtrueをboolean型引数に使うことは強く推奨されません。 著者が暗黙のundefinedデフォルト変換(すなわちfalse)を期待しがちなため、混乱の元となります。 [API-DESIGN-PRINCIPLES]

引数型が辞書型または辞書型を平坦化されたメンバー型の1つとして持つユニオン型で、辞書型や祖先に required メンバーがなく、 引数が最後または以降がオプション引数のみの場合は、その引数をオプション・デフォルト値付きで宣言しなければなりません。

これはAPI設計上、空の辞書値を渡さずデフォルト値だけ使いたい場合に著者が明示的に空辞書を渡す必要がないようにするためです。

多くの場合デフォルト値は{}ですが、辞書型を平坦化されたメンバー型の1つとして持つユニオン型の場合は他メンバーの初期化値でも構いません。

booleanリテラル(trueやfalse)、nullトークン、integerトークン、decimalトークン、浮動小数点リテラル(Infinity、-Infinity、NaN)をデフォルト値に使った場合は、定数の場合と同様に解釈されます。

undefinedトークンをデフォルト値に使った場合、その値はIDLのundefined値となります。

オプション引数のデフォルト値にstringトークンも使え、 その値は以下のように決まる文字列型です:
  1. Sをstringトークンで一致したスカラー値(先頭と末尾のU+0022(")スカラー値を除く)とする。

  2. 引数の型ごとに:

    DOMString
    USVString
    列挙型

    stringトークンの値はS。

    ByteString

    Assert: SにU+00FFを超えるコードポイントが含まれていないこと。

    stringトークンの値はSの等価エンコード。

オプション引数の型が列挙型の場合、 デフォルト値はその列挙型値のいずれかでなければなりません。

オプション引数のデフォルト値として、空のシーケンス値を表す2トークン値[]も使えます。この値の型は、デフォルト値として使われるオプション引数の型と同じです。その型は、シーケンス型、内部型がシーケンス型であるヌラブル型、または平坦化されたメンバー型にシーケンス型を持つユニオン型もしくはヌラブルユニオン型でなければなりません。

オプション引数のデフォルト値として、ESのnullまたはプロパティを持たないオブジェクトから得られるような、デフォルト初期化された辞書値を表す2トークン値{}も使えます。この値の型は、デフォルト値として使われるオプション引数の型と同じです。その型は、辞書型、または平坦化されたメンバー型に辞書型を持つユニオン型でなければなりません。

次のIDLフラグメントは、 2通りの引数数で呼び出せる操作を持つインターフェースの例です:

[Exposed=Window]
interface ColorCreator {
  object createColor(double v1, double v2, double v3, optional double alpha);
};

これは以下のように2つのオーバーロード操作を持つインターフェースに相当します:

[Exposed=Window]
interface ColorCreator {
  object createColor(double v1, double v2, double v3);
  object createColor(double v1, double v2, double v3, double alpha);
};

次のIDLフラグメントは、 辞書型引数を取る操作を持つインターフェースの例です:

dictionary LookupOptions {
  boolean caseSensitive = false;
};

[Exposed=Window]
interface AddressBook {
  boolean hasAddressForName(USVString name, optional LookupOptions options = {});
};

hasAddressForNameを1引数で呼ぶと、2番目の引数にはデフォルト初期化されたLookupOptions辞書が渡され、caseSensitiveはfalseとなります。

操作に適用可能な拡張属性は以下の通りです: [CrossOriginIsolated]、 [Default]、 [Exposed]、 [LegacyUnforgeable]、 [NewObject]、 [SecureContext]。

操作operationのメソッド手順は、「operation(arg1, arg2, ...)メソッド手順は次の通り:」という文+リスト、または「operation(arg1, arg2, ...)メソッド手順は...」という文+インライン説明で記述します。

注: メソッド手順を定義する際は暗黙的にthisにアクセスできます。

DefaultValue ::
    ConstValue
    string
    [ ]
    { }
    null
    undefined
Operation ::
    RegularOperation
    SpecialOperation
RegularOperation ::
    Type OperationRest
SpecialOperation ::
    Special RegularOperation
Special ::
    getter
    setter
    deleter
OperationRest ::
    OptionalOperationName ( ArgumentList ) ;
OptionalOperationName ::
    OperationName
    ε
OperationName ::
    OperationNameKeyword
    identifier
OperationNameKeyword ::
    includes
ArgumentList ::
    Argument Arguments
    ε
Arguments ::
    , Argument Arguments
    ε
Argument ::
    ExtendedAttributeList ArgumentRest
ArgumentRest ::
    optional TypeWithExtendedAttributes ArgumentName Default
    Type Ellipsis ArgumentName
ArgumentName ::
    ArgumentNameKeyword
    identifier
Ellipsis ::
    ...
    ε
ArgumentNameKeyword ::
    attribute
    callback
    const
    constructor
    deleter
    dictionary
    enum
    getter
    includes
    inherit
    interface
    iterable
    maplike
    mixin
    namespace
    partial
    readonly
    required
    setlike
    setter
    static
    stringifier
    typedef
    unrestricted
2.5.3.1. toJSON

toJSON 通常の操作を宣言することで、 インターフェースは、 それを実装するオブジェクトをJSON型に変換する方法を指定します。

toJSON 通常の操作はこの用途に予約されています。 引数はゼロでなければならず、戻り値はJSON型でなければなりません。

JSON型は次の通りです:

toJSON 通常の操作をオブジェクト上でどう公開するか、 JSON型をどうJSON文字列に変換するかは、言語バインディング依存です。

注: JavaScriptバインディングでは、toJSONメソッドが公開され、 その返すJSON型はJavaScript値となり、JSON.stringify() 関数でJSON文字列に変換できます。 また、JavaScriptバインディングではtoJSON操作に[Default] 拡張属性を付与でき、この場合はデフォルトtoJSON手順が公開されます。

次のIDLフラグメントは、 TransactionインターフェースにtoJSONメソッド(本文で定義)を持つ例です:

[Exposed=Window]
interface Transaction {
  readonly attribute DOMString from;
  readonly attribute DOMString to;
  readonly attribute double amount;
  readonly attribute DOMString description;
  readonly attribute unsigned long number;
  TransactionJSON toJSON();
};

dictionary TransactionJSON {
  Account from;
  Account to;
  double amount;
  DOMString description;
};

TransactionインターフェースのtoJSON 通常の操作は、次のように定義できます:

toJSON()メソッド手順:

  1. jsonを新しいマップとする。

  2. 次の各属性識別子attrについて:「from」「to」「amount」「description」:

    1. valueをattrのgetter手順(this上)を実行した結果とする。

    2. json[attr]にvalueをセットする。

  3. jsonを返す。

JavaScriptバインディングでは、TransactionオブジェクトにtoJSON()メソッドが存在します:

// Transactionのインスタンス取得
var txn = getTransaction();

// 次のようなオブジェクトになる:
// {
//   from: "Bob",
//   to: "Alice",
//   amount: 50,
//   description: "books"
// }
txn.toJSON();

// 次のような文字列になる:
// '{"from":"Bob","to":"Alice","amount":50,"description":"books"}'
JSON.stringify(txn);

2.5.4. コンストラクター操作

あるインターフェースに コンストラクター操作メンバー(Constructorに一致)がある場合、 そのインターフェースを実装するオブジェクトを コンストラクターで生成できることを示します。

1つのインターフェースに 複数のコンストラクター操作を定義できます。 そのインターフェース上の各コンストラクター操作ごとに、 指定された引数でインスタンスを生成しようとする手段が提供されます。

インターフェース名interfaceのコンストラクター操作の コンストラクター手順は、 「new interface(arg1, arg2, ...)コンストラクター手順は次の通り:」という文+リスト、 または「new interface(arg1, arg2, ...)コンストラクター手順は...」という文+インライン説明で記述します。

コンストラクター手順は、何もしない・渡された値で thisを初期化する・例外をスローする、いずれかの動作を行う必要があります。

コンストラクターが thisを初期化しない場合は 「new Example(init)コンストラクター手順は何もしない」と記述できます。

コンストラクター操作の実装方法については § 3.7.1 インターフェースオブジェクトを参照してください。

以下のIDLは2つのインターフェースを定義しています。2番目はコンストラクター操作を持ち、1番目は持ちません。

[Exposed=Window]
interface NodeList {
  Node item(unsigned long index);
  readonly attribute unsigned long length;
};

[Exposed=Window]
interface Circle {
  constructor();
  constructor(double radius);
  attribute double r;
  attribute double cx;
  attribute double cy;
  readonly attribute double circumference;
};

これらのインターフェースをサポートするJavaScript実装では、Circleインターフェースオブジェクトに[[Construct]]内部メソッドが実装され、 インターフェースを実装する新しいオブジェクトを返します。 引数はゼロまたは1個取れます。

NodeListインターフェースオブジェクトが[[Construct]]内部メソッドを持つかは不明ですが、 いずれにせよコンストラクターとして使うとTypeErrorがスローされます。 [whatwg/webidl Issue #698]

var x = new Circle();      // 引数なしコンストラクターでCircleインターフェースを実装する
                           // プラットフォームオブジェクト参照を生成

var y = new Circle(1.25);  // 1引数コンストラクターでCircleオブジェクト生成

var z = new NodeList();    // コンストラクター未宣言なのでTypeErrorになる
Constructor ::
    constructor ( ArgumentList ) ;
ArgumentList ::
    Argument Arguments
    ε
Arguments ::
    , Argument Arguments
    ε
Argument ::
    ExtendedAttributeList ArgumentRest
ArgumentRest ::
    optional TypeWithExtendedAttributes ArgumentName Default
    Type Ellipsis ArgumentName
ArgumentName ::
    ArgumentNameKeyword
    identifier
Ellipsis ::
    ...
    ε
ArgumentNameKeyword ::
    attribute
    callback
    const
    constructor
    deleter
    dictionary
    enum
    getter
    includes
    inherit
    interface
    iterable
    maplike
    mixin
    namespace
    partial
    readonly
    required
    setlike
    setter
    static
    stringifier
    typedef
    unrestricted

2.5.5. ストリギファイア

あるインターフェースにストリギファイアがある場合、 そのインターフェースを実装するオブジェクトはデフォルト以外の文字列変換を持つことを意味します。ストリギファイアはstringifierキーワードで指定でき、 単独で使うとストリギファイア操作を生成します。

interface interface_identifier {
  stringifier;
};

インターフェースの付随する本文で、そのインターフェースのストリギファイ挙動を定義しなければなりません。

stringifierキーワードは属性にも付けられます。 この場合、オブジェクトを文字列に変換した際の値はその属性値となります。stringifierキーワードは、 属性がDOMString またはUSVString型でない限り付与できません。 また、静的属性には付与できません。

interface interface_identifier {
  stringifier attribute DOMString identifier;
};

1つのインターフェースにはストリギファイアは最大1つだけ存在できます。

Stringifier ::
    stringifier StringifierRest
StringifierRest ::
    OptionalReadOnly AttributeRest
    ;

次のIDLフラグメントは、 name属性の値でストリング化されるインターフェースを定義しています:

[Exposed=Window]
interface Student {
  constructor();
  attribute unsigned long id;
  stringifier attribute DOMString name;
};

JavaScriptバインディングでは、Studentオブジェクトが文字列を期待する文脈で使われた場合、 オブジェクトのnameプロパティ値が使われます:

var s = new Student();
s.id = 12345678;
s.name = '周杰倫';

var greeting = 'Hello, ' + s + '!';  // greeting == 'Hello, 周杰倫!'

次のIDLフラグメントは、 IDL自体には記載されていないカスタムストリング化挙動を持つインターフェースを定義します。

[Exposed=Window]
interface Student {
  constructor();
  attribute unsigned long id;
  attribute DOMString? familyName;
  attribute DOMString givenName;

  stringifier;
};

したがって、本文でストリギファイ挙動を説明する必要があります。 familyName・givenName属性がそれぞれ家族名・名前概念に裏付けられていると仮定します。

ストリギファイ挙動手順:

  1. thisのfamily nameがnullなら、 thisのgiven nameを返す。

  2. thisのgiven name+U+0020 SPACE+thisのfamily nameを連結して返す。

このIDLのJavaScript実装は以下のように動作します:

var s = new Student();
s.id = 12345679;
s.familyName = 'Smithee';
s.givenName = 'Alan';

var greeting = 'Hi ' + s;  // greeting == 'Hi Alan Smithee'

2.5.6. 特殊操作

特殊操作は、 その宣言が現れるインターフェースを実装するオブジェクト上で特定の特殊な挙動を宣言するものです。 特殊操作は、操作宣言内で特殊キーワードを使って宣言します。

特殊操作には3種類あります。以下の表は、各特殊操作の種類ごとに宣言に使う特殊キーワードとその目的を示します:

特殊操作 キーワード 目的
ゲッター getter オブジェクトがプロパティ取得でインデックスされた時の挙動を定義
セッター setter オブジェクトがプロパティ代入や作成でインデックスされた時の挙動を定義
デリーター deleter オブジェクトがプロパティ削除でインデックスされた時の挙動を定義

すべての言語バインディングが全ての特殊オブジェクト挙動をサポートするわけではありません。識別子なしで宣言された特殊操作は、その挙動をサポートしない言語バインディングでは単に機能しません。

次のIDLフラグメントはgetterとsetterを持つインターフェースの例です:

[Exposed=Window]
interface Dictionary {
  readonly attribute unsigned long propertyCount;

  getter double (DOMString propertyName);
  setter undefined (DOMString propertyName, double propertyValue);
};

プロパティgetter・setter非対応の言語バインディングでは、Dictionaryを実装するオブジェクトはその特殊挙動を持ちません。

特殊操作に識別子を付けて宣言することは、識別子なしの特殊操作宣言を独立して分離するのと同等です。この方法はインターフェースのメソッド手順の単純化に役立ちます。

次の2つのインターフェースは等価です:

[Exposed=Window]
interface Dictionary {
  readonly attribute unsigned long propertyCount;

  getter double getProperty(DOMString propertyName);
  setter undefined setProperty(DOMString propertyName, double propertyValue);
};
[Exposed=Window]
interface Dictionary {
  readonly attribute unsigned long propertyCount;

  double getProperty(DOMString propertyName);
  undefined setProperty(DOMString propertyName, double propertyValue);

  getter double (DOMString propertyName);
  setter undefined (DOMString propertyName, double propertyValue);
};

1つの操作に同じ特殊キーワードを2回使ってはなりません。

ゲッターとセッターには2種類あり、プロパティ名としてDOMStringを取るものは 名前付きプロパティゲッター・ 名前付きプロパティセッター、 プロパティインデックスとしてunsigned longを取るものは インデックス付きプロパティゲッター・ インデックス付きプロパティセッターです。 デリーターは1種類のみで、 名前付きプロパティデリーターです。 詳細は§ 2.5.6.1 インデックス付きプロパティ、 § 2.5.6.2 名前付きプロパティ参照。

1つのインターフェース上には、 名前付きプロパティデリーターは最大1つ、 ゲッター・セッター各種も最大1つずつしか存在できません。

インターフェースがある種類のセッターを持つ場合は、同じ種類のゲッターも持たなければなりません。名前付きプロパティデリーターを持つ場合は、 名前付きプロパティゲッターも持たなければなりません。

操作で宣言する特殊操作は可変長や オプション引数を持ってはなりません。

オブジェクトが、同じ特殊操作を定義する複数のインターフェースを実装する場合、その操作でどちらの特殊操作が呼ばれるかは未定義です。

2.5.6.1. インデックス付きプロパティ

インデックス付きプロパティゲッター を定義する インターフェイス は、インデックス付きプロパティをサポートすると言います。 拡張として、プラットフォームオブジェクト は、インターフェイスを 実装している場合、そのインターフェイスがインデックス付きプロパティをサポートしていれば インデックス付きプロパティをサポートすると言います。

もしインターフェイスがインデックス付きプロパティをサポートする 場合、インターフェイス定義には オブジェクトがどのインデックスでインデックス可能かという説明が伴わなければなりません。 これらのインデックスはサポートされるプロパティインデックスと呼ばれます。

インデックス付きプロパティをサポートするインターフェイスは、 "length" という名前の 整数型 属性を定義しなければなりません。

インデックス付きプロパティゲッターは 一つの unsigned long 引数を取るように宣言されなければなりません。 インデックス付きプロパティセッターは 二つの引数を取り、最初の引数が unsigned long でなければなりません。

interface interface_identifier {
  getter type identifier(unsigned long identifier);
  setter type identifier(unsigned long identifier, type identifier);

  getter type (unsigned long identifier);
  setter type (unsigned long identifier, type identifier);
};

インデックス付きプロパティゲッターとセッターの定義には以下の要件が適用されます:

もしインデックス付きプロパティゲッターや セッター がオペレーションと 識別子を使って指定された場合、 オブジェクトをサポートされるプロパティインデックスではない 整数でインデックス付けしても、 そのオペレーションでそのインデックスを渡して呼び出した場合と同じ挙動になるとは限りません。実際の挙動は言語バインディングによって異なります。

JavaScriptの言語バインディングでは、通常のプロパティ検索が行われます。例えば、次のIDLを考えます:

[Exposed=Window]
interface A {
  getter DOMString toWord(unsigned long index);
};

Aを実装するオブジェクトが サポートされるプロパティインデックス として 0 ≤ index < 2 の範囲を持つとします。また toWordは引数を英語の単語に変換して返すとします。 範囲外のインデックスでオペレーションを呼び出した場合の挙動と、オブジェクトを直接インデックス付けした場合の挙動は異なります:

var a = getA();

a.toWord(0);  // "zero" が評価される。
a[0];         // これも "zero" が評価される。

a.toWord(5);  // "five" が評価される。
a[5];         // プロパティ "5" が存在しないため undefined になる。

次のIDLフラグメントは OrderedMap インターフェイスを定義しており、 名前やインデックス番号による値の取得・設定を可能にします:

[Exposed=Window]
interface OrderedMap {
  readonly attribute unsigned long size;

  getter any getByIndex(unsigned long index);
  setter undefined setByIndex(unsigned long index, any value);

  getter any get(DOMString name);
  setter undefined set(DOMString name, any value);
};

すべての特殊操作が識別子付きオペレーションで宣言されているため、 必要な追加の説明はキー集合に関するものだけです。 get() オペレーションが、 OrderedMap で存在しないエントリを検索した場合は null を返すと定義されているなら、次の2文で十分です:

OrderedMap を実装するオブジェクト map は、 0 ≤ index < map.size の範囲のインデックスで インデックス付きプロパティをサポートします。

また、get() に渡して非null値が返る名前ごとに 名前付きプロパティもサポートします。

§ 3.9 レガシープラットフォームオブジェクトで説明されている通り、 JavaScriptの実装では レガシープラットフォームオブジェクトで OrderedMap を実装する場合、 名前付き・インデックス付き両方のプロパティ集合に対応した プロパティが作成されます。 これらのプロパティを使って、オブジェクトのメソッドを呼び出す場合と同様に オブジェクトとやり取りできます。以下の例を参照ください:

// map は OrderedMap インターフェイスを実装するレガシープラットフォームオブジェクトと仮定する。
var map = getOrderedMap();
var x, y;

x = map[0];       // map.length > 0 の場合、これは次と等価:
                  //
                  //   x = map.getByIndex(0)
                  //
                  // "0" というプロパティが map に作成されているため。
                  // それ以外では "0" プロパティが存在せず undefined になる。

map[1] = false;   // 次と等価:
                  //
                  //   map.setByIndex(1, false)

y = map.apple;    // "apple" という名前付きプロパティが存在する場合、
                  // 次と等価:
                  //
                  //   y = map.get('apple')
                  //
                  // "apple" プロパティが map に作成されているため。
                  // 存在しなければ undefined になる。

map.berry = 123;  // 次と等価:
                  //
                  //   map.set('berry', 123)

delete map.cake;  // "cake" という名前付きプロパティが存在する場合、
                  // その "cake" プロパティが削除され、次と等価な処理が行われる:
                  //
                  //   map.remove("cake")
2.5.6.2. 名前付きプロパティ

名前付きプロパティゲッター を定義する インターフェイス は、名前付きプロパティをサポートすると言います。 拡張として、プラットフォームオブジェクト は、そのオブジェクトが インターフェイス を実装し、そのインターフェイス自体が名前付きプロパティをサポートしている場合、 名前付きプロパティをサポートすると言います。

もしインターフェイスが名前付きプロパティをサポートする 場合、インターフェイス定義には オブジェクトをインデックス付けするために任意の時点で利用できる名前の順序付き集合の説明が伴わなければなりません。 これらの名前は サポートされるプロパティ名 と呼ばれます。

名前付きプロパティゲッターおよびデリーターは 一つの DOMString 引数を取るように宣言されなければなりません。 名前付きプロパティセッターは 二つの引数を取り、最初の引数が DOMString でなければなりません。

interface interface_identifier {
  getter type identifier(DOMString identifier);
  setter type identifier(DOMString identifier, type identifier);
  deleter type identifier(DOMString identifier);

  getter type (DOMString identifier);
  setter type (DOMString identifier, type identifier);
  deleter type (DOMString identifier);
};

名前付きプロパティゲッター・セッター・デリーターの定義には以下の要件が適用されます:

注: インデックス付きプロパティと同様に、 名前付きプロパティゲッター、 セッター または デリーター がオペレーションと 識別子を使って指定された場合、 オブジェクトを サポートされるプロパティ名ではない 名前でインデックス付けしても、 そのオペレーションでその名前を渡して呼び出した場合と同じ挙動になるとは限りません。 挙動は言語バインディングによって異なります。

2.5.7. 静的属性および操作

静的属性 および 静的操作 とは、 宣言された インターフェイス の特定のインスタンスには関連付けられず、インターフェイス自体に関連付けられるものです。 静的属性および操作は宣言に static キーワードを使用して宣言されます。

静的操作や静的属性をインターフェイスのインスタンス参照を通じて呼び出すことができるかどうかは、言語バインディングごとに異なります。

StaticMember ::
    static StaticMemberRest
StaticMemberRest ::
    OptionalReadOnly AttributeRest
    RegularOperation

次のIDLフラグメントは Circle インターフェイスを定義しており、 その上に静的操作が宣言されています:

[Exposed=Window]
interface Point { /* ... */ };

[Exposed=Window]
interface Circle {
  attribute double cx;
  attribute double cy;
  attribute double radius;

  static readonly attribute long triangulationCount;
  static Point triangulate(Circle c1, Circle c2, Circle c3);
};

JavaScript言語バインディングでは、関数オブジェクト triangulate および triangulationCount のアクセサプロパティは インターフェイスオブジェクト Circle 上に存在します:

var circles = getCircles();           // Circle オブジェクトの配列

typeof Circle.triangulate;            // "function" と評価される
typeof Circle.triangulationCount;     // "number" と評価される
Circle.prototype.triangulate;         // undefined となる
Circle.prototype.triangulationCount;  // これも undefined となる
circles[0].triangulate;               // こちらも同様
circles[0].triangulationCount;        // これも同じ

// 静的操作の呼び出し
var triangulationPoint = Circle.triangulate(circles[0], circles[1], circles[2]);

// 何回三角測量を行ったか調べる
window.alert(Circle.triangulationCount);

2.5.8. オーバーロード

インターフェイス上に定義された 通常の操作 または 静的操作 が、同じ種類(通常または静的)の操作として同じ 識別子を持つ別の操作と重複している場合、 その操作は オーバーロードされていると言います。 オーバーロードされた操作の識別子を使って、 インターフェイスを実装するオブジェクト上で操作を呼び出した場合、 渡された引数の数や型によって、どのオーバーロードされた操作が実際に呼び出されるかが決定されます。 コンストラクタ操作も オーバーロード可能です。 オーバーロードされた操作やコンストラクタが取ることができる引数にはいくつか制約があり、 これらの制約を説明するために 有効なオーバーロード集合 という概念が使われます。

オーバーロードされた 操作の集合は、次のいずれかでなければなりません:

操作は インターフェイス、 部分インターフェイス、 インターフェイスミックスイン、 部分インターフェイスミックスイン の定義をまたいでオーバーロードしてはなりません。

例えば、f と g の両方のオーバーロードは許可されません:

[Exposed=Window]
interface A {
  undefined f();
};

partial interface A {
  undefined f(double x);
  undefined g();
};

partial interface A {
  undefined g(DOMString x);
};

コンストラクタ操作や [LegacyFactoryFunction] 拡張属性は 部分インターフェイス の定義に現れることは許可されていないため、コンストラクタのオーバーロードを禁止する必要はありません。

有効なオーバーロード集合は、 特定の操作、 コンストラクタ操作 または [LegacyFactoryFunction]、 コールバック関数 の許容される呼び出しを表します。 有効なオーバーロード集合を計算するアルゴリズムは、 以下の4種類のIDL構成要素のいずれかに対して動作し、必要な入力は以下の通りです。

通常の操作の場合
静的操作の場合
コンストラクタの場合
レガシーファクトリ関数の場合

有効なオーバーロード集合は、インターフェイス上で指定されたオーバーロード操作やコンストラクタに 曖昧さがないかどうかなどを判断するために使われます。

項目は 有効なオーバーロード集合の タプルであり、 (呼び出し可能, 型リスト, オプショナリティリスト) という形式です。それぞれの 項目は以下の通りです:

各タプルは、 その操作・コンストラクタ・コールバック関数を、指定された型の引数値リストで呼び出せることを表します。 オプション引数 や 可変長操作・コンストラクタにより、 同じ操作やコンストラクタを識別する 有効なオーバーロード集合に 複数の項目が含まれる場合があります。

以下は 有効なオーバーロード集合を計算する アルゴリズムです。必要に応じて次の入力変数を使います:

拡張属性の引数について言及される場合、それは拡張属性の 名前付き引数リストの引数を指します。

  1. S を 順序付き集合とする。

  2. F を 順序付き集合とし、 項目は 有効なオーバーロード集合の種類ごとに以下とする:

    通常の操作の場合

    Fの要素は、インターフェイスI上に識別子Aで定義された 通常の操作です。

    静的操作の場合

    Fの要素は、インターフェイスI上に識別子Aで定義された 静的操作です。

    コンストラクタの場合

    Fの要素は インターフェイスI上の コンストラクタ操作 です。

    レガシーファクトリ関数の場合

    Fの要素は、インターフェイスI上の [LegacyFactoryFunction] 拡張属性であり、 名前付き引数リストの識別子がAであるものです。

  3. maxargを、F内の操作・レガシーファクトリ関数・コールバック関数が宣言で取る最大の引数数とする。 可変長操作やレガシーファクトリ関数では、 エリプシスが付く引数も1つとして数える。

    注: undefined f(long x, long... y); は2引数とみなされる。

  4. max = max(maxarg, N) とする。

  5. 各操作または拡張属性Xについて、F内で:

    1. argumentsを、Xが宣言で取る引数の リストとする。

    2. nを、argumentsの サイズ とする。

    3. typesを 型リストとする。

    4. optionalityValuesを オプショナリティリストとする。

    5. 各 argument について、arguments内で:

      1. types に argument の型を追加。

      2. optionalityValues に argument が最後の可変長引数なら "variadic"、 optional なら "optional"、 それ以外は "required" を追加。

    6. S に タプル (X, types, optionalityValues) を追加。

    7. もしXが 可変長として宣言されていれば:

      1. それぞれについて i は、範囲 n から max まで(上限を含まない):

        1. tを 型リストとする。

        2. oを オプショナリティリストとする。

        3. それぞれについて j は、範囲 0 から n まで、 上限を含まない:

          1. t に types[j] を追加。

          2. o に optionalityValues[j] を追加。

        4. それぞれについて j は、範囲 n から i まで、 上限を含む:

          1. t に types[n − 1] を追加。

          2. o に "variadic" を追加。

        5. S に タプル (X, t, o) を追加。

    8. i = n − 1 とする。

    9. i ≥ 0 の間:

      1. もし arguments[i] が optional でなければ ("optional"もしくは最後の可変長引数でなければ)、break。

      2. tを 型リストとする。

      3. oを オプショナリティリストとする。

      4. それぞれについて j は、範囲 0 から i まで、 上限を含まない:

        1. t に types[j] を追加。

        2. o に optionalityValues[j] を追加。

      5. S に タプル (X, t, o) を追加。

        注: i が 0 の場合、 S に (X, « », « ») を追加することになる ("« »" は 空リストを表す)。

      6. i = i − 1 とする。

  6. S を返す。

次のインターフェイスについて:

[Exposed=Window]
interface A {
  /* f1 */ undefined f(DOMString a);
  /* f2 */ undefined f(Node a, DOMString b, double... c);
  /* f3 */ undefined f();
  /* f4 */ undefined f(Event a, DOMString b, optional DOMString c, double... d);
};

NodeとEventがどちらも実装できるオブジェクトが存在しない2つのインターフェイスであると仮定すると、 識別子fの通常の操作の 引数数4に対する有効なオーバーロード集合は次の通りです:

«
  (f1, « DOMString »,                           « required »),
  (f2, « Node, DOMString »,                     « required, required »),
  (f2, « Node, DOMString, double »,             « required, required, variadic »),
  (f2, « Node, DOMString, double, double »,     « required, required, variadic, variadic »),
  (f3, « »,                                     « »),
  (f4, « Event, DOMString »,                    « required, required »),
  (f4, « Event, DOMString, DOMString »,         « required, required, optional »),
  (f4, « Event, DOMString, DOMString, double », « required, required, optional, variadic »)
»

2つの型は、次のアルゴリズムがtrueを返す場合、 識別可能と言います。

  1. 一方の型がnullable型を含み、 もう一方もnullable型を含むか、 ユニオン型であり フラット化されたメンバー型が 辞書型を含むか、 辞書型なら、 falseを返す。

    次のペアはどれも識別できません:
  2. 両方の型がユニオン型またはnullableなユニオン型なら、 一方の各メンバー型が他方の各メンバー型と識別可能であればtrue、そうでなければfalseを返す。

  3. 一方の型がユニオン型またはnullableなユニオン型なら、 そのユニオン型の各 メンバー型 が非ユニオン型と識別可能であればtrue、そうでなければfalseを返す。

  4. 各型のinner type が注釈付き型ならそれを取り、 さらにinner typeがnullable型ならそれを取った2つの「最も内側の型」を考える。 これら2つの型が次の表に現れるかカテゴリに属し、対応する欄に「●」があるか、文字があり追加要件を満たすならtrueを返す。 そうでなければfalseを返す。

    カテゴリ:

    interface-like
    dictionary-like
    sequence-like
    undefined
    boolean
    numeric types
    bigint
    string types
    object
    symbol
    interface-like
    callback function
    dictionary-like
    async sequence
    sequence-like
    undefined ● ● ● ● ● ● ● ● ● ●
    boolean ● ● ● ● ● ● ● ● ● ●
    numeric types (b) ● ● ● ● ● ● ● ●
    bigint ● ● ● ● ● ● ● ●
    string types ● ● ● ● ● (d) ●
    object ●
    symbol ● ● ● ● ●
    interface-like (a) ● ● ● ●
    callback function (c) ● ●
    dictionary-like ● ● ●
    async sequence
    sequence-like
    1. 識別された2つのinterface-like型が同じでなく、どのプラットフォームオブジェクトも両方の型を実装しない場合。

    2. 型は識別可能だが、オーバーロードでの利用には別の制約があり、 これら型のユニオン利用についての助言も参照。

    3. コールバック関数が [LegacyTreatNonObjectAsNull] 拡張属性を持たない場合、辞書型カテゴリの型と識別可能。

      例えば、ECMAScript値から コールバック関数と辞書型を含む ユニオン型に変換する場合、 値がcallableなら コールバック関数に変換し、それ以外は辞書型に変換される。
    4. 型は識別可能だが、ECMAScript値から変換する際、 文字列オブジェクトは 非同期シーケンスタイプ には変換されない(%Symbol.iterator%メソッドがあっても)。 文字列型がオーバーロード集合やユニオンに含まれる場合の規則です。

    double と DOMString は、numeric型とstring型の交差点に●があるので識別可能です。
    double と longは、 両方ともnumeric型で、numeric型とnumeric型の交差点に●や文字がないため識別できません。
    例:
    callback interface CBIface {
        undefined handle();
    };
    
    [Exposed=Window]
    interface Iface {
        attribute DOMString attr2;
    };
    
    dictionary Dict {
        DOMString field1;
    };
    

    CBIfaceはIfaceとは識別可能ですが(dictionary-likeとinterface-likeの交差点に●があるため)、 Dictとは識別できません(dictionary-like同士の交差点に●がないため)。

    Promise型は上記の表に現れず、 他の型とは識別できません。

有効なオーバーロード集合に 型リストサイズが同じ 項目が複数ある場合、 それらの項目について、各ペアの型リストのインデックスiの型が 識別可能である 必要がある。 この最も小さいインデックスを、 識別引数インデックス と呼び、これはその型リストサイズを持つ有効なオーバーロード集合の項目に対するインデックスである。

有効なオーバーロード集合には、 型リストサイズが同じ 項目が 2つ以上含まれてはならず、 そのうち一方の項目の 識別引数インデックス位置に bigint 型の引数があり、 他方にはnumeric型の引数が識別引数インデックス位置にある場合は不可。

前述の有効なオーバーロード集合では、 型リストサイズ2, 3, 4に複数の項目があります。 これらの型リストサイズに対し、 識別引数インデックスは0です。 NodeとEventは 識別可能だからです。

次のようなオーバーロードの利用は無効です:

[Exposed=Window]
interface B {
  undefined f(DOMString x);
  undefined f(USVString x);
};

DOMString と USVString は識別できないためです。

さらに、型リストサイズが同じアイテム群について、 識別引数インデックスより小さい各インデックスjにおいて、 すべての型リストの型は同じであり、 すべてのオプショナリティリストのインデックスjのオプショナリティ値も同じでなければなりません。

次は無効です:

[Exposed=Window]
interface B {
  /* f1 */ undefined f(DOMString w);
  /* f2 */ undefined f(long w, double x, Node y, Node z);
  /* f3 */ undefined f(double w, double x, DOMString y, Node z);
};

引数数4の場合の有効なオーバーロード集合:

«
  (f1, « DOMString »,                       « required »),
  (f2, « long, double, Node, Node »,        « required, required, required, required »),
  (f3, « double, double, DOMString, Node », « required, required, required, required »)
»

型リストサイズ4のアイテム群を見ると、 識別引数インデックスは2です。 Nodeと DOMString が識別可能だからです。 しかし、これら2つのオーバーロードの0番目の引数が異なるため、オーバーロードは無効です。

2.5.8.1. オーバーロードとユニオン型の違い

この節は参考情報です。

IDLの操作を定義する仕様において、オーバーロードとユニオン型やオプション引数の組み合わせには、機能的な重なりがあるように見えるかもしれません。

まず重要なのは、オーバーロードはユニオン型やオプション引数と異なる挙動を持ち、 どちらか一方で完全に定義することはできません(もちろん追加の記述を加えることでWeb IDL型システムの意義が失われる場合を除く)。 例えば、stroke() 操作がCanvasDrawPath インターフェイスに定義されている場合を考えます [HTML]:

interface CanvasDrawPathExcerpt {
  undefined stroke();
  undefined stroke(Path2D path);
};

JavaScript言語バインディングでは、stroke(undefined)を CanvasDrawPathExcerptを実装するオブジェクト上で呼び出すと、2番目のオーバーロードが呼ばれ、 undefinedはPath2Dに変換できないため TypeError となります。 しかし、操作がオプション引数で統合されていた場合、

interface CanvasDrawPathExcerptOptional {
  undefined stroke(optional Path2D path);
};

オーバーロード解決アルゴリズムは path引数が未指定とみなし、例外を投げません。

注: この例では、後者の挙動がWeb開発者の期待に沿っています。 CanvasDrawPath が現在設計されるなら、オプション引数でstroke()が定義されるでしょう。

さらに、意味論的な違いもあります。ユニオン型は通常「どの型でもほぼ同じように動作する」場合に使われますが、 オーバーロード操作はC++のオーバーロードのような言語機能に適合しやすく、 異なる型の引数で本質的に異なる挙動を持つ操作に向いています。 とはいえ、そうした操作はJavaScript言語では明示的なオーバーロードがないため、混乱を避けるためにも別名の操作にしたほうが良い場合が多いです。 そのため、オーバーロードは新しいAPIにはほとんど適さず、レガシーAPIや特殊な事情で現れることが多いです。

以下に、どのWeb IDL言語機能を使うべきか迷った場合の推奨例を挙げます:

上記のいずれにも当てはまらない場合は、仕様作成者がスタイルを選択できますが、たいていどちらでも十分に意図した挙動を記述できます。 ただし、変換アルゴリズムを含め、ユニオン型やオプション引数の方が オーバーロードの定義と変換アルゴリズムより 実装・理解が容易であり、JavaScriptのAPIにもより適しています。 したがって特別な事情がなければ、ユニオン型やオプション引数、またはその両方がデフォルトの選択肢です。

仕様では、ユニオン型とオーバーロードを混ぜて使うことも自由です。適切かつ便利と思えばそのようにしてください。

2.5.9. イテラブル宣言

インターフェイスは、インターフェイス本体内で イテラブル をイテラブル宣言 (Iterableに合致)を使って宣言できます。

interface interface_identifier {
  iterable<value_type>;
  iterable<key_type, value_type>;
};

イテラブルとして宣言されたインターフェイスを実装するオブジェクトは、値の列として反復処理(イテレーション)できます。

注: JavaScript言語バインディングでは、イテラブルなインターフェイスは entries, forEach, keys, values, %Symbol.iterator% プロパティをインターフェイスプロトタイプオブジェクト上に持ちます。

型パラメータが1つだけ指定されている場合、そのインターフェイスは 値イテレータとなり、指定された型の値を提供します。 型パラメータが2つ指定されている場合、そのインターフェイスは ペアイテレータとなり、 指定された型の値ペアを提供します。

値ペアとは、キー型と値型が与えられた場合、 2つの構造体アイテムを持つ アイテムのことです:

  1. アイテムの名前が"key"で、 値ペアの キーと呼ばれ、値はキー型のIDL値です。

  2. アイテムの名前が"value"で、 値ペアの 値と呼ばれ、値は値型のIDL値です。

値イテレータは、必ず インデックス付きプロパティをサポートする インターフェイスにのみ宣言できます。 この値イテレータの値型は、 インデックス付きプロパティゲッターが返す型と同じでなければなりません。 値イテレータは、 オブジェクトのインデックス付きプロパティをイテレートするものとして暗黙的に定義されます。

ペアイテレータは、 インデックス付きプロパティをサポートする インターフェイスには宣言できません。

ペアイテレータを持つインターフェースに付随する説明文では、 インターフェースの各インスタンスごとに リストとして 値ペアを定義する必要があります。 このリストがイテレートする値ペアです。

JavaScriptで値イテレータ用に生成されるforEachメソッドはArray.prototype.forEachのようにコールバックを呼び、 ペアイテレータ用forEachはMap.prototype.forEachのようにコールバックを呼びます。

値イテレータは現状 インデックス付きプロパティをサポートする インターフェイスだけで許されていますので、ArrayライクなforEachが理にかなっています。 値イテレータが (a) インデックス付きプロパティをサポートしないインターフェイス上に必要な場合や、 (b) Set.prototype.forEachのようにキーと値が同じになるforEachを必要とする場合があります。 そうしたAPIが必要なら issueを提出 してください。

注: これは配列イテレータオブジェクトの仕組みです。 インデックス付きプロパティをサポートするインターフェイスでは、 entries, keys, values, %Symbol.iterator% が返すイテレータオブジェクトは実際に配列イテレータオブジェクトです。

イテラブル宣言を持つ インターフェイスは entries, forEach, keys, valuesという名前の 属性、 定数、 通常の操作を持ってはならず、 またこれらの名前の属性、定数、通常の操作を持つ継承インターフェイスを持ってもいけません。

次のSessionManagerインターフェイスは、ユーザー名でキーされる複数のSessionオブジェクトにアクセスできます:

[Exposed=Window]
interface SessionManager {
  Session getSessionForUser(DOMString username);

  iterable<DOMString, Session>;
};

[Exposed=Window]
interface Session {
  readonly attribute DOMString username;
  // ...
};

イテレータの挙動は次のように定義できます:

イテレートすべき値ペアは、 値ペアのリストで、 キーがユーザー名、 値が そのユーザー名に対応するSessionオブジェクト(開いているもの)で、 ユーザー名でソートされます。

JavaScript言語バインディングでは、SessionManagerインターフェイスの インターフェイスプロトタイプオブジェクト にはvaluesメソッド(関数)があり、呼び出すとイテレータオブジェクトを返し、 そのイテレータオブジェクトにはnextメソッドがあり、次の値を返します。 keysやentriesメソッドはセッションオブジェクトのユーザー名やユーザー名/Sessionペアをイテレートします。 %Symbol.iterator% もあり、for..ofループでentriesと同じ値を使えます:

// SessionManagerのインスタンスを取得
// "anna"と"brian"の2ユーザーのセッションがあると仮定
var sm = getSessionManager();

typeof SessionManager.prototype.values;            // "function"と評価される
var it = sm.values();                              // values()はイテレータオブジェクトを返す
String(it);                                        // "[object SessionManager Iterator]"と評価される
typeof it.next;                                    // "function"と評価される

// このループは"anna"と"brian"を順に出力
for (;;) {
  let result = it.next();
  if (result.done) {
    break;
  }
  let session = result.value;
  console.log(session.username);
}

// このループも"anna"と"brian"を順に出力
for (let username of sm.keys()) {
  console.log(username);
}

// もう1つの方法
for (let [username, session] of sm) {
  console.log(username);
}

インターフェイスは複数のイテラブル宣言を持ってはなりません。 イテラブル宣言を持つインターフェイスの 継承インターフェイスもイテラブル宣言を持ってはなりません。 イテラブル宣言を持つインターフェイスおよびその継承インターフェイスは、 maplike宣言、 setlike宣言、 非同期イテラブル宣言を持ってはなりません。

次の拡張属性はイテラブル宣言に適用できます: [CrossOriginIsolated]、 [Exposed]、 [SecureContext]。

Iterable ::
    iterable < TypeWithExtendedAttributes OptionalType > ;
OptionalType ::
    , TypeWithExtendedAttributes
    ε

2.5.10. 非同期イテラブル宣言

インターフェイスは、 ボディ内で 非同期イテラブル宣言 (AsyncIterable に一致) を使用することで、 非同期で繰り返し可能であると宣言できます。 この宣言は インターフェイス の中で行います。

interface interface_identifier {
  async_iterable<value_type>;
  async_iterable<value_type>(/* arguments... */);
  async_iterable<key_type, value_type>;
  async_iterable<key_type, value_type>(/* arguments... */);
};

インターフェイスを非同期イテラブルとして宣言した場合、 それを実装するオブジェクトは値の列を非同期にイテレートできます。

型パラメータが1つだけの場合、そのインターフェイスは 値非同期イテラブル宣言となり、指定した型の値を非同期で提供します。 型パラメータが2つの場合、そのインターフェイスは ペア非同期イテラブル宣言となり、指定した型の 値ペアを非同期で提供します。

引数が指定されている場合、非同期イテラブル宣言の引数(ArgumentListに合致)はすべて オプション引数でなければなりません。

JavaScript言語バインディングでは、非同期イテラブルなインターフェイスは %Symbol.asyncIterator% とvaluesプロパティを インターフェイスプロトタイプオブジェクト上に持ちます。 ペア非同期イテラブル宣言の場合はentriesおよびkeysも追加されます。 これらのメソッドは非同期イテラブル宣言の引数リストに対応するオプション引数を受け取ることができ、 非同期イテレータ初期化手順(あれば)で処理されます。

この要件により、JavaScriptバインディングでfor-await-ofが直接使えるようになります。 for-await-ofは、引数無しで %Symbol.asyncIterator% メソッドを呼び出します。

非同期イテラブル宣言を持つインターフェイスには、 次のイテレーション結果を取得する アルゴリズムを定義する必要があります。 このアルゴリズムは、イテレートされるインターフェイスのインスタンスと、非同期イテレータ自身(状態保存などに利用可能)を受け取ります。 戻り値はPromiseであり、rejectされるか、 イテレーション終了のための特別なイテレーション終了値で解決するか、 以下のいずれかで解決します:

値非同期イテラブル宣言の場合:

宣言で指定した型の値

ペア非同期イテラブル宣言の場合:

宣言で指定した型の値2つからなるタプル

記述には、非同期イテレータreturnアルゴリズムを定義してもよいです。 このアルゴリズムは、イテレートされるインターフェイスのインスタンス・非同期イテレータ自身・any型の値1つを受け取ります。 非同期イテレータの途中終了時に呼ばれ、Promiseを返します。 Fulfillされた場合、値は無視され、Rejectされた場合はAPI利用側に伝播します。

JavaScriptバインディングでは、このアルゴリズムでasync iteratorのreturn()メソッド呼び出し時の挙動をカスタマイズできます。 breakやreturnでfor-await-ofループから抜ける時などに使われます。

同様のthrow()用フックも追加可能です。現状需要はありませんが、必要なら issueを提出してください。

記述には非同期イテレータ初期化手順も定義できます。 これらは、イテレートされるインターフェイスのインスタンス・新規作成されたイテレータオブジェクト・渡された引数(IDL値のリスト)を受け取ります。

非同期イテラブル宣言を持つインターフェイスは、 entries, keys, valuesという名前の 属性、 定数、 通常の操作を持ってはならず、 またこれらの名前の属性、定数、通常の操作を持つ継承インターフェイスも持ってはなりません。

次のSessionManagerインターフェイスは、ユーザー名でキーされる複数のSessionオブジェクトにアクセスできます:

[Exposed=Window]
interface SessionManager {
  Session getSessionForUser(DOMString username);

  async_iterable<DOMString, Session>;
};

[Exposed=Window]
interface Session {
  readonly attribute DOMString username;
  // ...
};

イテレータの挙動は次のように定義できます:

SessionManager非同期イテレータiteratorの 非同期イテレータ初期化手順:

  1. iteratorの現在状態を「まだ開始されていない」に設定。

SessionManagerのmanagerとその非同期イテレータiteratorの 次のイテレーション結果を取得する:

  1. promise を新しい promise とする。

  2. key を次の値(該当すれば)、そうでなければ null とする:

    もし iterator の current state が "not yet started" である場合

    manager の open sessions における、辞書順で最も小さい username

    それ以外の場合

    manager の open sessions における、iterator の current state より大きい username のうち、辞書順で最も小さいもの

    注: iterator の current state は、open sessions に存在しなくなっている場合があります。

  3. key が null なら:

    1. promise を end of iteration で解決する。

  4. それ以外の場合:

    1. session を key に対応する Session オブジェクトとする。

    2. promise を (username, session) で解決する。

    3. iterator の current state を username に設定する。

  5. promise を返す。

JavaScript言語バインディングでは、SessionManagerインターフェイスの インターフェイスプロトタイプオブジェクト には valuesメソッド(関数)があり、呼び出すと非同期イテレータオブジェクトを返し、 そのイテレータオブジェクトにはnextメソッドがある。 keys・entriesはセッションオブジェクトのユーザー名や(username, Session)ペアをイテレートする。 %Symbol.asyncIterator% もあり、for await..ofループでentriesと同じ値を使える:

// SessionManagerのインスタンスを取得
// "anna"と"brian"の2ユーザーのセッションがあると仮定
var sm = getSessionManager();

typeof SessionManager.prototype.values;            // "function"と評価される
var it = sm.values();                              // values()はイテレータオブジェクトを返す
typeof it.next;                                    // "function"と評価される

// このループは"anna"と"brian"を順に出力
for await (let username of sm.keys()) {
  console.log(username);
}

// もう1つの方法
for await (let [username, session] of sm) {
  console.log(username);
}

インターフェイスは複数の 非同期イテラブル宣言を持ってはなりません。 非同期イテラブル宣言を持つインターフェイスの 継承インターフェイスも非同期イテラブル宣言を持ってはなりません。 非同期イテラブル宣言を持つインターフェイス及びその継承インターフェイスは、 maplike宣言、 setlike宣言、 イテラブル宣言を持ってはなりません。

次の拡張属性は非同期イテラブル宣言に適用できます: [CrossOriginIsolated]、 [Exposed]、 [SecureContext]。

これらの拡張属性は現時点では考慮されていません。 今後考慮される場合は、期待通りの効果となります。

AsyncIterable ::
    async_iterable < TypeWithExtendedAttributes OptionalType > OptionalArgumentList ;
OptionalArgumentList ::
    ( ArgumentList )
    ε

2.5.11. maplike宣言

インターフェイスは、 インターフェイス本体内で maplike をmaplike宣言 (ReadWriteMaplike または readonly MaplikeRest) を使って宣言できます。

interface interface_identifier {
  readonly maplike<key_type, value_type>;
  maplike<key_type, value_type>;
};

maplikeとして宣言されたインターフェイスを実装するオブジェクトは、 最初は空の順序付きマップ(key–valueペア)を表します。 これはそのオブジェクトのマップエントリです。 キーと値の型はmaplike宣言の山括弧内で指定されます。キーは一意でなければなりません。

仕様策定者はマップエントリの内容を変更できます。 この変更はJavaScriptコードからオブジェクトの内容を観測した時にも自動的に反映されます。

maplikeインターフェイスは、言語バインディングに応じてマップエントリの問い合わせAPIをサポートします。 readonlyキーワードが使われていない場合は、マップエントリの変更APIもサポートします。

注: JavaScript言語バインディングでは、 マップエントリ操作APIはJavaScriptの Map オブジェクトに似ています。 readonlyキーワードの場合はentries、 forEach、get、 has、keys、 values、 %Symbol.iterator% メソッド、およびsizeゲッターが含まれます。 読み書き可能なmaplikeにはさらにclear、 delete、setメソッドも含まれます。

maplikeインターフェイスは、属性、定数、通常の操作で "entries", "forEach", "get", "has", "keys", "size", "values" という名前を持つものを持ってはならず、 また、これらの名前を持つ属性、定数、通常の操作を持つ継承インターフェイスも持てません。

読み書き可能なmaplikeインターフェイスは、 属性や 定数で "clear", "delete", "set" という名前を持つものを持ってはならず、 また、これらの名前を持つ属性、定数を持つ継承インターフェイスも持てません。

注: 読み書き可能なmaplikeインターフェイスは 通常の操作として "clear", "delete", "set"の名前を持つことができ、 これらはデフォルト実装(§ 3.7.11 maplike宣言で定義)を上書きします。 その場合、入力・出力仕様はデフォルト実装セクションの期待と一致させる必要があります。

インターフェイスは複数の maplike宣言 を持ってはなりません。 maplikeインターフェイスの継承インターフェイスも maplike宣言を持ってはなりません。 maplikeインターフェイスとその継承インターフェイスは、 イテラブル宣言、 非同期イテラブル宣言、 setlike宣言、 インデックス付きプロパティゲッター を持ってはなりません。

ReadOnlyMember ::
    readonly ReadOnlyMemberRest
ReadOnlyMemberRest ::
    AttributeRest
    MaplikeRest
    SetlikeRest
ReadWriteMaplike ::
    MaplikeRest
MaplikeRest ::
    maplike < TypeWithExtendedAttributes , TypeWithExtendedAttributes > ;

この仕様で定義された拡張属性は、 maplike宣言 には適用できません。

例を追加。

2.5.12. setlike宣言

インターフェイスは、 インターフェイス本体内で setlike をsetlike宣言 (ReadWriteSetlike または readonly SetlikeRest) を使って宣言できます。

interface interface_identifier {
  readonly setlike<type>;
  setlike<type>;
};

setlikeとして宣言されたインターフェイスを実装するオブジェクトは、 最初は空の順序付き集合(値のセット)を表します。 これはそのオブジェクトのセットエントリです。 値の型はsetlike宣言の山括弧内で指定されます。値は一意でなければなりません。

仕様策定者はセットエントリの内容を変更できます。 この変更はJavaScriptコードからオブジェクトの内容を観測した時にも自動的に反映されます。

setlikeインターフェイスは、言語バインディングに応じてセットエントリの問い合わせAPIをサポートします。 readonlyキーワードが使われていない場合は、セットエントリの変更APIもサポートします。

注: JavaScript言語バインディングでは、 セットエントリ操作APIはJavaScriptの Set オブジェクトに似ています。 readonlyキーワードの場合はentries、 forEach、has、 keys、values、 %Symbol.iterator% メソッド、およびsizeゲッターが含まれます。 読み書き可能なsetlikeにはさらにadd、 clear、deleteメソッドも含まれます。

setlikeインターフェイスは、属性、定数、通常の操作で "entries", "forEach", "has", "keys", "size", "values" という名前を持つものを持ってはならず、 また、これらの名前を持つ属性、定数、通常の操作を持つ継承インターフェイスも持てません。

読み書き可能なsetlikeインターフェイスは、 属性や 定数で "add", "clear", "delete" という名前を持つものを持ってはならず、 また、これらの名前を持つ属性、定数を持つ継承インターフェイスも持てません。

注: 読み書き可能なsetlikeインターフェイスは 通常の操作として "add", "clear", "delete"の名前を持つことができ、 これらはデフォルト実装(§ 3.7.12 setlike宣言で定義)を上書きします。 その場合、入力・出力仕様はデフォルト実装セクションの期待と一致させる必要があります。

インターフェイスは複数の setlike宣言 を持ってはなりません。 setlikeインターフェイスの継承インターフェイスも setlike宣言を持ってはなりません。 setlikeインターフェイスとその継承インターフェイスは、 イテラブル宣言、 非同期イテラブル宣言、 maplike宣言、 インデックス付きプロパティゲッター を持ってはなりません。

ReadOnlyMember ::
    readonly ReadOnlyMemberRest
ReadOnlyMemberRest ::
    AttributeRest
    MaplikeRest
    SetlikeRest
ReadWriteSetlike ::
    SetlikeRest
SetlikeRest ::
    setlike < TypeWithExtendedAttributes > ;

この仕様で定義された拡張属性は、 setlike宣言 には適用できません。

例を追加。

2.6. 名前空間

名前空間は、グローバルなシングルトンと関連する振る舞いを宣言する定義(Namespaceに合致)です。

namespace identifier {
  /* namespace_members... */
};

名前空間は、名前空間メンバー(NamespaceMembersに合致)、 すなわち波括弧内で宣言された通常の操作、 読み取り専用 通常の属性、 定数の集合の仕様です。 これらの操作や属性が名前空間にパッケージ化された振る舞いを記述します。

インターフェイスと同様に、名前空間のIDLはpartial namespace定義(partial Namespaceに合致)によって複数に分割できます。 partial namespace定義の識別子は、名前空間定義の識別子と同じでなければなりません。 各partial namespace定義に現れるメンバーは全て、名前空間自身のメンバーとみなされます。

namespace SomeNamespace {
  /* namespace_members... */
};

partial namespace SomeNamespace {
  /* namespace_members... */
};

注: partial interface定義と同様、partial namespace定義は仕様編集上の補助を目的としており、 名前空間の定義を文書の複数のセクションや複数文書に分散できます。

メンバーの出現順は、JavaScriptバインディングにおけるプロパティの列挙で意味を持ちます。

インターフェイスや辞書型とは異なり、名前空間は型を生成しません。

この仕様で定義された拡張属性のうち、 [CrossOriginIsolated]、 [Exposed]、 [SecureContext] 拡張属性のみが名前空間に適用可能です。

名前空間は必ず [Exposed] 拡張属性を注釈しなければなりません。

Partial ::
    partial PartialDefinition
PartialDefinition ::
    interface PartialInterfaceOrPartialMixin
    PartialDictionary
    Namespace
Namespace ::
    namespace identifier { NamespaceMembers } ;
NamespaceMembers ::
    ExtendedAttributeList NamespaceMember NamespaceMembers
    ε
NamespaceMember ::
    RegularOperation
    readonly AttributeRest
    Const

以下のIDLフラグメントは 名前空間を定義しています。

namespace VectorUtils {
  readonly attribute Vector unit;
  double dotProduct(Vector x, Vector y);
  Vector crossProduct(Vector x, Vector y);
};

JavaScript実装では、グローバルなVectorUtilsデータプロパティが 単純なオブジェクト(プロトタイプは %Object.prototype%) となり、宣言された各操作の列挙可能なデータプロパティと、宣言された各属性の列挙可能なget専用アクセサを持ちます:

Object.getPrototypeOf(VectorUtils);                         // Object.prototype となる。
Object.keys(VectorUtils);                                   // ["dotProduct", "crossProduct"] となる。
Object.getOwnPropertyDescriptor(VectorUtils, "dotProduct"); // { value: <関数>, enumerable: true, configurable: true, writable: true } となる。
Object.getOwnPropertyDescriptor(VectorUtils, "unit");       // { get: <関数>, enumerable: true, configurable: true } となる。

2.7. 辞書型

辞書型は、 Dictionaryに合致する定義であり、 固定された順序付きの順序付きマップデータ型を定義するために使用されます。 このマップのエントリは、 辞書メンバーと呼ばれ、 キーは文字列で、 値は定義内で指定された特定の型となります。

dictionary identifier {
  /* dictionary_members... */
};

辞書インスタンスは、その言語固有の表現(例:対応するJavaScriptオブジェクト)への参照を保持しません。 たとえば、操作から辞書を返す場合は、 辞書の現在の値から新しいJavaScriptオブジェクトが作成されます。 また、操作が引数として辞書を受け取る場合は、 渡されたJavaScript値から一度だけ変換が行われ、辞書が作成されます。 辞書の変更は対応するJavaScriptオブジェクトには反映されず、逆も同様です。

辞書型は属性や定数の型として使用してはなりません。

辞書型は、他の辞書型から継承するように定義できます。 辞書型の識別子の後にコロンと識別子が続く場合、 その識別子が継承元の辞書型を表します。識別子は必ず辞書型を指す必要があります。

辞書型は、その継承階層に循環があってはなりません。 つまり、辞書型Aが自分自身を継承してはならず、 また他の辞書型BがAを継承し、AがBを継承するような循環も不可です。

dictionary Base {
  /* dictionary_members... */
};

dictionary Derived : Base {
  /* dictionary_members... */
};

継承辞書型とは、 辞書型Dが直接または間接的に継承する全ての辞書型の集合です。 Dが他の辞書型を継承しなければ空集合です。 そうでなければ、Dが継承するEと、そのEの 継承辞書型も含みます。

辞書メンバーは 必須 として指定できます。言語固有値を辞書型に変換する際、そのメンバーの値を必ず指定する必要があります。 必須でない辞書メンバーは オプション です。

辞書メンバーを必須と指定しても、 それが観測可能になるのは他の表現(例えば操作の引数としてJavaScript値を渡す場合)をIDL辞書型に変換するときのみです。 仕様策定者は、辞書型が操作の戻り値としてのみ使われる場合などは、メンバーはすべて オプションにするべきです。

辞書型Dの値は、Dおよびその 継承辞書型 に定義された各辞書メンバーに対するエントリを持ちます。 必須メンバーや デフォルト値を持つメンバーには必ず対応する エントリが存在します。 それ以外のメンバーのエントリは辞書値に存在する場合としない場合があります。

JavaScriptバインディングでは、辞書メンバーに対応するプロパティの値がundefinedの場合、 そのプロパティが省略された場合と同じ扱いになります。 そのため、メンバーが必須ならエラーとなり、 デフォルト値があればそれが使われ、 それ以外はそのメンバーのエントリが辞書値に存在しません。

操作引数のデフォルト値と同様に、 boolean型 辞書メンバーのデフォルト値に trueを使うことは強く非推奨です。これは、undefinedのデフォルト変換として falseを期待する著者を混乱させるためです。 [API-DESIGN-PRINCIPLES]

文字列キーの順序付きマップは、 すべてのエントリが 辞書型Dの辞書メンバーに対応し、 それらの型が正しく、かつ必須またはデフォルト値付きメンバーに対応する エントリが存在すれば、暗黙的にその辞書型の値とみなされます。

dictionary Descriptor {
  DOMString name;
  sequence<unsigned long> serviceIdentifiers;
};

Descriptor辞書型は次の手順で作成できます:

  1. identifiers = « 1, 3, 7 » とする。

  2. «[ "name" → "test", "serviceIdentifiers" → identifiers ]» を返す。

各辞書メンバー (DictionaryMemberに合致)は、 型(Typeに合致)と 識別子 (型の後にidentifierトークン)が続きます。 識別子はキー名となります。 型が識別子に ?が続く場合、識別子は インターフェイス、 列挙型、 コールバック関数、 コールバックインターフェイス、 typedefのいずれかを指す必要があります。 ?が付いていない場合は、これらのいずれかまたは 辞書型を指す必要があります。

辞書メンバーの型(typedef展開後)がnullable型の場合、 そのinner typeは 辞書型であってはなりません。

dictionary identifier {
  type identifier;
};

オプションの辞書メンバーの識別子の後に U+003D(=)と値(DefaultValueに合致)が続く場合、 そのメンバーのデフォルト値となり、 著者コードや仕様本文で値が指定されない場合に使われる値です。

dictionary identifier {
  type identifier = "value";
};

デフォルト値としてbooleanリテラル(trueまたはfalse)、 nullトークン、 integerトークン、 decimalトークン、 3つの特殊な浮動小数点リテラル値(Infinity、-Infinity、NaN)、 stringトークン、 []の2トークン、{}の2トークンが使われた場合、 操作の オプション引数デフォルト値と同じ解釈をします。

辞書メンバーの型が列挙型の場合、 デフォルト値(指定されていれば)は列挙型の値のいずれかでなければなりません。

辞書メンバーの型の前にrequiredキーワードが付いている場合、 そのメンバーは必須 辞書メンバーとなります。

dictionary identifier {
  required type identifier;
};

辞書メンバーの型は、その辞書型自身を含んではなりません。型が辞書型Dを含むとは、以下のいずれかが真である場合です:

インターフェイスと同様に、辞書型のIDLは partial dictionary 定義(partial Dictionaryに合致)で分割できます。 partial dictionary定義の識別子は 本体の辞書型と同じでなければなりません。各partial dictionary定義のメンバーは全て辞書型自身のメンバーとみなされます。

dictionary SomeDictionary {
  /* dictionary_members... */
};

partial dictionary SomeDictionary {
  /* dictionary_members... */
};

注: partial interface定義と同様、partial dictionary定義は仕様編集上の補助を目的としており、 インターフェイス定義を文書の複数セクションや複数文書に分割できます。

辞書型の辞書メンバーの順序は、 継承辞書型のメンバーが非継承メンバーより前になり、 本体(およびpartial dictionary定義)に現れるメンバーは識別子のUnicodeコードポイント順(辞書順)になります。

辞書値の エントリーは常に、対応する 辞書 メンバーの順序であり、それらが 設定された順序には関係しない。

例えば、次の定義の場合:

dictionary B : A {
  long b;
  long a;
};

dictionary A {
  long c;
  long g;
};

dictionary C : B {
  long e;
  long f;
};

partial dictionary A {
  long h;
  long d;
};

C型の辞書値の辞書メンバーの順序は c, d, g, h, a, b, e, f となります。

辞書型はメンバーの順序が必要です。なぜなら、言語バインディングによっては辞書値をプラットフォームオブジェクトに渡した時の 辞書メンバー取得順で観測結果が変わる場合があるからです。例えば次のインターフェイスを考えます:

[Exposed=Window]
interface Something {
  undefined f(A a);
};

そしてこのJavaScriptコード:

var something = getSomething();  // Somethingのインスタンス取得
var x = 0;

var dict = { };
Object.defineProperty(dict, "d", { get: function() { return ++x; } });
Object.defineProperty(dict, "c", { get: function() { return ++x; } });

something.f(dict);

辞書メンバー取得順で値が決まります。Aの順序はc→dなので、 cの値が1、dの値が2となります。

その結果、2つの辞書値の エントリーが同じ キーと 等しい 値を持つ場合、それらは 等しい。そのエントリーが どの順序で 設定されたかには関係しない。

辞書メンバーの識別子は、 その辞書で定義されている別の辞書メンバーの識別子、または その辞書の 継承された辞書で定義されているものと同じであってはならない。

辞書には 拡張 属性は適用されない。

Partial ::
    partial PartialDefinition
PartialDefinition ::
    interface PartialInterfaceOrPartialMixin
    PartialDictionary
    Namespace
Dictionary ::
    dictionary identifier Inheritance { DictionaryMembers } ;
DictionaryMembers ::
    DictionaryMember DictionaryMembers
    ε
DictionaryMember ::
    ExtendedAttributeList DictionaryMemberRest
DictionaryMemberRest ::
    required TypeWithExtendedAttributes identifier ;
    Type identifier Default ;
PartialDictionary ::
    dictionary identifier { DictionaryMembers } ;
Default ::
    = DefaultValue
    ε
DefaultValue ::
    ConstValue
    string
    [ ]
    { }
    null
    undefined
Inheritance ::
    : identifier
    ε

辞書型の一つの用途は、多数のオプション引数を 操作に渡す際、 呼び出し元で指定順序に制約されずに渡すことを可能にすることです。 例えば、以下のIDLフラグメントを考えます:

[Exposed=Window]
interface Point {
  constructor();
  attribute double x;
  attribute double y;
};

dictionary PaintOptions {
  DOMString fillPattern = "black";
  DOMString strokePattern;
  Point position;
};

[Exposed=Window]
interface GraphicsContext {
  undefined drawRectangle(double width, double height, optional PaintOptions options);
};

IDLのJavaScript実装では、オプションの PaintOptions辞書型にObjectを渡せます:

// GraphicsContextのインスタンスを取得
var ctx = getGraphicsContext();

// 四角形を描画
ctx.drawRectangle(300, 200, { fillPattern: "red", position: new Point(10, 10) });

PaintOptionsのメンバーはオプションです。 fillPatternが省略された場合、 drawRectangleはデフォルト値を利用でき、明示的な省略時処理を記述する必要はありません。 strokePatternやpositionが省略された場合は drawRectangle側で明示的に省略時処理を行う必要があります。

2.8. 例外

例外は、 エラーを表すオブジェクトの一種であり、実装によってthrowされたり第一級値として扱われたりします。 Web IDLには仕様が参照・throwできる多くの事前定義された例外があり、 操作や属性等の定義で使用できます。カスタム例外型も、 インターフェイスとして DOMException を継承することで定義可能です。

単純例外は、 以下の型で識別されます:

これらは、JavaScript のすべての エラーオブジェクトに対応するが、 以下のものを除く。 AggregateError および SuppressedError、 これらは他のエラーをラップするためだけに設計されている。SyntaxError、 これは JavaScript パーサーによる使用のために予約されている。また、Error、 これは使用が予約されており、 作者による使用を目的とする。各 単純例外 の意味は、JavaScript 仕様における対応するエラーオブジェクトの意味と 一致する。

2番目の例外はDOMExceptionであり、 発生したエラーに関する詳細情報(name)をプログラム的に取得できます。 これらnameは 以下のDOMException名テーブルから選ばれます。

DOMException はインターフェイスタイプなので、 IDLで型として使えます。 例えば操作の戻り値型として DOMException を宣言できます。ただし例外はthrowされるべきものであり、戻り値で返すべきではないため、通常は推奨されません。

最後の例外はDOMExceptionの派生インターフェイスです。 これらはより複雑なため、専用の節§ 2.8.2 DOMException派生インターフェイスで説明します。

単純例外は 型名を指定することで生成できます。 DOMException はnameと DOMException を指定して生成できます。 例外はまたthrowすることもでき、 生成時と同じ情報を指定します。両ケースとも、例外の意味を説明する追加情報を指定可能であり、 これは例外メッセージの構築に有用です。

例外の生成・throwの文言例:

型がTypeErrorの 単純例外をthrowする:

TypeError をthrowする。

新しい DOMException を name "NotAllowedError" でスローするには:

"NotAllowedError" DOMException をthrowする。

新しい DOMException を name "SyntaxError" で作成するには:

object を新たに "SyntaxError" DOMException で 生成する。

新しい DOMException を name "OperationError" で promise を reject するには:

p を "OperationError" DOMException で rejectする。

例外メッセージの構築に追加情報を含める例:

"SyntaxError" DOMException をthrowし、 その値が末尾の空白を許容しないことを示す。

こうした追加コンテキストは、なぜ例外がthrowされたかが明確でない場合(アルゴリズム内の多くのステップで "SyntaxError" DOMExceptionがthrowされる等)に実装者にとって特に有用です。 一方、例えばユーザーが機能利用の許可を与えたか検証した直後に "NotAllowedError" DOMExceptionをthrowする場合は、メッセージは自明なので指定不要です。

例外の生成・throwの結果的な挙動は言語バインディングごとに異なります。

§ 3.14.3 例外の生成とthrowも参照ください。 JavaScriptバインディングにおける例外の生成・throwの詳細について記載されています。

2.8.1. 基本 DOMException エラー名

以下のDOMException名テーブルは、 基本のDOMException インターフェイスのインスタンスに許可されるnameの一覧と、 それらの意味、およびレガシーの数値エラーコード値を示します。

DOMException を継承するインターフェイス(§ 2.8.2 DOMException 派生インターフェイス参照)は 独自のnameを持ち、本テーブルには掲載されません。

DOMException を生成または throwする際は、仕様は必ずこの一覧のnameを使わなければなりません。 適切なnameがない場合は、issueを提出し、 共有名前空間への追加を議論してください。APIで複数のエラー条件をWeb開発者が区別する必要がある場合のみ、 新たなユースケース固有nameの追加が重要です。

DOMException のうち「非推奨」と記載されたnameはレガシー目的で保持されていますが、利用は推奨されません。

注: ここで定義される"SyntaxError" DOMException と、JavaScriptのSyntaxError を混同しないでください。 "SyntaxError" DOMException はWeb APIのパースエラー(例:セレクタのパースなど)を報告するために使用されます。 一方、JavaScriptのSyntaxError はJSパーサ専用です。 誤解を避けるため、SyntaxError DOMException の表記を使い、単にSyntaxError だけでDOMException を指すことは避けてください。 [DOM]

名前 説明 レガシーコード名・値
"IndexSizeError" 非推奨。 RangeError を代わりに使用してください。 INDEX_SIZE_ERR (1)
"HierarchyRequestError" 操作により不正なノードツリーが生成されます。 [DOM] HIERARCHY_REQUEST_ERR (3)
"WrongDocumentError" オブジェクトが誤った文書に属しています。 [DOM] WRONG_DOCUMENT_ERR (4)
"InvalidCharacterError" 文字列に不正な文字が含まれています。 INVALID_CHARACTER_ERR (5)
"NoModificationAllowedError" オブジェクトを変更できません。 NO_MODIFICATION_ALLOWED_ERR (7)
"NotFoundError" オブジェクトがここに見つかりません。 NOT_FOUND_ERR (8)
"NotSupportedError" 操作がサポートされていません。 NOT_SUPPORTED_ERR (9)
"InUseAttributeError" 属性が他の要素で利用中です。 [DOM] INUSE_ATTRIBUTE_ERR (10)
"InvalidStateError" オブジェクトが不正な状態です。 INVALID_STATE_ERR (11)
"SyntaxError" 文字列が期待されたパターンと一致しませんでした。 SYNTAX_ERR (12)
"InvalidModificationError" この方法でオブジェクトを変更できません。 INVALID_MODIFICATION_ERR (13)
"NamespaceError" 操作がXML名前空間によって許可されていません。 [XML-NAMES] NAMESPACE_ERR (14)
"InvalidAccessError" 非推奨。 無効な引数にはTypeError、 サポートされていない操作には"NotSupportedError" DOMException、 拒否された要求には"NotAllowedError" DOMExceptionを使用してください。 INVALID_ACCESS_ERR (15)
"TypeMismatchError" 非推奨。 TypeError を代わりに使用してください。 TYPE_MISMATCH_ERR (17)
"SecurityError" 操作が安全でありません。 SECURITY_ERR (18)
"NetworkError" ネットワークエラーが発生しました。 NETWORK_ERR (19)
"AbortError" 操作が中断されました。 ABORT_ERR (20)
"URLMismatchError" 非推奨。 URL_MISMATCH_ERR (21)
"QuotaExceededError" 非推奨。 QuotaExceededError DOMExceptionの派生インターフェイスを使用してください。 QUOTA_EXCEEDED_ERR (22)
"TimeoutError" 操作がタイムアウトしました。 TIMEOUT_ERR (23)
"InvalidNodeTypeError" 与えられたノードがこの操作に不適切または不適切な祖先を持つ。 [DOM] INVALID_NODE_TYPE_ERR (24)
"DataCloneError" オブジェクトをクローンできません。 DATA_CLONE_ERR (25)
"EncodingError" エンコードまたはデコード操作が失敗しました。 —
"NotReadableError" I/Oの読み取り操作が失敗しました。 —
"UnknownError" 一時的な理由(例:メモリ不足等)により操作が失敗しました。 —
"ConstraintError" トランザクション内のミューテーション操作が制約違反で失敗しました。 [INDEXEDDB] —
"DataError" 提供されたデータが不十分です。 —
"TransactionInactiveError" 現在アクティブでない、もしくは完了したトランザクションに対してリクエストが行われました。 [INDEXEDDB] —
"ReadOnlyError" "readonly"トランザクションで変更操作が行われました。 [INDEXEDDB] —
"VersionError" 既存バージョンより低いバージョンでデータベースを開こうとしました。 [INDEXEDDB] —
"OperationError" 操作固有の理由により失敗しました。 —
"NotAllowedError" 現在のコンテキストでユーザーエージェントまたはプラットフォームにより要求が許可されていません(ユーザーが権限を拒否した可能性あり)。 —
"OptOutError" ユーザーがプロセスからオプトアウトしました。 —

2.8.2. DOMException 派生インターフェイス

例外がDOMExceptionの name以上の情報をプログラム的に取得できる必要がある場合、仕様策定者は インターフェイスを定義し、 DOMExceptionを継承できます。 このようなインターフェイスは、開発者に予測可能な形を提供するため、以下の規則に従う必要があります。具体的には:

これらの要件により、これらインターフェイスに継承されたcode プロパティは常に0を返します。

DOMException 派生インターフェイスを生成・ throwするには、 インターフェイスの識別子と 構築に必要な追加情報を指定します。

QuotaExceededError のインスタンスをthrowするには:

QuotaExceededErrorをthrowし、 quotaに42、 requestedに50を指定する。

2.8.3. 事前定義されたDOMException 派生インターフェイス

現行標準では1つの事前定義済みDOMException 派生インターフェイスを定義しています:

[Exposed=*, Serializable]
interface QuotaExceededError : DOMException {
  constructor(optional DOMString message = "", optional QuotaExceededErrorOptions options = {});

  readonly attribute double? quota;
  readonly attribute double? requested;
};

dictionary QuotaExceededErrorOptions {
  double quota;
  double requested;
};

QuotaExceededError 例外はクォータ超過時にthrowできます。プロパティが2つあり、それぞれ開発者に要求値とクォータ値の比較情報を提供します。

以前の現行標準では"QuotaExceededError"は 基本DOMExceptionエラー名の一つでしたが、 追加情報の対応のため完全なインターフェイスに引き上げられました。

全てのQuotaExceededError インスタンスは、requestedと quota(いずれも数値またはnull)を持ち、初期値はnullです。

new QuotaExceededError(message, options) のコンストラクタ手順は以下の通りです:
  1. thisのnameを "QuotaExceededError"に設定。

  2. thisのmessageを messageに設定。

  3. もしoptions["quota"] が存在する場合:

    1. options["quota"] が0未満の場合、RangeErrorをスローする。

    2. thisのquotaを options["quota"]で設定。

  4. もしoptions["requested"] が存在する場合:

    1. options["requested"] が0未満の場合、RangeErrorをスローする。

    2. thisのrequested をoptions["requested"]で設定。

  5. this の quota が null でなく、this の requested が null でなく、 さらに this の requested が this の quota より小さい場合、 RangeError をスローする。

quotaのgetter手順は thisのquotaを返す。

requestedのgetter手順は thisのrequestedを返す。

QuotaExceededError インターフェイスはDOMException インターフェイスのcode getterを継承し、常に22を返します。ただしこの値に依存するのは非推奨です(QuotaExceededErrorでもDOMExceptionでも)。 name getterを使う方がよいです。


QuotaExceededError オブジェクトはシリアライズ可能オブジェクトです。

value・serializedを受け取るシリアライズ手順は:
  1. DOMException のシリアライズ手順をvalue・serializedで実行。

  2. serialized.[[Quota]]にvalueのquotaを設定。

  3. serialized.[[Requested]]にvalueのrequestedを設定。

serialized・valueを受け取るデシリアライズ手順は:
  1. DOMException のデシリアライズ手順をserialized・valueで実行。

  2. valueのquotaにserialized.[[Quota]]を設定。

  3. valueのrequestedにserialized.[[Requested]]を設定。


作成またはスローによってQuotaExceededError を生成する仕様は、 requestedおよびquotaの両方がnullでなく、 かつrequestedがquotaより小さい場合を提供してはならない。

2.9. 列挙型

列挙型は、 Enumに合致する定義であり、 有効な値が事前定義された文字列集合となる型を宣言します。列挙型は、 DOMString に割り当てられる値や 属性、 操作の引数として渡される値を制限できます。

enum identifier { "enum", "values" /* , ... */ };

列挙値は、 カンマ区切りのstringリテラルとして指定されます。 列挙値のリストに重複は許されません。

列挙値はすべて小文字で、複数語はハイフン区切りまたは区切りなしとすることが強く推奨されます。 別の命名方式を使う特別な理由がなければこの推奨に従ってください。 例えば「createobject」または「create-object」など。 関連API間で命名方式を統一するよう検討してください。

型が列挙型の場合、属性への代入や操作引数として有効でない文字列値を使った場合の挙動は言語バインディング依存です。

注: JavaScriptバインディングでは、属性への無効な文字列値の代入は無視されますが、 操作引数など他の文脈で渡した場合は例外がthrowされます。

この仕様で定義された拡張属性は 列挙型には適用できません。

Enum ::
    enum identifier { EnumValueList } ;
EnumValueList ::
    string EnumValueListComma
EnumValueListComma ::
    , EnumValueListString
    ε
EnumValueListString ::
    string EnumValueListComma
    ε

次のIDLフラグメントは、 列挙型を定義し、 属性や 操作引数の型として用いています:

enum MealType { "rice", "noodles", "other" };

[Exposed=Window]
interface Meal {
  attribute MealType type;
  attribute double size;     // in grams

  undefined initialize(MealType type, double size);
};

JavaScript実装では、typeプロパティやinitializeMeal関数に割り当てられる文字列は、 列挙型で定義されたものに制限されます。

var meal = getMeal();                // Mealのインスタンス取得

meal.initialize("rice", 200);        // 通常通り操作が呼ばれる

try {
  meal.initialize("sandwich", 100);  // TypeErrorがthrowされる
} catch (e) {
}

meal.type = "noodles";               // 属性代入は通常通り
meal.type = "dumplings";             // 属性代入は無視される
meal.type == "noodles";              // trueと評価される

2.10. コールバック関数

「Custom DOM Elements」仕様では、プラットフォームオブジェクト提供関数にコールバック関数型を使いたい意図があります。 「コールバック関数」という呼称を「関数」に変更し、両方の用途に使えることを明確にした方がよいでしょうか?

コールバック関数は、 callback CallbackRestに合致する定義であり、 関数型を宣言するために使います。

callback identifier = return_type (/* arguments... */);

注: 類似名のコールバックインターフェイスも参照ください。

イコール記号の左側の識別子が コールバック関数の名前となり、 右側の戻り値型・引数リスト(Type・ArgumentListに合致)が コールバック関数型のシグネチャとなります。

コールバック関数は 定数の型として使うことはできません。

コールバック関数型に適用可能な拡張属性は以下のみです: [LegacyTreatNonObjectAsNull]。

CallbackOrInterfaceOrMixin ::
    callback CallbackRestOrInterface
    interface InterfaceOrMixin
CallbackRest ::
    identifier = Type ( ArgumentList ) ;

次のIDLフラグメントは、 操作完了時にユーザー定義関数を呼び出すAPI用の コールバック関数を定義しています。

callback AsyncOperationCallback = undefined (DOMString status);

[Exposed=Window]
interface AsyncOperations {
  undefined performOperation(AsyncOperationCallback whenFinished);
};

JavaScriptバインディングでは、関数オブジェクトを操作引数として渡します。

var ops = getAsyncOperations();  // AsyncOperationsのインスタンス取得

ops.performOperation(function(status) {
  window.alert("Operation finished, status is " + status + ".");
});

2.11. typedef

typedefは、 Typedefに合致する定義であり、 型に新しい名前を与えるために使われます。この新しい名前は言語バインディングでは公開されず、 純粋にIDL内で型参照の簡略化のために使われます。

typedef type identifier;

新しい名前が与えられる型は typedefキーワードの後(TypeWithExtendedAttributesに合致)に指定され、 型の後ろのidentifierトークンが名前を表します。

Typeは、 同じまたは他のtypedefの識別子であってはなりません。

この仕様で定義された拡張属性は typedefには適用できません。

Typedef ::
    typedef TypeWithExtendedAttributes identifier ;

次のIDLフラグメントは、 typedefの利用例であり、 長いsequence型の代わりに 短い識別子を使えるようにしています。

[Exposed=Window]
interface Point {
  attribute double x;
  attribute double y;
};

typedef sequence<Point> Points;

[Exposed=Window]
interface Widget {
  boolean pointWithinBounds(Point p);
  boolean allPointsWithinBounds(Points ps);
};

2.12. インターフェイスを実装するオブジェクト

特定のIDLフラグメントセットの実装において、 オブジェクトはプラットフォームオブジェクトと見なされる場合があります。

プラットフォームオブジェクトは、 インターフェイスを実装するオブジェクトです。

レガシープラットフォームオブジェクトは、 プラットフォームオブジェクトであり、 [Global] 拡張属性を持たず、 インデックス付きプロパティ、 名前付きプロパティ、または両方をサポートするインターフェイスを実装します。

例えばブラウザでは、 DOMオブジェクト(NodeやDocumentなどのインターフェイスを実装)が JavaScriptからWebページ内容へアクセスを提供する場合、それらは プラットフォームオブジェクトです。 これらはC++などで実装されたエキゾチックオブジェクトの場合もあれば、ネイティブJavaScriptオブジェクトの場合もあります。 いずれにせよ、IDLフラグメントセットの実装は、 生成された全てのプラットフォームオブジェクトを認識できる必要があります。 実装内部状態でオブジェクトがプラットフォームオブジェクトかどうか記録したり、 内部C++クラス実装かどうかで判定するなど、認識方法は実装依存です。

それ以外のシステム上のオブジェクトはプラットフォームオブジェクト扱いされません。 例えば、WebページがJavaScriptライブラリでDOM Coreを実装する場合、 これはブラウザとは別実装と見なされ、 ライブラリが生成したNodeインターフェイス実装オブジェクトは、 ブラウザ実装におけるNodeプラットフォームオブジェクトとはされません。

コールバックインターフェイスは一方で、 任意のJavaScriptオブジェクトで実装可能です。 これによりWeb APIは著者定義操作を呼び出せます。 例えばDOM Events実装では、 EventListener インターフェイスを実装したオブジェクトをコールバック登録できます。

2.13. 型

この節では、Web IDLがサポートする型、各型に対応する値やInfra型、そしてその型の定数の表現方法を一覧します。

以下の型は整数型と呼ばれます: byte, octet, short, unsigned short, long, unsigned long, long long および unsigned long longです。

以下の型は数値型です: 整数型全て、 float, unrestricted float, double、 unrestricted doubleです。

プリミティブ型は bigint, boolean と 数値型全てです。

文字列型は DOMString, 全ての列挙型, ByteString, USVStringです。

バッファ型は ArrayBuffer と SharedArrayBufferです。

型付き配列型は Int8Array, Int16Array, Int32Array, Uint8Array, Uint16Array, Uint32Array, Uint8ClampedArray, BigInt64Array, BigUint64Array, Float16Array, Float32Array、 Float64Arrayです。

バッファビュー型は DataView および 型付き配列型全てです。

バッファソース型は バッファ型と バッファビュー型全てです。

object型、 全てのインターフェイス型、 全てのコールバックインターフェイス型は オブジェクト型です。

言語バインディング固有型からIDL型への変換は、操作を呼び出す時や 属性に値を代入する時、指定機能の実行前に全て行われます。 変換できない場合、操作は実行されず属性も更新されません。 言語バインディングによっては型変換失敗時に例外がthrowされる場合があり、 その場合例外は操作呼び出し元や属性代入元に伝播されます。

Type ::
    SingleType
    UnionType Null
TypeWithExtendedAttributes ::
    ExtendedAttributeList Type
SingleType ::
    DistinguishableType
    any
    PromiseType
UnionType ::
    ( UnionMemberType or UnionMemberType UnionMemberTypes )
UnionMemberType ::
    ExtendedAttributeList DistinguishableType
    UnionType Null
UnionMemberTypes ::
    or UnionMemberType UnionMemberTypes
    ε
DistinguishableType ::
    PrimitiveType Null
    StringType Null
    identifier Null
    sequence < TypeWithExtendedAttributes > Null
    async_sequence < TypeWithExtendedAttributes > Null
    object Null
    symbol Null
    BufferRelatedType Null
    FrozenArray < TypeWithExtendedAttributes > Null
    ObservableArray < TypeWithExtendedAttributes > Null
    RecordType Null
    undefined Null
ConstType ::
    PrimitiveType
    identifier
PrimitiveType ::
    UnsignedIntegerType
    UnrestrictedFloatType
    boolean
    byte
    octet
    bigint
UnrestrictedFloatType ::
    unrestricted FloatType
    FloatType
FloatType ::
    float
    double
UnsignedIntegerType ::
    unsigned IntegerType
    IntegerType
IntegerType ::
    short
    long OptionalLong
OptionalLong ::
    long
    ε
StringType ::
    ByteString
    DOMString
    USVString
PromiseType ::
    Promise < Type >
RecordType ::
    record < StringType , TypeWithExtendedAttributes >
Null ::
    ?
    ε

2.13.1. any

any型は 他の全ての非ユニオン型の 和集合です。

any型は 判別付きユニオン型に似ていて、その値ごとに 特定の非any型が 紐付いています。例えばany型の値に unsigned longの150や、 longの150があり、 これは異なる値です。

any値の型は 具体型と呼ばれます。 (ユニオン型の値も 具体型を持ちます。)

2.13.2. undefined

undefined型は 一意な値を持ちます。

undefinedの 定数値はIDLでundefinedトークンで表されます。

undefinedは いかなる場合も引数型(操作、 コールバック関数、 コンストラクタ操作等)や 辞書メンバー型 (直接でもユニオンでも)として使ってはなりません。 代わりにoptional引数や 非必須 辞書メンバーを使ってください。

注: この値は以前voidと綴られ、使用制限もより厳格でした。

2.13.3. boolean

boolean型は boolean値に対応します。

booleanの 定数値はIDLでtrueとfalseトークンで表されます。

2.13.4. byte

byte型は 8ビット符号付き整数に対応します。

byteの 定数値はIDLでintegerトークンで表されます。

2.13.5. octet

octet型は 8ビット符号なし整数に対応します。

octetの 定数値はIDLでintegerトークンで表されます。

2.13.6. short

short型は 16ビット符号付き整数に対応します。

shortの 定数値はIDLでintegerトークンで表されます。

2.13.7. unsigned short

unsigned short型は 16ビット符号なし整数に対応します。

unsigned shortの 定数値はIDLでintegerトークンで表されます。

2.13.8. long

long型は 32ビット符号付き整数に対応します。

longの 定数値はIDLでintegerトークンで表されます。

2.13.9. unsigned long

unsigned long型は 32ビット符号なし整数に対応します。

unsigned longの 定数値はIDLでintegerトークンで表されます。

2.13.10. long long

long long型は 64ビット符号付き整数に対応します。

long longの 定数値はIDLでintegerトークンで表されます。

2.13.11. unsigned long long

unsigned long long型は 64ビット符号なし整数に対応します。

unsigned long longの 定数値はIDLでintegerトークンで表されます。

2.13.12. float

float型は 浮動小数点数型で、有限な単精度32ビットIEEE 754浮動小数点数値の集合に対応します。 [IEEE-754]

floatの 定数値はIDLでdecimalトークンで表されます。

32ビット浮動小数点型を使う特別な理由がなければfloatより double型を 仕様では使うべきです。 double型の値集合の方が JavaScriptのNumber型により近いからです。

2.13.13. unrestricted float

unrestricted float型は 浮動小数点数型で、全ての単精度32ビットIEEE 754浮動小数点数値(有限値、非有限値、NaNなど特殊値含む)の集合に対応します。 [IEEE-754]

unrestricted floatの 定数値はIDLでdecimalトークンで表されます。

2.13.14. double

double型は 浮動小数点数型で、有限な倍精度64ビットIEEE 754浮動小数点数値の集合に対応します。 [IEEE-754]

doubleの 定数値はIDLでdecimalトークンで表されます。

2.13.15. unrestricted double

unrestricted double型は 浮動小数点数型で、全ての倍精度64ビットIEEE 754浮動小数点数値(有限値、非有限値、NaNなど特殊値含む)の集合に対応します。 [IEEE-754]

unrestricted doubleの 定数値はIDLでdecimalトークンで表されます。

2.13.16. bigint

bigint型は 範囲制限のない任意精度整数型です。

bigintの 定数値はIDLでintegerトークンで表されます。

2.13.17. DOMString

DOMString型は 文字列に対応します。

注: nullは DOMString型の値ではありません。 nullを許可する場合は nullableなDOMString (IDLではDOMString?)を使用してください。

注: DOMString値には マッチしないサロゲート コードポイントが含まれる場合があります。 これを許容しない場合はUSVStringを使ってください。

DOMString型定数値はIDLで表現できませんが、 DOMString型 辞書メンバー デフォルト値や 操作のoptional引数 デフォルト値には 文字列リテラルトークンの値を設定できます。

2.13.18. ByteString

ByteString型は バイト列に対応します。

ByteString型定数値はIDLで表現できませんが、 ByteString型 辞書メンバー デフォルト値や 操作のoptional引数 デフォルト値には 文字列リテラルトークンの値を設定できます。

ByteString型は HTTPなどバイトと文字列が混在するプロトコルとのインターフェース用途にのみ使うべきです。一般的な文字列は DOMString型で表現するべきで、 たとえ値がASCIIや8ビット文字コードであることが期待されても同様です。 8ビットデータを保持するには sequence型や frozen array型(要素型はoctetかbyte)、 Uint8Array、 Int8Arrayを使うべきです。 ByteStringは避けてください。

2.13.19. USVString

USVString型は スカラー値文字列に対応します。 文脈によって、これらはコード単位の列や スカラー値の列として扱われます。

USVString型定数値はIDLで表現できませんが、 USVString型 辞書メンバー デフォルト値や 操作のoptional引数 デフォルト値には 文字列リテラルトークンの値を設定できます。

USVString型は テキスト処理APIなど、スカラー値列として 文字列処理が必要な場合のみ使うべきです。ほとんどのAPIは DOMString型を使うべきで、 コード単位の解釈をしません。 迷う場合はDOMStringを使ってください。

2.13.20. object

object型は 全ての非nullオブジェクト参照の集合に対応します。

object型定数値はIDLで表現できません。

全てのオブジェクト参照とnullを含む型を表現するには nullable型 object?を使ってください。

2.13.21. symbol

symbol型は 全ての可能なsymbol値の集合に対応します。symbol値は不透明で object値ではありませんが、 識別性(自分自身のみ等価)を持ちます。

symbol型定数値はIDLで表現できません。

2.13.22. インターフェイス型

識別子が インターフェイスを指す場合、 その型はそのインターフェイスを実装した全ての非nullオブジェクト参照の集合に対応します。

IDL値はオブジェクト参照のみで表現されます。

特定インターフェイス型のオブジェクト参照定数値はIDLで表現できません。

そのインターフェイスを実装する全てのオブジェクト参照とnullを含む型を表現するには nullable型を使ってください。

2.13.23. コールバックインターフェイス型

識別子が コールバックインターフェイスを指す場合、 その型は全ての非nullオブジェクト参照の集合に対応します。

IDL値はオブジェクト参照と コールバックコンテキストのタプルで表現されます。 コールバックコンテキストは 言語バインディング固有値であり、言語バインディング固有オブジェクト参照をIDL値に変換する時点の実行コンテキスト情報を保持します。

注: JavaScriptオブジェクトの場合 コールバックコンテキストは そのObject値がIDLコールバックインターフェイス型値に変換される時点の インカンベント設定オブジェクトへの参照を保持します。 § 3.2.16 コールバックインターフェイス型参照。

特定コールバックインターフェイス型のオブジェクト参照定数値はIDLで表現できません。

全てのオブジェクト参照とnullを含む型を表現するには nullable型を使ってください。

2.13.24. 辞書型

識別子が 辞書型を指す場合、 その型は辞書定義に準拠する全ての辞書の集合に対応します。

順序付きマップのリテラル構文は、 文脈から特定の辞書型インスタンスとして扱われることが暗黙的に理解できれば辞書の表現にも使えます。 ただし、IDLフラグメント内で定数辞書値を表現する方法はありません。

2.13.25. 列挙型

識別子が 列挙型を指す場合、 その型はコード単位(DOMStringと同様)の シーケンスである文字列のうち、 列挙値として定義されたものの集合に対応します。

DOMString型と同様、 列挙型の定数値はIDLで表現できませんが、 列挙型の辞書メンバー デフォルト値や 操作のoptional引数 デフォルト値には 文字列リテラルトークンの値を設定できます。

2.13.26. コールバック関数型

識別子が コールバック関数を指す場合、 その型は指定されたシグネチャを持つ関数オブジェクトへの参照値の集合に対応します。

注: LegacyTreatNonObjectAsNull 拡張属性がコールバック関数の定義に指定される場合、 関数以外のオブジェクト参照値も許容されます。

IDLのコールバック関数型値は、オブジェクト参照と コールバックコンテキストのタプルで表現されます。

注: コールバックインターフェイス型と同様、 コールバックコンテキストは JavaScript Object値がIDLコールバック関数型値に変換される時点の インカンベント設定オブジェクト参照を保持します。 § 3.2.19 コールバック関数型参照。

コールバック関数型の定数値はIDLで表現できません。

2.13.27. nullable型 — T?

nullable型は 既存型(inner type)を基に、 追加でnull値を許容するIDL型です。 nullable型はIDLで型の後ろにU+003F(?)を付けて表します。 inner typeは次に該当してはなりません:

注: 辞書型は一般には null 許容にできますが、 オペレーション引数または辞書メンバーの型として使用される場合は null 許容にできません。

任意の型または型のカテゴリ X について、潜在的に null 許容な X は、 X、または null 許容型 で、その 内部型 が X であるものです。

IDL における null 許容型の定数値は、その 内部 型 の定数値と同じ方法で 表現されるか、null トークンで表現されます。

例えば、値がtrue、false、nullを許容する型は boolean?と記述します:

[Exposed=Window]
interface NetworkFetcher {
  undefined get(optional boolean? areWeThereYet = false);
};

次のインターフェイスは 2つの属性を持ちます。 1つはDOMStringまたはnull値、 もう1つはNodeオブジェクト参照またはnull値:

[Exposed=Window]
interface Node {
  readonly attribute DOMString? namespaceURI;
  readonly attribute Node? parentNode;
  // ...
};

2.13.28. sequence型 — sequence<T>

sequence<T>型は 型Tの値からなる(長さ0もあり得る)リスト値の集合を持つパラメータ化型です。

sequence型は必ず値渡しです。 言語バインディングでsequenceが何らかのオブジェクトで表現される場合、 sequenceをプラットフォームオブジェクトに渡しても そのオブジェクトにsequence参照が保持されることはありません。 プラットフォームオブジェクトから返されたsequenceもコピーであり、 変更はプラットフォームオブジェクトに反映されません。

リストのリテラル構文は、 文脈からsequence型インスタンスとして扱われることが暗黙的に理解できればsequenceの表現にも使えます。 ただし、IDLフラグメント内で定数sequence値を表現する方法はありません。

sequence型は属性や 定数の型として使ってはなりません。

注: この制約は、仕様策定者やAPI利用者が sequence型がコピー渡しされ、 参照渡しされないことを明確にするために存在します。writableなsequence型属性の代わりに、 sequenceの取得・設定操作を対で提供することが推奨されます。

リストは 全ての要素が型Tである限り、暗黙的にsequence<T>型として扱えます。

2.13.29. async_sequence型 — async_sequence<T>

async_sequence型は 型Tの値からなる非同期イテラブル(無限長もあり得る)シーケンスを生成できるオブジェクト参照値の集合を持つパラメータ化型です。

sequence型が 事前に値が全て分かる固定長リストであるのに対し、 async_sequence型の非同期イテラブルシーケンスは遅延生成です。 値や長さはasync_sequence生成時には分からず、 イテレーション時に非同期で値が生成される場合もあります。

async_sequence型は言語バインディングでオブジェクトで表現される場合は参照渡しです。 そのため、async_sequenceをプラットフォームオブジェクトに渡すと そのオブジェクトにasync_sequence参照が保持されます。 プラットフォームオブジェクトから返されたasync_sequenceも同じオブジェクトへの参照であり、 変更はプラットフォームオブジェクトに反映されます(sequence型とは対照的に)。

注: async_sequence型はIDLで構築できません。 操作の戻り値や辞書メンバー型として使われる場合、 async_sequenceはホスト環境から言語バインディングでIDL型に変換されて生成されます。 操作がasync_sequence型を返す代わりに、 インターフェイスに 非同期イテラブル宣言を持たせることもできます。

async_sequence型は属性や定数の型として使ってはなりません。

async_sequence型値はIDLで表現できません。

2.13.30. record型 — record<K, V>

レコード型は、 値が 順序付きマップであり、 キーが K のインスタンスで、値が V のインスタンスであるパラメーター化された型である。K は 次のいずれか でなければならない:DOMString、 USVString、 または ByteString。

順序付きマップのリテラル構文は、マップがレコードとして扱われていることが文脈から暗黙に 理解される場合、レコードを表すためにも使用できる。ただし、 IDL フラグメント内で定数のレコード値を表す方法はない。

レコードは常に値渡しされる。レコードが何らかの種類のオブジェクトによって 表される言語バインディングでは、レコードを プラットフォーム オブジェクトに渡しても、そのオブジェクトによってレコードへの参照が 保持されることにはならない。同様に、 プラットフォームオブジェクトから返されるレコードはいずれもコピーであり、それに加えた変更は プラットフォームオブジェクトには反映されない。

レコードは、属性または 定数の型として使用してはならない。

任意の 順序付きマップは、 record<K, V>として暗黙的に扱うことができる。ただし、 そのマップに含まれる エントリーの キー がすべて型 K であり、その 値 がすべて型 V である場合に限る。

2.13.31. Promise型 — Promise<T>

promise型は 型パラメータ化されており、その値は 「非同期処理の結果のプレースホルダとして使われるオブジェクト参照値」です。 詳細はJavaScript仕様の section 25.4 を参照してください。

Promise型はnullable不可ですが、Tはnullable可です。

Promise値はIDLで表現できません。

2.13.32. ユニオン型

ユニオン型は 複数の型の値集合の合併となる型です。ユニオン型(UnionTypeに合致)は 一連の型をorキーワードで区切り、括弧で囲んで記述します。 ユニオン型を構成する型はユニオンのメンバー型と呼びます。

例えば(Node or DOMString)や(double or sequence<double>)と書きます。 ユニオン型全体に?サフィックスを付ける場合は 閉じ括弧の後に置きます(例:(Node or DOMString)?)。

ユニオン型のメンバー型は ネストしたユニオン型には降りません。 例えば(double or (sequence<long> or Event) or (Node or DOMString)?)のメンバー型は double、(sequence<long> or Event)、(Node or DOMString)?です。

any 型と同様に、 ユニオン型の値には特定の型があり、 それは値に一致するメンバー型である。

共用体型の平坦化されたメンバー型は、 注釈付きである可能性があり、 次のように決定される型の集合 です:

  1. T を共用体型とします。

  2. S を ∅ に初期化します。

  3. T の各メンバー型 U について:

    1. U が注釈付き型である場合、 U を U の内部型に設定します。

    2. U がnull 許容型である場合、 U を U の内部型に設定します。

    3. U が共用体型である場合、 U の平坦化されたメンバー型を S に 追加します。

    4. そうでない場合、U は共用体型ではありません。 U を S に追加します。

  4. S を返します。

注: 例えば ユニオン型 (Node or (sequence<long> or Event) or (XMLHttpRequest or DOMString)? or sequence<(sequence<double> or NodeList)>) のflattened member型は Node、sequence<long>、Event、XMLHttpRequest、DOMString、 sequence<(sequence<double> or NodeList)>の6型です。

null 許容メンバー型の数 は、共用体型についての 整数で、 次のように決定されます:

  1. T を共用体型とします。

  2. n を 0 に初期化します。

  3. T の各メンバー型 U について:

    1. U がnull 許容型である場合:

      1. n を n + 1 に設定します。

      2. U を U の内部型に設定します。

    2. U が共用体型である場合:

      1. m を U のnull 許容メンバー 型の数とします。

      2. n を n + m に設定します。

  4. n を返します。

any 型は 決して 共用体 メンバー型として使用してはなりません。

null 許容メンバー型の数は、 共用体型について 0 または 1 でなければならず、1 の場合、その共用体型はさらに その辞書型を、その平坦化されたメンバー型に含んではなりません。

型がnull 許容型を 含むとは、次の場合です:

平坦化されたメンバー型の各組 (共用体型内のもの)、 T と U は、 区別可能でなければなりません。

作成できる共用体には bigint と 数値型があります。 ただし、これは通常、次のようなインターフェイスでのみ使用することが想定されています NumberFormat のように、値を 計算で使用するのではなく 書式設定するものです。 このような共用体を受け入れた後で、その 数値型の値をbigint に変換して さらに処理することは適切ではありません。これは 精度誤差を生じさせるおそれがあるためです。 どうか issue を 報告してから この機能を使用してください。

型がundefined を 含むとは、次の場合です:

共用体型の定数値は IDL では、その定数値と同じ方法で メンバー型が 表現 されます。

UnionType ::
    ( UnionMemberType or UnionMemberType UnionMemberTypes )
UnionMemberType ::
    ExtendedAttributeList DistinguishableType
    UnionType Null
UnionMemberTypes ::
    or UnionMemberType UnionMemberTypes
    ε
DistinguishableType ::
    PrimitiveType Null
    StringType Null
    identifier Null
    sequence < TypeWithExtendedAttributes > Null
    async_sequence < TypeWithExtendedAttributes > Null
    object Null
    symbol Null
    BufferRelatedType Null
    FrozenArray < TypeWithExtendedAttributes > Null
    ObservableArray < TypeWithExtendedAttributes > Null
    RecordType Null
    undefined Null

2.13.33. 注釈付き型

既存型に特定の拡張属性を指定することで 追加型を作成できます。これらの型を注釈付き型と呼び、注釈付けされる型を inner typeと呼びます。

[Clamp] longは新たな注釈付き型を定義し、 inner typeである longの挙動を基にしつつ、 [Clamp]拡張属性で修正したものです。

以下の拡張属性は型に適用可能です: [AllowResizable], [AllowShared], [Clamp], [EnforceRange], [LegacyNullToEmptyString]

型に関連付けられる拡張属性 IDL型typeについて、次の手順で決定します:
  1. extended attributes を新しい空の集合とします。

  2. type が、 TypeWithExtendedAttributes 生成規則内に直接ある Type である場合、追加します。生成規則の拡張属性のそれぞれを、 生成規則の ExtendedAttributeList に存在するものから extended attributes に。

    [Exposed=Window]
    interface I {
        attribute [XAttr] long attrib;
        undefined f1(sequence<[XAttr] long> arg);
        undefined f2(optional [XAttr] long arg);
    
        maplike<[XAttr2] DOMString, [XAttr3] long>;
    };
    
    dictionary D {
        required [XAttr] long member;
    };
    
  3. type が共用体型 U のメンバー型である場合、共用体型 U に追加します。それぞれの 関連付けられた拡張属性を U から extended attributes に。

    [Exposed=Window]
    interface I {
        attribute [XAttr] (long or Node) attrib;
    };
    
  4. type が null 許容型 N の内部型である場合、null 許容型 N の 追加を行い、 それぞれの関連付けられた拡張属性を N から extended attributes に。

    [Exposed=Window]
    interface I {
        attribute [XAttr] long? attrib;
    };
    
  5. type が、optional キーワードで宣言されていない引数 A の型である場合、 追加します。 extended attributes に、 拡張属性のうち、 A の ExtendedAttributeList に存在する Argument 生成規則のもので、 型に適用可能なものをすべて。

    [Exposed=Window]
    interface I {
        undefined f([XAttr] long attrib);
    };
    

    これは、[XAttr] が 型に適用可能な場合に限り、このステップの例となることに注意してください。そうでない場合、 [XAttr] は引数に適用され、 引数の型には適用されません。

  6. type が、辞書メンバー M の型であり、 必須ではない場合、追加します。 extended attributes に、 拡張属性のうち、 M の ExtendedAttributeList に存在する DictionaryMember 生成規則のもので、 型に適用可能なものをすべて。

    dictionary D {
        [XAttr] long member;
    };
    

    これは、[XAttr] が 型に適用可能な場合に限り、このステップの例となることに注意してください。そうでない場合、 [XAttr] は辞書 メンバーに適用され、メンバーの型には適用されません。

  7. type がtypedef である場合、追加します。関連付けられた拡張属性を、 新しい名前が付けられる型から extended attributes に。

    typedef [XAttr] long xlong;
    
  8. extended attributes を返します。

いかなる型でも、関連付けられる拡張属性は 型に適用可能な拡張属性のみ含む必要があります。

2.13.34. バッファソース型

バッファ型やそのビュー型となる全ての非nullオブジェクト参照値の集合に対応する型があります。 下表はそれぞれの型と対応するバッファやビューの種類を示します。

型 バッファの種類
ArrayBuffer 固定バイト数のバッファへのポインタ(nullも可)を保持するオブジェクト
SharedArrayBuffer 固定バイト数の共有バッファへのポインタ(null不可)を保持するオブジェクト
DataView バッファ型インスタンスへのビューであり、任意バイトオフセットの整数・浮動小数点値への型付きアクセスが可能
Int8Array バッファ型インスタンスへのビューであり、2の補数表現の符号付き整数配列としてビットサイズごとに公開
Int16Array
Int32Array
BigInt64Array
Uint8Array バッファ型インスタンスへのビューであり、ビットサイズごとに符号なし整数配列として公開
Uint16Array
Uint32Array
BigUint64Array
Uint8ClampedArray バッファ型インスタンスへのビューであり、8ビット符号なし整数としてクランプ変換付き配列で公開
Float16Array バッファ型インスタンスへのビューであり、指定ビットサイズのIEEE 754浮動小数点配列として公開。Float16ArrayはECMAScript提案 [PROPOSAL-FLOAT16ARRAY]に対応。
Float32Array
Float64Array

注: これらの型はすべてJavaScriptで定義されたクラスに対応します。

これらの型の定数値をIDLで表現する方法はありません。

仕様本文レベルでは、IDLバッファソース型は単なるオブジェクト参照です。 バッファ内部のバイト列を検査・操作するには、仕様本文で § 3.2.26 バッファソース型のアルゴリズムを利用してください。

BufferRelatedType ::
    ArrayBuffer
    SharedArrayBuffer
    DataView
    Int8Array
    Int16Array
    Int32Array
    Uint8Array
    Uint16Array
    Uint32Array
    Uint8ClampedArray
    BigInt64Array
    BigUint64Array
    Float16Array
    Float32Array
    Float64Array

2.13.35. フローズン配列型 — FrozenArray<T>

フローズン配列型は 型パラメータ化されており、値は固定長で変更不可な値の配列を保持するオブジェクト参照値です。配列内の値はT型です。

フローズン配列型は、インターフェイス上で定義される 通常属性または static属性の型としてのみ使うべきです。

次のIDLフラグメントは、 2つのフローズン配列属性(1つは読み取り専用、1つは非読み取り専用)を持つ インターフェイスを定義します。
[Exposed=Window]
interface PersonalPreferences {
    readonly attribute FrozenArray<DOMString> favoriteColors;
    attribute FrozenArray<DOMString> favoriteFoods;

    undefined randomizeFavoriteColors();
};

これらの属性の挙動は以下のように定義できます:

各PersonalPreferencesはfavorite colors(FrozenArray<DOMString>)を持ち、初期値は« "purple", "aquamarine" »からフローズン配列の生成を行った結果です。

各PersonalPreferencesはfavorite foods(FrozenArray<DOMString>)を持ち、初期値は空リストからフローズン配列の生成を行った結果です。

favoriteColorsのgetter手順はthisのfavorite colorsを返す。

favoriteFoodsのgetter手順はthisのfavorite foodsを返す。

favoriteFoodsのsetter手順はthisのfavorite foodsをthe given valueに設定する。

randomizeFavoriteColors()のメソッド手順は:

  1. newFavoriteColorsを、ランダムに選んだ2つの色文字列のリストとする。

  2. thisのfavorite colorsをnewFavoriteColorsからフローズン配列の生成を行った結果で設定する。

FrozenArray<T>値は参照であり、 sequence型が値渡しであるのとは異なります。

フローズン配列値をIDLで定数値として表現する方法はありません。

2.13.36. オブザーバブル配列型 — ObservableArray<T>

オブザーバブル配列型は 型パラメータ化されており、値はT型のオブジェクトからなる可変リストと、著者コードによるリスト内容変更時に実行される挙動を組み合わせたオブジェクト参照値です。

型パラメータTは辞書型、 sequence型、 record型、 オブザーバブル配列型のいずれも不可ですが、nullableは可です。

sequence型や フローズン配列型と同様、オブザーバブル配列型はJavaScript配列型のラッパーであり、使用時に追加意味論が課されます。

オブザーバブル配列型は、インターフェイス上で定義される 通常属性の型としてのみ使うべきです。

オブザーバブル配列型属性について、仕様策定者は以下のアルゴリズム群を指定できます:

これらのアルゴリズムはどちらも任意であり、提供されていない場合、デフォルトの動作は何もしないことである。いずれのアルゴリズムも、例えば不正な値を拒否するために例外をスローしてもよい。

JavaScript コードが既存のインデックスに新しい値を設定するときは、まず インデックス付き値の削除アルゴリズムが呼び出され既存の値が削除され、 次に新しい値でインデックス付き値の設定アルゴリズムが呼び出される。

型がobservable array 型である通常の属性には、 バッキングリスト(リスト、初期状態は空)が存在する。 仕様策定者はバッキングリストの内容を修正することができ、その内容は JavaScript コードから観測される observable array の内容にも自動的に反映される。 同様に、JavaScript コードによる observable array の内容の変更は、 インデックス付き値の設定および インデックス付き値の削除アルゴリズムを通過した後、バッキングリストにも反映される。

IDL で定数の observable array 値を表現する方法は存在しない。

次のIDLフラグメントは、 オブザーバブル配列属性を持つインターフェイスを定義します:
[Exposed=Window]
interface Building {
  attribute ObservableArray<Employee> employees;
};

属性の挙動は以下のように定義できます:

Buildingのemployees属性について、インデックス値設定アルゴリズムはemployeeとindexを受け取り:
  1. employeeが今日建物に入る許可がなければ、"NotAllowedError" DOMExceptionをthrow。

  2. indexが200以上なら、QuotaExceededError(quota=200, requested=index)をthrow。

  3. employeeを勤務開始させる。

Buildingのemployees属性について、インデックス値削除アルゴリズムはemployeeとindexを受け取り:

  1. employeeが建物から退去したことを警備に通知する。

この属性はJavaScriptコードで様々な操作が可能です:

// Buildingのインスタンス取得
const building = getBuilding();

building.employees.push(new Employee("A"));
building.employees.push(new Employee("B"));
building.employees.push(new Employee("C"));

building.employees.splice(2, 1);
const employeeB = building.employees.pop();

building.employees = [new Employee("D"), employeeB, new Employee("C")];

building.employees.length = 0;

// 例外発生:
building.employees.push("not an Employee; a string instead");

これら全ての操作は、上記で定義したインデックス値設定アルゴリズムを通り、条件次第で例外をthrowします。 また、この設定アルゴリズムとインデックス値削除アルゴリズムに記載の副作用も実行されます。

また、上記コード例で示すように、Array.prototypeの全メソッドはオブザーバブル配列で動作します。実際、完全に Arrayインスタンスとして振る舞います:

const normalArray = [];

// building.employeesがインデックス付きプロパティgetterインターフェイスの場合:normalArrayにbuilding.employeesのみ
// オブザーバブル配列(およびフローズン配列)では:normalArrayにbuilding.employees内の全アイテム
normalArray.concat(building.employees);

// namesはJS配列
const names = building.employees.map(employee => employee.name);

// ブランドチェックも通る:
console.assert(building.employees instanceof Array);
console.assert(Array.isArray(building.employees));
console.assert(building.employees.constructor === Array);

// JSON.stringifyでも配列扱い(外側の[]に注意)
console.assert(JSON.stringify(building.employees) === `[{}]`);

2.14. 拡張属性

拡張 属性とは、注釈であり 次のものに現れることができます: 定義、 注釈付き型としての型、 インターフェイス メンバー、 インターフェイスミックスイン メンバー、 コールバック インターフェイスメンバー、 名前空間 メンバー、 辞書 メンバー、 およびオペレーションの引数であり、 言語バインディングがこれらの構成要素をどのように扱うかを制御するために使用されます。 拡張属性は、 ExtendedAttributeList で指定され、 これは角括弧で囲まれ、カンマで区切られた ExtendedAttribute のリストです。

ExtendedAttribute 文法記号はほぼ任意のトークン列に合致しますが、 本書で定義される拡張属性は より制限された構文のみ許容します。 IDLフラグメント中で見つかった拡張属性は、以下の文法記号と照合されて どの形式か判定されます:

文法記号 形式 例
ExtendedAttributeNoArgs 引数なし [Replaceable]
ExtendedAttributeArgList 引数リストあり 現行標準では未使用。過去には[Constructor(double x, double y)]で使用。
ExtendedAttributeNamedArgList 名前付き引数リストあり [LegacyFactoryFunction=Image(DOMString src)]
ExtendedAttributeIdent 識別子あり [PutForwards=name]
ExtendedAttributeString 文字列あり [Reflect="popover"]
ExtendedAttributeInteger 整数あり [ReflectDefault=2]
ExtendedAttributeDecimal 小数あり [ReflectDefault=2.0]
ExtendedAttributeIntegerList 整数リストあり [ReflectRange=(2, 600)]
ExtendedAttributeIdentList 識別子リストあり [Exposed=(Window,Worker)]
ExtendedAttributeWildcard ワイルドカードあり [Exposed=*]

本現行標準ではJavaScript言語バインディングに適用可能な拡張属性がいくつか定義されており、 § 3.3 拡張属性で説明されています。 各拡張属性定義では上記のどの形式が許容されるか明示されます。

ExtendedAttributeList ::
    [ ExtendedAttribute ExtendedAttributes ]
    ε
ExtendedAttributes ::
    , ExtendedAttribute ExtendedAttributes
    ε
ExtendedAttribute ::
    ( ExtendedAttributeInner ) ExtendedAttributeRest
    [ ExtendedAttributeInner ] ExtendedAttributeRest
    { ExtendedAttributeInner } ExtendedAttributeRest
    Other ExtendedAttributeRest
ExtendedAttributeRest ::
    ExtendedAttribute
    ε
ExtendedAttributeInner ::
    ( ExtendedAttributeInner ) ExtendedAttributeInner
    [ ExtendedAttributeInner ] ExtendedAttributeInner
    { ExtendedAttributeInner } ExtendedAttributeInner
    OtherOrComma ExtendedAttributeInner
    ε
Other ::
    integer
    decimal
    identifier
    string
    other
    -
    -Infinity
    .
    ...
    :
    ;
    <
    =
    >
    ?
    *
    ByteString
    DOMString
    FrozenArray
    Infinity
    NaN
    ObservableArray
    Promise
    USVString
    any
    bigint
    boolean
    byte
    double
    false
    float
    long
    null
    object
    octet
    or
    optional
    record
    sequence
    short
    symbol
    true
    unsigned
    undefined
    ArgumentNameKeyword
    BufferRelatedType
OtherOrComma ::
    Other
    ,
IdentifierList ::
    identifier Identifiers
Identifiers ::
    , identifier Identifiers
    ε
IntegerList ::
    integer Integers
Integers ::
    , integer Integers
    ε
ExtendedAttributeNoArgs ::
    identifier
ExtendedAttributeArgList ::
    identifier ( ArgumentList )
ExtendedAttributeIdent ::
    identifier = identifier
ExtendedAttributeString ::
    identifier = string
ExtendedAttributeInteger ::
    identifier = integer
ExtendedAttributeDecimal ::
    identifier = decimal
ExtendedAttributeWildcard ::
    identifier = *
ExtendedAttributeIdentList ::
    identifier = ( IdentifierList )
ExtendedAttributeIntegerList ::
    identifier = ( IntegerList )
ExtendedAttributeNamedArgList ::
    identifier = identifier ( ArgumentList )

3. JavaScriptバインディング

この節では、§ 2 インターフェイス定義言語で定義されたIDLによる定義が ECMAScript Language Specification [ECMA-262] に定義されるJavaScriptの構成要素とどのように対応するかを説明します。

特に指定がない限り、この節で定義されるオブジェクトは ECMAScript § 10.1 Ordinary Object Internal Methods and Internal Slotsで説明される通常オブジェクトです。 オブジェクトが関数オブジェクトの場合は、 ECMAScript § 10.3 Built-in Function Objectsに従います。

この節ではオブジェクトの一部内部メソッドや内部スロットを再定義する場合があります。 他の仕様でも、プラットフォームオブジェクト (インターフェイスのインスタンス)について、 いかなる内部メソッドや内部スロットの定義も上書き可能です。 これらの意味論が変更されたオブジェクトは、エキゾチックオブジェクトの規則に従って扱われます。

JavaScriptオブジェクトの内部メソッドをオーバーライドすることは低レベルな操作であり、 通常オブジェクトと異なる挙動となる場合があるため、 セキュリティや互換性のために必要な場合以外は利用すべきではありません。 現状では HTMLAllCollection やLocation インターフェイスの定義に使われています。[HTML]

特に指定がない限り、この節や他の仕様で定義されるエキゾチックオブジェクトは、 通常オブジェクトと同じ内部スロットを持ち、 代替定義がない内部メソッドは 通常オブジェクトと同じです。

特に指定がない限り、この節で定義されるオブジェクトの[[Extensible]]内部スロット値はtrueです。

特に指定がない限り、この節で定義されるオブジェクトの[[Prototype]]内部スロットは %Object.prototype%です。

このセクションで説明される一部のオブジェクトには、クラス文字列が定義されている。 クラス文字列は、Object.prototype.toStringが返す文字列に含めるための文字列である。

オブジェクトがクラス文字列classStringを持つ場合、そのオブジェクトは作成時に、 名前が%Symbol.toStringTag% であるプロパティを持たなければならない。 PropertyDescriptor{[[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true, [[Value]]: classString} である。

この節のアルゴリズムはECMAScript § 5.2 アルゴリズム規約で説明される手順やサブ手順、数学演算などの記法慣例を用います。 また、他のECMA-262部分で定義された抽象演算や記法も参照する場合があります。

アルゴリズムで throw SomethingError と記述されている場合、 現在のrealmで JavaScriptのSomethingErrorオブジェクトを新たに構築し、 ECMA-262のアルゴリズムと同様にthrowすることを意味します。

アルゴリズムの手順は他のアルゴリズムや抽象演算を呼び出し、そこからthrowされる例外を明示的に処理しない場合があります。 例外がアルゴリズムや抽象演算からthrowされ、呼び出し元で明示的に処理されない場合、 そのアルゴリズムは終了し、例外は呼び出し元へ伝播し続けます。

次のアルゴリズムを考えます:

  1. xをこのアルゴリズムに渡されたJavaScript値とする。

  2. yを? ToString(x)の呼び出し結果とする。

  3. yを返す。

ToStringは例外をthrowし得ます(例えば({ toString: function() { throw 1 } })を渡した場合)ので、 上記アルゴリズム中で例外が処理されない場合、例外が発生するとこのアルゴリズムは終了し、 呼び出し元があればそこへ例外が伝播します。

3.1. JavaScript環境

特定のIDLフラグメントセットを JavaScriptで実装する場合、そのIDLフラグメント 定義に対応するJavaScriptオブジェクト群が存在します。 これらのオブジェクトを初期オブジェクトと呼び、以下を含みます:

各realmは、 それぞれ固有の初期オブジェクト群を持たなければならず、 それらはJavaScript実行コンテキストがrealmに入る前、かつそのrealmのグローバルオブジェクトが生成された後に作成されます。 あるrealm内の全初期オブジェクトの[[Prototype]]はそのrealm由来でなければなりません。

HTMLユーザーエージェントでは、複数のrealmが存在します(複数のフレームやウィンドウが生成された場合など)。 各フレームやウィンドウごとに独自の初期オブジェクト群があり、以下のHTML文書がこれを説明します:

<!DOCTYPE html>
<title>Different Realms</title>
<iframe id=a></iframe>
<script>
var iframe = document.getElementById("a");
var w = iframe.contentWindow;              // フレーム内のグローバルオブジェクト

Object == w.Object;                        // ECMA-262によりfalse
Node == w.Node;                            // false
iframe instanceof w.Node;                  // false
iframe instanceof w.Object;                // false
iframe.appendChild instanceof Function;    // true
iframe.appendChild instanceof w.Function;  // false
</script>

注: 全てのインターフェイスはどのrealmに公開されるか定義します。 これにより例えばWeb Workers用のrealmは Webページ用realmとは異なるインターフェイス群を公開できます。

執筆時点ではJavaScript仕様に反映されていませんが、 全てのJavaScriptオブジェクトは関連realmを持たなければなりません。 オブジェクトとrealmの関連付け機構は現状未規定ですが、 プラットフォームオブジェクトでは関連realmがオブジェクトの関連realmと等価であり、 非エキゾチックな関数オブジェクト(callable proxyやbound関数でない)は 関数オブジェクトの[[Realm]]内部スロット値と等価です。

3.2. JavaScript型マッピング

この節では、IDLの型がJavaScriptの型にどのようにマッピングされるかを説明します。

以下の各小節では、指定されたIDL型の値がJavaScriptでどのように表現されるかを説明します。各IDL型について、JavaScript値が IDL値へ変換 される方法(その型を期待するプラットフォームオブジェクトに渡された場合)、およびIDL値が その型から JavaScript値へ変換 される方法(プラットフォームオブジェクトから返される場合)を記述します。

以下の小節やアルゴリズムは、拡張属性を型ヘッダーに適用して作られる注釈付き型にも適用されます。

3.2.1. any

IDL any型は 他の全IDL型の合併であるため、すべてのJavaScript値型に対応できます。

JavaScript値VをIDL any値に 変換するアルゴリズム:

  1. Vがundefinedなら、 一意なundefined IDL値を返す。

  2. Vがnullなら、 nullのobject?参照を返す。

  3. VがBoolean型なら、 同じ真偽値を表すboolean値を返す。

  4. VがNumber型なら、 変換して unrestricted double値として返す。

  5. VがBigInt型なら、 変換して bigint値として返す。

  6. VがString型なら、 変換して DOMString値として返す。

  7. VがSymbol型なら、 変換して symbol値として返す。

  8. VがObject型なら、 Vを参照するIDL object値を返す。

IDL any値は JavaScript値へ変換 されますが、その際はIDL any値の 具体型の変換規則に従います(以降の節参照)。

3.2.2. undefined

JavaScript値VをIDL undefined値に 変換する場合、 Vを無視して一意なundefined値を返します。

一意なIDL undefined値は JavaScript値へ変換する際、 JavaScriptのundefined値となります。

3.2.3. boolean

JavaScript値VをIDL boolean値に 変換するアルゴリズム:

  1. xをToBoolean(V)の計算結果とする。

  2. JavaScript Boolean値xと同じ真偽値を表すIDL boolean値を返す。

IDL boolean値 trueはJavaScript値へ変換した時、 JavaScriptのtrue値となり、 IDL boolean値falseはJavaScriptのfalse値となります。

3.2.4. 整数型

この節で使われる数学演算は、 ECMAScript § 5.2 アルゴリズム規約で定義されたものも含め、 数学的実数上の厳密な演算として理解してください。

つまり、xがNumber値である場合、 「xに対する演算」とは 「xと同じ数値を表す数学的実数に対する演算」を意味します。

3.2.4.1. byte

JavaScript値VをIDL byte値に 変換するアルゴリズム:

  1. xを? ConvertToInt(V, 8, "signed")の結果とする。

  2. xと同じ数値を表すIDL byte値を返す。

IDL byte値を JavaScript値へ変換した結果は、 IDL byte値と同じ数値を表す Number値となります。 Number値は範囲[−128, 127]の整数です。

3.2.4.2. octet

JavaScript値VをIDL octet値に 変換するアルゴリズム:

  1. xを? ConvertToInt(V, 8, "unsigned")の結果とする。

  2. xと同じ数値を表すIDL octet値を返す。

IDL octet値を JavaScript値へ変換した結果は、 IDL octet値と同じ数値を表す Number値となります。 Number値は範囲[0, 255]の整数です。

3.2.4.3. short

JavaScript値VをIDL short値に 変換するアルゴリズム:

  1. xを? ConvertToInt(V, 16, "signed")の結果とする。

  2. xと同じ数値を表すIDL short値を返す。

IDL short値を JavaScript値へ変換した結果は、 IDL short値と同じ数値を表す Number値となります。 Number値は範囲[−32768, 32767]の整数です。

3.2.4.4. unsigned short

JavaScript値VをIDL unsigned short値に 変換するアルゴリズム:

  1. xを? ConvertToInt(V, 16, "unsigned")の結果とする。

  2. xと同じ数値を表すIDL unsigned short値を返す。

IDL unsigned short値を JavaScript値へ変換した結果は、 IDL unsigned short値と同じ数値を表す Number値となります。 Number値は範囲[0, 65535]の整数です。

3.2.4.5. long

JavaScript値VをIDL long値に 変換するアルゴリズム:

  1. xを? ConvertToInt(V, 32, "signed")の結果とする。

  2. xと同じ数値を表すIDL long値を返す。

IDL long値を JavaScript値へ変換した結果は、 IDL long値と同じ数値を表す Number値となります。 Number値は範囲[−2147483648, 2147483647]の整数です。

3.2.4.6. unsigned long

JavaScript値VをIDL unsigned long値に 変換するアルゴリズム:

  1. xを? ConvertToInt(V, 32, "unsigned")の結果とする。

  2. xと同じ数値を表すIDL unsigned long値を返す。

IDL unsigned long値を JavaScript値へ変換した結果は、 IDL unsigned long値と同じ数値を表す Number値となります。 Number値は範囲[0, 4294967295]の整数です。

3.2.4.7. long long

JavaScript値VをIDL long long値に 変換するアルゴリズム:

  1. xを? ConvertToInt(V, 64, "signed")の結果とする。

  2. xと同じ数値を表すIDL long long値を返す。

IDL long long値を JavaScript値へ変換した結果は、 long longに最も近い数値を表すNumber値となり、 2つの値が同じだけ近い場合は有効数字が偶数の方を選択します。 long longが範囲 [−253 + 1, 253 − 1]内なら、Numberは long longと全く同じ値を表せます。

3.2.4.8. unsigned long long

JavaScript値VをIDL unsigned long long値に 変換するアルゴリズム:

  1. xを? ConvertToInt(V, 64, "unsigned")の結果とする。

  2. xと同じ数値を表すIDL unsigned long long値を返す。

IDL unsigned long long値を JavaScript値へ変換した結果は、 unsigned long longに最も近い数値を表すNumber値となり、 2つの値が同じだけ近い場合は有効数字が偶数の方を選択します。 unsigned long longが253−1以下なら、Numberは unsigned long longと全く同じ値を表せます。

3.2.4.9. 抽象演算

IntegerPart(n):

  1. rをfloor(abs(n))とする。

  2. もしn<0なら−1×rを返す。

  3. それ以外ならrを返す。

ConvertToInt(V, bitLength, signedness):

  1. bitLength が 64 の場合:

    1. upperBound を 253 − 1 とします。

    2. signedness が "unsigned" の場合、lowerBound を 0 とします。

    3. そうでない場合、lowerBound を −253 + 1 とします。

      注: これにより、long long 型で、 関連付けられた [EnforceRange] または [Clamp] 拡張属性を持つものが、 JavaScript の Number 型 で曖昧さのない整数として表現可能であることが保証される。

  2. そうでなく、signedness が "unsigned" の場合:

    1. lowerBound を 0 とします。

    2. upperBound を 2bitLength − 1 とします。

  3. そうでない場合:

    1. lowerBound を -2bitLength − 1 とします。

    2. upperBound を 2bitLength − 1 − 1 とします。

  4. x を ? ToNumber(V) とします。

  5. x が −0 の場合、x を +0 に設定します。

  6. 変換先が、次の IDL 型に関連付けられた [EnforceRange] 拡張属性を持つ場合:

    1. x が NaN、+∞、または −∞ の場合、 TypeError をスローする。

    2. x を IntegerPart(x) に設定する。

    3. x < lowerBound または x > upperBound の場合、 TypeError をスローする。

    4. x を返す。

  7. x が NaN でなく、変換先が IDL 型であり、 関連付けられた [Clamp] 拡張属性を持つ 場合:

    1. x を min(max(x, lowerBound), upperBound) に設定します。

    2. x を最も近い整数に丸め、ちょうど中間にある場合は偶数の整数を選択し、 2 つの整数の間で、 −0 ではなく +0 を選択します。

    3. x を返します。

  8. x が NaN、+0、+∞、または −∞ の場合、 +0 を返します。

  9. x を IntegerPart(x) に設定します。

  10. x を x modulo 2bitLength に設定します。

  11. signedness が "signed" で、x ≥ 2bitLength − 1 の場合、 x − 2bitLength を返します。

  12. そうでない場合、x を返します。

3.2.5. float

JavaScript値VをIDL float値に 変換するアルゴリズム:

  1. xを? ToNumber(V)とする。

  2. xがNaN、+∞、−∞なら throw TypeError。

  3. Sを有限なIEEE 754単精度浮動小数点値集合(−0を除く)とし、2つの特殊値2128と−2128を加える。

  4. yをxに最も近いS内の値とし、2つの値が同じだけ近い場合は有効数字が偶数の方を選択する。 (この目的で2128と−2128は有効数字が偶数と見なす。)

  5. yが2128または−2128なら throw TypeError。

  6. yが+0かつxが負なら−0を返す。

  7. yを返す。

IDL float値を JavaScript値へ変換した結果は、 IDL float値と同じ数値を表す Number値です。

3.2.6. unrestricted float

JavaScript値VをIDL unrestricted float値に 変換するアルゴリズム:

  1. xを? ToNumber(V)とする。

  2. xがNaNなら、 IEEE 754 NaN値(ビットパターン0x7fc00000)を表すIDL unrestricted float値を返す。 [IEEE-754]

  3. Sを有限なIEEE 754単精度浮動小数点値集合(−0を除く)とし、2つの特殊値2128と−2128を加える。

  4. yをxに最も近いS内の値とし、2つの値が同じだけ近い場合は有効数字が偶数の方を選択する。 (この目的で2128と−2128は有効数字が偶数と見なす。)

  5. yが2128なら+∞を返す。

  6. yが−2128なら−∞を返す。

  7. yが+0かつxが負なら−0を返す。

  8. yを返す。

注: JavaScriptのNaN値は1つしかないため、 特定の単精度IEEE 754 NaN値に正規化する必要があります。上記で言及したNaN値は、ビットパターンを32ビット符号なし整数として解釈したとき最小値のquiet NaNです。

IDL unrestricted float値を JavaScript値へ変換した結果はNumber値です:

  1. IDL unrestricted float値がNaNなら、 Number値はNaNです。

  2. それ以外は、IDL unrestricted float値と同じ数値を表すNumber値です。

3.2.7. double

JavaScript値VをIDL double値に 変換するアルゴリズム:

  1. xを? ToNumber(V)とする。

  2. xがNaN、+∞、−∞なら throw TypeError。

  3. xと同じ数値を表すIDL double値を返す。

IDL double値を JavaScript値へ変換した結果は、 IDL double値と同じ数値を表す Number値です。

3.2.8. unrestricted double

JavaScript値VをIDL unrestricted double値に 変換するアルゴリズム:

  1. xを? ToNumber(V)とする。

  2. xがNaNなら、 IEEE 754 NaN値(ビットパターン0x7ff8000000000000)を表すIDL unrestricted double値を返す。 [IEEE-754]

  3. xと同じ数値を表すIDL unrestricted double値を返す。

注: JavaScriptのNaN値は1つしかないため、 特定の倍精度IEEE 754 NaN値に正規化する必要があります。上記で言及したNaN値は、ビットパターンを64ビット符号なし整数として解釈したとき最小値のquiet NaNです。

IDL unrestricted double値を JavaScript値へ変換した結果はNumber値です:

  1. IDL unrestricted double値がNaNなら、 Number値はNaNです。

  2. それ以外は、IDL unrestricted double値と同じ数値を表すNumber値です。

3.2.9. bigint

JavaScript値VをIDL bigint値に 変換するアルゴリズム:

  1. xを? ToBigInt(V)とする。

  2. xと同じ数値を表すIDL bigint値を返す。

IDL bigint値を JavaScript値へ変換した結果はBigInt値です:

  1. IDL BigInt値で、 IDL bigint値と同じ数値を表すものを返す。

JavaScript値VをIDL 数値型 Tまたはbigint値に 変換するアルゴリズム:

  1. xを? ToNumeric(V)とする。

  2. xがBigInt型なら:

    1. xと同じ数値を表すIDL bigint値を返す。

  3. (アサーション)xはNumber型。

  4. Tへの変換結果を返す。

3.2.10. DOMString

JavaScript 値 V は、変換されて IDL DOMString 値になります。次のアルゴリズムを実行します:

  1. V が null であり、変換先が次の IDL 型で、 関連付けられた [LegacyNullToEmptyString] 拡張 属性を持つ場合、空文字列を表す DOMString 値を返します。

  2. x を ? ToString(V) とします。

  3. IDL DOMString 値を返します。これは JavaScript String 値が表すものと同じコード単位の列を x が表すものです。

IDL DOMString 値を JavaScript 値に変換した結果は、 IDL DOMString が表すものと同じコード単位の列を表す String 値です。

3.2.11. ByteString

JavaScript値VをIDL ByteString値に 変換するアルゴリズム:

  1. xを? ToString(V)とする。

  2. xのいずれかの要素値が255を超える場合、 throw TypeError。

  3. xの長さと同じ長さで、各要素の値がxの対応する要素値と同じIDL ByteString値を返す。

IDL ByteString値を JavaScript値へ変換した結果は、 ByteStringの長さと同じ長さで、 各要素値が対応する ByteStringの要素値と同じ String値です。

3.2.12. USVString

JavaScript値VをIDL USVString値に 変換するアルゴリズム:

  1. stringをVをDOMStringに変換した結果とする。

  2. stringをスカラー値列へ変換した結果を持つIDL USVString値を返す。

IDL USVString値Sを JavaScript値へ変換した結果はSです。

3.2.13. object

IDL object値は JavaScriptのObject値で表現されます。

JavaScript値VをIDL object値に 変換するアルゴリズム:

  1. VがObject型でない場合、 throw TypeError。

  2. Vと同じオブジェクトを参照するIDL object値を返す。

IDL object値を JavaScript値へ変換した結果は、 IDL objectが 参照する同一オブジェクトを参照するObject値です。

3.2.14. symbol

IDL symbol値は JavaScriptのSymbol値で表現されます。

JavaScript値VをIDL symbol値に 変換するアルゴリズム:
  1. VがSymbol型でない場合、 throw TypeError。

  2. Vと同じSymbolを参照するIDL symbol値を返す。

IDL symbol値を JavaScript値へ変換した結果は、 IDL symbolが 参照する同一Symbolを参照するSymbol値です。

3.2.15. インターフェイス型

IDL インターフェイス型値は JavaScriptのObject値(関数オブジェクトも含む)で表現されます。

JavaScript値VをIDL インターフェイス型値に 変換するアルゴリズム(Iはインターフェイス):

  1. VがIを実装していれば、そのプラットフォームオブジェクトへの参照を表すIDL インターフェイス型値を返す。

  2. throw TypeError。

IDL インターフェイス型値を JavaScript値へ変換した結果は、 IDL インターフェイス型値が参照する同一オブジェクトを参照する Object値です。

3.2.16. コールバックインターフェイス型

IDL コールバックインターフェイス型値は JavaScriptのObject値(関数オブジェクトも含む)で表現されます。

JavaScript値VをIDL コールバックインターフェイス型値に 変換するアルゴリズム:

  1. VがObject型でない場合、 throw TypeError。

  2. Vへの参照を持つIDL コールバックインターフェイス型値を返す。 この時現任設定オブジェクトをコールバックコンテキストとする。

IDL コールバックインターフェイス型値を JavaScript値へ変換した結果は、 IDL コールバックインターフェイス型値が参照する同一オブジェクトを参照する Object値です。

3.2.17. 辞書型

IDL 辞書型の値 は JavaScript Object 値で表現されます。その オブジェクト(またはそのプロトタイプチェーン)上のプロパティは、辞書メンバーに対応します。

JavaScript 値 jsDict は、変換されて IDL 辞書 型の値になります。 次のアルゴリズムを実行します(D は辞書型です):

  1. jsDict が Object で はなく、かつ jsDict が undefined でも null でもない場合、TypeError をスローする。

  2. idlDict を空の 順序付きマップとし、 型 D の辞書を表すものとする。

  3. dictionaries を、D と D のすべての 継承された辞書からなるリストとし、 派生度の低いものから高いものの順とする。

  4. dictionaries 内の各辞書 dictionary について、順に:

    1. dictionary で宣言された各辞書メンバー member について、 辞書式順に:

      1. key を member の 識別子とする。

      2. jsDict が undefined または null のいずれかである場合:

        1. jsMemberValue を undefined とする。

      3. それ以外の場合、

        1. jsMemberValue を ? Get(jsDict, key) とする。

      4. jsMemberValue が undefined でない場合:

        1. idlMemberValue を、変換した jsMemberValue の結果で、その型が member に対して宣言された型である IDL 値とする。

        2. idlDict[key] を idlMemberValue に設定する。

      5. それ以外で、jsMemberValue が undefined だが member に デフォルト値がある場合:

        1. idlMemberValue を member のデフォルト値とする。

        2. idlDict[key] を idlMemberValue に設定する。

      6. それ以外で、jsMemberValue が undefined であり、 member が 必須である場合、TypeError をスローする。

  5. idlDict を返す。

注: 辞書メンバーが JavaScript オブジェクト上で検索される 順序は、必ずしもオブジェクトのプロパティ列挙順序と同じではありません。

IDL 辞書値 V は、変換されて JavaScript Object 値になります。 次のアルゴリズムを実行します(D は辞書です):

  1. O を OrdinaryObjectCreate(%Object.prototype%) とします。

  2. dictionaries を、D と D のすべての継承された辞書からなるリストとし、 派生の少ないものから多いものの順に並べます。

  3. dictionaries 内の各辞書 dictionary について、順番に:

    1. dictionary で宣言された各辞書メンバー member について、 辞書式順に:

      1. key を member の識別子とします。

      2. V[key] が存在する場合:

        1. idlValue を V[key] とします。

        2. value を、変換した結果、 idlValue を JavaScript 値にしたものとします。

        3. ! CreateDataPropertyOrThrow(O, key, value) を実行します。

        member にデフォルト値がある場合、 key は常に V に存在することを思い出してください。

  4. O を返します。

3.2.18. 列挙型

IDL 列挙型は JavaScriptのString値で表現されます。

JavaScript値VをIDL 列挙型値に 変換する手順(Eは列挙型):

  1. Sを? ToString(V)の結果とする。

  2. SがEの列挙値のいずれでもなければ、 throw TypeError。

  3. Sと等しい型Eの列挙値を返す。

IDL 列挙型値を JavaScript値へ変換した結果は、 コード単位列が 列挙値と同じであるString値です。

3.2.19. コールバック関数型

IDL コールバック関数型は JavaScriptの関数オブジェクトで表現されます。 ただし[LegacyTreatNonObjectAsNull]の場合は任意のオブジェクトも可です。

JavaScript 値 V は、変換されて IDL コールバック関数型の値になります。次の アルゴリズムを実行します:

  1. IsCallable(V) を呼び出した結果が false であり、IDL 値への変換が V が、 型がnull 許容の コールバック関数である属性に代入されたために 行われているのではなく、そのコールバック関数に [LegacyTreatNonObjectAsNull] が注釈されている場合、 TypeError を送出します。

  2. V が表すものと同じオブジェクトへの参照を表す IDL コールバック関数型の値を返します。その 現 incumbent settings object をコールバックコンテキストとします。

IDL コールバック関数型値を JavaScript値へ変換した結果は、 IDL コールバック関数型値が参照する同一オブジェクトを参照する値です。

3.2.20. nullable型 — T?

IDL null 許容型の 値は、 内部 IDL 型に対応する JavaScript 型の値、または JavaScript の null 値によって表現されます。

JavaScript 値 V は、変換されて IDL null 許容 型 T? 値になります(ここで T は内部型です)。変換は次のとおりです:

  1. V がObject ではなく、 IDL 値への変換が、 V が属性に代入されたことにより行われており、 その型がnull 許容の コールバック関数で、 [LegacyTreatNonObjectAsNull] が注釈されている場合、 IDL null 許容 型 T? の値 null を返します。

  2. そうでなく、V が undefined であり、 T がundefined を含む場合、 一意の undefined 値を返します。

  3. そうでなく、V が null または undefined の場合、 IDL null 許容 型 T? の値 null を返します。

  4. そうでない場合、 変換した結果を返します。V を 内部 IDL 型 T の規則を使用して変換します。

IDL null 許容 型の値を JavaScript 値に変換した結果は次のとおりです:

  1. IDL null 許容型 T? の値が null の場合、 JavaScript 値は null です。

  2. そうでない場合、JavaScript 値は、 IDL 変換の結果です。 null 許容型の IDL 値を 内部 IDL 型 T に変換します。

3.2.21. sequence型 — sequence<T>

IDL sequence<T>値は JavaScriptのArray値で表現されます。

JavaScript値VをIDL sequence<T>値に 変換する手順:

  1. VがObject型でない場合、 throw TypeError。

  2. methodを? GetMethod(V, %Symbol.iterator%)の結果とする。

  3. methodがundefinedなら、 throw TypeError。

  4. Vとmethodからsequenceの生成を行った結果を返す。

型sequence<T>の IDL sequence値Sを JavaScriptのArrayオブジェクトに変換する手順:

  1. nをSの長さとする。

  2. Aを[]式で生成した新しいArrayオブジェクトとする。

  3. iを0で初期化。

  4. i<nの間:

    1. VをSのインデックスiの値とする。

    2. EをVをJavaScript値へ変換した結果とする。

    3. Pを! ToString(i)の結果とする。

    4. ! CreateDataPropertyOrThrow(A, P, E)を実行。

    5. iをi+1にする。

  5. Aを返す。

3.2.21.1. イテラブルからsequenceの生成

イテラブルiterableとイテレータ取得メソッドmethodが与えられたとき、型sequence<T>のIDL値を生成するには、以下の手順を行う:

  1. iteratorRecordを? GetIteratorFromMethod(iterable, method)の結果とする。

  2. iを0で初期化。

  3. 繰り返し:

    1. nextを? IteratorStepValue(iteratorRecord)の結果とする。

    2. nextがdoneなら、 長さiの型sequence<T>のIDL値を返す。 インデックスjの要素の値はSjとする。

    3. Siをnextを型TのIDL値に変換した結果で初期化。

    4. iをi+1にする。

次のインターフェイスは sequence型属性とsequence型引数を持つ操作を定義する。

[Exposed=Window]
interface Canvas {

  sequence<DOMString> getSupportedImageCodecs();

  undefined drawPolygon(sequence<double> coordinates);
  sequence<double> getLastDrawnPolygon();

  // ...
};

このインターフェイスのJavaScript実装では、要素型がStringのArrayオブジェクトがsequence<DOMString>を、 要素型がNumberのArrayがsequence<double>を表現する。 Arrayオブジェクトは事実上値渡しとなる。 getSupportedImageCodecs()関数の呼び出しごとに新しいArrayが返り、 ArrayがdrawPolygonに渡された場合も呼び出し完了後は参照が保持されない。

// Canvasインスタンス取得。getSupportedImageCodecs()は
// 2つのDOMString値:"image/png"と"image/svg+xml"からなるsequenceを返すと仮定。
var canvas = getCanvas();

// 長さ2のArrayオブジェクト。
var supportedImageCodecs = canvas.getSupportedImageCodecs();

// "image/png"を返す。
supportedImageCodecs[0];

// canvas.getSupportedImageCodecs()の呼び出しごとに新しいArrayオブジェクトが返る。
// 返されたArrayを変更しても、次の呼び出しの戻り値には影響しない。
supportedImageCodecs[0] = "image/jpeg";

// "image/png"を返す。
canvas.getSupportedImageCodecs()[0];

// 常に新しいArrayが返るので、==で比較するとfalse。
canvas.getSupportedImageCodecs() == canvas.getSupportedImageCodecs();

// NumberのArray...
var a = [0, 0, 100, 0, 50, 62.5];

// ...はsequence<double>を期待するプラットフォームオブジェクトに渡せる。
canvas.drawPolygon(a);

// 各要素はまずToNumber()でdoubleに変換される。
// 次の呼び出しは前のものと同じだが、"hi"はdrawPolygon()の戻り前にalertされる。
a = [false, "",
     { valueOf: function() { alert("hi"); return 100; } }, 0,
     "50", new Number(62.5)];
canvas.drawPolygon(a);

// drawPolygon()に渡したArrayを変更してもCanvasには影響しない(値渡し)。
a[4] = 20;
var b = canvas.getLastDrawnPolygon();
alert(b[4]);    // "50"がalertされる。

3.2.22. 非同期sequence型 — async_sequence<T>

JavaScriptバインディングにおいて、IDL async sequence値は 以下の項目を持つ構造体として表現される:

JavaScript値VをIDL async_sequence<T>値に 変換する手順:
  1. VがObject型でない場合、 throw TypeError。

  2. methodを? GetMethod(obj, %Symbol.asyncIterator%)の結果とする。

  3. methodがundefinedの場合:

    1. syncMethodを? GetMethod(obj, %Symbol.iterator%)の結果とする。

    2. syncMethodがundefinedならthrow TypeError。

    3. IDL async sequence値を返す。objectにV、 methodにsyncMethod、 typeに"sync"を設定。

  4. IDL async sequence値を返す。objectにV、 methodにmethod、 typeに"async"を設定。

IDL async_sequence<T>値Vを JavaScriptオブジェクトに変換する手順:
  1. Vのobjectを返す。

3.2.22.1. 非同期sequenceのイテレーション

async sequenceは直接イテレートされません。まずオープンして非同期イテレータを作成し、その非同期イテレータを非同期的にイテレートして値を生成します。

非同期イテレータは、以下の構造体の項目を持ちます:

async sequenceのオープン手順: async_sequence<T> sequenceについて:

  1. iteratorを? GetIteratorFromMethod(sequenceのobject, sequenceのmethod)とする。

  2. sequenceのtypeが"sync"の場合は iteratorをCreateAsyncFromSyncIterator(iterator)の結果に置換する。

  3. 非同期イテレータ値を返す。 underlying recordにiterator、 type parameterにTを設定。

非同期イテレータの次の値取得手順: 非同期イテレータ iteratorについて:

  1. nextResultを IteratorNext(iteratorのunderlying record)の結果とする。

  2. nextResultがabrupt completionなら、その値でrejectされたpromiseを返す。

  3. nextPromiseをnextResultの値でresolveされたpromiseとする。

  4. nextPromiseに対して、以下のfulfilledステップで反応する(iterResultを与える):

    1. iterResultがObject型でない場合は、throw TypeError。

    2. doneを? IteratorComplete(iterResult)の結果とする。

    3. もしdoneがtrueなら:

      1. イテレーション終了を返す。

    4. それ以外:

      1. Vを? IteratorValue(iterResult)の結果とする。

      2. valueをVをiteratorのtype parameter型のIDL値に変換した結果とする。

      3. valueを返す。

非同期イテレータのクローズ手順: async iterator<T> iterator(ECMAScript値reason付き)について:

  1. iteratorRecordをiteratorのunderlying recordとする。

  2. iteratorObjをiteratorRecord.[[Iterator]]とする。

  3. returnMethodをGetMethod(iteratorObj, "return")の結果とする。

  4. returnMethodがabrupt completionなら、その値でrejectされたpromiseを返す。

  5. returnMethodがundefinedなら、undefinedでresolveされたpromiseを返す。

  6. returnResultをCall(returnMethod.[[Value]], iteratorObj, « reason »)の結果とする。

  7. returnResultがabrupt completionなら、その値でrejectされたpromiseを返す。

  8. returnPromiseをreturnResultの値でresolveされたpromiseとする。

  9. returnPromiseに対して、以下のfulfilledステップで反応する(returnPromiseResultを与える):

    1. returnPromiseResultがObject型でない場合は、throw TypeError。

    2. undefinedを返す。

concatNは、引数で渡されたasync sequenceがyieldする全ての文字列を連結した結果を返すpromiseを返す操作です。async sequenceがmaxN個の文字列をyieldしたらそこで連結・イテレータをクローズします。

interface I {
  Promise<DOMString> concatN(async_sequence<DOMString> strings, unsigned long maxN);
};

concatN(sequence, maxN)メソッドの手順:

  1. promiseを新しいpromiseとする。

  2. resultを空文字列で初期化。

  3. nを0で初期化。

  4. iteratorをsequenceをオープンした結果とする。

  5. stepをasync sequenceを処理する手順列とする:

    1. nextをiteratorの次の値取得の結果とする。

    2. nextに反応する:

      • nextが値vでfulfilledされた場合:

        1. vがイテレーション終了ならpromiseをresultでresolve。

        2. resultにvを連結した結果でresultを更新。

        3. nをn+1に。

        4. nがmaxNなら:

          1. finishをiteratorを理由undefinedでクローズした結果とする。

          2. finishに反応する:

            • finishがfulfilledならpromiseをresultでresolve。

            • finishが理由rでrejectedならpromiseをrでreject。

        5. それ以外:

          1. stepを呼び出す。

      • nextが理由rでrejectedされた場合はpromiseをrでreject。

  6. stepを呼び出す。

  7. promiseを返す。

3.2.23. record型 — record<K, V>

IDL record<K, V>値は JavaScriptのObject値で表現されます。

JavaScript値OをIDL record<K, V>値に 変換する手順:

  1. OがObject型でない場合、 throw TypeError。

  2. resultを新しい空の record<K, V>インスタンスで初期化。

  3. keysを? O.[[OwnPropertyKeys]]()の結果とする。

  4. keysの各 keyについて:

    1. descを? O.[[GetOwnProperty]](key)の結果とする。

    2. descがundefinedでなく、かつdesc.[[Enumerable]]がtrueなら:

      1. typedKeyをkeyを型KのIDL値に変換した結果とする。

      2. valueを? Get(O, key)の結果とする。

      3. typedValueをvalueを型VのIDL値に変換した結果とする。

      4. Set result[typedKey] = typedValue。

        注: KがUSVStringでkeyにペアでないサロゲートが含まれる場合、 typedKeyがすでにresultに存在する可能性があります。

  5. resultを返す。

IDL record<…>値Dを JavaScript値へ変換する手順:

  1. resultをOrdinaryObjectCreate(%Object.prototype%)で初期化。

  2. Dの各key→valueについて:

    1. jsKeyをkeyをJavaScript値に変換した結果とする。

    2. jsValueをvalueをJavaScript値に変換した結果とする。

    3. createdを! CreateDataProperty(result, jsKey, jsValue)の結果とする。

    4. (アサーション)createdはtrueである。

  3. resultを返す。

JavaScript値{b: 3, a: 4}を record<DOMString, double>型引数として渡した場合、 IDL値「[ "b" → 3, "a" → 4 ]」となります。

Recordは自分自身の enumerableプロパティのみを考慮します。 したがって、以下のIDL操作 record<DOMString, double> identity(record<DOMString, double> arg)が引数をそのまま返す場合、下記のコードはアサーションをパスします:

let proto = {a: 3, b: 4};
let obj = {__proto__: proto, d: 5, c: 6}
Object.defineProperty(obj, "e", {value: 7, enumerable: false});
let result = identity(obj);
console.assert(result.a === undefined);
console.assert(result.b === undefined);
console.assert(result.e === undefined);
let entries = Object.entries(result);
console.assert(entries[0][0] === "d");
console.assert(entries[0][1] === 5);
console.assert(entries[1][0] === "c");
console.assert(entries[1][1] === 6);

Recordのキーと値には制約を設けられますが、キーは3つの文字列型間のみ制約できます。 下記の変換結果は次の通りです:

値 渡される型 結果
{"😞": 1} record<ByteString, double> TypeError
{"\uD83D": 1} record<USVString, double> «[ "\uFFFD" → 1 ]»
{"\uD83D": {hello: "world"}} record<DOMString, double> «[ "\uD83D" → 0 ]»

3.2.24. Promise型 — Promise<T>

IDL promise型値は JavaScriptのPromiseCapabilityレコードで表現されます。

JavaScript値VをIDL Promise<T>値に 変換する手順:

  1. promiseCapabilityを? NewPromiseCapability(%Promise%)で初期化。

  2. ? Call(promiseCapability.[[Resolve]], undefined, « V »)を実行。

  3. promiseCapabilityを返す。

IDL promise型値を JavaScript値へ変換した結果は、 IDL promise型値が表すレコードの[[Promise]]フィールドの値です。

JSの値をPromise<T>のIDL値に変換する場合、 まず値は(IDLの)Promiseでラップされ、 その後の仕組みによりプロミスが正しくT型の値に 解決されることが保証されます。

これはたとえば、 Promise<T>型の引数を取ると定義されたメソッドが 自動的にPromise オブジェクト (最終的にTオブジェクトに解決される必要あり)と Tオブジェクト自体の両方を受け入れることを 意味します。

(さらに、最初は他のどんな型のオブジェクトも受け付けますが、 型が違う場合は 後でプロミスが自動的に拒否されます。)

3.2.24.1. Promiseの生成・操作

新しいPromiseの生成手順: Promise<T>を realm realmで生成するには:

  1. constructorをrealm.[[Intrinsics]].[[%Promise%]]とする。

  2. ? NewPromiseCapability(constructor)を返す。

resolveされたpromiseの生成手順: Promise<T> 型で値x(型T)をrealm realmに持つ場合:

  1. valueをxをJavaScript値に変換した結果とする。

  2. constructorをrealm.[[Intrinsics]].[[%Promise%]]とする。

  3. promiseCapabilityを? NewPromiseCapability(constructor)で初期化。

  4. ! Call(promiseCapability.[[Resolve]], undefined, « value »)を実行。

  5. promiseCapabilityを返す。

rejectされたpromiseの生成手順: Promise<T> 型で理由r(JavaScript値)をrealm realmに持つ場合:

  1. constructorをrealm.[[Intrinsics]].[[%Promise%]]とする。

  2. promiseCapabilityを? NewPromiseCapability(constructor)で初期化。

  3. ! Call(promiseCapability.[[Reject]], undefined, « r »)を実行。

  4. promiseCapabilityを返す。

resolve手順: Promise<T> pを値x(型T)でresolveするには:

  1. xが与えられていない場合は、一意なundefined値とする。

  2. valueをxをJavaScript値に変換した結果とする。

  3. ! Call(p.[[Resolve]], undefined, « value »)を実行。

Tがundefinedなら、 x引数は省略可能であり、簡易な「resolve p」用法が可能です。

reject手順: Promise<T> pを理由r(JavaScript値)でrejectするには:

  1. ! Call(p.[[Reject]], undefined, « r »)を実行。

promiseへの反応手順: Promise<T> promiseに対して、fulfilled/rejectedまたは両方の場合の処理手順を与えて以下を実行:

  1. 引数Vで呼ばれるonFulfilledStepsを以下とする:

    1. valueをVを型TのIDL値に変換した結果とする。

    2. promiseがfulfilledの場合に実行する手順があれば、resultをその手順をvalue(Tがundefined以外の場合のみ)で実行した結果とし、 それ以外はresultをvalueとする。

    3. resultをJavaScript値に変換して返す。

  2. onFulfilledをCreateBuiltinFunction(onFulfilledSteps, 1, "", « »)とする。

  3. 引数Rで呼ばれるonRejectedStepsを以下とする:

    1. reasonをRを型anyのIDL値に変換した結果とする。

    2. promiseがrejectedの場合に実行する手順があれば、resultをその手順をreasonで実行した結果とし、 それ以外はresultをreasonでrejectされたpromiseとする。

    3. resultをJavaScript値に変換して返す。

  4. onRejectedをCreateBuiltinFunction(onRejectedSteps, 1, "", « »)とする。

  5. constructorをpromise.[[Promise]].[[Realm]].[[Intrinsics]].[[%Promise%]]とする。

  6. newCapabilityを? NewPromiseCapability(constructor)で初期化。

    注: 返したPromiseを 呼び出し側が必ず使うとは限りません。実装によってはnewCapabilityの生成を省略してよい場合があります。

  7. PerformPromiseThen(promise.[[Promise]], onFulfilled, onRejected, newCapability)を実行。

  8. newCapabilityを返す。

注: このアルゴリズムは promise.then() メソッドと非常に似た動作をします。 特に、手順が型UまたはPromise<U>値を返す場合、 このアルゴリズムもPromise<U>を返します。

fulfillment時の処理手順: Promise<T> promiseのfulfillment時に型Tの値を受け取る手順stepsを実行するには:

  1. promiseへの反応手順の結果を返す:

    • promiseが値vでfulfilledされた場合:

      1. stepsをvで実行。

rejection時の処理手順: Promise<T> promiseのrejection時にJavaScript値を受け取る手順stepsを実行するには:

  1. promiseへの反応手順の結果を返す:

    • promiseが理由rでrejectedされた場合:

      1. stepsをrで実行。

全てを待つ手順: list型 Promise<T> 値promises、成功時手順successSteps(list型T値を受け取る)、失敗時手順failureSteps(理由any値を受け取る)について:

  1. fullfilledCountを0で初期化。

  2. rejectedをfalseで初期化。

  3. rejectionHandlerStepsを引数argで呼ばれる以下の手順とする:

    1. rejectedがtrueならこの手順を中止。

    2. rejectedをtrueにする。

    3. failureStepsをargで実行。

  4. rejectionHandlerをCreateBuiltinFunction(rejectionHandlerSteps, 1, "", « »)とする。

  5. totalをpromisesのsizeとする。

  6. totalが0なら:

    1. マイクロタスクをキューしてsuccessStepsに« »を与えて実行。

    2. return。

  7. indexを0で初期化。

  8. resultをtotal個のnull値のlistで初期化。

  9. promisesの各promiseについて:

    1. promiseIndexをindexとする。

    2. fulfillmentHandlerを引数argで呼ばれる以下の手順とする:

      1. result[promiseIndex]にargをセット。

      2. fullfilledCountをfullfilledCount+1に。

      3. fullfilledCountがtotalと等しければsuccessStepsにresultを与えて実行。

    3. fulfillmentHandlerをCreateBuiltinFunction(fulfillmentHandler, 1, "", « »)とする。

    4. PerformPromiseThen(promise, fulfillmentHandler, rejectionHandler)を実行。

    5. indexをindex+1に。

全てを待つpromiseの取得手順: list型 Promise<T> 値promisesと realm realmについて:

  1. promiseを新しいPromise型Promise<sequence<T>> をrealmで生成した結果とする。

  2. successStepsを引数resultsで呼ばれる以下の手順とする:

    1. resolve promiseをresultsで実行。

  3. failureStepsを引数reasonで呼ばれる以下の手順とする:

    1. reject promiseをreasonで実行。

  4. 全てを待つ手順に promises、successSteps、failureStepsを与えて実行。

  5. promiseを返す。

この定義は複数promiseの結果を集約して新たなpromiseを生成したい場合に有用です。 これはJavaScriptのPromise.all()と同様です。 新たなpromiseが不要なら全てを待つ手順の方が適しています。

handledとしてマーク手順: Promise<T> promiseについて promise.[[Promise]].[[PromiseIsHandled]]をtrueに設定する。

この定義はrejectされることが多く無視されるpromiseに有用です。 これによりunhandledrejectionイベントを発生させません。 よくある例はプロミスプロパティで、Web開発者が参照する場合と参照しない場合があります。 例としてwritableStreamWriter.closedプロパティのpromiseがあります。

3.2.24.2. 例

delayは操作で、指定したミリ秒後にfulfilledされるpromiseを返します。 Promiseをresolveする方法のシンプルな例です。

interface I {
  Promise<undefined> delay(unrestricted double ms);
};

delay(ms)メソッドの手順:

  1. realmをthisの 関連realmとする。

  2. taskSourceを適切なタスクソースとする。

  3. msがNaNならmsを+0とし、そうでなければmsと+0の大きい方にする。

  4. pを新しいpromiseをrealmで生成したものとする。

  5. 以下の手順を並行して行う:

    1. msミリ秒待つ。

    2. タスクをキューしてtaskSource上でresolve pを行う。

  6. pを返す。

validatedDelayは操作で、delay関数と似ていますが 引数のバリデーションを行います。 非同期処理開始前に即時rejectされたpromiseを使う例です。

interface I {
  Promise<undefined> validatedDelay(unrestricted double ms);
};

validatedDelay(ms)メソッドの手順:

  1. realmをthisの 関連realmとする。

  2. taskSourceを適切なタスクソースとする。

  3. msがNaNならTypeErrorでrejectされたpromiseをrealmで返す。

  4. msが0未満ならRangeErrorでrejectされたpromiseをrealmで返す。

  5. pを新しいpromiseをrealmで生成したものとする。

  6. 以下の手順を並行して行う:

    1. msミリ秒待つ。

    2. タスクをキューしてtaskSource上でresolve pを行う。

  7. pを返す。

addDelayは操作で、promiseのsettle後に追加で指定した遅延(ms)を加えて 新しいpromiseのsettleを遅らせます。

interface I {
  Promise<any> addDelay(Promise<any> promise, unrestricted double ms);
};

addDelay(ms, promise)メソッドの手順:

  1. realmをthisの 関連realmとする。

  2. taskSourceを適切なタスクソースとする。

  3. msがNaNならmsを+0とし、そうでなければmsと+0の大きい方にする。

  4. pを新しいpromiseをrealmで生成したものとする。

  5. promiseへの反応をpromiseに対して行う:

    • promiseが値vでfulfilledされた場合:

      1. 以下の手順を並行して行う:

        1. msミリ秒待つ。

        2. タスクをキューしてtaskSource上でresolve pをvで行う。

    • promiseが理由rでrejectedされた場合:

      1. 以下の手順を並行して行う:

        1. msミリ秒待つ。

        2. タスクをキューしてtaskSource上でreject pをrで行う。

  6. pを返す。

environment.readyは属性で、環境(例: DOM documentなど)が「ready」状態になった時を通知します。 環境に依存した非同期状態のコーディング例です。

interface Environment {
  readonly attribute Promise<undefined> ready;
};

すべてのEnvironmentオブジェクトはready promise(型Promise<undefined>)を持ちます。

ready属性getterの手順:

  1. thisのready promiseを返す。

Environmentオブジェクトをrealm realmで生成する手順:

  1. taskSourceを適切なタスクソースとする。

  2. environmentをnew Environmentオブジェクトとしてrealmで生成する。

  3. environmentのready promiseを新しいpromiseで初期化。

  4. 以下の手順を並行して行う:

    1. 非同期処理を実行する。

    2. environmentがreadyになったら、タスクをキューしてtaskSource上でresolve environmentのready promiseを行う。

    3. environmentがreadyにならなかったら、タスクをキューしてtaskSource上でreject environmentのready promiseを "NetworkError" DOMExceptionで行う。

  5. environmentを返す。

addBookmarkは操作で、ユーザーに現在のウェブページをブックマーク登録するようリクエストします。 設計検討の例からの実例で、 環境非同期性や即時rejectの現実的な使い方を示します。

interface I {
  Promise<undefined> addBookmark();
};

addBookmark()メソッドの手順:

  1. taskSourceを適切なタスクソースとする。

  2. このメソッドが明示的なユーザー操作の結果として呼び出されていなければ、名前が「SecurityError 」の DOMException で 拒否された promise を返します。

  3. ドキュメントの動作モードがスタンドアロンなら、名前が「NotSupportedError」の DOMException で 拒否された promise を返します。

  4. promiseを新しいpromiseで初期化。

  5. infoをウェブアプリのメタデータ取得結果とする。

  6. 以下の手順を並行して行う:

    1. infoを使って、ユーザーエージェント依存で ユーザーがブックマーク追加するか選択できるようにする。

      1. ブックマーク追加リクエストをユーザーが中止したら(例: Escapeキーや「キャンセル」ボタンなど)、 タスクをキューしてtaskSource上でreject promiseを "AbortError" DOMExceptionで行う。

      2. それ以外の場合はタスクをキューしてtaskSource上でresolve promiseを行う。

  7. promiseを返す。

[SERVICE-WORKERS]の複数箇所でget a promise to wait for allが使われています。 batchRequestはその簡易バージョン例です。 入力としてURLのsequenceを受け取り、 各URLをfetchして得られるResponseオブジェクトのsequenceのpromiseを返します。 fetchのどれかが失敗した場合はその失敗でrejectされたpromiseを返します。

interface I {
  Promise<sequence<Response>> batchRequest(sequence<USVString> urls);
};

batchRequest(urls)メソッドの手順:

  1. responsePromisesを空リスト« »で初期化。

  2. urlsの各urlについて:

    1. pをfetch()にurlを渡して呼び出した結果とする。

    2. responsePromisesにpを追加する。

  3. pをget a promise to wait for allでresponsePromisesを渡して呼び出した結果とする。

  4. pを返す。

3.2.25. ユニオン型

IDL ユニオン型値は JavaScriptの値で表現され、 それぞれユニオンのメンバー型に対応します。

JavaScript値VをIDL ユニオン型値に 変換する手順:

  1. ユニオン型がundefinedを含む場合でVがundefinedなら、 一意なundefined値を返す。

  2. ユニオン型がnullable型を含む場合で Vがnullまたはundefinedなら、 IDL値nullを返す。

  3. typesをユニオン型のフラット化メンバー型とする。

  4. Vがnullまたはundefinedの場合:

    1. typesに辞書型が含まれていれば、 Vをその辞書型に変換した結果を返す。

  5. Vがプラットフォームオブジェクトなら:

    1. typesにVが実装するインターフェイス型が含まれていれば、 Vへの参照を持つIDL値を返す。

    2. typesにobjectが含まれていれば、 Vへの参照を持つIDL値を返す。

  6. VがObject型で、Vが[[ArrayBufferData]] 内部スロットを持ち、 IsSharedArrayBuffer(V)がfalseなら:

    1. typesにArrayBufferが含まれていれば、 VをArrayBufferに変換した結果を返す。

    2. typesにobjectが含まれていれば、 Vへの参照を持つIDL値を返す。

  7. VがObject型で、Vが[[ArrayBufferData]] 内部スロットを持ち、 IsSharedArrayBuffer(V)がtrueなら:

    1. typesにSharedArrayBufferが含まれていれば、 VをSharedArrayBufferに変換した結果を返す。

    2. typesにobjectが含まれていれば、 Vへの参照を持つIDL値を返す。

  8. VがObject型で、Vが[[DataView]] 内部スロットを持つ場合:

    1. typesにDataViewが含まれていれば、 VをDataViewに変換した結果を返す。

    2. typesにobjectが含まれていれば、 Vへの参照を持つIDL値を返す。

  9. VがObject型で、Vが[[TypedArrayName]] 内部スロットを持つ場合:

    1. typesにVの[[TypedArrayName]] 内部スロット値と一致する型付き配列型が含まれていれば、 Vをその型に変換した結果を返す。

    2. typesにobjectが含まれていれば、 Vへの参照を持つIDL値を返す。

  10. IsCallable(V)がtrueなら:

    1. typesにコールバック関数型が含まれていれば、 Vをその型に変換した結果を返す。

    2. typesにobjectが含まれていれば、 Vへの参照を持つIDL値を返す。

  11. VがObject型なら:

    1. typesにasync sequence型が含まれていれば:

      1. typesに文字列型が含まれていないか、 Vが[[StringData]] 内部スロットを持たない場合:

        1. asyncMethodを? GetMethod(V, %Symbol.asyncIterator%)の結果とする。

        2. asyncMethodがundefinedでなければ、 async sequence型のIDL値を返す。 objectにV、 methodにsyncMethod、 typeに"async"を設定。

        3. syncMethodを? GetMethod(V, %Symbol.iterator%)の結果とする。

        4. syncMethodがundefinedでなければ、 async sequence型のIDL値を返す。 objectにV、 methodにsyncMethod、 typeに"sync"を設定。

    2. typesにsequence型が含まれていれば:

      1. methodを? GetMethod(V, %Symbol.iterator%)の結果とする。

      2. methodがundefinedでなければ、 sequenceを生成した結果を返す。

    3. typesにfrozen array型が含まれていれば:

      1. methodを? GetMethod(V, %Symbol.iterator%)の結果とする。

      2. methodがundefinedでなければ、 frozen arrayを生成した結果を返す。

    4. typesに辞書型が含まれていれば、 Vをその型に変換した結果を返す。

    5. typesにrecord型が含まれていれば、 Vをその型に変換した結果を返す。

    6. typesにコールバックインターフェイス型が含まれていれば、 Vをその型に変換した結果を返す。

    7. typesにobjectが含まれていれば、 Vへの参照を持つIDL値を返す。

  12. VがBoolean型なら:

    1. typesにbooleanが含まれていれば、 Vをbooleanに変換した結果を返す。

  13. VがNumber型なら:

    1. typesに数値型が含まれていれば、 Vをその型に変換した結果を返す。

  14. VがBigInt型なら:

    1. typesにbigintが含まれていれば、 Vをbigintに変換した結果を返す。

  15. typesに文字列型が含まれていれば、 Vをその型に変換した結果を返す。

  16. typesに数値型とbigintが含まれていれば、 Vを数値型またはbigint型へ変換した結果を返す。

  17. typesに数値型が含まれていれば、 Vをその型に変換した結果を返す。

  18. typesにbooleanが含まれていれば、 Vをbooleanに変換した結果を返す。

  19. typesにbigintが含まれていれば、 Vをbigintに変換した結果を返す。

  20. TypeErrorをthrowする。

IDLユニオン型値は JavaScript値へ変換されます。 変換方法は当該IDLユニオン型値の具体的な型の規則に従います(§ 3.2 JavaScript型マッピング参照)。

3.2.26. バッファソース型

IDL ArrayBuffer の値は、対応する JavaScript クラスのオブジェクトによって表現される。 [AllowResizable] に関連付けられていない場合、 拡張 属性として、JavaScript ArrayBuffer オブジェクト V のみを基盤とすることができ、この V について IsFixedLengthArrayBuffer(V) は true である。

IDL SharedArrayBuffer の値は、対応する JavaScript クラスのオブジェクトによって表現される。[AllowResizable] に関連付けられていない場合、 拡張 属性として、JavaScript SharedArrayBuffer オブジェクト V のみを基盤とすることができ、この V について IsFixedLengthArrayBuffer(V) は true である。

IDL バッファー ビュー型の値は、対応する JavaScript クラスのオブジェクトによって表現され、それらのオブジェクトには次の追加の制限がある。

JavaScript 値 V は 変換される IDL ArrayBuffer 値へ、次のアルゴリズムを実行することで変換される。

  1. V が Object では ない場合、 または V が [[ArrayBufferData]] 内部スロットを持たない 場合、スローする 次の TypeError。

  2. IsSharedArrayBuffer(V) が true である場合、スローする 次の TypeError。

  3. 変換先が IDL 型ではなく、 [AllowResizable] に関連付けられている 拡張属性ではなく、IsFixedLengthArrayBuffer(V) が false である 場合、スローする 次の TypeError。

  4. 返す IDL ArrayBuffer 値は参照であり、 V と同じオブジェクトを指す。

JavaScript 値 V は 変換される IDL SharedArrayBuffer 値へ、次のアルゴリズムを実行することで変換される。

  1. V が Object では ない場合、 または V が [[ArrayBufferData]] 内部スロットを持たない 場合、スローする 次の TypeError。

  2. IsSharedArrayBuffer(V) が false である場合、 スローする 次の TypeError。

  3. 変換先が IDL 型ではなく、 [AllowResizable] に関連付けられている 拡張属性ではなく、IsFixedLengthArrayBuffer(V) が false である 場合、スローする 次の TypeError。

  4. 返す IDL SharedArrayBuffer 値は参照であり、 V と同じオブジェクトを指す。

JavaScript 値 V は 変換される IDL DataView 値へ、次のアルゴリズムを実行することで変換される。

  1. V が Object では ない場合、 または V が [[DataView]] 内部スロットを持たない 場合、スローする 次の TypeError。

  2. 変換先が IDL 型ではなく、 [AllowShared] に関連付けられている 拡張属性ではなく、IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) が true である 場合、スローする 次の TypeError。

  3. 変換先が IDL 型ではなく、 [AllowResizable] に関連付けられている 拡張属性ではなく、IsFixedLengthArrayBuffer(V.[[ViewedArrayBuffer]]) が false である 場合、スローする 次の TypeError。

  4. 返す IDL DataView 値は参照であり、 V と同じオブジェクトを指す。

JavaScript 値 V は 変換される IDL Int8Array、 Int16Array、 Int32Array、 Uint8Array、 Uint16Array、 Uint32Array、 Uint8ClampedArray、 BigInt64Array、 BigUint64Array、 Float16Array、 Float32Array、 または Float64Array 値へ 次のアルゴリズムを実行することで変換される。

  1. T を、V の変換先である IDL 型とする。

  2. V が Object では ない場合、 または V が [[TypedArrayName]] 内部スロットを T の名前と等しい値で持たない 場合、スローする 次の TypeError。

  3. 変換先が IDL 型ではなく、 [AllowShared] に関連付けられている 拡張属性ではなく、IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) が true である 場合、スローする 次の TypeError。

  4. 変換先が IDL 型ではなく、 [AllowResizable] に関連付けられている 拡張属性ではなく、IsFixedLengthArrayBuffer(V.[[ViewedArrayBuffer]]) が false である 場合、スローする 次の TypeError。

  5. V と同じオブジェクトへの参照である型 T の IDL 値を返す。

任意のバッファソース型のIDL値をJavaScript値に変換した結果は、 そのIDL値が参照しているオブジェクトと同じオブジェクトへの参照を表すObject値である。

切り離す ArrayBuffer arrayBuffer を:
  1. jsArrayBuffer を ? AllocateArrayBuffer(realm.[[Intrinsics]].[[%ArrayBuffer%]], bytes の 長さ) とする。

  2. arrayBuffer を、jsArrayBuffer を ArrayBuffer 型のIDL値に変換した結果とする。

  3. bytes を arrayBuffer に 書き込む。

  4. arrayBuffer を返す。

生成する SharedArrayBuffer バイト列 bytes を realm realm で:
  1. jsSharedArrayBuffer を ? AllocateSharedArrayBuffer(realm.[[Intrinsics]].[[%SharedArrayBuffer%]], bytes の 長さ) とする。

  2. sharedArrayBuffer を、jsSharedArrayBuffer を SharedArrayBuffer 型のIDL値に変換した結果とする。

  3. bytes を sharedArrayBuffer に 書き込む。

  4. sharedArrayBuffer を返す。

生成する ArrayBufferView 型のいずれかを バイト列 bytes を realm realm で:
  1. 型が DataView でない場合、bytes の 長さ を、その型の 要素サイズ で割った余りが 0 であることを保証する。

  2. arrayBuffer を ArrayBuffer を bytes から realm で作成した結果とする。

  3. jsArrayBuffer を arrayBuffer を JavaScript値に変換した結果とする。

  4. constructor を realm.[[Intrinsics]] から作成する ArrayBufferView 型に対応するコンストラクタとする。

  5. jsView を ! Construct(constructor, « jsArrayBuffer ») とする。

  6. jsView を与えられた型に 変換した結果を返す。

バッファソースが保持するバイト列のコピーを得るには、buffer source型 のインスタンス bufferSource を用い、以下の手順を実行する:
  1. jsBufferSource を bufferSource を JavaScript値に変換した結果とする。

  2. jsArrayBuffer を jsBufferSource とする。

  3. offset を 0 とする。

  4. length を 0 とする。

  5. jsBufferSource が [[ViewedArrayBuffer]] 内部スロット を持つ場合:

    1. jsArrayBuffer を jsBufferSource.[[ViewedArrayBuffer]] に設定する。

    2. offset を jsBufferSource.[[ByteOffset]] に設定する。

    3. length を jsBufferSource.[[ByteLength]] に設定する。

  6. それ以外の場合:

    1. jsBufferSource は ArrayBuffer または SharedArrayBuffer オブジェクトであることを保証する。

    2. length を jsBufferSource.[[ArrayBufferByteLength]] に設定する。

  7. IsDetachedBuffer(jsArrayBuffer) が true なら、空の バイト列 を返す。

  8. bytes を バイト列 の新規インスタンスで、長さを length とする。

  9. 各 i を範囲 offset から offset + length まで(上限を含まない)の値として、 bytes[i − offset] をGetValueFromBuffer(jsArrayBuffer, i, Uint8, true, Unordered) に設定する。

  10. bytes を返す。

バイト長は、buffer source型 のインスタンス bufferSource に対して、以下の手順で得られる値である:
  1. jsBufferSource を bufferSource を JavaScript値に変換した結果とする。

  2. jsBufferSource が [[ViewedArrayBuffer]] 内部スロットを持つ場合は、 jsBufferSource.[[ByteLength]] を返す。

  3. jsBufferSource.[[ArrayBufferByteLength]] を返す。

下層バッファは、buffer source型 のインスタンス bufferSource に対して、以下の手順で得られる値である:
  1. bufferSource が buffer型 のインスタンスであれば bufferSource を返す。

  2. jsBufferView を bufferSource を JavaScript値に変換した結果とする。

  3. jsBuffer を jsBufferView.[[ViewedArrayBuffer]] とする。

  4. IsSharedArrayBuffer(jsBuffer) が false の場合、 jsBuffer を ArrayBuffer 型のIDL値に変換した結果を返す。

  5. jsBuffer を SharedArrayBuffer 型のIDL値に変換した結果を返す。

書き込むには、 バイト列 bytes を buffer型 のインスタンス arrayBuffer に、オプションで startingOffset(デフォルト0)を指定して、以下の手順を実行する:
  1. jsArrayBuffer を arrayBuffer を JavaScript値に変換した結果とする。

  2. bytes の 長さ ≤ jsArrayBuffer.[[ArrayBufferByteLength]] − startingOffset であることを保証する。

  3. 各 i を範囲 startingOffset から startingOffset + bytes の長さ まで(上限を含まない)の値として、 SetValueInBuffer(jsArrayBuffer, i, Uint8, bytes[i - startingOffset], true, Unordered) を実行する。

書き込むには、バイト列 bytes を ArrayBufferView view に、オプションで startingOffset(デフォルト0)を指定して、以下の手順を実行する:
  1. jsView を view を JavaScript値に変換した結果とする。

  2. bytes の 長さ ≤ jsView.[[ByteLength]] − startingOffset であることを保証する。

  3. もし view が DataView でなければ、 bytes の 長さ を viewの型の要素サイズで割った余り が0であることを保証する。

  4. arrayBuffer を、jsView.[[ViewedArrayBuffer]] を ArrayBuffer 型のIDL値に変換した結果とする。

  5. bytes を arrayBuffer に startingOffset = jsView.[[ByteOffset]] + startingOffset で書き込む。

buffer source型 のインスタンスに書き込む仕様文を書く際は、 下層データがスクリプトの著者や他のAPIによって予期しないタイミングで容易に変更されうるため、十分に注意しなければならない。 特に SharedArrayBuffer オブジェクトが関与する場合は注意が必要である。

共有されていない場合は、より推奨されるパターンとして、まず ArrayBuffer を転送して、他の変更と重複して書き込みが発生しないことを保証し、 必要に応じて新しい ArrayBuffer インスタンスを著者コードに渡すことができる。 または、バイト列のコピーを取得し、そのバイト列を変更し、 それを使って新しい ArrayBuffer または ArrayBufferView を作成して著者コードに渡すこともできる。

生成する ArrayBuffer バイト列 bytes を realm realm で:
  1. jsArrayBuffer を arrayBuffer を JavaScript値に変換した結果とする。

  2. ? DetachArrayBuffer(jsArrayBuffer) を実行する。

この操作は、 jsArrayBuffer が [[ArrayBufferDetachKey]] を持ち、その値が undefined でない場合(例えば WebAssembly.Memory の buffer 属性の場合)には例外を投げる。 [WASM-JS-API-1]

すでに 切り離されたバッファを切り離す操作は何も起こらない(no-op)である。

buffer source型 のインスタンス bufferSource が 切り離されたかどうかは、以下の手順で true かどうか判定する:
  1. jsArrayBuffer を bufferSource を JavaScript値に変換した結果とする。

  2. jsArrayBuffer が [[ViewedArrayBuffer]] 内部スロットを持つ場合は、 jsArrayBuffer を jsArrayBuffer.[[ViewedArrayBuffer]] に設定する。

  3. IsDetachedBuffer(jsArrayBuffer) の結果を返す。

buffer source型 のインスタンス bufferSource が 転送可能かどうかは、以下の手順で true かどうか判定する:
  1. jsArrayBuffer を bufferSource を JavaScript値に変換した結果とする。

  2. jsArrayBuffer が [[ViewedArrayBuffer]] 内部スロットを持つ場合は、 jsArrayBuffer を jsArrayBuffer.[[ViewedArrayBuffer]] に設定する。

  3. IsSharedArrayBuffer(jsArrayBuffer) が true なら、false を返す。

  4. IsDetachedBuffer(jsArrayBuffer) が true なら、false を返す。

  5. jsArrayBuffer.[[ArrayBufferDetachKey]] が undefined でないなら、false を返す。

  6. true を返す。

転送には、ArrayBuffer arrayBuffer に対して、オプションで レルム targetRealm を指定して以下の手順を行う:
  1. jsArrayBuffer を arrayBuffer を JavaScript値に変換した結果とする。

  2. IsDetachedBuffer(jsArrayBuffer) が true なら、TypeError を投げる。

  3. arrayBufferData を jsArrayBuffer.[[ArrayBufferData]] とする。

  4. arrayBufferByteLength を jsArrayBuffer.[[ArrayBufferByteLength]] とする。

  5. ? DetachArrayBuffer(jsArrayBuffer) を実行する。

  6. targetRealm が指定されていない場合は、targetRealm を 現在のレルムとする。

  7. jsTransferred を ? AllocateArrayBuffer(targetRealm.[[Intrinsics]].[[%ArrayBuffer%]], 0) とする。

  8. jsTransferred.[[ArrayBufferData]] を arrayBufferData に設定する。

  9. jsTransferred.[[ArrayBufferByteLength]] を arrayBufferByteLength に設定する。

  10. jsTransferred を ArrayBuffer 型のIDL値に変換した結果を返す。

この操作は、以下の場合に例外を投げる:

3.2.27. フローズン配列 — FrozenArray<T>

フローズン配列型の値は、フローズンされた JavaScript Array オブジェクトの参照として表現される。

JavaScript値 V は 変換 されて、IDL FrozenArray<T>値になる。以下のアルゴリズムを実行する:

  1. values を、V を IDL 型 sequence<T> に変換した結果とする。

  2. フローズン配列を作成して values から得られた結果を返す。

値の列 T から フローズン配列を作成するには、以下の手順を実行する:

  1. array を 型 T の値の列を JavaScript 値に変換した結果とする。

  2. ! SetIntegrityLevel(array, "frozen") を実行する。

  3. array を返す。

IDL の FrozenArray<T> 値をJavaScript 値に変換した結果は、 その IDL の FrozenArray<T> が表すオブジェクトと同じオブジェクトへの参照を表す Object 値である。

3.2.27.1. イテラブルからフローズン配列を作成する

イテラブル iterable とイテレーター取得関数 method を用いて、型 FrozenArray<T> のIDL値を作成するには、以下の手順を実行する:

  1. values を、iterable と method から sequence を生成し、型は sequence<T> とすることで得られる結果とする。

  2. values から frozen array を生成した結果を返す。

3.2.28. オブザーバブル配列 — ObservableArray<T>

オブザーバブル配列型の値は、オブザーバブル配列エキゾチックオブジェクトによって表現される。

通常の変換アルゴリズムの代わりに、オブザーバブル配列型は 属性ゲッターと属性セッターアルゴリズムの一部として特別な処理を持つ。

JavaScript バインディングでは、プラットフォームオブジェクトを表す JavaScript オブジェクトは、 observable array 型 の 通常属性ごとに 対応する observable array exotic object を持つ。 これらは 属性定義アルゴリズムの一部として生成・管理される。

JavaScriptバインディングにおけるオブザーバブル配列属性の裏リストは、プラットフォームオブジェクト objと属性 attribute が与えられたとき、以下のアルゴリズムで返される リストである:
  1. Assert: obj が インターフェイスのinterfaceを実装し、その 通常属性 attribute を持つこと。

  2. oa を obj の 裏で支えるオブザーバブル配列エキゾチックオブジェクト(attribute用)とする。

  3. oa.[[ProxyHandler]].[[BackingList]] を返す。

3.3. 拡張属性

この節では、JavaScriptバインディングに影響を与える 拡張属性 を定義する。

3.3.1. [AllowResizable]

[AllowResizable] 拡張 属性が null 許容の可能性がある バッファー型に現れる場合、それは新しい IDL 型を作成し、それぞれ対応する JavaScript ArrayBuffer または SharedArrayBuffer オブジェクトを リサイズ可能にする。

[AllowResizable] 拡張 属性が null 許容の可能性がある バッファービュー型に現れ、 [AllowShared] 拡張 属性が現れない場合、それは新しい IDL 型を作成し、そのバッファービュー型を JavaScript ArrayBuffer のうちリサイズ可能なものを基盤とすることを、固定長の ArrayBufferのみを基盤とする代わりに許可する。

[AllowResizable] 拡張 属性と [AllowShared] 拡張 属性の 両方が null 許容の可能性がある バッファービュー型に現れる場合、それは新しい IDL 型を作成し、 そのバッファービュー型を追加で JavaScript SharedArrayBuffer のうち拡張可能なものを基盤とすることを許可する。

[AllowResizable] 拡張属性は 引数を取ってはならない。

null 許容の可能性がある バッファーソース型ではない型は、 [AllowResizable] に関連付けられてはならない 拡張属性。

JavaScript 値を IDL バッファーソース型に変換する規則については、 § 3.2.26 バッファーソース型を参照し、 [AllowResizable] の使用に伴う具体的な要件を確認されたい。

§ 3.3.2 [AllowShared] の 例では、[AllowResizable] と [AllowShared] の両方の使用例を参照できる。

3.3.2. [AllowShared]

[AllowShared] 拡張 属性が null 許容の可能性がある バッファービュー型に現れる場合、それは オブジェクトが SharedArrayBuffer を基盤とすることを、ArrayBufferのみを基盤とする代わりに許可する新しい IDL 型を作成する。

[AllowShared] 拡張属性は 引数を取ってはならない。

null 許容の可能性がある バッファービュー型ではない型は、 [AllowShared] に関連付けられてはならない 拡張属性。

JavaScript 値を IDL バッファービュー型に変換する規則については、 § 3.2.26 バッファーソース型を参照し、 [AllowShared] の使用に伴う具体的な要件を確認されたい。

次の IDL断片は、 [AllowResizable] と [AllowShared] 拡張属性の組み合わせ例を示す:
[Exposed=Window]
interface ExampleBufferFeature {
  undefined writeInto(ArrayBufferView dest);
  undefined writeIntoResizable([AllowResizable] ArrayBufferView dest);
  undefined writeIntoShared([AllowShared] ArrayBufferView dest);
  undefined writeIntoSharedResizable([AllowResizable, AllowShared] ArrayBufferView dest);
};

この定義により、

3.3.3. [Clamp]

[Clamp] 拡張 属性が null 許容の可能性がある 整数型に現れる場合、 新しい IDL 型が作成され、JavaScript Number がその IDL 型に変換されるとき、 範囲外の値は、モジュロ演算を使用する演算子 (ToInt32、ToUint32 など)を使用するのではなく、有効な値の範囲にクランプされる。

[Clamp] 拡張属性は 引数を 取ってはならない。

[Clamp] 拡張 属性で注釈された型は、読み取り専用 属性に現れてはならない。型は、[Clamp] と [EnforceRange] の両方に 関連付けられてはならない。 null 許容の可能性が ある 整数 型ではない型は、 [Clamp] 拡張属性に 関連付けられてはならない 。

JavaScript 値を各種 IDL 整数 型に変換する規則については、§ 3.2.4 整数型 を参照し、 [Clamp] の使用に伴う具体的な要件を確認されたい。

次の IDL断片では、3つの octet 引数を取る2つの操作が宣言されている。1つは3つ全ての引数に [Clamp] 拡張属性を付与し、もう1つは付与していない:

[Exposed=Window]
interface GraphicsContext {
  undefined setColor(octet red, octet green, octet blue);
  undefined setColorClamped([Clamp] octet red, [Clamp] octet green, [Clamp] octet blue);
};

setColorClamped を octet の範囲外の Number 値で呼び出すと、値は [0, 255] の範囲にクランプされる。

// GraphicsContextのインスタンスを取得。
var context = getGraphicsContext();

// 非[Clamp]版は ToUint8 を使い Number をoctetに変換する。setColor(255, 255, 1) と等価。
context.setColor(-1, 255, 257);

// 範囲外値でsetColorClampedを呼び出す。setColorClamped(0, 255, 255) と等価。
context.setColorClamped(-1, 255, 257);

3.3.4. [CrossOriginIsolated]

[CrossOriginIsolated] 拡張属性が インターフェイス、 部分インターフェイス、 インターフェイスミクシン、 部分インターフェイスミクシン、 コールバックインターフェイス、 名前空間、 部分名前空間、 インターフェイスメンバー、 インターフェイスミクシンメンバー、 名前空間メンバー に付与された場合、その構成要素は 環境の クロスオリジン分離機能 が true の場合のみ公開されることを示す。[CrossOriginIsolated]拡張属性はその他の構成要素には使ってはならない。

[CrossOriginIsolated] 拡張属性は引数を取ってはならない。

[CrossOriginIsolated] が オーバーロードされた 操作に付与されている場合、全てのオーバーロードに付与しなければならない。

[CrossOriginIsolated] 拡張属性は、以下の両方に指定してはならない:

注: これは、メンバーに[CrossOriginIsolated] 拡張属性を付与しても、包含定義にも[CrossOriginIsolated]拡張属性が付与されている場合はメンバーの公開範囲がさらに制限されることはないためである。

[CrossOriginIsolated] 拡張属性を持たない インターフェイスは、[CrossOriginIsolated] を指定した別のインターフェイスから継承してはならない。

次の IDL断片は、全てのコンテキストから実行可能な1つの操作と、クロスオリジン分離コンテキストからのみ実行可能な2つの操作を持つインターフェイスを定義する。

[Exposed=Window]
interface ExampleFeature {
  // これは全てのコンテキストで成功する。
  Promise <Result> calculateNotSoSecretResult();

  // 非分離コンテキストではこの操作は公開されない。そうしたコンテキストではExampleFeature.prototypeに"calculateSecretResult"プロパティは存在しない。
  [CrossOriginIsolated] Promise<Result> calculateSecretResult();

  // 同様に、この属性も非分離コンテキストでは公開されず、ExampleFeature.prototypeに"secretBoolean"プロパティは存在しない。
  [CrossOriginIsolated] readonly attribute boolean secretBoolean;
};

// HighResolutionTimerは非分離コンテキストでは公開されず、そのメンバーも公開されない。その場合 Window に "HighResolutionTimer" プロパティは存在しない。
[Exposed=Window, CrossOriginIsolated]
interface HighResolutionTimer {
  DOMHighResTimeStamp getHighResolutionTime();
};

// 下記のインターフェイスミクシンメンバーは、ホストインターフェイスが非分離属性を持つかどうかに関わらず、非分離コンテキストでは公開されない。その場合ExampleFeature.prototypeに"snap"プロパティは存在しない。
[CrossOriginIsolated]
interface mixin Snapshotable {
  Promise<boolean> snap();
};
ExampleFeature includes Snapshotable;

// 一方、下記のインターフェイスミクシンメンバーは、ホストインターフェイスが[CrossOriginIsolated]拡張属性を持たなければ非分離コンテキストでも公開される。つまり、非分離コンテキストではExampleFeature.prototypeに"log"プロパティが存在する。
interface mixin Loggable {
  Promise<boolean> log();
};
ExampleFeature includes Loggable;

3.3.5. [Default]

[Default] 拡張属性が通常操作に付与されている場合、その操作が呼び出されたときに適切なデフォルトメソッド手順を実行することを示す。

[Default] 拡張属性は引数を取ってはならない。

[Default] 拡張属性は、通常操作以外や、デフォルトメソッド手順が定義されていないものには使用してはならない。

例として、[Default]拡張属性は toJSON 通常操作に付与するのに適している:

[Exposed=Window]
interface Animal {
  attribute DOMString name;
  attribute unsigned short age;
  [Default] object toJSON();
};

[Exposed=Window]
interface Human : Animal {
  attribute Dog? pet;
  [Default] object toJSON();
};

[Exposed=Window]
interface Dog : Animal {
  attribute DOMString? breed;
};

JavaScriptバインディングでは、Animal, Human、Dog(継承経由)オブジェクトに toJSON() メソッドが存在する:

// Humanのインスタンスを取得。
var alice = getHuman();

// 評価結果は以下のようなオブジェクト(この時点で pet はDogインスタンス):
//
// {
//   name: "Alice",
//   age: 59,
//   pet: Dog
// }
alice.toJSON();

// DogインターフェイスはデフォルトtoJSON手順を使用しないため"breed"は欠落:
//
// {
//   name: "Tramp",
//   age: 6
// }
alice.pet.toJSON();

// 以下のような文字列になる:
// '{"name":"Alice","age":59,"pet":{"name":"Tramp","age":6}}'
JSON.stringify(alice);

3.3.6. [EnforceRange]

[EnforceRange] 拡張 属性が null 許容の可能性がある 整数型に現れる場合、それは JavaScript Number が その IDL 型に変換されるとき、範囲外の値が、有効な値に変換されるのではなく例外をスローさせる モジュロ演算を使用する演算子によって (ToInt32、ToUint32 など)新しい IDL 型を作成する。 Number は、その範囲に対して検査される前にゼロ方向に丸められる。

[EnforceRange] 拡張属性は 引数を 取ってはならない。

[EnforceRange] 拡張属性で注釈された型は、 読み取り専用属性に現れてはならない。型は [Clamp] と [EnforceRange] の両方に 関連付けられてはならない。 また、null 許容の可能性が ある 整数 型ではない型は、 [EnforceRange] 拡張属性に 関連付けられてはならない。

JavaScript 値を各種 IDL 整数 型に変換する規則については、§ 3.2 JavaScript 型のマッピング を参照し、 [EnforceRange] の使用に伴う具体的な要件を確認されたい。

次の IDL断片では、3つの octet 引数を取る2つの操作が宣言されている。1つは3つ全ての引数に [EnforceRange] 拡張属性を付与し、もう1つは付与していない:

[Exposed=Window]
interface GraphicsContext {
  undefined setColor(octet red, octet green, octet blue);
  undefined setColorEnforcedRange([EnforceRange] octet red, [EnforceRange] octet green, [EnforceRange] octet blue);
};

IDLのJavaScript実装では、setColorEnforcedRange を octet の範囲外の Number 値で呼び出すと、例外が投げられる。

// GraphicsContextのインスタンスを取得。
var context = getGraphicsContext();

// 非[EnforceRange]版は ToUint8 を使い Number をoctetに変換する。setColor(255, 255, 1) と等価。
context.setColor(-1, 255, 257);

// setColorEnforcedRangeを呼び出すと、値はゼロ方向に丸められる。setColor(0, 255, 255) と等価。
context.setColorEnforcedRange(-0.9, 255, 255.2);

// 以下は例外(TypeError)が投げられる。丸め後も範囲外のため。
context.setColorEnforcedRange(-1, 255, 256);

3.3.7. [Exposed]

[Exposed] 拡張属性が インターフェイス、 部分インターフェイス、 インターフェイスミクシン、 部分インターフェイスミクシン、 コールバックインターフェイス、 名前空間、 部分名前空間、 または個々の インターフェイスメンバー、 インターフェイスミクシンメンバー、 名前空間メンバー に付与された場合、その構成要素が指定したグローバルインターフェイス群で公開されることを示す。

[Exposed] 拡張属性は 識別子、 識別子リスト、 または ワイルドカードのいずれかを取る必要がある。 各識別子は何らかの インターフェイスの グローバル名であり、重複してはならない。

自身の公開セットは、 識別子のセットまたは特別な値 * であり、次のように定義される:

[Exposed] 拡張属性が識別子 I を取る場合

自身の公開セットは セット « I » である。

[Exposed] 拡張属性が識別子リスト I を取る場合

自身の公開セットは セット I である。

[Exposed] 拡張属性がワイルドカードを取る場合

自身の公開セットは * である。

[Exposed=*] の使用には注意が必要である。 APIが重要な新機能を公開しない場合のみ適している。 APIが環境によって制限・無効化される可能性がある場合は、グローバルを明示的に列挙する方が望ましい。

公開セットの共通部分は、構成要素 C と interface-or-null H に対し次のように定義される:

  1. Assert: C は インターフェイスメンバー、インターフェイスミクシンメンバー、名前空間メンバー、 部分インターフェイス、部分インターフェイスミクシン、部分名前空間、インターフェイスミクシンであること。

  2. Assert: H は インターフェイスまたはnullである。

  3. H が null なら、C の 自身の公開セット を返す。

  4. C の 自身の公開セットが * なら、H の 公開セット を返す。

  5. H の 公開セットが * なら、C の 自身の公開セット を返す。

  6. C の 自身の公開セット と H の 公開セット の共通部分を返す。

構成要素 C の 公開セットを取得するには、以下の手順を実行する:
  1. Assert: C は インターフェイス、コールバックインターフェイス、 名前空間、 インターフェイスメンバー、インターフェイスミクシンメンバー、または名前空間メンバーであること。

  2. H を C が インターフェイスミクシンメンバーなら ホストインターフェイス、そうでなければ null とする。

  3. C が インターフェイスメンバー、インターフェイスミクシンメンバー、名前空間メンバーなら:

    1. [Exposed] 拡張属性が C に指定されていれば、公開セットの共通部分(C, H) を返す。

    2. C を元の インターフェイス、部分インターフェイス、 インターフェイスミクシン、部分インターフェイスミクシン、 名前空間、部分名前空間の C に設定する。

  4. C が 部分インターフェイス、部分インターフェイスミクシン、部分名前空間なら:

    1. [Exposed] 拡張属性が C に指定されていれば、公開セットの共通部分(C, H) を返す。

    2. C を元の インターフェイス、インターフェイスミクシン、名前空間の定義の C に設定する。

  5. C が インターフェイスミクシンなら:

    1. H は null ではないこと。

    2. [Exposed] 拡張属性が C に指定されていれば、公開セットの共通部分(C, H) を返す。

    3. C を H に設定する。

  6. C は インターフェイス、コールバックインターフェイス、名前空間であること。

  7. [Exposed] 拡張属性が C に指定されていること。

  8. C の 自身の公開セットを返す。

[Exposed] が オーバーロードされた 操作に指定されている場合、全てのオーバーロードに同一に指定されなければならない。

[Exposed] 拡張属性は インターフェイスメンバー、 インターフェイスミクシンメンバー、 名前空間メンバー と、そのメンバーが宣言されている 部分インターフェイス、 部分インターフェイスミクシン、 部分名前空間定義の両方に指定してはならない。

注: 部分インターフェイス、部分インターフェイスミクシン、部分名前空間に [Exposed] 拡張属性を付与するのは、各メンバーに個別に付与する省略表現であるためである。

[Exposed] が 部分インターフェイスまたは部分名前空間に指定されている場合、その 自身の公開セットは 元の インターフェイスまたは 名前空間の 公開セットの部分集合でなければならない。

[Exposed] が インターフェイスメンバーまたは名前空間メンバーに指定されている場合、その メンバーの公開セットは 所属する インターフェイスまたは名前空間の 公開セットの部分集合でなければならない。

[Exposed] が 部分インターフェイスミクシンと元の インターフェイスミクシンの両方に指定されている場合、部分インターフェイスミクシンの 自身の公開セットはインターフェイスミクシンの 自身の公開セットの部分集合でなければならない。

[Exposed] が インターフェイスミクシンメンバーと インターフェイスミクシンの両方に指定されている場合、そのインターフェイスミクシンメンバーの 自身の公開セットは インターフェイスミクシンの 自身の公開セットの部分集合でなければならない。

インターフェイス X が他のインターフェイス Y を 継承している場合、X の 公開セットは Y の 公開セットの部分集合でなければならない。

注: インターフェイスミクシンは複数の インターフェイスに include できるので、そのメンバーの 公開セットは それを include した インターフェイスに依存する関数となる。 [Exposed] 拡張属性が インターフェイスミクシンメンバー、部分インターフェイスミクシン、インターフェイスミクシンに付与されていれば、そのメンバーの 公開セットは該当構成要素の 自身の公開セットと ホストインターフェイスの 公開セットの共通部分となる。そうでなければホストインターフェイスの 公開セットとなる。

インターフェイス、コールバックインターフェイス、名前空間、 またはメンバー construct が 与えられた レルム realm で 公開されているかどうかは、以下の手順で true になるか判定する:
  1. construct の 公開セットが * でなく、 realm.[[GlobalObject]] が construct の 公開セット内の インターフェイスを実装していなければ false を返す。

  2. realm の 設定オブジェクトがセキュアコンテキストでなく、かつ construct が [SecureContext] で条件付き公開されていれば false を返す。

  3. realm の 設定オブジェクトのクロスオリジン分離機能が false で、construct が [CrossOriginIsolated] で条件付き公開されていれば false を返す。

  4. true を返す。

インターフェイス、コールバックインターフェイス、名前空間、 またはメンバー construct が 与えられた 拡張属性 exposure condition で 条件付き公開されているかどうかは、以下の手順で true になるか判定する:
  1. Assert: construct は インターフェイス、コールバックインターフェイス、 名前空間、 インターフェイスメンバー、インターフェイスミクシンメンバー、名前空間メンバーであること。

  2. H を construct が インターフェイスミクシンメンバーなら ホストインターフェイス、そうでなければ null とする。

  3. construct が インターフェイスメンバー、インターフェイスミクシンメンバー、名前空間メンバーなら:

    1. exposure condition 拡張属性が construct に指定されていれば true を返す。

    2. そうでなければ construct を元の インターフェイス、部分インターフェイス、 インターフェイスミクシン、部分インターフェイスミクシン、 名前空間、部分名前空間の construct に設定する。

  4. construct が 部分インターフェイス、部分インターフェイスミクシン、部分名前空間なら:

    1. exposure condition 拡張属性が construct に指定されていれば true を返す。

    2. そうでなければ construct を元の インターフェイス、インターフェイスミクシン、名前空間の定義の construct に設定する。

  5. construct が インターフェイスミクシンなら:

    1. exposure condition 拡張属性が construct に指定されていれば true を返す。

    2. そうでなければ construct を H に設定する。

  6. construct は インターフェイス、コールバックインターフェイス、名前空間であること。

  7. exposure condition 拡張属性が construct に指定されていれば true を返す。

  8. そうでなければ false を返す。

注: JavaScriptグローバルオブジェクトの関連設定オブジェクトがセキュアコンテキストやクロスオリジン分離機能の有無を後から変更できないため、インターフェイスやインターフェイスメンバーのプロパティ作成は初期オブジェクトが作成される時点で一度決定できる。

詳細は § 3.7 インターフェイス、 § 3.7.5 定数、 § 3.7.6 属性、 § 3.7.7 操作 を参照。[Exposed] 使用時の具体的な要件が記載されている。

[Exposed] は、インターフェイス、 コールバックインターフェイス、名前空間、または個々のインターフェイス、 ミクシン、 名前空間メンバーが ワーカー、Worklet、 Window、 あるいはその組み合わせで利用可能かを制御するために使うことを意図している。

以下のIDL断片はその使い方例である:

[Exposed=Window, Global=Window]
interface Window {
  // ...
};

// SharedWorkerGlobalScope と DedicatedWorkerGlobalScope の両方に同じ識別子 Worker を使うことで、[Exposed] 拡張属性で両方を一度に指定できる。
[Exposed=Worker, Global=Worker]
interface SharedWorkerGlobalScope : WorkerGlobalScope {
  // ...
};

[Exposed=Worker, Global=Worker]
interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
  // ...
};

// Dimensions はワーカーでもメインスレッドでも利用できる。
[Exposed=(Window,Worker)]
interface Dimensions {
  constructor(double width, double height);
  readonly attribute double width;
  readonly attribute double height;
};

// WorkerNavigator はワーカーのみで利用可能。ワーカーのグローバルスコープで WorkerNavigator を評価するとインターフェイスオブジェクトが得られるが、メインスレッドでは ReferenceError となる。
[Exposed=Worker]
interface WorkerNavigator {
  // ...
};

// Node はメインスレッドのみで利用可能。ワーカーのグローバルスコープで Node を評価すると ReferenceError となる。
[Exposed=Window]
interface Node {
  // ...
};

// MathUtils はワーカーでもメインスレッドでも利用できる。
[Exposed=(Window,Worker)]
namespace MathUtils {
  double someComplicatedFunction(double x, double y);
};

// WorkerUtils はワーカーのみで利用可能。ワーカーのグローバルスコープで WorkerUtils を評価すると名前空間オブジェクトが得られるが、メインスレッドでは ReferenceError となる。
[Exposed=Worker]
namespace WorkerUtils {
  undefined setPriority(double x);
};

// NodeUtils はメインスレッドのみで利用可能。ワーカーのグローバルスコープで NodeUtils を評価すると ReferenceError となる。
[Exposed=Window]
namespace NodeUtils {
  DOMString getAllText(Node node);
};

3.3.8. [Global]

[Global] 拡張属性がインターフェイスに付与されている場合、このインターフェイスを実装するオブジェクトが レルムのグローバルオブジェクトとして使われることを示す。

[Global] 拡張属性はあわせて グローバル名 をインターフェイスに定義する:

[Global] 拡張属性が識別子を取る場合

« 指定された識別子 »

[Global] 拡張属性が識別子リストを取る場合

識別子リスト

[Global] 拡張属性は上記いずれかの形式でなければならない。

注: グローバル名は インターフェイスを [Exposed] 拡張属性で参照するために使うことができる識別子である。 一つのグローバル名は複数の異なるグローバルインターフェイスで共有でき、[Exposed]を使って一度に全てに公開できる。 例えば「Worker」は複数種のスレッド関連グローバルインターフェイスを指すために使われている。

こうしたグローバルインターフェイスは、プロトタイプチェーンの構造や インターフェイスメンバーに対応するプロパティの反映方法が他のインターフェイスと異なる。具体的には:

  1. 名前付きプロパティは、オブジェクト自身ではなくプロトタイプチェーン上の 名前付きプロパティオブジェクト に公開される。

  2. インターフェイスメンバーは インターフェイスから オブジェクト自身のプロパティとなり、 インターフェイスプロトタイプオブジェクトのプロパティにはならない。

全てのレルムは グローバルプロトタイプチェーンが可変かどうかというブール値を持つ。 これはレルム生成時に設定でき、そのレルムの存続期間中は変更できない。デフォルトは false。

これにより ShadowRealm グローバルは可変プロトタイプを持てる。

名前付きプロパティをプロトタイプチェーン上のオブジェクトに置く理由は、変数宣言や裸の代入で グローバルオブジェクト自身のプロパティが名前付きプロパティを隠す(シャドウする)ためである。

インターフェイスメンバーに対応するプロパティをオブジェクト自身に置くことで、以下のような機能検出コードが機能する:

var indexedDB = window.indexedDB || window.webkitIndexedDB ||
                window.mozIndexedDB || window.msIndexedDB;

var requestAnimationFrame = window.requestAnimationFrame ||
                            window.mozRequestAnimationFrame || ...;

JavaScriptの変数宣言の扱いにより、上記コードは window.indexedDB や window.requestAnimationFrame の評価結果が undefined となる。これはシャドウされる変数プロパティが代入の前に既に作成されているため。

[Global] 拡張属性がインターフェイスに使われた場合:

[Global] が 部分インターフェイス 定義で指定された場合、その部分インターフェイスは 名前付きプロパティゲッターを定義する部分でなければならない。

[Global] 拡張属性は 同じインターフェイスで 同一レルム内で複数のオブジェクトが実装できる場合には使ってはならない。

注: これは名前付きプロパティオブジェクトがプロトタイプチェーン上にあり、 複数のオブジェクトの名前付きプロパティが同じ継承元オブジェクト上に公開されるのは意味がないため。

インターフェイスが[Global] 拡張属性で宣言された場合、 インターフェイス全体で同じ識別子を持つ メンバーが複数あってはならない。 また、stringifierや 反復宣言、 非同期反復宣言、 maplike宣言や setlike宣言 も複数あってはならない。

注: これはインターフェイスの全てのメンバーが、インターフェイスを実装するオブジェクト上に直接配置されるためである。

[Global]の使用に伴う名前付きプロパティの要件については § 3.7.4 名前付きプロパティオブジェクト、 インターフェイスメンバーに対応するプロパティの配置の要件については§ 3.7.5 定数、§ 3.7.6 属性、§ 3.7.7 操作 を参照。

Window インターフェイスは Window オブジェクト上にフレームをプロパティとして公開する。 Window オブジェクトは JavaScriptグローバルオブジェクトも兼ねるため、変数宣言や名前付きプロパティへの代入によって それらの値が置き換えられることになる。属性への変数宣言では既存プロパティが置き換えられることはない。

[Exposed=Window, Global=Window]
interface Window {
  getter any (DOMString name);
  attribute DOMString name;
  // ...
};

以下のHTML文書は Window オブジェクトの名前付きプロパティがシャドウされる様子と、 属性のプロパティは同名の変数宣言でも置き換えられないことを示している:

<!DOCTYPE html>
<title>Window上の変数宣言と代入</title>
<iframe name=abc></iframe>
<!-- 名前付きプロパティのシャドウ -->
<script>
  window.abc;    // iframe の Window オブジェクトを評価。
  abc = 1;       // 名前付きプロパティをシャドウ。
  window.abc;    // 評価結果は 1。
</script>

<!-- IDL属性用プロパティの保持 -->
<script>
  Window.prototype.def = 2;         // プロトタイプにプロパティを追加。
  window.hasOwnProperty("length");  // 評価結果 true。
  length;                           // 評価結果 1。
  def;                              // 評価結果 2。
</script>
<script>
  var length;                       // 変数宣言は既存プロパティを変更しない。
  length;                           // 評価結果 1。
  var def;                          // 変数宣言でシャドウプロパティを作成。
  def;                              // 評価結果 undefined。
</script>

3.3.9. [NewObject]

[NewObject] 拡張属性が 通常 または static 操作に付与されている場合、 その操作を呼び出すと、必ず新しく生成されたオブジェクトへの参照が返されることを示す。

[NewObject] 拡張属性は 引数を取ってはならない。

[NewObject] 拡張属性は 通常または static 操作で、 戻り値型が インターフェイス型または Promise型 以外には使ってはならない。

例えば、この拡張属性は createElement() 操作(Documentインターフェイス)に付与するのが適切である。 この操作は呼び出すたびに必ず新しいオブジェクトが返されるためである。[DOM]

[Exposed=Window]
interface Document : Node {
  [NewObject] Element createElement(DOMString localName);
  // ...
};

3.3.10. [PutForwards]

[PutForwards] 拡張属性が、型が インターフェイス型の readonly 通常属性宣言に付与されている場合、 その属性への代入は特定の動作になることを示す。 すなわち、代入は(拡張属性の引数で指定された)オブジェクトの属性への代入として「転送」される。

[PutForwards] 拡張属性は 識別子を取らなければならない。 前提として:

この場合、J には N という識別子の属性 B が宣言されていなければならない。 Iを実装するオブジェクトの属性Aに値を代入すると、その値はAが参照するオブジェクトの属性Bに代入される。

[PutForwards]でアノテートされた属性はチェーン可能である。すなわち、[PutForwards]拡張属性を持つ属性が、同じくその拡張属性を持つ属性を参照することができる。 転送代入チェーンに循環(サイクル)があってはならない。循環とは、転送代入のチェーンをたどったとき、同じインターフェイス上の同じ属性に2回以上到達する場合である。

[PutForwards]拡張属性付き属性は、[LegacyLenientSetter]や [Replaceable]拡張属性と同時に宣言してはならない。

[PutForwards]拡張属性は 属性が readonlyでない場合には使ってはならない。

[PutForwards]拡張属性は static属性には使ってはならない。

[PutForwards]拡張属性は 名前空間で宣言された属性には使ってはならない。

[PutForwards]の実装方法については 属性の節を参照。

次のIDL断片は、名前と人のインターフェイスを定義している。 Personインターフェイスのname属性には [PutForwards]拡張属性が付与されており、 この属性への代入がPersonオブジェクトのfull属性への代入になることを示している:

[Exposed=Window]
interface Name {
  attribute DOMString full;
  attribute DOMString family;
  attribute DOMString given;
};

[Exposed=Window]
interface Person {
  [PutForwards=full] readonly attribute Name name;
  attribute unsigned short age;
};

JavaScriptバインディングでは、以下のようにnameプロパティへ代入できる:

var p = getPerson();           // Personインスタンスを取得。

p.name = 'John Citizen';       // この文...
p.name.full = 'John Citizen';  // ...は上と同じ動作。

3.3.11. [Replaceable]

[Replaceable] 拡張属性が readonly 通常属性に付与されている場合、 プラットフォームオブジェクト上でそのプロパティに代入を行うと 同じ名前の独自プロパティがそのオブジェクト上に生成され、代入された値がセットされる。 このプロパティはインターフェイスプロトタイプオブジェクト上の属性に対応するアクセサプロパティをシャドウする。

[Replaceable] 拡張属性は 引数を取ってはならない。

[Replaceable] 拡張属性付き属性は、 [LegacyLenientSetter]や [PutForwards]拡張属性と同時に宣言してはならない。

[Replaceable]拡張属性は 属性が readonlyでない場合には使ってはならない。

[Replaceable]拡張属性は static属性には使ってはならない。

[Replaceable]拡張属性は 名前空間で宣言された属性には使ってはならない。

[Replaceable]の使用に伴う詳細要件については § 3.7.6 属性 を参照。

次のIDL断片は、 カウンタをインクリメントする操作と、初期値0のカウンタ値を公開する属性を持つインターフェイスを定義する:

[Exposed=Window]
interface Counter {
  [Replaceable] readonly attribute unsigned long value;
  undefined increment();
};

Counterを実装するプラットフォームオブジェクト上でvalueプロパティに代入すると、 属性に対応するプロパティがシャドウされる:

var counter = getCounter();                              // Counterインスタンスを取得。
counter.value;                                           // 0。

counter.hasOwnProperty("value");                         // false。
Object.getPrototypeOf(counter).hasOwnProperty("value");  // true。

counter.increment();
counter.increment();
counter.value;                                           // 2。

counter.value = 'a';                                     // Counter::valueとは無関係のプロパティでシャドウ。
                                                         // 

counter.hasOwnProperty("value");                         // true。

counter.increment();
counter.value;                                           // 'a'。

delete counter.value;                                    // 元のプロパティが現れる。
counter.value;                                           // 3。

3.3.12. [SameObject]

[SameObject] 拡張属性が readonly 属性に付与されている場合、 その属性の値を取得するたびに、常に同じ値が返されなければならないことを示す。

[SameObject] 拡張属性は 引数を取ってはならない。

[SameObject]拡張属性は、 readonly 属性で型が インターフェイス型 または object 以外には使ってはならない。

例えば、この拡張属性は implementation 属性(Documentインターフェイス)に付与するのが適切である。 同じDocumentオブジェクトに対しては常に同じオブジェクトが返されるためである。[DOM]

[Exposed=Window]
interface Document : Node {
  [SameObject] readonly attribute DOMImplementation implementation;
  // ...
};

3.3.13. [SecureContext]

[SecureContext] 拡張属性が インターフェイス、 部分インターフェイス、 インターフェイスミクシン、 部分インターフェイスミクシン、 コールバックインターフェイス、 名前空間、 部分名前空間、 インターフェイスメンバー、 インターフェイスミクシンメンバー、 名前空間メンバー に付与された場合、その構成要素は 安全なコンテキストでのみ公開される ことを示す。 [SecureContext] 拡張属性は他の構成要素に使ってはならない。

[SecureContext] 拡張属性は、引数を取ってはならない。

[SecureContext] が オーバーロードされた 操作に付与されている場合、全てのオーバーロードに付与しなければならない。

[SecureContext] 拡張属性は、以下の両方に指定してはならない:

注: これは、メンバーに[SecureContext]拡張属性を付与しても、包含定義にも[SecureContext]拡張属性が付与されている場合はメンバーの公開範囲がさらに制限されることはないためである。

[SecureContext] 拡張属性を持たない インターフェイスは、[SecureContext]を指定した別のインターフェイスから継承してはならない。

[SecureContext]は [CrossOriginIsolated]で条件付き公開される構成要素には指定してはならない。 (この場合は冗長であり、クロスオリジン分離環境は必ず安全なコンテキストでもあるため。)

次のIDL断片は、 全てのコンテキストから実行可能な操作ひとつと、安全なコンテキストからのみ実行可能な操作を2つ持つインターフェイスを定義する:

[Exposed=Window]
interface ExampleFeature {
  // これは全てのコンテキストで成功する。
  Promise <Result> calculateNotSoSecretResult();

  // 非安全コンテキストではこの操作は公開されない。そうしたコンテキストではExampleFeature.prototypeに"calculateSecretResult"プロパティは存在しない。
  [SecureContext] Promise<Result> calculateSecretResult();

  // 同様に、この属性も非安全コンテキストでは公開されず、ExampleFeature.prototypeに"secretBoolean"プロパティは存在しない。
  [SecureContext] readonly attribute boolean secretBoolean;
};

// HeartbeatSensorは非安全コンテキストでは公開されず、そのメンバーも公開されない。その場合 Window に "HeartbeatSensor" プロパティは存在しない。
[Exposed=Window, SecureContext]
interface HeartbeatSensor {
  Promise<float> getHeartbeatsPerMinute();
};

// 下記のインターフェイスミクシンメンバーは、ホストインターフェイスが安全属性を持つかどうかに関わらず、非安全コンテキストでは公開されない。その場合ExampleFeature.prototypeに"snap"プロパティは存在しない。
[SecureContext]
interface mixin Snapshotable {
  Promise<boolean> snap();
};
ExampleFeature includes Snapshotable;

// 一方、下記のインターフェイスミクシンメンバーは、ホストインターフェイスが[SecureContext]拡張属性を持たなければ非安全コンテキストでも公開される。つまり、非安全コンテキストではExampleFeature.prototypeに"log"プロパティが存在する。
interface mixin Loggable {
  Promise<boolean> log();
};
ExampleFeature includes Loggable;

3.3.14. [Unscopable]

[Unscopable] 拡張属性が通常属性または通常操作に付与されている場合、 そのインターフェイスメンバーを持つインターフェイスを実装するオブジェクトは、そのプロパティ名を基底オブジェクトとするオブジェクト環境記録に含めない。 その結果、プロパティ名に一致する裸の識別子はwith文内ではそのプロパティに解決されない。 これはプロパティ名をインターフェイスプロトタイプオブジェクトの %Symbol.unscopables% プロパティ値に含めることで実現される。

[Unscopable] 拡張属性は 引数を取ってはならない。

[Unscopable] 拡張属性は 通常属性または通常操作以外には使ってはならない。

[Unscopable] 拡張属性は 名前空間で宣言された属性に使ってはならない。

[Unscopable]の使用に伴う詳細要件については § 3.7.3 インターフェイスプロトタイプオブジェクト を参照。

例として、下記のIDL:

[Exposed=Window]
interface Thing {
  undefined f();
  [Unscopable] g();
};

fプロパティはwith文内の裸の識別子として参照できるが、gプロパティは参照できない:

var thing = getThing();  // Thingのインスタンス
with (thing) {
  f;                     // Functionオブジェクトとして評価。
  g;                     // ReferenceErrorが投げられる。
}

3.4. レガシー拡張属性

この節では、JavaScriptバインディングに影響を与える拡張属性のうち、§ 3.3 拡張属性とは異なり、 現行標準Webプラットフォーム機能のためだけに存在するものを定義する。 仕様書では、レガシーAPIの動作を定義するために必要な場合以外は使用しないこと。

これらの拡張属性の使用理由がある場合は、事前に issueを提出 して議論することを強く推奨する。

3.4.1. [LegacyFactoryFunction]

この機能の代わりに、インターフェイスにコンストラクタ操作を持たせること。

[LegacyFactoryFunction] 拡張属性がインターフェイスに付与されている場合、 JavaScriptグローバルオブジェクトに指定された名前のプロパティができ、その値はインターフェイスを実装するオブジェクトを生成できる関数となる。 同じインターフェイスに複数の[LegacyFactoryFunction]拡張属性を付与できる。

[LegacyFactoryFunction] 拡張属性は 名前付き引数リストを取らなければならない。 identifierが「=」の後に出現した場合、それが[LegacyFactoryFunction]の 識別子となる。 インターフェイス上の各[LegacyFactoryFunction]拡張属性について、 指定された引数を上述のプロパティ値であるコンストラクタ関数に渡すことで インターフェイスを実装するオブジェクトを生成できる。

レガシーファクトリ関数に使う 識別子は、他のインターフェイスの [LegacyFactoryFunction ] 拡張属性で使う識別子と同じであってはならず、このインターフェイスまたは他のインターフェイスの [LegacyWindowAlias] 拡張属性で使う 識別子とも同じであってはなりません。また、 インターフェイスオブジェクトを持つインターフェイスの識別子と同じであってはならず、 予約済み識別子のいずれかであってもなりません。

[LegacyFactoryFunction]と[Global]拡張属性は同じインターフェイスに同時に指定してはならない。

レガシーファクトリ関数の実装詳細については § 3.7.2 レガシーファクトリ関数 を参照。

次のIDLは[LegacyFactoryFunction]拡張属性を使うインターフェイスを定義する:

[Exposed=Window,
 LegacyFactoryFunction=Audio(DOMString src)]
interface HTMLAudioElement : HTMLMediaElement {
  // ...
};

このインターフェイスをサポートするJavaScript実装ではHTMLAudioElementオブジェクトをAudio関数で生成できる:

typeof Audio;                   // 'function'。

var a2 = new Audio('a.flac');   // 引数1つのコンストラクタでHTMLAudioElementを生成。

追加のレガシー仕様として、これらのファクトリ関数はprototypeプロパティが元のインターフェイスのprototypeと等しくなる:

console.assert(Audio.prototype === HTMLAudioElement.prototype);

3.4.2. [LegacyLenientSetter]

[LegacyLenientSetter] 拡張属性がreadonly 通常属性に付与されている場合、 その属性のアクセサプロパティには何もしない(no-op)セッターが生成される。 これにより、strict modeでそのプロパティに誤って代入しても例外が投げられず無視されるようになる。

strict mode下で、IDL属性をポリフィルしようとプロパティへ代入した結果、プロパティが既に存在する場合に例外が投げられてページが壊れる事例が観測されている。 [LegacyLenientSetter]がないと、ブラウザはその機能を実装できなくなる場合がある。

[LegacyLenientSetter]拡張属性は 引数を取ってはならない。 readonly 通常属性以外には使ってはならない。

[LegacyLenientSetter]拡張属性付き属性は、 [PutForwards]や [Replaceable]拡張属性と同時に宣言してはならない。

[LegacyLenientSetter]拡張属性は 名前空間で宣言された属性に使ってはならない。

[LegacyLenientSetter]の実装方法については 属性の節を参照。

次のIDLは[LegacyLenientSetter]拡張属性を使うインターフェイスを定義する:

[Exposed=Window]
interface Example {
  [LegacyLenientSetter] readonly attribute DOMString x;
  readonly attribute DOMString y;
};

このインターフェイスをサポートするJavaScript実装では、xに対応するアクセサプロパティにはno-opのセッターがあり、strict modeでも代入しても無視される:

"use strict";

var example = getExample();  // Exampleのインスタンスを取得。

// strict modeでもセッターがno-opなので問題なし。
example.x = 1;

// strict modeでセッターがないためTypeErrorが投げられる。
example.y = 1;

3.4.3. [LegacyLenientThis]

[LegacyLenientThis] 拡張属性が通常属性に付与されている場合、 その属性のgetterやsetterを、属性が属するインターフェイスを実装していないオブジェクトで呼び出しても無視される。

[LegacyLenientThis] 拡張属性は引数を取ってはならない。 static属性には使ってはならない。

[LegacyLenientThis] 拡張属性は、名前空間で宣言された属性には使ってはならない。

[LegacyLenientThis]の実装方法については 属性の節を参照。

次のIDLは[LegacyLenientThis]拡張属性を使うインターフェイスを定義する:

[Exposed=Window]
interface Example {
  [LegacyLenientThis] attribute DOMString x;
  attribute DOMString y;
};

このインターフェイスをサポートするJavaScript実装では、xに対応するアクセサプロパティのgetter/setterはExampleオブジェクト以外でも呼び出せる:

var example = getExample();  // Exampleのインスタンスを取得。
var obj = { };

// 問題なし。
example.x;

// Exampleオブジェクト以外で呼び出しても無視される([LegacyLenientThis]使用時)。
Object.getOwnPropertyDescriptor(Example.prototype, "x").get.call(obj);

// Example.prototype自体でも無視される。
Example.prototype.x;

// y属性はTypeErrorになる(Example.prototypeはExampleオブジェクトではないため)。
Example.prototype.y;

3.4.4. [LegacyNamespace]

この機能の代わりに、インターフェイス名は特定の接頭辞で始める命名規則を使い、識別子にドットを入れず表現できる。

[LegacyNamespace] 拡張属性がインターフェイスに付与されている場合、 インターフェイスオブジェクトがグローバルオブジェクトのプロパティとしてではなく、拡張属性引数で指定された名前空間のプロパティとして作成される。

[LegacyNamespace] 拡張属性は識別子を取らなければならない。 この識別子は名前空間定義の識別子でなければならない。

[LegacyNamespace]と[LegacyNoInterfaceObject]拡張属性は同じインターフェイスに同時に指定してはならない。

名前空間上にインターフェイスを公開する詳細については § 3.13.1 名前空間オブジェクト を参照。

次のIDL断片は、 名前空間と[LegacyNamespace]を使ってその名前空間内に定義されるインターフェイスを定義する:
namespace Foo { };

[LegacyNamespace=Foo]
interface Bar {
  constructor();
};

上記名前空間・インターフェイスをサポートするJavaScript実装では、Barコンストラクタは次のようにアクセスできる:

var instance = new Foo.Bar();

3.4.5. [LegacyNoInterfaceObject]

[LegacyNoInterfaceObject] 拡張属性がインターフェイスに付与されている場合、 JavaScriptバインディングでそのインターフェイスのインターフェイスオブジェクトは作成されない。

[LegacyNoInterfaceObject] 拡張属性は引数を取ってはならない。

[LegacyNoInterfaceObject] 拡張属性は、 コンストラクタやstatic操作を持つインターフェイスには使ってはならない。

[LegacyNoInterfaceObject]拡張属性を持たないインターフェイスは、 [LegacyNoInterfaceObject]拡張属性を持つインターフェイスから継承してはならない。

[LegacyNoInterfaceObject]の使用に伴う詳細要件は § 3.7 インターフェイス を参照。

次のIDL断片は、インターフェイスオブジェクトがJavaScriptグローバルオブジェクトに公開されるものと、公開されないものの2つのインターフェイスを定義する:

[Exposed=Window]
interface Storage {
  undefined addEntry(unsigned long key, any value);
};

[Exposed=Window,
 LegacyNoInterfaceObject]
interface Query {
  any lookupEntry(unsigned long key);
};

このIDLのJavaScript実装では、Storageのプロトタイプは操作できるが、Queryのプロトタイプは操作できない:

typeof Storage;                        // "object"。

// Storage.addEntryにalert()を追加。
var fn = Storage.prototype.addEntry;
Storage.prototype.addEntry = function(key, value) {
  alert('Calling addEntry()');
  return fn.call(this, key, value);
};

typeof Query;                          // "undefined"。

var fn = Query.prototype.lookupEntry;  // 例外(Queryは定義されていない)

3.4.6. [LegacyNullToEmptyString]

[LegacyNullToEmptyString] 拡張 属性が DOMString または USVString 型に現れる場合、 JavaScript null がその IDL 型に変換されるときに、 デフォルトの処理とは異なる方法で処理される新しい IDL 型を作成する。デフォルトでは "null" に文字列化されるところ、代わりに空文字列に変換される。

[LegacyNullToEmptyString] 拡張属性は、 関連付けられる型が DOMString または USVString でない場合、その型に関連付けてはならない。

注: 型に 適用可能な他の拡張属性とは異なり、 型に適用可能である [LegacyNullToEmptyString] は、null 許容型、たとえば DOMString? には使用できない。これは null がすでにその 型の有効な値であるためである。

[LegacyNullToEmptyString] の使用に伴う具体的な要件については、§ 3.2.10 DOMString を参照されたい。

次のIDL断片は、 拡張属性付き型の属性と、拡張属性付き型の引数を持つ操作を持つインターフェイスを定義する:
[Exposed=Window]
interface Dog {
  attribute DOMString name;
  attribute [LegacyNullToEmptyString] DOMString owner;

  boolean isMemberOfBreed([LegacyNullToEmptyString] DOMString breedName);
};

このインターフェイスを実装するJavaScriptでは、DogのownerプロパティやisMemberOfBreedの引数にnullを渡すと、"null"ではなく空文字列になる:

var d = getDog();         // Dogインターフェイスのプラットフォームオブジェクト。

d.name = null;            // .nameへの代入は文字列"null"になる。
d.owner = null;           // .ownerへの代入は空文字列になる。
d.isMemberOfBreed(null);  // 引数は空文字列になる。

3.4.7. [LegacyOverrideBuiltIns]

[LegacyOverrideBuiltIns] 拡張 属性 が インターフェイスに現れる場合、 そのインターフェイスを実装する レガシープラットフォームオブジェクトについて、 オブジェクトのすべての サポートされるプロパティ名に対応するプロパティが オブジェクト上に存在するように見えることを示す。 これは、オブジェクトまたはその プロトタイプチェーン上に他のどのようなプロパティが存在するかに関係しない。つまり、名前付きプロパティは常に そうでなければオブジェクト上に現れるあらゆるプロパティを隠す。 これは通常の動作とは対照的であり、通常は名前付きプロパティは オブジェクト自体またはそのプロトタイプチェーン上のどこにも 同じ名前のプロパティがない場合にのみ公開される。

[LegacyOverrideBuiltIns] 拡張属性は 引数を 取ってはならず また、インターフェイスに現れてはならない そのインターフェイスが 名前付きプロパティ getterを定義していない場合、 または [Global] 拡張 属性でも宣言されている場合。 この拡張属性が 部分 インターフェイス 定義で指定されている場合、その部分インターフェイス定義は インターフェイス定義のうち、 名前付き プロパティ getterを定義する部分でなければならない。

部分インターフェイス定義で[LegacyOverrideBuiltIns]拡張属性が指定された場合は、インターフェイス本体にも付与されたものとみなす。

[LegacyOverrideBuiltIns]の使用に伴う詳細要件については § 3.9 レガシープラットフォームオブジェクトや § 3.9.3 [[DefineOwnProperty]] を参照。

次のIDL断片は、名前付きプロパティゲッターを持つインターフェイスと、持たないインターフェイスを定義する:

[Exposed=Window]
interface StringMap {
  readonly attribute unsigned long length;
  getter DOMString lookup(DOMString key);
};

[Exposed=Window,
 LegacyOverrideBuiltIns]
interface StringMap2 {
  readonly attribute unsigned long length;
  getter DOMString lookup(DOMString key);
};

これらのインターフェイスを実装するJavaScriptでは、プロパティの取得結果が異なる:

// StringMapのインスタンスを取得。サポートプロパティ名は"abc", "length", "toString"とする。
var map1 = getStringMap();

// 名前付きプロパティゲッター呼び出し。
map1.abc;

// length属性に対応する"length"プロパティ。
map1.length;

// プロトタイプチェーン上のtoStringプロパティ。
map1.toString;

// StringMap2のインスタンス。"abc", "length", "toString"がサポートプロパティ名。
var map2 = getStringMap2();

// 名前付きプロパティゲッター呼び出し。
map2.abc;

// length属性に対応する"length"プロパティだが、名前付きプロパティゲッターが呼ばれる。
map2.length;

// toStringプロパティも名前付きプロパティゲッターが呼ばれる。
map2.toString;

3.4.8. [LegacyTreatNonObjectAsNull]

[LegacyTreatNonObjectAsNull] 拡張 属性が コールバック関数に現れる場合、 これは、型が null 許容の コールバック 関数である 属性に代入される任意の値が、より緩やかに変換されることを示す。値がオブジェクトでない場合、その値は null に変換され、値が 呼び出し可能でない場合、その値は 呼び出されたときに何もしない コールバック 関数値に変換される。

§ 3.2.20 null 許容型 — T?、§ 3.2.19 コールバック関数型および § 3.12 コールバック 関数の呼び出しを参照し、 [LegacyTreatNonObjectAsNull] の使用に伴う具体的な要件を確認されたい。

次の IDL フラグメントは、1つの 属性の型が [LegacyTreatNonObjectAsNull] で注釈された コールバック 関数であり、もう1つの型が コールバック 関数で、拡張属性を持たないインターフェイスを定義する。

callback OccurrenceHandler = undefined (DOMString details);

[LegacyTreatNonObjectAsNull]
callback ErrorHandler = undefined (DOMString details);

[Exposed=Window]
interface Manager {
  attribute OccurrenceHandler? handler1;
  attribute ErrorHandler? handler2;
};

JavaScript実装では、オブジェクト以外(例: Number値)やcallableでない値をhandler1に代入すると、handler2への代入と挙動が異なる:

var manager = getManager();  // Managerインスタンスを取得。

manager.handler1 = function() { };
manager.handler1;            // 関数として評価。

try {
  manager.handler1 = 123;    // TypeErrorが投げられる。
} catch (e) {
}

try {
  manager.handler1 = {};     // TypeErrorが投げられる。
} catch (e) {
}

manager.handler2 = function() { };
manager.handler2;            // 関数として評価。

manager.handler2 = 123;
manager.handler2;            // nullとして評価。

manager.handler2 = {};
manager.handler2;            // オブジェクトとして評価。

3.4.9. [LegacyUnenumerableNamedProperties]

[LegacyUnenumerableNamedProperties] 拡張 属性 が インターフェイス に現れ、そのインターフェイスが 名前付きプロパティをサポートする場合、 そのインターフェイスのすべての名前付きプロパティが列挙不可であることを示す。

[LegacyUnenumerableNamedProperties] 拡張属性は 引数を 取ってはならず また、インターフェイスに現れてはならない そのインターフェイスが 名前付きプロパティ getterを定義していない場合。

[LegacyUnenumerableNamedProperties] 拡張属性がインターフェイスに指定されている場合、そのすべての派生インターフェイスに適用され、 それらのいずれにも指定してはならない。

§ 3.9.1 [[GetOwnProperty]] を参照し、 [LegacyUnenumerableNamedProperties] の使用に伴う具体的な要件を確認されたい。

3.4.10. [LegacyUnforgeable]

[LegacyUnforgeable] 拡張 属性が 通常 属性または非 静的 操作に現れる場合、 その属性または操作が JavaScript プロパティとして反映され、 その動作を変更できないようになり、 オブジェクトに対してプロパティ検索を行うと 常にその属性のプロパティ値が返されることを示す。 特に、そのプロパティは構成不可となり、 プロトタイプ上ではなく、 オブジェクト自体の own プロパティとして存在する。

属性または操作は、 指定されたインターフェイス A 上で 偽造不能であるという。これは、その属性または操作が A 上で宣言され、 かつ [LegacyUnforgeable] 拡張 属性で注釈されている場合である。

[LegacyUnforgeable] 拡張属性は 引数を取ってはならない。

[LegacyUnforgeable] 拡張 属性は 通常属性 または非 静的 操作以外のものに現れてはならない。 それが 操作に現れる場合、 そのインターフェイス上で 同じ 識別子を持つすべての操作に 現れなければならない。

[LegacyUnforgeable] 拡張属性は、 名前空間上で宣言された属性には使用してはならない。

属性または操作 X がインターフェイス A 上で 偽造不能であり、 A が別のインターフェイス B の 継承されたインターフェイスの1つである場合、 B は 通常属性 または非 静的 操作を、 X と同じ 識別子で 持ってはならない。

例:下記は許されない。

[Exposed=Window]
interface A1 {
  [LegacyUnforgeable] readonly attribute DOMString x;
};
[Exposed=Window]
interface B1 : A1 {
  undefined x();  // 不正:A1のxによってシャドウされる。
};

[Exposed=Window]
interface B2 : A1 { };
B2 includes M1;
interface mixin M1 {
  undefined x();  // 不正:B2のxはA1のxでシャドウされる。
};

詳細要件は § 3.7.6 属性、§ 3.7.7 操作、§ 3.8 インターフェイスを実装するプラットフォームオブジェクト、§ 3.9 レガシープラットフォームオブジェクト、§ 3.9.3 [[DefineOwnProperty]] を参照。[LegacyUnforgeable]使用時の具体的要件が記載されている。

次のIDL断片は、2つの属性を持つインターフェイスを定義し、1つは[LegacyUnforgeable]指定:

[Exposed=Window]
interface System {
  [LegacyUnforgeable] readonly attribute DOMString username;
  readonly attribute long long loginTime;
};

JavaScript実装では、username属性はオブジェクト自身のnon-configurableなプロパティとして公開される:

var system = getSystem();                      // Systemインスタンス取得。

system.hasOwnProperty("username");             // true。
system.hasOwnProperty("loginTime");            // false。
System.prototype.hasOwnProperty("username");   // false。
System.prototype.hasOwnProperty("loginTime");  // true。

try {
  // non-configurableなので失敗。
  Object.defineProperty(system, "username", { value: "administrator" });
} catch (e) { }

// System.prototype.loginTimeはconfigurableなのでdefinePropertyできる。
var forgedLoginTime = 5;
Object.defineProperty(System.prototype, "loginTime", { value: forgedLoginTime });

system.loginTime;  // forgedLoginTimeが返る。

3.4.11. [LegacyWindowAlias]

[LegacyWindowAlias] 拡張 属性が インターフェイスに現れる場合、 これは、Window インターフェイスが、 プロパティを 拡張属性で言及された各 識別子について 持つことを示し、 その値は、そのインターフェイスの インターフェイスオブジェクトである。

[LegacyWindowAlias] 拡張属性は 識別子または 識別子リストを取ることができる。 「=」の後に現れるidentifierは[LegacyWindowAlias]の 識別子となる。

[LegacyWindowAlias]の識別子は、このインターフェイスまたは他のインターフェイスの[LegacyWindowAlias]拡張属性、[LegacyFactoryFunction]拡張属性で使われる識別子、インターフェイスオブジェクトを持つインターフェイスの識別子、予約識別子と重複してはならない。

[LegacyWindowAlias]と[LegacyNoInterfaceObject]拡張属性は同じインターフェイスに同時に指定してはならない。

[LegacyWindowAlias]と[LegacyNamespace]拡張属性は同じインターフェイスに同時に指定してはならない。

[LegacyWindowAlias]拡張属性は、Windowインターフェイスを公開セットに含まないインターフェイスには指定してはならない。

インターフェイスに複数の[LegacyWindowAlias]拡張属性を指定してはならない。

レガシーwindowエイリアスの実装詳細については § 3.7 インターフェイス を参照。

下記IDLは[LegacyWindowAlias]を使うインターフェイスを定義する:

[Exposed=Window,
 LegacyWindowAlias=WebKitCSSMatrix]
interface DOMMatrix : DOMMatrixReadOnly {
  // ...
};

このインターフェイスをサポートするJavaScript実装では、Windowオブジェクト上に、同じ値・同じ特性を持つ2つのプロパティが公開される。一つは通常のインターフェイスオブジェクト用、もう一つはレガシー名用。

WebKitCSSMatrix === DOMMatrix;     // true。

var m = new WebKitCSSMatrix();     // DOMMatrixを実装する新しいオブジェクトを生成。

m.constructor === DOMMatrix;       // true。
m.constructor === WebKitCSSMatrix; // true。
{}.toString.call(m);               // '[object DOMMatrix]'。

3.5. セキュリティ

以下の節で定義される一部のアルゴリズムは、あるオブジェクトに対してセキュリティチェックを実行する。 このチェックは、操作の呼び出しや属性へのアクセスを許可すべきか判断するために用いられる。セキュリティチェックは次の3つの入力を取る:

  1. 操作呼び出しや属性アクセスが行われているプラットフォームオブジェクト

  2. 操作や属性の識別子

  3. 関数オブジェクトの種類 — 操作の場合は"method"、属性のgetter/setterの場合は"getter"または"setter"。

注: セキュリティチェックの実装方法はHTML標準で定義されている。[HTML]

3.6. オーバーロード解決アルゴリズム

関数呼び出しがどのように解決されるかを定義するため、 オーバーロード解決アルゴリズム を定義する。その入力は 有効オーバーロード集合 S と、JavaScript 値のリスト args である。 その出力は、S のいずれかのエントリーの 操作または 拡張 属性と、 IDL 値または特殊値 “missing” のリストからなるペアである。アルゴリズムは次のように動作する。

  1. maxarg を、S のエントリーの型リストのうち最長のものの長さとする。

  2. n を args の サイズとする。

  3. argcount を min(maxarg, n) に初期化する。

  4. 型リストの長さが argcount でないすべてのエントリーを S から削除する。

  5. S が空の場合、TypeError を スローする。

  6. d を −1 に初期化する。

  7. method を undefined に初期化する。

  8. S に複数のエントリーがある場合、 d を S のエントリーの 識別引数インデックス に設定する。

  9. values を空のリストに初期化する。各エントリーは IDL 値または 特殊値 “missing” のいずれかとなる。

  10. i を 0 に初期化する。

  11. i < d の間、次を行う。

    1. V を args[i] とする。

    2. type を、S の任意のエントリーの型リストにおけるインデックス i の型と する。

      注: この時点で S のすべてのエントリーは、 インデックス i において同じ型と オプション性値を持つ。

    3. optionality を、S の任意のエントリーの オプション性値のリストにおけるインデックス i の値と する。

    4. optionality が “optional” で、V が undefined の場合、 次を行う。

      1. インデックス i の引数が デフォルト値付きで宣言されている 場合、そのデフォルト値を values に追加する。

      2. そうでなければ、特殊値 “missing” を values に追加する。

    5. そうでなければ、V を IDL 型 type に 変換した 結果を values に追加する。

    6. i を i + 1 に設定する。

  12. i = d の場合、次を行う。

    1. V を args[i] とする。

      注: これは、どのオーバーロードが選択されるかを 解決するために使用される引数である。

    2. V が undefined であり、S に オプション性値のリストのインデックス i に “optional” を持つエントリーがある 場合、他のすべてのエントリーを S から削除する。

    3. そうでなく、V が null または undefined であり、 S に、型リストの位置 i に次の型のいずれかを持つエントリーがある場合、

      他のすべてのエントリーを S から削除する。

    4. そうでなく、V が プラットフォームオブジェクトであり、 S に、型リストの位置 i に次の型のいずれかを持つエントリーがある場合、

      他のすべてのエントリーを S から削除する。

    5. そうでなく、V が Object であり、V が [[ArrayBufferData]] 内部スロットを持ち、 S に、型リストの位置 i に次の型のいずれかを持つエントリーがある場合、

      他のすべてのエントリーを S から削除する。

    6. そうでなく、V が Object であり、V が [[DataView]] 内部スロットを持ち、 S に、型リストの位置 i に次の型のいずれかを持つエントリーがある場合、

      他のすべてのエントリーを S から削除する。

    7. そうでなく、V が Object であり、V が [[TypedArrayName]] 内部スロットを持ち、 S に、型リストの位置 i に次の型のいずれかを持つエントリーがある場合、

      他のすべてのエントリーを S から削除する。

    8. そうでなく、IsCallable(V) が true であり、 S に、型リストの位置 i に次の型のいずれかを持つエントリーがある場合、

      他のすべてのエントリーを S から削除する。

    9. そうでなく、V が Object であり、 S に、型リストの位置 i に次の 型のいずれかを持つエントリーがある場合、

      かつ、次のすべてが true ではなく、

      かつ、次の手順を実行した後、

      1. method を ? GetMethod(V, %Symbol.asyncIterator%) とする。

      2. method が undefined の場合、method を ? GetMethod(V, %Symbol.iterator%) に設定する。

      method が undefined でない場合、他のすべての エントリーを S から削除する。

    10. そうでなく、V が Object であり、 S に、型リストの位置 i に次の 型のいずれかを持つエントリーがある場合、

      かつ、次の手順を実行した後、

      1. method を ? GetMethod(V, %Symbol.iterator%) とする。

      method が undefined でない場合、他のすべての エントリーを S から削除する。

    11. そうでなく、V が Object であり、 S に、型リストの位置 i に次の型のいずれかを持つエントリーがある場合、

      他のすべてのエントリーを S から削除する。

    12. そうでなく、V が Boolean であり、 S に、型リストの位置 i に次の型のいずれかを持つエントリーがある場合、

      他のすべてのエントリーを S から削除する。

    13. そうでなく、V が Number であり、 S に、型リストの位置 i に次の型のいずれかを持つエントリーがある場合、

      他のすべてのエントリーを S から削除する。

    14. そうでなく、V が BigInt であり、 S に、型リストの位置 i に次の型のいずれかを持つエントリーがある場合、

      他のすべてのエントリーを S から削除する。

    15. そうでなく、S に、型リストの 位置 i に次の型のいずれかを持つエントリーがある場合、

      他のすべてのエントリーを S から削除する。

    16. そうでなく、S に、型リストの 位置 i に次の型のいずれかを持つエントリーがある場合、

      他のすべてのエントリーを S から削除する。

    17. そうでなく、S に、型リストの 位置 i に次の型のいずれかを持つエントリーがある場合、

      他のすべてのエントリーを S から削除する。

    18. そうでなく、S に、型リストの 位置 i に次の型のいずれかを持つエントリーがある場合、

      他のすべてのエントリーを S から削除する。

    19. そうでなく、S に any を型リストの位置 i に持つエントリーがある場合、他のすべてのエントリーを S から削除する。

    20. そうでなければ、TypeError を スローする。

  13. callable を、S の唯一のエントリーの 操作または 拡張属性 とする。

  14. i = d かつ method が undefined でない場合、

    1. V を args[i] とする。

    2. T を、S に残っているエントリーの 型リストにおけるインデックス i の型とする。

    3. アサート: T は シーケンス型である。

    4. V と method から型 T の シーケンスを作成した 結果を values に追加する。

    5. i を i + 1 に設定する。

  15. i < argcount の間、次を行う。

    1. V を args[i] とする。

    2. type を、S に残っている エントリーの型リストにおけるインデックス i の型とする。

    3. optionality を、S に残っているエントリーの オプション性値のリストにおけるインデックス i の値とする。

    4. optionality が “optional” で、V が undefined の場合、 次を行う。

      1. インデックス i の引数が デフォルト値付きで宣言されている 場合、そのデフォルト値を values に追加する。

      2. そうでなければ、特殊値 “missing” を values に追加する。

    5. そうでなければ、 V を IDL 型 type に 変換した結果を values に追加する。

    6. i を i + 1 に設定する。

  16. i が callable が取るよう宣言されている引数の数未満である間、

    1. callable のインデックス i の引数が デフォルト値付きで宣言されている場合、 そのデフォルト値を values に追加する。

    2. そうでなく、callable のインデックス i の引数が可変長でない場合、 特殊値 “missing” を values に追加する。

    3. i を i + 1 に設定する。

  17. ペア <callable, values> を返す。

オーバーロード解決アルゴリズムは、呼び出されるオーバーロードされた操作やコンストラクタ等の特定と、JavaScript引数値の対応するIDL値への変換の両方を行う。非公式には以下のように動作する。

まず、関数に渡されたJavaScript引数の数で有効なオーバーロードを選択する:

正しい引数数の可能なオーバーロード集合が得られたら、JavaScript値を左から右へ変換する。オーバーロード時の制約により、この時点で複数の候補がある場合、引数リストの中でどの位置を使って最終的なオーバーロードを選択するかが決まる。この位置が識別引数インデックスである。

まず識別引数より左の引数を変換する(左側の引数は他のオーバーロードでも同じインデックスで同じ型である必要がある)。次に識別引数インデックスで渡されたJavaScript値の型を調べ、それがどのIDL型に対応するかを判定する。これにより最終的に呼び出すオーバーロードが決定される。ここで渡された値がundefinedで、その位置にoptional引数のオーバーロードがあれば、そのオーバーロードを選択する。ここで渡された値の型に対応する有効なオーバーロードがなければTypeErrorをスローする。一般的に、識別引数インデックスでの値検査は副作用を持たず、オーバーロード解決アルゴリズムでの副作用はJavaScript値のIDL値への変換のみである(例外として、識別引数インデックスがasync sequence型、sequence型、frozen array型のいずれかの場合、該当するオーバーロードを決めるために%Symbol.asyncIterator% / %Symbol.iterator%プロパティの取得を試み、識別引数の変換を個別に行う)。

この時点で使用するオーバーロードが決定したので、残りの引数(識別引数以降)も変換し、最後の可能な引数以降に渡された余分な引数は引き続き無視する。

optional引数のJavaScript値をIDL値に変換する際、undefinedはoptional引数のデフォルト値(あれば)に変換され、なければ特別な値“missing”になる。

ただし、最終の可変長(variadic)引数に対応するoptional引数の場合は、undefinedは“missing”として特別扱いされず、非optional引数と同様に可変長引数型に変換される。

3.7. インターフェイス

ある インターフェイスが 所与の realm で 公開されており、 [LegacyNoInterfaceObject] または [LegacyNamespace] 拡張 属性を指定して宣言されていないすべての場合について、 対応するプロパティが、その realm の グローバルオブジェクト上に存在する。 そのプロパティの名前はインターフェイスの 識別子であり、 その値は インターフェイスオブジェクトと呼ばれるオブジェクトである。 インターフェイスオブジェクトの特性については、§ 3.7.1 インターフェイス オブジェクトで説明する。

もし LegacyWindowAlias 拡張属性が 公開されたインターフェイスに指定されている場合、 LegacyWindowAlias の識別子群に含まれる各 識別子ごとに、Window グローバルオブジェクト上に対応するプロパティが存在する。 プロパティ名は指定された 識別子 となり、 その値はそのインターフェイスのインターフェイスオブジェクトへの参照である。

さらに、公開インターフェイス上の各[LegacyFactoryFunction]拡張属性ごとに、JavaScriptグローバルオブジェクト上に対応するプロパティが存在する。 プロパティ名は[LegacyFactoryFunction]の識別子であり、その値はレガシーファクトリ関数と呼ばれるオブジェクトで、インターフェイスを実装するオブジェクトの生成を可能にする。 レガシーファクトリ関数の特性については§ 3.7.2 レガシーファクトリ関数を参照。

本節で定義される一部のJavaScriptメソッドは、最初のステップで実装チェックを行い、呼び出し対象が正しい種類のオブジェクトであり、現在のコンテキストから呼び出し可能かどうか検証する。

オブジェクトの実装チェックを行うには、jsValueをインターフェイスinterface・識別子name・型typeに対して:

  1. objectを? ToObject(jsValue)とする。

  2. objectがプラットフォームオブジェクトなら、以下を渡してセキュリティチェックを実行:

    • プラットフォームオブジェクトobject

    • 識別子name

    • 型type

  3. objectがinterfaceを実装していない場合、TypeErrorをスロー。

  4. objectを返す。

このアルゴリズムは現時点で一貫して使われているわけではない。

3.7.1. インターフェイスオブジェクト

あるインターフェイスオブジェクトは、そのインターフェイスに対応する組み込み関数オブジェクトとなる。 インターフェイスオブジェクトには、そのインターフェイス上で定義された定数やstatic操作に対応するプロパティが存在する(詳細は§ 3.7.5 定数や§ 3.7.7 操作参照)。

インターフェイスがコンストラクタ操作で宣言されている場合、そのインターフェイスオブジェクトはコンストラクタとして呼び出すことができ、そのインターフェイスを実装するオブジェクトが生成される。 関数として呼び出すと例外が投げられる。

インターフェイスオブジェクトで、そのインターフェイスがコンストラクタ操作で宣言されていない場合、関数としてもコンストラクタとしても呼び出すと例外が投げられる。

インターフェイスIのインターフェイスオブジェクトは、インターフェイスプロトタイプオブジェクトを関連付けて持つ。 このプロトタイプオブジェクトには、インターフェイス上で定義された通常属性や通常操作に対応するプロパティが存在し、詳細は§ 3.7.3 インターフェイスプロトタイプオブジェクト参照。

注: インターフェイスオブジェクトは関数オブジェクトなので、typeof演算子を適用すると"function"が返る。

インターフェイスはオーバーライドされたコンストラクタ手順を持ちうる。これによりインターフェイスオブジェクトの呼び出しや構築時の挙動が変更される。デフォルトではこの手順は持たない。

通常、コンストラクタはコンストラクタ操作とその挙動を定義することで記述される。 オーバーライドされたコンストラクタ手順は、より複雑な状況でのみ使用すること。 この機能を使いたい編集者は事前にissueを提出して議論することを強く推奨する。

インターフェイスI(識別子id)のインターフェイスオブジェクト をrealm(レルム)で生成する手順:

  1. steps を、もし存在する場合は I の 上書きされたコンストラクター手順 とし、 存在しない場合は以下の手順とする:

    1. もし I が constructor operation とともに宣言されていなかった場合、 スロー する TypeError。

    2. もし NewTarget が undefined であれば、 スロー する TypeError。

    3. args を、渡された引数とする。

    4. n を サイズ、 args の要素数とする。

    5. id をインターフェース I の識別子とする。

    6. 有効なオーバーロードセットを計算する。 識別子 id を持つ インターフェース I 上のコンストラクターと引数数 n で、結果を S とする。

    7. <constructor, values> を、S と args を オーバーロード解決アルゴリズム に渡した結果とする。

    8. object を、インターフェース I を実装する新しいオブジェクトを内部的に生成する の結果とし、realm および NewTarget を使用する。

    9. コンストラクター手順を constructor で実行し、 object を this として、values を引数値として渡す。

    10. O を object、 JavaScript値へ変換済み とする。

    11. アサート:O は 実装している I であるオブジェクトである。

    12. アサート:O.[[Realm]] は realm である。

    13. O を返す。

  2. constructorProto を realm.[[Intrinsics]].[[%Function.prototype%]] とする。

  3. もし I が他のインターフェース P から継承している場合、 constructorProto を realm の インターフェースオブジェクト P に設定する。

  4. unforgeables を OrdinaryObjectCreate(null) とする。

  5. 偽造不能な通常操作を定義する、 realm を与えて I の unforgeables 上に。

  6. 偽造不能な通常属性を定義する、 realm を与えて I の unforgeables 上に。

  7. F.[[Unforgeables]] に unforgeables を設定する。

    注: このオブジェクトはユーザーコードには決して公開されません。 これはインターフェースに偽造不能なメンバがある場合、すべてのインスタンスが 属性getter、属性setter、および 操作関数用に 同じJavaScript関数オブジェクトを使用することを保証するためだけに存在します。

  8. length を 0 とする。

  9. もし I が constructor operation とともに宣言されていた場合、

    1. 有効なオーバーロードセットを計算する。 識別子 id を持つ インターフェース I 上の引数数0のコンストラクターで、結果を S とする。

    2. S に含まれるエントリの引数リストの中で最も短いものの長さを length に設定する。

  10. F を CreateBuiltinFunction(steps, length, id, « [[Unforgeables]] », realm, constructorProto) とする。

  11. proto を、インターフェースプロトタイプオブジェクトを作成する インターフェース I を realm での結果とする。

  12. ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: proto, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false}) を実行する。

  13. 定数を定義する、 インターフェース I の F 上に realm を与えて。

  14. 静的属性を定義する、 インターフェース I の F 上に realm を与えて。

  15. 静的操作を定義する、 インターフェース I の F 上に realm を与えて。

  16. F を返す。

3.7.2. レガシーファクトリ関数

1つ以上の レガシーファクトリー関数が、 [LegacyFactoryFunction] 拡張 属性によって存在し、 所定の 識別子を持つものは、組み込み関数オブジェクトである。 これにより、 次の [LegacyFactoryFunction] 拡張属性が現れるインターフェイスを実装するオブジェクトを構築できる。

レガシーファクトリー関数は、識別子 id を持ち、 所定の インターフェイス I について、レルム realm で、 次のように 作成される。

  1. steps を次の手順とする。

    1. NewTarget が undefined の場合、 スローする TypeError。

    2. args を渡された引数とする。

    3. n を サイズ( args の)とする。

    4. 有効オーバーロード 集合を計算する。レガシーファクトリー関数の 識別子 id について、 対象となる インターフェイス I と引数の個数 n を用い、その結果を S とする。

    5. <constructor, values> を、 S と args を オーバーロード解決アルゴリズムに渡した結果とする。

    6. object を、内部的に 新しいオブジェクトを作成して I を実装した結果とし、realm と NewTarget を用いる。

    7. constructor の コンストラクター手順を実行し、 object を this とし、values を引数値とする。

    8. O を、object を JavaScript 値に変換したものとする。

    9. アサート: O は I を 実装するオブジェクトである。

    10. アサート: O.[[Realm]] は realm である。

    11. O を返す。

  2. 有効オーバーロード集合を計算する。対象は、 識別子 id を持つレガシーファクトリー関数であり、 インターフェイス I 上で引数の個数を 0 とし、その結果を S とする。

  3. length を、S のエントリーの引数リストのうち最短のものの長さとする。

  4. F を CreateBuiltinFunction(steps, length, id, « », realm) とする。

  5. proto を、インターフェイスプロトタイプオブジェクト、インターフェイス I の realm におけるものとする。

  6. 次を実行する: ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: proto, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false}).

  7. F を返す。

3.7.3. インターフェイスプロトタイプオブジェクト

定義されたすべての インターフェイスプロトタイプオブジェクトは、 インターフェイスごとに存在し、 そのインターフェイスが [LegacyNoInterfaceObject] 拡張 属性で宣言されているかどうかには関係しない。

所定の インターフェイスプロトタイプオブジェクトは、インターフェイス interface および レルム realm について、 次のように 作成される。

  1. proto を null とする。

  2. interface が [Global] 拡張属性で宣言され、 かつ interface が 名前付きプロパティをサポートする場合、 proto を、interface と realm のために 名前付き プロパティオブジェクトを作成した結果に設定する。

  3. そうでなく、interface が別のインターフェイスから継承するよう宣言されている場合、 proto を インターフェイスプロトタイプオブジェクト、 realm における その 継承元インターフェイスのものに設定する。

  4. そうでなく、interface が DOMException インターフェイスである場合、 proto を realm.[[Intrinsics]].[[%Error.prototype%]] に設定する。

  5. そうでなければ、proto を realm.[[Intrinsics]].[[%Object.prototype%]] に設定する。

  6. アサート: proto は Object である。

  7. interfaceProtoObj を null とする。

  8. realm の グローバルプロトタイプチェーンが可変である が true の場合、次を行う。

    1. interfaceProtoObj を OrdinaryObjectCreate(proto) に設定する。

  9. そうでなく、interface が [Global] 拡張属性で宣言されているか、または interface が、[Global] 拡張属性で宣言されたインターフェイスの 継承元インターフェイスの集合に含まれる場合、次を行う。

    1. interfaceProtoObj を MakeBasicObject(« [[Prototype]], [[Extensible]] ») に設定する。

    2. interfaceProtoObj.[[Prototype]] を proto に設定する。

    3. interfaceProtoObj の内部メソッドのうち、 不変プロトタイプエキゾチック オブジェクトに固有のものを、 ECMA-262 の不変プロトタイプ エキゾチックオブジェクトで指定された定義に設定する。

  10. そうでなければ、interfaceProtoObj を OrdinaryObjectCreate(proto) に設定する。

  11. interface に、[Unscopable] 拡張属性で宣言された メンバーが存在する場合、 次を行う。

    1. unscopableObject を OrdinaryObjectCreate(null) とする。

    2. interface の、[Unscopable] 拡張属性で宣言された 各 公開された メンバー member について、

      1. id を member の 識別子とする。

      2. ! CreateDataPropertyOrThrow(unscopableObject, id, true) を実行する。

    3. desc を PropertyDescriptor{[[Value]]: unscopableObject, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true} とする。

    4. ! DefinePropertyOrThrow(interfaceProtoObj, %Symbol.unscopables%, desc) を実行する。

  12. interface が [Global] 拡張属性で宣言されていない場合、次を行う。

    1. 所定の realm において interface の 通常属性を定義する( interfaceProtoObj 上に)。

    2. 所定の realm において interface の 通常操作を定義する( interfaceProtoObj 上に)。

    3. 所定の realm において interface の 反復メソッドを定義する( interfaceProtoObj 上に)。

    4. 所定の realm において interface の 非同期 反復メソッドを定義する(interfaceProtoObj 上に)。

  13. 所定の realm において interface の 定数を 定義する(interfaceProtoObj 上に)。

  14. [LegacyNoInterfaceObject] 拡張属性が interface に指定されていない場合、次を行う。

    1. constructor を、realm における interface の インターフェイスオブジェクトと する。

    2. desc を PropertyDescriptor{[[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true, [[Value]]: constructor} とする。

    3. ! DefinePropertyOrThrow(interfaceProtoObj, "constructor", desc) を実行する。

  15. interfaceProtoObj を返す。

さらに、インターフェイスプロトタイプオブジェクトは、次から宣言的にプロパティを 取得する。

代わりに、それらのプロパティを命令的に定義する。

[LegacyNoInterfaceObject] 拡張 属性で 定義された インターフェイスの インターフェイスプロトタイプオブジェクトには アクセスできる。 たとえば、次の IDL の場合、

[Exposed=Window,
 LegacyNoInterfaceObject]
interface Foo {
};

partial interface Window {
  attribute Foo foo;
};

インターフェイスプロトタイプオブジェクトには、 インターフェイス オブジェクトを介してアクセスすることはできない (window.Foo として存在しないため)。ただし、 Foo のインスタンスは、その [[GetPrototypeOf]] 内部メソッドを呼び出すことで、インターフェイスプロトタイプ オブジェクトを公開できる。この例では Object.getPrototypeOf(window.foo) である。

インターフェイスプロトタイプオブジェクトの クラス文字列は、インターフェイスの 修飾名である。

3.7.4. 名前付きプロパティオブジェクト

[Global] で宣言されたすべての インターフェイスについて、 拡張 属性を持ち、 名前付きプロパティをサポートする場合、 そのインターフェイスには、名前付きプロパティオブジェクトとして知られるオブジェクトが存在し、 その上で名前付きプロパティが公開される。

名前付きプロパティオブジェクト(インターフェイスinterface・レルムrealm)の生成手順:
  1. protoをnullで初期化。

  2. interfaceが他インターフェイスから継承していれば、protoをrealm内の継承インターフェイスのインターフェイスプロトタイプオブジェクトでセット。

  3. それ以外はprotoをrealm.[[Intrinsics]].[[%Object.prototype%]]でセット。

  4. objをMakeBasicObject(« [[Prototype]], [[Extensible]] »)で生成。

  5. obj.[[GetOwnProperty]]を§ 3.7.4.1 [[GetOwnProperty]]の定義に従ってセット。

  6. obj.[[DefineOwnProperty]]を§ 3.7.4.2 [[DefineOwnProperty]]の定義に従ってセット。

  7. obj.[[Delete]]を§ 3.7.4.3 [[Delete]]の定義に従ってセット。

  8. obj.[[SetPrototypeOf]]を§ 3.7.4.4 [[SetPrototypeOf]]の定義に従ってセット。

  9. obj.[[PreventExtensions]]を§ 3.7.4.5 [[PreventExtensions]]の定義に従ってセット。

  10. obj.[[Prototype]]にprotoをセット。

  11. objを返す。

注: 名前付きプロパティオブジェクトの[[OwnPropertyKeys]]内部メソッドはOrdinaryOwnPropertyKeysを使い続ける。レガシープラットフォームオブジェクトの対応物とは異なる。名前付きプロパティは「本当の」独自プロパティではないため、この内部メソッドでは返されない。

名前付きプロパティオブジェクトのクラス文字列は、インターフェイスの識別子と文字列"Properties"を連結したもの。

3.7.4.1. [[GetOwnProperty]]

名前付きプロパティ オブジェクト O の [[GetOwnProperty]] 内部メソッドが プロパティキー P で呼び出された場合、次の手順を実行する。

  1. A を、名前付き プロパティオブジェクト O の インターフェイスとする。

  2. object を、O.[[Realm]] の グローバルオブジェクトとする。

  3. アサート: object は A を 実装する。

  4. プロパティ名 P とオブジェクト object を用いて 名前付きプロパティ可視性アルゴリズムを実行した結果が true の場合、次を行う。

    1. operation を、名前付きプロパティ getter の宣言に使用された操作とする。

    2. value を未初期化の変数とする。

    3. operation が 識別子なしで定義されていた場合、 value を、インターフェイスの説明に列挙された手順を実行して P を名前として 名前付きプロパティの値を 決定した 結果に設定する。

    4. そうでなければ、operation は識別子付きで定義されていた。value を、 operation の説明に列挙された手順を P を唯一の引数値として実行した結果に 設定する。

    5. desc を、新たに作成されたフィールドを持たない Property Descriptor と する。

    6. desc.[[Value]] を、value を JavaScript 値に 変換した 結果に設定する。

    7. A が [LegacyUnenumerableNamedProperties] 拡張属性を持つインターフェイスを 実装する場合、 desc.[[Enumerable]] を false に設定し、 そうでなければ true に設定する。

    8. desc.[[Writable]] を true に設定し、 desc.[[Configurable]] を true に設定する。

    9. desc を返す。

  5. OrdinaryGetOwnProperty(O, P) を返す。

3.7.4.2. [[DefineOwnProperty]]

名前付きプロパティオブジェクトの[[DefineOwnProperty]]内部メソッドが呼び出されたとき、以下の手順を行う:

  1. falseを返す。

3.7.4.3. [[Delete]]

名前付きプロパティオブジェクトの[[Delete]]内部メソッドが呼び出されたとき、以下の手順を行う:

  1. falseを返す。

3.7.4.4. [[SetPrototypeOf]]

名前付きプロパティオブジェクトOの[[SetPrototypeOf]]内部メソッドがJavaScript値Vで呼び出されたとき、以下の手順を行う:

  1. もしOの関連付けられたrealmのグローバルプロトタイプチェーンがmutableなら、 ? OrdinarySetPrototypeOf(O, V)を返す。

  2. ? SetImmutablePrototype(O, V)を返す。

3.7.4.5. [[PreventExtensions]]

名前付きプロパティオブジェクトの[[PreventExtensions]]内部メソッドが呼び出されたとき、以下の手順を行う:

  1. falseを返す。

注: これにより[[PreventExtensions]]が失敗することで、名前付きプロパティオブジェクトを拡張可能なままに保つ。

3.7.5. 定数

定数は インターフェイス オブジェクト、 レガシーコールバックインターフェイスオブジェクト、 インターフェイスプロトタイプオブジェクト、および インターフェイスが [Global] 拡張 属性で宣言されている場合、そのインターフェイスを 実装する唯一のオブジェクト上にも公開される。

定数定義をインターフェイス・コールバックインターフェイス・名前空間definitionでtarget(レルムrealm指定)に対して行うには、以下の手順:
  1. 全ての 定数const(definitionのメンバー)について:

    1. constがrealmで公開されていなければ、continue。

    2. valueにconstのIDL値をJavaScript値へ変換したものをセット。

    3. descにPropertyDescriptor{[[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false, [[Value]]: value}をセット。

    4. idにconstの識別子をセット。

    5. ! DefinePropertyOrThrow(target, id, desc)を実行。

3.7.6. 属性

静的 属性は インターフェイスオブジェクト上で公開される。 通常 属性は インターフェイスプロトタイプオブジェクト上で公開される。 ただし、その属性が 偽造不能である場合、または インターフェイスが [Global] 拡張 属性で宣言されている場合は例外であり、 その場合、それらはインターフェイスを 実装するすべてのオブジェクト上で公開される。

通常の属性を定義するために、インターフェースまたは名前空間definitionをtarget上に、 realmrealmを与えて、以下の手順を実行します:
  1. attributesを、リストとして、通常の属性であるdefinitionのメンバーのリストとして初期化します。

  2. attributesから属性であり 偽造不可なものをすべて削除します。

  3. attributesのattributesをdefinitionのtarget上にrealmを与えて定義します。

静的属性を定義するために、インターフェースまたは名前空間definitionをtarget上に、 realmrealmを与えて、以下の手順を実行します:
  1. attributesを、リストとして、静的属性であるdefinitionのメンバーのリストとして初期化します。

  2. attributesのattributesをdefinitionのtarget上にrealmを与えて定義します。

偽造不可な通常の属性を定義するために、インターフェースまたは名前空間 definition をtarget上に、 realmrealmを与えて、以下の手順を実行します:
  1. attributesを、リストとして、偽造不可な通常の属性であり メンバーであるもののリストとして初期化します。

  2. attributesのattributesをdefinitionのtarget上にrealmを与えて定義します。

属性を定義するために、attributesをインターフェースまたは名前空間definitionのtarget上に、 realmrealmを与えて、以下の手順を実行します:
  1. attributesの各属性attrについて:

    1. もしattrがrealmで公開されていなければ、continueします。

    2. getterを、属性ゲッターの生成結果として、attr、definition、realmを与えて取得します。

    3. setterを、属性セッターの生成結果として、attr、definition、realmを与えて取得します。

      注:属性セッター生成アルゴリズムは、 attrが読み取り専用の場合はundefinedを返します。

    4. もしattrが偽造不可ならconfigurableはfalseとし、 そうでなければtrueとします。

    5. descをPropertyDescriptor{[[Getter]]: getter, [[Setter]]: setter, [[Enumerable]]: true, [[Configurable]]: configurable}とします。

    6. idをattrの識別子とします。

    7. ! DefinePropertyOrThrow(target, id, desc)を実行します。

    8. もしattrの型が型引数Tをもつオブザーバブル配列型なら、 targetのバックエンドオブザーバブル配列エキゾチックオブジェクトを attrのために、オブザーバブル配列エキゾチックオブジェクトの作成アルゴリズムの結果(realm、T、attrのインデックス付き値の設定アルゴリズム、attrのインデックス付き値の削除アルゴリズム)で設定します。

属性ゲッターは、以下のようにして生成されます。与えられるのは 属性 attribute、名前空間またはインターフェースtarget、realmrealmです:

  1. steps を次の一連の手順とする:

    1. 次の手順の実行を試みる:

      1. idlObject を null とする。

      2. もし target が インターフェース であり、attribute が 通常属性 である場合:

        1. jsValue を this の値(nullまたはundefinedでなければ)、 そうでなければ realm の グローバルオブジェクト とする。 (この後のステップでグローバルオブジェクトが target を実装しておらず [LegacyLenientThis] が 指定されていない場合は TypeError になる。)

        2. もし jsValue が プラットフォームオブジェクトである なら、 セキュリティチェックを実施する。jsValue、 attribute の 識別子、"getter" を渡す。

        3. もし jsValue が target を実装していない 場合:

          1. もし attribute が [LegacyLenientThis] 拡張属性 として指定されている場合は undefined を返す。

          2. それ以外の場合、スローする TypeError。

        4. もし attribute の型が observable array type であれば、 jsValue の backing observable array exotic object for attribute を返す。

        5. jsValue を参照するIDL インターフェース型値を idlObject に設定する。

      3. R を getter手順 を attribute のものとして idlObject を this にして実行した結果とする。

      4. 変換 の結果である R を attribute が宣言されている型の JavaScript値として返す。

    その後、例外 E がスローされた場合:

    1. もし attribute の型が promise type であれば、 ! Call(%Promise.reject%, %Promise%, «E») を返す。

    2. それ以外の場合、これらの手順を終了し、例外を伝播させる。

  2. name を "get " という文字列で attribute の 識別子 の前に付け加えた文字列とする。

  3. F を CreateBuiltinFunction(steps, 0, name, « », realm) とする。

  4. F を返す。

属性セッターは、以下のようにして生成されます。与えられるのは 属性 attribute、名前空間またはインターフェースtarget、realmrealmです:

  1. もし target が 名前空間 である場合:

    1. アサート:attribute は 読み取り専用 である。

    2. undefined を返す。

  2. もし attribute が 読み取り専用 であり、かつ [LegacyLenientSetter] [PutForwards] または [Replaceable] 拡張属性 を持たない場合、undefined を返す。属性セッター関数は存在しない。

  3. アサート:attribute の型は promise型 ではない。

  4. steps を次の一連の手順とする:

    1. V を undefined とする。

    2. 引数が渡されていた場合、最初の引数の値を V に設定する。

    3. id を attribute の 識別子 とする。

    4. idlObject を null とする。

    5. もし attribute が 通常属性 である場合:

      1. jsValue を this の値(nullまたはundefinedでなければ)、 そうでなければ realm の グローバルオブジェクト とする。 (この後のステップでグローバルオブジェクトが target を実装しておらず、 [LegacyLenientThis] が 指定されていない場合、TypeError になる。)

      2. もし jsValue が プラットフォームオブジェクトである ならば、 セキュリティチェックを実施し、 jsValue、id、"setter" を渡す。

      3. validThis を、jsValue が target を実装していれば true、そうでなければ false とする。

      4. もし validThis が false かつ attribute に [LegacyLenientThis] 拡張属性 が指定されていない場合は、 スローする TypeError。

      5. もし attribute が [Replaceable] 拡張属性で宣言されている場合:

        1. ? CreateDataPropertyOrThrow(jsValue, id, V) を実行する。

        2. undefined を返す。

      6. もし validThis が false であれば undefined を返す。

      7. もし attribute が [LegacyLenientSetter] 拡張属性で宣言されている場合 undefined を返す。

      8. もし attribute が [PutForwards] 拡張属性で宣言されている場合:

        1. Q を ? Get(jsValue, id) に設定する。

        2. もし Q が オブジェクトでなければ、スローする TypeError。

        3. forwardId を [PutForwards] 拡張属性の identifier 引数値とする。

        4. ? Set(Q, forwardId, V, false) を実行する。

        5. undefined を返す。

      9. idlObject を jsValue を参照するIDL インターフェース型値に設定する。

      10. もし attribute の型が observable array型 かつ型引数 T である場合:

        1. newValues を 変換の結果として V を sequence<T> 型のIDL値にする。

        2. oa を idlObject の attribute の backing observable array exotic objectとする。

        3. 長さを設定し、 oa.[[ProxyHandler]] を 0 にする。

        4. i を 0 とする。

        5. i < newValues の サイズ の間、繰り返す:

          1. oa.[[ProxyHandler]].[[SetAlgorithm]] の指示するアルゴリズム手順を newValues[i] および i を与えて実行する。

          2. 追加 で newValues[i] を oa.[[ProxyHandler]].[[BackingList]] に追加する。

        6. undefined を返す。

    6. idlValue を次のように決定する:

      attribute の型が 列挙型 の場合
      1. S を ? ToString(V) の結果とする。

      2. もし S が 列挙値のいずれでもない場合、 undefined を返す。

      3. それ以外の場合、idlValue を S と等しい列挙値とする。

      それ以外の場合
      idlValue は 変換 の結果である V を attribute の型のIDL値に変換したものとする。
    7. setter手順 を attribute のものとして idlObject を this にし、idlValue を 与えられた値 として実行する。

    8. undefined を返す。

  5. name を "set " という文字列に id を連結したものとする。

  6. F を CreateBuiltinFunction(steps, 1, name, « », realm) とする。

  7. F を返す。

注: IDL属性にはプロパティは一つしかありませんが、 アクセサプロパティのgetter/setterは、プロパティに対応するIDL属性がアクセスされるオブジェクトのthis値を渡されるため、インスタンス固有のデータを公開できます。

注: 読み取り専用の属性に対応するプロパティに代入しようとすると、 そのスクリプトがstrict modeかどうかで挙動が異なります。 strict modeの場合はTypeErrorがスローされ、 そうでない場合は代入は無視されます。

3.7.7. 操作

各 identifier が一意となる exposed な operation が interface 上に定義されている場合、 対応するプロパティが存在する。 Static operation は interface object 上に公開される。 Regular operation は interface prototype object 上に公開されるが、 operation が unforgeable である場合や interface が [Global] extended attribute で宣言されている場合には、 その interface を implements する各オブジェクト上に公開される。

define the regular operations interface または namespace definition の regular operations を target 上で定義するには、realm realm を与え、以下の手順を実行する:
  1. operations を、list のうち、 regular operation で members であるものとして definition から取得する。

  2. Remove を用いて、operations から operation のうち unforgeable なものを除去する。

  3. Define the operations operations を、definition および target に対し、realm を用いて定義する。

define the static operations interface または namespace definition の static operations を target 上で定義するには、realm realm を与え、以下の手順を実行する:
  1. operations を、list のうち、 static operation で members であるものとして definition から取得する。

  2. Define the operations operations を、definition および target に対し、realm を用いて定義する。

define the unforgeable regular operations interface または namespace definition の unforgeable regular operations を target 上で定義するには、realm realm を与え、以下の手順を実行する:
  1. operations を、list のうち、 unforgeable な regular operation で members であるものとして definition から取得する。

  2. Define the operations operations を、definition および target に対し、realm を用いて定義する。

define the operations operations を interface または namespace definition のものとして target 上に、 realm realm を与え、以下の手順を実行する:
  1. For each operation op を operations の要素として:

    1. もし op が realm にて exposed でなければ、continue する。

    2. method を create an operation function を op、definition、realm に対して実行した結果とする。

    3. もし op が unforgeable であれば modifiable を false、 それ以外なら true とする。

    4. desc を PropertyDescriptor{[[Value]]: method, [[Writable]]: modifiable, [[Enumerable]]: true, [[Configurable]]: modifiable} とする。

    5. id を op の identifier とする。

    6. ! DefinePropertyOrThrow(target, id, desc) を実行する。

create an operation function operation op、namespace または interface target、 realm realm を与え:
  1. id を op の 識別子 とする。

  2. steps を、関数引数値 args を与えた場合の次の一連の手順とする:

    1. 次の手順の実行を試みる:

      1. idlObject を null とする。

      2. もし target が インターフェース であり、かつ op が 静的操作でない場合:

        1. jsValue を this の値とし、それが null または undefined でない場合はそのまま、そうでなければ realm の グローバルオブジェクト とする。(グローバルオブジェクトが target を実装しない場合は、この後の手順で TypeError が発生する。)

        2. もし jsValue が プラットフォームオブジェクトである なら、 セキュリティチェックを実施し、 jsValue、id、"method" を渡す。

        3. もし jsValue が target インターフェースを実装していなければ、 スローする TypeError。

        4. idlObject を jsValue を参照するIDL インターフェース型値に設定する。

      3. n を サイズ args の要素数とする。

      4. 有効なオーバーロードセットを計算する。通常操作(op が通常操作の場合)または 静的操作(op が静的操作の場合)について、 識別子 id と target、引数数 n で実行し、結果を S とする。

      5. <operation, values> を、S と args を オーバーロード解決アルゴリズム に渡した結果とする。

      6. R を null とする。

      7. もし operation が [Default] 拡張属性 で宣言されている場合:

        1. アサート:operation は default method手順を持つ。

        2. R を default method手順を operation に対して idlObject を this として、values を引数値にして実行した結果に設定する。

      8. それ以外の場合、R を method手順 を operation のもので idlObject を this とし、values を引数値にして実行した結果に設定する。

      9. R を JavaScript値へ変換 したものとして返す。

        R は op が返すと宣言された型の IDL 値であることを仮定している。[whatwg/webidl Issue #674]

    その後、例外 E がスローされた場合:

    1. もし op の 戻り値型 が promise型 の場合は、 ! Call(%Promise.reject%, %Promise%, «E») を返す。

    2. それ以外の場合、これらの手順を終了し、例外を伝播させる。

  3. 有効なオーバーロードセットを計算する。通常操作(op が通常操作の場合)または 静的操作(op が静的操作の場合)について、 識別子 id と target および引数数 0 で実行し、結果を S とする。

  4. length を S に含まれるエントリの引数リスト最短長とする。

  5. F を CreateBuiltinFunction(steps, length, id, « », realm) とする。

  6. F を返す。

3.7.7.1. デフォルト操作

通常の操作 デフォルトメソッド手順を持つ とは、その 識別子 が下記の表の第一列に現れる場合を指す。 この場合、その デフォルトメソッド手順 は表の第二列に示されたアルゴリズムによって与えられ、操作は表の第三列で示された返却型を持たなければならない。

識別子 デフォルトメソッド手順 返却型
"toJSON" デフォルト toJSON 手順 object

通常の操作 が デフォルトメソッド手順を持たない 場合、[Default] 拡張属性 で宣言してはならない。

3.7.7.1.1. デフォルト toJSON 操作

デフォルト toJSON 手順は、インターフェース I に対して次の通り実行する:

  1. map を新しい 順序付きマップ とする。

  2. stack を 継承スタックを作成する で インターフェース I を渡して得る。

  3. 継承スタックの属性値を収集するを、 this, stack, map を渡して呼び出す。

  4. result を OrdinaryObjectCreate(%Object.prototype%) の結果とする。

  5. map の各 key → value について、

    1. k を key IDL から JavaScript への値変換の結果とする。

    2. v を value IDL から JavaScript への値変換の結果とする。

    3. ! CreateDataPropertyOrThrow(result, k, v) を実行する。

  6. result を返す。

継承スタックの属性値を収集するは プラットフォームオブジェクト object, スタック stack, 順序付きマップ map を与えて実行する:

  1. I を stack から pop する結果とする。

  2. 属性値を収集する を object, I, map で呼び出す。

  3. もし stack が 空でなければ、 継承スタックの属性値を収集するを object, stack, map で呼び出す。

属性値を収集するは プラットフォームオブジェクト object, インターフェース I, 順序付きマップ map を与えて実行する:

  1. もし toJSON 操作が [Default] 拡張属性で I 上に宣言されていれば、 各 公開された 通常属性 attr で インターフェースメンバーであるものについて順に:

    1. id を attr の 識別子とする。

    2. value を getter 手順を attr に対し object を this として実行した結果とする。

    3. もし value が JSON 型であれば、set map[id] = value とする。

継承スタックを作成するは インターフェース I に対して以下を実行する:

  1. stack を新しい スタックとする。

  2. stack に push するで I を stack に追加する。

  3. while I が 継承するインターフェースが存在する間、

    1. I をその インターフェースとする。

    2. stack に push するで I を stack に追加する。

  4. stack を返す。

[Default] 拡張属性付きの toJSON 操作を宣言した インターフェース のみ、その 通常属性が含まれる。継承したインターフェースで toJSON 操作が宣言されていても含まれない。例えば、次の IDL 断片を考える:

[Exposed=Window]
interface A {
  [Default] object toJSON();
  attribute DOMString a;
};

[Exposed=Window]
interface B : A {
  attribute DOMString b;
};

[Exposed=Window]
interface C : B {
  [Default] object toJSON();
  attribute DOMString c;
};

上記の C インターフェースを実装するオブジェクトで toJSON() メソッドを呼び出した場合、次の JSON オブジェクトが返る:

{
    "a": "...",
    "c": "..."
}

上記の A(または B)インターフェースを実装するオブジェクトで toJSON() メソッドを呼び出した場合は:

{
    "a": "..."
}

toJSON 操作は インターフェースミックスイン(または 部分インターフェース)にも宣言でき、元の インターフェースに宣言した場合と同じ意味となる。例として、次の IDL 断片を考える:

[Exposed=Window]
interface D {
  attribute DOMString d;
};

interface mixin M {
  [Default] object toJSON();
  attribute DOMString m;
};

D includes M;

上記の D インターフェースを実装するオブジェクトで toJSON() メソッドを呼び出した場合:

{
    "d": "...",
    "m": "..."
}

3.7.8. ストリンギファイア

もし インターフェース が 公開された stringifier を持つ場合、 以下の特性を持つプロパティが存在しなければならない:

3.7.9. イテラブル宣言

イテレーションメソッドを定義する インターフェース definition を target 上で、realm realm を与えて定義するには、以下の手順を実行する:
  1. もし definition が インデックス付きプロパティgetter を持つ場合:

    1. DefineMethodProperty(target, %Symbol.iterator%, %Array.prototype.values%, false) を実行する。

    2. もし definition が 値イテレーター を持つ場合:

      1. ! CreateDataPropertyOrThrow(target, "entries", %Array.prototype.entries%) を実行する。

      2. ! CreateDataPropertyOrThrow(target, "keys", %Array.prototype.keys%) を実行する。

      3. ! CreateDataPropertyOrThrow(target, "values", %Array.prototype.values%) を実行する。

      4. ! CreateDataPropertyOrThrow(target, "forEach", %Array.prototype.forEach%) を実行する。

  2. それ以外の場合、definition が ペアイテレーター を持つ場合:

    1. %Symbol.iterator% および entries メソッドを定義する:

      1. steps を次の一連の手順とする:

        1. jsValue を ? ToObject(this の値) とする。

        2. もし jsValue が プラットフォームオブジェクトである なら、セキュリティチェックを実行し、 jsValue, "%Symbol.iterator%", "method" を渡す。

        3. もし jsValue が definition を実装していない なら、 スローする TypeError。

        4. definition のデフォルトイテレーターオブジェクトを新しく作成して返す。 その target は jsValue とし、 kind は "key+value"、 index は 0 とする。

      2. F を CreateBuiltinFunction(steps, 0, "entries", « », realm) とする。

      3. DefineMethodProperty(target, %Symbol.iterator%, F, false) を実行する。

      4. ! CreateDataPropertyOrThrow(target, "entries", F) を実行する。

    2. keys メソッドを定義する:

      1. steps を次の一連の手順とする:

        1. jsValue を ? ToObject(this の値) とする。

        2. もし jsValue が プラットフォームオブジェクトである なら、セキュリティチェックを実行し、 jsValue, "keys", "method" を渡す。

        3. もし jsValue が definition を実装していない なら、 スローする TypeError。

        4. definition のデフォルトイテレーターオブジェクトを新しく作成して返す。 その target は jsValue とし、 kind は "key"、 index は 0 とする。

      2. F を CreateBuiltinFunction(steps, 0, "keys", « », realm) とする。

      3. ! CreateDataPropertyOrThrow(target, "keys", F) を実行する。

    3. values メソッドを定義する:

      1. steps を次の一連の手順とする:

        1. jsValue を ? ToObject(this の値) とする。

        2. もし jsValue が プラットフォームオブジェクトである なら、セキュリティチェックを実行し、 jsValue, "values", "method" を渡す。

        3. もし jsValue が definition を実装していない なら、 スローする TypeError。

        4. definition のデフォルトイテレーターオブジェクトを新しく作成して返す。 その target は jsValue とし、 kind は "value"、 index は 0 とする。

      2. F を CreateBuiltinFunction(steps, 0, "values", « », realm) とする。

      3. ! CreateDataPropertyOrThrow(target, "values", F) を実行する。

    4. forEach メソッドを定義する:

      1. 関数引数値 callback および thisArg を与えて、 steps を次の一連の手順とする:

        1. jsValue を ? ToObject(this の値) とする。

        2. もし jsValue が プラットフォームオブジェクトである なら、セキュリティチェックを実行し、 jsValue, "forEach", "method" を渡す。

        3. もし jsValue が definition を実装していない なら、 スローする TypeError。

        4. idlCallback を callback を IDL値に変換した Function とする。

        5. idlObject を jsValue を参照するIDL インターフェース型値に設定する。

        6. pairs を idlObject の反復する値のペアのリストとする。

        7. i を 0 とする。

        8. i < pairs の サイズの間、繰り返す:

          1. pair を pairs[i] とする。

          2. コールバック関数を呼び出す。 idlCallback に « pair の value, pair の key, idlObject » を渡し、thisArg を コールバックthis値とする。

          3. pairs を idlObject の現在の反復する値のペアのリストに更新する(変化している可能性がある)。

          4. i を i + 1 にする。

      2. F を CreateBuiltinFunction(steps, 1, "forEach", « », realm) とする。

      3. ! CreateDataPropertyOrThrow(target, "forEach", F) を実行する。

3.7.9.1. デフォルトイテレーターオブジェクト

ある インターフェース、target、イテレーションkindに対する デフォルトイテレーターオブジェクト は、 [[Prototype]] 内部スロット が その インターフェース用の イテレータープロトタイプオブジェクト となるオブジェクトである。

デフォルトイテレーターオブジェクト には、以下の3つの内部値がある:

注: デフォルトイテレーターオブジェクトは ペアイテレーター のみで使用される。 値イテレーターは、現状オブジェクトの サポートされるインデックス付きプロパティのみをイテレートするため、 標準のJavaScript Arrayイテレーターオブジェクトを利用する。

注: デフォルトイテレーターオブジェクト は class string を持たない。 インターフェースの デフォルトイテレーターオブジェクトに対して Object.prototype.toString()が呼び出された場合、そのインターフェースの イテレータープロトタイプオブジェクト の class string が使われる。

3.7.9.2. イテレータープロトタイプオブジェクト

イテレータープロトタイプオブジェクト とは、ある インターフェース に対して ペアイテレーター を持つ全てのインターフェースごとに存在するオブジェクトである。これは、そのインターフェース用の デフォルトイテレーターオブジェクト のプロトタイプとなる。

[[Prototype]] 内部スロット は イテレータープロトタイプオブジェクトについて、 %Iterator.prototype%でなければならない。

イテレーター結果 値ペア pair と kind kind に対し、以下の手順で与えられる:
  1. result を kind の値に応じて決定する:

    "key"
    1. idlKey を pair の key とする。

    2. key を IDL から JavaScript 値への変換 で idlKey を変換した結果とする。

    3. result は key である。

    "value"
    1. idlValue を pair の value とする。

    2. value を IDL から JavaScript 値への変換 で idlValue を変換した結果とする。

    3. result は value である。

    "key+value"
    1. idlKey を pair の key とする。

    2. idlValue を pair の value とする。

    3. key を IDL から JavaScript 値への変換 で idlKey を変換した結果とする。

    4. value を IDL から JavaScript 値への変換 で idlValue を変換した結果とする。

    5. array を ! ArrayCreate(2) の結果とする。

    6. ! CreateDataPropertyOrThrow(array, "0", key) を実行する。

    7. ! CreateDataPropertyOrThrow(array, "1", value) を実行する。

    8. result は array である。

  2. CreateIteratorResultObject(result, false) を返す。

イテレータープロトタイプオブジェクトは、属性 { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true } を持つ next データプロパティを持たなければならず、 その値は 組み込み関数オブジェクト CreateBuiltinFunction(nextSteps, 0, "next", « ») でなければならない。 ここで、nextSteps は次のアルゴリズムである:

  1. interface を、イテレータプロトタイプオブジェクトが存在する インターフェイスとする。

  2. thisValue を this の値とする。

  3. object を ? ToObject(thisValue) の結果とする。

  4. もし object が プラットフォームオブジェクト であれば、 セキュリティチェックを実施する(以下を渡す):

    • プラットフォームオブジェクト object

    • 識別子 "next"

    • 型 "method"

  5. もし object が interface の デフォルトイテレーターオブジェクトでなければ、 TypeError を投げる。

  6. index を object の index とする。

  7. kind を object の kind とする。

  8. values を object の target の イテレート対象の値ペアとする。

  9. len を values の長さとする。

  10. もし index が len 以上なら、 CreateIteratorResultObject(undefined, true) を返す。

  11. pair を values の index 番目のエントリとする。

  12. object の index を index + 1 に設定する。

  13. イテレーター結果 を pair と kind で返す。

ある インターフェース 用の イテレータープロトタイプオブジェクト の class string は、 その インターフェース の 識別子 と文字列 " Iterator" を連結したものである。

3.7.10. 非同期イテラブル宣言

非同期イテレーションメソッドを定義するには、インターフェース definition を target 上に、realm realm を与えて、以下の手順を実行する:
  1. もし definition が非同期イテラブル宣言(いずれかの種類)がない場合、返す。

  2. アサート:definition はインデックス付きプロパティ getterや イテラブル宣言を持たない。

  3. もし definition がペアの非同期イテラブル宣言を持つなら、 %Symbol.asyncIterator% および entries メソッドを定義する:

    1. 関数引数値 args を与えて、steps を次の一連の手順とする:

      1. jsValue を ? ToObject(this の値) とする。

      2. もし jsValue が プラットフォームオブジェクトであるなら、セキュリティチェック を jsValue, "%Symbol.asyncIterator%", "method" を渡し実施する。

      3. もし jsValue が definition を実装していなければ、スローする TypeError。

      4. idlObject を jsValue を参照するIDL インターフェース型値に設定する。

      5. idlArgs を 非同期イテレーターメソッド用の引数変換で args を与えての結果とする。

      6. iterator を definition 用の新しいデフォルト非同期イテレーターオブジェクトとし、 idlObject をtarget、 "key+value" を kind、is finished を false とする。

      7. もし存在するなら、definition 用の非同期イテレーター初期化手順を idlObject, iterator, idlArgs を与えて実行する。

      8. iterator を返す。

    2. F を CreateBuiltinFunction(steps, 0, "entries", « », realm) とする。

    3. DefineMethodProperty(target, %Symbol.asyncIterator%, F, false) を実行する。

    4. ! CreateDataPropertyOrThrow(target, "entries", F) を実行する。

  4. もし definition がペアの非同期イテラブル宣言を持つなら、 keys メソッドを定義する:

    1. 関数引数値 args を与えて steps を次の一連の手順とする:

      1. jsValue を ? ToObject(this の値) とする。

      2. もし jsValue が プラットフォームオブジェクトであるなら、セキュリティチェック を jsValue, "keys", "method" を渡し実施する。

      3. もし jsValue が definition を実装していなければ、スローする TypeError。

      4. idlObject を jsValue を参照するIDL インターフェース型値に設定する。

      5. idlArgs を 非同期イテレーターメソッド用の引数変換で args を与えての結果とする。

      6. iterator を definition 用の新しいデフォルト非同期イテレーターオブジェクトとし、 idlObject をtarget、 "key" を kind、is finished を false とする。

      7. もし存在するなら、definition 用の非同期イテレーター初期化手順を idlObject, iterator, idlArgs を与えて実行する。

      8. iterator を返す。

    2. F を CreateBuiltinFunction(steps, 0, "keys", « », realm) とする。

    3. ! CreateDataPropertyOrThrow(target, "keys", F) を実行する。

  5. values および必要であれば %Symbol.asyncIterator% メソッドを定義する:

    1. 関数引数値 args を与えて steps を次の一連の手順とする:

      1. jsValue を ? ToObject(this の値) とする。

      2. もし jsValue が プラットフォームオブジェクトであるなら、セキュリティチェック を jsValue, "values", "method" を渡し実施する。

      3. もし jsValue が definition を実装していなければ、スローする TypeError。

      4. idlObject を jsValue を参照するIDL インターフェース型値に設定する。

      5. idlArgs を 非同期イテレーターメソッド用の引数変換で args を与えての結果とする。

      6. iterator を definition 用の新しいデフォルト非同期イテレーターオブジェクトとし、 idlObject をtarget、 "value" を kind、is finished を false とする。

      7. もし存在するなら、definition 用の非同期イテレーター初期化手順を idlObject, iterator, idlArgs を与えて実行する。

      8. iterator を返す。

    2. F を CreateBuiltinFunction(steps, 0, "values", « », realm) とする。

    3. ! CreateDataPropertyOrThrow(target, "values", F) を実行する。

    4. もし definition が値の非同期イテラブル宣言を持つ場合、 ! DefineMethodProperty(target, %Symbol.asyncIterator%, F, false) を実行する。

非同期イテレーターメソッドの引数変換 は、インターフェース definition(非同期イテラブル宣言を持つ)と JavaScript値のリスト args を与えて:
  1. idlArgs を空のリストとする。

  2. argCount を definition の 非同期イテラブル宣言 の引数数(もしくはその非同期イテラブル宣言に引数リストがなければ0)とする。

  3. i を 0 とする。

  4. While i < argCount の間:

    1. もし i ≥ args の サイズ もしくは args[i] が undefined なら:

      1. もし 非同期イテラブル宣言 のその引数(インデックス i)が デフォルト値で宣言されていれば、 そのデフォルト値を idlArgs に追加する。

      2. それ以外の場合、idlArgs に特殊値 "missing" を追加する。

    2. それ以外の場合、idlArgs に追加する値は ECMAScript値からIDL型変換で args[i] を 非同期イテラブル宣言の引数リスト(インデックスi)の型に変換した値とする。

    3. i を i + 1 にする。

  5. idlArgs を返す。

これは、全ての引数がオプションでありオーバーロードが許可されない場合の オーバーロード解決アルゴリズム の特殊ケースである。

3.7.10.1. デフォルト非同期イテレーターオブジェクト

ある インターフェース、target、イテレーションkindに対する デフォルト非同期イテレーターオブジェクト は、 [[Prototype]] 内部スロット が その インターフェース用の 非同期イテレータープロトタイプオブジェクト となるオブジェクトである。

デフォルト非同期イテレーターオブジェクト には、以下の内部値がある:

注: デフォルト非同期イテレーターオブジェクト は class string を持たない。 インターフェースの デフォルト非同期イテレーターオブジェクトに対して Object.prototype.toString()が呼び出された場合、そのインターフェースの 非同期イテレータープロトタイプオブジェクト の class string が使われる。

3.7.10.2. 非同期イテレータープロトタイプオブジェクト

非同期イテレータープロトタイプオブジェクト とは、ある インターフェース に対して 非同期イテラブル宣言 を持つ全てのインターフェースごとに存在するオブジェクトである。 これは、そのインターフェース用の デフォルト非同期イテレーターオブジェクト のプロトタイプとなる。

[[Prototype]] 内部スロット は 非同期イテレータープロトタイプオブジェクトについて、 %AsyncIteratorPrototype%でなければならない。

非同期イテレータープロトタイプオブジェクト は、属性 { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true } を持つ next データ プロパティを持たなければならず、 その値は 組み込み関数オブジェクト CreateBuiltinFunction(nextSteps, 0, "next", « ») でなければならない。ここで、nextSteps は次のアルゴリズムである:

  1. interface を、非同期イテレータプロトタイプオブジェクトが存在する インターフェイスとする。

  2. thisValidationPromiseCapability を ! NewPromiseCapability(%Promise%) とする。

  3. thisValue を this の値とする。

  4. object を Completion(ToObject(thisValue)) とする。

  5. IfAbruptRejectPromise(object, thisValidationPromiseCapability) を実行する。

  6. もし object が プラットフォームオブジェクト であれば、セキュリティチェックを実施(以下を渡す):

    • プラットフォームオブジェクト object

    • 識別子 "next"

    • 型 "method"

    このとき例外 e が投げられた場合:

    1. ! Call(thisValidationPromiseCapability.[[Reject]], undefined, « e ») を実行する。

    2. thisValidationPromiseCapability.[[Promise]] を返す。

  7. もし object が interface の デフォルト非同期イテレーターオブジェクトでなければ:

    1. error を新しい TypeError とする。

    2. ! Call(thisValidationPromiseCapability.[[Reject]], undefined, « error ») を実行する。

    3. thisValidationPromiseCapability.[[Promise]] を返す。

  8. nextSteps を次の手順列とする:

    1. nextPromiseCapability を ! NewPromiseCapability(%Promise%) とする。

    2. もし object の is finished が true なら:

      1. result を CreateIteratorResultObject(undefined, true) とする。

      2. ! Call(nextPromiseCapability.[[Resolve]], undefined, « result ») を実行する。

      3. nextPromiseCapability.[[Promise]] を返す。

    3. kind を object の kind とする。

    4. nextPromise を 次のイテレーション結果を取得で object の target および object を与えた結果とする。

    5. fulfillSteps を次の手順列(nextを与える)とする:

      1. object の ongoing promise を null に設定する。

      2. もし next が イテレーション終了 なら:

        1. object の is finished を true に設定する。

        2. CreateIteratorResultObject(undefined, true) を返す。

      3. それ以外の場合、もし interface が ペア非同期イテラブル宣言 を持つ場合:

        1. Assert: next は 値ペア である。

        2. イテレーター結果 を next と kind で返す。

      4. それ以外の場合:

        1. Assert: interface は 値非同期イテラブル宣言 を持つ。

        2. Assert: next は宣言で示された型の値である。

        3. value を next を IDL から JavaScript値変換した結果とする。

        4. CreateIteratorResultObject(value, false) を返す。

    6. onFulfilled を CreateBuiltinFunction(fulfillSteps, 1, "", « ») の結果とする。

    7. rejectSteps を次の手順列(reasonを与える)とする:

      1. object の ongoing promise を null に設定する。

      2. object の is finished を true に設定する。

      3. 例外を投げる reason を投げる。

    8. onRejected を CreateBuiltinFunction(rejectSteps, 1, "", « ») の結果とする。

    9. PerformPromiseThen(nextPromise, onFulfilled, onRejected, nextPromiseCapability) を実行する。

    10. nextPromiseCapability.[[Promise]] を返す。

  9. ongoingPromise を object の ongoing promiseとする。

  10. もし ongoingPromise が null でなければ:

    1. afterOngoingPromiseCapability を ! NewPromiseCapability(%Promise%) とする。

    2. onSettled を CreateBuiltinFunction(nextSteps, 0, "", « ») の結果とする。

    3. PerformPromiseThen(ongoingPromise, onSettled, onSettled, afterOngoingPromiseCapability) を実行する。

    4. object の ongoing promise を afterOngoingPromiseCapability.[[Promise]] に設定する。

  11. それ以外の場合:

    1. object の ongoing promise を nextSteps の実行結果に設定する。

  12. object の ongoing promise を返す。

非同期イテレーター return アルゴリズムが その インターフェイスに対して定義されている場合、 非同期イテレータープロトタイプオブジェクト は、属性 { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true } を持つ return データ プロパティを持たなければならず、 その値は 組み込み関数オブジェクト CreateBuiltinFunction(returnSteps, 1, "return", « ») でなければならない。ここで、returnSteps は 1 つの引数 value を取る次のアルゴリズムである:

  1. interface を、非同期イテレータプロトタイプオブジェクトが存在する インターフェイスとする。

  2. returnPromiseCapability を NewPromiseCapability(%Promise%) の ! により得る。

  3. thisValue を this の値とする。

  4. object を ToObject(thisValue) の Completion により得る。

  5. IfAbruptRejectPromise(object, returnPromiseCapability) を行う。

  6. もし object が プラットフォームオブジェクトであれば、 以下を引数として セキュリティチェックを実行する:

    • プラットフォームオブジェクト object

    • 識別子 "return"

    • 型 "method"

    これにより例外 e が投げられた場合:

    1. Call(returnPromiseCapability.[[Reject]], undefined, « e ») を ! で実行する。

    2. returnPromiseCapability.[[Promise]] を返す。

  7. もし object が interface 用の default asynchronous iterator object でなければ、次を行う:

    1. error を新しい TypeError とする。

    2. Call(returnPromiseCapability.[[Reject]], undefined, « error ») を ! で実行する。

    3. returnPromiseCapability.[[Promise]] を返す。

  8. returnSteps を以下の手順とする:

    1. returnPromiseCapability を NewPromiseCapability(%Promise%) の ! により得る。

    2. もし object の is finished が true なら、次を行う:

      1. result を CreateIteratorResultObject(value, true) により得る。

      2. Call(returnPromiseCapability.[[Resolve]], undefined, « result ») を ! で実行する。

      3. returnPromiseCapability.[[Promise]] を返す。

    3. object の is finished を true に設定する。

    4. interface 用の 非同期イテレータ return アルゴリズム を、 object の target、object、 そして value を与えて実行した結果を返す。

  9. ongoingPromise を object の ongoing promise とする。

  10. もし ongoingPromise が null でなければ、次を行う:

    1. afterOngoingPromiseCapability を NewPromiseCapability(%Promise%) の ! により得る。

    2. onSettled を CreateBuiltinFunction(returnSteps, 0, "", « ») により得る。

    3. PerformPromiseThen(ongoingPromise, onSettled, onSettled, afterOngoingPromiseCapability) を実行する。

    4. object の ongoing promise を afterOngoingPromiseCapability.[[Promise]] に設定する。

  11. それ以外の場合:

    1. object の ongoing promise を returnSteps の実行結果に設定する。

  12. fulfillSteps を以下の手順とする:

    1. CreateIteratorResultObject(value, true) を返す。

  13. onFulfilled を CreateBuiltinFunction(fulfillSteps, 0, "", « ») により得る。

  14. PerformPromiseThen(object の ongoing promise, onFulfilled, undefined, returnPromiseCapability) を実行する。

  15. returnPromiseCapability.[[Promise]] を返す。

ある インターフェース 用の 非同期イテレータープロトタイプオブジェクト の class string は、 その インターフェース の 識別子 と文字列 " AsyncIterator" を連結したものである。

3.7.11. マップライク宣言

ある インターフェース A が maplike宣言 で宣言されている場合、 A の インターフェースプロトタイプオブジェクト にいくつかの追加プロパティが存在する。 これらの追加プロパティについては、以下のサブセクションで説明する。

3.7.11.1. size

A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ size プロパティが存在しなければならない:

3.7.11.2. %Symbol.iterator%

A のインターフェイスプロトタイプオブジェクト上には、 名前が %Symbol.iterator% シンボルであるデータプロパティが存在しなければならない。 その属性は { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } であり、その値は entries プロパティの値である関数オブジェクトである。

マップイテレーターの生成 map map と kind("key+value"、"key"、"value"のいずれか)を与えて:
  1. closure を、 map と kind をキャプチャして、呼び出された際に以下の手順を実行する パラメータ無しの Abstract Closureとして新規作成する:

    1. map の全て key → value について:

      1. key、value をそれぞれ JavaScript値へ変換する。

      2. もし kind が "key" なら、result を key とする。

      3. それ以外で kind が "value" なら、result を value とする。

      4. それ以外の場合、result を CreateArrayFromList(« key, value ») とする。

      5. ? GeneratorYield(CreateIteratorResultObject(result, false)) を実行する。

      注: map の サイズやエントリの順序は、 Yield によりこの抽象操作の実行が一時停止された間に変更されている可能性がある。

    2. undefined を返す。

  2. CreateIteratorFromClosure(closure, "%MapIteratorPrototype%", %MapIteratorPrototype%) を返す。

3.7.11.3. entries

A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ entries データプロパティが存在しなければならない:

3.7.11.4. keys

A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ keys データプロパティが存在しなければならない:

3.7.11.5. values

A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ values データプロパティが存在しなければならない:

3.7.11.6. forEach

A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ forEach データプロパティが存在しなければならない:

3.7.11.7. get

A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ get データプロパティが存在しなければならない:

3.7.11.8. has

A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ has データプロパティが存在しなければならない:

3.7.11.9. set

もし A が識別子 "set" を持つ member を宣言していない場合で、 A がread–writeのmaplike宣言で宣言されている場合は、 A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ set データプロパティが存在しなければならない:

インターフェイスが set メソッドを宣言している場合、 同様に -0 キーを +0 に写像するべきであり、 this を返さなければならない。

3.7.11.10. delete

もし A が識別子 "delete" を持つ member を宣言していない場合で、 A がread–writeのmaplike宣言で宣言されている場合は、 A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ delete データプロパティが存在しなければならない:

インターフェイスが delete メソッドを宣言している場合、 同様に -0 キーを +0 に写像するべきであり、 キーが存在していたかどうかを示す boolean を返さなければならない。

3.7.11.11. clear

もし A が識別子 "clear" を持つ member を宣言していない場合で、 A がread–writeのmaplike宣言で宣言されている場合は、 A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ clear データプロパティが存在しなければならない:

インターフェイスが clear メソッドを宣言している場合、 マップ エントリーオブジェクトを(新しいものを生成するのではなく)保持しなければならず、 undefined を返さなければならない。

3.7.12. setlike宣言

ある インターフェース A が setlike宣言 で宣言されている場合、 A の インターフェースプロトタイプオブジェクト にいくつかの追加プロパティが存在する。 これらの追加プロパティについては、以下のサブセクションで説明する。

3.7.12.1. size

A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ size プロパティが存在しなければならない:

3.7.12.2. %Symbol.iterator%

A のインターフェイスプロトタイプオブジェクト上には、 名前が %Symbol.iterator% シンボルであるデータプロパティが存在しなければならない。 その属性は { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } であり、その値は values プロパティの値である関数オブジェクトである。

セットイテレーターの生成 set set と kind("key+value"、"value"のいずれか)を与えて:
  1. closure を、 set と kind をキャプチャして、呼び出された際に以下の手順を実行する パラメータ無しの Abstract Closureとして新規作成する:

    1. set の全て entry について:

      1. entry を JavaScript値へ変換する。

      2. もし kind が "value" なら、result を entry とする。

      3. それ以外の場合、result を CreateArrayFromList(« entry, entry ») とする。

      4. ? GeneratorYield(CreateIteratorResultObject(result, false)) を実行する。

      注: set の サイズやエントリの順序は、 Yield によりこの抽象操作の実行が一時停止された間に変更されている可能性がある。

    2. undefined を返す。

  2. CreateIteratorFromClosure(closure, "%SetIteratorPrototype%", %SetIteratorPrototype%) を返す。

3.7.12.3. entries

A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ entries データプロパティが存在しなければならない:

3.7.12.4. keys

keys データプロパティが A のインターフェイスプロトタイプオブジェクト上に存在しなければならない。 その属性は { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true } であり、その値は values プロパティの値である関数オブジェクトである。

3.7.12.5. values

A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ values データプロパティが存在しなければならない:

3.7.12.6. forEach

A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ forEach データプロパティが存在しなければならない:

3.7.12.7. has

A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ has データプロパティが存在しなければならない:

3.7.12.8. add

もし A が識別子 "add" を持つ member を宣言していない場合で、 A がread–writeのsetlike宣言で宣言されている場合は、 A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ add データプロパティが存在しなければならない:

インターフェイスが add メソッドを宣言している場合、 同様に -0 値を +0 に写像するべきであり、 設定された値を返さなければならない。

3.7.12.9. delete

もし A が識別子 "delete" を持つ member を宣言していない場合で、 A がread–writeのsetlike宣言で宣言されている場合は、 A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ delete データプロパティが存在しなければならない:

インターフェイスが delete メソッドを宣言している場合、 同様に -0 値を +0 に写像するべきであり、 値が存在していたかどうかを示す boolean を返さなければならない。

3.7.12.10. clear

もし A が識別子 "clear" を持つ member を宣言していない場合で、 A がread–writeのsetlike宣言で宣言されている場合は、 A の インターフェースプロトタイプオブジェクト 上に 以下の特徴を持つ clear データプロパティが存在しなければならない:

インターフェイスが clear メソッドを宣言している場合、 セット エントリーオブジェクトを(新しいものを生成するのではなく)保持しなければならず、 undefined を返さなければならない。

3.8. インターフェースを実装するプラットフォームオブジェクト

JavaScript値 value が プラットフォームオブジェクトであるのは、value が Objectである かつ value が [[PrimaryInterface]] 内部スロットを持つ場合である。
JavaScript値 value が implements するインターフェース interface interface とは、 value が プラットフォームオブジェクトである かつ value.[[PrimaryInterface]] の 包括的な継承インターフェース が interface を 含む場合である。

仕様書では、「object implements interface」という概念を、「object が interfaceオブジェクトである」など様々な形で参照されることがある。

全ての プラットフォームオブジェクトは、 realm と関連付けられている。これは 初期オブジェクトと同様である。 このrealmは プラットフォームオブジェクトの [[Realm]] スロットに格納される。 Web IDLを利用する仕様は、各プラットフォームオブジェクトがどのrealm(または間接的にどのグローバルオブジェクト)と関連付けられるのかを明示する責任がある。 特に、以下のアルゴリズムは新しい プラットフォームオブジェクト を引数で与えられたrealmと関連付ける。

インターフェースを実装する新しいオブジェクトの作成では interface と realm realm を与え、以下の手順を実行する:
  1. インターフェースを内部的に実装する新しいオブジェクトを作成し、 interface、realm、undefined を与えた結果を返す。

インターフェースを内部的に実装する新しいオブジェクトを作成では interface、realm realm、JavaScript値 newTarget を与え、以下の手順を実行する:
  1. Assert: interface は realm で 公開されている。

  2. もし newTarget が undefined なら:

    1. prototype を realm の interface 用 インターフェースプロトタイプオブジェクトとする。

  3. それ以外の場合:

    1. Assert: IsCallable(newTarget) は true。

    2. prototype を ? Get(newTarget, "prototype") とする。

    3. もし prototype が Objectでない場合:

      1. targetRealm を ? GetFunctionRealm(newTarget) とする。

      2. prototype を targetRealm の interface 用 インターフェースプロトタイプオブジェクトに設定する。

  4. slots を « [[Prototype]], [[Extensible]], [[Realm]], [[PrimaryInterface]] » とする。

  5. もし interface が DOMException なら、 [[ErrorData]] を slots に追加する。

  6. instance を MakeBasicObject(slots) とする。

  7. instance.[[Realm]] を realm に設定する。

  8. instance.[[PrimaryInterface]] を interface に設定する。

  9. instance.[[Prototype]] を prototype に設定する。

  10. interfaces を interface の 包括的な継承インターフェースとする。

  11. 全ての インターフェース ancestor interface in interfaces について:

    1. unforgeables を realm の ancestor interface の インターフェースオブジェクトの [[Unforgeables]] スロット値とする。

    2. keys を ! unforgeables.[[OwnPropertyKeys]]() の結果とする。

    3. 各 key in keys について:

      1. descriptor を ! unforgeables.[[GetOwnProperty]](key) の結果とする。

      2. ! DefinePropertyOrThrow(instance, key, descriptor) を実行する。

  12. もし interface が [Global] 拡張属性で宣言されている場合:

    1. 通常の操作を定義するを interface、instance、realm で実行する。

    2. 通常の属性を定義するを interface、instance、realm で実行する。

    3. イテレーションメソッドを定義するを interface、instance、realm で実行する。

    4. 非同期イテレーションメソッドを定義するを interface、instance、realm で実行する。

    5. グローバルプロパティ参照を定義するを instance、realm で実行する。

    6. instance.[[SetPrototypeOf]] を § 3.8.1 [[SetPrototypeOf]] の定義に従って設定する。

  13. それ以外で、interfaces が インターフェースで インデックス付きプロパティや 名前付きプロパティをサポートするものを含む場合:

    1. instance.[[GetOwnProperty]] を § 3.9.1 [[GetOwnProperty]] の定義に従って設定する。

    2. instance.[[Set]] を § 3.9.2 [[Set]] の定義に従って設定する。

    3. instance.[[DefineOwnProperty]] を § 3.9.3 [[DefineOwnProperty]] の定義に従って設定する。

    4. instance.[[Delete]] を § 3.9.4 [[Delete]] の定義に従って設定する。

    5. instance.[[PreventExtensions]] を § 3.9.5 [[PreventExtensions]] の定義に従って設定する。

    6. instance.[[OwnPropertyKeys]] を § 3.9.6 [[OwnPropertyKeys]] の定義に従って設定する。

  14. instance を返す。

グローバルプロパティ参照を定義するには target、realm realm を与え、以下の手順を実行する:
  1. interfaces を リストとし、realm で 公開されている全ての インターフェース を含める。

  2. もし A と B が interfaces の 要素であり、 A が B を 継承していたら、 A のインデックスは B よりも高くなるよう interfaces をソートする。

  3. 全ての interfaces の interface について:

    1. interface が [LegacyNoInterfaceObject] または [LegacyNamespace] 拡張属性で宣言されていなければ:

      1. id を interface の 識別子とする。

      2. interfaceObject を インターフェースオブジェクトの作成し、interface、id、realmを与えた結果とする。

      3. DefineMethodProperty(target, id, interfaceObject, false) を実行する。

      4. もし interface が [LegacyWindowAlias] 拡張属性 で宣言されていて、 target が Window インターフェースを実装している場合:

        1. [LegacyWindowAlias]の識別子群に含まれる全ての識別子idについて:

          1. DefineMethodProperty(target, id, interfaceObject, false) を実行する。

    2. もし interface が [LegacyFactoryFunction] 拡張属性で宣言されている場合:

      1. [LegacyFactoryFunction]の識別子群に含まれる全ての識別子idについて:

        1. legacyFactoryFunction を レガシーファクトリ関数の作成で id、interface、realm を与えた結果とする。

        2. DefineMethodProperty(target, id, legacyFactoryFunction, false) を実行する。

  4. 全ての コールバックインターフェース interface で realm で 公開され、かつ 定数が定義されているものについて:

    1. id を interface の 識別子とする。

    2. interfaceObject を レガシーコールバックインターフェースオブジェクトの作成で interface、id、realm を与えた結果とする。

    3. DefineMethodProperty(target, id, interfaceObject, false) を実行する。

  5. 全ての 名前空間 namespace で realm で 公開されているものについて:

    1. id を namespace の 識別子とする。

    2. namespaceObject を 名前空間オブジェクトの作成で namespace、realm を与えた結果とする。

    3. DefineMethodProperty(target, id, namespaceObject, false) を実行する。

プラットフォームオブジェクトが implements するインターフェースの集合は、そのオブジェクトのライフタイム中には変更されない。

異なる プラットフォームオブジェクト が 異なる グローバルオブジェクト を持っていても、 [[PrimaryInterface]] 内部スロットには同じ インターフェースへの参照を共有する。例えば、同一オリジンのiframeを含むページで、iframeのメソッドが メインページの同種の要素で呼ばれても例外は投げられない。

インターフェースミクスインはimplementsアルゴリズムの評価に直接関与しない。代わりに、インターフェースミクスインをincludeする各インターフェースは、そのインターフェースミクスインの各memberの「コピー」を持つ。対応するoperation functionは、レシーバがそのインターフェースミクスインをincludeする特定のインターフェースを実装していることをチェックする。

プライマリインターフェースとは、 プラットフォームオブジェクトの [[PrimaryInterface]] 内部スロットの値であり、 そのオブジェクトが implements する最も派生した インターフェースである。

ある realm に関連付けられた プラットフォームオブジェクトは、作成後に グローバル環境を変更できる。 プラットフォームオブジェクトに関連付けられている realm が変更された場合、 その [[Prototype]] 内部スロットは 直ちに新しい関連realmの プライマリインターフェースの インターフェースプロトタイプオブジェクトに更新されなければならない。

また、[Global] 拡張属性を持つ インターフェースを実装する プラットフォームオブジェクトは、 以下から宣言的にプロパティを取得する:

これらのプロパティは命令的に定義すること。

3.8.1. [[SetPrototypeOf]]

インターフェースが [Global] 拡張属性を持つ プラットフォームオブジェクト O の [[SetPrototypeOf]] 内部メソッドが JavaScript言語値 V で呼び出された場合、以下の手順を実行する:

  1. もし O の 関連realm の グローバルプロトタイプチェーンがmutableか が true なら、 ? OrdinarySetPrototypeOf(O, V) を返す。

  2. ? SetImmutablePrototype(O, V) を返す。

注: Window オブジェクトについては、WindowProxy オブジェクトの存在により、[[SetPrototypeOf]] が Window オブジェクトに直接呼び出されることはないため、実装の有無は観測できない。他のグローバルオブジェクトではこの挙動が必要となる。

3.9. レガシープラットフォームオブジェクト

レガシープラットフォームオブジェクトは、 インデックス付きや 名前付きの プロパティに対応する追加プロパティを持つように見える。 これらのプロパティはオブジェクト上の「実際の」ownプロパティではなく、[[GetOwnProperty]] 内部メソッド によって 露出されているため、そう見えるだけである。

1つのオブジェクトがインデックス付きプロパティをサポートする複数のインターフェースを実装することは許容されている。 ただし、その場合、オブジェクトの サポートされるプロパティインデックス に関して定義が競合している場合は、 そのオブジェクトが持つ追加プロパティや、インデックス付きプロパティの正確な挙動は未定義となる。名前付きプロパティについても同様である。

インデックス付きプロパティgetterは、 レガシープラットフォームオブジェクトが実装する最も派生したインターフェース上で定義されたものが、 配列インデックスによるオブジェクトのインデックス参照時の挙動を定義する。同様に インデックス付きプロパティsetterも 最も派生したインターフェース上の定義が利用される。 このようにして、祖先インターフェースの特殊操作定義はオーバーライド可能になる。

プロパティ名が、あるプラットフォームオブジェクト O において unforgeable property name(偽造不可プロパティ名) であるとは、 O が インターフェースを実装していて、 そのインターフェースがその識別子の interface member を持ち、 そのinterface memberが O のいずれかの実装インターフェース上で unforgeable である場合を指す。

getter への対応は § 3.9.1 [[GetOwnProperty]]で、 setter への対応は § 3.9.3 [[DefineOwnProperty]] および § 3.9.2 [[Set]]で扱われる。

さらに、レガシープラットフォームオブジェクトは以下の内部メソッドを持つ:

3.9.1. [[GetOwnProperty]]

全ての レガシープラットフォームオブジェクト O の [[GetOwnProperty]] 内部メソッドは、 プロパティ名 P で呼び出された場合、以下のように動作しなければならない:

  1. ? LegacyPlatformObjectGetOwnProperty(O, P, false) を返す。

3.9.2. [[Set]]

全ての レガシープラットフォームオブジェクト O の [[Set]] 内部メソッドは、 プロパティ名 P、値 V、JavaScript言語値 Receiver で呼び出された場合、以下のように動作しなければならない:

  1. もし O と Receiver が同一オブジェクトなら:

    1. もし O が インターフェースを実装していて、インデックス付きプロパティsetterを持ち、 P が 配列インデックスなら:

      1. インデックス付きプロパティsetterを呼び出す(O, P, V)。

      2. true を返す。

    2. もし O が インターフェースを実装していて、名前付きプロパティsetterを持ち、 P が String型なら:

      1. 名前付きプロパティsetterを呼び出す(O, P, V)。

      2. true を返す。

  2. ownDesc を ? LegacyPlatformObjectGetOwnProperty(O, P, true) とする。

  3. ? OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc) を実行する。

3.9.3. [[DefineOwnProperty]]

全ての レガシープラットフォームオブジェクト O の [[DefineOwnProperty]] 内部メソッドがプロパティキー P と プロパティディスクリプタ Desc で呼び出された場合、以下の手順を実行する:

  1. もし O が インデックス付きプロパティをサポートしていて、 P が 配列インデックスなら:

    1. IsDataDescriptor(Desc) の結果が falseなら、false を返す。

    2. もし O が インデックス付きプロパティsetterを持つインターフェースを実装していなければ false を返す。

    3. インデックス付きプロパティsetterを呼び出す(O, P, Desc.[[Value]])。

    4. true を返す。

  2. O が 名前付きプロパティをサポートし、 O が [Global] を持つ インターフェイスを実装せず、 拡張属性であり、 P が String であり、 かつ P が O の 偽造不能プロパティ名 でない場合、次を行う。

    1. P が サポートされるプロパティ名でない場合は creating を true とし、そうで なければ false とする。

    2. O が [LegacyOverrideBuiltIns] を持つインターフェイスを 実装する場合、または O が 拡張属性を持つか、O が P という名前の own プロパティを持たない場合、次を行う。

      1. creating が false で、O が 名前付きプロパティ setterを持つインターフェイスを実装しない場合、 false を返す。

      2. O が 名前付きプロパティ setterを持つインターフェイスを 実装する場合、次を行う。

        1. IsDataDescriptor(Desc) を呼び出した結果が false で ある場合、 false を返す。

        2. O 上で、P と Desc.[[Value]] を用いて 名前付きプロパティ setter を呼び出す。

        3. true を返す。

  3. ! OrdinaryDefineOwnProperty(O, P, Desc) を返す。

3.9.4. [[Delete]]

すべての レガシープラットフォームオブジェクト O の [[Delete]] 内部メソッドは、 プロパティ名 P で呼び出された場合、次のように動作しなければならない。

  1. O が インデックス付きプロパティをサポートし、 P が 配列インデックスである場合、次を行う。

    1. index を ! ToUint32(P) を呼び出した結果とする。

    2. index が サポートされるプロパティインデックスでない場合、 true を返す。

    3. false を返す。

  2. O が 名前付きプロパティをサポートし、 O が [Global] を持つ インターフェイスを実装せず、 拡張属性であり、 プロパティ名 P とオブジェクト O を用いて 名前付きプロパティ可視性アルゴリズムを呼び出した結果が true である場合、次を行う。

    1. O が 名前付き プロパティ deleterを持つインターフェイスを実装しない場合、false を返す。

    2. operation を、名前付きプロパティ deleter の宣言に使用された操作とする。

    3. operation が 識別子なしで定義されていた場合、次を行う。

      1. インターフェイスの説明に列挙された手順を実行して、 既存の名前付き プロパティを削除する。 P を名前として用いる。

      2. その手順が削除に失敗したことを示した場合、 false を返す。

    4. そうでなければ、operation は識別子付きで定義されていた。

      1. operation の メソッド手順を実行し、 O を this とし、« P » を 引数値とする。

      2. operation が 戻り値の型として boolean を持つよう宣言され、手順が false を返した場合、 false を返す。

    5. true を返す。

  3. O が名前 P の own プロパティを持つ場合、次を行う。

    1. そのプロパティが構成可能でない場合、false を返す。

    2. そうでなければ、そのプロパティを O から削除する。

  4. true を返す。

3.9.5. [[PreventExtensions]]

レガシープラットフォームオブジェクトの [[PreventExtensions]] 内部メソッドが呼び出された場合、以下の手順を実行する:

  1. false を返す。

注: これは レガシープラットフォームオブジェクト を 拡張可能(extensible)なままにし、[[PreventExtensions]] が失敗することを保証する。

3.9.6. [[OwnPropertyKeys]]

この文書では、インターフェースを実装するプラットフォームオブジェクト (または 例外を表すプラットフォームオブジェクト)の 完全なプロパティ列挙順を定義していない。 ただし、レガシープラットフォームオブジェクトについては [[OwnPropertyKeys]] 内部メソッドを以下の通り定義する。

レガシープラットフォームオブジェクト O の [[OwnPropertyKeys]] 内部メソッドが呼び出された場合、以下の手順を実行する:

  1. keys を JavaScriptのString値およびSymbol値の空リストとして新規作成する。

  2. もし O が インデックス付きプロパティをサポートしている場合は、 各 O の サポートされるプロパティインデックス index について、 昇順で append し、 ! ToString(index) を keys に追加する。

  3. もし O が 名前付きプロパティをサポートしている場合は、 各 O の サポートされるプロパティ名 P について、 named property visibility algorithm で 可視なら append し、P を keys に追加する。

  4. 各 O の ownプロパティキー(String型) P について、プロパティ作成の昇順で append し、P を keys に追加する。

  5. 各 O の ownプロパティキー(Symbol型) P について、プロパティ作成の昇順で append し、P を keys に追加する。

  6. Assert: keys に重複はない。

  7. keys を返す。

3.9.7. 抽象操作

プロパティ名 P が 配列インデックスか判定するには、次のアルゴリズムを適用する:

  1. もし P が String型でなければ、false を返す。

  2. index を CanonicalNumericIndexString(P) の結果とする。

  3. もし index が undefined なら false を返す。

  4. もし IsInteger(index) が false なら false を返す。

  5. もし index が −0 なら false を返す。

  6. もし index < 0 なら false を返す。

  7. もし index ≥ 232 − 1 なら false を返す。

    注: 232 − 1 は JavaScript の最大配列長である。

  8. true を返す。

名前付き プロパティ可視性アルゴリズム は、指定された名前付きプロパティがオブジェクト上で公開されるかどうかを判定するために使用される。 一部の名前付きプロパティは、 [LegacyOverrideBuiltIns] 拡張 属性が使用されたかどうかに応じて、オブジェクト上で公開されない。 このアルゴリズムは、プロパティ名 P とオブジェクト O を用いて次のように動作する。

  1. P が O の サポートされるプロパティ名でない場合、 false を返す。

  2. O が P という名前の own プロパティを持つ場合、false を返す。

    注: これには、 O が偽造不能プロパティを持つ場合も含まれる。 実際には、それらは常にオブジェクトがサポートされるプロパティ名を持つ前に設定され、 一度設定されると、対応する名前付きプロパティは不可視になるためである。

  3. O が [LegacyOverrideBuiltIns] 拡張属性を持つインターフェイスを 実装する場合、true を返す。

  4. prototype を O.[[GetPrototypeOf]]() とする。

  5. prototype が null でない間、次を行う。

    1. prototype が 名前付き プロパティオブジェクトでなく、 かつ prototype が P という名前の own プロパティを持つ場合、false を返す。

    2. prototype を prototype.[[GetPrototypeOf]]() に設定する。

  6. true を返す。

これにより、名前付きプロパティを持つオブジェクトに対してプロパティ解決が以下の順序で行われることが保証される:

  1. インデックス付きプロパティ。

  2. ownプロパティ(偽造不可属性や操作も含む)。

  3. [LegacyOverrideBuiltIns] の場合:

    1. 名前付きプロパティ。

    2. プロトタイプチェーンからのプロパティ。

  4. それ以外([LegacyOverrideBuiltIns] でない場合):

    1. プロトタイプチェーンからのプロパティ。

    2. 名前付きプロパティ。

インデックス付きプロパティsetterを呼び出す には、プラットフォームオブジェクト O、プロパティ名 P、JavaScript値 V を与え、以下の手順を実施する:

  1. index を ? ToUint32(P) の結果とする。

  2. creating を index が サポートされるプロパティインデックスでなければ true、そうであれば false とする。

  3. operation をインデックス付きプロパティsetterを宣言した際に使用したoperationとする。

  4. T を operation の第2引数の型とする。

  5. value を、V を型 T の IDL 値に変換した結果とする。

  6. もし operation が識別子無しで定義されていれば:

    1. もし creating が true なら、インターフェース記述の指示に従い 新しいインデックス付きプロパティの値を設定する手順を、 indexをインデックス、valueを値として実行する。

    2. それ以外の場合(creating が false)、インターフェース記述の指示に従い 既存のインデックス付きプロパティの値を設定する手順を、 indexをインデックス、valueを値として実行する。

  7. それ以外の場合、operation が識別子付きで定義されていれば、 メソッド手順(operation)を O を this、« index, value » を引数値として実行する。

名前付きプロパティsetterを呼び出す には、プラットフォームオブジェクト O、プロパティ名 P、JavaScript値 V を与え、以下の手順を実施する:

  1. creating を P が サポートされるプロパティ名でなければ true、そうであれば false とする。

  2. operation を名前付きプロパティsetterを宣言した際に使用したoperationとする。

  3. T を operation の第2引数の型とする。

  4. value を、V を型 T の IDL 値に変換した結果とする。

  5. もし operation が識別子無しで定義されていれば:

    1. もし creating が true なら、インターフェース記述の指示に従い 新しい名前付きプロパティの値を設定する手順を、 Pを名前、valueを値として実行する。

    2. それ以外の場合(creating が false)、インターフェース記述の指示に従い 既存の名前付きプロパティの値を設定する手順を、 Pを名前、valueを値として実行する。

  6. それ以外の場合、operation が識別子付きで定義されていれば、 メソッド手順(operation)を O を this、« P, value » を引数値として実行する。

LegacyPlatformObjectGetOwnProperty 抽象操作は、 オブジェクト O、プロパティ名 P、boolean値 ignoreNamedProps を受けて次の手順を実行する:

  1. もし O が インデックス付きプロパティをサポートしていて、 P が 配列インデックスなら:

    1. index を ! ToUint32(P) の結果とする。

    2. もし index が サポートされるプロパティインデックスなら:

      1. operation をインデックス付きプロパティgetterを宣言した際に使用したoperationとする。

      2. value を未初期化変数とする。

      3. もし operation が識別子無しで定義されていれば、 value をインターフェース記述の指示に従い インデックス付きプロパティの値を取得する手順を indexをインデックスとして実行した結果に設定する。

      4. それ以外の場合、operation が識別子付きで定義されていれば value を メソッド手順(operation)を O を this、« index » を引数値として実行した結果に設定する。

      5. desc をフィールド無しの新規 プロパティディスクリプタとして生成する。

      6. desc.[[Value]] を valueをJavaScript値へ変換した結果に設定する。

      7. もし O が インデックス付きプロパティsetterを持つインターフェースを実装していれば desc.[[Writable]] を true に、そうでなければ false に設定する。

      8. desc.[[Enumerable]] および desc.[[Configurable]] を true に設定する。

      9. desc を返す。

    3. ignoreNamedProps を true に設定する。

  2. もし O が 名前付きプロパティをサポートしていて、 ignoreNamedProps が false なら:

    1. もし 名前付きプロパティ可視性アルゴリズム(プロパティ名 P、オブジェクト O)の結果が true なら:

      1. operation を名前付きプロパティgetterを宣言した際に使用したoperationとする。

      2. value を未初期化変数とする。

      3. もし operation が識別子無しで定義されていれば、 value をインターフェース記述の指示に従い 名前付きプロパティの値を取得する手順を Pを名前として実行した結果に設定する。

      4. それ以外の場合、operation が識別子付きで定義されていれば value を メソッド手順(operation)を O を this、« P » を引数値として実行した結果に設定する。

      5. desc をフィールド無しの新規 プロパティディスクリプタとして生成する。

      6. desc.[[Value]] を valueをJavaScript値へ変換した結果に設定する。

      7. もし O が 名前付きプロパティsetterを持つインターフェースを実装していれば desc.[[Writable]] を true に、そうでなければ false に設定する。

      8. もし O が [LegacyUnenumerableNamedProperties] 拡張属性を持つインターフェースを実装していれば desc.[[Enumerable]] を false に、そうでなければ true に設定する。

      9. desc.[[Configurable]] を true に設定する。

      10. desc を返す。

  3. OrdinaryGetOwnProperty(O, P) を返す。

3.10. オブザーバブル配列エキゾチックオブジェクト

オブザーバブル配列エキゾチックオブジェクトは、JavaScriptの Proxyエキゾチックオブジェクトの特定の型であり、本節で定義されたプロキシトラップを用いて作成される。 これは、JavaScript仕様が ArrayインスタンスをプロキシターゲットとするProxyエキゾチックオブジェクトに対し特別な扱いを行っているためであり、 オブザーバブル配列型がこの特別扱いを保ったままJavaScriptコードに公開されることを保証したいからである。

オブザーバブル配列エキゾチックオブジェクトで使われるプロキシトラップは、通常のArrayインスタンスの不変条件よりも多くの不変条件を保証する:

オブザーバブル配列エキゾチックオブジェクトの作成 を、realm realm、Web IDL型 T、アルゴリズム setAlgorithm および deleteAlgorithm を与えて行う:
  1. innerArray を ! ArrayCreate(0) とする。

  2. handler を OrdinaryObjectCreate(null, « [[Type]], [[SetAlgorithm]], [[DeleteAlgorithm]], [[BackingList]] ») とする。

  3. handler.[[Type]] に T を設定する。

  4. handler.[[SetAlgorithm]] に setAlgorithm を設定する。

  5. handler.[[DeleteAlgorithm]] に deleteAlgorithm を設定する。

  6. defineProperty を CreateBuiltinFunction(§ 3.10.1 defineProperty の手順, 3, "", « », realm) とする。

  7. ! CreateDataPropertyOrThrow(handler, "defineProperty", defineProperty) を実行する。

  8. deleteProperty を CreateBuiltinFunction(§ 3.10.2 deleteProperty の手順, 2, "", « », realm) とする。

  9. ! CreateDataPropertyOrThrow(handler, "deleteProperty", deleteProperty) を実行する。

  10. get を CreateBuiltinFunction(§ 3.10.3 get の手順, 3, "", « », realm) とする。

  11. ! CreateDataPropertyOrThrow(handler, "get", get) を実行する。

  12. getOwnPropertyDescriptor を CreateBuiltinFunction(§ 3.10.4 getOwnPropertyDescriptor の手順, 2, "", « », realm) とする。

  13. ! CreateDataPropertyOrThrow(handler, "getOwnPropertyDescriptor", getOwnPropertyDescriptor) を実行する。

  14. has を CreateBuiltinFunction(§ 3.10.5 has の手順, 2, "", « », realm) とする。

  15. ! CreateDataPropertyOrThrow(handler, "has", has) を実行する。

  16. ownKeys を CreateBuiltinFunction(§ 3.10.6 ownKeys の手順, 1, "", « », realm) とする。

  17. ! CreateDataPropertyOrThrow(handler, "ownKeys", ownKeys) を実行する。

  18. preventExtensions を CreateBuiltinFunction(§ 3.10.7 preventExtensions の手順, « », 0, "", realm) とする。

  19. ! CreateDataPropertyOrThrow(handler, "preventExtensions", preventExtensions) を実行する。

  20. set を CreateBuiltinFunction(§ 3.10.8 set の手順, « », 4, "", realm) とする。

  21. ! CreateDataPropertyOrThrow(handler, "set", set) を実行する。

  22. ! ProxyCreate(innerArray, handler) を返す。

3.10.1. defineProperty

definePropertyプロキシトラップの手順(オブザーバブル配列エキゾチックオブジェクト用、O, P, descriptorObjを与える)は以下の通り:
  1. handler を this の値とする。

  2. descriptor を ! ToPropertyDescriptor(descriptorObj) の結果とする。

  3. P が "length" なら:

    1. IsAccessorDescriptor(descriptor) が true なら false を返す。

    2. descriptor.[[Configurable]] が present かつ値が true なら false を返す。

    3. descriptor.[[Enumerable]] が present かつ値が true なら false を返す。

    4. descriptor.[[Writable]] が present かつ値が false なら false を返す。

    5. descriptor.[[Value]] が present なら、 lengthの設定(handler, descriptor.[[Value]])の結果を返す。

    6. true を返す。

  4. P が 配列インデックスなら:

    1. IsAccessorDescriptor(descriptor) が true なら false を返す。

    2. descriptor.[[Configurable]] が present かつ値が false なら false を返す。

    3. descriptor.[[Enumerable]] が present かつ値が false なら false を返す。

    4. descriptor.[[Writable]] が present かつ値が false なら false を返す。

    5. descriptor.[[Value]] が present なら、 インデックス値の設定(handler, P, descriptor.[[Value]])の結果を返す。

    6. true を返す。

  5. ? O.[[DefineOwnProperty]](P, descriptor) を返す。

3.10.2. deleteProperty

deletePropertyプロキシトラップの手順(オブザーバブル配列エキゾチックオブジェクト用、O, Pを与える)は以下の通り:
  1. handler を this の値とする。

  2. P が "length" なら false を返す。

  3. P が 配列インデックスなら:

    1. oldLen を handler.[[BackingList]] の サイズとする。

    2. index を ! ToUint32(P) の結果とする。

    3. index ≠ oldLen − 1 なら false を返す。

    4. handler.[[DeleteAlgorithm]] のアルゴリズム手順を、handler.[[BackingList]][index] と index を与えて実行する。

    5. handler.[[BackingList]] から最後の要素を削除する。

    6. true を返す。

  4. ? O.[[Delete]](P) を返す。

3.10.3. get

getプロキシトラップの手順(オブザーバブル配列エキゾチックオブジェクト用、O, P, Receiverを与える)は以下の通り:
  1. handler を this の値とする。

  2. length を handler.[[BackingList]] の サイズとする。

  3. P が "length" なら length を返す。

  4. P が 配列インデックスなら:

    1. index を ! ToUint32(P) の結果とする。

    2. index ≥ length なら undefined を返す。

    3. jsValue を handler.[[BackingList]][index] をJavaScript値へ変換した結果とする。

    4. 上記のステップで例外が投げられることはない。

    5. jsValue を返す。

  5. ? O.[[Get]](P, Receiver) を返す。

3.10.4. getOwnPropertyDescriptor

getOwnPropertyDescriptorプロキシトラップの手順(オブザーバブル配列エキゾチックオブジェクト用、O, Pを与える)は以下の通り:
  1. handler を this の値とする。

  2. length を handler.[[BackingList]] の サイズとする。

  3. P が "length" なら ! FromPropertyDescriptor(PropertyDescriptor{[[Configurable]]: false, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: length }) を返す。

  4. P が 配列インデックスなら

    1. index を ! ToUint32(P) の結果とする。

    2. index ≥ length なら undefined を返す。

    3. jsValue を handler.[[BackingList]][index] をJavaScript値へ変換した結果とする。

    4. 上記のステップで例外が投げられることはない。

    5. FromPropertyDescriptor(PropertyDescriptor{[[Configurable]]: true, [[Enumerable]]: true, [[Writable]]: true, [[Value]]: jsValue }) を返す。

  5. FromPropertyDescriptor(? O.[[GetOwnProperty]](P)) を返す。

3.10.5. has

hasプロキシトラップの手順(オブザーバブル配列エキゾチックオブジェクト用、O, Pを与える)は以下の通り:
  1. handler を this の値とする。

  2. P が "length" なら true を返す。

  3. P が 配列インデックスなら:

    1. index を ! ToUint32(P) の結果とする。

    2. index < handler.[[BackingList]] の サイズ なら true を返す。

    3. false を返す。

  4. ? O.[[HasProperty]](P) を返す。

3.10.6. ownKeys

ownKeysプロキシトラップの手順(オブザーバブル配列エキゾチックオブジェクト用、Oを与える)は以下の通り:
  1. handler を this の値とする。

  2. length を handler.[[BackingList]] の サイズとする。

  3. keys を空の リストとして初期化する。

  4. i を 0 とする。

  5. While i < length の間:

    1. Append ! ToString(i) を keys に追加する。

    2. i を i + 1 にする。

  6. Extend keys に ! O.[[OwnPropertyKeys]]() の結果を追加する。

  7. CreateArrayFromList(keys) を返す。

3.10.7. preventExtensions

preventExtensionsプロキシトラップの手順(オブザーバブル配列エキゾチックオブジェクト用)は以下の通り:
  1. false を返す。

3.10.8. set

setプロキシトラップの手順(オブザーバブル配列エキゾチックオブジェクト用、O, P, V, Receiverを与える)は以下の通り:
  1. handler を this の値とする。

  2. P が "length" なら lengthの設定(handler, V)の結果を返す。

  3. P が 配列インデックスなら インデックス値の設定(handler, P, V)の結果を返す。

  4. ? O.[[Set]](P, V, Receiver) を返す。

3.10.9. 抽象操作

lengthの設定 (オブザーバブル配列エキゾチックオブジェクトの handler, newLen を与える):
  1. uint32Len を ? ToUint32(newLen) の結果とする。

  2. numberLen を ? ToNumber(newLen) の結果とする。

  3. uint32Len ≠ numberLen なら RangeError 例外を投げる。

  4. oldLen を handler.[[BackingList]] の サイズとする。

  5. uint32Len > oldLen なら false を返す。

  6. indexToDelete を oldLen − 1 とする。

  7. While indexToDelete ≥ uint32Len の間:

    1. handler.[[DeleteAlgorithm]] の手順を、handler.[[BackingList]][indexToDelete]、indexToDelete を与えて実行する。

    2. handler.[[BackingList]] から最後の要素を削除する。

    3. indexToDelete を indexToDelete − 1 にする。

  8. true を返す。

インデックス値の設定 (オブザーバブル配列エキゾチックオブジェクトの handler, P, V を与える):
  1. oldLen を handler.[[BackingList]] の サイズとする。

  2. index を ! ToUint32(P) の結果とする。

  3. index > oldLen なら false を返す。

  4. idlValue を Vを handler.[[Type]] 型のIDL値に変換した結果とする。

  5. index < oldLen なら:

    1. handler.[[DeleteAlgorithm]] の手順を、handler.[[BackingList]][index]、index を与えて実行する。

  6. handler.[[SetAlgorithm]] の手順を、idlValue、index を与えて実行する。

  7. index = oldLen なら idlValueを handler.[[BackingList]] に追加する。

  8. それ以外の場合、handler.[[BackingList]][index] を idlValue に設定する。

  9. true を返す。

3.11. コールバックインターフェース

§ 2.12 インターフェースを実装するオブジェクトで説明されている通り、 コールバックインターフェースは 任意のJavaScriptオブジェクトによってスクリプトで実装できる。 以下は、あるオブジェクトに対して コールバックインターフェースの operation を呼び出す場合のケースである:

JavaScriptオブジェクトは、定数に対応する プロパティを持っていなくても、 その定数を宣言している コールバックインターフェースを実装したとみなされることに注意。

Web IDL 引数リストは、 各値がIDL値または特殊値“missing”(省略されたオプション引数を表す)のいずれかである値の リストである。

Web IDL 引数リストを JavaScript 引数リストに変換するには、 Web IDL 引数リスト args を与え、以下の手順を行う:
  1. jsArgs を空の リストとする。

  2. i を 0 とする。

  3. count を 0 とする。

  4. i < args の サイズ の間:

    1. args[i] が特殊値“missing”なら、undefined を jsArgs に追加する。

    2. それ以外の場合、args[i] はIDL値:

      1. convertResult を args[i] をJavaScript値に変換した結果とする(例外は再スロー)。

      2. convertResult を jsArgs に追加する。

      3. count を i + 1 に設定する。

    3. i を i + 1 にする。

  5. jsArgs を count個の要素になるよう切り捨てる。

  6. jsArgs を返す。

ユーザーオブジェクトの operation を呼び出すには、 コールバックインターフェース型値 value、 operation名 opName、Web IDL 引数リスト args、オプションの コールバックthis値 thisArg を与え、以下の手順を実行する。 これらの手順はIDL値を返すか例外を投げる。

  1. completion を未初期化変数とする。

  2. thisArg が与えられていなければ thisArg を undefined にする。

  3. O を value に対応するJavaScriptオブジェクトとする。

  4. realm を O の 関連realmとする。

  5. relevant settings を realm の 設定オブジェクトとする。

  6. stored settings を value の コールバックコンテキストとする。

  7. スクリプトの実行準備を relevant settings で行う。

  8. コールバックの実行準備を stored settings で行う。

  9. X を O とする。

  10. IsCallable(O) が false なら:

    1. getResult を Completion(Get(O, opName)) とする。

    2. getResult が abrupt completion なら completion に getResult を設定し return のステップへジャンプする。

    3. X を getResult.[[Value]] に設定する。

    4. IsCallable(X) が false なら completion に Completion Record { [[Type]]: throw, [[Value]]: 新規 TypeError オブジェクト, [[Target]]: 空 } を設定し return のステップへジャンプする。

    5. thisArg を O に設定(与えられた値を上書き)。

  11. jsArgs を argsをJavaScript引数リストに変換した結果とする。例外が投げられた場合、 completion に投げられた例外のcompletion値を設定し return のステップへジャンプする。

  12. callResult を Completion(Call(X, thisArg, jsArgs)) とする。

  13. callResult が abrupt completion なら completion に callResult を設定し return のステップへジャンプする。

  14. completion を callResult.[[Value]] をoperationの戻り値型のIDL値に変換した結果に設定する。例外が投げられた場合はcompletionに例外のcompletion値を設定する。

  15. Return: この時点で completion はIDL値か abrupt completion となる。

    1. コールバック実行後のクリーンアップを stored settings で行う。

    2. スクリプト実行後のクリーンアップを relevant settings で行う。

    3. completionがIDL値ならcompletionを返す。

    4. completionが abrupt completion で、operationの戻り値型が promise型でない場合、completion.[[Value]] をthrowする。

    5. rejectedPromise を ! Call(%Promise.reject%, %Promise%, «completion.[[Value]]») とする。

    6. rejectedPromise をoperationの戻り値型へ変換した結果を返す。

3.11.1. レガシーコールバックインターフェースオブジェクト

ある コールバックインターフェース が ある realmで公開されていて、 そのインターフェース上に 定数が定義されている場合、 対応するプロパティが realm の グローバルオブジェクト 上に存在する。 このプロパティ名は コールバックインターフェースの識別子であり、 その値は レガシーコールバックインターフェースオブジェクトである。

特定の コールバックインターフェースの レガシーコールバックインターフェースオブジェクトは 組み込み関数オブジェクトである。 そのプロパティには、そのインターフェースで定義されている 定数が対応しており、詳細は § 3.7.5 定数 に記載されている。

注: レガシーコールバックインターフェースオブジェクトは 関数オブジェクトであるため、 そのレガシーコールバックインターフェースオブジェクトにtypeof演算子を適用すると "function" を返す。

特定の コールバックインターフェース interface (識別子 id、realm realm)の レガシーコールバックインターフェースオブジェクトは、以下の手順で 生成される:

  1. steps を次の手順とする:

    1. スロー する TypeError。

  2. F を CreateBuiltinFunction(steps, 0, id, « », realm) とする。

  3. 定数を定義する、realm を指定して interface の定数を F 上に。

  4. F を返す。

3.12. コールバック関数の呼び出し

JavaScriptの 呼び出し可能オブジェクトが コールバック関数値として利用される場合は、 operationが コールバックインターフェース値上で呼び出される場合(前節参照)と 似た方法で呼び出される。

呼び出す には コールバック関数型値 callable、 Web IDL 引数リスト args、 例外動作 exceptionBehavior("report"または"rethrow")、 オプションの コールバックthis値 thisArg を与え、以下の手順を実行する。 これらの手順はIDL値を返すか例外を投げる。

exceptionBehavior 引数は、callable の 戻り値型が promise型でない場合に限り必須となる。 callable の戻り値型が undefined または any 以外なら 必ず "rethrow" でなければならない。

呼び出し元がこれを正しく指定していない場合、現行標準では指定が必須な場面では "rethrow" を指定したものと見なすべきである。
  1. completion を未初期化変数とする。

  2. thisArg が与えられていなければ thisArg を undefined にする。

  3. F を callable に対応するJavaScriptオブジェクトとする。

  4. IsCallable(F) が false なら:

    1. 注: これはコールバック関数が [LegacyTreatNonObjectAsNull] 属性付きの属性から来た場合のみ起こり得る。

    2. undefined をコールバック関数の戻り値型に変換した結果を返す。

  5. realm を F の 関連realmとする。

  6. relevant settings を realm の 設定オブジェクトとする。

  7. stored settings を callable の コールバックコンテキストとする。

  8. スクリプトの実行準備を relevant settings で行う。

  9. コールバックの実行準備を stored settings で行う。

  10. jsArgs を argsをJavaScript引数リストに変換した結果とする。例外が投げられた場合、 completion に投げられた例外のcompletion値を設定し return のステップへジャンプする。

  11. callResult を Completion(Call(F, thisArg, jsArgs)) とする。

  12. callResult が abrupt completion なら completion に callResult を設定し return のステップへジャンプする。

  13. completion を callResult.[[Value]] をコールバック関数の戻り値型のIDL値に変換した結果に設定する。例外が投げられた場合はcompletionに例外のcompletion値を設定する。

  14. Return: この時点で completion はIDL値か abrupt completion となる。

    1. コールバック実行後のクリーンアップを stored settings で行う。

    2. スクリプト実行後のクリーンアップを relevant settings で行う。

    3. completionがIDL値ならcompletionを返す。

    4. Assert: completionは abrupt completion であること。

    5. exceptionBehaviorが"rethrow"なら completion.[[Value]] をthrowする。

    6. それ以外で exceptionBehaviorが"report"なら:

      1. Assert: callable の 戻り値型は undefined または any であること。

      2. 例外の報告 completion.[[Value]] を realm の グローバルオブジェクトに対して行う。

      3. 一意な undefined IDL値を返す。

    7. Assert: callable の 戻り値型は promise型であること。

    8. rejectedPromise を ! Call(%Promise.reject%, %Promise%, «completion.[[Value]]») とする。

    9. rejectedPromise をコールバック関数の戻り値型へ変換した結果を返す。

一部のコールバック関数は コンストラクタとして使われる場合がある。その場合、戻り値型が promise型であってはならない。

コールバック関数を構築するには コールバック関数型値 callable、 Web IDL 引数リスト args を与え、以下の手順を実行する。 これらの手順はIDL値を返すか例外を投げる。

  1. completion を未初期化変数とする。

  2. F を callable に対応するJavaScriptオブジェクトとする。

  3. IsConstructor(F) が false なら TypeError 例外を投げる。

  4. realm を F の 関連realmとする。

  5. relevant settings を realm の 設定オブジェクトとする。

  6. stored settings を callable の コールバックコンテキストとする。

  7. スクリプトの実行準備を relevant settings で行う。

  8. コールバックの実行準備を stored settings で行う。

  9. jsArgs を argsをJavaScript引数リストに変換した結果とする。例外が投げられた場合、 completion に投げられた例外のcompletion値を設定し return のステップへジャンプする。

  10. callResult を Completion(Construct(F, jsArgs)) とする。

  11. callResult が abrupt completion なら completion に callResult を設定し return のステップへジャンプする。

  12. completion を callResult.[[Value]] をコールバック関数の戻り値型のIDL値に変換した結果に設定する。例外が投げられた場合はcompletionに例外のcompletion値を設定する。

  13. Return: この時点で completion はIDL値か abrupt completion となる。

    1. コールバック実行後のクリーンアップを stored settings で行う。

    2. スクリプト実行後のクリーンアップを relevant settings で行う。

    3. completionが abrupt completion なら completion.[[Value]] をthrowする。

    4. completionを返す。

3.13. 名前空間

ある 名前空間 が特定の realmで公開されている場合、 対応するプロパティがその realm の グローバルオブジェクト上に存在する。 プロパティ名はその名前空間の 識別子であり、値は 名前空間オブジェクトと呼ばれるオブジェクトである。

名前空間オブジェクトの特徴は § 3.13.1 名前空間オブジェクト に記載されている。

3.13.1. 名前空間オブジェクト

特定の 名前空間 namespace と realm realm の 名前空間オブジェクトは、以下の手順で 生成される:

  1. namespaceObject を OrdinaryObjectCreate(realm.[[Intrinsics]].[[%Object.prototype%]]) とする。

  2. 通常の属性を定義する(namespace, namespaceObject, realm)を実行する。

  3. 通常の操作を定義する(namespace, namespaceObject, realm)を実行する。

  4. 定数の定義(namespace, namespaceObject, realm)を実行する。

  5. 各 公開された インターフェース interface で、 [LegacyNamespace] 拡張属性の引数として namespace の識別子が指定されているものについて:

    1. id を interface の 識別子とする。

    2. interfaceObject を インターフェースオブジェクトの生成(interface, id, realm)の結果とする。

    3. DefineMethodProperty(namespaceObject, id, interfaceObject, false) を実行する。

  6. namespaceObject を返す。

クラス文字列(class string)は 名前空間オブジェクトの 名前空間の 識別子である。

3.14. 例外

3.14.1. DOMException のカスタムバインディング

JavaScript バインディングでは、DOMException のインターフェイスプロトタイプオブジェクトは、 その [[Prototype]] 内部スロットが、インターフェイスプロトタイプオブジェクトを作成する抽象操作で定義されるように、 組み込みオブジェクト %Error.prototype% に設定される。 また、すべての組み込み例外と同様に、[[ErrorData]] および [[Stack]] スロットも持つ。

さらに、実装がネイティブの Error オブジェクトに他の特別な能力や 非標準プロパティ(line および column プロパティなど)を与える場合、 それらも DOMException オブジェクトで公開するべきである。

3.14.2. 例外オブジェクト

単純例外は 対応する型のネイティブJavaScriptオブジェクトとして表現される。

DOMException は プラットフォームオブジェクトとして DOMException インターフェースを実装する。

3.14.3. 例外の生成とthrow

単純例外の生成(型 T の場合):
  1. message を例外状況に適した 実装依存メッセージとする。呼び出し元仕様は、実装がこのメッセージを構築する際の参考情報を持つ場合がある。

    実装はこのメッセージを構築する際、クロスオリジンフレームのURLやユーザーを特定できる情報など、機密性やセキュリティに関する情報を漏らさないよう注意すること。

  2. args を « message » とする。

  3. constructor を 現行realm.[[Intrinsics]].[[%T%]] とする。

  4. ! Construct(constructor, args) を返す。

DOMExceptionの生成(文字列 name を与える):
  1. Assert: name は DOMException 名テーブルに含まれている。

  2. ex を 現行realmで新規作成した DOMException とする。

  3. ex の name を name に設定する。

  4. ex の message を例外状況に適した 実装依存メッセージに設定する。呼び出し元仕様は、実装がこのメッセージを構築する際の参考情報を持つ場合がある。

    実装はこのメッセージを構築する際、クロスオリジンフレームのURLやユーザーを特定できる情報など、機密性やセキュリティに関する情報を漏らさないよう注意すること。

  5. ex を返す。

DOMException派生インターフェースの生成(インターフェース 識別子 type、追加の初期化指示を与える):
  1. ex を 現行realmで新規作成した type識別子の インターフェース インスタンスとする。

  2. ex の name を type に設定する。

  3. ex の message を例外状況に適した 実装依存メッセージに設定する。呼び出し元仕様は、実装がこのメッセージを構築する際の参考情報を持つ場合がある。

    実装はこのメッセージを構築する際、クロスオリジンフレームのURLやユーザーを特定できる情報など、機密性やセキュリティに関する情報を漏らさないよう注意すること。

  4. 呼び出し元による追加の初期化処理を ex に対して実施する。

  5. ex を返す。

例外のthrow(例外の場合):
  1. O を 例外の生成(同じ引数)で得る。

  2. O をthrowする。

上記のアルゴリズムは、例外を表すオブジェクトが関数オブジェクトから伝播して外へ出る場合、 そのレルムに関連付けられているものに制限する。 すなわち、その 関数オブジェクトのレルム(つまり、関数が 実行される時点の現在のレルム)である。 たとえば、次の IDL を考える。

[Exposed=Window]
interface MathUtils {
  // xが負の場合は "NotSupportedError" DOMException をthrowする。
  double computeSquareRoot(double x);
};

もし異なる realm の MathUtils オブジェクトに対して computeSquareRoot を適用した場合、 throwされる例外はメソッドのrealm(呼び出されたメソッドのrealm)に属するものであり、 適用されたオブジェクトのrealmではない:

const myMU = window.getMathUtils();          // このrealmのMathUtilsオブジェクト
const otherMU = otherWindow.getMathUtils();  // 異なるrealmのMathUtilsオブジェクト

myMU instanceof Object;                      // trueになる
otherMU instanceof Object;                   // falseになる
otherMU instanceof otherWindow.Object;       // trueになる

try {
  otherMU.doComputation.call(myMU, -1);
} catch (e) {
  console.assert(!(e instanceof DOMException));
  console.assert(e instanceof otherWindow.DOMException);
}

3.14.4. 例外の扱い

特に指定がない限り、 本書の要件によりJavaScriptランタイムセマンティクスが呼び出され、 例外がthrowされて終了した場合は、その例外は呼び出し元へ伝播し、そこでcatchされなければさらにその呼び出し元へ、以降も同様に伝播しなければならない。

文書の慣例に従い、本書で定義されるアルゴリズムはthrowされた例外を捕捉する場合があり、その際には 例外がthrowされた場合に取るべき具体的な手順を記述するか、 abrupt completionを明示的に扱う。

次のIDLフラグメントは2つのインターフェースと1つの例外を定義する。 ExceptionThrowerのvalueOf属性は、値の取得を試みるたびに例外をthrowするよう定義されている。

[Exposed=Window]
interface Dahut {
  attribute DOMString type;
};

[Exposed=Window]
interface ExceptionThrower {
  // この属性は常に NotSupportedError をthrowし値を返さない。
  attribute long valueOf;
};

このインターフェースをサポートするJavaScript実装があると仮定すると、以下のコードは例外の扱い方を示している:

var d = getDahut();              // Dahut のインスタンスを取得
var et = getExceptionThrower();  // ExceptionThrower のインスタンスを取得

try {
  d.type = { toString: function() { throw "abc"; } };
} catch (e) {
  // ここで文字列 "abc" がcatchされる。ネイティブオブジェクトから文字列へ変換する過程で無名関数が呼び出され、[[DefaultValue]]・ToPrimitive・ToStringアルゴリズムは例外をcatchしない。
}

try {
  d.type = { toString: { } };
} catch (e) {
  // ここで例外がcatchされる。toStringプロパティ値のネイティブオブジェクトに対して[[Call]]を呼ぶ際に例外が発生するため。
}

try {
  d.type = Symbol();
} catch (e) {
  // ここで例外がcatchされる。Symbol値に対してJavaScriptのToString抽象操作を呼ぶ際に例外が発生するため。
}

d.type = et;
// ここでは未catchの "NotSupportedError" DOMException がthrowされる。
// [[DefaultValue]]アルゴリズムがExceptionThrowerオブジェクトの"valueOf"プロパティ値の取得を試みるためで、この例外はこのコードブロックの外へ伝播する。

4. 共通定義

本節では、すべての適合実装がサポートしなければならない共通定義について記載する。

4.1. ArrayBufferView

typedef (Int8Array or Int16Array or Int32Array or
         Uint8Array or Uint16Array or Uint32Array or Uint8ClampedArray or
         BigInt64Array or BigUint64Array or
         Float16Array or Float32Array or Float64Array or DataView) ArrayBufferView;

ArrayBufferView typedefは ArrayBuffer または SharedArrayBuffer ([AllowShared]使用時)に対してビューを提供するオブジェクトを表すために使用される。

4.2. BufferSource

typedef (ArrayBuffer or ArrayBufferView) BufferSource;

BufferSource typedefは ArrayBuffer そのもの、または ArrayBuffer へのビューを提供するオブジェクトを表すために使用される。

注: [AllowShared] は BufferSource では利用できない。ArrayBufferが対応していないためである。 代わりに AllowSharedBufferSource を使用すること。

4.3. AllowSharedBufferSource

typedef (ArrayBuffer or SharedArrayBuffer or [AllowShared] ArrayBufferView) AllowSharedBufferSource;

AllowSharedBufferSource typedefは ArrayBuffer または SharedArrayBuffer そのもの、またはArrayBufferもしくはSharedArrayBufferへのビューを提供するオブジェクトを表すために使用される。

4.4. DOMException

DOMException 型は以下のIDLフラグメントで定義されるインターフェース型である:

[Exposed=*,
 Serializable]
interface DOMException { // JavaScriptバインディングの注意事項は後述
  constructor(optional DOMString message = "", optional DOMString name = "Error");
  readonly attribute DOMString name;
  readonly attribute DOMString message;
  readonly attribute unsigned short code;

  const unsigned short INDEX_SIZE_ERR = 1;
  const unsigned short DOMSTRING_SIZE_ERR = 2;
  const unsigned short HIERARCHY_REQUEST_ERR = 3;
  const unsigned short WRONG_DOCUMENT_ERR = 4;
  const unsigned short INVALID_CHARACTER_ERR = 5;
  const unsigned short NO_DATA_ALLOWED_ERR = 6;
  const unsigned short NO_MODIFICATION_ALLOWED_ERR = 7;
  const unsigned short NOT_FOUND_ERR = 8;
  const unsigned short NOT_SUPPORTED_ERR = 9;
  const unsigned short INUSE_ATTRIBUTE_ERR = 10;
  const unsigned short INVALID_STATE_ERR = 11;
  const unsigned short SYNTAX_ERR = 12;
  const unsigned short INVALID_MODIFICATION_ERR = 13;
  const unsigned short NAMESPACE_ERR = 14;
  const unsigned short INVALID_ACCESS_ERR = 15;
  const unsigned short VALIDATION_ERR = 16;
  const unsigned short TYPE_MISMATCH_ERR = 17;
  const unsigned short SECURITY_ERR = 18;
  const unsigned short NETWORK_ERR = 19;
  const unsigned short ABORT_ERR = 20;
  const unsigned short URL_MISMATCH_ERR = 21;
  const unsigned short QUOTA_EXCEEDED_ERR = 22;
  const unsigned short TIMEOUT_ERR = 23;
  const unsigned short INVALID_NODE_TYPE_ERR = 24;
  const unsigned short DATA_CLONE_ERR = 25;
};

注記: § 3.14.1 DOMException カスタムバインディングで述べたように、JavaScript バインディングは インターフェイス型に対する通常の要件に加えて、追加の 要件を課す。

各 DOMException オブジェクトには、関連付けられた name と message があり、どちらも文字列である。

new DOMException(message, name) コンストラクター手順は次のとおりである:

  1. this のname を name に設定する。

  2. this のmessage を message に設定する。

name ゲッター手順は、 this のname を返すことである。

message ゲッター手順は、 this のmessage を返すことである。

code ゲッター手順は、this の name について、 DOMException 名前表で示されるレガシー コードを返すことであり、そのような項目が表に存在しない場合は 0 を返すことである。

DOMException オブジェクトは直列化可能オブジェクトである。

value と serialized が与えられたときの、それらの直列化手順は次のとおりである:

  1. serialized.[[Name]] を value のname に設定する。
  2. serialized.[[Message]] を value のmessage に設定する。
  3. serialized.[[Stack]] を、 value.[[Stack]] から派生した実装定義の文字列に設定する。
  4. ユーザーエージェントは、まだ仕様化されていない、付随する興味深いデータ、特に line および column プロパティがあれば、その直列化表現を serialized に付加するべきである。

value と serialized が与えられたときの、それらの逆直列化手順は次のとおりである:

  1. value のname を serialized.[[Name]] に設定する。
  2. value のmessage を serialized.[[Message]] に設定する。
  3. value.[[Stack]] を serialized.[[Stack]] に設定する。
  4. 他のデータが serialized に付加されている場合は、それを逆直列化して value に付加する。

4.5. Function

callback Function = any (any... arguments);

Function コールバック関数 型は、引数として何が渡されても、また返される値の種類にも制限がない関数値を表現するために使われる。

4.6. VoidFunction

callback VoidFunction = undefined ();

VoidFunction コールバック関数 型は、引数を取らず値も返さない関数値を表現するために使われる。

5. 拡張性

この節は参考情報です。

言語バインディング要件への拡張は、本書で定義されたものと衝突しない 拡張属性 を用いて指定できる。 プライベートやプロジェクト固有で使う拡張は、他の仕様書に現れる IDLフラグメント には含めるべきではない。他の仕様で利用が必要な拡張は、現行標準の次版への採用も視野に Web IDL の担当グループ(執筆時点では W3C Web Platform Working Group) と調整することを推奨する。

IDL言語の他の側面への拡張は強く推奨されない。

6. レガシー構造

この節は参考情報です。

レガシーWeb IDL構造は、レガシーWebプラットフォーム機能を仕様化するためだけに存在する。 これらは一般的に "Legacy" という文字列で始まる。 レガシーWeb IDL構造は、レガシーWebプラットフォーム機能の挙動を仕様化するため、またはその機能との整合性のために必要な場合以外は 仕様書で使用することは強く推奨されない。 レガシーWeb IDL構造の使用を検討する編集者は、事前に issueを登録 して議論することが強く推奨される。

構造をレガシーとマークすること自体は、その構造が現行標準からすぐに削除されることを意味するものではない。 ただし、様々な指標により、当該構造が仕様から削除可能になった場合や、 レガシーでないWeb IDL構造に置き換えられる場合は、削除候補となることを示唆するものである。

7. 本仕様書の参照方法

この節は参考情報です。

Webプラットフォームインターフェースを1つ以上の IDLフラグメント で定義する他の仕様書は、本仕様書を参照することが期待される。 それらの仕様書では、IDLが本仕様書に記載された通りに解釈されることを示すため、 以下のような文章を含めることが推奨される:

本仕様書の付録Aに記載されたIDLフラグメントは、本仕様書の標準参照に定義されたIDLフラグメントと併せて、 “Web IDL”現行標準に記載された 適合IDLフラグメント集合 として解釈される必要がある。 [WEBIDL]

さらに、参照仕様書のユーザーエージェントの適合クラスについても 本仕様書の 適合実装クラスとリンクすることが推奨される:

FooMLユーザーエージェントの適合実装は、本仕様書の付録AのIDLフラグメントについても、 “Web IDL”現行標準に記載された 適合実装 である必要がある。 [WEBIDL]

8. プライバシーおよびセキュリティに関する考慮事項

本仕様はJavaScriptとIDL値の間の変換層を定義する。不適切な実装はセキュリティ上の問題につながる可能性がある。

本仕様は、any型や object型のIDL型を通じて JavaScript値を直接扱う能力も提供する。これらの値を安全に扱わなければ、セキュリティ上の問題につながる。 特に、ユーザースクリプトは、これらの値のほぼすべての操作に応じて実行され、仕様や実装の期待を損なう可能性がある。

本仕様は SharedArrayBuffer オブジェクトとの相互作用も可能にしており、これらを用いたタイミング攻撃のリスクがある。 これらのオブジェクトを利用する仕様は、そのような攻撃への考慮が必要である。

謝辞

この節は参考情報です。

編集者は以下の方々の本仕様への貢献に感謝します: Glenn Adams, David Andersson, Jake Archibald, Tab Atkins-Bittner, L. David Baron, Art Barstow, Nils Barth, Robin Berjon, David Bruant, Jan-Ivar Bruaroey, Marcos Cáceres, Giovanni Campagna, François Daoust, Domenic Denicola, Chris Dumez, Michael Dyck, Daniel Ehrenberg, Brendan Eich, João Eiras, Gorm Haug Eriksen, Sigbjorn Finne, David Flanagan, Aryeh Gregor, Dimitry Golubovsky, James Graham, Aryeh Gregor, Tiancheng “Timothy” Gu, Kartikaya Gupta, Marcin Hanclik, Jed Hartman, Stefan Haustein, Dominique Hazaël-Massieux, Ian Hickson, Björn Höhrmann, Kyle Huey, Lachlan Hunt, Oliver Hunt, Jim Jewett, Wolfgang Keller, Anne van Kesteren, Olav Junker Kjær, Takayoshi Kochi, Magnus Kristiansen, Raphael Kubo da Costa, Takeshi Kurosawa, Yves Lafon, Travis Leithead, Jim Ley, Kevin Lindsey, Jens Lindström, Peter Linss, 呂康豪 (Kang-Hao Lu), Kyle Machulis, Darien Maillet Valentine, Mark Miller, Ms2ger, Andrew Oakley, 岡坂 史紀 (Shiki Okasaka), Jason Orendorff, Olli Pettay, Simon Pieters, Andrei Popescu, François Remy, Tim Renouf, Jeremy Roman, Tim Ruffles, Alex Russell, Takashi Sakamoto, Doug Schepers, Jonas Sicking, Garrett Smith, Sam Sneddon, Jungkee Song, Josh Soref, Maciej Stachowiak, Austin Sullivan, Anton Tayanovskyy, triple-underscore, Peter Van der Beken, Jeff Walden, Allen Wirfs-Brock, Jeffrey Yasskin, Collin Xu。

編集者が不在の間、本仕様の維持をしていただいたSam Weinig氏にも特に感謝します。

この標準は Edgar Chen (Mozilla, echen@mozilla.com) と Tiancheng "Timothy" Gu (timothygu99@gmail.com) によって執筆され、 Boris Zbarsky (bzbarsky@mit.edu), Cameron McCormack (cam@mcc.id.au), Tobie Langel (tobie@unlockopen.com) らによる大幅な貢献があります。

IDL文法

この節では、開始記号 Definitions が、全体の IDLフラグメント にマッチする LL(1)文法を定義する。

文法の各生成規則の右辺は、ゼロでない個数の終端記号と非終端記号の並び、または ε(何もないことを表す)である。 大文字で始まる記号は非終端記号である。 等幅フォントで記載された記号は終端記号である。 小文字で始まるサンセリフ体の記号は、Perl 5正規表現構文 [PERLRE] を用いた正規表現でマッチする終端記号である:

integer = /-?([1-9][0-9]*|0[Xx][0-9A-Fa-f]+|0[0-7]*)/
decimal = /-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+)/
identifier = /[_-]?[A-Za-z][0-9A-Z_a-z-]*/
string = /"[^"]*"/
whitespace = /[\t\n\r ]+/
comment = /\/\/.*|\/\*(.|\n)*?\*\//
other = /[^\t\n\r 0-9A-Za-z]/

トークナイザは スカラー値の列で動作する。 トークナイズ時は、可能な限り最長一致でマッチを行う必要がある。例えば、入力テキストが「a1」の場合は、identifier 1つとしてトークナイズされ、 identifierとintegerに分割されない。 最長一致が上記の名前付き終端記号または文法の他の終端記号いずれかに一致する場合は、後者としてトークナイズしなければならない。 したがって、入力「long」は終端記号 longとしてトークナイズされ、 "long"という identifier にはならない。 また「.」は終端記号 .としてトークナイズされ、 otherにはならない。

IDL構文は大文字・小文字を区別する。文法で使われる等幅フォント終端記号や identifier 終端の値も同様である。 例えば、入力「Const」は identifierとしてトークナイズされ、 終端記号 constにはならない。 interfaceの 識別子が "A"なら"a"とは区別される。 また 拡張属性 [legacyfactoryfunction]は [LegacyFactoryFunction] 拡張属性として認識されない。

暗黙的に、入力テキストの各終端記号の間には任意個数の whitespace や comment 終端が許される。これらの whitespace や comment 終端はパース時に無視される。

以下のLL(1)文法は、開始記号 Definitions から始まり、 IDLフラグメントにマッチする:

Definitions ::
    ExtendedAttributeList Definition Definitions
    ε

Definition ::
    CallbackOrInterfaceOrMixin
    Namespace
    Partial
    Dictionary
    Enum
    Typedef
    IncludesStatement

ArgumentNameKeyword ::
    attribute
    callback
    const
    constructor
    deleter
    dictionary
    enum
    getter
    includes
    inherit
    interface
    iterable
    maplike
    mixin
    namespace
    partial
    readonly
    required
    setlike
    setter
    static
    stringifier
    typedef
    unrestricted

CallbackOrInterfaceOrMixin ::
    callback CallbackRestOrInterface
    interface InterfaceOrMixin

InterfaceOrMixin ::
    InterfaceRest
    MixinRest

InterfaceRest ::
    identifier Inheritance { InterfaceMembers } ;

Partial ::
    partial PartialDefinition

PartialDefinition ::
    interface PartialInterfaceOrPartialMixin
    PartialDictionary
    Namespace

PartialInterfaceOrPartialMixin ::
    PartialInterfaceRest
    MixinRest

PartialInterfaceRest ::
    identifier { PartialInterfaceMembers } ;

InterfaceMembers ::
    ExtendedAttributeList InterfaceMember InterfaceMembers
    ε

InterfaceMember ::
    PartialInterfaceMember
    Constructor

PartialInterfaceMembers ::
    ExtendedAttributeList PartialInterfaceMember PartialInterfaceMembers
    ε

PartialInterfaceMember ::
    Const
    Operation
    Stringifier
    StaticMember
    Iterable
    AsyncIterable
    ReadOnlyMember
    ReadWriteAttribute
    ReadWriteMaplike
    ReadWriteSetlike
    InheritAttribute

Inheritance ::
    : identifier
    ε

MixinRest ::
    mixin identifier { MixinMembers } ;

MixinMembers ::
    ExtendedAttributeList MixinMember MixinMembers
    ε

MixinMember ::
    Const
    RegularOperation
    Stringifier
    OptionalReadOnly AttributeRest

IncludesStatement ::
    identifier includes identifier ;

CallbackRestOrInterface ::
    CallbackRest
    interface identifier { CallbackInterfaceMembers } ;

CallbackInterfaceMembers ::
    ExtendedAttributeList CallbackInterfaceMember CallbackInterfaceMembers
    ε

CallbackInterfaceMember ::
    Const
    RegularOperation

Const ::
    const ConstType identifier = ConstValue ;

ConstValue ::
    BooleanLiteral
    FloatLiteral
    integer

BooleanLiteral ::
    true
    false

FloatLiteral ::
    decimal
    -Infinity
    Infinity
    NaN

ConstType ::
    PrimitiveType
    identifier

ReadOnlyMember ::
    readonly ReadOnlyMemberRest

ReadOnlyMemberRest ::
    AttributeRest
    MaplikeRest
    SetlikeRest

ReadWriteAttribute ::
    AttributeRest

InheritAttribute ::
    inherit AttributeRest

AttributeRest ::
    attribute TypeWithExtendedAttributes AttributeName ;

AttributeName ::
    AttributeNameKeyword
    identifier

AttributeNameKeyword ::
    required

OptionalReadOnly ::
    readonly
    ε

DefaultValue ::
    ConstValue
    string
    [ ]
    { }
    null
    undefined

Operation ::
    RegularOperation
    SpecialOperation

RegularOperation ::
    Type OperationRest

SpecialOperation ::
    Special RegularOperation

Special ::
    getter
    setter
    deleter

OperationRest ::
    OptionalOperationName ( ArgumentList ) ;

OptionalOperationName ::
    OperationName
    ε

OperationName ::
    OperationNameKeyword
    identifier

OperationNameKeyword ::
    includes

ArgumentList ::
    Argument Arguments
    ε

Arguments ::
    , Argument Arguments
    ε

Argument ::
    ExtendedAttributeList ArgumentRest

ArgumentRest ::
    optional TypeWithExtendedAttributes ArgumentName Default
    Type Ellipsis ArgumentName

ArgumentName ::
    ArgumentNameKeyword
    identifier

Ellipsis ::
    ...
    ε

Constructor ::
    constructor ( ArgumentList ) ;

Stringifier ::
    stringifier StringifierRest

StringifierRest ::
    OptionalReadOnly AttributeRest
    ;

StaticMember ::
    static StaticMemberRest

StaticMemberRest ::
    OptionalReadOnly AttributeRest
    RegularOperation

Iterable ::
    iterable < TypeWithExtendedAttributes OptionalType > ;

OptionalType ::
    , TypeWithExtendedAttributes
    ε

AsyncIterable ::
    async_iterable < TypeWithExtendedAttributes OptionalType > OptionalArgumentList ;

OptionalArgumentList ::
    ( ArgumentList )
    ε

ReadWriteMaplike ::
    MaplikeRest

MaplikeRest ::
    maplike < TypeWithExtendedAttributes , TypeWithExtendedAttributes > ;

ReadWriteSetlike ::
    SetlikeRest

SetlikeRest ::
    setlike < TypeWithExtendedAttributes > ;

Namespace ::
    namespace identifier { NamespaceMembers } ;

NamespaceMembers ::
    ExtendedAttributeList NamespaceMember NamespaceMembers
    ε

NamespaceMember ::
    RegularOperation
    readonly AttributeRest
    Const

Dictionary ::
    dictionary identifier Inheritance { DictionaryMembers } ;

DictionaryMembers ::
    DictionaryMember DictionaryMembers
    ε

DictionaryMember ::
    ExtendedAttributeList DictionaryMemberRest

DictionaryMemberRest ::
    required TypeWithExtendedAttributes identifier ;
    Type identifier Default ;

PartialDictionary ::
    dictionary identifier { DictionaryMembers } ;

Default ::
    = DefaultValue
    ε

Enum ::
    enum identifier { EnumValueList } ;

EnumValueList ::
    string EnumValueListComma

EnumValueListComma ::
    , EnumValueListString
    ε

EnumValueListString ::
    string EnumValueListComma
    ε

CallbackRest ::
    identifier = Type ( ArgumentList ) ;

Typedef ::
    typedef TypeWithExtendedAttributes identifier ;

Type ::
    SingleType
    UnionType Null

TypeWithExtendedAttributes ::
    ExtendedAttributeList Type

SingleType ::
    DistinguishableType
    any
    PromiseType

UnionType ::
    ( UnionMemberType or UnionMemberType UnionMemberTypes )

UnionMemberType ::
    ExtendedAttributeList DistinguishableType
    UnionType Null

UnionMemberTypes ::
    or UnionMemberType UnionMemberTypes
    ε

DistinguishableType ::
    PrimitiveType Null
    StringType Null
    identifier Null
    sequence < TypeWithExtendedAttributes > Null
    async_sequence < TypeWithExtendedAttributes > Null
    object Null
    symbol Null
    BufferRelatedType Null
    FrozenArray < TypeWithExtendedAttributes > Null
    ObservableArray < TypeWithExtendedAttributes > Null
    RecordType Null
    undefined Null

PrimitiveType ::
    UnsignedIntegerType
    UnrestrictedFloatType
    boolean
    byte
    octet
    bigint

UnrestrictedFloatType ::
    unrestricted FloatType
    FloatType

FloatType ::
    float
    double

UnsignedIntegerType ::
    unsigned IntegerType
    IntegerType

IntegerType ::
    short
    long OptionalLong

OptionalLong ::
    long
    ε

StringType ::
    ByteString
    DOMString
    USVString

PromiseType ::
    Promise < Type >

RecordType ::
    record < StringType , TypeWithExtendedAttributes >

Null ::
    ?
    ε

BufferRelatedType ::
    ArrayBuffer
    SharedArrayBuffer
    DataView
    Int8Array
    Int16Array
    Int32Array
    Uint8Array
    Uint16Array
    Uint32Array
    Uint8ClampedArray
    BigInt64Array
    BigUint64Array
    Float16Array
    Float32Array
    Float64Array

ExtendedAttributeList ::
    [ ExtendedAttribute ExtendedAttributes ]
    ε

ExtendedAttributes ::
    , ExtendedAttribute ExtendedAttributes
    ε

ExtendedAttribute ::
    ( ExtendedAttributeInner ) ExtendedAttributeRest
    [ ExtendedAttributeInner ] ExtendedAttributeRest
    { ExtendedAttributeInner } ExtendedAttributeRest
    Other ExtendedAttributeRest

ExtendedAttributeRest ::
    ExtendedAttribute
    ε

ExtendedAttributeInner ::
    ( ExtendedAttributeInner ) ExtendedAttributeInner
    [ ExtendedAttributeInner ] ExtendedAttributeInner
    { ExtendedAttributeInner } ExtendedAttributeInner
    OtherOrComma ExtendedAttributeInner
    ε

Other ::
    integer
    decimal
    identifier
    string
    other
    -
    -Infinity
    .
    ...
    :
    ;
    <
    =
    >
    ?
    *
    ByteString
    DOMString
    FrozenArray
    Infinity
    NaN
    ObservableArray
    Promise
    USVString
    any
    bigint
    boolean
    byte
    double
    false
    float
    long
    null
    object
    octet
    or
    optional
    record
    sequence
    short
    symbol
    true
    unsigned
    undefined
    ArgumentNameKeyword
    BufferRelatedType

OtherOrComma ::
    Other
    ,

IdentifierList ::
    identifier Identifiers

Identifiers ::
    , identifier Identifiers
    ε

IntegerList ::
    integer Integers

Integers ::
    , integer Integers
    ε

ExtendedAttributeNoArgs ::
    identifier

ExtendedAttributeArgList ::
    identifier ( ArgumentList )

ExtendedAttributeIdent ::
    identifier = identifier

ExtendedAttributeString ::
    identifier = string

ExtendedAttributeInteger ::
    identifier = integer

ExtendedAttributeDecimal ::
    identifier = decimal

ExtendedAttributeWildcard ::
    identifier = *

ExtendedAttributeIdentList ::
    identifier = ( IdentifierList )

ExtendedAttributeIntegerList ::
    identifier = ( IntegerList )

ExtendedAttributeNamedArgList ::
    identifier = identifier ( ArgumentList )

注: Other 非終端記号は、 (, ), [, ], {, } および , を除く任意の単一終端記号にマッチします。

一方、ExtendedAttribute 非終端記号は、括弧、角括弧、波括弧がバランスしていて、, トークンがそのバランスした括弧内にのみ現れる限り、空でない終端記号の並びにマッチしますが、 そのような可能な並びのうち、 この仕様で定義されている 拡張属性 で使用されるものは一部のみです。 拡張属性で使用される構文については § 2.14 拡張属性 を参照してください。

文書の規約

本書では、以下の書式規約が使用されています。

本書のアルゴリズムでは、以下の規約が使用されています。

適合性

図、例、注記、および参考情報として明記されたセクションを除き、本仕様書のすべてが規範的です。

本仕様書は Infra Standard(基盤標準)に依存します。[INFRA]

本仕様書では、以下の適合クラスを定義します。

IDLフラグメントの適合セット

複数の IDLフラグメント の集合は、 この仕様書でIDLフラグメントに適用されるmust、required、およびshallレベルの基準をすべて満たす場合、 IDLフラグメントの適合セットとみなされます。

適合実装

ユーザーエージェントは、 適合実装 として、 IDLフラグメントの適合セットに対して、 ユーザーエージェントがサポートするすべての言語バインディングに関して、この仕様書のmust、required、およびshallレベルの基準をすべて満たす場合に該当します。

適合JavaScript実装

ユーザーエージェントは、 適合JavaScript実装 として、 IDLフラグメントの適合セットに対して、 JavaScript言語バインディングに関して、この仕様書のmust、required、およびshallレベルの基準をすべて満たす場合に該当します。

知的財産権

この現行標準には、W3Cの WebIDL [sic] Level 1 から複製された資料が含まれており、 W3C Software and Document Licenseの下で提供されています。

Copyright © WHATWG (Apple, Google, Mozilla, Microsoft)。この文書は クリエイティブ・コモンズ表示 4.0 国際ライセンス の下でライセンスされています。一部がソースコードに組み込まれる場合、その部分は BSD 3-Clause License の下でライセンスされます。

これは現行標準です。特許審査版については 現行標準審査ドラフトを参照してください。

索引

本仕様で定義されている用語

参照により定義される用語

参考文献

規範参考文献

[DOM]
Anne van Kesteren. DOM標準。現行標準。 URL: https://dom.spec.whatwg.org/
[ECMA-262]
ECMAScript言語仕様書。URL: https://tc39.es/ecma262/multipage/
[ECMA-402]
ECMAScript国際化API仕様書。URL: https://tc39.es/ecma402/
[HTML]
Anne van Kesteren; 他。HTML標準。 現行標準。URL: https://html.spec.whatwg.org/multipage/
[IEEE-754]
IEEE浮動小数点算術標準。2019年7月22日。URL: https://ieeexplore.ieee.org/document/8766229
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra標準。 現行標準。URL: https://infra.spec.whatwg.org/
[PERLRE]
Perl正規表現(Perl 5.8.8)。2006年2月。URL: http://search.cpan.org/dist/perl/pod/perlre.pod
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL標準。現行標準。URL: https://webidl.spec.whatwg.org/

参考情報文献

[API-DESIGN-PRINCIPLES]
Jeffrey Yasskin. Webプラットフォーム設計原則。URL: https://w3ctag.github.io/design-principles/
[CSS3-CONDITIONAL]
Chris Lilley; David Baron; Elika Etemad. CSS条件付き規則モジュール レベル3。URL: https://drafts.csswg.org/css-conditional-3/
[CSSOM]
Daniel Glazman; Emilio Cobos Álvarez. CSSオブジェクトモデル(CSSOM)。URL: https://drafts.csswg.org/cssom/
[FETCH]
Anne van Kesteren. Fetch標準。現行標準。 URL: https://fetch.spec.whatwg.org/
[INDEXEDDB]
Nikunj Mehta; 他。Indexed Database API。URL: https://w3c.github.io/IndexedDB/
[PROPOSAL-FLOAT16ARRAY]
JavaScriptにfloat16型付き配列追加提案。URL: https://tc39.es/proposal-float16array/
[SERVICE-WORKERS]
Monica CHINTALA; Yoshisato Yanagisawa. Service Workers Nightly. URL: https://w3c.github.io/ServiceWorker/
[STREAMS]
Adam Rice; 他。Streams標準。現行標準。URL: https://streams.spec.whatwg.org/
[WASM-JS-API-1]
Daniel Ehrenberg. WebAssembly JavaScriptインターフェース。URL: https://webassembly.github.io/spec/js-api/
[WASM-JS-API-2]
. Ms2ger; Ryan Hunt. WebAssembly JavaScriptインターフェース。URL: https://webassembly.github.io/spec/js-api/
[XML-NAMES]
Tim Bray; 他。Namespaces in XML 1.0(第3版)。2009年12月8日。REC。URL: https://www.w3.org/TR/xml-names/

IDL索引

[Exposed=*, Serializable]
interface QuotaExceededError : DOMException {
  constructor(optional DOMString message = "", optional QuotaExceededErrorOptions options = {});

  readonly attribute double? quota;
  readonly attribute double? requested;
};

dictionary QuotaExceededErrorOptions {
  double quota;
  double requested;
};

typedef (Int8Array or Int16Array or Int32Array or
         Uint8Array or Uint16Array or Uint32Array or Uint8ClampedArray or
         BigInt64Array or BigUint64Array or
         Float16Array or Float32Array or Float64Array or DataView) ArrayBufferView;

typedef (ArrayBuffer or ArrayBufferView) BufferSource;
typedef (ArrayBuffer or SharedArrayBuffer or [AllowShared] ArrayBufferView) AllowSharedBufferSource;
[Exposed=*,
 Serializable]
interface DOMException { // but see below note about JavaScript binding
  constructor(optional DOMString message = "", optional DOMString name = "Error");
  readonly attribute DOMString name;
  readonly attribute DOMString message;
  readonly attribute unsigned short code;

  const unsigned short INDEX_SIZE_ERR = 1;
  const unsigned short DOMSTRING_SIZE_ERR = 2;
  const unsigned short HIERARCHY_REQUEST_ERR = 3;
  const unsigned short WRONG_DOCUMENT_ERR = 4;
  const unsigned short INVALID_CHARACTER_ERR = 5;
  const unsigned short NO_DATA_ALLOWED_ERR = 6;
  const unsigned short NO_MODIFICATION_ALLOWED_ERR = 7;
  const unsigned short NOT_FOUND_ERR = 8;
  const unsigned short NOT_SUPPORTED_ERR = 9;
  const unsigned short INUSE_ATTRIBUTE_ERR = 10;
  const unsigned short INVALID_STATE_ERR = 11;
  const unsigned short SYNTAX_ERR = 12;
  const unsigned short INVALID_MODIFICATION_ERR = 13;
  const unsigned short NAMESPACE_ERR = 14;
  const unsigned short INVALID_ACCESS_ERR = 15;
  const unsigned short VALIDATION_ERR = 16;
  const unsigned short TYPE_MISMATCH_ERR = 17;
  const unsigned short SECURITY_ERR = 18;
  const unsigned short NETWORK_ERR = 19;
  const unsigned short ABORT_ERR = 20;
  const unsigned short URL_MISMATCH_ERR = 21;
  const unsigned short QUOTA_EXCEEDED_ERR = 22;
  const unsigned short TIMEOUT_ERR = 23;
  const unsigned short INVALID_NODE_TYPE_ERR = 24;
  const unsigned short DATA_CLONE_ERR = 25;
};

callback Function = any (any... arguments);
callback VoidFunction = undefined ();
✔MDN

DOMException/DOMException

In all current engines.

Firefox37+Safari10.1+Chrome46+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
✔MDN

DOMException/message

In all current engines.

Firefox1+Safari1+Chrome1+
Opera12.1+Edge79+
Edge (Legacy)12+IE9+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
✔MDN

DOMException/name

In all current engines.

Firefox1+Safari1+Chrome1+
Opera12.1+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
✔MDN

DOMException

In all current engines.

Firefox1+Safari1+Chrome1+
Opera12.1+Edge79+
Edge (Legacy)12+IE9+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile12.1+
Node.js17.0.0+