From 43818669f623f50cb9a81930fd335297ad5a5bb2 Mon Sep 17 00:00:00 2001 From: Anne van Kesteren Date: Mon, 16 Sep 2024 09:53:03 +0200 Subject: [PATCH] Review Draft Publication: September 2024 --- index.bs | 2 +- review-drafts/2024-09.bs | 15347 +++++++++++++++++++++++++++++++++++++ 2 files changed, 15348 insertions(+), 1 deletion(-) create mode 100644 review-drafts/2024-09.bs diff --git a/index.bs b/index.bs index aa214732..97bc1f6f 100644 --- a/index.bs +++ b/index.bs @@ -3,7 +3,7 @@ Group: WHATWG H1: Web IDL Shortname: webidl Text Macro: TWITTER webidl -Text Macro: LATESTRD 2024-03 +Text Macro: LATESTRD 2024-09 Abstract: This standard defines an interface definition language, Web IDL, that can be used to describe interfaces that Abstract: are intended to be implemented in web browsers. Translation: ja https://triple-underscore.github.io/WebIDL-ja.html diff --git a/review-drafts/2024-09.bs b/review-drafts/2024-09.bs new file mode 100644 index 00000000..57c398e1 --- /dev/null +++ b/review-drafts/2024-09.bs @@ -0,0 +1,15347 @@ +
+Group: WHATWG
+Status: RD
+Date: 2024-09-16
+H1: Web IDL
+Shortname: webidl
+Text Macro: TWITTER webidl
+Text Macro: LATESTRD 2024-09
+Abstract: This standard defines an interface definition language, Web IDL, that can be used to describe interfaces that
+Abstract: are intended to be implemented in web browsers.
+Translation: ja https://triple-underscore.github.io/WebIDL-ja.html
+Complain About: accidental-2119 no
+
+ + + +
+urlPrefix: https://tc39.es/ecma262/; spec: ecmascript
+    type: method; for: ECMAScript
+        text: JSON.stringify(); url: sec-json.stringify
+        text: %Array.prototype.entries%; url: sec-array.prototype.entries
+        text: %Array.prototype.forEach%; url: sec-array.prototype.foreach
+        text: %Array.prototype.keys%; url: sec-array.prototype.keys
+        text: %Array.prototype.values%; url: sec-array.prototype.values
+        text: %Promise.reject%; url: sec-promise.reject
+        text: %Promise.prototype.then%; url: sec-promise.prototype.then
+    type: argument
+        text: NewTarget; url: sec-built-in-function-objects
+    type: abstract-op
+        text: Completion; url: sec-completion-record-specification-type
+        text: IsInteger; url: sec-isinteger
+        text: Type; url: sec-ecmascript-data-types-and-values
+        text: abs; url: eqn-abs
+        text: floor; url: eqn-floor
+        text: max; url: eqn-max
+        text: min; url: eqn-min
+    type: dfn;
+        text: Abstract Closure; url: sec-abstract-closure
+        text: NumericLiteral; url: sec-literals-numeric-literals
+        text: modulo; url: eqn-modulo
+        url: sec-returnifabrupt-shorthands
+            text: !
+            text: ?
+        text: ECMA-262 Immutable Prototype Exotic Objects; url: sec-immutable-prototype-exotic-objects
+        text: abrupt completion; url: sec-completion-record-specification-type
+        text: array iterator object; url: sec-array-iterator-objects
+        text: built-in function object; url: sec-built-in-function-objects
+        text: callable; for: ECMAScript; url: sec-iscallable
+        text: Completion Record; url: sec-completion-record-specification-type
+        text: conventions; for: ECMAScript; url: sec-algorithm-conventions
+        text: current realm; url: current-realm
+        text: element; for: ECMAScript String; url: sec-ecmascript-language-types-string-type
+        text: enumerable; url: sec-property-attributes
+        text: equally close values; url: sec-ecmascript-language-types-number-type
+        text: error objects; for: ECMAScript; url: sec-error-objects
+        url: sec-object-internal-methods-and-internal-slots
+            text: internal method
+            text: internal slot
+        for: ordinary object; url: sec-ordinary-object-internal-methods-and-internal-slots
+            text: internal method
+            text: internal slot
+        text: own property; url: sec-own-property
+        text: PromiseCapability; url: sec-promisecapability-records
+        text: element size; url: table-the-typedarray-constructors
+urlPrefix: https://tc39.es/proposal-resizablearraybuffer/; spec: RESIZABLE-BUFFERS-PROPOSAL
+    type: abstract-op
+        text: IsResizableArrayBuffer; url: sec-isresizablearraybuffer
+
+ +
+{
+    "PROPOSAL-FLOAT16ARRAY": {
+        "publisher": "Ecma",
+        "href": "https://tc39.es/proposal-float16array/",
+        "title": "Proposal to add float16 TypedArrays to JavaScript"
+    }
+}
+
+ + + + +

Introduction

+ +This section is informative. + +This standard defines an interface definition language, Web IDL, that can be used to describe +interfaces that are intended to be implemented in web browsers. Web IDL is an IDL variant with a +number of features that allow the behavior of common script objects in the web platform to be +specified more readily. How interfaces described with Web IDL correspond to constructs within +JavaScript execution environments is also detailed here. + +Concretely, Web IDL provides a syntax for specifying the surface APIs of web platform objects, as +well as JavaScript bindings that detail how those APIs manifest as JavaScript constructs. This +ensures common tasks, such as installing global properties, processing numeric inputs, or exposing +iteration behavior, remain uniform across web platform specifications: such specifications describe +their interfaces using Web IDL, and then use prose to specify API-specific details. + +

The term "JavaScript" is used to refer to ECMA-262, rather than the official term ECMAScript, since the term JavaScript is more widely known.

+ + +

Interface definition language

+ +This section describes a language, Web IDL, which can be used to define +interfaces for APIs in the Web platform. A specification that defines Web APIs +can include one or more IDL fragments that +describe the interfaces (the state and behavior that objects can exhibit) +for the APIs defined by that specification. +An [=IDL fragment=] is +a sequence of definitions that matches the Definitions grammar symbol. +The set of [=IDL fragments=] that +an implementation supports is not ordered. +See [[#idl-grammar]] for the complete grammar and an explanation of the notation used. + +The different kinds of definitions that can appear in an +[=IDL fragment=] are: +[=interfaces=], +[=partial interface|partial interface definitions=], +[=interface mixins=], +[=partial interface mixin|partial mixin definitions=], +[=callback functions=], +[=callback interfaces=], +[=namespaces=], +[=partial namespace|partial namespace definitions=], +[=dictionary|dictionaries=], +[=partial dictionary|partial dictionary definitions=], +[=typedefs=] and +[=includes statements=]. +These are all defined in the following sections. + +Each [=definition=] +(matching Definition) +can be preceded by a list of [=extended attributes=] (matching +ExtendedAttributeList), +which can control how the definition will be handled in language bindings. +The extended attributes defined by this specification that are language binding +agnostic are discussed in [[#idl-extended-attributes]], +while those specific to the JavaScript language binding are discussed +in [[#js-extended-attributes]]. + +
+    [extended_attributes]
+    interface identifier {
+      /* interface_members... */
+    };
+
+ +
+    Definitions :
+        ExtendedAttributeList Definition Definitions
+        ε
+
+ +
+    Definition :
+        CallbackOrInterfaceOrMixin
+        Namespace
+        Partial
+        Dictionary
+        Enum
+        Typedef
+        IncludesStatement
+
+ +
+ + The following is an example of an [=IDL fragment=]. + +
+        [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);
+        };
+    
+ + Here, four [=interfaces=] + are being defined. + The GraphicalWindow interface has two + [=read only=] [=attributes=], + one writable attribute, and two [=operations=] + defined on it. Objects that implement the GraphicalWindow interface + will expose these attributes and operations in a manner appropriate to the + particular language being used. + + In JavaScript, the attributes on the IDL interfaces will be exposed as accessor + properties and the operations as data properties whose value is a [=built-in function object=] on a + prototype object for all GraphicalWindow + objects; each JavaScript object that implements GraphicalWindow + will have that prototype object in its prototype chain. + + The [=constructor operation=] that appears on GraphicalWindow + causes a [=constructor=] to exist in JavaScript implementations, + so that calling new GraphicalWindow() would return a new object + that implemented the interface. + + All [=interfaces=] have the [{{Exposed}}] [=extended attribute=], which ensures the interfaces + are only available in [=realms=] whose [=realm/global object=] is a {{Window}} object. +
+ + +

Names

+ +Every [=interface=], +[=partial interface|partial interface definition=], +[=namespace=], +[=partial namespace|partial namespace definition=], +[=dictionary=], +[=partial dictionary|partial dictionary definition=], +[=enumeration=], +[=callback function=], +[=callback interface=] and +[=typedef=] (together called named definitions) +and every [=constant=], +[=attribute=], +and [=dictionary member=] has an +identifier, as do some +[=operations=]. +The identifier is determined by an +identifier token somewhere +in the declaration: + +* For [=named definitions=], + the identifier token that appears + directly after the interface, namespace, + dictionary, enum + or callback keyword + determines the identifier of that definition. +
+        interface interface_identifier { /* interface_members... */ };
+        partial interface interface_identifier { /* interface_members... */ };
+        namespace namespace_identifier { /* namespace_members... */ };
+        partial namespace namespace_identifier { /* namespace_members... */ };
+        dictionary dictionary_identifier { /* dictionary_members... */ };
+        partial dictionary dictionary_identifier { /* dictionary_members... */ };
+        enum enumeration_identifier { "enum", "values" /* , ... */ };
+        callback callback_identifier = return_type (/* arguments... */);
+        callback interface callback_interface_identifier { /* interface_members... */ };
+    
+* For [=attributes=], + [=typedefs=] + and [=dictionary members=], + the final identifier token before the + semicolon at the end of the declaration determines the identifier. +
+        [extended_attributes]
+        interface identifier {
+          attribute type attribute_identifier;
+        };
+
+        typedef type typedef_identifier;
+
+        dictionary identifier {
+          type dictionary_member_identifier;
+        };
+    
+* For [=constants=], + the identifier token before the + equals sign determines the identifier. +
const type constant_identifier = 42;
+* For [=operations=], the + identifier token that appears + after the return type but before the opening parenthesis (that is, + one that is matched as part of the OptionalOperationName + grammar symbol in an OperationRest) determines the identifier of the operation. If + there is no such identifier token, + then the operation does not have an identifier. +
+        interface interface_identifier {
+          return_type operation_identifier(/* arguments... */);
+        };
+    
+ +Note: Operations can have no identifier when they are being used to declare a +[=special operation|special kind of operation=], such as a getter or setter. + +For all of these constructs, the [=identifier=] +is the value of the identifier token with any leading +U+005F (_) removed. + +Note: A leading U+005F (_) is used to escape an identifier from looking +like a reserved word so that, for example, an interface named "interface" can be +defined. The leading U+005F (_) is dropped to unescape the +identifier. + +Operation arguments can take a slightly wider set of identifiers. In an operation +declaration, the identifier of an argument is specified immediately after its +type and is given by either an identifier +token or by one of the keywords that match the ArgumentNameKeyword +symbol. If one of these keywords is used, it need not be escaped with a leading +underscore. + +
+    interface interface_identifier {
+      return_type operation_identifier(argument_type argument_identifier /* , ... */);
+    };
+
+ +
+    ArgumentNameKeyword :
+        "async"
+        "attribute"
+        "callback"
+        "const"
+        "constructor"
+        "deleter"
+        "dictionary"
+        "enum"
+        "getter"
+        "includes"
+        "inherit"
+        "interface"
+        "iterable"
+        "maplike"
+        "mixin"
+        "namespace"
+        "partial"
+        "readonly"
+        "required"
+        "setlike"
+        "setter"
+        "static"
+        "stringifier"
+        "typedef"
+        "unrestricted"
+
+ +If an identifier token is used, then the +[=identifier=] of the operation argument +is the value of that token with any leading +U+005F (_) removed. +If instead one of the ArgumentNameKeyword +keyword token is used, then the [=identifier=] of the operation argument +is simply that token. + +The [=identifier=] of any of the abovementioned +IDL constructs (except operation arguments) must not be "constructor", +"toString", +or begin with a U+005F (_). These +are known as reserved identifiers. + +Although the "toJSON" [=identifier=] is not a [=reserved identifier=], +it must only be used for [=regular operations=] +that convert objects to [=JSON types=], +as described in [[#idl-tojson-operation]]. + +Note: Further restrictions on identifier names for particular constructs can be made +in later sections. + +Within the set of [=IDL fragments=] +that a given implementation supports, +the [=identifier=] of every +[=interface=], +[=namespace=], +[=dictionary=], +[=enumeration=], +[=callback function=], +[=callback interface=] and +[=typedef=] +must not +be the same as the identifier of any other +[=interface=], +[=namespace=], +[=dictionary=], +[=enumeration=], +[=callback function=], +[=callback interface=] or +[=typedef=]. + +Within an [=IDL fragment=], a reference +to a [=definition=] need not appear after +the declaration of the referenced definition. References can also be made +across [=IDL fragments=]. + +
+ + Therefore, the following [=IDL fragment=] is valid: + +
+        [Exposed=Window]
+        interface B : A {
+          undefined f(SequenceOfLongs x);
+        };
+
+        [Exposed=Window]
+        interface A {
+        };
+
+        typedef sequence<long> SequenceOfLongs;
+    
+
+ +
+ + The following [=IDL fragment=] + demonstrates how [=identifiers=] + are given to definitions and [=interface members=]. + +
+        // Typedef identifier: "number"
+        typedef double number;
+
+        // Interface identifier: "System"
+        [Exposed=Window]
+        interface System {
+
+          // Operation identifier:          "createObject"
+          // Operation argument identifier: "interface"
+          object createObject(DOMString _interface);
+
+          // Operation argument identifier: "interface"
+          sequence<object> getObjects(DOMString interface);
+
+          // Operation has no identifier; it declares a getter.
+          getter DOMString (DOMString keyName);
+        };
+
+        // Interface identifier: "TextField"
+        [Exposed=Window]
+        interface TextField {
+
+          // Attribute identifier: "const"
+          attribute boolean _const;
+
+          // Attribute identifier: "value"
+          attribute DOMString? _value;
+        };
+    
+ + Note that while the second [=attribute=] + on the TextField [=interface=] + need not have been escaped with an underscore (because "value" is + not a keyword in the IDL grammar), it is still unescaped + to obtain the attribute's [=identifier=]. + +
+ + +

Interfaces

+ +[=IDL fragments=] are used to +describe object oriented systems. In such systems, objects are entities +that have identity and which are encapsulations of state and behavior. +An interface is a definition (matching +interface InterfaceRest) that declares some +state and behavior that an object implementing that interface will expose. + +
+    [extended_attributes]
+    interface identifier {
+      /* interface_members... */
+    };
+
+ +An interface is a specification of a set of +interface members +(matching InterfaceMembers). +These are the [=members=] that appear between the braces in the interface declaration. + +Interfaces in Web IDL describe how objects that implement the +interface behave. In bindings for object oriented languages, it is +expected that an object that implements a particular IDL interface +provides ways to inspect and modify the object's state and to +invoke the behavior described by the interface. + +An interface can be defined to inherit from another interface. +If the identifier of the interface is followed by a +U+003A (:) +and an [=identifier=], +then that identifier identifies the inherited interface. +An object that implements an interface that inherits from another +also implements that inherited interface. The object therefore will also +have members that correspond to the interface members from the inherited interface. + +
+    interface identifier : identifier_of_inherited_interface {
+      /* interface_members... */
+    };
+
+ +The order that members appear in has significance for property enumeration in the JavaScript binding. + +Interfaces may specify an interface member that has the same name as +one from an inherited interface. Objects that implement the derived +interface will expose the member on the derived interface. It is +language binding specific whether the overridden member can be +accessed on the object. + +
+ + Consider the following two interfaces. + +
+        [Exposed=Window]
+        interface A {
+          undefined f();
+          undefined g();
+        };
+
+        [Exposed=Window]
+        interface B : A {
+          undefined f();
+          undefined g(DOMString x);
+        };
+    
+ + In the JavaScript language binding, an instance of B + will have a prototype chain that looks like the following: + +
+        [Object.prototype: the Object prototype object]
+             ↑
+        [A.prototype: interface prototype object for A]
+             ↑
+        [B.prototype: interface prototype object for B]
+             ↑
+        [instanceOfB]
+    
+ + Calling instanceOfB.f() in JavaScript will invoke the f defined + on B. However, the f from A + can still be invoked on an object that implements B by + calling A.prototype.f.call(instanceOfB). + +
+ +The inherited interfaces of +a given interface |A| is the set of all interfaces that |A| +inherits from, directly or indirectly. If |A| does not [=interface/inherit=] +from another interface, then the set is empty. Otherwise, the set +includes the interface |B| that |A| [=interface/inherits=] +from and all of |B|'s [=inherited interfaces=]. + +An interface must not be declared such that +its inheritance hierarchy has a cycle. That is, an interface +|A| cannot inherit from itself, nor can it inherit from another +interface |B| that inherits from |A|, and so on. + +
+ The [=list=] of inclusive inherited interfaces of an [=interface=] |I| + is defined as follows: + + 1. Let |result| be « ». + 1. Let |interface| be |I|. + 1. While |interface| is not null: + 1. [=list/Append=] |interface| to |result|. + 1. Set |interface| to the [=interface=] that |I| [=interface/inherits=] from, if any, and + null otherwise. + 1. Return |result|. +
+ +Note that general multiple inheritance of interfaces is not supported, and +objects also cannot implement arbitrary sets of interfaces. +Objects can be defined to implement a single given interface |A|, +which means that it also implements all of |A|'s [=inherited interfaces=]. +In addition, an [=includes statement=] can be used +to define that objects implementing an [=interface=] |A| +will always also include the [=interface mixin member|members=] +of the [=interface mixins=] |A| [=includes=]. + +Each interface member can be preceded by a list of [=extended attributes=] (matching +ExtendedAttributeList), +which can control how the interface member will be handled in language bindings. + +
+    [extended_attributes]
+    interface identifier {
+
+      [extended_attributes]
+      const type constant_identifier = 42;
+
+      [extended_attributes]
+      attribute type identifier;
+
+      [extended_attributes]
+      return_type identifier(/* arguments... */);
+    };
+
+ +The IDL for interfaces can be split into multiple parts by using +partial interface definitions +(matching partial interface +PartialInterfaceRest). +The [=identifier=] of a partial +interface definition must be the same +as the identifier of an interface definition. All of +the members that appear on each of the partial interfaces are considered to be +members of the interface itself. + +
+    interface SomeInterface {
+      /* interface_members... */
+    };
+
+    partial interface SomeInterface {
+      /* interface_members... */
+    };
+
+ +Note: Partial interface definitions are intended for use as a specification +editorial aide, allowing the definition of an interface to be separated +over more than one section of the document, and sometimes multiple documents. + +The order of appearance of an [=interface=] +definition and any of its [=partial interface=] +definitions does not matter. + +Note: A partial interface definition cannot specify that the interface +[=interface/inherits=] from another interface. +Inheritance is to be specified on the original [=interface=] +definition. + +The relevant language binding determines how interfaces correspond to constructs +in the language. + +The following extended attributes are applicable to interfaces: +[{{CrossOriginIsolated}}], +[{{Exposed}}], +[{{Global}}], +[{{LegacyFactoryFunction}}], +[{{LegacyNoInterfaceObject}}], +[{{LegacyOverrideBuiltIns}}], +[{{LegacyWindowAlias}}], and +[{{SecureContext}}]. + +The following extended attributes are applicable to [=partial interfaces=]: +[{{CrossOriginIsolated}}], +[{{Exposed}}], +[{{LegacyOverrideBuiltIns}}], and +[{{SecureContext}}]. + +[=Interfaces=] must be annotated with an [{{Exposed}}] [=extended attribute=]. + +
+ +The qualified name of an [=interface=] |interface| is defined as follows: + +1. Let |identifier| be the [=identifier=] of |interface|. +1. If |interface| has a [{{LegacyNamespace}}] [=extended attribute=], then: + 1. Let |namespace| be the identifier argument of the [{{LegacyNamespace}}] + [=extended attribute=]. + 1. Return the [=concatenation=] of « |namespace|, |identifier| » with + separator U+002E (.). +1. Return |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
+        ε
+
+ +
+ + The following [=IDL fragment=] + demonstrates the definition of two mutually referential [=interfaces=]. + Both Human and Dog + inherit from Animal. Objects that implement + either of those two interfaces will thus have a name attribute. + +
+        [Exposed=Window]
+        interface Animal {
+          attribute DOMString name;
+        };
+
+        [Exposed=Window]
+        interface Human : Animal {
+          attribute Dog? pet;
+        };
+
+        [Exposed=Window]
+        interface Dog : Animal {
+          attribute Human? owner;
+        };
+    
+
+ +
+ + The following [=IDL fragment=] defines + simplified versions of a DOM [=interfaces=] + and a [=callback interface=]. + +
+        [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);
+        };
+    
+ + Plain objects can implement a [=callback interface=] like + EventListener: + +
+        var node = getNode();                                // Obtain an instance of Node.
+
+        var listener = {
+          handleEvent: function(event) {
+            // ...
+          }
+        };
+        node.addEventListener("click", listener);            // This works.
+
+        node.addEventListener("click", function() { ... });  // As does this.
+    
+ + It is not possible for such an object to implement an [=interface=] like + Node, however: + +
+        var node = getNode();  // Obtain an instance of Node.
+
+        var newNode = {
+          nodeName: "span",
+          parentNode: null,
+          appendChild: function(newchild) {
+            // ...
+          },
+          addEventListener: function(type, listener) {
+            // ...
+          }
+        };
+        node.appendChild(newNode);  // This will throw a TypeError exception.
+    
+
+ + +

Interface mixins

+ +An interface mixin is a definition (matching interface MixinRest) +that declares state and behavior that can be [=included=] by one or more [=interfaces=], +and that are exposed by objects that implement an [=interface=] +that [=includes=] the [=interface mixin=]. + +
+    interface mixin identifier {
+      /* mixin_members... */
+    };
+
+ +Note: [=Interface mixins=], much like [=partial interfaces=], +are intended for use as a specification editorial aide, +allowing a coherent set of functionalities to be grouped together, +and included in multiple interfaces, possibly across documents. +They are not meant to be exposed through language bindings. +Guidance on when to choose [=partial interfaces=], [=interface mixins=], +or [=partial interface mixins=] can be found in [[#using-mixins-and-partials]]. + +An [=interface mixin=] is a specification of a set of interface mixin members +(matching MixinMembers), +which are the [=constants=], [=regular operations=], [=regular attributes=], and [=stringifiers=] +that appear between the braces in the [=interface mixin=] declaration. + +These [=constants=], [=regular operations=], [=regular attributes=], and [=stringifiers=] +describe the behaviors that can be implemented by an object, +as if they were specified on the [=interface=] that [=includes=] them. + +[=Static attributes=], [=static operations=], [=special operations=], and +[=iterable declaration|iterable=], [=asynchronously iterable declaration|asynchronously iterable=], +[=maplike declaration|maplike=], and [=setlike declarations=] cannot appear in [=interface mixin=] +declarations. + +As with interfaces, the IDL for [=interface mixins=] can be split into multiple parts by using +partial interface mixin definitions +(matching partial interface MixinRest). +The [=identifier=] of a [=partial interface mixin=] [=definition=] must +be the same as the [=identifier=] of an [=interface mixin=] [=definition=]. +All of the [=interface mixin member|members=] that appear on each of the [=partial interface mixin=] [=definitions=] +are considered to be [=members=] of the [=interface mixin=] itself, +and—by extension—of the [=interfaces=] that [=include=] the [=interface mixin=]. + +
+    interface mixin SomeMixin {
+      /* mixin_members... */
+    };
+
+    partial interface mixin SomeMixin {
+      /* mixin_members... */
+    };
+
+ +The order that members appear in has significance for property enumeration +in the JavaScript binding. + +Note that unlike [=interfaces=] or [=dictionaries=], [=interface mixins=] do not create types. + +Of the extended attributes defined in this specification, +only the [{{CrossOriginIsolated}}], [{{Exposed}}], and [{{SecureContext}}] extended attributes +are applicable to [=interface mixins=]. + +An includes statement is a definition +(matching IncludesStatement) +used to declare that all objects implementing an [=interface=] |I| +(identified by the first [=identifier=]) +must additionally include the [=interface mixin member|members=] of [=interface mixin=] |M| +(identified by the second identifier). +[=Interface=] |I| is said to include +[=interface mixin=] |M|. + +
+    interface_identifier includes mixin_identifier;
+
+ +The first [=identifier=] must reference a [=interface=] |I|. +The second identifier must reference an [=interface mixin=] |M|. + +Each [=interface mixin member|member=] of |M| is considered to be +a [=member=] of each [=interface=] |I|, |J|, |K|, … that [=includes=] |M|, +as if a copy of each [=interface mixin member|member=] had been made. +So for a given member m of |M|, +interface |I| is considered to have a [=member=] mI, +interface |J| is considered to have a [=member=] mJ, +interface |K| is considered to have a [=member=] mK, and so on. +The host interfaces of mI, mJ, +and mK, are |I|, |J|, and |K| respectively. + +Note: In JavaScript, this implies that each [=regular operation=] +declared as a [=interface mixin member|member=] of [=interface mixin=] |M|, +and exposed as a data property with a [=built-in function object=] value, +is a distinct [=built-in function object=] +in each [=interface prototype object=] +whose associated [=interface=] [=includes=] |M|. +Similarly, for [=attributes=], each copy of the accessor property has +distinct [=built-in function objects=] for its getters and setters. + +The order of appearance of [=includes statements=] affects the order in which [=interface mixin=] +are [=included=] by their [=host interface=]. + +Issue: [=interface mixin member|Member=] order isn't clearly specified, +in particular when [=interface mixins=] are defined in separate documents. +It is discussed in issue #432. + +No [=extended attributes=] defined in this specification are applicable to [=includes statements=]. + +
+ + The following [=IDL fragment=] defines an [=interface=], Entry, + and an [=interface mixin=], Observable. + The [=includes statement=] specifies that + Observable's [=interface mixin member|members=] + are always included on objects implementing Entry. + +
+        interface Entry {
+          readonly attribute unsigned short entryType;
+          // ...
+        };
+
+        interface mixin Observable {
+          undefined addEventListener(DOMString type,
+                                EventListener listener,
+                                boolean useCapture);
+          // ...
+        };
+
+        Entry includes Observable;
+    
+ + A JavaScript implementation would thus have an addEventListener + property in the prototype chain of every Entry: + +
+        var e = getEntry();          // Obtain an instance of Entry.
+        typeof e.addEventListener;   // Evaluates to "function".
+    
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+    MixinRest :
+        "mixin" identifier "{" MixinMembers "}" ";"
+
+ +
+    MixinMembers :
+        ExtendedAttributeList MixinMember MixinMembers
+        ε
+
+ +
+    MixinMember :
+        Const
+        RegularOperation
+        Stringifier
+        OptionalReadOnly AttributeRest
+
+ +
+    IncludesStatement :
+        identifier "includes" identifier ";"
+
+ +

Using mixins and partials

+ +This section is informative. + +[=Interface mixins=] allow the sharing of [=attributes=], [=constants=], and [=operations=] +across multiple [=interfaces=]. +If you're only planning to extend a single interface, +you might consider using a [=partial interface=] instead. + +For example, instead of: + +
+    interface mixin WindowSessionStorage {
+      readonly attribute Storage sessionStorage;
+    };
+    Window includes WindowSessionStorage;
+
+ +do: + +
+    partial interface Window {
+      readonly attribute Storage sessionStorage;
+    };
+
+ +Additionally, you can rely on extending [=interface mixins=] exposed by other specifications +to target common use cases, such as [=exposed|exposing=] +a set of [=attributes=], [=constants=], or [=operations=] +across both window and worker contexts. + +For example, instead of the common but verbose: + +
+    interface mixin GlobalCrypto {
+      readonly attribute Crypto crypto;
+    };
+
+    Window includes GlobalCrypto;
+    WorkerGlobalScope includes GlobalCrypto;
+
+ +you can extend the {{WindowOrWorkerGlobalScope}} [=interface mixin=] using a [=partial interface mixin=]: + +
+    partial interface mixin WindowOrWorkerGlobalScope {
+      readonly attribute Crypto crypto;
+    };
+
+ + +

Callback interfaces

+ +A callback interface is a [=definition=] matching +callback interface +identifier { +CallbackInterfaceMembers +} ;. +It can be implemented by any object, as described in [[#idl-objects]]. + +Note: A [=callback interface=] is not an [=interface=]. The name and syntax are left over from +earlier versions of this standard, where these concepts had more in common. + +A [=callback interface=] is a specification of a set of +callback interface members +(matching CallbackInterfaceMembers). +These are the [=members=] that appear between the braces in the interface declaration. + +
+    callback interface identifier {
+      /* interface_members... */
+    };
+
+ +Note: See also the similarly named [=callback function=] definition. + +[=Callback interfaces=] must define exactly one [=regular operation=]. + +
+ + Specification authors should not define + [=callback interfaces=] + unless required to describe the requirements of existing APIs. + Instead, a [=callback function=] should be used. + + The definition of {{EventListener}} as a + [=callback interface=] + is an example of an existing API that needs to allow + objects with a + given property (in this case handleEvent) to be considered to implement the interface. + For new APIs, and those for which there are no compatibility concerns, + using a [=callback function=] will allow + only a [=function object=] (in the JavaScript + language binding). + +
+ +[=Callback interfaces=] which declare [=constants=] +must be annotated with an [{{Exposed}}] [=extended attribute=]. + + +
+    CallbackRestOrInterface :
+        CallbackRest
+        "interface" identifier "{" CallbackInterfaceMembers "}" ";"
+
+ +
+    CallbackInterfaceMembers :
+        ExtendedAttributeList CallbackInterfaceMember CallbackInterfaceMembers
+        ε
+
+ +
+    CallbackInterfaceMember :
+        Const
+        RegularOperation
+
+ + +

Members

+ +[=Interfaces=], [=interface mixins=], and [=namespaces=] are specifications of a set of +members (respectively matching +InterfaceMembers, +MixinMembers, and +NamespaceMembers), +which are the [=constants=], [=attributes=], [=operations=], and +other declarations that appear between the braces of their declarations. +[=Attributes=] describe the state that an object +implementing the [=interface=], [=interface mixin=], or [=namespace=] will expose, +and [=operations=] describe the behaviors that can be invoked on the object. +[=Constants=] declare named constant values +that are exposed as a convenience to users of objects in the system. + +
+ + When an [=interface=] [=includes=] an [=interface mixin=], each [=member=] + of the interface mixin is also considered a member of the interface. In contrast, + [=interface/inherit|inherited=] interface members are not considered members + of the interface. + +
+ +The [=constructor steps=], [=getter steps=], [=setter steps=], and [=method steps=] for the various +[=members=] defined on an [=interface=] or [=interface mixin=] have access to a +this value, which is an IDL value of the [=interface=] type that the member is +declared on or that [=includes=] the [=interface mixin=] the member is declared on. + +[=Setter steps=] also have access to the given value, +which is an IDL value of the type the [=attribute=] is declared as. + +[=Interfaces=], [=interface mixins=], [=callback interfaces=] and [=namespaces=] each support a +different set of [=members=], +which are specified in [[#idl-interfaces]], [[#idl-interface-mixins]], +[[#idl-callback-interfaces]], and [[#idl-namespaces]], +and summarized in the following informative table: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
[=Interfaces=][=Callback interfaces=][=Interface mixins=][=Namespaces=]
[=Constants=]
[=Regular attributes=]Only [=read only=] attributes
[=Static attributes=]
[=Regular Operations=]
[=Stringifiers=]
[=Special Operations=]
[=Static Operations=]
[=Iterable declarations=]
[=Asynchronously iterable declarations=]
[=Maplike declarations=]
[=Setlike declarations=]
+ +

Constants

+ +A constant is a declaration (matching +Const) used to bind a constant value to a name. +Constants can appear on [=interfaces=] and [=callback interfaces=]. + +

+ Constants have in the past primarily been used to define + named integer codes in the style of an enumeration. The Web platform + is moving away from this design pattern in favor of the use of strings. + Editors who wish to use this feature are strongly advised to discuss this + by filing an issue + before proceeding. +

+ +
const type constant_identifier = 42;
+ +The [=identifier=] of a +[=constant=] +must not be the same as the identifier +of another [=interface member=] or [=callback interface member=] +defined on the same [=interface=] or [=callback interface=]. +The identifier also must not +be "length", "name" or "prototype". + +Note: These three names are the names of properties that are defined on the +[=interface object=] in the JavaScript language binding. + +The type of a constant (matching ConstType) +must not be any type other than +a [=primitive type=]. +If an [=identifier=] is used, +it must reference a [=typedef=] +whose type is a primitive type. + +The ConstValue part of a +constant declaration gives the value of the constant, which can be +one of the two boolean literal tokens (true +and false), an +integer token, +a decimal token, +or one of the three special floating point constant values +(-Infinity, Infinity and NaN). + +Note: These values – in addition to strings and the empty sequence – can also be used to specify the +[=dictionary member/default value|default value of a dictionary member=] or +of an optional argument. +Note that strings, the +empty sequence [], and the default dictionary {} cannot be used as the value of a +[=constant=]. + +The value of the boolean literal tokens true and +false are the IDL {{boolean}} values +true and false. + +
+ + The value of an integer token + is an integer whose value is determined as follows: + + 1. Let |S| be the sequence of [=scalar values=] matched by the integer token. + 1. Let |sign| be −1 if |S| begins with U+002D (-), and 1 otherwise. + 1. Let |base| be the base of the number based on the [=scalar values=] that follow the optional leading U+002D (-): +
+ : U+0030 (0), U+0058 (X) + : U+0030 (0), U+0078 (x) + :: The base is 16. + : U+0030 (0) + :: The base is 8. + : Otherwise + :: The base is 10. +
+ 1. Let |number| be the result of interpreting all remaining [=scalar values=] following the optional leading U+002D (-) + character and any [=scalar values=] indicating the base as an integer specified in base |base|. + 1. Return |sign| × |number|. +
+ +The type of an integer token is the same +as the type of the constant, dictionary member or optional argument it is being used as the value of. +The value of the integer token must not +lie outside the valid range of values for its type, as given in +[[#idl-types]]. + +
+ The value of a decimal token is + either an IEEE 754 single-precision floating point number or an IEEE 754 + double-precision floating point number, depending on the type of the + constant, dictionary member or optional argument it is being used as the value for, determined as follows: + + 1. Let |S| be the sequence of [=scalar values=] matched by the + decimal token. + 1. Let |result| be the Mathematical Value that would be obtained if + |S| were parsed as a JavaScript [=NumericLiteral=]. + 1. If the decimal token is being + used as the value for a {{float}} or {{unrestricted float}}, then + the value of the decimal token + is the IEEE 754 single-precision floating point number closest to |result|. + 1. Otherwise, the decimal token is being + used as the value for a {{double}} or {{unrestricted double}}, and + the value of the decimal token + is the IEEE 754 double-precision floating point number closest to |result|. [[!IEEE-754]] +
+ +The value of a constant value specified as +Infinity, -Infinity, or NaN is either +an IEEE 754 single-precision floating point number or an IEEE 754 +double-precision floating point number, depending on the type of the +constant, dictionary member, or optional argument it is being used as the +value for: + +
+ : Type {{unrestricted float}}, constant value Infinity + :: The value is the IEEE 754 single-precision positive infinity value. + : Type {{unrestricted double}}, constant value Infinity + :: The value is the IEEE 754 double-precision positive infinity value. + : Type {{unrestricted float}}, constant value -Infinity + :: The value is the IEEE 754 single-precision negative infinity value. + : Type {{unrestricted double}}, constant value -Infinity + :: The value is the IEEE 754 double-precision negative infinity value. + : Type {{unrestricted float}}, constant value NaN + :: The value is the IEEE 754 single-precision NaN value with the bit pattern 0x7fc00000. + : Type {{unrestricted double}}, constant value NaN + :: The value is the IEEE 754 double-precision NaN value with the bit pattern 0x7ff8000000000000. +
+ +The type of a decimal token is the same +as the type of the constant, dictionary member or optional argument it is being used as the value of. +The value of the decimal token must not +lie outside the valid range of values for its type, as given in [[#idl-types]]. +Also, Infinity, -Infinity and NaN must not +be used as the value of a {{float}} or {{double}}. + +The value of the null token is the special +null value that is a member of the +[=nullable types=]. The type of +the null token is the same as the +type of the constant, dictionary member or optional argument it is being used as the value of. + +If |VT| is the type of the value assigned to a constant, and |DT| +is the type of the constant, dictionary member or optional argument itself, then these types must +be compatible, which is the case if |DT| and |VT| are identical, +or |DT| is a [=nullable type=] +whose [=nullable types/inner type=] is |VT|. + +[=Constants=] are not associated with +particular instances of the [=interface=] or [=callback interface=] +on which they appear. It is language binding specific whether +[=constants=] are exposed on instances. + +
+ + The JavaScript language binding does however + allow [=constants=] to be accessed + through objects implementing the IDL [=interfaces=] + on which the [=constants=] are declared. + For example, with the following IDL: + +
+        [Exposed=Window]
+        interface A {
+          const short rambaldi = 47;
+        };
+    
+ + the constant value can be accessed in JavaScript either as + A.rambaldi or instanceOfA.rambaldi. + +
+ +The following extended attributes are applicable to constants: +[{{CrossOriginIsolated}}], +[{{Exposed}}], and +[{{SecureContext}}]. + +
+    Const :
+        "const" ConstType identifier "=" ConstValue ";"
+
+ +
+    ConstValue :
+        BooleanLiteral
+        FloatLiteral
+        integer
+
+ +
+    BooleanLiteral :
+        "true"
+        "false"
+
+ +
+    FloatLiteral :
+        decimal
+        "-Infinity"
+        "Infinity"
+        "NaN"
+
+ +
+    ConstType :
+        PrimitiveType
+        identifier
+
+ +
+ + The following [=IDL fragment=] + demonstrates how [=constants=] + of the above types can be defined. + +
+        [Exposed=Window]
+        interface Util {
+          const boolean DEBUG = false;
+          const octet LF = 10;
+          const unsigned long BIT_MASK = 0x0000fc00;
+          const double AVOGADRO = 6.022e23;
+        };
+    
+
+ + +

Attributes

+ +An attribute is an [=interface member=] or [=namespace member=] +(matching +inherit AttributeRest, +static OptionalReadOnly AttributeRest, +stringifier OptionalReadOnly AttributeRest, +OptionalReadOnly AttributeRest, +or AttributeRest) +that is used to declare data fields with a given type and +[=identifier=] whose value can +be retrieved and (in some cases) changed. There are two kinds of attributes: + +1. [=regular attributes=], which are those + used to declare that objects implementing the [=interface=] + will have a data field member with the given [=identifier=] +
+        interface interface_identifier {
+          attribute type identifier;
+        };
+    
+1. [=static attributes=], which are used + to declare attributes that are not associated with a particular object implementing the interface +
+        interface interface_identifier {
+          static attribute type identifier;
+        };
+    
+ +If an attribute has no static keyword, then it declares a +regular attribute. Otherwise, +it declares a [=static attribute=]. Note that in addition to being [=interface members=], +[=read only=] [=regular attributes=] can be [=namespace members=] as well. + +The getter steps of an attribute |attr| should be introduced using text of the form “The +|attr| getter steps are:” followed by a list, or “The |attr| getter steps +are to” followed by an inline description. + +The setter steps of an attribute |attr| should be introduced using text of the form “The +|attr| setter steps are:” followed by a list, or “The |attr| setter steps +are to” followed by an inline description. + +Note: When defining [=getter steps=], you implicitly have access to [=this=]. +When defining [=setter steps=], you implicitly have access to [=this=] and +[=the given value=]. + +The [=identifier=] of an +[=attribute=] +must not be the same as the identifier +of another [=interface member=] +defined on the same [=interface=]. +The identifier of a static attribute must not +be "prototype". + +The type of the attribute is given by the type (matching Type) +that appears after the attribute keyword. +If the Type is an +[=identifier=] or an identifier followed by ?, +then the identifier must +identify an [=interface=], [=enumeration=], +[=callback function=], [=callback interface=] or [=typedef=]. + +The type of the attribute, after resolving typedefs, must not be a +[=nullable type|nullable=] or non-nullable version of any of the following types: + +* a [=sequence type=] +* a [=dictionary type=] +* a [=record type=] +* a [=union type=] + that has a nullable or non-nullable sequence type, dictionary, + or record + as one of its [=flattened member types=] + +The attribute is read only if the +readonly keyword is used before the attribute keyword. +An object that implements the interface on which a read only attribute +is defined will not allow assignment to that attribute. It is language +binding specific whether assignment is simply disallowed by the language, +ignored or an exception is thrown. + +
+    interface interface_identifier {
+      readonly attribute type identifier;
+    };
+
+ +Attributes whose type is a [=promise type=] must be [=read only=]. Additionally, they cannot have +any of the [=extended attributes=] [{{LegacyLenientSetter}}], [{{PutForwards}}], [{{Replaceable}}], or +[{{SameObject}}]. + +A [=regular attribute=] +that is not [=read only=] +can be declared to inherit its getter +from an ancestor interface. This can be used to make a read only attribute +in an ancestor interface be writable on a derived interface. An attribute +[=inherit its getter|inherits its getter=] if +its declaration includes inherit in the declaration. +The read only attribute from which the attribute inherits its getter +is the attribute with the same identifier on the closest ancestor interface +of the one on which the inheriting attribute is defined. The attribute +whose getter is being inherited must be +of the same type as the inheriting attribute. + +Note: The grammar ensures that inherit does not appear on a [=read only=] attribute +or a [=static attribute=]. + +
+    [Exposed=Window]
+    interface Ancestor {
+      readonly attribute TheType theIdentifier;
+    };
+
+    [Exposed=Window]
+    interface Derived : Ancestor {
+      inherit attribute TheType theIdentifier;
+    };
+
+ +When the stringifier keyword is used +in a [=regular attribute=] +declaration, it indicates that objects implementing the +interface will be stringified to the value of the attribute. See +[[#idl-stringifiers]] for details. + +
+    interface interface_identifier {
+      stringifier attribute DOMString identifier;
+    };
+
+ +The following [=extended attributes=] +are applicable to regular and static attributes: +[{{CrossOriginIsolated}}], +[{{Exposed}}], +[{{SameObject}}], and +[{{SecureContext}}]. + +The following [=extended attributes=] +are applicable only to regular attributes: +[{{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 :
+        "async"
+        "required"
+
+ +
+    OptionalReadOnly :
+        "readonly"
+        ε
+
+ +
+ + The following [=IDL fragment=] + demonstrates how [=attributes=] + can be declared on an [=interface=]: + +
+        [Exposed=Window]
+        interface Animal {
+
+          // A simple attribute that can be set to any string value.
+          readonly attribute DOMString name;
+
+          // An attribute whose value can be assigned to.
+          attribute unsigned short age;
+        };
+
+        [Exposed=Window]
+        interface Person : Animal {
+
+          // An attribute whose getter behavior is inherited from Animal, and need not be
+          // specified in the description of Person.
+          inherit attribute DOMString name;
+        };
+    
+
+ + +

Operations

+ +An operation is an [=interface member=], [=callback interface +member=] or [=namespace member=] +(matching static RegularOperation, +stringifier, +RegularOperation or +SpecialOperation) +that defines a behavior that can be invoked on objects implementing the interface. +There are three kinds of operation: + +1. [=regular operations=], which + are those used to declare that objects implementing the + [=interface=] will have a method with + the given [=identifier=] +
+        interface interface_identifier {
+          return_type identifier(/* arguments... */);
+        };
+    
+1. [=special operations=], + which are used to declare special behavior on objects + implementing the interface, such as object indexing and stringification +
+        interface interface_identifier {
+          /* special_keyword */ return_type identifier(/* arguments... */);
+          /* special_keyword */ return_type (/* arguments... */);
+        };
+    
+1. [=static operations=], + which are used to declare operations that are not associated with + a particular object implementing the interface +
+        interface interface_identifier {
+          static return_type identifier(/* arguments... */);
+        };
+    
+ +If an operation has an identifier but no static +keyword, then it declares a regular operation. +If the operation has a +[=special keyword=] +used in its declaration (that is, any keyword matching +Special, or +the stringifier keyword), +then it declares a special operation. A single operation can declare +both a regular operation and a special operation; +see [[#idl-special-operations]] for details on special operations. +Note that in addition to being [=interface members=], +regular operations can also be [=callback interface members=] and [=namespace members=]. + +If an operation has no identifier, +then it must be declared to be a special operation +using one of the special keywords. + +The identifier of a [=regular operation=] or [=static operation=] +must not be the same as the identifier +of a [=constant=] or [=attribute=] +defined on the same [=interface=], [=callback interface=] or [=namespace=]. +The identifier of a static operation must not be "prototype". + +Note: The identifier can be the same +as that of another operation on the interface, however. +This is how operation overloading is specified. + +Note: The [=identifier=] of a [=static operation=] +can be the same as the identifier +of a [=regular operation=] +defined on the same [=interface=]. + +The return type of the operation is given +by the type (matching Type) +that appears before the operation's optional [=identifier=]. +If the return type is an +[=identifier=] followed by ?, +then the identifier must +identify an [=interface=], [=dictionary=], [=enumeration=], +[=callback function=], [=callback interface=] or [=typedef=]. + +An operation's arguments (matching ArgumentList) +are given between the parentheses in the declaration. Each individual argument is specified +as a type (matching Type) followed by an [=identifier=] +(matching ArgumentName). + +Note: For expressiveness, the identifier of an operation argument can also be specified +as one of the keywords matching the ArgumentNameKeyword +symbol without needing to escape it. + +If the Type of an operation argument is an identifier +followed by ?, +then the identifier must identify an [=interface=], +[=enumeration=], [=callback function=], [=callback interface=], +or [=typedef=]. +If the operation argument type is an [=identifier=] +not followed by ?, then the identifier must +identify any one of those definitions or a [=dictionary=]. + +If the operation argument type, after resolving typedefs, +is a [=nullable type=], +its [=nullable types/inner type=] must not be a [=dictionary type=]. + +
+    interface interface_identifier {
+      return_type identifier(type identifier, type identifier /* , ... */);
+    };
+
+ +The identifier of each argument must not be the same +as the identifier of another argument in the same operation declaration. + +Each argument can be preceded by a list of +[=extended attributes=] (matching +ExtendedAttributeList), +which can control how a value passed as the argument will be handled in +language bindings. + +
+    interface interface_identifier {
+      return_type identifier([extended_attributes] type identifier, [extended_attributes] type identifier /* , ... */);
+    };
+
+ +
+ + The following [=IDL fragment=] + demonstrates how [=regular operations=] + can be declared on an [=interface=]: + +
+        [Exposed=Window]
+        interface Dimensions {
+          attribute unsigned long width;
+          attribute unsigned long height;
+        };
+
+        [Exposed=Window]
+        interface Button {
+
+          // An operation that takes no arguments and returns a boolean.
+          boolean isMouseOver();
+
+          // Overloaded operations.
+          undefined setDimensions(Dimensions size);
+          undefined setDimensions(unsigned long width, unsigned long height);
+        };
+    
+
+ +An operation or [=constructor operation=] is considered to be +variadic +if the final argument uses the ... token just +after the argument type. Declaring an operation to be variadic indicates that +the operation can be invoked with any number of arguments after that final argument. +Those extra implied formal arguments are of the same type as the final explicit +argument in the operation declaration. The final argument can also be omitted +when invoking the operation. An argument must not +be declared with the ... token unless it +is the final argument in the operation's argument list. + +
+    interface interface_identifier {
+      return_type identifier(type... identifier);
+      return_type identifier(type identifier, type... identifier);
+    };
+
+ +[=Extended attributes=] +that [=takes an argument list|take an argument list=] +([{{LegacyFactoryFunction}}], of those +defined in this specification) and [=callback functions=] +are also considered to be [=variadic=] +when the ... token is used in their argument lists. + +
+ + The following [=IDL fragment=] defines an interface that has + two variadic operations: + +
+        [Exposed=Window]
+        interface IntegerSet {
+          readonly attribute unsigned long cardinality;
+
+          undefined union(long... ints);
+          undefined intersection(long... ints);
+        };
+    
+ + In the JavaScript binding, variadic operations are implemented by + functions that can accept the subsequent arguments: + +
+        var s = getIntegerSet();  // Obtain an instance of IntegerSet.
+
+        s.union();                // Passing no arguments corresponding to 'ints'.
+        s.union(1, 4, 7);         // Passing three arguments corresponding to 'ints'.
+    
+ + A binding for a language that does not support variadic functions + might specify that an explicit array or list of integers be passed + to such an operation. + +
+ +An argument is considered to be an optional argument +if it is declared with the optional keyword. +The final argument of a [=variadic=] operation +is also considered to be an optional argument. Declaring an argument +to be optional indicates that the argument value can be omitted +when the operation is invoked. The final argument in an +operation must not explicitly be declared to be +optional if the operation is [=variadic=]. + +
+    interface interface_identifier {
+      return_type identifier(type identifier, optional type identifier);
+    };
+
+ +Optional arguments can also have a default value +specified. If the argument's identifier is followed by a U+003D (=) +and a value (matching DefaultValue), +then that gives the optional argument its [=optional argument/default value=]. +The implicitly optional final argument of a [=variadic=] +operation must not have a default value specified. +The default value is the value to be assumed when the operation is called with the +corresponding argument omitted. + +
+    interface interface_identifier {
+      return_type identifier(type identifier, optional type identifier = "value");
+    };
+
+ +

+ It is strongly suggested not to use a [=optional argument/default value=] + of true for {{boolean}}-typed arguments, + as this can be confusing for authors who might otherwise expect the default + conversion of undefined to be used (i.e., false). + [[API-DESIGN-PRINCIPLES]] +

+ +If the type of an argument is a [=dictionary type=] or a [=union type=] that has +a [=dictionary type=] as one +of its [=flattened member types=], and that dictionary type and its ancestors have no +[=dictionary member/required=] [=dictionary member|members=], and the argument is either the final argument or is +followed only by [=optional arguments=], then the argument must be specified as +optional and have a default value provided. + +
+ + This is to encourage API designs that do not require authors to pass an + empty dictionary value when they wish only to use the dictionary's + default values. + + Usually the default value provided will be {}, but in the + case of a [=union type=] that has a dictionary type as one of its + [=flattened member types=] a default value could be provided that + initializes some other member of the union. +
+ +When a boolean literal token (true or false), +the null token, +an integer token, a +decimal token or one of +the three special floating point literal values (Infinity, +-Infinity or NaN) is used as the +[=optional argument/default value=], +it is interpreted in the same way as for a [=constant=]. + +When the undefined token is used as the +[=optional argument/default value=], +the value is the IDL {{undefined}} value. + +
+ Optional argument default values can also be specified using a + string + token, whose value is a + [=string type=] determined as follows: + + 1. Let |S| be the sequence of [=scalar values=] matched by + the string token + with its leading and trailing U+0022 (") [=scalar values=] removed. + 1. Depending on the type of the argument: +
+ : {{DOMString}} + : {{USVString}} + : an [=enumeration=] type + :: The value of the string token + is |S|. + : {{ByteString}} + :: Assert: |S| doesn't contain any [=code points=] higher than U+00FF. + + The value of the string token + is the [=isomorphic encoding=] of |S|. +
+
+ +If the type of the [=optional argument=] +is an [=enumeration=], then its +[=optional argument/default value=] if specified must +be one of the [=enumeration's values=]. + +Optional argument default values can also be specified using the +two token value [], which represents an empty sequence +value. The type of this value is the same as the type of the optional +argument it is being used as the default value of. That type +must be a [=sequence type=], a [=nullable type=] whose [=nullable types/inner type=] is a +[=sequence type=] or a [=union type=] or [=nullable type|nullable=] union type +that has a [=sequence type=] in its [=flattened member types=]. + +Optional argument default values can also be specified using the two token value +{}, which represents a default-initialized (as if from ES +null or an object with no properties) dictionary value. The type +of this value is the same as the type of the optional argument it is being used +as the default value of. That type must be a [=dictionary type=], or a [=union +type=] that has a [=dictionary type=] in its [=flattened member types=]. + +
+ + The following [=IDL fragment=] + defines an [=interface=] + with a single [=operation=] + that can be invoked with two different argument list lengths: + +
+        [Exposed=Window]
+        interface ColorCreator {
+          object createColor(double v1, double v2, double v3, optional double alpha);
+        };
+    
+ + It is equivalent to an [=interface=] + that has two [=overloaded=] + [=operations=]: + +
+        [Exposed=Window]
+        interface ColorCreator {
+          object createColor(double v1, double v2, double v3);
+          object createColor(double v1, double v2, double v3, double alpha);
+        };
+    
+
+ +
+ + The following [=IDL fragment=] + defines an [=interface=] + with an operation that takes a dictionary argument: + +
+        dictionary LookupOptions {
+          boolean caseSensitive = false;
+        };
+
+        [Exposed=Window]
+        interface AddressBook {
+          boolean hasAddressForName(USVString name, optional LookupOptions options = {});
+        };
+    
+ + If hasAddressForName is called with only one argument, the + second argument will be a default-initialized LookupOptions + dictionary, which will cause caseSensitive to be set to + false. +
+ +The following extended attributes are applicable to operations: +[{{CrossOriginIsolated}}], +[{{Default}}], +[{{Exposed}}], +[{{LegacyUnforgeable}}], +[{{NewObject}}], and +[{{SecureContext}}]. + +The method steps of an operation |operation| should be introduced using text of the form +“The |operation|(arg1, arg2, ...) method +steps are:” followed by a list, or “The |operation|(arg1, +arg2, ...) method steps are to” followed by an inline description. + +Note: When defining [=method steps=], you implicitly have access to [=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 :
+        "..."
+        ε
+
+ +
+ +
toJSON
+ +By declaring a toJSON [=regular operation=], +an [=interface=] specifies how to convert the objects that implement it to [=JSON types=]. + +The toJSON [=regular operation=] is reserved for this usage. +It must take zero arguments and return a [=JSON type=]. + +The JSON types are: + +* [=numeric types=], +* {{boolean}}, +* [=string types=], +* [=nullable types=] whose [=nullable types/inner type=] is a [=JSON type=], +* [=annotated types=] whose [=annotated types/inner type=] is a [=JSON type=], +* [=union types=] whose [=member types=] are [=JSON types=], +* [=typedefs=] whose [=type being given a new name=] is a [=JSON type=], +* [=sequence types=] whose parameterized type is a [=JSON type=], +* [=frozen array types=] whose parameterized type is a [=JSON type=], +* [=dictionary types=] where the types of all [=dictionary members|members=] declared on the dictionary and all its [=inherited dictionaries=] are [=JSON types=], +* [=records=] where all of their [=map/values=] are [=JSON types=], +* {{object}}, +* [=interface types=] that have a toJSON operation declared on themselves or + one of their [=inherited interfaces=]. + +How the toJSON [=regular operation=] +is made available on an object in a language binding, +and how exactly the [=JSON types=] are converted into a JSON string, +is language binding specific. + +Note: In the JavaScript language binding, +this is done by exposing a toJSON method +which returns the [=JSON type=] +converted into a JavaScript value +that can be turned into a JSON string +by the {{JSON.stringify()}} function. +Additionally, in the JavaScript language binding, +the toJSON operation can take a [{{Default}}] [=extended attribute=], +in which case the [=default toJSON steps=] are exposed instead. + +
+ + The following [=IDL fragment=] defines an interface Transaction + that has a toJSON method defined in prose: + +
+        [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;
+        };
+    
+ + The toJSON [=regular operation=] of Transaction [=interface=] + could be defined as follows: + + +
+ + The toJSON() method steps are: + + 1. Let |json| be a new [=map=]. + 1. [=list/For each=] attribute [=identifier=] |attr| in « "from", "to", "amount", "description" »: + 1. Let |value| be the result of running the [=getter steps=] of |attr| on [=this=]. + 1. Set |json|[|attr|] to |value|. + 1. Return |json|. +
+ + In the JavaScript language binding, there would exist a toJSON() method on + Transaction objects: + +
+        // Get an instance of Transaction.
+        var txn = getTransaction();
+
+        // Evaluates to an object like this:
+        // {
+        //   from: "Bob",
+        //   to: "Alice",
+        //   amount: 50,
+        //   description: "books"
+        // }
+        txn.toJSON();
+
+        // Evaluates to a string like this:
+        // '{"from":"Bob","to":"Alice","amount":50,"description":"books"}'
+        JSON.stringify(txn);
+    
+
+ + +

Constructor operations

+ +If an [=interface=] has a [=constructor operation=] member (matching +Constructor), it indicates that it is possible to +create objects that [=implement=] the [=interface=] using a [=constructor=]. + +Multiple [=constructor operations=] may appear on a given [=interface=]. +For each [=constructor operation=] on the [=interface=], there will be a way to attempt to +construct an instance by passing the specified arguments. + +The constructor steps of a [=constructor operation=] that is a member of an interface +named |interface| should be introduced using text of the form “The +new |interface|(arg1, arg2, ...) constructor steps +are:” followed by a list, or “The +new |interface|(arg1, arg2, ...) constructor steps +are to” followed by an inline description. + +The constructor steps must do nothing, initialize the value passed as [=this=], or throw an +exception. + +

If the constructor does not initialize +[=this=], one can write “The new Example(init) constructor +steps are to do nothing.” + +See [[#interface-object]] for details on how a [=constructor operation=] is to be implemented. + +

+ + The following IDL defines two interfaces. The second has [=constructor operations=], while the + first does not. + +
+        [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;
+        };
+    
+ + A JavaScript implementation supporting these interfaces would implement a \[[Construct]] + internal method on the Circle interface object which would return a + new object that [=implements=] the interface. + It would take either zero or one argument. + + Issue(whatwg/webidl#698): It is unclear whether the NodeList interface + object would implement a \[[Construct]] internal method. In any case, trying to use it as a + constructor will cause a {{TypeError}} to be thrown. + +
+        var x = new Circle();      // This uses the zero-argument constructor to create a
+                                   // reference to a platform object that implements the
+                                   // Circle interface.
+
+        var y = new Circle(1.25);  // This also creates a Circle object, this time using
+                                   // the one-argument constructor.
+
+        var z = new NodeList();    // This would throw a TypeError, since no
+                                   // constructor is declared.
+    
+
+ + + +
+    Constructor :
+        "constructor" "(" ArgumentList ")" ";"
+
+ +
+
+
+
+
+
+
+ + +

Stringifiers

+ +When an [=interface=] has a stringifier, it indicates that objects +that implement the interface have a non-default conversion to a string. Stringifiers can be +specified using a stringifier keyword, which creates a stringifier operation when +used alone. + +
+    interface interface_identifier {
+      stringifier;
+    };
+
+ +Prose accompanying the interface must define +the stringification behavior +of the interface. + +The stringifier keyword +can also be placed on an [=attribute=]. +In this case, the string to convert the object to is the +value of the attribute. The stringifier keyword +must not be placed on an attribute unless +it is declared to be of type {{DOMString}} or {{USVString}}. +It also must not be placed on +a [=static attribute=]. + +
+    interface interface_identifier {
+      stringifier attribute DOMString identifier;
+    };
+
+ +On a given [=interface=], there must exist at most one stringifier. + +
+    Stringifier :
+        "stringifier" StringifierRest
+
+ +
+    StringifierRest :
+        OptionalReadOnly AttributeRest
+        ";"
+
+ +
+ + The following [=IDL fragment=] + defines an interface that will stringify to the value of its + name attribute: + +
+        [Exposed=Window]
+        interface Student {
+          constructor();
+          attribute unsigned long id;
+          stringifier attribute DOMString name;
+        };
+    
+ + In the JavaScript binding, using a Student + object in a context where a string is expected will result in the + value of the object's name property being + used: + +
+        var s = new Student();
+        s.id = 12345678;
+        s.name = '周杰倫';
+
+        var greeting = 'Hello, ' + s + '!';  // Now greeting == 'Hello, 周杰倫!'.
+    
+ + The following [=IDL fragment=] + defines an interface that has custom stringification behavior that is + not specified in the IDL itself. + +
+        [Exposed=Window]
+        interface Student {
+          constructor();
+          attribute unsigned long id;
+          attribute DOMString? familyName;
+          attribute DOMString givenName;
+
+          stringifier;
+        };
+    
+ + Thus, there needs to be prose to explain the stringification behavior. + We assume that the familyName and + givenName attributes are backed by + family name and given name concepts, respectively. + +
+ + The [=stringification behavior=] steps are: + + 1. If [=this=]'s family name is null, then return [=this=]'s given name. + 2. Return the concatenation of [=this=]'s given name, followed by U+0020 SPACE, followed by [=this=]'s family name. + +
+ + A JavaScript implementation of the IDL would behave as follows: + +
+        var s = new Student();
+        s.id = 12345679;
+        s.familyName = 'Smithee';
+        s.givenName = 'Alan';
+
+        var greeting = 'Hi ' + s;  // Now greeting == 'Hi Alan Smithee'.
+    
+
+ + +

Special operations

+ +A special operation is a +declaration of a certain kind of special behavior on objects implementing +the interface on which the special operation declarations appear. +Special operations are declared by using a +special keyword +in an operation declaration. + +There are three kinds of special operations. The table below indicates +for a given kind of special operation what special keyword +is used to declare it and what the purpose of the special operation is: + + + + + + + + + + + + + + + + + + + + + + +
Special operationKeywordPurpose
GettersgetterDefines behavior for when an object is indexed for property retrieval.
SetterssetterDefines behavior for when an object is indexed for property + assignment or creation.
DeletersdeleterDefines behavior for when an object is indexed for property deletion.
+ +Not all language bindings support all of the four kinds of special +object behavior. When special operations are declared using +operations with no identifier, then in language bindings that do +not support the particular kind of special operations there simply +will not be such functionality. + +
+ + The following IDL fragment defines an interface with a getter and a setter: + +
+        [Exposed=Window]
+        interface Dictionary {
+          readonly attribute unsigned long propertyCount;
+
+          getter double (DOMString propertyName);
+          setter undefined (DOMString propertyName, double propertyValue);
+        };
+    
+ + In language bindings that do not support property getters and setters, + objects implementing [=Dictionary=] will not + have that special behavior. + +
+ +Defining a special operation with an [=identifier=] +is equivalent to separating the special operation out into its own +declaration without an identifier. This approach is allowed to +simplify [=method steps=] of an interface's operations. + +
+ + The following two interfaces are equivalent: + +
+        [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);
+        };
+    
+
+ +A given [=special keyword=] must not +appear twice on an operation. + +Getters and setters come in two varieties: ones that +take a {{DOMString}} as a property name, +known as +named property getters and +named property setters, +and ones that take an {{unsigned long}} +as a property index, known as +indexed property getters and +indexed property setters. +There is only one variety of deleter: +named property deleters. +See [[#idl-indexed-properties]] +and [[#idl-named-properties]] +for details. + +On a given [=interface=], +there must exist at most one +[=named property deleter=], +and at most one of each variety of getter and setter. + +If an interface has a setter of a given variety, +then it must also have a getter of that +variety. If it has a [=named property deleter=], +then it must also have a +[=named property getter=]. + +Special operations declared using operations must not +be [=variadic=] nor have any +[=optional arguments=]. + +If an object implements more than one [=interface=] +that defines a given special operation, then it is undefined which (if any) +special operation is invoked for that operation. + + +
Indexed properties
+ +An [=interface=] that defines an [=indexed property getter=] +is said to support indexed properties. +By extension, a [=platform object=] +is said to [=support indexed properties=] if +it implements an [=interface=] that itself does. + +If an interface [=support indexed properties|supports indexed properties=], +then the interface definition must be accompanied by +a description of what indices the object can be indexed with at +any given time. These indices are called the supported property indices. + +Interfaces that [=support indexed properties=] must define +an [=integer types|integer-typed=] [=attribute=] named "length". + +Indexed property getters must +be declared to take a single {{unsigned long}} argument. +Indexed property setters must +be declared to take two arguments, where the first is an {{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);
+    };
+
+ +The following requirements apply to the definitions of indexed property getters and setters: + +* If an [=indexed property getter=] was specified using an [=operation=] + with an [=identifier=], + then the value returned when indexing the object with a given [=supported property indices|supported property index=] + is the value that would be returned by invoking the operation, passing + the index as its only argument. If the operation used to declare the indexed property getter + did not have an identifier, then the interface definition must be accompanied + by a description of how to determine the value of an indexed property + for a given index. +* If an [=indexed property setter=] was specified using an operation + with an identifier, + then the behavior that occurs when indexing the object for property assignment with a given supported property index and value + is the same as if the operation is invoked, passing + the index as the first argument and the value as the second argument. If the operation used to declare the indexed property setter + did not have an identifier, then the interface definition must be accompanied + by a description of how to set the value of an existing indexed property + and how to set the value of a new indexed property + for a given property index and value. + +
+ + Note that if an [=indexed property getter=] or + [=indexed property setters|setter=] + is specified using an [=operation=] with an [=identifier=], + then indexing an object with an integer that is not a [=supported property indices|supported property index=] + does not necessarily elicit the same behavior as invoking the operation with that index. The actual behavior in this + case is language binding specific. + + In the JavaScript language binding, a regular property lookup is done. For example, take the following IDL: + +
+        [Exposed=Window]
+        interface A {
+          getter DOMString toWord(unsigned long index);
+        };
+    
+ + Assume that an object implementing A has [=supported property indices=] + in the range 0 ≤ index < 2. Also assume that toWord is defined to return + its argument converted into an English word. The behavior when invoking the + [=operation=] with an out of range index + is different from indexing the object directly: + +
+        var a = getA();
+
+        a.toWord(0);  // Evalautes to "zero".
+        a[0];         // Also evaluates to "zero".
+
+        a.toWord(5);  // Evaluates to "five".
+        a[5];         // Evaluates to undefined, since there is no property "5".
+    
+
+ +
+ + The following [=IDL fragment=] defines an interface + OrderedMap which allows + retrieving and setting values by name or by index number: + +
+        [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);
+        };
+    
+ + Since all of the special operations are declared using + operations with identifiers, the only additional prose + that is necessary is that which describes what keys those sets + have. Assuming that the get() operation is + defined to return null if an + attempt is made to look up a non-existing entry in the + OrderedMap, then the following + two sentences would suffice: + +
+ + An object map implementing OrderedMap + supports indexed properties with indices in the range + 0 ≤ index < map.size. + + Such objects also support a named property for every name that, + if passed to get(), would return a non-null value. + +
+ + As described in [[#js-legacy-platform-objects]], + a JavaScript implementation would create + properties on a [=legacy platform object=] implementing + OrderedMap that correspond to + entries in both the named and indexed property sets. + These properties can then be used to interact + with the object in the same way as invoking the object's + methods, as demonstrated below: + +
+        // Assume map is a legacy platform object implementing the OrderedMap interface.
+        var map = getOrderedMap();
+        var x, y;
+
+        x = map[0];       // If map.length > 0, then this is equivalent to:
+                          //
+                          //   x = map.getByIndex(0)
+                          //
+                          // since a property named "0" will have been placed on map.
+                          // Otherwise, x will be set to undefined, since there will be
+                          // no property named "0" on map.
+
+        map[1] = false;   // This will do the equivalent of:
+                          //
+                          //   map.setByIndex(1, false)
+
+        y = map.apple;    // If there exists a named property named "apple", then this
+                          // will be equivalent to:
+                          //
+                          //   y = map.get('apple')
+                          //
+                          // since a property named "apple" will have been placed on
+                          // map.  Otherwise, y will be set to undefined, since there
+                          // will be no property named "apple" on map.
+
+        map.berry = 123;  // This will do the equivalent of:
+                          //
+                          //   map.set('berry', 123)
+
+        delete map.cake;  // If a named property named "cake" exists, then the "cake"
+                          // property will be deleted, and then the equivalent to the
+                          // following will be performed:
+                          //
+                          //   map.remove("cake")
+    
+
+ + +
Named properties
+ +An [=interface=] that defines a [=named property getter=] +is said to support named properties. +By extension, a [=platform object=] +is said to [=support named properties=] if +it implements an [=interface=] that itself does. + +If an interface [=support named properties|supports named properties=], +then the interface definition must be accompanied by +a description of the ordered set of names that can be used to index the object +at any given time. These names are called the +supported property names. + +Named property getters and deleters must +be declared to take a single {{DOMString}} argument. +Named property setters must +be declared to take two arguments, where the first is a {{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);
+    };
+
+ +The following requirements apply to the definitions of named property getters, setters and deleters: + +* If a [=named property getter=] was specified using an [=operation=] + with an [=identifier=], + then the value returned when indexing the object with a given [=supported property name=] + is the value that would be returned by invoking the operation, passing + the name as its only argument. If the operation used to declare the named property getter + did not have an identifier, then the interface definition must be accompanied + by a description of how to determine the value of a named property + for a given property name. +* If a [=named property setter=] was specified using an operation + with an identifier, + then the behavior that occurs when indexing the object for property assignment with a given supported property name and value + is the same as if the operation is invoked, passing + the name as the first argument and the value as the second argument. If the operation used to declare the named property setter + did not have an identifier, then the interface definition must be accompanied + by a description of how to set the value of an existing named property + and how to set the value of a new named property + for a given property name and value. +* If a [=named property deleter=] was specified using an operation + with an identifier, + then the behavior that occurs when indexing the object for property deletion with a given supported property name + is the same as if the operation is invoked, passing + the name as the only argument. If the operation used to declare the named property deleter + did not have an identifier, then the interface definition must be accompanied + by a description of how to delete an existing named property + for a given property name. + +Note: As with [=indexed properties=], +if an [=named property getter=], +[=named property setters|setter=] or +[=named property deleters|deleter=] +is specified using an [=operation=] with an [=identifier=], +then indexing an object with a name that is not a [=supported property name=] +does not necessarily elicit the same behavior as invoking the operation with that name; the behavior +is language binding specific. + + +

Static attributes and operations

+ +Static attributes and +static operations are ones that +are not associated with a particular instance of the +[=interface=] +on which it is declared, and is instead associated with the interface +itself. Static attributes and operations are declared by using the +static keyword in their declarations. + +It is language binding specific whether it is possible to invoke +a static operation or get or set a static attribute through a reference +to an instance of the interface. + +
+    StaticMember :
+        "static" StaticMemberRest
+
+ +
+    StaticMemberRest :
+        OptionalReadOnly AttributeRest
+        RegularOperation
+
+ +
+ + The following [=IDL fragment=] defines an interface + Circle that has a static + operation declared on it: + +
+        [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);
+        };
+    
+ + In the JavaScript language binding, the [=function object=] for + triangulate and the accessor property for triangulationCount + will exist on the [=interface object=] + for Circle: + +
+        var circles = getCircles();           // an Array of Circle objects
+
+        typeof Circle.triangulate;            // Evaluates to "function"
+        typeof Circle.triangulationCount;     // Evaluates to "number"
+        Circle.prototype.triangulate;         // Evaluates to undefined
+        Circle.prototype.triangulationCount;  // Also evaluates to undefined
+        circles[0].triangulate;               // As does this
+        circles[0].triangulationCount;        // And this
+
+        // Call the static operation
+        var triangulationPoint = Circle.triangulate(circles[0], circles[1], circles[2]);
+
+        // Find out how many triangulations we have done
+        window.alert(Circle.triangulationCount);
+    
+
+ + +

Overloading

+ +If a [=regular operation=] +or [=static operation=] +defined on an [=interface=] +has an [=identifier=] +that is the same as the identifier of another operation on that +interface of the same kind (regular or static), then the operation is said to be +overloaded. When the identifier +of an overloaded operation is used to invoke one of the +operations on an object that implements the interface, the +number and types of the arguments passed to the operation +determine which of the overloaded operations is actually +invoked. +[=Constructor operations=] can be overloaded too. +There are some restrictions on the arguments +that overloaded operations and constructors can be +specified to take, and in order to describe these restrictions, +the notion of an effective overload set is used. + +A set of overloaded [=operations=] must either: + +* contain no [=operations=] whose [=return type=] is a [=promise type=]; +* only contain [=operations=] whose [=return type=] is a [=promise type=]. + +[=Operations=] must not be overloaded across +[=interface=], +[=partial interface=], +[=interface mixin=], and +[=partial interface mixin=] +definitions. + +
+ + For example, the overloads for both f and g + are disallowed: + +
+        [Exposed=Window]
+        interface A {
+          undefined f();
+        };
+
+        partial interface A {
+          undefined f(double x);
+          undefined g();
+        };
+
+        partial interface A {
+          undefined g(DOMString x);
+        };
+    
+ + Note that [=constructor operations=] and + [{{LegacyFactoryFunction}}] + [=extended attributes=] are disallowed from appearing + on [=partial interface=] definitions, + so there is no need to also disallow overloading for constructors. + +
+ +An effective overload set +represents the allowable invocations for a particular +[=operation=], +constructor (specified with a [=constructor operation=] +or [{{LegacyFactoryFunction}}]), or +[=callback function=]. +The algorithm to [=compute the effective overload set=] +operates on one of the following four types of IDL constructs, and listed with them below are +the inputs to the algorithm needed to compute the set. + + : For regular operations + : For static operations + :: * the [=interface=] on which the [=operations=] are to be found + * the [=identifier=] of the operations + * the number of arguments to be passed + : For constructors + :: * the [=interface=] on which the [=constructor operations=] are to be found + * the number of arguments to be passed + : For legacy factory functions + :: * the [=interface=] on which the [{{LegacyFactoryFunction}}] [=extended attributes=] are to be found + * the [=identifier=] of the legacy factory function + * the number of arguments to be passed + +An [=effective overload set=] is used, among other things, to determine whether there are +ambiguities in the overloaded operations and constructors specified on an interface. + +The [=set/items=] of an [=effective overload set=] are [=tuples=] of the form +([=effective overload set tuple/callable=], [=type list=], [=optionality list=]) +whose [=tuple/items=] are described below: + +* A callable is an [=operation=] + if the [=effective overload set=] is for [=regular operations=], + [=static operations=], or [=constructor operations=]; and it is an [=extended attribute=] + if the [=effective overload set=] is for [=legacy factory functions=]. +* A type list is a [=list=] of IDL types. +* An optionality list is a [=list=] of + three possible optionality values + – "required", "optional" or "variadic" – + indicating whether the argument at a given index was + declared as being [=optional argument|optional=] + or corresponds to a [=variadic=] argument. + +Each [=tuple=] represents an allowable invocation of the operation, +constructor, or callback function with an argument value list of the given types. +Due to the use of [=optional arguments=] +and [=variadic=] operations +and constructors, there may be multiple items in an [=effective overload set=] identifying +the same operation or constructor. + +
+ The algorithm below describes how to compute the effective overload set. + The following input variables are used, if they are required: + + * the identifier of the operation or legacy factory function is |A| + * the argument count is |N| + * the interface is |I| + + Whenever an argument of an extended attribute is mentioned, + it is referring to an argument of the extended attribute's + [=takes a named argument list|named argument list=]. + + 1. Let |S| be an [=ordered set=]. + 1. Let |F| be an [=ordered set=] with [=set/items=] as follows, + according to the kind of [=effective overload set=]: +
+ : For regular operations + :: The elements of |F| are the [=regular operations=] with + identifier |A| defined on interface |I|. + : For static operations + :: The elements of |F| are the [=static operations=] with + identifier |A| defined on interface |I|. + : For constructors + :: The elements of |F| are the + [=constructor operations=] on interface |I|. + : For legacy factory functions + :: The elements of |F| are the + [{{LegacyFactoryFunction}}] + [=extended attributes=] on interface |I| whose + [=takes a named argument list|named argument lists'=] + identifiers are |A|. +
+ + 1. Let |maxarg| be the maximum number of arguments the operations, + legacy factory functions, or callback functions in |F| are declared to take. + For [=variadic=] operations and legacy factory functions, + the argument on which the ellipsis appears counts as a single argument. + + Note: So undefined f(long x, long... y); is considered to be declared to take two arguments. + 1. Let |max| be max(|maxarg|, |N|). + 1. [=set/For each=] operation or extended attribute |X| in |F|: + 1. Let |arguments| be the [=list=] of arguments |X| is declared to take. + 1. Let |n| be the [=list/size=] of |arguments|. + 1. Let |types| be a [=type list=]. + 1. Let |optionalityValues| be an [=optionality list=]. + 1. [=list/For each=] |argument| in |arguments|: + 1. [=list/Append=] the type of |argument| to |types|. + 1. [=list/Append=] "variadic" to |optionalityValues| if |argument| is a final, variadic argument, + "optional" if |argument| is [=optional argument|optional=], + and "required" otherwise. + 1. [=set/Append=] the [=tuple=] (|X|, |types|, |optionalityValues|) to |S|. + 1. If |X| is declared to be [=variadic=], then: + 1. [=list/For each=] |i| in [=the range=] |n| to |max| − 1, inclusive: + 1. Let |t| be a [=type list=]. + 1. Let |o| be an [=optionality list=]. + 1. [=list/For each=] |j| in [=the range=] 0 to |n| − 1, inclusive: + 1. [=list/Append=] |types|[|j|] to |t|. + 1. [=list/Append=] |optionalityValues|[|j|] to |o|. + 1. [=list/For each=] |j| in [=the range=] |n| to |i|, inclusive: + 1. [=list/Append=] |types|[|n| − 1] to |t|. + 1. [=list/Append=] "variadic" to |o|. + 1. [=set/Append=] the [=tuple=] (|X|, |t|, |o|) to |S|. + 1. Let |i| be |n| − 1. + 1. [=iteration/While=] |i| ≥ 0: + 1. If |arguments|[|i|] is not [=optional argument|optional=] + (i.e., it is not marked as "optional" and is not + a final, variadic argument), then [=iteration/break=]. + 1. Let |t| be a [=type list=]. + 1. Let |o| be an [=optionality list=]. + 1. [=list/For each=] |j| in [=the range=] 0 to |i| − 1, inclusive: + 1. [=list/Append=] |types|[|j|] to |t|. + 1. [=list/Append=] |optionalityValues|[|j|] to |o|. + 1. [=set/Append=] the [=tuple=] (|X|, |t|, |o|) to |S|. + + Note: if |i| is 0, this means to add to |S| the tuple (|X|, « », « »); + (where "« »" represents an [=list/is empty|empty list=]). + 1. Set |i| to |i| − 1. + 1. Return |S|. +
+ +
+ + For the following interface: + +
+        [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);
+        };
+    
+ + assuming Node and Event + are two other interfaces of which no object can implement both, + the [=effective overload set=] + for [=regular operations=] with + identifier f and argument count 4 is: + +
+      «
+        (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 »)
+      »
+    
+
+ +Two types are distinguishable if +the following algorithm returns true. + +
    +1. If one type [=includes a nullable type=] + and the other type either + [=includes a nullable type=], + is a [=union type=] with [=flattened member types=] + including a [=dictionary type=], or + is a [=dictionary type=], + return false. +
    + None of the following pairs are distinguishable: +
      +
    • + {{double}}? and + Dictionary1 +
    • +
    • + (Interface1 or {{long}})? and + (Interface2 or {{DOMString}})? +
    • +
    • + (Interface1 or {{long}}?) and + (Interface2 or {{DOMString}})? +
    • +
    • + (Interface1 or {{long}}?) and + (Interface2 or {{DOMString}}?) +
    • +
    • + (Dictionary1 or {{long}}) and + (Interface2 or {{DOMString}})? +
    • +
    • + (Dictionary1 or {{long}}) and + (Interface2 or {{DOMString}}?) +
    • +
    +
    +1. If both types are either a [=union type=] or [=nullable type|nullable=] [=union type=], + return true if each member type of the one + is distinguishable with each member type of the other, + or false otherwise. +1. If one type is a [=union type=] or nullable union type, + return true if each + [=member type=] of the union type is distinguishable + with the non-union type, + or false otherwise. +1. Consider the two "innermost" types derived by taking each type's [=annotated types/inner type=] + if it is an [=annotated type=], and then taking its [=nullable types/inner type=] inner type + if the result is a [=nullable type=]. If these two innermost types appear or are in categories + appearing in the following table and there is a “●” mark in the corresponding entry + or there is a letter in the corresponding entry and the designated additional + requirement below the table is satisfied, then return true. + Otherwise return false. + + Categories: +
    +
    interface-like
    +
    + * [=interface types=] + * [=buffer source types=] +
    dictionary-like
    +
    + * [=dictionary types=] + * [=record types=] + * [=callback interface types=] +
    sequence-like
    +
    + * [=sequence types=] + * [=frozen array types=] +
    + + + + + + + + + + + + + + + + + +
    undefined
    +
    boolean
    +
    numeric types
    +
    bigint
    +
    string types
    +
    object
    +
    symbol
    +
    interface-like
    +
    callback function
    +
    dictionary-like
    +
    sequence-like
    +
    undefined + + ● + ● + ● + ● + ● + ● + ● + ● + + ● +
    boolean + + + ● + ● + ● + ● + ● + ● + ● + ● + ● +
    numeric types + + + + (b) + ● + ● + ● + ● + ● + ● + ● +
    bigint + + + + + ● + ● + ● + ● + ● + ● + ● +
    string types + + + + + + ● + ● + ● + ● + ● + ● +
    object + + + + + + + ● + + + + +
    symbol + + + + + + + + ● + ● + ● + ● +
    interface-like + + + + + + + + (a) + ● + ● + ● +
    callback function + + + + + + + + + + (c) + ● +
    dictionary-like + + + + + + + + + + + ● +
    sequence-like + + + + + + + + + + + +
    + +
      + 1. The two identified interface-like types are + not the same, and no single [=platform object=] implements both + interface-like types. + 1. The types are distinguishable, but there is + a separate restriction on their use in + overloading below. Please also note the + advice about using unions of these types. + 1. A [=callback function=] that does not have + [{{LegacyTreatNonObjectAsNull}}] extended attribute is + distinguishable from a type in the dictionary-like category. +
      + For example, when converting an ECMAScript value to [=union + type=] which includes a [=callback function=] and a + dictionary-like type, if the value is [=ECMAScript/callable=], + then it is converted to a [=callback function=]. Otherwise, it is + converted to a dictionary-like type. +
      +
    + +
    + {{double}} and {{DOMString}} are distinguishable because + there is a ● at the intersection of [=numeric types=] with [=string types=]. +
    + +
    + {{double}} and {{long}} are not distinguishable because they are both [=numeric types=], + and there is no ● or letter at the intersection of [=numeric types=] with [=numeric types=]. +
    + +
    + Given: + +
    +            callback interface CBIface {
    +                undefined handle();
    +            };
    +
    +            [Exposed=Window]
    +            interface Iface {
    +                attribute DOMString attr2;
    +            };
    +
    +            dictionary Dict {
    +                DOMString field1;
    +            };
    +        
    + + CBIface is distinguishable from Iface + because there's a ● at the intersection of dictionary-like and interface-like, + but it is not distinguishable from Dict + because there's no ● at the intersection of dictionary-like and itself. +
    + +
    + [=Promise types=] do not appear in the above table, and as a consequence are + not distinguishable with any other type. +
    + +
+ +If there is more than one [=list/item=] in an [=effective overload set=] +that has a given [=type list=] [=list/size=], +then for those items there must be an index |i| such that +for each pair of items the types at index |i| are [=distinguishable=]. +The lowest such index is termed the distinguishing argument index +for the items of the [=effective overload set=] with the given type list size. + +

An [=effective overload set=] must not contain more than +one [=list/item=] with the same [=type list=] [=list/size=], where one [=list/item=] has a +{{bigint}} argument at the [=distinguishing argument index=] and another has a [=numeric type=] +argument at the [=distinguishing argument index=]. + +

+ + Consider the [=effective overload set=] shown in the previous example. + There are multiple items in the set with type lists 2, 3 and 4. + For each of these type list size, the [=distinguishing argument index=] is 0, since Node and + Event are [=distinguishable=]. + + The following use of overloading however is invalid: + +
+        [Exposed=Window]
+        interface B {
+          undefined f(DOMString x);
+          undefined f(USVString x);
+        };
+    
+ + since {{DOMString}} and {{USVString}} are not distinguishable. + +
+ +In addition, for each index |j|, where |j| is less than the +[=distinguishing argument index=] +for a given type list size, the types at index |j| in +all of the items' type lists must be the same, +and the [=optionality values=] at index |j| in all of the items' optionality lists must +be the same. + +
+ + The following is invalid: + +
+        [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);
+        };
+    
+ + For argument count 4, the [=effective overload set=] is: + +
+      «
+        (f1, « DOMString »,                       « required »),
+        (f2, « long, double, Node, Node »,        « required, required, required, required »),
+        (f3, « double, double, DOMString, Node », « required, required, required, required »)
+      »
+    
+ + Looking at items with type list size 4, the + [=distinguishing argument index=] + is 2, since Node and + {{DOMString}} are [=distinguishable=]. + However, since the arguments in these two overloads at index 0 are different, + the overloading is invalid. + +
+ + +
Overloading vs. union types
+ +This section is informative. + +
+ +For specifications defining IDL [=operations=], it might seem that [=overloaded|overloads=] and a +combination of [=union types=] and [=optional arguments=] have some feature overlap. + +It is first important to note that [=overloaded|overloads=] have different behaviors than [=union +types=] or [=optional arguments=], and one cannot be fully defined using the other (unless, +of course, additional prose is provided, which can defeat the purpose of the Web IDL type system). +For example, consider the {{CanvasDrawPath/stroke()}} operations defined on the {{CanvasDrawPath}} +interface [[HTML]]: + +
+    interface CanvasDrawPathExcerpt {
+      undefined stroke();
+      undefined stroke(Path2D path);
+    };
+
+ +Per the JavaScript language binding, calling stroke(undefined) on an object +implementing CanvasDrawPathExcerpt would attempt to call the second +overload, yielding a {{TypeError}} since undefined cannot be converted to a {{Path2D}}. However, if the operations were instead +defined with [=optional arguments=] and merged into one, + +
+    interface CanvasDrawPathExcerptOptional {
+      undefined stroke(optional Path2D path);
+    };
+
+ +the [=overload resolution algorithm=] would treat the path argument as missing +given the same call stroke(undefined), and not throw any exceptions. + +Note: For this particular example, the latter behavior is actually what Web developers would +generally expect. If {{CanvasDrawPath}} were to be designed today, [=optional arguments=] would be +used for stroke(). + +Additionally, there are semantic differences as well. [=Union types=] are usually used in the sense +that "any of the types would work in about the same way". In contrast, [=overloaded=] operations are +designed to map well to language features such as C++ overloading, and are usually a better fit for +operations with more substantial differences in what they do given arguments of different types. +However, in most cases, operations with such substantial differences are best off with different +names to avoid confusion for Web developers, since the JavaScript language does not provide +language-level overloading. As such, overloads are rarely appropriate for new APIs, instead often +appearing in legacy APIs or in specialized circumstances. + +That being said, we offer the following recommendations and examples in case of difficulties to +determine what Web IDL language feature to use: + +* In the unusual case where the operation needs to return values of different types for different + argument types, [=overloaded|overloading=] will result in more expressive IDL fragments. This is almost never appropriate API design, and separate operations with distinct + names usually are a better choice for such cases. + + Suppose there is an operation calculate() that accepts a {{long}}, + {{DOMString}}, or CalculatableInterface (an [=interface type=]) as its + only argument, and returns a value of the same type as its argument. It would be clearer to + write the IDL fragment using [=overloaded=] operations as + +
+        interface A {
+          long calculate(long input);
+          DOMString calculate(DOMString input);
+          CalculatableInterface calculate(CalculatableInterface input);
+        };
+    
+ + than using a [=union type=] with a [=typedef=] as + +
+        typedef (long or DOMString or CalculatableInterface) Calculatable;
+        interface A {
+          Calculatable calculate(Calculatable input);
+        };
+    
+ + which does not convey the fact that the return value is always of the same type as input. + + If the specified calculate() is a new API and does not have any + compatibility concerns, it is suggested to use different names for the overloaded operations, + perhaps as + +
+        interface A {
+          long calculateNumber(long input);
+          DOMString calculateString(DOMString input);
+          CalculatableInterface calculateCalculatableInterface(CalculatableInterface input);
+        };
+    
+ + which allows Web developers to write explicit and unambiguous code. + +* When the operation has significantly different semantics for different argument types or + lengths, [=overloaded|overloading=] is preferred. Again, in such scenarios, it is usually better + to create separate operations with distinct names, but legacy APIs sometimes follow this + pattern. + + As an example, the {{CSS/supports(property, value)}} and {{CSS/supports(conditionText)}} + operations of the {{CSS}} interface are defined as the + following IDL fragment [[CSS3-CONDITIONAL]] [[CSSOM]]. + +
+        partial interface CSS {
+          static boolean supports(CSSOMString property, CSSOMString value);
+          static boolean supports(CSSOMString conditionText);
+        };
+    
+ + Using [=optional arguments=] one can rewrite the IDL fragment as follows: + +
+        partial interface CSSExcerptOptional {
+          static boolean supports(CSSOMString propertyOrConditionText, optional CSSOMString value);
+        };
+    
+ + Even though the IDL is shorter in the second version, two distinctively different concepts are + conflated in the first argument. Without [=overloaded|overloads=], the question "is property or conditionText paired with value?" + is much more difficult to answer without reading the [=method steps=] of the operation. This + makes the second version remarkably less readable than the first. + + Another consideration is that the [=method steps=] for [=overloaded=] operations can be + specified in separate blocks, which can aid in both reading and writing specifications. This is + not the case for [=optional arguments=]. This means that in the first case the specification + author can write the [=method steps=] of the operations as: + +
+ + The supports(property, value) + method steps are: + + 1. … + + ---- + + The supports(conditionText) method steps are: + + 1. … + +
+ + Yet using value as an [=optional argument=], the specification author has to + use more boilerplate-style text to effectively replicate the [=overload resolution algorithm=]. + +
+ + The supports(|propertyOrConditionText|, |value|) method steps are: + + 1. If |value| is given, then: + 1. Let property be |propertyOrConditionText|. + 1. … + 1. Otherwise: + 1. Let conditionText be |propertyOrConditionText|. + 1. … + +
+ + If the two overloads have little to no shared parts, it is better to leave overload resolution + to the IDL mechanism. + +* If the operation accepts multiple types for multiple arguments with no coupling between types of + different arguments, [=union types=] can sometimes be the only viable solution. + +
+        typedef (long long or DOMString or CalculatableInterface) SupportedArgument;
+        interface A {
+          undefined add(SupportedArgument operand1, SupportedArgument operand2);
+        };
+    
+ + For the add() operation above, to specify it using + [=overloaded|overloads=] would require + +
+        interface A {
+          undefined add(long long operand1, long long operand2);
+          undefined add(long long operand1, DOMString operand2);
+          undefined add(long long operand1, CalculatableInterface operand2);
+          undefined add(DOMString operand1, long long operand2);
+          undefined add(DOMString operand1, DOMString operand2);
+          undefined add(DOMString operand1, CalculatableInterface operand2);
+          undefined add(CalculatableInterface operand1, long long operand2);
+          undefined add(CalculatableInterface operand1, DOMString operand2);
+          undefined add(CalculatableInterface operand1, CalculatableInterface operand2);
+        };
+    
+ + and nine times the corresponding prose! + +* Specification authors are encouraged to treat missing argument and undefined + argument the same way in the JavaScript language binding. + + Given the following IDL fragment: + +
+        interface A {
+          undefined foo();
+          undefined foo(Node? arg);
+        };
+    
+ + Using the JavaScript language binding, calling foo(undefined) and + foo(null) would both run the steps corresponding to the foo(|arg|) operation, with |arg| set to null, while foo() alone + would go to the first overload. This can be a surprising behavior for many API users. Instead, + specification authors are encouraged to use an [=optional argument=], which would categorize + both foo() and foo(undefined) as "|arg| is missing". + +
+        interface A {
+          undefined foo(optional Node? arg);
+        };
+    
+ + In general, optionality is best expressed using the optional keyword, and not + using overloads. + +When the case fits none of the categories above, it is up to the specification author to choose the +style, since it is most likely that either style would sufficiently and conveniently describe the +intended behavior. However, the definition and conversion algorithms of +[=union types=] and [=optional arguments=] are simpler to implement and reason about than [=overload +resolution algorithm|those=] of [=overloaded|overloads=], and usually result in more idiomatic APIs +in the JavaScript language binding. Thus, unless any other considerations apply, [=union types=], +[=optional arguments=], or both are the default choice. + +Specifications are also free to mix and match union types and overloads, if the author finds it +appropriate and convenient. + +
+ + +

Iterable declarations

+ +An [=interface=] can be declared to be +iterable by using an iterable declaration +(matching Iterable) in the body of the interface. + +
+    interface interface_identifier {
+      iterable<value_type>;
+      iterable<key_type, value_type>;
+    };
+
+ +Objects implementing an interface that is declared to be iterable +support being iterated over to obtain a sequence of values. + +Note: In the JavaScript language binding, an interface that is iterable +will have entries, forEach, +keys, values, and {{%Symbol.iterator%}} +properties on its [=interface prototype object=]. + +If a single type parameter is given, then the interface has a +value iterator and provides +values of the specified type. +If two type parameters are given, then the interface has a +pair iterator and provides +[=value pairs=] with the given types. + +A value pair, given a key type and a value type, is a [=/struct=] with two +[=struct/items=]: +1. an [=struct/item=] whose [=struct/name=] is "key", which is referred to as the [=value pair=]'s + key, and whose value is an IDL value of the key type; +1. an [=struct/item=] whose [=struct/name=] is "value", which is referred to as the + [=value pair=]'s value, and whose value is an IDL value of the + value type. + +A [=value iterator=] +must only be declared on an interface +that [=support indexed properties|supports indexed properties=]. +The value-type of the [=value iterator=] +must be the same as the type returned by +the [=indexed property getter=]. +A [=value iterator=] is implicitly +defined to iterate over the object's indexed properties. + +A [=pair iterator=] +must not be declared on an interface +that [=support indexed properties|supports indexed properties=]. + +Prose accompanying an [=interface=] with a [=pair iterator=] must define a [=/list=] of +[=value pairs=] for each instance of the [=interface=], which is the list of +value pairs to iterate over. + +
+ + The JavaScript forEach method that is generated for a + [=value iterator=] + invokes its callback like Array.prototype.forEach does, and the forEach + method for a [=pair iterator=] + invokes its callback like Map.prototype.forEach does. + + Since [=value iterators=] + are currently allowed only on interfaces that + [=support indexed properties=], + it makes sense to use an Array-like forEach method. + There could be a need for [=value iterators=] + (a) on interfaces that do not + [=support indexed properties=], + or (b) with a forEach method that instead invokes its callback like + Set.prototype.forEach (where the key is the same as the value). + If you're creating an API that needs such a forEach method, please + file an issue. + +
+ +Note: This is how [=array iterator objects=] work. +For interfaces that [=support indexed properties=], +the iterator objects returned by entries, +keys, values, and {{%Symbol.iterator%}} are +actual [=array iterator objects=]. + +[=Interfaces=] with an [=iterable declaration=] must not have any [=attributes=], [=constants=], or +[=regular operations=] named "entries", "forEach", "keys", or +"values", or have any [=inherited interfaces=] that have [=attributes=], [=constants=], +or [=regular operations=] with these names. + +
+ + Consider the following interface SessionManager, which allows access to + a number of Session objects keyed by username: + +
+        [Exposed=Window]
+        interface SessionManager {
+          Session getSessionForUser(DOMString username);
+
+          iterable<DOMString, Session>;
+        };
+
+        [Exposed=Window]
+        interface Session {
+          readonly attribute DOMString username;
+          // ...
+        };
+    
+ + The behavior of the iterator could be defined like so: + +
+ + The [=value pairs to iterate over=] are the list of [=value pairs=] with the + [=value pair/key=] being the username and the [=value pair/value=] being the open + Session object on the SessionManager + object corresponding to that username, sorted by username. + +
+ + In the JavaScript language binding, the [=interface prototype object=] + for the SessionManager [=interface=] + has a values method that is a function, which, when invoked, + returns an iterator object that itself has a next method that returns the + next value to be iterated over. It has keys and entries + methods that iterate over the usernames of session objects + and username/Session object pairs, respectively. It also has + a {{%Symbol.iterator%}} method that allows a SessionManager + to be used in a for..of loop that has the same value as the + entries method: + +
+        // Get an instance of SessionManager.
+        // Assume that it has sessions for two users, "anna" and "brian".
+        var sm = getSessionManager();
+
+        typeof SessionManager.prototype.values;            // Evaluates to "function"
+        var it = sm.values();                              // values() returns an iterator object
+        String(it);                                        // Evaluates to "[object SessionManager Iterator]"
+        typeof it.next;                                    // Evaluates to "function"
+
+        // This loop will log "anna" and then "brian".
+        for (;;) {
+          let result = it.next();
+          if (result.done) {
+            break;
+          }
+          let session = result.value;
+          console.log(session.username);
+        }
+
+        // This loop will also log "anna" and then "brian".
+        for (let username of sm.keys()) {
+          console.log(username);
+        }
+
+        // Yet another way of accomplishing the same.
+        for (let [username, session] of sm) {
+          console.log(username);
+        }
+    
+
+ +An interface must not have more than one +[=iterable declaration=]. +The [=inherited interfaces=] +of an interface with an +[=iterable declaration=] +must not also have an +[=iterable declaration=]. +An interface with an [=iterable declaration=] +and its [=inherited interfaces=] +must not have a +[=maplike declaration=], +[=setlike declaration=], or +[=asynchronously iterable declaration=]. + +The following extended attributes are applicable to [=iterable declarations=]: +[{{CrossOriginIsolated}}], +[{{Exposed}}], and +[{{SecureContext}}]. + +
+    Iterable :
+        "iterable" "<" TypeWithExtendedAttributes OptionalType ">" ";"
+
+ +
+    OptionalType :
+        "," TypeWithExtendedAttributes
+        ε
+
+ + +

Asynchronously iterable declarations

+ +An [=interface=] can be declared to be asynchronously iterable by using an +asynchronously iterable declaration +(matching AsyncIterable) in the body of the +[=interface=]. + +
+    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... */);
+    };
+
+ +Objects that [=implement=] an [=interface=] that is declared to be asynchronously iterable support +being iterated over asynchronously to obtain a sequence of values. + +If a single type parameter is given, then the interface has a +value asynchronously iterable declaration and asynchronously provides values of the +specified type. If two type parameters are given, then the interface has a +pair asynchronously iterable declaration and asynchronously provides +[=value pairs=] with the given types. + +If given, an [=asynchronously iterable declaration=]'s arguments (matching +ArgumentList) must all be [=optional arguments=]. + +
+ In the JavaScript language binding, an interface that is asynchronously iterable will have + {{%Symbol.asyncIterator%}} and values properties on its + [=interface prototype object=]. If the interface has a + [=pair asynchronously iterable declaration=], it will additionally have + entries and keys properties. All of these + methods can be passed optional arguments, which correspond to the argument list in the + [=asynchronously iterable declaration=], and are processed by the + [=asynchronous iterator initialization steps=], if any exist. + + With this in mind, the requirement that all arguments be optional ensures that, in the + JavaScript binding, for-await-of can work directly on + instances of the interface, since for-await-of calls the + {{%Symbol.asyncIterator%}} method with no arguments. +
+ +Prose accompanying an [=interface=] with an [=asynchronously iterable declaration=] must define a +get the next iteration result algorithm. +This algorithm receives the instance of the [=interface=] that is being iterated, as well as the +async iterator itself (which can be useful for storing state). +It must return a {{Promise}} that either rejects, resolves with a special end of +iteration value to signal the end of the iteration, or resolves with one of the following: + +: for [=value asynchronously iterable declarations=]: +:: a value of the type given in the declaration; +: for [=pair asynchronously iterable declarations=]: +:: a [=tuple=] containing a value of the first type given in the declaration, and a value of the second type given in the declaration. + +The prose may also define an asynchronous iterator return algorithm. This +algorithm receives the instance of the [=interface=] that is being iterated, the async iterator +itself, and a single argument value of type {{any}}. This algorithm is invoked in the case of +premature termination of the async iterator. It must return a {{Promise}}; if that promise +fulfills, its fulfillment value will be ignored, but if it rejects, that failure will be passed on +to users of the async iterator API. + +

In the JavaScript binding, this algorithm allows customizing the behavior when the +async iterator's return() method is invoked. This most commonly occurs when a +break or return statement causes an exit from a +for-await-of loop. + +

We could add a similar hook for throw(). So far there has been no need, +but if you are creating an API that needs such capabilities, please +file an issue. + +The prose may also define asynchronous iterator initialization steps. These +receive the instance of the [=interface=] being iterated, the newly-created iterator object, and a +[=list=] of IDL values representing the arguments passed, if any. + +[=Interfaces=] with an [=asynchronously iterable declaration=] must not have any [=attributes=], +[=constants=], or [=regular operations=] named "entries", "keys", or +"values", or have any [=inherited interfaces=] that have [=attributes=], [=constants=], +or [=regular operations=] with these names. + +

+ + Consider the following interface SessionManager, which allows access + to a number of Session objects keyed by username: + +
+        [Exposed=Window]
+        interface SessionManager {
+          Session getSessionForUser(DOMString username);
+
+          async iterable<DOMString, Session>;
+        };
+
+        [Exposed=Window]
+        interface Session {
+          readonly attribute DOMString username;
+          // ...
+        };
+    
+ + The behavior of the iterator could be defined like so: + +
+ + The [=asynchronous iterator initialization steps=] for a SessionManager + async iterator |iterator| are: + + 1. Set |iterator|'s current state to "not + yet started". + + To [=get the next iteration result=] for a SessionManager + |manager| and its async iterator |iterator|: + + 1. Let |promise| be a new promise. + 1. Let |key| be the following value, if it exists, or null otherwise: +
+ : If |iterator|'s [=SessionManager async iterator/current state=] is "not yet + started" + :: the smallest username in |manager|'s open sessions, in lexicographical order + + : Otherwise + :: the smallest username in |manager|'s open sessions that is greater than + |iterator|'s current state, in lexicographical order +
+ + Note: |iterator|'s [=SessionManager async iterator/current state=] might no longer be + present in the open sessions. + 1. If |key| is null, then: + 1. Resolve |promise| with [=end of iteration=]. + 1. Otherwise: + 1. Let |session| be the Session object corresponding to |key|. + 1. Resolve |promise| with (|username|, |session|). + 1. Set |iterator|'s [=SessionManager async iterator/current state=] to |username|. + 1. Return |promise|. + +
+ + In the JavaScript language binding, the [=interface prototype object=] for the + SessionManager [=interface=] has a values method that is a + function, which, when invoked, returns an asynchronous iterator object that itself has a + next method that returns the next value to be iterated over. + It has keys and entries methods that iterate over the usernames of + session objects and (username, Session) object pairs, respectively. + It also has a {{%Symbol.asyncIterator%}} method that allows a SessionManager + to be used in a for await..of loop that has the same value as the + entries method: + +
+        // Get an instance of SessionManager.
+        // Assume that it has sessions for two users, "anna" and "brian".
+        var sm = getSessionManager();
+
+        typeof SessionManager.prototype.values;            // Evaluates to "function"
+        var it = sm.values();                              // values() returns an iterator object
+        typeof it.next;                                    // Evaluates to "function"
+
+        // This loop will log "anna" and then "brian".
+        for await (let username of sm.keys()) {
+          console.log(username);
+        }
+
+        // Yet another way of accomplishing the same.
+        for await (let [username, session] of sm) {
+          console.log(username);
+        }
+    
+
+ +An [=interface=] must not have more than one [=asynchronously iterable declaration=]. +The [=inherited interfaces=] of an [=interface=] with an [=asynchronously iterable declaration=] +must not also have an [=asynchronously iterable declaration=]. +An [=interface=] with an [=asynchronously iterable declaration=] and its [=inherited interfaces=] +must not have a [=maplike declaration=], [=setlike declaration=], or [=iterable declaration=]. + +The following extended attributes are applicable to [=asynchronously iterable declarations=]: +[{{CrossOriginIsolated}}], +[{{Exposed}}], and +[{{SecureContext}}]. + +Issue: these [=extended attributes=] are not currently taken into account. +When they are, the effect will be as you would expect. + +
+    AsyncIterable :
+        "async" "iterable" "<" TypeWithExtendedAttributes OptionalType ">" OptionalArgumentList ";"
+
+ +
+    OptionalArgumentList :
+        "(" ArgumentList ")"
+        ε
+
+ + +

Maplike declarations

+ +An [=interface=] can be declared to be +maplike by using a maplike declaration +(matching ReadWriteMaplike or +readonly MaplikeRest) in the body of the interface. + +
+    interface interface_identifier {
+      readonly maplike<key_type, value_type>;
+      maplike<key_type, value_type>;
+    };
+
+ +Objects implementing an interface that is declared to be maplike +represent an [=ordered map=] of key–value pairs, initially empty, +known as that object's map entries. +The types used for the keys and values are given in the angle +brackets of the maplike declaration. Keys are required to be unique. + +Specification authors can modify the contents of the [=map entries=], +which will automatically be reflected in the contents of the object +as observed by JavaScript code. + +Maplike interfaces support an API for querying the map entries +appropriate for the language binding. If the readonly +keyword is not used, then it also supports an API for modifying +the map entries. + +Note: In the JavaScript language binding, the API for interacting +with the map entries is similar to that available on JavaScript +{{Map}} objects. If the readonly +keyword is used, this includes entries, +forEach, get, +has, keys, +values, {{%Symbol.iterator%}} methods, and a +size getter. +For read–write maplikes, it also includes clear, +delete, and set methods. + +Maplike interfaces must not have any [=attributes=], [=constants=], or [=regular operations=] named +"entries", "forEach", "get", "has", +"keys", "size", or "values", or have any +[=inherited interfaces=] that have [=attributes=], [=constants=], or [=regular operations=] with +these names. + +Read–write maplike interfaces must not +have any [=attributes=] +or [=constants=] named +"clear", "delete", +or "set", or have any [=inherited interfaces=] +that have [=attributes=] or [=constants=] with these names. + +Note: Read-write maplike interfaces can have regular operations named +"clear", "delete", or "set", which will override the default +implementation of those methods (defined in [[#js-maplike]]). If such regular operations are +defined, they must match the input and output expectations of each method, defined in their default +implementation sections. + +An interface must not have more than one +[=maplike declaration=]. +The [=inherited interfaces=] +of a maplike interface must not +also have a [=maplike declaration=]. +A maplike interface and its [=inherited interfaces=] +must not have an +[=iterable declaration=], +an [=asynchronously iterable declaration=], +a [=setlike declaration=], or +an [=indexed property getter=]. + +
+ +
+ +
+    ReadWriteMaplike :
+        MaplikeRest
+
+ +
+    MaplikeRest :
+        "maplike" "<" TypeWithExtendedAttributes "," TypeWithExtendedAttributes ">" ";"
+
+ +No [=extended attributes=] +defined in this specification are applicable to [=maplike declarations=]. + +Issue: Add example. + + +

Setlike declarations

+ +An [=interface=] can be declared to be +setlike by using a setlike declaration +(matching ReadWriteSetlike or +readonly SetlikeRest) in the body of the interface. + +
+    interface interface_identifier {
+      readonly setlike<type>;
+      setlike<type>;
+    };
+
+ +Objects implementing an interface that is declared to be setlike +represent an [=ordered set=] of values, initially empty, +known as that object's set entries. +The type of the values is given in the angle +brackets of the setlike declaration. Values are required to be unique. + +Specification authors can modify the contents of the [=set entries=], +which will automatically be reflected in the contents of the object +as observed by JavaScript code. + +Setlike interfaces support an API for querying the set entries +appropriate for the language binding. If the readonly +keyword is not used, then it also supports an API for modifying +the set entries. + +Note: In the JavaScript language binding, the API for interacting +with the set entries is similar to that available on JavaScript +{{Set}} objects. If the readonly +keyword is used, this includes entries, +forEach, has, +keys, values, +{{%Symbol.iterator%}} methods, and a size getter. +For read–write setlikes, it also includes add, +clear, and delete methods. + +Setlike interfaces must not have any [=attributes=], [=constants=], or [=regular operations=] named +"entries", "forEach", "has", "keys", +"size", or "values", or have any [=inherited interfaces=] that have +[=attributes=], [=constants=], or [=regular operations=] with these names. + +Read–write setlike interfaces must not +have any [=attributes=] +or [=constants=] named +"add", "clear", +or "delete", or have any [=inherited interfaces=] +that have [=attributes=] or [=constants=] with these names. + +Note: Read-write setlike interfaces can have regular operations named +"add", "clear", or "delete", which will override the default +implementation of those methods (defined in [[#js-setlike]]). If such regular operations are +defined, they must match the input and output expectations of each method, defined in their default +implementation sections. + +An interface must not have more than one +[=setlike declaration=]. +The [=inherited interfaces=] +of a setlike interface must not +also have a [=setlike declaration=]. +A setlike interface and its [=inherited interfaces=] +must not have an +[=iterable declaration=], +an [=asynchronously iterable declaration=], +a [=maplike declaration=], or +an [=indexed property getter=]. + +
+ +
+ +
+    ReadWriteSetlike :
+        SetlikeRest
+
+ +
+    SetlikeRest :
+        "setlike" "<" TypeWithExtendedAttributes ">" ";"
+
+ +No [=extended attributes=] +defined in this specification are applicable to [=setlike declarations=]. + +Issue: Add example. + + +

Namespaces

+ +A namespace is a definition (matching Namespace) that declares a global singleton with +associated behaviors. + +
+    namespace identifier {
+      /* namespace_members... */
+    };
+
+ +A namespace is a specification of a set of +namespace members +(matching NamespaceMembers), which are the +[=regular operations=], [=read only=] [=regular attributes=], and [=constants=] that appear between +the braces in the namespace declaration. These operations and attributes describe the behaviors +packaged into the namespace. + +As with interfaces, the IDL for namespaces can be split into multiple parts by using +partial namespace definitions +(matching partial Namespace). The [=identifier=] of a partial namespace definition must be the same as the identifier of a namespace definition. +All of the members that appear on each of the partial namespace definitions are +considered to be members of the namespace itself. + +
+    namespace SomeNamespace {
+      /* namespace_members... */
+    };
+
+    partial namespace SomeNamespace {
+      /* namespace_members... */
+    };
+
+ +Note: As with partial interface definitions, partial namespace definitions are intended for +use as a specification editorial aide, allowing the definition of a namespace to be +separated over more than one section of the document, and sometimes multiple +documents. + +The order that members appear in has significance for property enumeration in the JavaScript binding. + +Note that unlike interfaces or dictionaries, namespaces do not create types. + +Of the extended attributes defined in this specification, only the [{{CrossOriginIsolated}}], [{{Exposed}}], and [{{SecureContext}}] extended attributes are applicable to namespaces. + +[=Namespaces=] must be annotated with the [{{Exposed}}] [=extended attribute=]. + +
+ +
+ +
+    Namespace :
+        "namespace" identifier "{" NamespaceMembers "}" ";"
+
+ +
+    NamespaceMembers :
+        ExtendedAttributeList NamespaceMember NamespaceMembers
+        ε
+
+ +
+    NamespaceMember :
+        RegularOperation
+        "readonly" AttributeRest
+        Const
+
+ +
+ + The following [=IDL fragment=] defines a + [=namespace=]. + +
+        namespace VectorUtils {
+          readonly attribute Vector unit;
+          double dotProduct(Vector x, Vector y);
+          Vector crossProduct(Vector x, Vector y);
+        };
+    
+ + A JavaScript implementation would then expose a global VectorUtils + data property which was a simple object (with prototype + {{%Object.prototype%}}) with enumerable data properties for each declared operation, and + enumerable get-only accessors for each declared attribute: + +
+        Object.getPrototypeOf(VectorUtils);                         // Evaluates to Object.prototype.
+        Object.keys(VectorUtils);                                   // Evaluates to ["dotProduct", "crossProduct"].
+        Object.getOwnPropertyDescriptor(VectorUtils, "dotProduct"); // Evaluates to { value: <a function>, enumerable: true, configurable: true, writable: true }.
+        Object.getOwnPropertyDescriptor(VectorUtils, "unit");       // Evaluates to { get: <a function>, enumerable: true, configurable: true }.
+    
+
+ + +

Dictionaries

+ +A dictionary is a definition (matching +Dictionary) +used to define an [=ordered map=] data type with a fixed, ordered set of [=map/entries=], +termed dictionary members, +where [=map/keys=] are strings and [=map/values=] are of a particular type specified in the definition. + +
+    dictionary identifier {
+      /* dictionary_members... */
+    };
+
+ +Dictionary instances do not retain a reference to their language-specific representations (e.g., +the corresponding JavaScript object). So for example, returning a dictionary from an [=operation=] +will result in a new JavaScript object being created from the current values of the dictionary. And, +an operation that accepts a dictionary as an argument will perform a one-time conversion from the +given JavaScript value into the dictionary, based on the current properties of the JavaScript +object. Modifications to the dictionary will not be reflected in the corresponding JavaScript +object, and vice-versa. + +Dictionaries must not be used as the type of an [=attribute=] or [=constant=]. + +A dictionary can be defined to inherit from another dictionary. +If the identifier of the dictionary is followed by a colon and a [=identifier=], +then that identifier identifies the inherited dictionary. The identifier +must identify a dictionary. + +A dictionary must not be declared such that +its inheritance hierarchy has a cycle. That is, a dictionary +|A| cannot inherit from itself, nor can it inherit from another +dictionary |B| that inherits from |A|, and so on. + +
+    dictionary Base {
+      /* dictionary_members... */
+    };
+
+    dictionary Derived : Base {
+      /* dictionary_members... */
+    };
+
+ +The inherited dictionaries of +a given dictionary |D| is the set of all dictionaries that |D| +inherits from, directly or indirectly. If |D| does not [=dictionary/inherit=] +from another dictionary, then the set is empty. Otherwise, the set +includes the dictionary |E| that |D| [=interface/inherits=] +from and all of |E|'s [=inherited dictionaries=]. + +[=Dictionary members=] can be specified as +required, meaning that +converting a language-specific value to a dictionary requires providing a value for that member. Any +dictionary member that is not [=dictionary member/required=] is +optional. + +Note that specifying [=dictionary members=] as [=dictionary member/required=] only has +an observable effect when converting other representations of dictionaries (like a JavaScript value +supplied as an argument to an [=operation=]) to an IDL dictionary. Specification authors should +leave the members [=dictionary member/optional=] in all other cases, including when a dictionary +type is used solely as the [=return type=] of [=operations=]. + +A given dictionary value of type |D| can have [=map/entries=] for each of the dictionary members +defined on |D| and on any of |D|'s [=inherited dictionaries=]. Dictionary members that are specified +as [=dictionary member/required=], or that are specified as having a +[=dictionary member/default value=], will always have such corresponding [=map/entries=]. Other +members' entries might or might not [=map/exist=] in the dictionary value. + +

+ In the JavaScript binding, a value of undefined for the property + corresponding to a [=dictionary member=] is treated the same as omitting that property. Thus, it + will cause an error if the member is [=dictionary member/required=], or will trigger the + [=dictionary member/default value=] if one is present, or will result in no [=map/entry=] + existing in the dictionary value otherwise. +

+ +

+ As with [=optional argument/default value|operation argument default values=], it is strongly + encouraged not to use true as the [=dictionary member/default value=] for + {{boolean}}-typed [=dictionary members=], as this can be confusing for authors who might + otherwise expect the default conversion of undefined to be used (i.e., + false). [[API-DESIGN-PRINCIPLES]] +

+ +An [=ordered map=] with string [=map/keys=] can be implicitly treated as a dictionary value of a +specific dictionary |D| if all of its [=map/entries=] correspond to [=dictionary members=], as long +as those entries have the correct types, and there are [=map/entries=] present for any +[=dictionary member/required=] or [=dictionary member/default value|defaulted=] dictionary members. + +
+
+    dictionary Descriptor {
+      DOMString name;
+      sequence<unsigned long> serviceIdentifiers;
+    };
+    
+ + A Descriptor dictionary could be created as in the following steps: + + 1. Let |identifiers| be « 1, 3, 7 ». + 1. Return «[ "name" → "test", "serviceIdentifiers" → |identifiers| ]». +
+ +Each [=dictionary member=] (matching +DictionaryMember) is specified +as a type (matching Type) followed by an +[=identifier=] +(given by an identifier token following +the type). The identifier is the key name of the key–value pair. +If the Type +is an [=identifier=] +followed by ?, then the identifier +must identify an +[=interface=], [=enumeration=], +[=callback function=], [=callback interface=] or [=typedef=]. +If the dictionary member type is an identifier +not followed by ?, then the identifier must +identify any one of those definitions or a [=dictionary=]. + +If the type of the [=dictionary member=], after resolving typedefs, +is a [=nullable type=], +its [=nullable types/inner type=] must not be a [=dictionary type=]. + +
+    dictionary identifier {
+      type identifier;
+    };
+
+ +If the identifier for an [=dictionary member/optional=] [=dictionary member=] is followed by a +U+003D (=) and a value (matching DefaultValue), then that gives the dictionary member its default value, which +is the value used by default when author code or specification text does not provide a value for +that member. + +
+    dictionary identifier {
+      type identifier = "value";
+    };
+
+ +When a boolean literal token (true or false), +the null token, +an integer token, a +decimal token, +one of the three special floating point literal values (Infinity, +-Infinity or NaN), +a string token, the two +token sequence [], or the two token sequence {} is +used as the +[=dictionary member/default value=], +it is interpreted in the same way as for an [=operation=]'s +[=optional argument/default value|optional argument default value=]. + +If the type of the [=dictionary member=] +is an [=enumeration=], then its +[=dictionary member/default value=] if specified must +be one of the [=enumeration's values=]. + +If the type of the dictionary member is preceded by the +required keyword, the member is considered a [=dictionary member/required=] +[=dictionary member=]. + +
+    dictionary identifier {
+      required type identifier;
+    };
+
+ +The type of a dictionary member must not include +the dictionary it appears on. A type includes a dictionary |D| +if at least one of the following is true: + +* the type is |D| +* the type is a dictionary that [=dictionary/inherits=] from |D| +* the type is a [=nullable type=] + whose [=nullable types/inner type=] includes |D| +* the type is a [=sequence type=] or [=frozen array type|frozen array=] + whose element type includes |D| +* the type is a [=union type=], + one of whose [=member types=] + includes |D| +* the type is a dictionary, one of whose members or inherited members has + a type that includes |D| +* the type is [=record=]<|K|, |V|> where |V| includes |D| + +As with interfaces, the IDL for dictionaries can be split into multiple parts +by using partial dictionary definitions +(matching partial Dictionary). +The [=identifier=] of a partial +dictionary definition must be the same as the +identifier of a dictionary definition. All of the members that appear on each +of the partial dictionary definitions are considered to be members of +the dictionary itself. + +
+    dictionary SomeDictionary {
+      /* dictionary_members... */
+    };
+
+    partial dictionary SomeDictionary {
+      /* dictionary_members... */
+    };
+
+ +Note: As with partial interface definitions, partial dictionary definitions are intended for use as a specification +editorial aide, allowing the definition of an interface to be separated +over more than one section of the document, and sometimes multiple documents. + +The order of the [=dictionary members=] +on a given dictionary is such that inherited dictionary members are ordered +before non-inherited members, and the dictionary members on the one +dictionary definition (including any partial dictionary definitions) are +ordered lexicographically by the Unicode codepoints that comprise their +identifiers. + +
+ + For example, with the following definitions: + +
+        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;
+        };
+    
+ + the order of the [=dictionary members=] + of a dictionary value of type C is + c, d, g, h, a, b, e, f. + + Dictionaries need to have their members ordered because + in some language bindings the behavior observed when passing + a dictionary value to a platform object depends on the order + the dictionary members are fetched. For example, consider the + following additional interface: + +
+        [Exposed=Window]
+        interface Something {
+          undefined f(A a);
+        };
+    
+ + and this JavaScript code: + +
+        var something = getSomething();  // Get an instance of 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);
+    
+ + The order that the dictionary members are fetched in determines + what values they will be taken to have. Since the order for + A is defined to be c then d, + the value for c will be 1 and the value for d will be 2. + +
+ +The identifier of a dictionary member must not be +the same as that of another dictionary member defined on the dictionary or +on that dictionary's [=inherited dictionaries=]. + +No [=extended attributes=] are applicable to dictionaries. + +
+ +
+ +
+    Dictionary :
+        "dictionary" identifier Inheritance "{" DictionaryMembers "}" ";"
+
+ +
+    DictionaryMembers :
+        DictionaryMember DictionaryMembers
+        ε
+
+ +
+    DictionaryMember :
+        ExtendedAttributeList DictionaryMemberRest
+
+ +
+    DictionaryMemberRest :
+        "required" TypeWithExtendedAttributes identifier ";"
+        Type identifier Default ";"
+
+ +
+    PartialDictionary :
+        "dictionary" identifier "{" DictionaryMembers "}" ";"
+
+ +
+    Default :
+        "=" DefaultValue
+        ε
+
+ +
+ +
+ +
+ + One use of dictionary types is to allow a number of optional + arguments to + an [=operation=] without being + constrained as to the order they are specified at the call site. For example, + consider the following [=IDL fragment=]: + +
+        [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);
+        };
+    
+ + In a JavaScript implementation of the IDL, an Object + can be passed in for the optional + PaintOptions dictionary: + +
+        // Get an instance of GraphicsContext.
+        var ctx = getGraphicsContext();
+
+        // Draw a rectangle.
+        ctx.drawRectangle(300, 200, { fillPattern: "red", position: new Point(10, 10) });
+    
+ + The members of PaintOptions are [=dictionary member/optional=]. + If fillPattern is omitted, the definition of + drawRectangle can assume that it has the given default values + and not include explicit wording to handle its omission. + drawRectangle needs to explicitly handle the case where + strokePattern and position are omitted. + +
+ + +

Exceptions

+ +An exception is a type of object that represents an error and +which can be thrown or treated as a first class value by implementations. Web IDL has a number of +pre-defined exceptions that specifications can reference and throw in their definition of +operations, attributes, and so on. Custom exception types can also be defined, as [=interfaces=] +that [=interface/inherit=] from {{DOMException}}. + +A simple exception is identified by one of the +following types: + +* EvalError +* RangeError +* ReferenceError +* TypeError +* URIError + +These correspond to all of the JavaScript [=ECMAScript/error objects=] (apart from +{{SyntaxError}} and {{Error}}, which are deliberately +omitted as they are reserved for use by the JavaScript parser and by authors, respectively). The +meaning of each [=simple exception=] matches its corresponding error object in the JavaScript +specification. + +The second kind of exception is a {{DOMException}}, which provides further +programmatically-introspectable detail on the error that occurred by giving a [=DOMException/name=]. +Such [=DOMException/names=] are drawn from the DOMException names table below. + +

As {{DOMException}} is an [=interface type=], it can be used as a type in IDL. This +allows for example an [=operation=] to be declared to have a {{DOMException}} [=return type=]. This +is generally a bad pattern, however, as exceptions are meant to be thrown and not returned. + +The final kind of exception is a derived interface of {{DOMException}}. These are more complicated, +and thus described in the dedicated section [[#idl-DOMException-derived-interfaces]]. + +[=Simple exceptions=] can be +created by providing their +type name. A {{DOMException}} can be [=exception/created=] by providing its [=DOMException/name=] +followed by {{DOMException}}. Exceptions can also be +thrown, by providing the same details +required to [=exception/create=] one. In both cases, the caller may provide additional information +about what the exception indicates, which is useful when constructing the exception's message. + +

+

Here is are some examples of wording to use to create and throw exceptions. + To throw a new [=simple exception=] whose type is {{TypeError}}: + +

+

[=exception/Throw=] a {{TypeError}}. +

+ +

To throw a new {{DOMException}} with [=DOMException/name=] "{{NotAllowedError}}": + +

+

[=exception/Throw=] a "{{NotAllowedError}}" {{DOMException}}. +

+ +

To create a new {{DOMException}} with [=DOMException/name=] "{{SyntaxError}}": + +

+

Let object be a newly [=exception/created=] "{{SyntaxError}}" + {{DOMException}}. +

+ +

To [=reject=] a promise with a new {{DOMException}} with [=DOMException/name=] + "{{OperationError}}": + +

+ [=Reject=] p with an "{{OperationError}}" {{DOMException}}. +
+
+ +
+

An example of including additional information used to construct the exception message would + be: + +

+ [=exception/Throw=] a "{{SyntaxError}}" {{DOMException}} indicating that the given value + had disallowed trailing spaces. +
+ +

Such additional context is most helpful to implementers when it is not immediately obvious + why the exception is being thrown, e.g., because there are many different steps in the algorithm + which throw a "{{SyntaxError}}" {{DOMException}}. In contrast, if your specification throws a + "{{NotAllowedError}}" {{DOMException}} immediately after checking if the user has provided + permission to use a given feature, it's fairly obvious what sort of message the implementation + ought to construct, and so specifying it is not necessary. +

+ +The resulting behavior from creating and throwing an exception is language binding specific. + +

See [[#js-creating-throwing-exceptions]] for details on what creating and throwing an +exception entails in the JavaScript language binding. + + +

Base {{DOMException}} error names

+ +The DOMException names table below lists all the +allowed [=DOMException/names=] for instances of the base {{DOMException}} interface, along with a +description of what such names mean, and legacy numeric error code values. + +

Interfaces [=interface/inheriting=] from {{DOMException}}, in the manner described +in [[#idl-DOMException-derived-interfaces]], will have their own names, not listed in this table. + +When [=exception/creating=] or [=exception/throwing=] a {{DOMException}}, specifications must use +one of these names. If a specification author believes none of these names are a good fit for their +case, they must +file an issue +to discuss adding a new name to the shared namespace, so that the community can coordinate such +efforts. Note that adding new use-case-specific names is only important if you believe web +developers will discriminate multiple error conditions arising from a single API. + +

The {{DOMException}} names marked as deprecated are kept for legacy purposes, but +their usage is discouraged. + +Note: Don't confuse the "{{SyntaxError!!exception}}" {{DOMException}} defined here +with JavaScript's {{SyntaxError}}. +"{{SyntaxError!!exception}}" {{DOMException}} is used to report parsing errors in web APIs, +for example when parsing selectors, +while the JavaScript {{SyntaxError}} is reserved for the JavaScript parser. +To help disambiguate this further, +always favor the "{{SyntaxError!!exception}}" {{DOMException}} notation +over just using {{SyntaxError!!exception}} to refer to the {{DOMException}}. [[DOM]] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameDescriptionLegacy code name and value
"IndexSizeError"Deprecated. Use {{RangeError}} instead.INDEX_SIZE_ERR (1)
"HierarchyRequestError"The operation would yield an incorrect [=node tree=]. [[DOM]]HIERARCHY_REQUEST_ERR (3)
"WrongDocumentError"The object is in the wrong [=document=]. [[DOM]]WRONG_DOCUMENT_ERR (4)
"InvalidCharacterError"The string contains invalid characters.INVALID_CHARACTER_ERR (5)
"NoModificationAllowedError"The object can not be modified.NO_MODIFICATION_ALLOWED_ERR (7)
"NotFoundError"The object can not be found here.NOT_FOUND_ERR (8)
"NotSupportedError"The operation is not supported.NOT_SUPPORTED_ERR (9)
"InUseAttributeError"The attribute is in use by another [=/element=]. [[DOM]]INUSE_ATTRIBUTE_ERR (10)
"InvalidStateError"The object is in an invalid state.INVALID_STATE_ERR (11)
"SyntaxError"The string did not match the expected pattern.SYNTAX_ERR (12)
"InvalidModificationError"The object can not be modified in this way.INVALID_MODIFICATION_ERR (13)
"NamespaceError"The operation is not allowed by Namespaces in XML. [[XML-NAMES]]NAMESPACE_ERR (14)
"InvalidAccessError" + Deprecated. + Use {{TypeError}} for invalid arguments, + "{{NotSupportedError!!exception}}" {{DOMException}} for unsupported operations, and + "{{NotAllowedError!!exception}}" {{DOMException}} for denied requests instead. + INVALID_ACCESS_ERR (15)
"TypeMismatchError"Deprecated. Use {{TypeError}} instead.TYPE_MISMATCH_ERR (17)
"SecurityError"The operation is insecure.SECURITY_ERR (18)
"NetworkError"A network error occurred.NETWORK_ERR (19)
"AbortError"The operation was aborted.ABORT_ERR (20)
"URLMismatchError"Deprecated.URL_MISMATCH_ERR (21)
"QuotaExceededError"The quota has been exceeded.QUOTA_EXCEEDED_ERR (22)
"TimeoutError"The operation timed out.TIMEOUT_ERR (23)
"InvalidNodeTypeError"The supplied [=node=] is incorrect or has an incorrect ancestor for this operation. [[DOM]]INVALID_NODE_TYPE_ERR (24)
"DataCloneError"The object can not be cloned.DATA_CLONE_ERR (25)
"EncodingError"The encoding operation (either encoded or decoding) failed.
"NotReadableError"The I/O read operation failed.
"UnknownError"The operation failed for an unknown transient reason (e.g. out of memory).
"ConstraintError"A mutation operation in a transaction failed because a constraint was not satisfied. [[INDEXEDDB]]
"DataError"Provided data is inadequate.
"TransactionInactiveError"A request was placed against a transaction which is currently not active, or which is finished. [[INDEXEDDB]]
"ReadOnlyError"The mutating operation was attempted in a "readonly" transaction. [[INDEXEDDB]]
"VersionError"An attempt was made to open a database using a lower version than the existing version. [[INDEXEDDB]]
"OperationError"The operation failed for an operation-specific reason.
"NotAllowedError"The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.
"OptOutError"The user opted out of the process.
+ +

{{DOMException}} derived interfaces

+ +When an exception needs to carry additional programmatically-introspectable information, beyond what +can be provided with a {{DOMException}}'s [=DOMException/name=], specification authors can create an +[=interface=] which [=interface/inherits=] from {{DOMException}}. Such interfaces need to follow +certain rules, in order to have a predictable shape for developers. Specifically: + +* The [=identifier=] of the [=interface=] must end with Error, and must not be any + of the names in the DOMException names table. +* The [=interface=] must have a [=constructor operation=] which sets the instance's + [=DOMException/name=] to the interface's [=identifier=]. +* Their [=constructor operation=] must take as its first parameter an [=optional argument|optional=] + {{DOMString}} named |message| defaulting to the empty string, and must set the instance's + [=DOMException/message=] to |message|. +* Their [=constructor operation=] should take as its second parameter a [=dictionary=] containing + the additional information that needs to be exposed. +* They should have [=read only=] [=attributes=], whose names are the same as the members of the + constructor dictionary, which return the values accepted by the constructor operation. +* They should be [=serializable objects=], whose [=serialization steps=] and + [=deserialization steps=] preserve the additional information. + +

These requirements mean that the inherited {{DOMException/code}} property of these +interfaces will always return 0. + +

+ The definition for a {{DOMException}} derived interface which carries along an additional + "protocol error code", which is derived from what the server sent over some some hypothetical + network protocol "protocol X", could look something like this: + +
+        [Exposed=Window, Serializable]
+        interface ProtocolXError : DOMException {
+          constructor(optional DOMString message = "", ProtocolXErrorOptions options);
+
+          readonly attribute unsigned long long errorCode;
+        };
+
+        dictionary ProtocolXErrorOptions {
+            required [EnforceRange] unsigned long long errorCode;
+        };
+    
+ + Every ProtocolXError instance has an error code, + a number. + +
+ The new ProtocolXError(|message|, |options|) constructor steps are: + + 1. Set [=this=]'s [=DOMException/name=] to "ProtocolXError". + 1. Set [=this=]'s [=DOMException/message=] to |message|. + 1. Set [=this=]'s [=ProtocolXError/error code=] to |options|["errorCode"]. +
+ +
+ The errorCode getter steps are to return [=this=]'s + [=ProtocolXError/error code=]. +
+ + ProtocolXError objects are [=serializable objects=]. + +
+ Their [=serialization steps=], given |value| and |serialized|, are: + + 1. Run the {{DOMException}} [=serialization steps=] given |value| and |serialized|. + 1. Set |serialized|.\[[ErrorCode]] to |value|'s [=ProtocolXError/error code=]. +
+ +
+ Their [=deserialization steps=], given |serialized| and |value|, are: + + 1. Run the {{DOMException}} [=deserialization steps=] given |serialized| and |value|. + 1. Set |value|'s [=ProtocolXError/error code=] to |serialized|.\[[ErrorCode]]. +
+
+ +To [=exception/create=] or [=exception/throw=] a {{DOMException}} derived interface, supply its +[=interface=] [=identifier=] as well as the additional information needed to construct it. + +
+

To throw an instance of the ProtocolXError exemplified + above: + +

+

[=exception/Throw=] a ProtocolXError whose [=ProtocolXError/error code=] + is 42. +

+
+ +

Enumerations

+ +An enumeration is a definition (matching +Enum) used to declare a type +whose valid values are a set of predefined strings. Enumerations +can be used to restrict the possible +{{DOMString}} values that can be assigned to an +[=attribute=] or passed to an +[=operation=]. + +
enum identifier { "enum", "values" /* , ... */ };
+ +The enumeration values are specified +as a comma-separated list of string literals. +The list of [=enumeration values=] +must not include duplicates. + +

+ It is strongly suggested that enumeration values be all lowercase, + and that multiple words be separated using dashes or not be + separated at all, unless there is a specific reason to use another + value naming scheme. For example, an enumeration value that + indicates an object should be created could be named + "createobject" or "create-object". + Consider related uses of enumeration values when deciding whether + to dash-separate or not separate enumeration value words so that + similar APIs are consistent. +

+ +The behavior when a string value that is not a valid enumeration value +is used when assigning to an [=attribute=], +or passed as an [=operation=] argument, +whose type is the enumeration, is language binding specific. + +Note: In the JavaScript binding, assignment of an invalid string value to an +[=attribute=] is ignored, while +passing such a value in other contexts (for example as an [=operation=] argument) +results in an exception being thrown. + +No [=extended attributes=] +defined in this specification are applicable to [=enumerations=]. + +
+    Enum :
+        "enum" identifier "{" EnumValueList "}" ";"
+
+ +
+    EnumValueList :
+        string EnumValueListComma
+
+ +
+    EnumValueListComma :
+        "," EnumValueListString
+        ε
+
+ +
+    EnumValueListString :
+        string EnumValueListComma
+        ε
+
+ +
+ + The following [=IDL fragment=] + defines an [=enumeration=] + that is used as the type of an [=attribute=] + and an [=operation=] argument: + +
+        enum MealType { "rice", "noodles", "other" };
+
+        [Exposed=Window]
+        interface Meal {
+          attribute MealType type;
+          attribute double size;     // in grams
+
+          undefined initialize(MealType type, double size);
+        };
+    
+ + A JavaScript implementation would restrict the strings that can be + assigned to the type property or passed to the initializeMeal function + to those identified in the [=enumeration=]. + +
+        var meal = getMeal();                // Get an instance of Meal.
+
+        meal.initialize("rice", 200);        // Operation invoked as normal.
+
+        try {
+          meal.initialize("sandwich", 100);  // Throws a TypeError.
+        } catch (e) {
+        }
+
+        meal.type = "noodles";               // Attribute assigned as normal.
+        meal.type = "dumplings";             // Attribute assignment ignored.
+        meal.type == "noodles";              // Evaluates to true.
+    
+
+ + +

Callback functions

+ +

+ The “Custom DOM Elements” spec wants to use callback function types for + platform object provided functions. Should we rename “callback functions” to + just “functions” to make it clear that they can be used for both purposes? +

+ +A callback function is a definition (matching +callback CallbackRest) used to declare a function type. + +
callback identifier = return_type (/* arguments... */);
+ +Note: See also the similarly named [=callback interfaces=]. + +The [=identifier=] on the +left of the equals sign gives the name of the [=callback function=] +and the return type and argument list (matching Type +and ArgumentList) on the right side of the equals +sign gives the signature of the callback function type. + +[=Callback functions=] must not +be used as the type of a [=constant=]. + +The following extended attribute is applicable to callback functions: +[{{LegacyTreatNonObjectAsNull}}]. + +
+ +
+ +
+    CallbackRest :
+        identifier "=" Type "(" ArgumentList ")" ";"
+
+ +
+ + The following [=IDL fragment=] defines + a [=callback function=] used for an API that + invokes a user-defined function when an operation is complete. + +
+        callback AsyncOperationCallback = undefined (DOMString status);
+
+        [Exposed=Window]
+        interface AsyncOperations {
+          undefined performOperation(AsyncOperationCallback whenFinished);
+        };
+    
+ + In the JavaScript language binding, a [=function object=] is + passed as the operation argument. + +
+        var ops = getAsyncOperations();  // Get an instance of AsyncOperations.
+
+        ops.performOperation(function(status) {
+          window.alert("Operation finished, status is " + status + ".");
+        });
+    
+
+ + +

Typedefs

+ +A typedef is a definition (matching +Typedef) +used to declare a new name for a type. This new name is not exposed +by language bindings; it is purely used as a shorthand for referencing +the type in the IDL. + +
typedef type identifier;
+ +The type being given a new name is specified after the typedef +keyword (matching TypeWithExtendedAttributes), and the +identifier token following the +type gives the name. + +The Type must not +be the identifier of the same or another [=typedef=]. + +No [=extended attributes=] +defined in this specification are applicable to [=typedefs=]. + +
+    Typedef :
+        "typedef" TypeWithExtendedAttributes identifier ";"
+
+ +
+ + The following [=IDL fragment=] + demonstrates the use of [=typedefs=] + to allow the use of a short + [=identifier=] instead of a long + [=sequence type=]. + +
+        [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);
+        };
+    
+
+ + +

Objects implementing interfaces

+ +In a given implementation of a set of [=IDL fragments=], +an object can be described as being a [=platform object=]. + +Platform objects are objects +that implement an [=interface=]. + +Legacy platform objects are +[=platform objects=] that implement an [=interface=] which +does not have a [{{Global}}] [=extended attribute=], and which +[=support indexed properties|supports indexed properties=], +[=support named properties|named properties=], or both. + +In a browser, for example, +the browser-implemented DOM objects (implementing interfaces such as Node and +Document) that provide access to a web page's contents +to JavaScript running in the page would be [=platform objects=]. These objects might be exotic objects, +implemented in a language like C++, or they might be native JavaScript objects. Regardless, +an implementation of a given set of IDL fragments needs to be able to recognize all [=platform objects=] +that are created by the implementation. This might be done by having some internal state that records whether +a given object is indeed a platform object for that implementation, or perhaps by observing +that the object is implemented by a given internal C++ class. How exactly platform objects +are recognized by a given implementation of a set of IDL fragments is implementation specific. + +All other objects in the system would not be treated as platform objects. For example, assume that +a web page opened in a browser loads a JavaScript library that implements DOM Core. This library +would be considered to be a different implementation from the browser provided implementation. +The objects created by the JavaScript library that implement the Node interface +will not be treated as platform objects that implement Node by the browser implementation. + +[=Callback interfaces=], on the other hand, can be implemented by any JavaScript object. This +allows Web APIs to invoke author-defined operations. For example, the DOM Events implementation +allows authors to register callbacks by providing objects that implement the +{{EventListener}} interface. + + +

Types

+ +This section lists the types supported by Web IDL, +the set of values or [[Infra|Infra]] type +corresponding to each type, and how [=constants=] +of that type are represented. + +The following types are known as integer types: +{{byte}}, +{{octet}}, +{{short}}, +{{unsigned short}}, +{{long}}, +{{unsigned long}}, +{{long long}} and +{{unsigned long long}}. + +The following types are known as numeric types: +the [=integer types=], +{{float}}, +{{unrestricted float}}, +{{double}} and +{{unrestricted double}}. + +The primitive types are +{{bigint}}, {{boolean}} and the [=numeric types=]. + +The string types are +{{DOMString}}, all [=enumeration types=], +{{ByteString}} and {{USVString}}. + +The buffer types are {{ArrayBuffer}} and {{SharedArrayBuffer}}. + +The typed array types are +{{Int8Array}}, +{{Int16Array}}, +{{Int32Array}}, +{{Uint8Array}}, +{{Uint16Array}}, +{{Uint32Array}}, +{{Uint8ClampedArray}}, +{{BigInt64Array}}, +{{BigUint64Array}}, +{{Float16Array}}, +{{Float32Array}}, and +{{Float64Array}}. + +The buffer view types are {{DataView}} and the [=typed array types=]. + +The buffer source types are the [=buffer types=] and the [=buffer view types=]. + +The {{object}} type, +all [=interface types=], and +all [=callback interface types=] +are known as object types. + +

+ When conversions are made from language binding specific types to + IDL types in order to invoke an [=operation=] + or assign a value to an [=attribute=], + all conversions necessary will be performed before the + specified functionality of the operation or attribute assignment + is carried out. If the conversion cannot + be performed, then the operation will not run or + the attribute will not be updated. In some language bindings, + type conversions could result in an exception being thrown. + In such cases, these exceptions will be propagated to the + code that made the attempt to invoke the operation or + assign to the attribute. +

+ +
+    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
+        "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 :
+        "?"
+        ε
+
+ +

any

+ +The {{any}} type is the union of all other possible +non-[=union type|union=] types. + +The {{any}} type is like +a discriminated union type, in that each of its values has a +specific non-{{any}} type +associated with it. For example, one value of the +{{any}} type is the +{{unsigned long}} +150, while another is the {{long}} 150. +These are distinct values. + +The particular type of an {{any}} +value is known as its specific type. +(Values of [=union types=] also have +[=specific types=].) + +

undefined

+ +The {{undefined}} type has a unique value. + +{{undefined}} constant values in IDL +are represented with the undefined token. + +{{undefined}} must not be used as the type of an argument in any circumstance +(in an [=operation=], [=callback function=], [=constructor operation=], etc), +or as the type of a [=dictionary member=], +whether directly or in a union. +Instead, use an [=optional argument=] +or a non-[=dictionary member/required=] [=dictionary member=]. + +Note: This value was previously spelled void, +and more limited in how it was allowed to be used. + +

boolean

+ +The {{boolean}} type has two values: +true and false. + +{{boolean}} constant values in IDL are +represented with the true and +false tokens. + +

byte

+ +The {{byte}} type is a signed integer +type that has values in the range [−128, 127]. + +{{byte}} constant values in IDL are +represented with integer +tokens. + +

octet

+ +The {{octet}} type is an unsigned integer +type that has values in the range [0, 255]. + +{{octet}} constant values in IDL are +represented with integer +tokens. + +

short

+ +The {{short}} type is a signed integer +type that has values in the range [−32768, 32767]. + +{{short}} constant values in IDL are +represented with integer +tokens. + +

unsigned short

+ +The {{unsigned short}} type is an unsigned integer +type that has values in the range [0, 65535]. + +{{unsigned short}} constant values in IDL are +represented with integer +tokens. + +

long

+ +The {{long}} type is a signed integer +type that has values in the range [−2147483648, 2147483647]. + +{{long}} constant values in IDL are +represented with integer +tokens. + +

unsigned long

+ +The {{unsigned long}} type is an unsigned integer +type that has values in the range [0, 4294967295]. + +{{unsigned long}} constant values in IDL are +represented with integer +tokens. + +

long long

+ +The {{long long}} type is a signed integer +type that has values in the range [−9223372036854775808, 9223372036854775807]. + +{{long long}} constant values in IDL are +represented with integer +tokens. + +

unsigned long long

+ +The {{unsigned long long}} type is an unsigned integer +type that has values in the range [0, 18446744073709551615]. + +{{unsigned long long}} constant values in IDL are +represented with integer +tokens. + +

float

+ +The {{float}} type is a floating point numeric +type that corresponds to the set of finite single-precision 32-bit +IEEE 754 floating point numbers. [[!IEEE-754]] + +{{float}} constant values in IDL are +represented with decimal +tokens. + +

+ Unless there are specific reasons to use a 32-bit floating point type, + specifications should use + {{double}} rather than {{float}}, + since the set of values that a {{double}} can + represent more closely matches a JavaScript Number. +

+ +

unrestricted float

+ +The {{unrestricted float}} type is a floating point numeric +type that corresponds to the set of all possible single-precision 32-bit +IEEE 754 floating point numbers, finite, non-finite, and special "not a number" values (NaNs). [[!IEEE-754]] + +{{unrestricted float}} constant values in IDL are +represented with decimal +tokens. + +

double

+ +The {{double}} type is a floating point numeric +type that corresponds to the set of finite double-precision 64-bit +IEEE 754 floating point numbers. [[!IEEE-754]] + +{{double}} constant values in IDL are +represented with decimal +tokens. + +

unrestricted double

+ +The {{unrestricted double}} type is a floating point numeric +type that corresponds to the set of all possible double-precision 64-bit +IEEE 754 floating point numbers, finite, non-finite, and special "not a number" values (NaNs). [[!IEEE-754]] + +{{unrestricted double}} constant values in IDL are +represented with decimal +tokens. + +

bigint

+ +The {{bigint}} type is an arbitrary integer type, unrestricted in range. + +{{bigint}} constant values in IDL are represented with +integer tokens. + +

DOMString

+ +The {{DOMString}} type corresponds to [=strings=]. + +Note: null is not a value of type {{DOMString}}. To allow +null, a [=nullable type|nullable=] {{DOMString}}, written as +DOMString? in IDL, needs to be used. + +Note: A {{DOMString}} value might include unmatched [=surrogate=] [=code points=]. Use {{USVString}} +if this is not desirable. + +There is no way to represent a constant {{DOMString}} +value in IDL, although {{DOMString}} [=dictionary member=] [=dictionary member/default values=] +and [=optional argument|operation optional argument=] [=optional argument/default values=] +can be set to [=value of string literal tokens|the value=] of a +string literal. + +

ByteString

+ +The {{ByteString}} type corresponds to [=byte sequences=]. + +There is no way to represent a constant {{ByteString}} +value in IDL, although {{ByteString}} [=dictionary member=] [=dictionary member/default values=] +and [=optional argument|operation optional argument=] [=optional argument/default values=] +can be set to [=value of string literal tokens|the value=] of a +string literal. + +

+ Specifications should only use + {{ByteString}} for interfacing with protocols + that use bytes and strings interchangeably, such as HTTP. In general, + strings should be represented with + {{DOMString}} values, even if it is expected + that values of the string will always be in ASCII or some + 8-bit character encoding. [=sequence types|Sequences=] or + [=frozen array type|frozen arrays=] with {{octet}} or {{byte}} + elements, {{Uint8Array}}, or {{Int8Array}} should be used for holding + 8-bit data rather than {{ByteString}}. +

+ + +

USVString

+ +The {{USVString}} type +corresponds to [=scalar value strings=]. +Depending on the context, +these can be treated as sequences of either 16-bit unsigned integer [=code units=] +or [=scalar values=]. + +There is no way to represent a constant {{USVString}} +value in IDL, although {{USVString}} [=dictionary member=] [=dictionary member/default values=] +and [=optional argument|operation optional argument=] [=optional argument/default values=] +can be set to [=value of string literal tokens|the value=] of a +string literal. + +

+ Specifications should only use + {{USVString}} for APIs that perform + text processing and need a string of + [=scalar values=] to operate on. Most APIs that use strings + should instead be using {{DOMString}}, + which does not make any interpretations of the [=code units=] + in the string. When in doubt, use {{DOMString}}. +

+ + +

object

+ +The {{object}} type corresponds to the set of +all possible non-null object references. + +There is no way to represent a constant {{object}} +value in IDL. + +To denote a type that includes all possible object references plus the +null value, use the [=nullable type=] +object?. + +

symbol

+ +The {{symbol}} type corresponds to the set of all possible symbol values. Symbol values are opaque, +non-{{object}} values which nevertheless have identity (i.e., are only equal to themselves). + +There is no way to represent a constant {{symbol}} value in IDL. + +

Interface types

+ +An [=identifier=] that +identifies an [=interface=] is used to refer to +a type that corresponds to the set of all possible non-null references to objects that +implement that interface. + +An IDL value of the interface type is represented just +by an object reference. + +There is no way to represent a constant object reference value for +a particular interface type in IDL. + +To denote a type that includes all possible references to objects implementing +the given interface plus the null value, +use a [=nullable type=]. + +

Callback interface types

+ +An [=identifier=] that identifies a [=callback interface=] is used to refer to a type that +corresponds to the set of all possible non-null references to objects. + +An IDL value of the interface type is represented by a tuple of an object reference and a +callback context. +The [=callback context=] is a language binding specific value, and is used to store information +about the execution context at the time the language binding specific object reference is +converted to an IDL value. + +Note: For JavaScript objects, the [=callback context=] is used to hold a reference to the +incumbent settings object at the time the Object value is converted to an IDL +callback interface type value. See [[#js-callback-interface]]. + +There is no way to represent a constant object reference value for a particular +[=callback interface type=] in IDL. + +To denote a type that includes all possible references to objects plus the null +value, use a [=nullable type=]. + +

Dictionary types

+ +An [=identifier=] that +identifies a [=dictionary=] is used to refer to +a type that corresponds to the set of all dictionaries that adhere to +the dictionary definition. + +The literal syntax for [=ordered maps=] may also be used to represent dictionaries, when it is +implicitly understood from context that the map is being treated as an instance of a specific +dictionary type. However, there is no way to represent a constant dictionary value inside IDL +fragments. + +

Enumeration types

+ +An [=identifier=] that +identifies an [=enumeration=] is used to +refer to a type whose values are the set of strings (sequences of +[=code units=], as with +{{DOMString}}) that are the +[=enumeration's values=]. + +Like {{DOMString}}, there is no way to represent a constant [=enumeration=] +value in IDL, although enumeration-typed [=dictionary member=] [=dictionary member/default values=] +and [=optional argument|operation optional argument=] [=optional argument/default values=] +can be set to [=value of string literal tokens|the value=] of a +string literal. + +

Callback function types

+ +An [=identifier=] that identifies +a [=callback function=] is used to refer to +a type whose values are references to objects that are functions with the given signature. + +Note: If the [{{LegacyTreatNonObjectAsNull}}] [=extended attribute=] is specified on the [=definition=] of +the [=callback function=], the values can be references to objects that are not functions. + +An IDL value of the callback function type is represented by a tuple of an object +reference and a [=callback context=]. + +Note: As with [=callback interface types=], the [=callback context=] is used to hold a +reference to the incumbent settings object at +the time a JavaScript Object value is converted to an IDL +callback function type value. See [[#js-callback-function]]. + +There is no way to represent a constant [=callback function=] +value in IDL. + +

Nullable types — |T|?

+ +A nullable type is an IDL type constructed +from an existing type (called the inner type), +which just allows the additional value null +to be a member of its set of values. [=Nullable types=] +are represented in IDL by placing a U+003F (?) +character after an existing type. +The [=nullable types/inner type=] must not be: + +* {{any}}, +* a [=promise type=], +* an [=observable array type=], +* another nullable type, or +* a [=union type=] that itself [=includes a nullable type=] + or has a dictionary type as one of its [=flattened member types=]. + +Note: Although dictionary types can in general be nullable, +they cannot when used as the type of an operation argument or a dictionary member. + +Nullable type constant values in IDL are represented in the same way that +constant values of their [=nullable types/inner type=] +would be represented, or with the null token. + +
+ + For example, a type that allows the values true, + false and null + is written as boolean?: + +
+        [Exposed=Window]
+        interface NetworkFetcher {
+          undefined get(optional boolean? areWeThereYet = false);
+        };
+    
+ + The following [=interface=] has two + [=attributes=]: one whose value can + be a {{DOMString}} or the null + value, and another whose value can be a reference to a Node + object or the null value: + +
+        [Exposed=Window]
+        interface Node {
+          readonly attribute DOMString? namespaceURI;
+          readonly attribute Node? parentNode;
+          // ...
+        };
+    
+
+ + +

Sequence types — sequence<|T|>

+ +The sequence<|T|> +type is a parameterized type whose values are (possibly zero-length) [=lists=] of +values of type |T|. + +Sequences are always passed by value. In +language bindings where a sequence is represented by an object of +some kind, passing a sequence to a [=platform object=] +will not result in a reference to the sequence being kept by that object. +Similarly, any sequence returned from a platform object +will be a copy and modifications made to it will not be visible to the platform object. + +The literal syntax for [=lists=] may also be used to represent sequences, when it is implicitly +understood from context that the list is being treated as a sequences. However, there is no way to +represent a constant sequence value inside IDL fragments. + +Sequences must not be used as the +type of an [=attribute=] or +[=constant=]. + +Note: This restriction exists so that it is clear to specification writers +and API users that [=sequence types|sequences=] +are copied rather than having references +to them passed around. Instead of a writable [=attribute=] of a sequence +type, it is suggested that a pair of [=operations=] to get and set the +sequence is used. + +Any [=list=] can be implicitly treated as a sequence<|T|>, as long as it contains +only [=list/items=] that are of type |T|. + + +

Record types — record<|K|, |V|>

+ +A record type is a parameterized type whose values are [=ordered maps=] with +[=map/keys=] that are instances of |K| and [=map/values=] that are instances of |V|. |K| must be one +of {{DOMString}}, {{USVString}}, or {{ByteString}}. + +The literal syntax for [=ordered maps=] may also be used to represent records, when it is implicitly +understood from context that the map is being treated as a record. However, there is no way to +represent a constant record value inside IDL fragments. + +Records are always passed by value. In language bindings where a record +is represented by an object of some kind, passing a record +to a [=platform object=] will not result in a reference to the record +being kept by that object. Similarly, any record returned from a +platform object will be a copy and modifications made to it will not be visible +to the platform object. + +Records must not be used as the type of an [=attribute=] or +[=constant=]. + +Any [=ordered map=] can be implicitly treated as a record<|K|, |V|>, as long as +it contains only [=map/entries=] whose [=map/keys=] are all of of type |K| and whose [=map/values=] +are all of type |V|. + + +

Promise types — Promise<|T|>

+ +A promise type is a parameterized type +whose values are references to objects that “is used as a place holder +for the eventual results of a deferred (and possibly asynchronous) computation +result of an asynchronous operation”. +See section 25.4 +of the JavaScript specification for details on the semantics of promise objects. + +Promise types are non-nullable, but |T| may be nullable. + +There is no way to represent a promise value in IDL. + +

Union types

+ +A union type is a type whose set of values +is the union of those in two or more other types. Union types (matching +UnionType) +are written as a series of types separated by the or keyword +with a set of surrounding parentheses. +The types which comprise the union type are known as the +union's member types. + +
+ + For example, you might write (Node or DOMString) + or (double or sequence<double>). When applying a + ? suffix to a + [=union type=] + as a whole, it is placed after the closing parenthesis, + as in (Node or DOMString)?. + + Note that the [=member types=] + of a union type do not descend into nested union types. So for + (double or (sequence<long> or Event) or (Node or DOMString)?) the member types + are double, (sequence<long> or Event) and + (Node or DOMString)?. + +
+ +Like the {{any}} type, values of +union types have a [=specific type=], +which is the particular [=member type=] +that matches the value. + +
+ + The flattened member types + of a [=union type=], possibly [=annotated type|annotated=], is a set of types determined as + follows: + + 1. Let |T| be the [=union type=]. + 1. Initialize |S| to ∅. + 1. For each [=member type=] |U| of |T|: + 1. If |U| is an [=annotated type=], then + set |U| to be the [=annotated types/inner type=] of |U|. + 1. If |U| is a [=nullable type=], then + set |U| to be the [=nullable types/inner type=] of |U|. + 1. If |U| is a [=union type=], then + add to |S| the [=flattened member types=] + of |U|. + 1. Otherwise, |U| is not a [=union type=]. + Add |U| to |S|. + 1. Return |S|. +
+ + +Note: For example, the [=flattened member types=] +of the [=union type=] +(Node or (sequence<long> or Event) or (XMLHttpRequest or DOMString)? or sequence<(sequence<double> or NodeList)>) +are the six types Node, sequence<long>, Event, +XMLHttpRequest, DOMString and +sequence<(sequence<double> or NodeList)>. + +
+ + The number of nullable member types + of a [=union type=] is an integer + determined as follows: + + 1. Let |T| be the [=union type=]. + 1. Initialize |n| to 0. + 1. For each [=member type=] |U| of |T|: + 1. If |U| is a [=nullable type=], then: + 1. Set |n| to |n| + 1. + 1. Set |U| to be the [=nullable types/inner type=] of |U|. + 1. If |U| is a [=union type=], then: + 1. Let |m| be the [=number of nullable member types=] of |U|. + 1. Set |n| to |n| + |m|. + 1. Return |n|. +
+ +The {{any}} type must not +be used as a [=member types|union member type=]. + +The [=number of nullable member types=] +of a [=union type=] must +be 0 or 1, and if it is 1 then the union type must also not have +a [=dictionary type=] in its [=flattened member types=]. + +A type includes a nullable type if: + +* the type is a [=nullable type=], or +* the type is an [=annotated type=] and its [=annotated types/inner type=] is a nullable type, or +* the type is a [=union type=] and its + [=number of nullable member types=] is 1. + +Each pair of [=flattened member types=] +in a [=union type=], T and U, +must be [=distinguishable=]. + +

+It is possible to create a union of {{bigint}} and a [=numeric type=]. +However, this is generally only supposed to be used for interfaces such as +[[ECMA-402#numberformat-objects|NumberFormat]], which formats the values rather than using them in +calculations. +It would not be appropriate to accept such a union, only to then convert values of the +[=numeric type=] to a {{bigint}} for further processing, as this runs the risk of introducing +precision errors. +Please +file an issue +before using this feature. +

+ +A type includes undefined if: + +* the type is {{undefined}}, or +* the type is a [=nullable type=] and its [=nullable types/inner type=] [=includes undefined=], or +* the type is an [=annotated type=] and its [=annotated types/inner type=] [=includes undefined=], or +* the type is a [=union type=] and one of its [=member types=] [=includes undefined=]. + +[=Union type=] constant values +in IDL are represented in the same way that constant values of their +[=member types=] would be +represented. + +
+ +
+ +
+ +
+ + +

Annotated types

+ +Additional types can be created from existing ones by specifying certain [=extended attributes=] on +the existing types. Such types are called annotated types, and the types they +annotate are called inner types. + +
+ [Clamp] long defines a new [=annotated type=], whose behavior is based on that of + the [=annotated types/inner type=] {{long}}, but modified as specified by the [{{Clamp}}] + extended attribute. +
+ +The following extended attributes are applicable to types: +[{{AllowResizable}}], +[{{AllowShared}}], +[{{Clamp}}], +[{{EnforceRange}}], and +[{{LegacyNullToEmptyString}}]. + +
+ The extended attributes associated with + an IDL type |type| are determined as follows: + + 1. Let |extended attributes| be a new empty [=ordered set|set=]. + 1. If |type| appears as part of a + TypeWithExtendedAttributes + production, [=set/append=] each of the [=extended attributes=] present in the production's + ExtendedAttributeList to + |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;
+                };
+            
+
+ 1. If |type| is a [=member type=] of a [=union type=] |U|, [=set/append=] each of the + [=extended attributes associated with=] |U| to |extended attributes|. + +
+
+                [Exposed=Window]
+                interface I {
+                    attribute [XAttr] (long or Node) attrib;
+                };
+            
+
+ 1. If |type| appears as part of a Type production + directly within an Argument production, + [=set/append=] to |extended attributes| all of the [=extended attributes=] present in the + production's + ExtendedAttributeList that are + [=applicable to types=]. + +
+
+                [Exposed=Window]
+                interface I {
+                    undefined f([XAttr] long attrib);
+                };
+            
+ + Note that this is an example of this step only if [XAttr] is + [=applicable to types=]; otherwise [XAttr] applies to the argument, and not + the argument's type. +
+ 1. If |type| appears as part of a Type production + directly within a DictionaryMember + production, [=set/append=] to |extended attributes| all of the [=extended attributes=] + present in the production's + ExtendedAttributeList that are + [=applicable to types=]. + +
+
+                dictionary D {
+                    [XAttr] long member;
+                };
+            
+ + Note that this is an example of this step only if [XAttr] is + [=applicable to types=]; otherwise [XAttr] applies to the dictionary + member, and not the member's type. +
+ 1. If |type| is a [=typedef=], [=set/append=] the [=extended attributes associated with=] the + [=type being given a new name=] to |extended attributes|. + +
+
+                typedef [XAttr] long xlong;
+            
+
+ 1. Return |extended attributes|. +
+ +For any type, the [=extended attributes associated with=] it must only contain +[=extended attributes=] that are [=applicable to types=]. + +

Buffer source types

+ +There are a number of types that correspond to sets of all possible non-null +references to objects that represent a buffer of data or a view on to a buffer of +data. The table below lists these types and the kind of buffer or view they represent. + + + + + + + + + + + + + + + + + + +
Type + Kind of buffer +
ArrayBuffer + An object that holds a pointer (which can be null) to a buffer of a fixed number of bytes +
SharedArrayBuffer + An object that holds a pointer (which cannot be null) to a shared buffer of a fixed number of bytes +
DataView + A view on to a [=buffer type=] instance that allows typed access to integers and floating point values stored at arbitrary offsets into the buffer +
Int8Array + A view on to a [=buffer type=] instance that exposes it as an array of two's complement signed integers of the given size in bits +
Int16Array +
Int32Array +
BigInt64Array +
Uint8Array + A view on to a [=buffer type=] instance that exposes it as an array of unsigned integers of the given size in bits +
Uint16Array +
Uint32Array +
BigUint64Array +
Uint8ClampedArray + A view on to a [=buffer type=] instance that exposes it as an array of unsigned 8-bit integers with clamped conversions +
Float16Array + A view on to a [=buffer type=] instance that exposes it as an array of IEEE 754 floating point numbers of the given size in bits; Float16Array corresponds to the ECMAScript proposal [[PROPOSAL-FLOAT16ARRAY]]. +
Float32Array +
Float64Array +
+ +Note: These types all correspond to classes defined in JavaScript. + +There is no way to represent a constant value of any of these types in IDL. + +At the specification prose level, IDL [=buffer source types=] are simply references to objects. To +inspect or manipulate the bytes inside the buffer, specification prose needs to use the algorithms +in [[#js-buffer-source-types]]. + +
+    BufferRelatedType :
+        "ArrayBuffer"
+        "SharedArrayBuffer"
+        "DataView"
+        "Int8Array"
+        "Int16Array"
+        "Int32Array"
+        "Uint8Array"
+        "Uint16Array"
+        "Uint32Array"
+        "Uint8ClampedArray"
+        "BigInt64Array"
+        "BigUint64Array"
+        "Float16Array"
+        "Float32Array"
+        "Float64Array"
+
+ + +

Frozen array types — FrozenArray<|T|>

+ +A frozen array type is a parameterized +type whose values are references to objects that hold a fixed length array +of unmodifiable values. The values in the array are of type |T|. + +Frozen array types must only be used as the type of [=regular attributes=] or [=static attributes=] +defined on an [=interface=]. + +
+ The following [=IDL fragment=] defines an [=interface=] with two frozen array attributes, one + [=read only=] and one not. + +
+        [Exposed=Window]
+        interface PersonalPreferences {
+            readonly attribute FrozenArray<DOMString> favoriteColors;
+            attribute FrozenArray<DOMString> favoriteFoods;
+
+            undefined randomizeFavoriteColors();
+        };
+    
+ + The behavior of these attributes could be defined like so: + +
+ Each PersonalPreferences has associated favorite colors, a {{FrozenArray}}<{{DOMString}}>, initially equal to the result of [=creating a frozen array=] from « "purple", "aquamarine" ». + + Each PersonalPreferences has an associated favorite foods, a {{FrozenArray}}<{{DOMString}}>, initially equal to the result of [=creating a frozen array=] from the empty list. + + The favoriteColors [=getter steps=] are to return [=this=]'s favorite colors. + + The favoriteFoods [=getter steps=] are to return [=this=]'s favorite foods. + + The favoriteFoods [=setter steps=] are to set [=this=]'s favorite foods to [=the given value=]. + + The randomizeFavoriteColors() [=method steps=] are: + + 1. Let |newFavoriteColors| be a list of two strings representing colors, chosen randomly. + + 1. Set [=this=]'s favorite colors to the result of [=creating a frozen array=] from |newFavoriteColors|. +
+
+ +Since FrozenArray<|T|> values +are references, they are unlike [=sequence types=], +which are lists of values that are passed by value. + +There is no way to represent a constant frozen array value in IDL. + +

Observable array types — ObservableArray<|T|>

+ +An observable array type is a parameterized type +whose values are references to a combination of a mutable list of objects of type |T|, as well as +behavior to perform when author code modifies the contents of the list. + +The parameterized type |T| must not be a [=dictionary type=], [=sequence type=], [=record type=], +or [=observable array type=]. However, |T| may be nullable. + +Similar to [=sequence types=] and [=frozen array types=], observable array types wrap around +JavaScript array types, imposing additional semantics on their usage. + +Observable array types must only be used as the type of [=regular attributes=] defined on an [=interface=]. + +For an attribute whose type is an observable array type, specification authors can specify a series +of algorithms: + +* set an indexed value, which accepts an IDL + value that is about to be set in the observable array, and the index at which it is being set; +* delete an indexed value, which accepts an + IDL value that is about to be removed from the observable array, and the index from which it is + being removed. + +Both of these algorithms are optional, and if not provided, the default behavior will be to do +nothing. Either algorithm may throw an exception, e.g., to reject invalid values. + +Note that when JavaScript code sets an existing index to a new value, this will first call the +[=observable array attribute/delete an indexed value=] algorithm to remove the existing value, and +then the [=observable array attribute/set an indexed value=] algorithm with the new value. + +Every [=regular attribute=] whose type is an [=observable array type=] has a +backing list, which is a [=list=], initially empty. +Specification authors can modify the contents of the backing list, which will automatically be +reflected in the contents of the observable array as observed by JavaScript code. Similarly, any +modifications by JavaScript code to the contents of the observable array will be reflected back into +the backing list, after passing through the [=observable array attribute/set an indexed value=] and +[=observable array attribute/delete an indexed value=] algorithms. + +There is no way to represent a constant observable array value in IDL. + +
+ + The following [=IDL fragment=] defines an [=interface=] with an observable array attribute: + +
+        [Exposed=Window]
+        interface Building {
+          attribute ObservableArray<Employee> employees;
+        };
+    
+ + The behavior of the attribute could be defined like so: + +
+ The [=observable array attribute/set an indexed value=] algorithm for + Building's employees attribute, given + |employee| and |index|, is: + + 1. If |employee| is not allowed to enter the building today, then throw a + "{{NotAllowedError}}" {{DOMException}}. + 1. If |index| is greater than 200, then throw a "{{QuotaExceededError}}" {{DOMException}}. + 1. Put |employee| to work! + + The [=observable array attribute/delete an indexed value=] algorithm for + Building's employees attribute, given + |employee| and index, is: + + 1. Alert security that |employee| has left the building. +
+ + Then, JavaScript code could manipulate the employees property in + various ways: + +
+        // Get an instance of 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;
+
+        // Will throw:
+        building.employees.push("not an Employee; a string instead");
+    
+ + All of these manipulations would pass through the above-defined + [=observable array attribute/set an indexed value=] algorithm, potentially throwing if the + conditions described there were met. They would also perform the appropriate side effects listed + there and in the [=observable array attribute/delete an indexed value=] algorithm. + + Another thing to note about the above code example is how all of the JavaScript array methods + from {{%Array.prototype%}} work on the observable array. Indeed, it fully behaves like an + Array instance: + +
+        const normalArray = [];
+
+        // If building.employees were defined as an indexed property getter interface: normalArray
+        // would contains a single item, building.employees.
+        //
+        // For observable arrays (and frozen arrays): normalArray contains all of the items inside
+        // of building.employees.
+        normalArray.concat(building.employees);
+
+        // names is a JavaScript Array.
+        const names = building.employees.map(employee => employee.name);
+
+        // Passes various brand checks:
+        console.assert(building.employees instanceof Array);
+        console.assert(Array.isArray(building.employees));
+        console.assert(building.employees.constructor === Array);
+
+        // Even is treated as an array by JSON.stringify! (Note the outer []s.)
+        console.assert(JSON.stringify(building.employees) === `[{}]`);
+    
+
+ +

Extended attributes

+ +An extended attribute is an annotation +that can appear on +[=definitions=], +types as [=annotated types=], +[=interface members=], +[=interface mixin members=], +[=callback interface members=], +[=namespace members=], +[=dictionary members=], +and [=operation=] arguments, and +is used to control how language bindings will handle those constructs. +Extended attributes are specified with an +ExtendedAttributeList, +which is a square bracket enclosed, comma separated list of +ExtendedAttributes. + +The ExtendedAttribute +grammar symbol matches nearly any sequence of tokens, however the +[=extended attributes=] +defined in this document only accept a more restricted syntax. +Any extended attribute encountered in an +[=IDL fragment=] is +matched against the following five grammar symbols to determine +which form (or forms) it is in: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Grammar symbolFormExample
+ ExtendedAttributeNoArgs + + takes no arguments + + [Replaceable] +
+ ExtendedAttributeArgList + + takes an argument list + + Not currently used; previously used by [Constructor(double x, double y)] +
+ ExtendedAttributeNamedArgList + + takes a named argument list + + [LegacyFactoryFunction=Image(DOMString src)] +
+ ExtendedAttributeIdent + + takes an identifier + + [PutForwards=name] +
+ ExtendedAttributeIdentList + + takes an identifier list + + [Exposed=(Window,Worker)] +
+ ExtendedAttributeWildcard + + takes a wildcard + + [Exposed=*] +
+ +This specification defines a number of extended attributes that +are applicable to the JavaScript language binding, which are described in +[[#js-extended-attributes]]. +Each extended attribute definition will state which of the above +five forms are allowed. + +
+    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
+        ε
+
+ +
+    ExtendedAttributeNoArgs :
+        identifier
+
+ +
+    ExtendedAttributeArgList :
+        identifier "(" ArgumentList ")"
+
+ +
+    ExtendedAttributeIdent :
+        identifier "=" identifier
+
+ +
+    ExtendedAttributeWildcard :
+        identifier "=" "*"
+
+ +
+    ExtendedAttributeIdentList :
+        identifier "=" "(" IdentifierList ")"
+
+ +
+    ExtendedAttributeNamedArgList :
+        identifier "=" identifier "(" ArgumentList ")"
+
+ + +

JavaScript binding

+ +This section describes how definitions written with the IDL defined in +[[#idl]] correspond to particular constructs +in JavaScript, as defined by the ECMAScript Language Specification +[[!ECMA-262]]. + +Unless otherwise specified, objects defined in this section are ordinary objects as described in +[[ecmascript#sec-ordinary-object-internal-methods-and-internal-slots]], and if the +object is a [=function object=], [[ecmascript#sec-built-in-function-objects]]. + +This section may redefine certain internal methods and internal slots of objects. Other +specifications may also override the definitions of any internal method or internal slots of a +[=platform object=] that is an instance of an [=interface=]. These objects with changed semantics +shall be treated in accordance with the rules for exotic objects. + +

+ As overriding internal JavaScript object methods is a low level operation and + can result in objects that behave differently from ordinary objects, + this facility should not be used unless necessary + for security or compatibility. This is currently used to define the + {{HTMLAllCollection}} and {{Location}} interfaces. [[HTML]] +

+ +Unless otherwise specified, exotic objects defined in this section and other specifications have the +same [=ordinary object/internal slots=] as ordinary objects, and all of the internal methods for +which alternative definitions are not given are the same as [=ordinary object/internal +methods|those=] of ordinary objects. + +Unless otherwise specified, the \[[Extensible]] internal slot +of objects defined in this section has the value true. + +Unless otherwise specified, the \[[Prototype]] internal slot +of objects defined in this section is {{%Object.prototype%}}. + +Some objects described in this section are defined to have a class string, +which is the string to include in the string returned from Object.prototype.toString. + +If an object has a [=class string=] |classString|, then the object must, +at the time it is created, have a property whose name is the {{%Symbol.toStringTag%}} symbol +with PropertyDescriptor{\[[Writable]]: false, +\[[Enumerable]]: false, \[[Configurable]]: true, +\[[Value]]: |classString|}. + +

+ Algorithms in this section use the conventions described in [[ecmascript#sec-algorithm-conventions]], such as the use of steps and substeps, the use of mathematical + operations, and so on. This section may also reference abstract operations + and notations defined in other parts of ECMA-262. +

+ +When an algorithm says to +throw a |Something|Error +then this means to construct a new JavaScript |Something|Error object in +the [=current realm=] and to throw it, just as the algorithms in ECMA-262 do. + +Note that algorithm steps can call in to other algorithms and abstract operations and +not explicitly handle exceptions that are thrown from them. When an exception +is thrown by an algorithm or abstract operation and it is not explicitly +handled by the caller, then it is taken to end the algorithm and propagate out +to its caller, and so on. + +
+ +
+ + Consider the following algorithm: + + 1. Let |x| be the JavaScript value passed in to this algorithm. + 1. Let |y| be the result of calling [=?=] ToString(|x|). + 1. Return |y|. +
+ + Since ToString can throw an exception (for example if passed the object + ({ toString: function() { throw 1 } })), and the exception is + not handled in the above algorithm, if one is thrown then it causes this + algorithm to end and for the exception to propagate out to its caller, if there + is one. + +
+ + +

JavaScript environment

+ +In a JavaScript implementation of a given set of +[=IDL fragments=], +there will exist a number of JavaScript objects that correspond to +definitions in those [=IDL fragments=]. +These objects are termed the initial objects, +and comprise the following: + +* [=interface objects=] +* [=legacy callback interface objects=] +* [=legacy factory functions=] +* [=interface prototype objects=] +* [=named properties objects=] +* [=iterator prototype objects=] +* [=attribute getters=] +* [=attribute setters=] +* the function objects that correspond to operations +* the function objects that correspond to stringifiers + +Each [=realm=] +must have its own unique set of each of +the [=initial objects=], created +before control enters any JavaScript execution context associated with the +realm, but after the [=realm/global object=] for that realm is created. The \[[Prototype]]s +of all initial objects in a given [=realm=] must come from +that same [=realm=]. + +
+ + In an HTML user agent, multiple [=realms=] can exist when + multiple frames or windows are created. Each frame or window will have + its own set of [=initial objects=], + which the following HTML document demonstrates: + +
+        <!DOCTYPE html>
+        <title>Different Realms</title>
+        <iframe id=a></iframe>
+        <script>
+        var iframe = document.getElementById("a");
+        var w = iframe.contentWindow;              // The global object in the frame
+
+        Object == w.Object;                        // Evaluates to false, per ECMA-262
+        Node == w.Node;                            // Evaluates to false
+        iframe instanceof w.Node;                  // Evaluates to false
+        iframe instanceof w.Object;                // Evaluates to false
+        iframe.appendChild instanceof Function;    // Evaluates to true
+        iframe.appendChild instanceof w.Function;  // Evaluates to false
+        </script>
+    
+
+ +Note: All [=interfaces=] define which [=realms=] they are [=exposed=] in. +This allows, for example, [=realms=] for Web Workers to [=expose=] +different sets of supported interfaces from those exposed in realms +for Web pages. + +Although at the time of this writing the JavaScript specification does not reflect this, +every JavaScript object must have an associated [=realm=]. The mechanisms +for associating objects with realms are, for now, underspecified. However, we note that +in the case of [=platform objects=], the +associated realm is equal to the object's [=relevant realm=], and +for non-exotic [=function objects=] (i.e. not [=ECMAScript/callable=] proxies, and not bound functions) +the associated realm is equal to the value of the [=function object=]'s \[[Realm]] internal +slot. + + +

JavaScript type mapping

+ +This section describes how types in the IDL map to types in JavaScript. + +Each sub-section below describes how values of a given IDL type are represented +in JavaScript. For each IDL type, it is described how JavaScript values are +converted to an IDL value +when passed to a [=platform object=] expecting that type, and how IDL values +of that type are converted to JavaScript values +when returned from a platform object. + +Note that the sub-sections and algorithms below also apply to [=annotated types=] created by applying +extended attributes to the types named in their headers. + + +

any

+ +Since the IDL {{any}} type +is the union of all other IDL types, it can correspond to any +JavaScript value type. + +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{any}} value by running the following algorithm: + + 1. If |V| is undefined, then + return the unique {{undefined}} IDL value. + 1. If |V| is null, then + return the null {{object|object?}} reference. + 1. If Type(|V|) is Boolean, then + return the {{boolean}} value that represents the same truth value. + 1. If Type(|V|) is Number, then + return the result of converting |V| + to an {{unrestricted double}}. + 1. If Type(|V|) is BigInt, then + return the result of converting |V| + to a {{bigint}}. + 1. If Type(|V|) is String, then + return the result of converting |V| + to a {{DOMString}}. + 1. If Type(|V|) is Symbol, then + return the result of converting |V| + to a {{symbol}}. + 1. If Type(|V|) is Object, then + return an IDL {{object}} value that references |V|. +
+ +

+ + An IDL {{any}} value is [=converted to a JavaScript value=] + according to the rules for converting + the [=specific type=] of the IDL {{any}} value + as described in the remainder of this section. +

+ + +

undefined

+ +

+ + A JavaScript value |V| is [=converted to an IDL value|converted=] to an IDL {{undefined}} value by + returning the unique {{undefined}} value, ignoring |V|. +

+ +

+ + The unique IDL {{undefined}} value is [=converted to a JavaScript value|converted=] to the + JavaScript undefined value. +

+ + +

boolean

+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{boolean}} value by running the following algorithm: + + 1. Let |x| be the result of computing ToBoolean(|V|). + 1. Return the IDL {{boolean}} value that is the one that + represents the same truth value as the + JavaScript Boolean value |x|. +
+ +

+ + The IDL {{boolean}} value true + is [=convert to a JavaScript value|converted=] to + the JavaScript true value and the IDL {{boolean}} + value false is converted to the JavaScript + false value. +

+ +

Integer types

+ +Mathematical operations used in this section, +including those defined in [[ecmascript#sec-algorithm-conventions]], +are to be understood as computing exact mathematical results +on mathematical real numbers. + +In effect, where x is a Number value, +“operating on x” is shorthand for +“operating on the mathematical real number that represents the same numeric value as x”. + +
byte
+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{byte}} value by running the following algorithm: + + 1. Let |x| be [=?=] ConvertToInt(|V|, 8, "signed"). + 1. Return the IDL {{byte}} value that represents the same numeric value as |x|. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL {{byte}} value to a JavaScript + value is a Number that represents + the same numeric value as the IDL {{byte}} value. + The Number value will be an integer in the range [−128, 127]. +

+ + +
octet
+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{octet}} value by running the following algorithm: + + 1. Let |x| be [=?=] ConvertToInt(|V|, 8, "unsigned"). + 1. Return the IDL {{octet}} value that represents the same numeric value as |x|. +
+ +

+ + The result of [=convert to a JavaScript value|converting=] + an IDL {{octet}} value to a JavaScript + value is a Number that represents + the same numeric value as the IDL + {{octet}} value. + The Number value will be an integer in the range [0, 255]. +

+ + +
short
+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{short}} value by running the following algorithm: + + 1. Let |x| be [=?=] ConvertToInt(|V|, 16, "signed"). + 1. Return the IDL {{short}} value that represents the same numeric value as |x|. + +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL {{short}} value to a JavaScript + value is a Number that represents the + same numeric value as the IDL + {{short}} value. + The Number value will be an integer in the range [−32768, 32767]. +

+ + +
unsigned short
+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{unsigned short}} value by running the following algorithm: + + 1. Let |x| be [=?=] ConvertToInt(|V|, 16, "unsigned"). + 1. Return the IDL {{unsigned short}} value that represents the same numeric value as |x|. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL {{unsigned short}} value to a JavaScript + value is a Number that + represents the same numeric value as the IDL + {{unsigned short}} value. + The Number value will be an integer in the range [0, 65535]. +

+ + +
long
+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{long}} value by running the following algorithm: + + 1. Let |x| be [=?=] ConvertToInt(|V|, 32, "signed"). + 1. Return the IDL {{long}} value that represents the same numeric value as |x|. +
+ +

+ + The result of [=convert to a JavaScript value|converting=] + an IDL {{long}} value to a JavaScript + value is a Number that + represents the same numeric value as the IDL + {{long}} value. + The Number value will be an integer in the range [−2147483648, 2147483647]. +

+ + +
unsigned long
+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{unsigned long}} value by running the following algorithm: + + 1. Let |x| be [=?=] ConvertToInt(|V|, 32, "unsigned"). + 1. Return the IDL {{unsigned long}} value that represents the same numeric value as |x|. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL {{unsigned long}} value to a JavaScript + value is a Number that + represents the same numeric value as the IDL + {{unsigned long}} value. + The Number value will be an integer in the range [0, 4294967295]. +

+ + +
long long
+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{long long}} value by running the following algorithm: + + 1. Let |x| be [=?=] ConvertToInt(|V|, 64, "signed"). + 1. Return the IDL {{long long}} value that represents the same numeric value as |x|. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL {{long long}} value to a JavaScript + value is a Number value that + represents the closest numeric value to the {{long long}}, + choosing the numeric value with an even significand if there are + two [=equally close values=]. + If the {{long long}} is in the range + [−253 + 1, 253 − 1], then the Number + will be able to represent exactly the same value as the + {{long long}}. +

+ + +
unsigned long long
+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{unsigned long long}} value by running the following algorithm: + + 1. Let |x| be [=?=] ConvertToInt(|V|, 64, "unsigned"). + 1. Return the IDL {{unsigned long long}} value that represents the same numeric value as |x|. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL {{unsigned long long}} value to a JavaScript + value is a Number value that + represents the closest numeric value to the {{unsigned long long}}, + choosing the numeric value with an even significand if there are + two [=equally close values=]. + If the {{unsigned long long}} is less than or equal to 253 − 1, + then the Number will be able to + represent exactly the same value as the + {{unsigned long long}}. +

+ +
Abstract operations
+ +
+ + IntegerPart(|n|): + + 1. Let |r| be floor(abs(|n|)). + 1. If |n| < 0, then return -1 × |r|. + 1. Otherwise, return |r|. +
+ +
+ + ConvertToInt(|V|, |bitLength|, |signedness|): + + 1. If |bitLength| is 64, then: + 1. Let |upperBound| be 253 − 1. + 1. If |signedness| is "unsigned", then let |lowerBound| be 0. + 1. Otherwise let |lowerBound| be −253 + 1. + + Note: this ensures {{long long}} types + [=extended attribute associated with|associated with=] [{{EnforceRange}}] or + [{{Clamp}}] [=extended attributes=] are representable in JavaScript's [=Number type=] + as unambiguous integers. + + 1. Otherwise, if |signedness| is "unsigned", then: + 1. Let |lowerBound| be 0. + 1. Let |upperBound| be 2|bitLength| − 1. + 1. Otherwise: + 1. Let |lowerBound| be -2|bitLength| − 1. + 1. Let |upperBound| be 2|bitLength| − 1 − 1. + 1. Let |x| be [=?=] ToNumber(|V|). + 1. If |x| is −0, then set |x| to +0. + 1. If the conversion is to an IDL type [=extended attribute associated with|associated with=] + the [{{EnforceRange}}] [=extended attribute=], then: + 1. If |x| is NaN, +∞, or −∞, + then [=JavaScript/throw=] a {{TypeError}}. + 1. Set |x| to IntegerPart(|x|). + 1. If |x| < |lowerBound| or |x| > |upperBound|, + then [=JavaScript/throw=] a {{TypeError}}. + 1. Return |x|. + 1. If |x| is not NaN and the conversion is to an IDL type + [=extended attribute associated with|associated with=] the [{{Clamp}}] extended attribute, + then: + 1. Set |x| to min(max(|x|, |lowerBound|), |upperBound|). + 1. Round |x| to the nearest integer, choosing the even integer if it lies halfway between two, + and choosing +0 rather than −0. + 1. Return |x|. + 1. If |x| is NaN, +0, +∞, or −∞, + then return +0. + 1. Set |x| to IntegerPart(|x|). + 1. Set |x| to |x| [=modulo=] 2|bitLength|. + 1. If |signedness| is "signed" and |x| ≥ 2|bitLength| − 1, + then return |x| − 2|bitLength|. + 1. Otherwise, return |x|. +
+ + +

float

+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{float}} value by running the following algorithm: + + 1. Let |x| be [=?=] ToNumber(|V|). + 1. If |x| is NaN, +∞, or −∞, + then [=JavaScript/throw=] a {{TypeError}}. + 1. Let |S| be the set of finite IEEE 754 single-precision floating + point values except −0, but with two special values added: 2128 and + −2128. + 1. Let |y| be the number in |S| that is closest + to |x|, selecting the number with an + even significand if there are two [=equally close values=]. + (The two special values 2128 and −2128 + are considered to have even significands for this purpose.) + 1. If |y| is 2128 or −2128, then [=JavaScript/throw=] a {{TypeError}}. + 1. If |y| is +0 and |x| is negative, return −0. + 1. Return |y|. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL {{float}} value to a JavaScript + value is the Number value that represents the same numeric value as the IDL + {{float}} value. +

+ + +

unrestricted float

+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{unrestricted float}} value by running the following algorithm: + + 1. Let |x| be [=?=] ToNumber(|V|). + 1. If |x| is NaN, then return the IDL {{unrestricted float}} value that represents the IEEE 754 NaN value with the bit pattern 0x7fc00000 [[!IEEE-754]]. + 1. Let |S| be the set of finite IEEE 754 single-precision floating + point values except −0, but with two special values added: 2128 and + −2128. + 1. Let |y| be the number in |S| that is closest + to |x|, selecting the number with an + even significand if there are two [=equally close values=]. + (The two special values 2128 and −2128 + are considered to have even significands for this purpose.) + 1. If |y| is 2128, return +∞. + 1. If |y| is −2128, return −∞. + 1. If |y| is +0 and |x| is negative, return −0. + 1. Return |y|. +
+ +Note: Since there is only a single JavaScript NaN value, +it must be canonicalized to a particular single precision IEEE 754 NaN value. The NaN value +mentioned above is chosen simply because it is the quiet NaN with the lowest +value when its bit pattern is interpreted as an unsigned 32-bit integer. + +
+ + + The result of [=convert to a JavaScript value|converting=] + an IDL {{unrestricted float}} value to a JavaScript + value is a Number: + + 1. If the IDL {{unrestricted float}} value is a NaN, + then the Number value is NaN. + 1. Otherwise, the Number value is + the one that represents the same numeric value as the IDL + {{unrestricted float}} value. +
+ + +

double

+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{double}} value by running the following algorithm: + + 1. Let |x| be [=?=] ToNumber(|V|). + 1. If |x| is NaN, +∞, or −∞, + then [=JavaScript/throw=] a {{TypeError}}. + 1. Return the IDL {{double}} value + that represents the same numeric value as |x|. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL {{double}} value to a JavaScript + value is the Number value that represents the + same numeric value as the IDL {{double}} value. +

+ + +

unrestricted double

+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{unrestricted double}} value by running the following algorithm: + + 1. Let |x| be [=?=] ToNumber(|V|). + 1. If |x| is NaN, then + return the IDL {{unrestricted double}} value that represents + the IEEE 754 NaN value with the bit pattern 0x7ff8000000000000 [[!IEEE-754]]. + 1. Return the IDL {{unrestricted double}} value + that represents the same numeric value as |x|. +
+ +Note: Since there is only a single JavaScript NaN value, +it must be canonicalized to a particular double precision IEEE 754 NaN value. The NaN value +mentioned above is chosen simply because it is the quiet NaN with the lowest +value when its bit pattern is interpreted as an unsigned 64-bit integer. + +
+ + + The result of [=converted to a JavaScript value|converting=] + an IDL {{unrestricted double}} value to a JavaScript + value is a Number: + + 1. If the IDL {{unrestricted double}} value is a NaN, + then the Number value is NaN. + 1. Otherwise, the Number value is + the one that represents the same numeric value as the IDL + {{unrestricted double}} value. +
+ +

bigint

+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{bigint}} value by running the following algorithm: + + 1. Let |x| be [=?=] [$ToBigInt$](|V|). + 1. Return the IDL {{bigint}} value that represents the same numeric value as |x|. +
+ +
+ + + The result of [=converted to a JavaScript value|converting=] + an IDL {{bigint}} value to a JavaScript value is a BigInt: + + 1. Return the {{BigInt}} value that represents the same numeric value as the IDL {{bigint}} + value. +
+ +
+ + + A JavaScript value |V| is converted + to an IDL [=numeric type=] |T| or {{bigint}} value by running the following algorithm: + + 1. Let |x| be [=?=] [$ToNumeric$](|V|). + 1. If [$Type$](|x|) is BigInt, then + 1. Return the IDL {{bigint}} value that represents the same numeric value as |x|. + 1. Assert: [$Type$](|x|) is Number. + 1. Return the result of [=converted to a JavaScript value|converting=] |x| to |T|. +
+ + +

DOMString

+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{DOMString}} value by running the following algorithm: + + 1. If |V| is null and the conversion is to an IDL type + [=extended attribute associated with|associated with=] the [{{LegacyNullToEmptyString}}] extended + attribute, then return the {{DOMString}} value that represents the empty string. + 1. Let |x| be [=?=] ToString(|V|). + 1. Return the IDL {{DOMString}} value that represents the same sequence of code units as the one the JavaScript String value |x| represents. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL {{DOMString}} value to a JavaScript + value is the String + value that represents the same sequence of [=code units=] that the + IDL {{DOMString}} represents. +

+ + +

ByteString

+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{ByteString}} value by running the following algorithm: + + 1. Let |x| be [=?=] ToString(|V|). + 1. If the value of any [=ECMAScript String/element=] + of |x| is greater than 255, then [=JavaScript/throw=] a {{TypeError}}. + 1. Return an IDL {{ByteString}} value + whose length is the length of |x|, and where the value of each element is + the value of the corresponding element of |x|. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL {{ByteString}} value to a JavaScript + value is a String + value whose length is the length of the {{ByteString}}, + and the value of each [=ECMAScript String/element=] of which is the value + of the corresponding element of the {{ByteString}}. +

+ + +

USVString

+ +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{USVString}} value by running the following algorithm: + + 1. Let |string| be the result of [=converted to an IDL value|converting=] |V| + to a {{DOMString}}. + 1. Return an IDL {{USVString}} value that is the result of + [=string/convert|converting=] |string| to a sequence of [=scalar values=]. +
+ +
+ + + The result of [=converted to a JavaScript value|converting=] + an IDL {{USVString}} value |S| to a JavaScript + value is |S|. +
+ + +

object

+ +IDL {{object}} +values are represented by JavaScript Object values. + +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{object}} value by running the following algorithm: + + 1. If Type(|V|) is not Object, then [=JavaScript/throw=] a {{TypeError}}. + 1. Return the IDL {{object}} value that is a reference to the same object as |V|. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL {{object}} value to a JavaScript + value is the Object value that represents a reference to the same object that the + IDL {{object}} represents. +

+ + +

symbol

+ +IDL {{symbol}} values are represented by JavaScript Symbol values. + +
+ + A JavaScript value |V| is [=converted to an IDL value|converted=] to an IDL {{symbol}} value + by running the following algorithm: + + 1. If Type(|V|) is not Symbol, then [=JavaScript/throw=] a {{TypeError}}. + 1. Return the IDL {{symbol}} value that is a reference to the same symbol as |V|. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] an IDL {{symbol}} value to a + JavaScript value is the Symbol value that represents a reference to the same + symbol that the IDL {{symbol}} represents. +

+ + +

Interface types

+ +IDL [=interface type=] +values are represented by JavaScript Object values (including [=function objects=]). + +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL [=interface type=] value by running the following algorithm (where |I| is the [=interface=]): + + 1. If |V| [=implements=] |I|, then return the IDL [=interface type=] value that represents a reference to that platform object. + 1. [=JavaScript/Throw=] a {{TypeError}}. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL [=interface type=] + value to a JavaScript value is the Object + value that represents a reference to the same object that the IDL + [=interface type=] value represents. +

+ + +

Callback interface types

+ +IDL [=callback interface type=] +values are represented by JavaScript Object values (including [=function objects=]). + +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL [=callback interface type=] value by running the following algorithm: + + 1. If Type(|V|) is not Object, then [=JavaScript/throw=] a {{TypeError}}. + 1. Return the IDL [=callback interface type=] value that represents a reference to |V|, with + the incumbent settings object as the [=callback context=]. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL [=callback interface type=] + value to a JavaScript value is the Object + value that represents a reference to the same object that the IDL + [=callback interface type=] value represents. +

+ + +

Dictionary types

+ +IDL [=dictionary type=] values are represented +by JavaScript Object values. Properties on +the object (or its prototype chain) correspond to [=dictionary members=]. + +
+ + + A JavaScript value |jsDict| is [=converted to an IDL value|converted=] + to an IDL [=dictionary type=] value by + running the following algorithm (where |D| is the [=dictionary type=]): + + 1. If Type(|jsDict|) is not Undefined, Null or Object, then [=JavaScript/throw=] a {{TypeError}}. + 1. Let |idlDict| be an empty [=ordered map=], representing a dictionary of type |D|. + 1. Let |dictionaries| be a list consisting of |D| and all of |D|'s [=inherited dictionaries=], + in order from least to most derived. + 1. For each dictionary |dictionary| in |dictionaries|, in order: + 1. For each dictionary member |member| declared on |dictionary|, in lexicographical order: + 1. Let |key| be the [=identifier=] of |member|. + 1. Let |jsMemberValue| be a JavaScript value, depending on Type(|jsDict|): +
+ : Undefined + : Null + :: undefined + : anything else + :: [=?=] Get(|jsDict|, |key|) +
+ 1. If |jsMemberValue| is not undefined, then: + 1. Let |idlMemberValue| be the result of [=converted to an IDL value|converting=] |jsMemberValue| to an IDL value whose type is the type |member| is declared to be of. + 1. [=map/Set=] |idlDict|[|key|] to |idlMemberValue|. + 1. Otherwise, if |jsMemberValue| is undefined but |member| has a [=dictionary member/default value=], then: + 1. Let |idlMemberValue| be |member|'s default value. + 1. [=map/Set=] |idlDict|[|key|] to |idlMemberValue|. + 1. Otherwise, if |jsMemberValue| is undefined and |member| is + [=dictionary member/required=], then throw a {{TypeError}}. + 1. Return |idlDict|. +
+ +Note: The order that [=dictionary members=] are looked +up on the JavaScript object are not necessarily the same as the object's property enumeration order. + +
+ + + An IDL dictionary value |V| is [=converted to a JavaScript value|converted=] + to a JavaScript Object value by + running the following algorithm (where |D| is the [=dictionary=]): + + 1. Let |O| be [$OrdinaryObjectCreate$]({{%Object.prototype%}}). + 1. Let |dictionaries| be a list consisting of |D| and all of |D|'s [=inherited dictionaries=], + in order from least to most derived. + 1. For each dictionary |dictionary| in |dictionaries|, in order: + 1. For each dictionary member |member| declared on |dictionary|, in lexicographical order: + 1. Let |key| be the [=identifier=] of |member|. + 1. If |V|[|key|] [=map/exists=], then: + 1. Let |idlValue| be |V|[|key|]. + 1. Let |value| be the result of [=converted to a JavaScript value|converting=] |idlValue| to a JavaScript value. + 1. Perform [=!=] CreateDataPropertyOrThrow(|O|, |key|, |value|). + +

Recall that if |member| has a [=dictionary member/default value=], + then |key| will always [=map/exist=] in |V|.

+ 1. Return |O|. +
+ + +

Enumeration types

+ +IDL [=enumeration types=] are represented by JavaScript String +values. + +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL [=enumeration|enumeration type=] value as follows + (where |E| is the [=enumeration=]): + + 1. Let |S| be the result of calling [=?=] ToString(|V|). + 1. If |S| is not one of |E|'s [=enumeration values=], + then [=JavaScript/throw=] a {{TypeError}}. + 1. Return the enumeration value of type |E| that is equal to |S|. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL [=enumeration|enumeration type=] value to a JavaScript + value is the String + value that represents the same sequence of [=code units=] as + the [=enumeration value=]. +

+ + +

Callback function types

+ +IDL [=callback function types=] are represented by JavaScript [=function objects=], except in the +[{{LegacyTreatNonObjectAsNull}}] case, when they can be any object. + +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL [=callback function type=] value by running the following algorithm: + + 1. If the result of calling IsCallable(|V|) is false + and the conversion to an IDL value + is not being performed due + to |V| being assigned to an [=attribute=] + whose type is a [=nullable type|nullable=] + [=callback function=] + that is annotated with [{{LegacyTreatNonObjectAsNull}}], + then [=JavaScript/throw=] a {{TypeError}}. + 1. Return the IDL [=callback function type=] value + that represents a reference to the same object that |V| represents, with the + incumbent settings object as the [=callback context=]. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL [=callback function type=] + value to a JavaScript value is a reference to the same object + that the IDL [=callback function type=] value represents. +

+ + +

Nullable types — |T|?

+ +IDL [=nullable type=] values are represented +by values of either the JavaScript type corresponding to the [=nullable types/inner type|inner IDL type=], or +the JavaScript null value. + +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL [=nullable type=] |T|? + value (where |T| is the [=nullable types/inner type=]) as follows: + + 1. If Type(|V|) is not Object, and + the conversion to an IDL value is being performed due + to |V| being assigned to an [=attribute=] + whose type is a [=nullable type|nullable=] + [=callback function=] + that is annotated with [{{LegacyTreatNonObjectAsNull}}], + then return the IDL + [=nullable type=] |T|? + value null. + 1. Otherwise, if |V| is undefined, + and |T| [=includes undefined=], + return the unique {{undefined}} value. + 1. Otherwise, if |V| is null or undefined, then return the IDL + [=nullable type=] |T|? + value null. + 1. Otherwise, return the result of + [=converted to an IDL value|converting=] |V| + using the rules for the [=nullable types/inner type|inner IDL type=] T. +
+ +
+ + + The result of [=converted to a JavaScript value|converting=] + an IDL [=nullable type=] value to a JavaScript value is: + + 1. If the IDL [=nullable type=] |T|? + value is null, + then the JavaScript value is null. + 1. Otherwise, the JavaScript value is the result of + [=converted to a JavaScript value|converting=] + the IDL [=nullable type=] value + to the [=nullable types/inner type|inner IDL type=] |T|. +
+ +

Sequences — sequence<|T|>

+ +IDL sequence<|T|> values are represented by +JavaScript Array values. + +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL sequence<T> value as follows: + + 1. If Type(|V|) is not Object, + [=JavaScript/throw=] a {{TypeError}}. + 1. Let |method| be [=?=] GetMethod(|V|, {{%Symbol.iterator%}}). + 1. If |method| is undefined, + [=JavaScript/throw=] a {{TypeError}}. + 1. Return the result of [=creating a sequence from an iterable|creating a sequence=] + from |V| and |method|. +
+ +
+ + + An IDL sequence value |S| of type + sequence<T> is + [=converted to a JavaScript value|converted=] + to a JavaScript Array object as follows: + + + 1. Let |n| be the length of |S|. + 1. Let |A| be a new Array object created as if by the expression []. + 1. Initialize |i| to be 0. + 1. While |i| < |n|: + 1. Let |V| be the value in |S| at index |i|. + 1. Let |E| be the result of [=converted to a JavaScript value|converting=] + |V| to a JavaScript value. + 1. Let |P| be the result of calling [=!=] ToString(|i|). + 1. Perform [=!=] CreateDataPropertyOrThrow(|A|, |P|, |E|). + 1. Set |i| to |i| + 1. + 1. Return |A|. +
+ + +
Creating a sequence from an iterable
+ +
+ + To create an IDL value of type sequence<|T|> + given an iterable |iterable| and an iterator getter |method|, + perform the following steps: + + 1. Let |iteratorRecord| be [=?=] GetIteratorFromMethod(|iterable|, |method|). + 1. Initialize |i| to be 0. + 1. Repeat + 1. Let |next| be [=?=] IteratorStepValue(|iteratorRecord|). + 1. If |next| is done, + then return an IDL sequence value of type + sequence<|T|> + of length |i|, where the value of the element + at index |j| is + |S||j|. + 1. Initialize |S||i| to the result of + [=converted to an IDL value|converting=] + |next| to an IDL value of type |T|. + 1. Set |i| to |i| + 1. +
+ +
+ + The following [=interface=] defines + an [=attribute=] of a sequence + type as well as an [=operation=] + with an argument of a sequence type. + +
+        [Exposed=Window]
+        interface Canvas {
+
+          sequence<DOMString> getSupportedImageCodecs();
+
+          undefined drawPolygon(sequence<double> coordinates);
+          sequence<double> getLastDrawnPolygon();
+
+          // ...
+        };
+    
+ + In a JavaScript implementation of this interface, an Array + object with elements of type String is used to + represent a sequence<DOMString>, while an + Array with elements of type Number + represents a sequence<double>. The + Array objects are effectively passed by + value; every time the getSupportedImageCodecs() + function is called a new Array is + returned, and whenever an Array is + passed to drawPolygon no reference + will be kept after the call completes. + +
+        // Obtain an instance of Canvas.  Assume that getSupportedImageCodecs()
+        // returns a sequence with two DOMString values: "image/png" and "image/svg+xml".
+        var canvas = getCanvas();
+
+        // An Array object of length 2.
+        var supportedImageCodecs = canvas.getSupportedImageCodecs();
+
+        // Evaluates to "image/png".
+        supportedImageCodecs[0];
+
+        // Each time canvas.getSupportedImageCodecs() is called, it returns a
+        // new Array object.  Thus modifying the returned Array will not
+        // affect the value returned from a subsequent call to the function.
+        supportedImageCodecs[0] = "image/jpeg";
+
+        // Evaluates to "image/png".
+        canvas.getSupportedImageCodecs()[0];
+
+        // This evaluates to false, since a new Array object is returned each call.
+        canvas.getSupportedImageCodecs() == canvas.getSupportedImageCodecs();
+
+        // An Array of Numbers...
+        var a = [0, 0, 100, 0, 50, 62.5];
+
+        // ...can be passed to a platform object expecting a sequence<double>.
+        canvas.drawPolygon(a);
+
+        // Each element will be converted to a double by first calling ToNumber().
+        // So the following call is equivalent to the previous one, except that
+        // "hi" will be alerted before drawPolygon() returns.
+        a = [false, "",
+             { valueOf: function() { alert("hi"); return 100; } }, 0,
+             "50", new Number(62.5)];
+        canvas.drawPolygon(a);
+
+        // Modifying an Array that was passed to drawPolygon() is guaranteed not to
+        // have an effect on the Canvas, since the Array is effectively passed by value.
+        a[4] = 20;
+        var b = canvas.getLastDrawnPolygon();
+        alert(b[4]);    // This would alert "50".
+    
+
+ + +

Records — record<|K|, |V|>

+ +IDL [=record=]<|K|, |V|> values are represented by +JavaScript Object values. + +
+ + + A JavaScript value |O| is [=converted to an IDL value|converted=] + to an IDL [=record=]<|K|, |V|> value as follows: + + 1. If Type(|O|) is not Object, + [=JavaScript/throw=] a {{TypeError}}. + 1. Let |result| be a new empty instance of [=record=]<|K|, |V|>. + 1. Let |keys| be [=?=] |O|.\[[OwnPropertyKeys]](). + 1. [=list/For each=] |key| of |keys|: + 1. Let |desc| be [=?=] |O|.\[[GetOwnProperty]](|key|). + 1. If |desc| is not undefined + and |desc|.\[[Enumerable]] is true: + 1. Let |typedKey| be |key| [=converted to an IDL value=] of type |K|. + 1. Let |value| be [=?=] Get(|O|, |key|). + 1. Let |typedValue| be |value| [=converted to an IDL value=] of type |V|. + 1. [=map/Set=] |result|[|typedKey|] to |typedValue|. + + Note: It's possible that |typedKey| is already in |result|, + if |K| is {{USVString}} and |key| contains unpaired surrogates. + 1. Return |result|. +
+ +
+ + + An IDL [=record=]<…> value |D| is + [=converted to a JavaScript value|converted=] + to a JavaScript value as follows: + + 1. Let |result| be [$OrdinaryObjectCreate$]({{%Object.prototype%}}). + 1. [=map/For each=] |key| → |value| of |D|: + 1. Let |jsKey| be |key| [=converted to a JavaScript value=]. + 1. Let |jsValue| be |value| [=converted to a JavaScript value=]. + 1. Let |created| be [=!=] CreateDataProperty(|result|, |jsKey|, |jsValue|). + 1. Assert: |created| is true. + 1. Return |result|. +
+ +
+ + + Passing the JavaScript value {b: 3, a: 4} as a + [=record=]<DOMString, double> argument + would result in the IDL value «[ "b" → 3, "a" → 4 ]». + + Records only consider [=own property|own=] [=enumerable=] + properties, so given an IDL operation + record<DOMString, double> + identity(record<DOMString, double> arg) which returns its + argument, the following code passes its assertions: + +
+        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 keys and values can be constrained, although keys can only be + constrained among the three string types. + The following conversions have the described results: + + + + + + + + + + + + + + + + + +
ValuePassed to typeResult
{"😞": 1}[=record=]<ByteString, double>{{TypeError}}
{"\uD83D": 1}[=record=]<USVString, double>«[ "\uFFFD" → 1 ]»
{"\uD83D": {hello: "world"}}[=record=]<DOMString, double>«[ "\uD83D" → 0 ]»
+
+ + +

Promise types — Promise<|T|>

+ +IDL [=promise type=] values are represented by JavaScript [=PromiseCapability=] records. + +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] to an IDL + Promise<T> value as follows: + + 1. Let |promiseCapability| be [=?=] [$NewPromiseCapability$]({{%Promise%}}). + 1. Perform [=?=] [$Call$](|promiseCapability|.\[[Resolve]], undefined, + « |V| »). + 1. Return |promiseCapability|. +
+ +

+ + The result of [=converted to a JavaScript value|converting=] + an IDL [=promise type=] value to a JavaScript + value is the value of the \[[Promise]] field of the record that + IDL [=promise type=] represents. +

+ +
Creating and manipulating Promises
+ +
+ + To create a new + Promise<T> in a [=realm=] |realm|, + perform the following steps: + + 1. Let |constructor| be |realm|.\[[Intrinsics]].[[{{%Promise%}}]]. + 1. Return [=?=] [$NewPromiseCapability$](|constructor|). +
+ +
+ + To create a resolved promise of type + Promise<|T|>, with |x| (a value of type |T|) in a [=realm=] + |realm|, perform the following steps: + + 1. Let |value| be the result of [=converted to a JavaScript value|converting=] |x| to a + JavaScript value. + 1. Let |constructor| be |realm|.\[[Intrinsics]].[[{{%Promise%}}]]. + 1. Let |promiseCapability| be [=?=] [$NewPromiseCapability$](|constructor|). + 1. Perform [=!=] [$Call$](|promiseCapability|.\[[Resolve]], undefined, + « |value| »). + 1. Return |promiseCapability|. +
+ +
+ + To create a rejected promise of type + Promise<T>, with reason |r| (a + JavaScript value) in a [=realm=] |realm|, perform the following steps: + + 1. Let |constructor| be |realm|.\[[Intrinsics]].[[{{%Promise%}}]]. + 1. Let |promiseCapability| be [=?=] [$NewPromiseCapability$](|constructor|). + 1. Perform [=!=] [$Call$](|promiseCapability|.\[[Reject]], undefined, + « |r| »). + 1. Return |promiseCapability|. +
+ +
+ + To resolve a Promise<|T|> |p| with |x| (a + value of type |T|), perform the following steps: + + 1. If |x| is not given, then let it be the {{undefined}} value. + 1. Let |value| be the result of [=converted to a JavaScript value|converting=] |x| to a + JavaScript value. + 1. Perform [=!=] [$Call$](|p|.\[[Resolve]], undefined, « |value| »). + + If |T| is {{undefined}}, then the |x| argument is optional, allowing a simpler "[=resolve=] p" usage. +
+ +
+ + To reject a Promise<T> + |p| with reason |r| (a JavaScript value), perform the following steps: + + 1. Perform [=!=] [$Call$](|p|.\[[Reject]], undefined, « |r| »). +
+ +
+ + To react + to a Promise<|T|> |promise|, given one or two sets of steps + to perform, covering when the promise is fulfilled, rejected, or both, perform the following + steps: + + 1. Let |onFulfilledSteps| be the following steps given argument |V|: + 1. Let |value| be the result of [=converted to an IDL value|converting=] |V| to an IDL + value of type |T|. + 1. If there is a set of steps to be run if the promise was fulfilled, then let |result| be + the result of performing them, given |value| if |T| is not {{undefined}}. Otherwise, let + |result| be |value|. + 1. Return |result|, [=converted to a JavaScript value=]. + 1. Let |onFulfilled| be [$CreateBuiltinFunction$](|onFulfilledSteps|, « »): + 1. Let |onRejectedSteps| be the following steps given argument |R|: + 1. Let |reason| be the result of [=converted to an IDL value|converting=] + |R| to an IDL value of type {{any}}. + 1. If there is a set of steps to be run if the promise was rejected, then let |result| be + the result of performing them, given |reason|. Otherwise, let |result| be + [=a promise rejected with=] |reason|. + 1. Return |result|, [=converted to a JavaScript value=]. + 1. Let |onRejected| be [$CreateBuiltinFunction$](|onRejectedSteps|, « »): + 1. Let |constructor| be |promise|.\[[Promise]].\[[Realm]].\[[Intrinsics]].[[{{%Promise%}}]]. + 1. Let |newCapability| be [=?=] [$NewPromiseCapability$](|constructor|). + + Note: Not all callers will use the returned {{Promise}}. Implementations might wish to + avoid creating |newCapability| in those cases. + 1. Return [$PerformPromiseThen$](|promise|.\[[Promise]], |onFulfilled|, |onRejected|, + |newCapability|). + + Note: This algorithm will behave in a very similar way to the + {{%Promise.prototype.then%|promise.then()}} method. + In particular, if the steps return a value of type |U| or + Promise<|U|>, this algorithm returns a + Promise<|U|> as well. +
+ +
+ + To perform some steps upon fulfillment of a + Promise<|T|> |promise| given some steps |steps| taking a + value of type |T|, perform the following steps: + + 1. Return the result of [=promise/reacting=] to |promise|: + * If |promise| was fulfilled with value |v|, then: + 1. Perform |steps| with |v|. +
+ +
+ + To perform some steps upon rejection of a + Promise<T> |promise| given some steps + |steps| taking a JavaScript value, perform the following steps: + + 1. Return the result of [=promise/reacting=] to |promise|: + * If |promise| was rejected with reason |r|, then: + 1. Perform |steps| with |r|. +
+ +
+ + To wait for all with a [=list=] of + Promise<|T|> values |promises|, with success steps + |successSteps| that take a [=list=] of |T| values and failure steps |failureSteps| that take a + rejection reason {{any}} value, perform the following steps: + + 1. Let |fullfilledCount| be 0. + 1. Let |rejected| be false. + 1. Let |rejectionHandlerSteps| be the following steps given |arg|: + 1. If |rejected| is true, abort these steps. + 1. Set |rejected| to true. + 1. Perform |failureSteps| given |arg|. + 1. Let |rejectionHandler| be [$CreateBuiltinFunction$](|rejectionHandlerSteps|, « »): + 1. Let |total| be |promises|'s [=list/size=]. + 1. If |total| is 0, then: + 1. [=Queue a microtask=] to perform |successSteps| given « ». + 1. Return. + 1. Let |index| be 0. + 1. Let |result| be a [=list=] containing |total| null values. + 1. [=list/For each=] |promise| of |promises|: + 1. Let |promiseIndex| be |index|. + 1. Let |fulfillmentHandler| be the following steps given |arg|: + 1. Set |result|[|promiseIndex|] to |arg|. + 1. Set |fullfilledCount| to |fullfilledCount| + 1. + 1. If |fullfilledCount| equals |total|, then perform |successSteps| given |result|. + 1. Let |fulfillmentHandler| be [$CreateBuiltinFunction$](|fulfillmentHandler|, « »): + 1. Perform [$PerformPromiseThen$](|promise|, |fulfillmentHandler|, |rejectionHandler|). + 1. Set |index| to |index| + 1. +
+ +
+ + To + get a promise for waiting for all + with a [=list=] of Promise<|T|> values |promises| and a + [=realm=] |realm|, perform the following steps: + + 1. Let |promise| be [=a new promise=] of type + Promise<sequence<|T|>> in + |realm|. + 1. Let |successSteps| be the following steps, given |results|: + 1. [=Resolve=] |promise| with |results|. + 1. Let |failureSteps| be the following steps, given |reason|: + 1. [=Reject=] |promise| with |reason|. + 1. [=Wait for all=] with |promises|, given |successSteps| and |failureSteps|. + 1. Return |promise|. + +

This definition is useful when you wish to aggregate the results of multiple + promises, and then produce another promise from them, in the same way that + {{Promise/all()|Promise.all()}} functions for JavaScript code. If you do not need to produce + another promise, then [=waiting for all=] is likely better. +

+ +
+ To mark as handled a + Promise<T> |promise|, set + |promise|.\[[Promise]].\[[PromiseIsHandled]] to true. + +

This definition is useful for promises for which you expect rejections to often + be ignored; it ensures such promises do not cause {{Window/unhandledrejection}} events. The most + common use case is for promise properties, which the web developer might or might not consult. + An example is the {{WritableStreamDefaultWriter/closed|writableStreamWriter.closed}} promise. +

+ + +
Examples
+ +
+ + delay is an [=operation=] that returns a promise that will be fulfilled in a + number of milliseconds. + It illustrates how simply you can resolve a promise, with one line of prose. + +
+        interface I {
+          Promise<undefined> delay(unrestricted double ms);
+        };
+    
+ +
+ + The delay(|ms|) method steps are: + + 1. Let |realm| be [=this=]'s [=relevant realm=]. + 1. Let |taskSource| be some appropriate [=task source=]. + 1. If |ms| is NaN, let |ms| be +0; otherwise let |ms| be the maximum of |ms| and +0. + 1. Let |p| be [=a new promise=] in |realm|. + 1. Run the following steps [=in parallel=]: + 1. Wait |ms| milliseconds. + 1. [=Queue a task=] on |taskSource| to [=resolve=] |p|. + 1. Return |p|. +
+
+ +
+ + The validatedDelay [=operation=] is much like the + delay function, except it will validate its arguments. + This shows how to use rejected promises to signal immediate failure before even starting any + asynchronous operations. + +
+        interface I {
+          Promise<undefined> validatedDelay(unrestricted double ms);
+        };
+    
+ +
+ + The validatedDelay(|ms|) method steps are: + + 1. Let |realm| be [=this=]'s [=relevant realm=]. + 1. Let |taskSource| be some appropriate [=task source=]. + 1. If |ms| is NaN, return [=a promise rejected with=] a {{TypeError}} in |realm|. + 1. If |ms| < 0, return [=a promise rejected with=] a {{RangeError}} in |realm|. + 1. Let |p| be [=a new promise=] in |realm|. + 1. Run the following steps [=in parallel=]: + 1. Wait |ms| milliseconds. + 1. [=Queue a task=] on |taskSource| to [=resolve=] |p|. + 1. Return |p|. +
+
+ +
+ + addDelay is an [=operation=] that adds an extra number of milliseconds of delay + between |promise| settling and the returned promise settling. + +
+        interface I {
+          Promise<any> addDelay(Promise<any> promise, unrestricted double ms);
+        };
+    
+ +
+ + The addDelay(|ms|, |promise|) method steps are: + + 1. Let |realm| be [=this=]'s [=relevant realm=]. + 1. Let |taskSource| be some appropriate [=task source=]. + 1. If |ms| is NaN, let |ms| be +0; otherwise let |ms| be the maximum of |ms| and +0. + 1. Let |p| be [=a new promise=] in |realm|. + 1. [=promise/React=] to |promise|: + * If |promise| was fulfilled with value |v|, then: + 1. Run the following steps [=in parallel=]: + 1. Wait |ms| milliseconds. + 1. [=Queue a task=] on |taskSource| to [=resolve=] |p| with |v|. + * If |promise| was rejected with reason |r|, then: + 1. Run the following steps [=in parallel=]: + 1. Wait |ms| milliseconds. + 1. [=Queue a task=] on |taskSource| to [=reject=] |p| with |r|. + 1. Return |p|. +
+
+ +
+ + environment.ready is an [=attribute=] that signals when some part of some + environment, e.g. a DOM document, becomes "ready". + It illustrates how to encode environmental asynchronicity. + +
+        interface Environment {
+          readonly attribute Promise<undefined> ready;
+        };
+    
+ + Every Environment object must have a ready promise, + which is a Promise<undefined>. + +
+ + The ready attribute getter steps are: + + 1. Return [=this=]'s [=Environment/ready promise=]. +
+ +
+ + To create an Environment object in a [=realm=] |realm|, perform the following + steps: + + 1. Let |taskSource| be some appropriate [=task source=]. + 1. Let |environment| be [=new=] Environment object in |realm|. + 1. Set |environment|'s [=Environment/ready promise=] to [=a new promise=] in |realm|. + 1. Run the following steps [=in parallel=]: + 1. Do some asynchronous work. + 1. If |environment| becomes ready successfully, then [=queue a task=] on |taskSource| to + [=resolve=] |environment|'s [=Environment/ready promise=]. + 1. If |environment| fails to become ready, then [=queue a task=] on |taskSource| to + [=reject=] |environment|'s [=Environment/ready promise=] with a + "{{NetworkError!!exception}}" {{DOMException}}. + 1. Return |environment|. +
+
+ +
+ + addBookmark is an [=operation=] that requests that the user add the current web + page as a bookmark. + It's drawn from some + iterative design work and illustrates a more real-world scenario of appealing to + environmental asynchrony, as well as immediate rejections. + +
+        interface I {
+          Promise<undefined> addBookmark();
+        };
+    
+ +
+ + The addBookmark() method steps are: + + 1. Let |taskSource| be some appropriate [=task source=]. + 1. If this method was not invoked as a result of explicit user action, return + [=a promise rejected with=] a "{{SecurityError}}" {{DOMException}}. + 1. If the document's mode of operation is standalone, return [=a promise rejected with=] a + "{{NotSupportedError}}" {{DOMException}}. + 1. Let |promise| be [=a new promise=]. + 1. Let |info| be the result of getting a web application's metadata. + 1. Run the following steps [=in parallel=]: + 1. Using |info|, and in a manner that is user-agent specific, allow the end user to make a + choice as to whether they want to add the bookmark. + 1. If the end-user aborts the request to add the bookmark (e.g., they hit escape, or + press a "cancel" button), then [=queue a task=] on |taskSource| to [=reject=] + |promise| with an "{{AbortError}}" {{DOMException}}. + 1. Otherwise, [=queue a task=] on |taskSource| to [=resolve=] |promise|. + 1. Return |promise|. +
+
+ +
+ + Several places in [[SERVICE-WORKERS]] use [=get a promise to wait for all=]. + batchRequest illustrates a simplified version of one of their uses. + It takes as input a [=sequence=] of URLs, and returns a promise for a [=sequence=] of + {{Response}} objects created by fetching the corresponding URL. + If any of the fetches fail, it will return [=a promise rejected with=] that failure. + +
+        interface I {
+          Promise<sequence<Response>> batchRequest(sequence<USVString> urls);
+        };
+    
+ +
+ + The batchRequest(|urls|) method steps are: + + 1. Let |responsePromises| be « ». + 1. [=list/For each=] |url| of |urls|: + 1. Let |p| be the result of calling {{WindowOrWorkerGlobalScope/fetch()}} with |url|. + 1. [=list/Append=] |p| to |responsePromises|. + 1. Let |p| be the result of [=getting a promise to wait for all=] with |responsePromises|. + 1. Return |p|. +
+
+ + +

Union types

+ +IDL [=union type=] values are represented by JavaScript values +that correspond to the union's [=member types=]. + +
+ + + To [=converted to an IDL value|convert a JavaScript value=] |V| to an IDL [=union type=] + value is done as follows: + + 1. If the [=union type=] [=includes undefined=] + and |V| is undefined, + then return the unique {{undefined}} value. + 1. If the [=union type=] [=includes a nullable type=] and + |V| is null or undefined, + then return the IDL value null. + 1. Let |types| be the [=flattened member types=] + of the [=union type=]. + 1. If |V| is null or undefined, then: + 1. If |types| includes a [=dictionary type=], then return the + result of [=converted to an IDL value|converting=] |V| to that dictionary type. + 1. If |V| [=is a platform object=], then: + 1. If |types| includes an [=interface type=] that |V| + [=implements=], then return the IDL value that is a reference to the object |V|. + 1. If |types| includes {{object}}, then return the IDL value + that is a reference to the object |V|. + 1. If Type(|V|) is Object, |V| has an \[[ArrayBufferData]] + [=/internal slot=], and IsSharedArrayBuffer(|V|) is false, then: + 1. If |types| includes {{ArrayBuffer}}, then return the + result of [=converted to an IDL value|converting=] + |V| to {{ArrayBuffer}}. + 1. If |types| includes {{object}}, then return the IDL value + that is a reference to the object |V|. + 1. If Type(|V|) is Object, |V|, has an \[[ArrayBufferData]] + [=/internal slot=], and IsSharedArrayBuffer(|V|) is true, then: + 1. If |types| includes {{SharedArrayBuffer}}, then return the + result of [=converted to an IDL value|converting=] + |V| to {{SharedArrayBuffer}}. + 1. If |types| includes {{object}}, then return the IDL value + that is a reference to the object |V|. + 1. If Type(|V|) is Object and |V| has a \[[DataView]] [=/internal slot=], then: + 1. If |types| includes {{DataView}}, then return the + result of [=converted to an IDL value|converting=] + |V| to {{DataView}}. + 1. If |types| includes {{object}}, then return the IDL value + that is a reference to the object |V|. + 1. If Type(|V|) is Object and |V| has a \[[TypedArrayName]] [=/internal slot=], then: + 1. If |types| includes a [=typed array type=] + whose name is the value of |V|'s \[[TypedArrayName]] [=/internal slot=], then return the + result of [=converted to an IDL value|converting=] + |V| to that type. + 1. If |types| includes {{object}}, then return the IDL value + that is a reference to the object |V|. + 1. If IsCallable(|V|) is true, then: + 1. If |types| includes a [=callback function=] + type, then return the result of + [=converted to an IDL value|converting=] + |V| to that callback function type. + 1. If |types| includes {{object}}, then return the IDL value + that is a reference to the object |V|. + 1. If Type(|V|) is Object, then: + 1. If |types| includes a [=sequence type=], then + 1. Let |method| be [=?=] GetMethod(|V|, {{%Symbol.iterator%}}). + 1. If |method| is not undefined, + return the result of + [=creating a sequence from an iterable|creating a sequence=] + of that type from |V| and |method|. + 1. If |types| includes a [=frozen array type=], then + 1. Let |method| be [=?=] GetMethod(|V|, {{%Symbol.iterator%}}). + 1. If |method| is not undefined, + return the result of + [=Creating a frozen array from an iterable|creating a frozen array=] + of that type from |V| and |method|. + 1. If |types| includes a [=dictionary type=], then return the + result of [=converted to an IDL value|converting=] + |V| to that dictionary type. + 1. If |types| includes a [=record type=], then return the + result of [=converted to an IDL value|converting=] + |V| to that record type. + 1. If |types| includes a [=callback interface=] + type, then return the result of + [=converted to an IDL value|converting=] + |V| to that [=callback interface type=]. + 1. If |types| includes {{object}}, then return the IDL value + that is a reference to the object |V|. + 1. If Type(|V|) is Boolean, then: + 1. If |types| includes {{boolean}}, + then return the result of [=converted to an IDL value|converting=] + |V| to {{boolean}}. + 1. If Type(|V|) is Number, then: + 1. If |types| includes a [=numeric type=], + then return the result of [=converted to an IDL value|converting=] + |V| to that [=numeric type=]. + 1. If Type(|V|) is BigInt, then: + 1. If |types| includes {{bigint}}, + then return the result of [=converted to an IDL value|converting=] + |V| to {{bigint}} + 1. If |types| includes a [=string type=], + then return the result of + [=converted to an IDL value|converting=] + |V| to that type. + 1. If |types| includes a [=numeric type=] and {{bigint}}, + then return the result of [=converted to a numeric type or bigint|converting=] + |V| to either that [=numeric type=] or {{bigint}}. + 1. If |types| includes a [=numeric type=], + then return the result of [=converted to an IDL value|converting=] + |V| to that [=numeric type=]. + 1. If |types| includes {{boolean}}, + then return the result of [=converted to an IDL value|converting=] + |V| to {{boolean}}. + 1. If |types| includes {{bigint}}, + then return the result of [=converted to an IDL value|converting=] + |V| to {{bigint}}. + 1. [=JavaScript/Throw=] a {{TypeError}}. +
+ +

+ + An IDL union type value is + [=converted to a JavaScript value=] + according to the rules for converting the [=specific type=] + of the IDL union type value as described in this section ([[#js-type-mapping]]). +

+ + +

Buffer source types

+ +A value of an IDL {{ArrayBuffer}} is represented by an object of the corresponding JavaScript class. +If it is not [=extended attributes associated with|associated with=] the [{{AllowResizable}}] +[=extended attribute=], it can only be backed by JavaScript {{ArrayBuffer}} +objects |V| for which IsResizableArrayBuffer(|V|) is false. + +A value of an IDL {{SharedArrayBuffer}} is represented by an object of the corresponding JavaScript +class. If it is not [=extended attributes associated with|associated with=] the [{{AllowResizable}}] +[=extended attribute=], it can only be backed by JavaScript +{{SharedArrayBuffer}} objects |V| for which +IsResizableArrayBuffer(|V|) is false. + +Values of the IDL [=buffer view types=] are represented by objects of the corresponding JavaScript +class, with the following additional restrictions on those objects. + + + +
+ + + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{ArrayBuffer}} value by running the following algorithm: + + 1. If Type(|V|) is not Object, + or |V| does not have an \[[ArrayBufferData]] [=/internal slot=], + then [=JavaScript/throw=] a {{TypeError}}. + 1. If IsSharedArrayBuffer(|V|) is true, then [=JavaScript/throw=] + a {{TypeError}}. + 1. If the conversion is not to an IDL type + [=extended attributes associated with|associated with=] the [{{AllowResizable}}] + [=extended attribute=], and IsResizableArrayBuffer(|V|) is true, + then [=JavaScript/throw=] a {{TypeError}}. + 1. Return the IDL {{ArrayBuffer}} value that is a reference + to the same object as |V|. +
+ +
+ + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{SharedArrayBuffer}} value by running the following algorithm: + + 1. If Type(|V|) is not Object, + or |V| does not have an \[[ArrayBufferData]] [=/internal slot=], + then [=JavaScript/throw=] a {{TypeError}}. + 1. If IsSharedArrayBuffer(|V|) is false, then [=JavaScript/throw=] + a {{TypeError}}. + 1. If the conversion is not to an IDL type + [=extended attributes associated with|associated with=] the [{{AllowResizable}}] + [=extended attribute=], and IsResizableArrayBuffer(|V|) is true, + then [=JavaScript/throw=] a {{TypeError}}. + 1. Return the IDL {{SharedArrayBuffer}} value that is a reference + to the same object as |V|. +
+ +
+ + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL {{DataView}} value by running the following algorithm: + + 1. If Type(|V|) is not Object, + or |V| does not have a \[[DataView]] [=/internal slot=], + then [=JavaScript/throw=] a {{TypeError}}. + 1. If the conversion is not to an IDL type + [=extended attributes associated with|associated with=] the [{{AllowShared}}] + [=extended attribute=], and IsSharedArrayBuffer(|V|.\[[ViewedArrayBuffer]]) is true, + then [=JavaScript/throw=] a {{TypeError}}. + 1. If the conversion is not to an IDL type + [=extended attributes associated with|associated with=] the [{{AllowResizable}}] + [=extended attribute=], and IsResizableArrayBuffer(|V|.\[[ViewedArrayBuffer]]) is true, + then [=JavaScript/throw=] a {{TypeError}}. + 1. Return the IDL {{DataView}} value that is a reference + to the same object as |V|. +
+ +
+ + A JavaScript value |V| is + [=converted to an IDL value|converted=] + to an IDL {{Int8Array}}, + {{Int16Array}}, + {{Int32Array}}, + {{Uint8Array}}, + {{Uint16Array}}, + {{Uint32Array}}, + {{Uint8ClampedArray}}, + {{BigInt64Array}}, + {{BigUint64Array}}, + {{Float16Array}}, + {{Float32Array}}, or + {{Float64Array}} value + by running the following algorithm: + + 1. Let |T| be the IDL type |V| is being converted to. + 1. If Type(|V|) is not Object, + or |V| does not have a \[[TypedArrayName]] [=/internal slot=] + with a value equal to |T|'s name, + then [=JavaScript/throw=] a {{TypeError}}. + 1. If the conversion is not to an IDL type + [=extended attributes associated with|associated with=] the [{{AllowShared}}] + [=extended attribute=], and IsSharedArrayBuffer(|V|.\[[ViewedArrayBuffer]]) is true, + then [=JavaScript/throw=] a {{TypeError}}. + 1. If the conversion is not to an IDL type + [=extended attributes associated with|associated with=] the [{{AllowResizable}}] + [=extended attribute=], and IsResizableArrayBuffer(|V|.\[[ViewedArrayBuffer]]) is true, + then [=JavaScript/throw=] a {{TypeError}}. + 1. Return the IDL value of type |T| that is a reference to the same object as |V|. +
+ +
+ +The result of [=converted to a JavaScript value|converting=] +an IDL value of any [=buffer source type=] +to a JavaScript value is the Object value that represents +a reference to the same object that the IDL value represents. +
+ +
+ +
+ To create an {{ArrayBuffer}} from a [=byte sequence=] + |bytes| in a [=realm=] |realm|: + + 1. Let |jsArrayBuffer| be [=?=] + [$AllocateArrayBuffer$](|realm|.\[[Intrinsics]].[[{{%ArrayBuffer%}}]], |bytes|'s + [=byte sequence/length=]). + 1. Let |arrayBuffer| be the result of [=converted to an IDL value|converting=] |jsArrayBuffer| + to an IDL value of type {{ArrayBuffer}}. + 1. [=ArrayBuffer/Write=] |bytes| into |arrayBuffer|. + 1. Return |arrayBuffer|. +
+ +
+ To create a {{SharedArrayBuffer}} from a + [=byte sequence=] |bytes| in a [=realm=] |realm|: + + 1. Let |jsSharedArrayBuffer| be [=?=] + [$AllocateSharedArrayBuffer$](|realm|.\[[Intrinsics]].[[{{%SharedArrayBuffer%}}]], |bytes|'s + [=byte sequence/length=]). + 1. Let |sharedArrayBuffer| be the result of [=converted to an IDL value|converting=] + |jsSharedArrayBuffer| to an IDL value of type {{SharedArrayBuffer}}. + 1. [=SharedArrayBuffer/Write=] |bytes| into |sharedArrayBuffer|. + 1. Return |sharedArrayBuffer|. +
+ +
+ To create one of the {{ArrayBufferView}} types from a + [=byte sequence=] |bytes| in a [=realm=] |realm|: + + 1. Assert: if the type is not {{DataView}}, then |bytes|'s [=byte sequence/length=] [=modulo=] + the [=element size=] of that type is 0. + 1. Let |arrayBuffer| be the result of [=ArrayBuffer/creating=] an {{ArrayBuffer}} from |bytes| + in |realm|. + 1. Let |jsArrayBuffer| be the result of [=converted to a JavaScript value|converting=] + |arrayBuffer| to a JavaScript value. + 1. Let |constructor| be the appropriate constructor from |realm|.\[[Intrinsics]] for the type + of {{ArrayBufferView}} being created. + 1. Let |jsView| be [=!=] [$Construct$](|constructor|, « |jsArrayBuffer| »). + 1. Return the result of [=converted to an IDL value|converting=] |jsView| into the given type. +
+ +
+ To get a copy of the bytes held by the buffer source + given a [=buffer source type=] instance |bufferSource|: + + 1. Let |jsBufferSource| be the result of [=converted to a JavaScript value|converting=] + |bufferSource| to a JavaScript value. + 1. Let |jsArrayBuffer| be |jsBufferSource|. + 1. Let |offset| be 0. + 1. Let |length| be 0. + 1. If |jsBufferSource| has a \[[ViewedArrayBuffer]] [=/internal slot=], then: + 1. Set |jsArrayBuffer| to |jsBufferSource|.\[[ViewedArrayBuffer]]. + 1. Set |offset| to |jsBufferSource|.\[[ByteOffset]]. + 1. Set |length| to |jsBufferSource|.\[[ByteLength]]. + 1. Otherwise: + 1. Assert: |jsBufferSource| is an {{ArrayBuffer}} or + {{SharedArrayBuffer}} object. + 1. Set |length| to |jsBufferSource|.\[[ArrayBufferByteLength]]. + 1. If [$IsDetachedBuffer$](|jsArrayBuffer|) is true, then return the empty + [=byte sequence=]. + 1. Let |bytes| be a new [=byte sequence=] of [=byte sequence/length=] equal to |length|. + 1. For |i| in [=the range=] |offset| to |offset| + |length| − 1, inclusive, set + |bytes|[|i| − |offset|] to [$GetValueFromBuffer$](|jsArrayBuffer|, |i|, Uint8, + true, Unordered). + 1. Return |bytes|. +
+ +
+ The byte length of a [=buffer source type=] instance + |bufferSource| is the value returned by the following steps: + + 1. Let |jsBufferSource| be the result of [=converted to a JavaScript value|converting=] + |bufferSource| to a JavaScript value. + 1. If |jsBufferSource| has a \[[ViewedArrayBuffer]] internal slot, then return + |jsBufferSource|.\[[ByteLength]]. + 1. Return |jsBufferSource|.\[[ArrayBufferByteLength]]. +
+ + +
+ The underlying buffer of a [=buffer source type=] instance + |bufferSource| is the value returned by the following steps: + + 1. If |bufferSource| is a [=buffer type=] instance, then return |bufferSource|. + 1. Let |jsBufferView| be the result of [=converted to a JavaScript value|converting=] + |bufferSource| to a JavaScript value. + 1. Let |jsBuffer| be |jsBufferView|.\[[ViewedArrayBuffer]]. + 1. If [$IsSharedArrayBuffer$](|jsBuffer|) is false, then return the result of + [=converted to an IDL value|converting=] |jsBuffer| to an IDL value of type {{ArrayBuffer}}. + 1. Return the result of [=converted to an IDL value|converting=] |jsBuffer| to an IDL value of + type {{SharedArrayBuffer}}. +
+ +
+ To write a + [=byte sequence=] |bytes| into a [=buffer type=] instance |arrayBuffer|, optionally given a + |startingOffset| + (default 0): + + 1. Let |jsArrayBuffer| be the result of [=converted to a JavaScript value|converting=] + |arrayBuffer| to a JavaScript value. + 1. Assert: |bytes|'s [=byte sequence/length=] ≤ |jsArrayBuffer|.\[[ArrayBufferByteLength]] + − |startingOffset|. + 1. For |i| in [=the range=] |startingOffset| to |startingOffset| + |bytes|'s [=byte + sequence/length=] − 1, inclusive, perform [$SetValueInBuffer$](|jsArrayBuffer|, + |i|, Uint8, |bytes|[|i| - |startingOffset|], true, Unordered). +
+ +
+ To write a [=byte sequence=] |bytes| into an + {{ArrayBufferView}} |view|, optionally given a + |startingOffset| (default 0): + + 1. Let |jsView| be the result of [=converted to a JavaScript value|converting=] |view| to + a JavaScript value. + 1. Assert: |bytes|'s [=byte sequence/length=] ≤ |jsView|.\[[ByteLength]] − + |startingOffset|. + 1. Assert: if |view| is not a {{DataView}}, then |bytes|'s [=byte sequence/length=] [=modulo=] + the [=element size=] of |view|'s type is 0. + 1. Let |arrayBuffer| be the result of [=converted to an IDL value|converting=] + |jsView|.\[[ViewedArrayBuffer]] to an IDL value of type {{ArrayBuffer}}. + 1. [=ArrayBuffer/Write=] |bytes| into |arrayBuffer| with + [=ArrayBuffer/write/startingOffset=] set to |jsView|.\[[ByteOffset]] + + |startingOffset|. +
+ +
+ Extreme care must be taken when writing specification text that + [=ArrayBuffer/writes=] into a [=buffer source type=] instance, as the underlying data + can easily be changed by the script author or other APIs at unpredictable times. This is + especially true if a {{SharedArrayBuffer}} object is involved. + + For the non-shared cases, a more recommended pattern is to [=ArrayBuffer/transfer=] the + {{ArrayBuffer}} first if possible, to ensure the writes cannot overlap with other modifications, + and then give the new {{ArrayBuffer}} instance to author code as necessary. Alternately, you can + [=get a copy of the bytes held by the buffer source=], modify those bytes, and then use them to + [=ArrayBuffer/create=] a new {{ArrayBuffer}} or {{ArrayBufferView}} to give back to author code. +
+ +
+ To detach an {{ArrayBuffer}} |arrayBuffer|: + + 1. Let |jsArrayBuffer| be the result of [=converted to a JavaScript value|converting=] + |arrayBuffer| to a JavaScript value. + 1. Perform [=?=] [$DetachArrayBuffer$](|jsArrayBuffer|). + +

This will throw an exception if + |jsArrayBuffer| has an \[[ArrayBufferDetachKey]] that is not undefined, such as is the case + with the value of {{Memory|WebAssembly.Memory}}'s {{Memory/buffer}} attribute. + [[WASM-JS-API-1]] + +

Detaching a buffer that is already [=BufferSource/detached=] is a no-op. +

+ +
+ A [=buffer source type=] instance |bufferSource| is + detached if the following steps return true: + + 1. Let |jsArrayBuffer| be the result of [=converted to a JavaScript value|converting=] + |bufferSource| to a JavaScript value. + 1. If |jsArrayBuffer| has a \[[ViewedArrayBuffer]] internal slot, then set |jsArrayBuffer| to + |jsArrayBuffer|.\[[ViewedArrayBuffer]]. + 1. Return [$IsDetachedBuffer$](|jsArrayBuffer|). +
+ +
+ A [=buffer source type=] instance |bufferSource| is + transferable if the following steps return true: + + 1. Let |jsArrayBuffer| be the result of [=converted to a JavaScript value|converting=] + |bufferSource| to a JavaScript value. + 1. If |jsArrayBuffer| has a \[[ViewedArrayBuffer]] internal slot, then set |jsArrayBuffer| to + |jsArrayBuffer|.\[[ViewedArrayBuffer]]. + 1. If [$IsSharedArrayBuffer$](|jsArrayBuffer|) is true, then return false. + 1. If [$IsDetachedBuffer$](|jsArrayBuffer|) is true, then return false. + 1. If |jsArrayBuffer|.\[[ArrayBufferDetachKey]] is not undefined, then + return false. + 1. Return true. +
+ +
+ To transfer an {{ArrayBuffer}} |arrayBuffer|, optionally + given a [=realm=] |targetRealm|: + + 1. Let |jsArrayBuffer| be the result of [=converted to a JavaScript value|converting=] + |arrayBuffer| to a JavaScript value. + 1. If [$IsDetachedBuffer$](|jsArrayBuffer|) is false, then [=JavaScript/throw=] a + {{TypeError}}. + 1. Let |arrayBufferData| be |jsArrayBuffer|.\[[ArrayBufferData]]. + 1. Let |arrayBufferByteLength| be |jsArrayBuffer|.\[[ArrayBufferByteLength]]. + 1. Perform [=?=] [$DetachArrayBuffer$](|jsArrayBuffer|). + 1. If |targetRealm| is not given, let |targetRealm| be the [=current realm=]. + 1. Let |jsTransferred| be [=?=] + [$AllocateArrayBuffer$](|targetRealm|.\[[Intrinsics]].[[{{%ArrayBuffer%}}]], 0). + 1. Set |jsTransferred|.\[[ArrayBufferData]] to |arrayBufferData|. + 1. Set |jsTransferred|.\[[ArrayBufferByteLength]] to |arrayBufferByteLength|. + 1. Return the result of [=converted to an IDL value|converting=] |jsTransferred| to an IDL + value of type {{ArrayBuffer}}. + +
+ This will throw an exception under any of the following circumstances: + + * |arrayBuffer| cannot be [=BufferSource/detached=], for the reasons + explained in that algorithm's + definition; + * |arrayBuffer| is already [=BufferSource/detached=]; + * Sufficient memory cannot be allocated in |realm|. Generally this will only be the case + if |realm| is in a different [=agent cluster=] than the one in which |arrayBuffer| was + allocated. If they are in the same [=agent cluster=], then implementations will just + change the backing pointers to get the same observable results with better performance + and no allocations. +
+
+ +

Frozen arrays — FrozenArray<|T|>

+ +Values of frozen array types are represented by frozen JavaScript +Array object references. + +
+ + A JavaScript value |V| is [=converted to an IDL value|converted=] + to an IDL FrozenArray<|T|> value + by running the following algorithm: + + 1. Let |values| be the result of + [=converted to an IDL value|converting=] + |V| to IDL type sequence<|T|>. + 1. Return the result of + [=create a frozen array|creating a frozen array=] + from |values|. +
+ +
+ + To create a frozen array + from a sequence of values of type |T|, follow these steps: + + 1. Let |array| be the result of + [=converted to a JavaScript value|converting=] + the sequence of values of type |T| to a JavaScript value. + 1. Perform [=!=] SetIntegrityLevel(|array|, "frozen"). + 1. Return |array|. +
+ +The result of [=converted to a JavaScript value|converting=] +an IDL FrozenArray<|T|> value to a JavaScript +value is the Object value that represents a reference +to the same object that the IDL FrozenArray<|T|> represents. + + +
Creating a frozen array from an iterable
+ +
+ + To create an IDL value of type FrozenArray<|T|> given an + iterable |iterable| and an iterator getter |method|, perform the following steps: + + 1. Let |values| be the result of [=creating a sequence from an iterable|creating a sequence=] + of type sequence<|T|> from |iterable| and |method|. + 1. Return the result of [=create a frozen array|creating a frozen array=] from |values|. +
+ +

Observable arrays — ObservableArray<|T|>

+ +Values of observable array types are represented by [=observable array exotic objects=]. + +Instead of the usual conversion algorithms, observable array types have special handling as part of +the [=attribute getter=] and [=attribute setter=] algorithms. + +In the JavaScript binding, JavaScript objects that represent [=platform objects=] have a +backing observable array exotic object for each [=regular attribute=] of an +[=observable array type=]. These are created and managed as part of the [=define the attributes=] +algorithm. + +
+ The [=observable array attribute/backing list=] for an observable array attribute in the + JavaScript binding, given a [=platform object=] |obj| and an attribute |attribute|, is the + [=list=] returned by the following algorithm: + + 1. Assert: |obj| [=implements=] an [=interface=] with the [=regular attribute=] |attribute|. + 1. Let |oa| be |obj|'s [=backing observable array exotic object=] for |attribute|. + 1. Return |oa|.\[[ProxyHandler]].\[[BackingList]]. +
+ + +

Extended attributes

+ +This section defines a number of +[=extended attributes=] +whose presence affects the JavaScript binding. + + +

[AllowResizable]

+ +If the [{{AllowResizable}}] [=extended attribute=] appears on a [=buffer type=], it creates a new +IDL type that allows for the respective corresponding JavaScript {{ArrayBuffer}} +or {{SharedArrayBuffer}} object to be resizable. + +If the [{{AllowResizable}}] [=extended attribute=] appears on one of the [=buffer view types=] and +the [{{AllowShared}}] [=extended attribute=] does not, it creates a new IDL type that allows the +buffer view type to be backed by a JavaScript {{ArrayBuffer}} that is +resizable, instead of only by a fixed-length {{ArrayBuffer}}. + +If the [{{AllowResizable}}] [=extended attribute=] and the [{{AllowShared}}] [=extended attribute=] +both appear on one of the [=buffer view types=], it creates a new IDL type that allows the buffer +view type to be additionally backed by a JavaScript {{SharedArrayBuffer}} +that is growable. + +The [{{AllowResizable}}] extended attribute must [=takes no arguments|take no arguments=]. + +A type that is not a [=buffer source type=] must not be +[=extended attributes associated with|associated with=] the [{{AllowResizable}}] extended attribute. + +See the rules for converting JavaScript values to IDL [=buffer source types=] in +[[#js-buffer-source-types]] for the specific requirements that the use of [{{AllowResizable}}] entails. + +See the example in [[#AllowShared]] for example usage of both [{{AllowResizable}}] and [{{AllowShared}}]. + + +

[AllowShared]

+ +If the [{{AllowShared}}] [=extended attribute=] appears on one of the [=buffer view types=], it +creates a new IDL type that allows the object to be backed by an {{SharedArrayBuffer}} instead of +only by an {{ArrayBuffer}}. + +The [{{AllowShared}}] extended attribute must [=takes no arguments|take no arguments=]. + +A type that is not a [=buffer view type=] must not be +[=extended attributes associated with|associated with=] the [{{AllowShared}}] extended attribute. + +See the rules for converting JavaScript values to IDL [=buffer view types=] in +[[#js-buffer-source-types]] for the specific requirements that the use of [{{AllowShared}}] entails. + +
+ The following [=IDL fragment=] demonstrates the possible combinations of the + [{{AllowResizable}}] and [{{AllowShared}}] [=extended attribute=]: + +
+        [Exposed=Window]
+        interface ExampleBufferFeature {
+          undefined writeInto(ArrayBufferView dest);
+          undefined writeIntoResizable([AllowResizable] ArrayBufferView dest);
+          undefined writeIntoShared([AllowShared] ArrayBufferView dest);
+          undefined writeIntoSharedResizable([AllowResizable, AllowShared] ArrayBufferView dest);
+        };
+    
+ + With this definition, + +
+ + +

[Clamp]

+ +If the [{{Clamp}}] [=extended attribute=] appears on one of the [=integer types=], it creates a new +IDL type such that that when a JavaScript Number is converted to the IDL type, +out-of-range values will be clamped to the range of valid values, rather than using the operators +that use a modulo operation (ToInt32, ToUint32, etc.). + +The [{{Clamp}}] +extended attribute must +[=takes no arguments|take no arguments=]. + +A type annotated with the [{{Clamp}}] extended attribute must not appear in a [=read only=] +attribute. A type must not be [=extended attributes associated with|associated with=] both the +[{{Clamp}}] and [{{EnforceRange}}] extended attributes. A type that is not an [=integer type=] must +not be [=extended attributes associated with|associated with=] the [{{Clamp}}] extended attribute. + +See the rules for converting JavaScript values to the various IDL integer +types in [[#js-integer-types]] +for the specific requirements that the use of +[{{Clamp}}] entails. + +
+ + In the following [=IDL fragment=], + two [=operations=] are declared that + take three {{octet}} arguments; one uses + the [{{Clamp}}] [=extended attribute=] + on all three arguments, while the other does not: + +
+        [Exposed=Window]
+        interface GraphicsContext {
+          undefined setColor(octet red, octet green, octet blue);
+          undefined setColorClamped([Clamp] octet red, [Clamp] octet green, [Clamp] octet blue);
+        };
+    
+ + A call to setColorClamped with + Number values that are out of range for an + {{octet}} are clamped to the range [0, 255]. + +
+        // Get an instance of GraphicsContext.
+        var context = getGraphicsContext();
+
+        // Calling the non-[Clamp] version uses ToUint8 to coerce the Numbers to octets.
+        // This is equivalent to calling setColor(255, 255, 1).
+        context.setColor(-1, 255, 257);
+
+        // Call setColorClamped with some out of range values.
+        // This is equivalent to calling setColorClamped(0, 255, 255).
+        context.setColorClamped(-1, 255, 257);
+    
+
+ + +

[CrossOriginIsolated]

+ +If the [{{CrossOriginIsolated}}] [=extended attribute=] appears on an +[=interface=], +[=partial interface=], +[=interface mixin=], +[=partial interface mixin=], +[=callback interface=], +[=namespace=], +[=partial namespace=], +[=interface member=], +[=interface mixin member=], or +[=namespace member=], +it indicates that the construct is [=exposed=] only within an environment whose +[=environment settings object/cross-origin isolated capability=] is true. The +[{{CrossOriginIsolated}}] extended attribute must not be used on any other construct. + +The [{{CrossOriginIsolated}}] extended attribute must [=takes no arguments|take no arguments=]. + +If [{{CrossOriginIsolated}}] appears on an [=overloaded=] [=operation=], +then it must appear on all overloads. + +The [{{CrossOriginIsolated}}] [=extended attribute=] must not be specified both on + +* an [=interface member=] and its [=interface=] or [=partial interface=]; +* an [=interface mixin member=] and its [=interface mixin=] or [=partial interface mixin=]; +* a [=namespace member=] and its [=namespace=] or [=partial namespace=]. + +Note: This is because adding the [{{CrossOriginIsolated}}] [=extended attribute=] on a [=member=] +when its containing definition is also annotated with the [{{CrossOriginIsolated}}] +[=extended attribute=] does not further restrict the exposure of the [=member=]. + +An [=interface=] without the [{{CrossOriginIsolated}}] [=extended attribute=] +must not [=interface/inherit=] from another interface +that does specify [{{CrossOriginIsolated}}]. + +
+ + The following [=IDL fragment=] defines an interface with one [=operation=] that is executable + from all contexts, and two which are executable only from cross-origin isolated contexts. + +
+        [Exposed=Window]
+        interface ExampleFeature {
+          // This call will succeed in all contexts.
+          Promise <Result> calculateNotSoSecretResult();
+
+          // This operation will not be exposed to a non-isolated context. In such a context,
+          // there will be no "calculateSecretResult" property on ExampleFeature.prototype.
+          [CrossOriginIsolated] Promise<Result> calculateSecretResult();
+
+          // The same applies here: the attribute will not be exposed to a non-isolated context,
+          // and in such a context there will be no "secretBoolean" property on
+          // ExampleFeature.prototype.
+          [CrossOriginIsolated] readonly attribute boolean secretBoolean;
+        };
+
+        // HighResolutionTimer will not be exposed in a non-isolated context, nor will its members.
+        // In such a context, there will be no "HighResolutionTimer" property on Window.
+        [Exposed=Window, CrossOriginIsolated]
+        interface HighResolutionTimer {
+          DOMHighResTimeStamp getHighResolutionTime();
+        };
+
+        // The interface mixin members defined below will never be exposed in a non-isolated
+        // context, regardless of whether the interface that includes them is. That is, in
+        // non-isolated context, there will be no "snap" property on ExampleFeature.prototype.
+        [CrossOriginIsolated]
+        interface mixin Snapshotable {
+          Promise<boolean> snap();
+        };
+        ExampleFeature includes Snapshotable;
+
+        // On the other hand, the following interface mixin members will be exposed to a
+        // non-isolated context when included by a host interface that doesn't have the
+        // [CrossOriginIsolated] extended attribute. That is, in a non-isolated context, there will
+        // be a "log" property on ExampleFeature.prototype.
+        interface mixin Loggable {
+          Promise<boolean> log();
+        };
+        ExampleFeature includes Loggable;
+    
+
+ + +

[Default]

+ +If the [{{Default}}] [=extended attribute=] appears on a [=regular operation=], then it indicates +that the appropriate [=default method steps=] must be carried out when the operation is invoked. + +The [{{Default}}] extended attribute must +[=takes no arguments|take no arguments=]. + +The [{{Default}}] extended attribute must not be used on anything other than a [=regular operation=] +that [=has default method steps=] defined. + +
+ + As an example, the [{{Default}}] extended attribute is suitable + for use on toJSON [=regular operations=]: + +
+        [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;
+        };
+
+    
+ + In the JavaScript language binding, there would exist a toJSON() method on + Animal, Human, + and (via inheritance) Dog objects: + +
+        // Get an instance of Human.
+        var alice = getHuman();
+
+        // Evaluates to an object like this (notice how "pet" still holds
+        // an instance of Dog at this point):
+        //
+        // {
+        //   name: "Alice",
+        //   age: 59,
+        //   pet: Dog
+        // }
+        alice.toJSON();
+
+        // Evaluates to an object like this (notice how "breed" is absent,
+        // as the Dog interface doesn't use the default toJSON steps):
+        //
+        // {
+        //   name: "Tramp",
+        //   age: 6
+        // }
+        alice.pet.toJSON();
+
+        // Evaluates to a string like this:
+        // '{"name":"Alice","age":59,"pet":{"name":"Tramp","age":6}}'
+        JSON.stringify(alice);
+    
+
+ + +

[EnforceRange]

+ +If the [{{EnforceRange}}] [=extended attribute=] appears on one of the [=integer types=], it creates +a new IDL type such that that when a JavaScript Number is converted to the IDL +type, out-of-range values will cause an exception to be thrown, rather than being converted to a +valid value using using the operators that use a modulo operation (ToInt32, ToUint32, etc.). +The Number will be rounded toward zero before being checked against its range. + +The [{{EnforceRange}}] +extended attribute must +[=takes no arguments|take no arguments=]. + +A type annotated with the [{{EnforceRange}}] extended attribute must not appear in a +[=read only=] attribute. A type must not be [=extended attributes associated with|associated with=] +both the [{{Clamp}}] and [{{EnforceRange}}] extended attributes. A type that is not an +[=integer type=] must not be [=extended attributes associated with|associated with=] the +[{{EnforceRange}}] extended attribute. + +See the rules for converting JavaScript values to the various IDL integer +types in [[#js-type-mapping]] +for the specific requirements that the use of +[{{EnforceRange}}] entails. + +
+ + In the following [=IDL fragment=], + two [=operations=] are declared that + take three {{octet}} arguments; one uses + the [{{EnforceRange}}] [=extended attribute=] + on all three arguments, while the other does not: + +
+        [Exposed=Window]
+        interface GraphicsContext {
+          undefined setColor(octet red, octet green, octet blue);
+          undefined setColorEnforcedRange([EnforceRange] octet red, [EnforceRange] octet green, [EnforceRange] octet blue);
+        };
+    
+ + In a JavaScript implementation of the IDL, a call to setColorEnforcedRange with + Number values that are out of range for an + {{octet}} will result in an exception being + thrown. + +
+        // Get an instance of GraphicsContext.
+        var context = getGraphicsContext();
+
+        // Calling the non-[EnforceRange] version uses ToUint8 to coerce the Numbers to octets.
+        // This is equivalent to calling setColor(255, 255, 1).
+        context.setColor(-1, 255, 257);
+
+        // When setColorEnforcedRange is called, Numbers are rounded towards zero.
+        // This is equivalent to calling setColor(0, 255, 255).
+        context.setColorEnforcedRange(-0.9, 255, 255.2);
+
+        // The following will cause a TypeError to be thrown, since even after
+        // rounding the first and third argument values are out of range.
+        context.setColorEnforcedRange(-1, 255, 256);
+    
+
+ + +

[Exposed]

+ +When the [{{Exposed}}] [=extended attribute=] appears on +an [=interface=], +[=partial interface=], +[=interface mixin=], +[=partial interface mixin=], +[=callback interface=], +[=namespace=], +[=partial namespace=], or +an individual [=interface member=], +[=interface mixin member=], or +[=namespace member=], +it indicates that the construct is exposed +on that particular set of global interfaces. + +The [{{Exposed}}] [=extended attribute=] must either +[=takes an identifier|take an identifier=], +[=takes an identifier list|take an identifier list=] or +[=takes a wildcard|take a wildcard=]. +Each of the identifiers mentioned must be a [=global name=] of some [=interface=] and be unique. + +The own exposure set is either a [=/set=] of identifiers or the special value +*, defined as follows: + +
+ : If the [{{Exposed}}] [=extended attribute=] [=takes an identifier=] |I| + :: The [=own exposure set=] is the [=/set=] « |I| ». + : If the [{{Exposed}}] [=extended attribute=] [=takes an identifier list=] |I| + :: The [=own exposure set=] is the [=/set=] |I|. + : If the [{{Exposed}}] [=extended attribute=] [=takes a wildcard=] + :: The [=own exposure set=] is *. +
+ +

+ [Exposed=*] is to be used with care. + It is only appropriate when an API does not expose significant new capabilities. + If the API might be restricted or disabled in some environments, + it is preferred to list the globals explicitly. +

+ +
+ +The exposure set intersection of a construct |C| and interface-or-null |H| is defined as +follows: + +1. Assert: |C| is an [=interface member=], [=interface mixin member=], [=namespace member=], + [=partial interface=], [=partial interface mixin=], [=partial namespace=], or + [=interface mixin=]. +1. Assert: |H| is an [=interface=] or null. +1. If |H| is null, return |C|'s [=own exposure set=]. +1. If |C|'s [=own exposure set=] is *, return |H|'s [=exposure set=]. +1. If |H|'s [=exposure set=] is *, return |C|'s [=own exposure set=]. +1. Return the [=set/intersection=] of |C|'s [=own exposure set=] and |H|'s + [=exposure set=]. + +
+ +
+ To get the exposure set of a construct |C|, + run the following steps: + + 1. Assert: |C| is an [=interface=], [=callback interface=], [=namespace=], + [=interface member=], [=interface mixin member=], or [=namespace member=]. + 1. Let |H| be |C|'s [=host interface=] if |C| is an [=interface mixin member=], or null otherwise. + 1. If |C| is an [=interface member=], [=interface mixin member=], or [=namespace member=], then: + 1. If the [{{Exposed}}] [=extended attribute=] is specified on |C|, + return the [=exposure set intersection=] of |C| and |H|. + 1. Set |C| to the + [=interface=], [=partial interface=], + [=interface mixin=], [=partial interface mixin=], + [=namespace=], or [=partial namespace=] + |C| is declared on. + 1. If |C| is a [=partial interface=], [=partial interface mixin=], or [=partial namespace=], then: + 1. If the [{{Exposed}}] [=extended attribute=] is specified on |C|, + return the [=exposure set intersection=] of |C| and |H|. + 1. Set |C| to the original [=interface=], [=interface mixin=], or [=namespace=] definition + of |C|. + 1. If |C| is an [=interface mixin=], then: + 1. Assert: |H| is not null. + 1. If the [{{Exposed}}] [=extended attribute=] is specified on |C|, + return the [=exposure set intersection=] of |C| and |H|. + 1. Set |C| to |H|. + 1. Assert: |C| is an [=interface=], [=callback interface=] or [=namespace=]. + 1. Assert: The [{{Exposed}}] [=extended attribute=] is specified on |C|. + 1. Return |C|'s [=own exposure set=]. +
+ +If [{{Exposed}}] appears on an [=overloaded=] [=operation=], +then it must appear identically on all overloads. + +The [{{Exposed}}] extended attribute must not be specified both on +an [=interface member=], [=interface mixin member=], or [=namespace member=], and on +the [=partial interface=], [=partial interface mixin=], or [=partial namespace=] definition +the [=member=] is declared on. + +Note: This is because adding an [{{Exposed}}] [=extended attribute=] on a +[=partial interface=], [=partial interface mixin=], or [=partial namespace=] +is shorthand for annotating each of its [=members=]. + +If [{{Exposed}}] appears on a [=partial interface=] or [=partial namespace=], +then the partial's [=own exposure set=] must be a subset of +the [=exposure set=] of the partial's original [=interface=] or [=namespace=]. + +If [{{Exposed}}] appears on an [=interface member|interface=] or [=namespace member=], +then the [=member=]'s [=exposure set=] must be a subset +of the [=exposure set=] of the [=interface=] or [=namespace=] it is a member of. + +If [{{Exposed}}] appears both on a [=partial interface mixin=] +and its original [=interface mixin=], +then the [=partial interface mixin=]'s [=own exposure set=] +must be a subset of the [=interface mixin=]'s [=own exposure set=]. + +If [{{Exposed}}] appears both on an [=interface mixin member=] +and the [=interface mixin=] it is a member of, +then the [=interface mixin members=]'s [=own exposure set=] +must be a subset of the [=interface mixin=]'s [=own exposure set=]. + +If an interface |X| [=interface/inherits=] from another interface |Y| +then the [=exposure set=] of |X| must be a subset of the [=exposure set=] of |Y|. + +Note: As an [=interface mixin=] can be [=included=] by different [=interfaces=], +the [=exposure set=] of its [=interface mixin member|members=] is a function of +the [=interface=] that [=includes=] them. +If the [=interface mixin member=], [=partial interface mixin=], or [=interface mixin=] +is annotated with an [{{Exposed}}] [=extended attribute=], +then the [=interface mixin member=]'s [=exposure set=] +is the [=set/intersection=] of the relevant construct's [=own exposure set=] +with the [=host interface=]'s [=exposure set=]. +Otherwise, it is the [=host interface=]'s [=exposure set=]. + +
+ An [=interface=], [=callback interface=], [=namespace=], or [=member=] |construct| is + exposed in a given [=realm=] |realm| if the following steps + return true: + + 1. If |construct|'s [=exposure set=] is not *, and |realm|.\[[GlobalObject]] does + not implement an [=interface=] that is in |construct|'s [=exposure set=], then return false. + 1. If |realm|'s [=realm/settings object=] is not a [=secure context=], and |construct| is + [=conditionally exposed=] on [{{SecureContext}}], then return false. + 1. If |realm|'s [=realm/settings object=]'s + [=environment settings object/cross-origin isolated capability=] is false, and |construct| + is [=conditionally exposed=] on [{{CrossOriginIsolated}}], then return false. + 1. Return true. +
+ +
+ An [=interface=], [=callback interface=], [=namespace=], or [=member=] |construct| is + conditionally exposed on a given + [=extended attribute=] |exposure condition| if the following steps return true: + + 1. Assert: |construct| is an [=interface=], [=callback interface=], [=namespace=], + [=interface member=], [=interface mixin member=], or [=namespace member=]. + 1. Let |H| be |construct|'s [=host interface=] if |construct| is an [=interface mixin member=], + or null otherwise. + 1. If |construct| is an [=interface member=], [=interface mixin member=], or + [=namespace member=], then: + 1. If the |exposure condition| [=extended attribute=] is specified on |construct|, + then return true. + 1. Otherwise, set |construct| to be the + [=interface=], [=partial interface=], + [=interface mixin=], [=partial interface mixin=], + [=namespace=], or [=partial namespace=] + |construct| is declared on. + 1. If |construct| is a [=partial interface=], [=partial interface mixin=], or + [=partial namespace=], then: + 1. If the |exposure condition| [=extended attribute=] is specified on |construct|, + then return true. + 1. Otherwise, set |construct| to be the original [=interface=], [=interface mixin=], or + [=namespace=] definition of |construct|. + 1. If |construct| is an [=interface mixin=], then: + 1. If the |exposure condition| [=extended attribute=] is specified on |construct|, + then return true. + 1. Otherwise, set |construct| to |H|. + 1. Assert: |construct| is an [=interface=], [=callback interface=] or [=namespace=]. + 1. If the |exposure condition| [=extended attribute=] is specified on |construct|, + then return true. + 1. Otherwise, return false. +
+ +Note: Since it is not possible for the [=relevant settings object=] +for a JavaScript global object to change whether it is a +[=secure context=] or [=environment settings object/cross-origin isolated capability=] over time, an +implementation's decision to create properties for an interface or interface member can be made +once, at the time the [=initial objects=] are created. + +See +[[#js-interfaces]], +[[#js-constants]], +[[#js-attributes]], +[[#js-operations]], and +for the specific requirements that the use of +[{{Exposed}}] entails. + +
+ + [{{Exposed}}] is intended to be used to control whether [=interfaces=], + [=callback interfaces=], [=namespaces=], or individual [=interface member|interface=], + [=interface mixin member|mixin=] or [=namespace members=] are available for use in workers, + {{Worklet}}, {{Window}}, or any combination of the above. + + The following IDL fragment shows how that might be achieved: + +
+        [Exposed=Window, Global=Window]
+        interface Window {
+          // ...
+        };
+
+        // By using the same identifier Worker for both SharedWorkerGlobalScope
+        // and DedicatedWorkerGlobalScope, both can be addressed in an [Exposed]
+        // extended attribute at once.
+        [Exposed=Worker, Global=Worker]
+        interface SharedWorkerGlobalScope : WorkerGlobalScope {
+          // ...
+        };
+
+        [Exposed=Worker, Global=Worker]
+        interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
+          // ...
+        };
+
+        // Dimensions is available for use in workers and on the main thread.
+        [Exposed=(Window,Worker)]
+        interface Dimensions {
+          constructor(double width, double height);
+          readonly attribute double width;
+          readonly attribute double height;
+        };
+
+        // WorkerNavigator is only available in workers.  Evaluating WorkerNavigator
+        // in the global scope of a worker would give you its interface object, while
+        // doing so on the main thread will give you a ReferenceError.
+        [Exposed=Worker]
+        interface WorkerNavigator {
+          // ...
+        };
+
+        // Node is only available on the main thread.  Evaluating Node
+        // in the global scope of a worker would give you a ReferenceError.
+        [Exposed=Window]
+        interface Node {
+          // ...
+        };
+
+        // MathUtils is available for use in workers and on the main thread.
+        [Exposed=(Window,Worker)]
+        namespace MathUtils {
+          double someComplicatedFunction(double x, double y);
+        };
+
+        // WorkerUtils is only available in workers.  Evaluating WorkerUtils
+        // in the global scope of a worker would give you its namespace object, while
+        // doing so on the main thread will give you a ReferenceError.
+        [Exposed=Worker]
+        namespace WorkerUtils {
+          undefined setPriority(double x);
+        };
+
+        // NodeUtils is only available in the main thread.  Evaluating NodeUtils
+        // in the global scope of a worker would give you a ReferenceError.
+        [Exposed=Window]
+        namespace NodeUtils {
+          DOMString getAllText(Node node);
+        };
+    
+
+ + +

[Global]

+ +If the [{{Global}}] [=extended attribute=] appears on an [=interface=], +it indicates that objects implementing this interface will +be used as the global object in a [=realm=]. + +The [{{Global}}] [=extended attribute=] also defines the +global names for the [=interface=]: + +
+ : If the [{{Global}}] [=extended attribute=] [=takes an identifier=] + :: « the given [=identifier=] » + : If the [{{Global}}] [=extended attribute=] [=takes an identifier list=] + :: the identifier list +
+ +The [{{Global}}] extended attribute must be one of the forms given above. + +Note: The [=global names=] for the [=interface=] are the [=identifiers=] that can be used to +reference it in the [{{Exposed}}] [=extended attribute=]. +A single name can be shared across multiple different global interfaces, +allowing an interface to more easily use [{{Exposed}}] to expose itself to all of them at once. +For example, "Worker" is used to refer to several distinct types of threading-related +global interfaces. + +For these global [=interfaces=], the structure of the prototype chain and how properties +corresponding to [=interface members=] will be reflected on the prototype objects will be different +from other interfaces. Specifically: + +1. Any [=named properties=] + will be exposed on an object in the prototype chain – the + [=named properties object=] – + rather than on the object itself. +1. [=Interface members=] from the + [=interface=] + will correspond to properties on the object itself rather than on + [=interface prototype objects=]. + +All [=realms=] have an is global prototype chain mutable boolean, +which can be set when the [=realm=] is created. +Its value can not change during the lifetime of the [=realm=]. +By default it is set to false. + +

This allows the ShadowRealm global to have a mutable prototype.

+ +
+ + Placing named properties on an object in the prototype chain + is done so that variable declarations and bareword assignments + will shadow the named property with a property on the global + object itself. + + Placing properties corresponding to interface members on + the object itself will mean that common feature detection + methods like the following will work: + +
+        var indexedDB = window.indexedDB || window.webkitIndexedDB ||
+                        window.mozIndexedDB || window.msIndexedDB;
+
+        var requestAnimationFrame = window.requestAnimationFrame ||
+                                    window.mozRequestAnimationFrame || ...;
+    
+ + Because of the way variable declarations are handled in + JavaScript, the code above would result in the window.indexedDB + and window.requestAnimationFrame evaluating + to undefined, as the shadowing variable + property would already have been created before the + assignment is evaluated. + +
+ +If the [{{Global}}] [=extended attributes=] is +used on an [=interface=], then: + +* The interface must not define a [=named property setter=]. +* The interface must not define [=indexed property getters=] or [=indexed property setter|setters=]. +* The interface must not define a [=constructor operation=]. +* The interface must not also be declared with the [{{LegacyOverrideBuiltIns}}] + extended attribute. +* The interface must not [=interface/inherit=] from another interface with the + [{{LegacyOverrideBuiltIns}}] extended attribute. +* Any other interface must not [=interface/inherit=] from it. + +If [{{Global}}] is specified on +a [=partial interface=] +definition, then that partial interface definition must +be the part of the interface definition that defines +the [=named property getter=]. + +The [{{Global}}] [=extended attribute=] must not +be used on an [=interface=] that can have more +than one object implementing it in the same [=realm=]. + +Note: This is because the [=named properties object=], +which exposes the named properties, is in the prototype chain, and it would not make +sense for more than one object's named properties to be exposed on an object that +all of those objects inherit from. + +If an interface is declared with the [{{Global}}] [=extended attribute=], then +there must not be more than one +[=member=] across +the interface +with the same [=identifier=]. +There also must not be more than +one [=stringifier=] +or more than one [=iterable declaration=], +[=asynchronously iterable declaration=], +[=maplike declaration=] or +[=setlike declaration=] +across those interfaces. + +Note: This is because all of the [=members=] of the interface +get flattened down on to the object that [=implements=] the interface. + +See [[#named-properties-object]] for the specific requirements +that the use of [{{Global}}] entails for [=named properties=], +and [[#js-constants]], [[#js-attributes]] and [[#js-operations]] +for the requirements relating to the location of properties +corresponding to [=interface members=]. + +
+ + The Window interface exposes frames as properties on the Window + object. Since the Window object also serves as the + JavaScript global object, variable declarations or assignments to the named properties + will result in them being replaced by the new value. Variable declarations for + attributes will not create a property that replaces the existing one. + +
+        [Exposed=Window, Global=Window]
+        interface Window {
+          getter any (DOMString name);
+          attribute DOMString name;
+          // ...
+        };
+    
+ + The following HTML document illustrates how the named properties on the + Window object can be shadowed, and how + the property for an attribute will not be replaced when declaring + a variable of the same name: + +
+        <!DOCTYPE html>
+        <title>Variable declarations and assignments on Window</title>
+        <iframe name=abc></iframe>
+        <!-- Shadowing named properties -->
+        <script>
+          window.abc;    // Evaluates to the iframe's Window object.
+          abc = 1;       // Shadows the named property.
+          window.abc;    // Evaluates to 1.
+        </script>
+
+        <!-- Preserving properties for IDL attributes -->
+        <script>
+          Window.prototype.def = 2;         // Places a property on the prototype.
+          window.hasOwnProperty("length");  // Evaluates to true.
+          length;                           // Evaluates to 1.
+          def;                              // Evaluates to 2.
+        </script>
+        <script>
+          var length;                       // Variable declaration leaves existing property.
+          length;                           // Evaluates to 1.
+          var def;                          // Variable declaration creates shadowing property.
+          def;                              // Evaluates to undefined.
+        </script>
+    
+
+ + +

[NewObject]

+ +If the [{{NewObject}}] +[=extended attribute=] +appears on a [=regular operation|regular=] +or [=static operations|static=] +[=operation=], +then it indicates that when calling the operation, +a reference to a newly created object +must always be returned. + +The [{{NewObject}}] +extended attribute must +[=takes no arguments|take no arguments=]. + +The [{{NewObject}}] +extended attribute must not +be used on anything other than a [=regular operation|regular=] +or [=static operations|static=] +[=operation=] +whose [=return type=] +is an [=interface type=] or +a [=promise type=]. + +
+ + As an example, this extended attribute is suitable for use on + the {{Document/createElement()}} operation on the {{Document}} interface, + since a new object is always returned when + it is called. [[DOM]] + +
+        [Exposed=Window]
+        interface Document : Node {
+          [NewObject] Element createElement(DOMString localName);
+          // ...
+        };
+    
+
+ + +

[PutForwards]

+ +If the [{{PutForwards}}] +[=extended attribute=] +appears on a [=read only=] +[=regular attribute=] declaration whose type is +an [=interface type=], +it indicates that assigning to the attribute will have specific behavior. +Namely, the assignment is “forwarded” to the attribute (specified by +the extended attribute argument) on the object that is currently +referenced by the attribute being assigned to. + +The [{{PutForwards}}] extended +attribute must [=takes an identifier|take an identifier=]. +Assuming that: + +* |A| is the [=attribute=] + on which the [{{PutForwards}}] + extended attribute appears, +* |I| is the [=interface=] + on which |A| is declared, +* |J| is the [=interface type=] + that |A| is declared to be of, and +* |N| is the [=identifier=] + argument of the extended attribute, + +then there must be another +[=attribute=] |B| +declared on |J| whose [=identifier=] +is |N|. Assignment of a value to the attribute |A| +on an object implementing |I| will result in that value +being assigned to attribute |B| of the object that |A| +references, instead. + +Note that [{{PutForwards}}]-annotated +[=attributes=] can be +chained. That is, an attribute with the [{{PutForwards}}] +[=extended attribute=] +can refer to an attribute that itself has that extended attribute. +There must not exist a cycle in a +chain of forwarded assignments. A cycle exists if, when following +the chain of forwarded assignments, a particular attribute on +an [=interface=] is +encountered more than once. + +An attribute with the [{{PutForwards}}] +extended attribute must not also be declared +with the [{{LegacyLenientSetter}}] or +[{{Replaceable}}] extended attributes. + +The [{{PutForwards}}] +extended attribute must not be used +on an [=attribute=] that +is not [=read only=]. + +The [{{PutForwards}}] extended attribute +must not be used on a +[=static attribute=]. + +The [{{PutForwards}}] extended attribute +must not be used on an attribute declared on +a [=namespace=]. + +See the Attributes section for how +[{{PutForwards}}] +is to be implemented. + +
+ + The following [=IDL fragment=] defines interfaces for names and people. + The [{{PutForwards}}] extended + attribute is used on the name attribute + of the Person interface to indicate + that assignments to that attribute result in assignments to the + full attribute of the + Person object: + +
+        [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;
+        };
+    
+ + In the JavaScript binding, this would allow assignments to the + name property: + +
+        var p = getPerson();           // Obtain an instance of Person.
+
+        p.name = 'John Citizen';       // This statement...
+        p.name.full = 'John Citizen';  // ...has the same behavior as this one.
+    
+
+ + +

[Replaceable]

+ +If the [{{Replaceable}}] +[=extended attribute=] +appears on a [=read only=] +[=regular attribute=], +it indicates that setting the corresponding property on the +[=platform object=] will result in +an own property with the same name being created on the object +which has the value being assigned. This property will shadow +the accessor property corresponding to the attribute, which +exists on the [=interface prototype object=]. + +The [{{Replaceable}}] +extended attribute must +[=takes no arguments|take no arguments=]. + +An attribute with the [{{Replaceable}}] +extended attribute must not also be declared +with the [{{LegacyLenientSetter}}] or +[{{PutForwards}}] extended attributes. + +The [{{Replaceable}}] +extended attribute must not be used +on an [=attribute=] that +is not [=read only=]. + +The [{{Replaceable}}] extended attribute +must not be used on a +[=static attribute=]. + +The [{{Replaceable}}] extended attribute +must not be used on an attribute declared on +a [=namespace=]. + +See [[#js-attributes]] +for the specific requirements that the use of +[{{Replaceable}}] entails. + +
+ + The following [=IDL fragment=] + defines an [=interface=] + with an [=operation=] + that increments a counter, and an [=attribute=] + that exposes the counter's value, which is initially 0: + +
+        [Exposed=Window]
+        interface Counter {
+          [Replaceable] readonly attribute unsigned long value;
+          undefined increment();
+        };
+    
+ + Assigning to the value property + on a [=platform object=] implementing Counter + will shadow the property that corresponds to the + [=attribute=]: + +
+        var counter = getCounter();                              // Obtain an instance of Counter.
+        counter.value;                                           // Evaluates to 0.
+
+        counter.hasOwnProperty("value");                         // Evaluates to false.
+        Object.getPrototypeOf(counter).hasOwnProperty("value");  // Evaluates to true.
+
+        counter.increment();
+        counter.increment();
+        counter.value;                                           // Evaluates to 2.
+
+        counter.value = 'a';                                     // Shadows the property with one that is unrelated
+                                                                 // to Counter::value.
+
+        counter.hasOwnProperty("value");                         // Evaluates to true.
+
+        counter.increment();
+        counter.value;                                           // Evaluates to 'a'.
+
+        delete counter.value;                                    // Reveals the original property.
+        counter.value;                                           // Evaluates to 3.
+    
+
+ + +

[SameObject]

+ +If the [{{SameObject}}] +[=extended attribute=] +appears on a [=read only=] +[=attribute=], then it +indicates that when getting the value of the attribute on a given +object, the same value must always +be returned. + +The [{{SameObject}}] +extended attribute must +[=takes no arguments|take no arguments=]. + +The [{{SameObject}}] +extended attribute must not +be used on anything other than a [=read only=] +[=attribute=] +whose type is an [=interface type=] +or {{object}}. + +
+ + As an example, this extended attribute is suitable for use on + the {{Document/implementation}} attribute on the {{Document}} interface + since the same object is always returned for a given + {{Document}} object. [[DOM]] + +
+        [Exposed=Window]
+        interface Document : Node {
+          [SameObject] readonly attribute DOMImplementation implementation;
+          // ...
+        };
+    
+
+ + +

[SecureContext]

+ +If the [{{SecureContext}}] [=extended attribute=] appears on an +[=interface=], +[=partial interface=], +[=interface mixin=], +[=partial interface mixin=], +[=callback interface=], +[=namespace=], +[=partial namespace=], +[=interface member=], +[=interface mixin member=], or +[=namespace member=], +it indicates that the construct is [=exposed=] +only within a [=secure context=]. +The [{{SecureContext}}] extended attribute must not be used +on any other construct. + +The [{{SecureContext}}] extended attribute must [=takes no arguments|take no arguments=]. + +If [{{SecureContext}}] appears on an [=overloaded=] [=operation=], +then it must appear on all overloads. + +The [{{SecureContext}}] [=extended attribute=] must not be specified both on + +* an [=interface member=] and its [=interface=] or [=partial interface=]; +* an [=interface mixin member=] and its [=interface mixin=] or [=partial interface mixin=]; +* a [=namespace member=] and its [=namespace=] or [=partial namespace=]. + +Note: This is because adding the [{{SecureContext}}] [=extended attribute=] on a [=member=] when +its containing definition is also annotated with the [{{SecureContext}}] [=extended attribute=] +does not further restrict the exposure of the [=member=]. + +An [=interface=] without the [{{SecureContext}}] [=extended attribute=] +must not [=interface/inherit=] from another interface +that does specify [{{SecureContext}}]. + +[{{SecureContext}}] must not be specified on a construct is that is [=conditionally exposed=] on +[{{CrossOriginIsolated}}]. (Doing so would be redundant, since every environment which is +[=environment settings object/cross-origin isolated capability|cross-origin isolated=] is also a +[=secure context=].) + +
+ + The following [=IDL fragment=] defines an interface + with one [=operation=] that is executable from all + contexts, and two which are executable only from secure contexts. + +
+        [Exposed=Window]
+        interface ExampleFeature {
+          // This call will succeed in all contexts.
+          Promise <Result> calculateNotSoSecretResult();
+
+          // This operation will not be exposed to a non-secure context. In such a context,
+          // there will be no "calculateSecretResult" property on ExampleFeature.prototype.
+          [SecureContext] Promise<Result> calculateSecretResult();
+
+          // The same applies here: the attribute will not be exposed to a non-secure context,
+          // and in a non-secure context there will be no "secretBoolean" property on
+          // ExampleFeature.prototype.
+          [SecureContext] readonly attribute boolean secretBoolean;
+        };
+
+        // HeartbeatSensor will not be exposed in a non-secure context, nor will its members.
+        // In such a context, there will be no "HeartbeatSensor" property on Window.
+        [Exposed=Window, SecureContext]
+        interface HeartbeatSensor {
+          Promise<float> getHeartbeatsPerMinute();
+        };
+
+        // The interface mixin members defined below will never be exposed in a non-secure context,
+        // regardless of whether the interface that includes them is. That is, in a non-secure
+        // context, there will be no "snap" property on ExampleFeature.prototype.
+        [SecureContext]
+        interface mixin Snapshotable {
+          Promise<boolean> snap();
+        };
+        ExampleFeature includes Snapshotable;
+
+        // On the other hand, the following interface mixin members will be exposed to a non-secure
+        // context when included by a host interface that doesn't have the [SecureContext] extended
+        // attribute. That is, in a non-secure context, there will be a "log" property on
+        // ExampleFeature.prototype.
+        interface mixin Loggable {
+          Promise<boolean> log();
+        };
+        ExampleFeature includes Loggable;
+    
+
+ + +

[Unscopable]

+ +If the [{{Unscopable}}] +[=extended attribute=] +appears on a [=regular attribute=] +or [=regular operation=], it +indicates that an object that [=implements=] an interface with the given +interface member will not include its property name in any object +environment record with it as its base object. The result of this is +that bare identifiers matching the property name will not resolve to +the property in a with statement. This is achieved by +including the property name on the +[=interface prototype object=]'s +{{%Symbol.unscopables%}} property's value. + +The [{{Unscopable}}] +extended attribute must +[=takes no arguments|take no arguments=]. + +The [{{Unscopable}}] +extended attribute must not appear on +anything other than a [=regular attribute=] +or [=regular operation=]. + +The [{{Unscopable}}] extended attribute must not be used on an attribute declared on a +[=namespace=]. + +See [[#interface-prototype-object]] +for the specific requirements that the use of +[{{Unscopable}}] entails. + +
+ + For example, with the following IDL: + +
+        [Exposed=Window]
+        interface Thing {
+          undefined f();
+          [Unscopable] g();
+        };
+    
+ + the f property can be referenced with a bare identifier + in a with statement but the g property cannot: + +
+        var thing = getThing();  // An instance of Thing
+        with (thing) {
+          f;                     // Evaluates to a Function object.
+          g;                     // Throws a ReferenceError.
+        }
+    
+
+ + +

Legacy extended attributes

+ +This section defines a number of [=extended attributes=] whose presence affects the JavaScript +binding. Unlike those in [[#js-extended-attributes]], these exist only so that legacy Web platform +features can be specified. They should not be used in specifications, unless required to specify the +behavior of legacy APIs. + +Editors who believe they have a good reason for using these extended attributes are strongly advised +to discuss this by +filing an issue +before proceeding. + + +

[LegacyFactoryFunction]

+ +

Instead of using this feature, give your interface a [=constructor operation=].

+ +If the [{{LegacyFactoryFunction}}] +[=extended attribute=] +appears on an [=interface=], +it indicates that the JavaScript global object will have a property with the +specified name whose value is a function that can +create objects that implement the interface. +Multiple [{{LegacyFactoryFunction}}] extended +attributes may appear on a given interface. + +The [{{LegacyFactoryFunction}}] extended attribute must +[=takes a named argument list|take a named argument list=]. +The identifier that occurs directly after the +“=” is the [{{LegacyFactoryFunction}}]'s identifier. +For each [{{LegacyFactoryFunction}}] extended attribute on the interface, +there will be a way to construct an object that +[=implements=] the interface by passing the specified arguments to the [=constructor=] +that is the value of the aforementioned property. + +The [=LegacyFactoryFunction identifier|identifier=] used for the legacy factory function must not +be the same as that used by a [{{LegacyFactoryFunction}}] +extended attribute on another interface, must not +be the same as an [=LegacyWindowAlias identifier|identifier=] used by a [{{LegacyWindowAlias}}] +extended attribute on this interface or another interface, +must not be the same as an [=identifier=] of an interface +that has an [=interface object=], +and must not be one of the +[=reserved identifiers=]. + +The [{{LegacyFactoryFunction}}] and [{{Global}}] [=extended attributes=] must not be specified on the +same [=interface=]. + +See [[#legacy-factory-functions]] for details on how legacy factory functions +are to be implemented. + +
+ + The following IDL defines an interface that uses the + [{{LegacyFactoryFunction}}] extended + attribute. + +
+        [Exposed=Window,
+         LegacyFactoryFunction=Audio(DOMString src)]
+        interface HTMLAudioElement : HTMLMediaElement {
+          // ...
+        };
+    
+ + A JavaScript implementation that supports this interface will + allow the construction of HTMLAudioElement + objects using the Audio function. + +
+        typeof Audio;                   // Evaluates to 'function'.
+
+        var a2 = new Audio('a.flac');   // Creates an HTMLAudioElement using the
+                                        // one-argument constructor.
+    
+ + As an additional legacy quirk, these factory functions will have a prototype + property equal to the prototype of the original interface: + +
+        console.assert(Audio.prototype === HTMLAudioElement.prototype);
+    
+
+ + +

[LegacyLenientSetter]

+ +If the [{{LegacyLenientSetter}}] +[=extended attribute=] +appears on a [=read only=] +[=regular attribute=], +it indicates that a no-op setter will be generated for the attribute's +accessor property. This results in erroneous assignments to the property +in strict mode to be ignored rather than causing an exception to be thrown. + +

Pages have been observed where authors have attempted to polyfill an IDL attribute +by assigning to the property, but have accidentally done so even if the property exists. In strict +mode, this would cause an exception to be thrown, potentially breaking page. Without +[{{LegacyLenientSetter}}], this could prevent a browser from shipping the feature.

+ +The [{{LegacyLenientSetter}}] extended attribute +must [=takes no arguments|take no arguments=]. +It must not be used on anything other than +a [=read only=] [=regular attribute=]. + +An attribute with the [{{LegacyLenientSetter}}] +extended attribute must not also be declared +with the [{{PutForwards}}] +or [{{Replaceable}}] extended attributes. + +The [{{LegacyLenientSetter}}] extended attribute must not be used on an attribute declared on a +[=namespace=]. + +See the Attributes section for how +[{{LegacyLenientSetter}}] is to be implemented. + +
+ + The following IDL fragment defines an interface that uses the + [{{LegacyLenientSetter}}] extended + attribute. + +
+        [Exposed=Window]
+        interface Example {
+          [LegacyLenientSetter] readonly attribute DOMString x;
+          readonly attribute DOMString y;
+        };
+    
+ + A JavaScript implementation that supports this interface will + have a setter on the accessor property that correspond to x, + which allows any assignment to be ignored in strict mode. + +
+        "use strict";
+
+        var example = getExample();  // Get an instance of Example.
+
+        // Fine; while we are in strict mode, there is a setter that is a no-op.
+        example.x = 1;
+
+        // Throws a TypeError, since we are in strict mode and there is no setter.
+        example.y = 1;
+    
+
+ + +

[LegacyLenientThis]

+ +If the [{{LegacyLenientThis}}] +[=extended attribute=] +appears on a [=regular attribute=], +it indicates that invocations of the attribute's getter or setter +with a this value that is not an +object that [=implements=] the [=interface=] +on which the attribute appears will be ignored. + +The [{{LegacyLenientThis}}] extended attribute +must +[=takes no arguments|take no arguments=]. +It must not be used on a +[=static attribute=]. + +The [{{LegacyLenientThis}}] extended attribute must not be used on an attribute declared on a +[=namespace=]. + +See the Attributes section for how +[{{LegacyLenientThis}}] +is to be implemented. + +
+ + The following IDL fragment defines an interface that uses the + [{{LegacyLenientThis}}] extended + attribute. + +
+        [Exposed=Window]
+        interface Example {
+          [LegacyLenientThis] attribute DOMString x;
+          attribute DOMString y;
+        };
+    
+ + A JavaScript implementation that supports this interface will + allow the getter and setter of the accessor property that corresponds + to x to be invoked with something other than an Example + object. + +
+        var example = getExample();  // Get an instance of Example.
+        var obj = { };
+
+        // Fine.
+        example.x;
+
+        // Ignored, since the this value is not an Example object and [LegacyLenientThis] is used.
+        Object.getOwnPropertyDescriptor(Example.prototype, "x").get.call(obj);
+
+        // Also ignored, since Example.prototype is not an Example object and [LegacyLenientThis] is used.
+        Example.prototype.x;
+
+        // Throws a TypeError, since Example.prototype is not an Example object.
+        Example.prototype.y;
+    
+
+ + +

[LegacyNamespace]

+ +

Instead of using this feature, interface names can be formed with a naming +convention of starting with a particular prefix for a set of interfaces, as part of the identifier, +without the intervening dot.

+ +If the [{{LegacyNamespace}}] [=extended attribute=] appears on an [=interface=], it indicates that +the [=interface object=] for this interface will not be created as a property of the global +object, but rather as a property of the [=namespace=] identified by the argument to the extended +attribute. + +The [{{LegacyNamespace}}] extended attribute must [=take an identifier=]. +This identifier must be the [=identifier=] of a [=namespace=] definition. + +The [{{LegacyNamespace}}] and [{{LegacyNoInterfaceObject}}] +extended attributes must not be specified on the same interface. + +See [[#namespace-object]] for details on how an interface is exposed on a namespace. + +
+ The following [=IDL fragment=] defines a [=namespace=] and an [=interface=] which + uses [{{LegacyNamespace}}] to be defined inside of it. + +
+        namespace Foo { };
+
+        [LegacyNamespace=Foo]
+        interface Bar {
+          constructor();
+        };
+    
+ + In a JavaScript implementation of the above namespace and interface, the + constructor Bar can be accessed as follows: + +
+        var instance = new Foo.Bar();
+    
+
+ + +

[LegacyNoInterfaceObject]

+ +If the [{{LegacyNoInterfaceObject}}] [=extended attribute=] appears on an [=interface=], +it indicates that an [=interface object=] +will not exist for the interface in the JavaScript binding. + +The [{{LegacyNoInterfaceObject}}] extended attribute +must [=takes no arguments|take no arguments=]. + +The [{{LegacyNoInterfaceObject}}] extended attribute +must not be specified on an interface that has any +[=constructors=] or [=static operations=] defined on it. + +An interface that does not have the [{{LegacyNoInterfaceObject}}] extended +attribute specified must not inherit +from an interface that has the [{{LegacyNoInterfaceObject}}] extended +attribute specified. + +See [[#js-interfaces]] +for the specific requirements that the use of +[{{LegacyNoInterfaceObject}}] entails. + +
+ + The following [=IDL fragment=] defines two interfaces, one whose interface object + is exposed on the JavaScript global object, and one whose isn't: + +
+        [Exposed=Window]
+        interface Storage {
+          undefined addEntry(unsigned long key, any value);
+        };
+
+        [Exposed=Window,
+         LegacyNoInterfaceObject]
+        interface Query {
+          any lookupEntry(unsigned long key);
+        };
+    
+ + A JavaScript implementation of the above IDL would allow + manipulation of Storage's + prototype, but not Query's. + +
+        typeof Storage;                        // evaluates to "object"
+
+        // Add some tracing alert() call to Storage.addEntry.
+        var fn = Storage.prototype.addEntry;
+        Storage.prototype.addEntry = function(key, value) {
+          alert('Calling addEntry()');
+          return fn.call(this, key, value);
+        };
+
+        typeof Query;                          // evaluates to "undefined"
+        var fn = Query.prototype.lookupEntry;  // exception, Query isn't defined
+    
+
+ + +

[LegacyNullToEmptyString]

+ +If the [{{LegacyNullToEmptyString}}] [=extended attribute=] appears on the {{DOMString}} or {{USVString}} type, +it creates a new IDL type such that that when a JavaScript null is converted to the IDL type, +it will be handled differently from its default handling. Instead of being stringified to +"null", which is the default, it will be converted to the empty string. + +The [{{LegacyNullToEmptyString}}] extended attribute must not be +[=extended attribute associated with|associated with=] a type that is not {{DOMString}} or {{USVString}}. + +Note: This means that even DOMString? must not use [{{LegacyNullToEmptyString}}], since +null is a valid value of that type. + +See [[#js-DOMString]] for the specific requirements that the use of [{{LegacyNullToEmptyString}}] entails. + +
+ The following [=IDL fragment=] defines an interface that has one attribute whose type has the + extended attribute, and one operation whose argument's type has the extended attribute: + +
+        [Exposed=Window]
+        interface Dog {
+          attribute DOMString name;
+          attribute [LegacyNullToEmptyString] DOMString owner;
+
+          boolean isMemberOfBreed([LegacyNullToEmptyString] DOMString breedName);
+        };
+    
+ + A JavaScript implementation implementing the Dog + interface would convert a null value + assigned to the owner property or passed as the + argument to the isMemberOfBreed function + to the empty string rather than "null": + +
+        var d = getDog();         // Assume d is a platform object implementing the Dog
+                                  // interface.
+
+        d.name = null;            // This assigns the string "null" to the .name
+                                  // property.
+
+        d.owner = null;           // This assigns the string "" to the .owner property.
+
+        d.isMemberOfBreed(null);  // This passes the string "" to the isMemberOfBreed
+                                  // function.
+    
+
+ + +

[LegacyOverrideBuiltIns]

+ +If the [{{LegacyOverrideBuiltIns}}] +[=extended attribute=] +appears on an [=interface=], +it indicates that for a [=legacy platform object=] implementing the interface, +properties corresponding to all of +the object's [=supported property names=] +will appear to be on the object, +regardless of what other properties exist on the object or its +prototype chain. This means that named properties will always shadow +any properties that would otherwise appear on the object. +This is in contrast to the usual behavior, which is for named properties +to be exposed only if there is no property with the +same name on the object itself or somewhere on its prototype chain. + +The [{{LegacyOverrideBuiltIns}}] +extended attribute must +[=takes no arguments|take no arguments=] +and must not appear on an interface +that does not define a [=named property getter=] +or that also is declared with the [{{Global}}] [=extended attribute=]. +If the extended attribute is specified on +a [=partial interface=] +definition, then that partial interface definition must +be the part of the interface definition that defines +the [=named property getter=]. + +If the [{{LegacyOverrideBuiltIns}}] extended attribute is specified on a +[=partial interface=] definition, it is considered to appear on the +[=interface=] itself. + +See [[#js-legacy-platform-objects]] +and [[#legacy-platform-object-defineownproperty]] +for the specific requirements that the use of +[{{LegacyOverrideBuiltIns}}] entails. + +
+ + The following [=IDL fragment=] + defines two [=interfaces=], + one that has a [=named property getter=] + and one that does not. + +
+        [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);
+        };
+    
+ + In a JavaScript implementation of these two interfaces, + getting certain properties on objects implementing + the interfaces will result in different values: + +
+        // Obtain an instance of StringMap.  Assume that it has "abc", "length" and
+        // "toString" as supported property names.
+        var map1 = getStringMap();
+
+        // This invokes the named property getter.
+        map1.abc;
+
+        // This fetches the "length" property on the object that corresponds to the
+        // length attribute.
+        map1.length;
+
+        // This fetches the "toString" property from the object's prototype chain.
+        map1.toString;
+
+        // Obtain an instance of StringMap2.  Assume that it also has "abc", "length"
+        // and "toString" as supported property names.
+        var map2 = getStringMap2();
+
+        // This invokes the named property getter.
+        map2.abc;
+
+        // This also invokes the named property getter, despite the fact that the "length"
+        // property on the object corresponds to the length attribute.
+        map2.length;
+
+        // This too invokes the named property getter, despite the fact that "toString" is
+        // a property in map2's prototype chain.
+        map2.toString;
+    
+
+ + +

[LegacyTreatNonObjectAsNull]

+ +If the [{{LegacyTreatNonObjectAsNull}}] [=extended attribute=] appears on a [=callback function=], then +it indicates that any value assigned to an [=attribute=] whose type is a [=nullable type|nullable=] +[=callback function=] will be converted more loosely: if the value is not an object, it will be +converted to null, and if the value is not [=ECMAScript/callable=], it will be converted to a +[=callback function=] value that does nothing when called. + +See [[#js-nullable-type]], [[#js-callback-function]] and [[#js-invoking-callback-functions]] +for the specific requirements that the use of +[{{LegacyTreatNonObjectAsNull}}] entails. + +
+ + The following [=IDL fragment=] defines an interface that has one + attribute whose type is a [{{LegacyTreatNonObjectAsNull}}]-annotated + [=callback function=] and another whose type is a + [=callback function=] without the [=extended attribute=]: + +
+        callback OccurrenceHandler = undefined (DOMString details);
+
+        [LegacyTreatNonObjectAsNull]
+        callback ErrorHandler = undefined (DOMString details);
+
+        [Exposed=Window]
+        interface Manager {
+          attribute OccurrenceHandler? handler1;
+          attribute ErrorHandler? handler2;
+        };
+    
+ + In a JavaScript implementation, assigning a value that is not + an object (such as a Number value), or that is not [=ECMAScript/callable=] + to handler1 will have different behavior from that when assigning + to handler2: + +
+        var manager = getManager();  // Get an instance of Manager.
+
+        manager.handler1 = function() { };
+        manager.handler1;            // Evaluates to the function.
+
+        try {
+          manager.handler1 = 123;    // Throws a TypeError.
+        } catch (e) {
+        }
+
+        try {
+          manager.handler1 = {};     // Throws a TypeError.
+        } catch (e) {
+        }
+
+        manager.handler2 = function() { };
+        manager.handler2;            // Evaluates to the function.
+
+        manager.handler2 = 123;
+        manager.handler2;            // Evaluates to null.
+
+        manager.handler2 = {};
+        manager.handler2;            // Evaluates to the object.
+    
+
+ + +

[LegacyUnenumerableNamedProperties]

+ +If the [{{LegacyUnenumerableNamedProperties}}] +[=extended attribute=] +appears on a [=interface=] +that [=support named properties|supports named properties=], +it indicates that all the interface's named properties are unenumerable. + +The [{{LegacyUnenumerableNamedProperties}}] +extended attribute must +[=takes no arguments|take no arguments=] +and must not appear on an interface +that does not define a [=named property getter=]. + +If the [{{LegacyUnenumerableNamedProperties}}] +extended attribute is specified on an interface, then it applies to all its derived interfaces and +must not be specified on any of them. + +See [[#legacy-platform-object-getownproperty]] +for the specific requirements that the use of +[{{LegacyUnenumerableNamedProperties}}] +entails. + + +

[LegacyUnforgeable]

+ +If the [{{LegacyUnforgeable}}] [=extended attribute=] appears on +[=regular attributes=] or non-[=static operations|static=] [=operations=], +it indicates that the attribute or operation +will be reflected as a JavaScript property +in a way that means its behavior cannot be modified +and that performing a property lookup on the object +will always result in the attribute's property value being returned. +In particular, the property will be non-configurable +and will exist as an own property on the object itself +rather than on its prototype. + +An attribute or operation is said to be +unforgeable on a given interface |A| +if the attribute or operation is declared on |A|, +and is annotated with the [{{LegacyUnforgeable}}] [=extended attribute=]. + +The [{{LegacyUnforgeable}}] extended attribute must [=takes no arguments|take no arguments=]. + +The [{{LegacyUnforgeable}}] [=extended attribute=] must not appear +on anything other than a [=regular attribute=] +or a non-[=static operations|static=] [=operation=]. +If it does appear on an [=operation=], +then it must appear on all operations +with the same [=identifier=] on that interface. + +The [{{LegacyUnforgeable}}] extended attribute must not be used +on an attribute declared on a [=namespace=]. + +If an attribute or operation |X| is [=unforgeable=] on an interface |A|, +and |A| is one of the [=inherited interfaces=] of another interface |B|, +then |B| must not have a [=regular attribute=] +or non-[=static operations|static=] [=operation=] +with the same [=identifier=] as |X|. + +
+ + For example, the following is disallowed: + +
+        [Exposed=Window]
+        interface A1 {
+          [LegacyUnforgeable] readonly attribute DOMString x;
+        };
+        [Exposed=Window]
+        interface B1 : A1 {
+          undefined x();  // Invalid; would be shadowed by A1's x.
+        };
+
+        [Exposed=Window]
+        interface B2 : A1 { };
+        B2 includes M1;
+        interface mixin M1 {
+          undefined x();  // Invalid; B2's copy of x would be shadowed by A1's x.
+        };
+    
+
+ +See [[#js-attributes]], +[[#js-operations]], +[[#js-platform-objects]], +[[#js-legacy-platform-objects]] and +[[#legacy-platform-object-defineownproperty]] +for the specific requirements that the use of +[{{LegacyUnforgeable}}] entails. + +
+ + The following [=IDL fragment=] defines + an interface that has two [=attributes=], + one of which is designated as [{{LegacyUnforgeable}}]: + +
+        [Exposed=Window]
+        interface System {
+          [LegacyUnforgeable] readonly attribute DOMString username;
+          readonly attribute long long loginTime;
+        };
+    
+ + In a JavaScript implementation of the interface, the username attribute will be exposed as a non-configurable property on the + object itself: + +
+        var system = getSystem();                      // Get an instance of System.
+
+        system.hasOwnProperty("username");             // Evaluates to true.
+        system.hasOwnProperty("loginTime");            // Evaluates to false.
+        System.prototype.hasOwnProperty("username");   // Evaluates to false.
+        System.prototype.hasOwnProperty("loginTime");  // Evaluates to true.
+
+        try {
+          // This call would fail, since the property is non-configurable.
+          Object.defineProperty(system, "username", { value: "administrator" });
+        } catch (e) { }
+
+        // This defineProperty call would succeed, because System.prototype.loginTime
+        // is configurable.
+        var forgedLoginTime = 5;
+        Object.defineProperty(System.prototype, "loginTime", { value: forgedLoginTime });
+
+        system.loginTime;  // So this now evaluates to forgedLoginTime.
+    
+
+ + +

[LegacyWindowAlias]

+ +If the [{{LegacyWindowAlias}}] [=extended attribute=] appears on an [=interface=], +it indicates that the {{Window}} [=interface=] will have a property +for each [=identifier=] mentioned in the extended attribute, +whose value is the [=interface object=] for the interface. + +The [{{LegacyWindowAlias}}] extended attribute must either +[=takes an identifier|take an identifier=] or +[=takes an identifier list|take an identifier list=]. +The identifiers that occur after the +“=” are the [{{LegacyWindowAlias}}]'s identifiers. + +Each of the [=LegacyWindowAlias identifier|identifiers=] of [{{LegacyWindowAlias}}] +must not be the same as one used by a [{{LegacyWindowAlias}}] +extended attribute on this interface or another interface, +must not be the same as the [=LegacyFactoryFunction identifier|identifier=] used by a [{{LegacyFactoryFunction}}] +extended attribute on this interface or another interface, +must not be the same as an [=identifier=] of an interface that has an [=interface object=], +and must not be one of the [=reserved identifiers=]. + +The [{{LegacyWindowAlias}}] and [{{LegacyNoInterfaceObject}}] +extended attributes must not be specified on the same interface. + +The [{{LegacyWindowAlias}}] and [{{LegacyNamespace}}] +extended attributes must not be specified on the same interface. + +The [{{LegacyWindowAlias}}] extended attribute must not be specified +on an interface that does not include the {{Window}} [=interface=] +in its [=exposure set=]. + +An interface must not have more than one [{{LegacyWindowAlias}}] extended attributes specified. + +See [[#js-interfaces]] for details on how legacy window aliases +are to be implemented. + +
+ + The following IDL defines an interface that uses the + [{{LegacyWindowAlias}}] extended attribute. + +
+        [Exposed=Window,
+         LegacyWindowAlias=WebKitCSSMatrix]
+        interface DOMMatrix : DOMMatrixReadOnly {
+          // ...
+        };
+    
+ + A JavaScript implementation that supports this interface will + expose two properties on the {{Window}} object with the same value + and the same characteristics; + one for exposing the [=interface object=] normally, + and one for exposing it with a legacy name. + +
+        WebKitCSSMatrix === DOMMatrix;     // Evaluates to true.
+
+        var m = new WebKitCSSMatrix();     // Creates a new object that
+                                           // implements DOMMatrix.
+
+        m.constructor === DOMMatrix;       // Evaluates to true.
+        m.constructor === WebKitCSSMatrix; // Evaluates to true.
+        {}.toString.call(m);               // Evaluates to '[object DOMMatrix]'.
+    
+
+ + +

Security

+ +Certain algorithms in the sections below are defined to +perform a security check on a given +object. This check is used to determine whether a given +[=operation=] invocation or +[=attribute=] access should be +allowed. The security check takes the following three inputs: + +1. the [=platform object=] on + which the operation invocation or attribute access is being done, +1. the [=identifier=] + of the operation or attribute, and +1. the type of the [=function object=] – + "method" (when it corresponds to an IDL operation), or + "getter" or "setter" (when it corresponds to the + getter or setter function of an IDL attribute). + +Note: The HTML Standard defines how a security check is performed. [[!HTML]] + + +

Overload resolution algorithm

+ +
+ + In order to define how function invocations are resolved, the + overload resolution algorithm + is defined. Its input is an [=effective overload set=], + |S|, and a list of JavaScript values, |args|. + Its output is a pair consisting of the [=operation=] or + [=extended attribute=] of one of |S|'s entries + and a list of IDL values or the special value “missing”. The algorithm behaves as follows: + + 1. Let |maxarg| be the length of the longest type list of the entries in |S|. + 1. Let |n| be the [=list/size=] of |args|. + 1. Initialize |argcount| to be min(|maxarg|, |n|). + 1. Remove from |S| all entries whose type list is not of length |argcount|. + 1. If |S| is empty, then [=JavaScript/throw=] a {{TypeError}}. + 1. Initialize |d| to −1. + 1. Initialize |method| to undefined. + 1. If there is more than one entry in |S|, then set + |d| to be the [=distinguishing argument index=] + for the entries of |S|. + 1. Initialize |values| to be an empty list, where each entry will be either an IDL value or the special value “missing”. + 1. Initialize |i| to 0. + 1. While |i| < |d|: + 1. Let |V| be |args|[|i|]. + 1. Let |type| be the type at index |i| in the type list of any entry in |S|. + + Note: All entries in |S| at this point have the same type and [=optionality value=] at index |i|. + + 1. Let |optionality| be the value at index |i| in the list of [=optionality values=] of any entry in |S|. + 1. If |optionality| is “optional” and |V| is undefined, then: + 1. If the argument at index |i| is declared with a [=optional argument/default value=], + then append to |values| that default value. + 1. Otherwise, append to |values| the special value “missing”. + 1. Otherwise, append to |values| the result of [=converted to an IDL value|converting=] + |V| to IDL type |type|. + 1. Set |i| to |i| + 1. + 1. If |i| = |d|, then: + 1. Let |V| be |args|[|i|]. + + Note: This is the argument that will be used to resolve which overload is selected. + + 1. If |V| is undefined, and there is an entry in |S| + whose list of [=optionality values=] has “optional” at index |i|, + then remove from |S| all other entries. + + 1. Otherwise: if |V| is null or undefined, + and there is an entry in |S| that has one of the following types at position |i| of its type list, + * a [=nullable type=] + * a [=dictionary type=] + * an [=annotated type=] whose [=annotated types/inner type=] is one of the above types + * a [=union type=] or [=annotated type|annotated=] union type that [=includes a nullable type=] or that + has a [=dictionary type=] in its [=flattened member types|flattened members=] + + then remove from |S| all other entries. + + 1. Otherwise: if |V| [=is a platform object=], and + there is an entry in |S| that has one of the following types at position |i| of its type list, + * an [=interface type=] that |V| [=implements=] + * {{object}} + * a [=nullable type|nullable=] version of any of the above types + * an [=annotated type=] whose [=annotated types/inner type=] is one of the above types + * a [=union type=], [=nullable type|nullable=] union type, or [=annotated type|annotated=] union type + that has one of the above types in its [=flattened member types=] + + then remove from |S| all other entries. + + 1. Otherwise: if Type(|V|) is Object, |V| has an \[[ArrayBufferData]] [=/internal slot=], and + there is an entry in |S| that has one of the following types at position |i| of its type list, + * {{ArrayBuffer}} + * {{SharedArrayBuffer}} + * {{object}} + * a [=nullable type|nullable=] version of either of the above types + * an [=annotated type=] whose [=annotated types/inner type=] is one of the above types + * a [=union type=], [=nullable type|nullable=] union type, or [=annotated type|annotated=] union type + that has one of the above types in its [=flattened member types=] + + then remove from |S| all other entries. + + 1. Otherwise: if Type(|V|) is Object, |V| has a \[[DataView]] [=/internal slot=], and + there is an entry in |S| that has one of the following types at position |i| of its type list, + * {{DataView}} + * {{object}} + * a [=nullable type|nullable=] version of either of the above types + * an [=annotated type=] whose [=annotated types/inner type=] is one of the above types + * a [=union type=], [=nullable type|nullable=] union type, or [=annotated type|annotated=] union type + that has one of the above types in its [=flattened member types=] + + then remove from |S| all other entries. + + 1. Otherwise: if Type(|V|) is Object, |V| has a \[[TypedArrayName]] [=/internal slot=], and + there is an entry in |S| that has one of the following types at position |i| of its type list, + * a [=typed array type=] whose name + is equal to the value of |V|'s \[[TypedArrayName]] [=/internal slot=] + * {{object}} + * a [=nullable type|nullable=] version of either of the above types + * an [=annotated type=] whose [=annotated types/inner type=] is one of the above types + * a [=union type=], [=nullable type|nullable=] union type, or [=annotated type|annotated=] union type + that has one of the above types in its [=flattened member types=] + + then remove from |S| all other entries. + + 1. Otherwise: if IsCallable(|V|) is true, + and there is an entry in |S| that has one of the following types at position |i| of its type list, + * a [=callback function=] type + * {{object}} + * a [=nullable type|nullable=] version of any of the above types + * an [=annotated type=] whose [=annotated types/inner type=] is one of the above types + * a [=union type=], [=nullable type|nullable=] union type, or [=annotated type|annotated=] union type + that has one of the above types in its [=flattened member types=] + + then remove from |S| all other entries. + + 1. Otherwise: if Type(|V|) is Object and + there is an entry in |S| that has one of the + following types at position |i| of its type list, + * a [=sequence type=] + * a [=nullable type|nullable=] [=sequence type=] + * an [=annotated type=] whose [=annotated types/inner type=] is a [=sequence type=] + * a [=union type=], [=nullable type|nullable=] union type, or [=annotated type|annotated=] union type + that has a [=sequence type=] in its [=flattened member types=] + + and after performing the following steps, + + 1. Let |method| be [=?=] GetMethod(|V|, {{%Symbol.iterator%}}). + + |method| is not undefined, then remove from |S| all + other entries. + + 1. Otherwise: if Type(|V|) is Object and + there is an entry in |S| that has one of the following types at position |i| of its type list, + * a [=callback interface type=] + * a [=dictionary type=] + * a [=record type=] + * {{object}} + * a [=nullable type|nullable=] version of any of the above types + * an [=annotated type=] whose [=annotated types/inner type=] is one of the above types + * a [=union type=], [=nullable type|nullable=] union type, or [=annotated type|annotated=] union type + that has one of the above types in its [=flattened member types=] + + then remove from |S| all other entries. + + 1. Otherwise: if Type(|V|) is Boolean + and there is an entry in |S| that has one of the following types at position |i| of its type list, + * {{boolean}} + * a [=nullable type|nullable=] {{boolean}} + * an [=annotated type=] whose [=annotated types/inner type=] is one of the above types + * a [=union type=], [=nullable type|nullable=] union type, or [=annotated type|annotated=] union type + that has one of the above types in its [=flattened member types=] + + then remove from |S| all other entries. + + 1. Otherwise: if Type(|V|) is Number + and there is an entry in |S| that has one of the following types at position |i| of its type list, + * a [=numeric type=] + * a [=nullable type|nullable=] [=numeric type=] + * an [=annotated type=] whose [=annotated types/inner type=] is one of the above types + * a [=union type=], [=nullable type|nullable=] union type, or [=annotated type|annotated=] union type + that has one of the above types in its [=flattened member types=] + + then remove from |S| all other entries. + + 1. Otherwise: if Type(|V|) is BigInt + and there is an entry in |S| that has one of the following types at position |i| of its type list, + * {{bigint}} + * a [=nullable type|nullable=] {{bigint}} + * an [=annotated type=] whose [=annotated types/inner type=] is one of the above types + * a [=union type=], [=nullable type|nullable=] union type, or [=annotated type|annotated=] union type + that has one of the above types in its [=flattened member types=] + + then remove from |S| all other entries. + + 1. Otherwise: if there is an entry in |S| that has one of the following types at position |i| of its type list, + * a [=string type=] + * a [=nullable type|nullable=] version of any of the above types + * an [=annotated type=] whose [=annotated types/inner type=] is one of the above types + * a [=union type=], [=nullable type|nullable=] union type, or [=annotated type|annotated=] union type + that has one of the above types in its [=flattened member types=] + + then remove from |S| all other entries. + + 1. Otherwise: if there is an entry in |S| that has one of the following types at position |i| of its type list, + * a [=numeric type=] + * a [=nullable type|nullable=] [=numeric type=] + * an [=annotated type=] whose [=annotated types/inner type=] is one of the above types + * a [=union type=], [=nullable type|nullable=] union type, or [=annotated type|annotated=] union type + that has one of the above types in its [=flattened member types=] + + then remove from |S| all other entries. + + 1. Otherwise: if there is an entry in |S| that has one of the following types at position |i| of its type list, + * {{boolean}} + * a [=nullable type|nullable=] {{boolean}} + * an [=annotated type=] whose [=annotated types/inner type=] is one of the above types + * a [=union type=], [=nullable type|nullable=] union type, or [=annotated type|annotated=] union type + that has one of the above types in its [=flattened member types=] + + then remove from |S| all other entries. + + 1. Otherwise: if there is an entry in |S| that has one of the following types at position |i| of its type list, + * {{bigint}} + * a [=nullable type|nullable=] {{bigint}} + * an [=annotated type=] whose [=annotated types/inner type=] is one of the above types + * a [=union type=], [=nullable type|nullable=] union type, or [=annotated type|annotated=] union type + that has one of the above types in its [=flattened member types=] + + then remove from |S| all other entries. + + 1. Otherwise: if there is an entry in |S| that has {{any}} at position |i| + of its type list, then remove from |S| all other entries. + 1. Otherwise: [=JavaScript/throw=] a {{TypeError}}. + 1. Let |callable| be the [=operation=] or [=extended attribute=] + of the single entry in |S|. + 1. If |i| = |d| and |method| is not undefined, then + 1. Let |V| be |args|[|i|]. + 1. Let |T| be the type at index |i| in the + type list of the remaining entry in |S|. + 1. Assert: |T| is a [=sequence type=]. + 1. Append to |values| the result of + [=creating a sequence from an iterable|creating a sequence=] + of type |T| from |V| and |method|. + 1. Set |i| to |i| + 1. + 1. While |i| < |argcount|: + 1. Let |V| be |args|[|i|]. + 1. Let |type| be the type at index |i| in the type list of the remaining entry in |S|. + 1. Let |optionality| be the value at index |i| in the list of [=optionality values=] of the remaining entry in |S|. + 1. If |optionality| is “optional” and |V| is undefined, then: + 1. If the argument at index |i| is declared with a [=optional argument/default value=], + then append to |values| that default value. + 1. Otherwise, append to |values| the special value “missing”. + 1. Otherwise, append to |values| the result of + [=converted to an IDL value|converting=] |V| to IDL type |type|. + 1. Set |i| to |i| + 1. + 1. While |i| is less than the number of arguments |callable| is declared to take: + 1. If |callable|'s argument at index |i| is declared with a [=optional argument/default value=], + then append to |values| that default value. + 1. Otherwise, if |callable|'s argument at index |i| is not variadic, then append to |values| the special value “missing”. + 1. Set |i| to |i| + 1. + 1. Return the pair <|callable|, |values|>. +
+ +
+ + The overload resolution algorithm performs both the identification + of which overloaded operation, constructor, etc. is being called, + and the conversion of the JavaScript argument values to their + corresponding IDL values. Informally, it operates as follows. + + First, the selection of valid overloads is done by considering + the number of JavaScript arguments that were passed in to the function: + + * If there are more arguments passed in than the longest + overload argument list, then they are ignored. + * After ignoring these trailing arguments, only overloads + that can take this exact number of arguments are considered. + If there are none, then a {{TypeError}} is thrown. + + Once we have a set of possible overloads with the right number + of arguments, the JavaScript values are converted from left to right. + The nature of the restrictions on overloading means that if we + have multiple possible overloads at this point, then there will + be one position in the argument list that will be used to + distinguish which overload we will finally select; this is + the [=distinguishing argument index=]. + + We first convert the arguments to the left of the distinguishing + argument. (There is a requirement that an argument to the left of + the distinguishing argument index has the same type as in the other + overloads, at the same index.) Then we inspect the type of the + JavaScript value that is passed in at the distinguishing argument + index to determine which IDL type it can correspond to. + This allows us to select the final overload that will + be invoked. If the value passed in is undefined + and there is an overload with an optional argument at this + position, then + we will choose that overload. If there is no valid overload for the type of + value passed in here, then we throw a {{TypeError}}. + Generally, the inspection of the value at the distinguishing argument index does not have any + side effects, and the only side effects in the overload resolution algorithm are the result of + converting the JavaScript values to IDL values. + (An exception exists when one of the overloads has a [=sequence type=] or [=frozen array type=] + at the distinguishing argument index. + In this case, we attempt to get the {{%Symbol.iterator%}} property to determine the appropriate + overload, and perform the conversion of the distinguishing argument separately before continuing + with the next step.) + + At this point, we have determined which overload to use. We now + convert the remaining arguments, from the distinguishing argument onwards, + again ignoring any additional arguments that were ignored due to being passed + after the last possible argument. + + When converting an optional argument's JavaScript value to its + equivalent IDL value, + undefined will be converted into the + optional argument's default value, + if it has one, or a special value “missing” otherwise. + + Optional arguments corresponding to a final, variadic argument do + not treat undefined as a special “missing” value, however. + The undefined value is converted to the type + of variadic argument as would be done for a non-optional + argument. + +
+ + +

Interfaces

+ +For every [=interface=] that is [=exposed=] in +a given [=realm=] and that is not declared with +the [{{LegacyNoInterfaceObject}}] or [{{LegacyNamespace}}] [=extended attributes=], +a corresponding property exists on the [=realm=]'s [=realm/global object=]. +The name of the property is the [=identifier=] of the interface, +and its value is an object called the interface object. +The characteristics of an interface object are described in [[#interface-object]]. + +If the [{{LegacyWindowAlias}}] extended attribute was specified on an [=exposed=] interface, +then for each [=LegacyWindowAlias identifier|identifier=] in [{{LegacyWindowAlias}}]'s [=LegacyWindowAlias identifier|identifiers=] +there exists a corresponding property on the {{Window}} global object. +The name of the property is the given [=LegacyWindowAlias identifier|identifier=], +and its value is a reference to the [=interface object=] for the [=interface=]. + +In addition, for every [{{LegacyFactoryFunction}}] extended attribute on an [=exposed=] interface, +a corresponding property exists on the JavaScript global object. +The name of the property is the [{{LegacyFactoryFunction}}]'s [=LegacyFactoryFunction identifier|identifier=], +and its value is an object called a legacy factory function, +which allows creation of objects that implement the interface. +The characteristics of a legacy factory function are described in [[#legacy-factory-functions]]. + +
+ Some JavaScript methods defined in this section will perform an implementation check in their opening steps, + to ensure they're being called on the correct kind of object + and that the method is valid to call from the current context. + + To implementation-check an object |jsValue| + against the interface |interface|, + with the identifier |name| + and the type |type|: + + 1. Let |object| to [=?=] [$ToObject$](|jsValue|). + 1. If |object| is a [=platform object=], + then [=perform a security check=], passing: + + * the platform object |object| + * the identifier |name| + * the type |type| + 1. If |object| does not [=implement=] |interface|, then [=JavaScript/throw=] a {{TypeError}}. + 1. Return |object|. + + Issue: This algo is not yet consistently used everywhere. +
+ + +

Interface object

+ +The [=interface object=] for a given [=interface=] is a [=built-in function object=]. +It has properties that correspond to the [=constants=] and [=static operations=] +defined on that interface, +as described in sections [[#js-constants]] and [[#js-operations]]. + +If the [=interface=] is declared with a [=constructor operation=], +then the [=interface object=] can be called as a [=constructor=] +to create an object that [=implements=] that interface. +Calling that interface as a function will throw an exception. + +[=Interface objects=] whose [=interfaces=] are not declared +with a [=constructor operation=] will throw when called, +both as a function and as a [=constructor=]. + +An [=interface object=] for an [=interface=] +has an associated object called the [=interface prototype object=]. +This object has properties that correspond to +the [=regular attributes=] and [=regular operations=] defined on the interface, +and is described in more detail in [[#interface-prototype-object]]. + +Note: Since an [=interface object=] is a [=function object=] +the typeof operator will return "function" when applied to an interface object. + +An interface may have overridden constructor steps, which can +change the behavior of the [=interface object=] when called or constructed. By +default interfaces do not have such steps. + +

+ In general, constructors are described by defining a [=constructor operation=] and its behavior. + The [=overridden constructor steps=] are used only for more complicated situations. + Editors who wish to use this feature are strongly advised to discuss this by + filing an issue before proceeding. +

+ +
+ + The [=interface object=] for a given [=interface=] |I| + with [=identifier=] |id| and in [=realm=] |realm| + is created as follows: + + 1. Let |steps| be |I|'s [=overridden constructor steps=] if they exist, or + the following steps otherwise: + 1. If |I| was not declared with a [=constructor operation=], + then [=JavaScript/throw=] a {{TypeError}}. + 1. If {{NewTarget}} is undefined, then + [=JavaScript/throw=] a {{TypeError}}. + 1. Let |args| be the passed arguments. + 1. Let |n| be the [=list/size=] of |args|. + 1. Let |id| be the identifier of interface |I|. + 1. [=Compute the effective overload set=] for constructors with [=identifier=] |id| on + [=interface=] |I| and with argument count |n|, and let |S| be the result. + 1. Let <|constructor|, |values|> be the result + of passing |S| and |args| to the [=overload resolution algorithm=]. + 1. Let |object| be the result of [=internally create a new object implementing the + interface|internally creating a new object implementing=] |I|, with |realm| and + {{NewTarget}}. + 1. Perform the [=constructor steps=] of |constructor| + with |object| as [=this=] and |values| as the argument values. + 1. Let |O| be |object|, [=converted to a JavaScript value=]. + 1. Assert: |O| is an object that [=implements=] |I|. + 1. Assert: |O|.\[[Realm]] is |realm|. + 1. Return |O|. + 1. Let |constructorProto| be |realm|.\[[Intrinsics]].[[{{%Function.prototype%}}]]. + 1. If |I| inherits from some other interface |P|, + then set |constructorProto| to the [=interface object=] of |P| in |realm|. + 1. Let |F| be CreateBuiltinFunction(|steps|, « \[[Unforgeables]] », + |realm|, |constructorProto|). + 1. Let |unforgeables| be [$OrdinaryObjectCreate$](null). + 1. [=Define the unforgeable regular operations=] of |I| on |unforgeables|, given |realm|. + 1. [=Define the unforgeable regular attributes=] of |I| on |unforgeables|, given |realm|. + 1. Set |F|.\[[Unforgeables]] to |unforgeables|. + + Note: this object is never exposed to user code. It exists only to ensure all instances + of an interface with an unforgeable member use the same JavaScript function objects for + [=attribute getters=], [=attribute setters=] and [=creating an operation + function|operation functions=]. + 1. Perform SetFunctionName(|F|, |id|). + 1. Let |length| be 0. + 1. If |I| was declared with a [=constructor operation=], then + 1. [=Compute the effective overload set=] for constructors with [=identifier=] |id| on + [=interface=] |I| and with argument count 0, and let |S| be the result. + 1. Set |length| to the length of the + shortest argument list of the entries in |S|. + 1. Perform SetFunctionLength(|F|, |length|). + 1. Let |proto| be the result of [=create an interface prototype object|creating an interface + prototype object=] of [=interface=] |I| in |realm|. + 1. Perform [=!=] DefinePropertyOrThrow(|F|, "prototype", + PropertyDescriptor{\[[Value]]: |proto|, \[[Writable]]: false, \[[Enumerable]]: false, \[[Configurable]]: false}). + 1. [=Define the constants=] of [=interface=] |I| on |F| given |realm|. + 1. [=Define the static attributes=] of [=interface=] |I| on |F| given |realm|. + 1. [=Define the static operations=] of [=interface=] |I| on |F| given |realm|. + 1. Return |F|. + +
+ + +

Legacy factory functions

+ +A [=legacy factory function=] that exists due to one or more +[{{LegacyFactoryFunction}}] [=extended attributes=] +with a given [=LegacyFactoryFunction identifier|identifier=] is a [=built-in function object=]. +It allows constructing objects that +implement the interface on which the +[{{LegacyFactoryFunction}}] extended attributes appear. + +
+ + The [=legacy factory function=] with [=LegacyFactoryFunction identifier|identifier=] |id| + for a given [=interface=] |I| in [=realm=] |realm| + is created as follows: + + 1. Let |steps| be the following steps: + 1. If {{NewTarget}} is undefined, then + [=JavaScript/throw=] a {{TypeError}}. + 1. Let |args| be the passed arguments. + 1. Let |n| be the [=list/size=] of |args|. + 1. [=Compute the effective overload set=] for legacy factory functions with [=identifier=] |id| + on [=interface=] |I| and with argument count |n|, and let |S| be the result. + 1. Let <|constructor|, |values|> be the result of passing |S| and + |args| to the [=overload resolution algorithm=]. + 1. Let |object| be the result of [=internally create a new object implementing the + interface|internally creating a new object implementing=] |I|, with |realm| and + {{NewTarget}}. + 1. Perform the [=constructor steps=] of |constructor| + with |object| as [=this=] and |values| as the argument values. + 1. Let |O| be |object|, [=converted to a JavaScript value=]. + 1. Assert: |O| is an object that [=implements=] |I|. + 1. Assert: |O|.\[[Realm]] is |realm|. + 1. Return |O|. + 1. Let |F| be CreateBuiltinFunction(|steps|, « », |realm|). + 1. Perform SetFunctionName(|F|, |id|). + 1. [=Compute the effective overload set=] for legacy factory functions with [=identifier=] |id| + on [=interface=] |I| and with argument count 0, and let |S| be the result. + 1. Let |length| be the length of the shortest argument list of the entries in |S|. + 1. Perform SetFunctionLength(|F|, |length|). + 1. Let |proto| be the [=interface prototype object=] of [=interface=] |I| in |realm|. + 1. Perform [=!=] DefinePropertyOrThrow(|F|, "prototype", + PropertyDescriptor{\[[Value]]: |proto|, \[[Writable]]: false, \[[Enumerable]]: false, \[[Configurable]]: false}). + 1. Return |F|. +
+ + +

Interface prototype object

+ +There will exist an interface prototype object +for every [=interface=] defined, +regardless of whether the interface was declared +with the [{{LegacyNoInterfaceObject}}] [=extended attribute=]. + +
+ + The [=interface prototype object=] for a given [=interface=] |interface| and [=realm=] |realm| + is created as follows: + + 1. Let |proto| be null. + 1. If |interface| is declared with the [{{Global}}] [=extended attribute=], + and |interface| [=support named properties|supports named properties=], + then set |proto| to the result of [=create a named properties object|creating a named + properties object=] for |interface| and |realm|. + 1. Otherwise, if |interface| is declared to inherit from another interface, + then set |proto| to the [=interface prototype object=] in |realm| + of that [=inherited interface=]. + 1. Otherwise, if |interface| is the {{DOMException}} [=interface=], + then set |proto| to |realm|.\[[Intrinsics]].[[{{%Error.prototype%}}]]. + 1. Otherwise, set |proto| to |realm|.\[[Intrinsics]].[[{{%Object.prototype%}}]]. + 1. Assert: Type(|proto|) is Object. + 1. Let |interfaceProtoObj| be null. + 1. If |realm|'s [=is global prototype chain mutable=] is true, then: + 1. Set |interfaceProtoObj| to [$OrdinaryObjectCreate$](|proto|). + 1. Otherwise, if |interface| is declared with the [{{Global}}] [=extended attribute=], or + |interface| is in the set of [=inherited interfaces=] of an interface + that is declared with the [{{Global}}] [=extended attribute=], then: + 1. Set |interfaceProtoObj| to [$MakeBasicObject$](« \[[Prototype]], \[[Extensible]] »). + 1. Set |interfaceProtoObj|.\[[Prototype]] to |proto|. + 1. Set the internal methods of |interfaceProtoObj| + which are specific to [=immutable prototype exotic objects=] + to the definitions specified in + [=ECMA-262 Immutable prototype exotic objects=]. + 1. Otherwise, set |interfaceProtoObj| to [$OrdinaryObjectCreate$](|proto|). + 1. If |interface| has any [=member=] declared with the [{{Unscopable}}] [=extended attribute=], + then: + 1. Let |unscopableObject| be [$OrdinaryObjectCreate$](null). + 1. [=list/For each=] [=exposed=] [=member=] |member| of |interface| + that is declared with the [{{Unscopable}}] [=extended attribute=]: + 1. Let |id| be |member|'s [=identifier=]. + 1. Perform [=!=] CreateDataPropertyOrThrow(|unscopableObject|, |id|, + true). + 1. Let |desc| be the PropertyDescriptor{\[[Value]]: |unscopableObject|, + \[[Writable]]: false, \[[Enumerable]]: false, + \[[Configurable]]: true}. + 1. Perform [=!=] DefinePropertyOrThrow(|interfaceProtoObj|, {{%Symbol.unscopables%}}, |desc|). + 1. If |interface| is not declared with the [{{Global}}] [=extended attribute=], then: + 1. [=Define the regular attributes=] of |interface| on |interfaceProtoObj| given |realm|. + 1. [=Define the regular operations=] of |interface| on |interfaceProtoObj| given |realm|. + 1. [=Define the iteration methods=] of |interface| on |interfaceProtoObj| given |realm|. + 1. [=Define the asynchronous iteration methods=] of |interface| on |interfaceProtoObj| + given |realm|. + 1. [=Define the constants=] of |interface| on |interfaceProtoObj| given |realm|. + 1. If the [{{LegacyNoInterfaceObject}}] [=extended attribute=] was not specified on |interface|, then: + 1. Let |constructor| be the [=interface object=] of |interface| in |realm|. + 1. Let |desc| be the PropertyDescriptor{\[[Writable]]: true, + \[[Enumerable]]: false, \[[Configurable]]: true, + \[[Value]]: |constructor|}. + 1. Perform [=!=] DefinePropertyOrThrow(|interfaceProtoObj|, "constructor", |desc|). + 1. Return |interfaceProtoObj|. +
+ +Additionally, [=interface prototype objects=] get properties declaratively from: + +* [[#js-stringifier]], +* [[#js-maplike]], and +* [[#js-setlike]]. + +Issue: Define those properties imperatively instead. + +
+ + The [=interface prototype object=] + of an [=interface=] that is defined with + the [{{LegacyNoInterfaceObject}}] + [=extended attribute=] + will be accessible. + For example, with the following IDL: + +
+        [Exposed=Window,
+         LegacyNoInterfaceObject]
+        interface Foo {
+        };
+
+        partial interface Window {
+          attribute Foo foo;
+        };
+    
+ + it is not possible to access the interface prototype object through + the [=interface object=] + (since it does not exist as window.Foo). However, an instance + of Foo can expose the interface prototype + object by calling its \[[GetPrototypeOf]] + [=/internal method=] – Object.getPrototypeOf(window.foo) in + this example. + +
+ +The [=class string=] of an [=interface prototype object=] is the [=interface=]'s [=qualified name=]. + + +

Named properties object

+ +For every [=interface=] declared with the [{{Global}}] [=extended attribute=] +that [=support named properties|supports named properties=], +there will exist an object known as the named properties object +for that interface on which named properties are exposed. + +
+ The [=named properties object=] for a given [=interface=] |interface| and [=realm=] |realm|, + is created as follows: + + 1. Let |proto| be null. + 1. If |interface| is declared to inherit from another interface, + then set |proto| to the [=interface prototype object=] in |realm| for the [=inherited interface=]. + 1. Otherwise, set |proto| to |realm|.\[[Intrinsics]].[[{{%Object.prototype%}}]]. + 1. Let |obj| be [$MakeBasicObject$](« \[[Prototype]], \[[Extensible]] »). + 1. Set |obj|.\[[GetOwnProperty]] as specified in [[#named-properties-object-getownproperty]]. + 1. Set |obj|.\[[DefineOwnProperty]] as specified in [[#named-properties-object-defineownproperty]]. + 1. Set |obj|.\[[Delete]] as specified in [[#named-properties-object-delete]]. + 1. Set |obj|.\[[SetPrototypeOf]] as specified in [[#named-properties-object-setprototypeof]]. + 1. Set |obj|.\[[PreventExtensions]] as specified in [[#named-properties-object-preventextensions]]. + 1. Set |obj|.\[[Prototype]] to |proto|. + 1. Return |obj|. +
+ +Note: The \[[OwnPropertyKeys]] internal method of a named properties object +continues to use OrdinaryOwnPropertyKeys, +unlike the counterpart for [=legacy platform objects=]. +Since named properties are not “real” own properties, +they will not be returned by this internal method. + +The [=class string=] of a [=named properties object=] +is the concatenation of the [=interface=]'s +[=identifier=] and the string "Properties". + + +
\[[GetOwnProperty]]
+ +
+ + When the \[[GetOwnProperty]] internal method of a [=named properties object=] |O| + is called with property key |P|, the following steps are taken: + + 1. Let |A| be the [=interface=] for the [=named properties object=] |O|. + 1. Let |object| be |O|.\[[Realm]]'s [=realm/global object=]. + 1. Assert: |object| [=implements=] |A|. + 1. If the result of running the [=named property visibility algorithm=] with + property name |P| and object |object| is true, then: + 1. Let |operation| be the operation used to declare the named property getter. + 1. Let |value| be an uninitialized variable. + 1. If |operation| was defined without an [=identifier=], then + set |value| to the result of performing the steps listed in the interface description to + [=determine the value of a named property=] + with |P| as the name. + 1. Otherwise, |operation| was defined with an identifier. Set |value| to the result + of performing the steps listed in the description of |operation| with |P| as the only argument value. + 1. Let |desc| be a newly created [=Property Descriptor=] with no fields. + 1. Set |desc|.\[[Value]] to the result of [=converted to a JavaScript value|converting=] + |value| to a JavaScript value. + 1. If |A| [=implements=] an interface with the + [{{LegacyUnenumerableNamedProperties}}] + [=extended attribute=], + then set |desc|.\[[Enumerable]] to false, + otherwise set it to true. + 1. Set |desc|.\[[Writable]] to true and + |desc|.\[[Configurable]] to true. + 1. Return |desc|. + 1. Return OrdinaryGetOwnProperty(|O|, |P|). +
+ + +
\[[DefineOwnProperty]]
+ +
+ + When the \[[DefineOwnProperty]] internal method of a [=named properties object=] is called, + the following steps are taken: + + 1. Return false. +
+ +
\[[Delete]]
+ +
+ + When the \[[Delete]] internal method of a [=named properties object=] is called, + the following steps are taken: + + 1. Return false. +
+ + +
\[[SetPrototypeOf]]
+ +
+ + When the \[[SetPrototypeOf]] internal method of a [=named properties object=] |O| is called with + JavaScript language value |V|, the following step is taken: + + 1. If |O|'s [=associated realm=]'s [=is global prototype chain mutable=] is true, + return [=?=] [$OrdinarySetPrototypeOf$](|O|, |V|). + 1. Return [=?=] SetImmutablePrototype(|O|, |V|). + +
+ + +
\[[PreventExtensions]]
+ +
+ + When the \[[PreventExtensions]] internal method of a [=named properties object=] is called, + the following steps are taken: + + 1. Return false. + + Note: this keeps [=named properties object=] extensible by + making \[[PreventExtensions]] fail. +
+ + +

Constants

+ +[=Constants=] are exposed on [=interface objects=], +[=legacy callback interface objects=], +[=interface prototype objects=], and +on the single object that [=implements=] the interface, +when an interface is declared with the [{{Global}}] [=extended attribute=]. + +
+ To define the constants of [=interface=], [=callback interface=], or [=namespace=] + |definition| on |target|, given [=realm=] |realm|, run the following steps: + + 1. [=list/For each=] [=constant=] |const| that is a [=member=] of |definition|: + 1. If |const| is not [=exposed=] in |realm|, then [=iteration/continue=]. + 1. Let |value| be the result of [=converted to a JavaScript value|converting=] + |const|'s IDL value to a JavaScript value. + 1. Let |desc| be the PropertyDescriptor{\[[Writable]]: false, + \[[Enumerable]]: true, \[[Configurable]]: false, + \[[Value]]: |value|}. + 1. Let |id| be |const|'s [=identifier=]. + 1. Perform [=!=] DefinePropertyOrThrow(|target|, |id|, |desc|). +
+ + +

Attributes

+ +[=Static attributes=] are exposed on the [=interface object=]. +[=Regular attributes=] are exposed on the [=interface prototype object=], +unless the attribute is [=unforgeable=] or +if the interface was declared with the [{{Global}}] [=extended attribute=], +in which case they are exposed on every object that [=implements=] the interface. + +
+ To define the regular attributes of [=interface=] or [=namespace=] |definition| on |target|, + given [=realm=] |realm|, run the following steps: + + 1. Let |attributes| be the [=list=] of [=regular attributes=] that are [=members=] of |definition|. + 1. [=list/Remove=] from |attributes| all the [=attributes=] that are [=unforgeable=]. + 1. [=Define the attributes=] |attributes| of |definition| on |target| given |realm|. +
+ +
+ To define the static attributes of [=interface=] or [=namespace=] |definition| on |target|, + given [=realm=] |realm|, run the following steps: + + 1. Let |attributes| be the [=list=] of [=static attributes=] that are [=members=] of |definition|. + 1. [=Define the attributes=] |attributes| of |definition| on |target| given |realm|. +
+ +
+ To define the unforgeable regular attributes of [=interface=] or [=namespace=] |definition| on |target|, + given [=realm=] |realm|, run the following steps: + + 1. Let |attributes| be the [=list=] of [=unforgeable=] [=regular attributes=] that are [=members=] of |definition|. + 1. [=Define the attributes=] |attributes| of |definition| on |target| given |realm|. +
+ +
+ To define the attributes |attributes| of [=interface=] or [=namespace=] |definition| on |target| + given [=realm=] |realm|, run the following steps: + + 1. [=list/For each=] [=attribute=] |attr| of |attributes|: + 1. If |attr| is not [=exposed=] in |realm|, then [=iteration/continue=]. + 1. Let |getter| be the result of creating an [=attribute getter=] + given |attr|, |definition|, and |realm|. + 1. Let |setter| be the result of creating an [=attribute setter=] + given |attr|, |definition|, and |realm|. + + Note: the algorithm to create an [=attribute setter=] + returns undefined if |attr| is [=read only=]. + 1. Let |configurable| be false if |attr| is [=unforgeable=] + and true otherwise. + 1. Let |desc| be the PropertyDescriptor{\[[Get]]: |getter|, \[[Set]]: |setter|, + \[[Enumerable]]: true, \[[Configurable]]: |configurable|}. + 1. Let |id| be |attr|'s [=identifier=]. + 1. Perform [=!=] DefinePropertyOrThrow(|target|, |id|, |desc|). + 1. If |attr|'s type is an [=observable array type=] with type argument |T|, then set + |target|'s [=backing observable array exotic object=] for |attr| to the result of + [=creating an observable array exotic object=] in |realm|, given |T|, |attr|'s + [=set an indexed value=] algorithm, and |attr|'s [=delete an indexed value=] algorithm. + +
+ +
+ + The attribute getter is created as follows, given an + [=attribute=] |attribute|, a [=namespace=] or [=interface=] |target|, and a [=realm=] |realm|: + + 1. Let |steps| be the following series of steps: + 1. Try running the following steps: + 1. Let |idlObject| be null. + 1. If |target| is an [=interface=], and |attribute| is a [=regular attribute=]: + 1. Let |jsValue| be the this value, if it is not + null or undefined, or |realm|'s + [=realm/global object=] otherwise. + (This will subsequently cause a {{TypeError}} in a few steps, if + the global object does not implement |target| and [{{LegacyLenientThis}}] is not + specified.) + + 1. If |jsValue| [=is a platform object=], then [=perform a security check=], + passing |jsValue|, |attribute|'s [=identifier=], and "getter". + 1. If |jsValue| does not [=implement=] |target|, then: + 1. If |attribute| was specified with the [{{LegacyLenientThis}}] + [=extended attribute=], then return undefined. + 1. Otherwise, [=JavaScript/throw=] a {{TypeError}}. + 1. If |attribute|'s type is an [=observable array type=], then return |jsValue|'s + [=backing observable array exotic object=] for |attribute|. + 1. Set |idlObject| to the IDL [=interface type=] value that represents a reference + to |jsValue|. + 1. Let |R| be the result of running the [=getter steps=] of |attribute| with + |idlObject| as [=this=]. + 1. Return the result of [=converted to a JavaScript value|converting=] |R| to a + JavaScript value of the type |attribute| is declared as. + + And then, if an exception |E| was thrown: + + 1. If |attribute|'s type is a [=promise type=], then return + [=!=] Call({{%Promise.reject%}}, {{%Promise%}}, «|E|»). + 1. Otherwise, end these steps and allow the exception to propagate. + 1. Let |F| be CreateBuiltinFunction(|steps|, « », |realm|). + 1. Let |name| be the string "get " prepended to |attribute|'s [=identifier=]. + 1. Perform SetFunctionName(|F|, |name|). + 1. Perform SetFunctionLength(|F|, 0). + 1. Return |F|. + +
+ +
+ + The attribute setter is created as follows, given an + [=attribute=] |attribute|, a [=namespace=] or [=interface=] |target|, and a [=realm=] |realm|: + + 1. If |target| is a [=namespace=]: + 1. Assert: |attribute| is [=read only=]. + 1. Return undefined. + 1. If |attribute| is [=read only=] and does not have a + [{{LegacyLenientSetter}}], [{{PutForwards}}] or [{{Replaceable}}] [=extended attribute=], return + undefined; there is no [=attribute setter=] function. + 1. Assert: |attribute|'s type is not a [=promise type=]. + 1. Let |steps| be the following series of steps: + 1. If no arguments were passed, then [=JavaScript/throw=] a {{TypeError}}. + 1. Let |V| be the value of the first argument passed. + 1. Let |id| be |attribute|'s [=identifier=]. + 1. Let |idlObject| be null. + 1. If |attribute| is a [=regular attribute=]: + 1. Let |jsValue| be the this value, if it is not + null or undefined, or |realm|'s + [=realm/global object=] otherwise. + (This will subsequently cause a {{TypeError}} in a few steps, if + the global object does not implement |target| and [{{LegacyLenientThis}}] is not + specified.) + + 1. If |jsValue| [=is a platform object=], then [=perform a security check=], passing + |jsValue|, |id|, and "setter". + 1. Let |validThis| be true if |jsValue| [=implements=] |target|, or false otherwise. + 1. If |validThis| is false and |attribute| was not specified with the [{{LegacyLenientThis}}] + [=extended attribute=], then [=JavaScript/throw=] a {{TypeError}}. + 1. If |attribute| is declared with the [{{Replaceable}}] extended attribute, then: + 1. Perform [=?=] CreateDataPropertyOrThrow(|jsValue|, |id|, |V|). + 1. Return undefined. + 1. If |validThis| is false, then return undefined. + 1. If |attribute| is declared with a [{{LegacyLenientSetter}}] extended attribute, then + return undefined. + 1. If |attribute| is declared with a [{{PutForwards}}] extended attribute, then: + 1. Let |Q| be [=?=] Get(|jsValue|, |id|). + 1. If Type(|Q|) is not Object, then [=JavaScript/throw=] a + {{TypeError}}. + 1. Let |forwardId| be the identifier argument of the [{{PutForwards}}] extended + attribute. + 1. Perform [=?=] Set(|Q|, |forwardId|, |V|, false). + 1. Return undefined. + 1. Set |idlObject| to the IDL [=interface type=] value that represents a reference + to |jsValue|. + 1. If |attribute|'s type is an [=observable array type=] with type argument |T|: + 1. Let |newValues| be the result of [=converted to an IDL value|converting=] |V| to + an IDL value of type sequence<|T|>. + 1. Let |oa| be |idlObject|'s |attribute|'s [=backing observable array exotic object=]. + 1. [=observable array exotic object/Set the length=] of |oa|.\[[ProxyHandler]] to 0. + 1. Let |i| be 0. + 1. While |i| < |newValues|'s [=list/size=]: + 1. Perform the algorithm steps given by + |oa|.\[[ProxyHandler]].\[[SetAlgorithm]], given |newValues|[|i|] and |i|. + 1. [=list/Append=] |newValues|[|i|] to |oa|.\[[ProxyHandler]].\[[BackingList]]. + 1. Return undefined. + 1. Let |idlValue| be determined as follows: + +
+
|attribute|'s type is an [=enumeration=]
+
+ 1. Let |S| be [=?=] ToString(|V|). + 1. If |S| is not one of the [=enumeration's values=], then + return undefined. + 1. Otherwise, |idlValue| is the enumeration value equal to |S|. +
+ +
Otherwise
+
+ |idlValue| is the result of [=converted to an IDL value|converting=] |V| to an + IDL value of |attribute|'s type. +
+
+ + 1. Perform the [=setter steps=] of |attribute|, + with |idlObject| as [=this=] and |idlValue| as [=the given value=]. + 1. Return undefined + 1. Let |F| be CreateBuiltinFunction(|steps|, « », |realm|). + 1. Let |name| be the string "set " prepended to |id|. + 1. Perform SetFunctionName(|F|, |name|). + 1. Perform SetFunctionLength(|F|, 1). + 1. Return |F|. +
+ +Note: Although there is only a single property for an IDL attribute, since +accessor property getters and setters are passed a [=this=] +value for the object on which property corresponding to the IDL attribute is +accessed, they are able to expose instance-specific data. + +Note: Attempting to assign to a property corresponding to a +[=read only=] [=attribute=] +results in different behavior depending on whether the script doing so is in strict mode. +When in strict mode, such an assignment will result in a {{TypeError}} +being thrown. When not in strict mode, the assignment attempt will be ignored. + + +

Operations

+ +For each unique [=identifier=] of an [=exposed=] [=operation=] defined on the [=interface=], +there exist a corresponding property. +[=Static operations=] are exposed of the [=interface object=]. +[=Regular operations=] are exposed on the [=interface prototype object=], +unless the operation is [=unforgeable=] or +the interface was declared with the [{{Global}}] [=extended attribute=], +in which case they are exposed on every object that [=implements=] the interface. + +
+ To define the regular operations of [=interface=] or [=namespace=] |definition| on |target|, given [=realm=] |realm|, + run the following steps: + + 1. Let |operations| be the [=list=] of [=regular operations=] that are [=members=] of |definition|. + 1. [=list/Remove=] from |operations| all the [=operations=] that are [=unforgeable=]. + 1. [=Define the operations=] |operations| of |definition| on |target| given |realm|. +
+ +
+ To define the static operations of [=interface=] or [=namespace=] |definition| on |target|, given [=realm=] |realm|, + run the following steps: + + 1. Let |operations| be the [=list=] of [=static operations=] that are [=members=] of |definition|. + 1. [=Define the operations=] |operations| of |definition| on |target| given |realm|. +
+ +
+ To define the unforgeable regular operations of [=interface=] or [=namespace=] |definition| on |target|, given [=realm=] |realm|, + run the following steps: + + 1. Let |operations| be the [=list=] of [=unforgeable=] [=regular operations=] that are [=members=] of |definition|. + 1. [=Define the operations=] |operations| of |definition| on |target| given |realm|. +
+ +
+ To define the operations |operations| of [=interface=] or [=namespace=] |definition| on |target|, + given [=realm=] |realm|, run the following steps: + + 1. [=list/For each=] [=operation=] |op| of |operations|: + 1. If |op| is not [=exposed=] in |realm|, then [=iteration/continue=]. + 1. Let |method| be the result of [=creating an operation function=] + given |op|, |definition|, and |realm|. + 1. Let |modifiable| be false if |op| is [=unforgeable=] + and true otherwise. + 1. Let |desc| be the PropertyDescriptor{\[[Value]]: |method|, + \[[Writable]]: |modifiable|, \[[Enumerable]]: true, + \[[Configurable]]: |modifiable|}. + 1. Let |id| be |op|'s [=identifier=]. + 1. Perform [=!=] DefinePropertyOrThrow(|target|, |id|, |desc|). +
+ +
+ To create an operation function, + given an [=operation=] |op|, a [=namespace=] or [=interface=] |target|, and a [=realm=] |realm|: + + 1. Let |id| be |op|'s [=identifier=]. + 1. Let |steps| be the following series of steps, given function argument + values |args|: + 1. Try running the following steps: + 1. Let |idlObject| be null. + 1. If |target| is an [=interface=], and |op| is not a [=static operation=]: + 1. Let |jsValue| be the this value, if it is not + null or undefined, or |realm|'s + [=realm/global object=] otherwise. + (This will subsequently cause a {{TypeError}} in a few steps, if + the global object does not implement |target| and [{{LegacyLenientThis}}] is not + specified.) + + 1. If |jsValue| [=is a platform object=], then [=perform a security check=], + passing |jsValue|, |id|, and "method". + 1. If |jsValue| does not [=implement=] the interface |target|, + [=JavaScript/throw=] a {{TypeError}}. + 1. Set |idlObject| to the IDL [=interface type=] value that represents a reference + to |jsValue|. + 1. Let |n| be the [=list/size=] of |args|. + 1. [=Compute the effective overload set=] for [=regular operations=] (if |op| is a + regular operation) or for [=static operations=] (if |op| is a static operation) + with [=identifier=] |id| on |target| and with argument count |n|, and let |S| be + the result. + 1. Let <|operation|, |values|> be the result of passing + |S| and |args| to the [=overload resolution algorithm=]. + 1. Let |R| be null. + 1. If |operation| is declared with a [{{Default}}] [=extended attribute=], then: + 1. Assert: |operation| [=has default method steps=]. + 1. Set |R| to the result of running the [=default method steps=] for |operation|, + with |idlObject| as [=this=] and |values| as the argument values. + 1. Otherwise, set |R| to the result of running the [=method steps=] of |operation|, + with |idlObject| as [=this=] and |values| as the argument values. + 1. Return |R|, [=converted to a JavaScript value=]. + + Issue(whatwg/webidl#674): |R| is assumed to be an IDL value of the type |op| is declared to return. + + And then, if an exception |E| was thrown: + + 1. If |op| has a [=return type=] + that is a [=promise type=], then return + [=!=] Call({{%Promise.reject%}}, {{%Promise%}}, «|E|»). + 1. Otherwise, end these steps and allow the exception to propagate. + 1. Let |F| be CreateBuiltinFunction(|steps|, « », |realm|). + 1. Perform SetFunctionName(|F|, |id|). + 1. [=Compute the effective overload set=] for [=regular operations=] (if |op| is a regular + operation) or for [=static operations=] (if |op| is a static operation) with [=identifier=] + |id| on |target| and with argument count 0, and let |S| be the result. + 1. Let |length| be the length of the shortest argument list in the entries in |S|. + 1. Perform SetFunctionLength(|F|, |length|). + 1. Return |F|. +
+ + +
Default operations
+ +A [=regular operation=] +has default method steps +if its [=identifier=] appears in the first column of the following table. In that case, its +default method steps are those given by the algorithm linked from the second column of +the table, and the operation must have the return type given in the third column of the table. + + + + + + + +
[=Identifier=] + [=Default method steps=] + [=Return type=]
"toJSON" + The [=default toJSON steps=] + {{object}}
+ +A [=regular operation=] that does not [=have default method steps=] must not be declared with a +[{{Default}}] [=extended attribute=]. + + +
Default toJSON operation
+ +
+ + The default toJSON steps for an [=interface=] |I| are: + + 1. Let |map| be a new [=ordered map=]. + 1. Let |stack| be the result of [=create an inheritance stack|creating an inheritance stack=] + for [=interface=] |I|. + 1. Invoke [=collect attribute values of an inheritance stack=] given [=this=], |stack|, and + |map|. + 1. Let |result| be [$OrdinaryObjectCreate$]({{%Object.prototype%}}). + 1. [=map/For each=] |key| → |value| of |map|, + 1. Let |k| be |key| [=converted to a JavaScript value=]. + 1. Let |v| be |value| [=converted to a JavaScript value=]. + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|result|, |k|, |v|). + 1. Return |result|. +
+ +
+ + To collect attribute values of an inheritance stack given a [=platform object=] + |object|, a [=stack=] |stack|, and an [=ordered map=] |map|: + + 1. Let |I| be the result of [=stack/pop|popping=] from |stack|. + 1. Invoke [=collect attribute values=] given |object|, |I|, and |map|. + 1. If |stack| [=stack/is not empty=], then invoke + [=collect attribute values of an inheritance stack=] given |object|, |stack|, and |map|. +
+ +
+ + To collect attribute values given a [=platform object=] |object|, an [=interface=] + |I|, and an [=ordered map=] |map|: + + 1. If a toJSON operation with a [{{Default}}] [=extended attribute=] is declared + on |I|, then [=list/for each=] [=exposed=] [=regular attribute=] |attr| that is an + [=interface member=] of |I|, in order: + 1. Let |id| be the [=identifier=] of |attr|. + 1. Let |value| be the result of running the [=getter steps=] of |attr| with |object| as + [=this=]. + 1. If |value| is a [=JSON type=], then [=map/set=] |map|[|id|] to |value|. + +
+ +
+ + To create an inheritance stack for [=interface=] |I|, + run the following steps: + + 1. Let |stack| be a new [=stack=]. + 1. [=stack/Push=] |I| onto |stack|. + 1. [=iteration/While=] |I| [=interface/inherits=] from an [=interface=], + 1. Let |I| be that [=interface=]. + 1. [=stack/Push=] |I| onto |stack|. + 1. Return |stack|. +
+ +
+ + Only [=regular attributes=] of [=interfaces=] that declare a toJSON operation with + a [{{Default}}] [=extended attribute=] are included, even if an [=inherited interface=] declares + such a toJSON operation. For example, consider the following [=IDL fragment=]: + +
+        [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;
+        };
+    
+ + Calling the toJSON() method of an object implementing interface + C defined above would return the following JSON object: + +
+    {
+        "a": "...",
+        "c": "..."
+    }
+    
+ + Calling the toJSON() method of an object implementing interface + A (or B) defined above would return: + +
+    {
+        "a": "..."
+    }
+    
+ + A toJSON operation can also be declared on an [=interface mixin=] (or + [=partial interface=]) and is equivalent to declaring it on the original [=interface=]. For + example, consider the following [=IDL fragment=]: + +
+        [Exposed=Window]
+        interface D {
+          attribute DOMString d;
+        };
+
+        interface mixin M {
+          [Default] object toJSON();
+          attribute DOMString m;
+        };
+
+        D includes M;
+    
+ + Calling the toJSON() method of an object implementing interface + D defined above would return: + +
+    {
+        "d": "...",
+        "m": "..."
+    }
+    
+
+ +

Stringifiers

+ +If the [=interface=] has an [=exposed=] [=stringifier=], +then there must exist a property with the following characteristics: + +* The name of the property is "toString". +* If the [=stringifier=] is [=unforgeable=] on the interface + or if the interface was declared with the [{{Global}}] [=extended attribute=], + then the property exists on every object that [=implements=] the interface. + Otherwise, the property exists on the [=interface prototype object=]. +* The property has attributes + { \[[Writable]]: |B|, \[[Enumerable]]: true, \[[Configurable]]: |B| }, + where |B| is false if the stringifier is [=unforgeable=] on the interface, + and true otherwise. +*
+ + The value of the property is a [=built-in function object=], which behaves as follows: + + 1. Let |thisValue| be the this value. + 1. Let |O| be [=?=] ToObject(|thisValue|). + 1. If |O| [=is a platform object=], + then [=perform a security check=], passing: + * the platform object |O|, + * the [=identifier=] of the [=stringifier=], and + * the type "method". + 1. If |O| does not [=implement=] the [=interface=] + on which the stringifier was declared, then [=JavaScript/throw=] a {{TypeError}}. + 1. Let |V| be an uninitialized variable. + 1. Depending on how stringifier was specified: +
+ : as a declaration + :: Set |V| to the result of performing the [=stringification behavior=] + of the interface. + : on an [=attribute=] + :: Set |V| to the result of running the [=getter steps=] of the attribute + (or those listed in the [=getter steps=] of the inherited attribute, if this attribute is declared to + [=inherit its getter=]), + with |O| as [=this=]. +
+ 1. Return the result of [=converted to a JavaScript value|converting=] |V| to a String value. +
+* The value of the [=function object=]'s length + property is the Number value 0. +* The value of the [=function object=]'s name + property is the String value "toString". + + +

Iterable declarations

+ +
+ To define the iteration methods + of [=interface=] |definition| on |target|, given [=realm=] |realm|, run the following steps: + + 1. If |definition| has an [=indexed property getter=], then: + 1. Perform [$DefineMethodProperty$](|target|, {{%Symbol.iterator%}}, + {{%Array.prototype.values%}}, false). + 1. If |definition| has a [=value iterator=], then: + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|target|, "entries", + {{%Array.prototype.entries%}}). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|target|, "keys", + {{%Array.prototype.keys%}}). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|target|, "values", + {{%Array.prototype.values%}}). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|target|, "forEach", + {{%Array.prototype.forEach%}}). + 1. Otherwise, if |definition| has a [=pair iterator=], then: + 1. Define the {{%Symbol.iterator%}} and entries methods: + 1. Let |steps| be the following series of steps: + 1. Let |jsValue| be [=?=] [$ToObject$](this value). + 1. If |jsValue| [=is a platform object=], then [=perform a security check=], + passing |jsValue|, "%Symbol.iterator%", and "method". + 1. If |jsValue| does not [=implement=] |definition|, then [=JavaScript/throw=] a + {{TypeError}}. + 1. Return a newly created [=default iterator object=] for |definition|, with + |jsValue| as its [=default iterator object/target=], "key+value" + as its [=default iterator object/kind=], and [=default iterator object/index=] + set to 0. + 1. Let |F| be [$CreateBuiltinFunction$](|steps|, « », |realm|). + 1. Perform [$SetFunctionName$](|F|, "entries"). + 1. Perform [$SetFunctionLength$](|F|, 0). + 1. Perform [$DefineMethodProperty$](|target|, {{%Symbol.iterator%}}, |F|, false). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|target|, "entries", |F|). + 1. Define the keys method: + 1. Let |steps| be the following series of steps: + 1. Let |jsValue| be [=?=] [$ToObject$](this value). + 1. If |jsValue| [=is a platform object=], then [=perform a security check=], + passing |jsValue|, "keys", and "method". + 1. If |jsValue| does not [=implement=] |definition|, then [=JavaScript/throw=] a + {{TypeError}}. + 1. Return a newly created [=default iterator object=] for |definition|, with + |jsValue| as its [=default iterator object/target=], "key" as its + [=default iterator object/kind=], and [=default iterator object/index=] set to 0. + 1. Let |F| be [$CreateBuiltinFunction$](|steps|, « », |realm|). + 1. Perform [$SetFunctionName$](|F|, "keys"). + 1. Perform [$SetFunctionLength$](|F|, 0). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|target|, "keys", |F|). + 1. Define the values method: + 1. Let |steps| be the following series of steps: + 1. Let |jsValue| be [=?=] [$ToObject$](this value). + 1. If |jsValue| [=is a platform object=], then [=perform a security check=], + passing |jsValue|, "values", and "method". + 1. If |jsValue| does not [=implement=] |definition|, then [=JavaScript/throw=] a + {{TypeError}}. + 1. Return a newly created [=default iterator object=] for |definition|, with + |jsValue| as its [=default iterator object/target=], "value" as its + [=default iterator object/kind=], and [=default iterator object/index=] set to 0. + 1. Let |F| be [$CreateBuiltinFunction$](|steps|, « », |realm|). + 1. Perform [$SetFunctionName$](|F|, "values"). + 1. Perform [$SetFunctionLength$](|F|, 0). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|target|, "values", |F|). + 1. Define the forEach method: + 1. Let |steps| be the following series of steps, given function argument values + |callback| and |thisArg|: + 1. Let |jsValue| be [=?=] [$ToObject$](this value). + 1. If |jsValue| [=is a platform object=], then [=perform a security check=], + passing |jsValue|, "forEach", and "method". + 1. If |jsValue| does not [=implement=] |definition|, then [=JavaScript/throw=] a + {{TypeError}}. + 1. Let |idlCallback| be |callback|, [=converted to an IDL value|converted=] to a + {{Function}}. + 1. Let |idlObject| be the IDL [=interface type=] value that represents a reference + to |jsValue|. + 1. Let |pairs| be |idlObject|'s list of [=value pairs to iterate over=]. + 1. Let |i| be 0. + 1. While |i| < |pairs|'s [=list/size=]: + 1. Let |pair| be |pairs|[|i|]. + 1. [=Invoke=] |idlCallback| with « |pair|'s [=value pair/value=], |pair|'s + [=value pair/key=], |idlObject| » and with |thisArg| as the + [=callback this value=]. + 1. Set |pairs| to |idlObject|'s current list of + [=value pairs to iterate over=]. (It might have changed.) + 1. Set |i| to |i| + 1. + 1. Let |F| be [$CreateBuiltinFunction$](|steps|, « », |realm|). + 1. Perform [$SetFunctionName$](|F|, "forEach"). + 1. Perform [$SetFunctionLength$](|F|, 1). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|target|, "forEach", |F|). +
+ + +
Default iterator objects
+ +A default iterator object for a given +[=interface=], target and iteration kind +is an object whose \[[Prototype]] [=/internal slot=] is the +[=iterator prototype object=] +for the [=interface=]. + +A [=default iterator object=] +has three internal values: + +* its target, which is an object whose values are to be + iterated, +* its kind, which is the iteration kind, +* its index, which is the current index into the values + to be iterated. + +Note: Default iterator objects are only used for [=pair iterators=]; +[=value iterators=], as they are currently +restricted to iterating over an object's +[=support indexed properties|supported indexed properties=], +use standard JavaScript Array iterator objects. + +Note: [=Default iterator objects=] do not have [=class strings=]; when Object.prototype.toString() is called on a [=default +iterator object=] of a given [=interface=], the [=class string=] of the +[=iterator prototype object=] of that [=interface=] is used. + + +
Iterator prototype object
+ +The iterator prototype object +for a given [=interface=] +is an object that exists for every interface that has a +[=pair iterator=]. It serves as the +prototype for [=default iterator objects=] +for the interface. + +The \[[Prototype]] [=/internal slot=] of an [=iterator prototype object=] +must be {{%IteratorPrototype%}}. + +
+ The iterator result for a [=value pair=] |pair| and a kind |kind| is given by the + following steps: + + 1. Let |result| be a value determined by the value of |kind|: +
+ : "key" + :: 1. Let |idlKey| be |pair|'s [=value pair/key=]. + 1. Let |key| be the result of [=converted to a JavaScript value|converting=] |idlKey| to a JavaScript value. + 1. |result| is |key|. + : "value" + :: 1. Let |idlValue| be |pair|'s [=value pair/value=]. + 1. Let |value| be the result of [=converted to a JavaScript value|converting=] |idlValue| to a JavaScript value. + 1. |result| is |value|. + : "key+value" + :: 1. Let |idlKey| be |pair|'s [=value pair/key=]. + 1. Let |idlValue| be |pair|'s [=value pair/value=]. + 1. Let |key| be the result of [=converted to a JavaScript value|converting=] |idlKey| to a JavaScript value. + 1. Let |value| be the result of [=converted to a JavaScript value|converting=] |idlValue| to a JavaScript value. + 1. Let |array| be [=!=] [$ArrayCreate$](2). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|array|, "0", |key|). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|array|, "1", |value|). + 1. |result| is |array|. +
+ 1. Return [$CreateIteratorResultObject$](|result|, false). +
+ +
+ + An [=iterator prototype object=] must have a next data property with attributes + { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true } + and whose value is a [=built-in function object=] that behaves as follows: + + 1. Let |interface| be the [=interface=] for which the + [=iterator prototype object=] exists. + 1. Let |thisValue| be the this value. + 1. Let |object| be [=?=] ToObject(|thisValue|). + 1. If |object| [=is a platform object=], + then [=perform a security check=], passing: + * the platform object |object|, + * the identifier "next", and + * the type "method". + 1. If |object| is not a [=default iterator object=] for |interface|, + then [=JavaScript/throw=] a {{TypeError}}. + 1. Let |index| be |object|'s [=default iterator object/index=]. + 1. Let |kind| be |object|'s [=default iterator object/kind=]. + 1. Let |values| be |object|'s [=default iterator object/target=]'s [=value pairs to iterate over=]. + 1. Let |len| be the length of |values|. + 1. If |index| is greater than or equal to |len|, then + return CreateIteratorResultObject(undefined, true). + 1. Let |pair| be the entry in |values| at index |index|. + 1. Set |object|'s index to |index| + 1. + 1. Return the [=iterator result=] for |pair| and |kind|. +
+ +The [=class string=] of an [=iterator prototype object=] for a given [=interface=] +is the result of concatenating the [=identifier=] of the [=interface=] +and the string " Iterator". + +

Asynchronous iterable declarations

+ +
+ To define the asynchronous iteration methods of [=interface=] |definition| on + |target|, given [=realm=] |realm|, run the following steps: + + 1. If |definition| does not have an an [=asynchronously iterable declaration=] (of either + sort), then return. + 1. Assert: |definition| does not have an [=indexed property getter=] or an + [=iterable declaration=]. + 1. If |definition| has a [=pair asynchronously iterable declaration=], then define the + {{%Symbol.asyncIterator%}} and entries methods: + 1. Let |steps| be the following series of steps, given function argument values |args|: + 1. Let |jsValue| be [=?=] [$ToObject$](this value). + 1. If |jsValue| [=is a platform object=], then [=perform a security check=], passing + |jsValue|, "%Symbol.asyncIterator%", and "method". + 1. If |jsValue| does not [=implement=] |definition|, then [=JavaScript/throw=] a + {{TypeError}}. + 1. Let |idlObject| be the IDL [=interface type=] value that represents a reference to + |jsValue|. + 1. Let |idlArgs| be the result of + [=converting arguments for an asynchronous iterator method=] given |args|. + 1. Let |iterator| be a newly created [=default asynchronous iterator object=] for + |definition| with |idlObject| as its + [=default asynchronous iterator object/target=], "key+value" as its + [=default asynchronous iterator object/kind=], and + [=default asynchronous iterator object/is finished=] set to false. + 1. Run the [=asynchronous iterator initialization steps=] for |definition| with + |idlObject|, |iterator|, and |idlArgs|, if any such steps exist. + 1. Return |iterator|. + 1. Let |F| be [$CreateBuiltinFunction$](|steps|, « », |realm|). + 1. Perform [$SetFunctionName$](|F|, "entries"). + 1. Perform [$SetFunctionLength$](|F|, 0). + 1. Perform [$DefineMethodProperty$](|target|, {{%Symbol.asyncIterator%}}, |F|, false). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|target|, "entries", |F|). + 1. If |definition| has a [=pair asynchronously iterable declaration=], then define the + keys method: + 1. Let |steps| be the following series of steps, given function argument values |args|: + 1. Let |jsValue| be [=?=] [$ToObject$](this value). + 1. If |jsValue| [=is a platform object=], then [=perform a security check=], passing + |jsValue|, "keys", and "method". + 1. If |jsValue| does not [=implement=] |definition|, then [=JavaScript/throw=] a + {{TypeError}}. + 1. Let |idlObject| be the IDL [=interface type=] value that represents a reference to + |jsValue|. + 1. Let |idlArgs| be the result of + [=converting arguments for an asynchronous iterator method=] given |args|. + 1. Let |iterator| be a newly created [=default asynchronous iterator object=] for + |definition| with |idlObject| as its + [=default asynchronous iterator object/target=], "key" as its + [=default asynchronous iterator object/kind=], and + [=default asynchronous iterator object/is finished=] set to false. + 1. Run the [=asynchronous iterator initialization steps=] for |definition| with + |idlObject|, |iterator|, and |idlArgs|, if any such steps exist. + 1. Return |iterator|. + 1. Let |F| be [$CreateBuiltinFunction$](|steps|, « », |realm|). + 1. Perform [$SetFunctionName$](|F|, "keys"). + 1. Perform [$SetFunctionLength$](|F|, 0). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|target|, "keys", |F|). + 1. Define the values, and possibly {{%Symbol.asyncIterator%}}, methods: + 1. Let |steps| be the following series of steps, given function argument values |args|: + 1. Let |jsValue| be [=?=] [$ToObject$](this value). + 1. If |jsValue| [=is a platform object=], then [=perform a security check=], passing + |jsValue|, "values", and "method". + 1. If |jsValue| does not [=implement=] |definition|, then [=JavaScript/throw=] a + {{TypeError}}. + 1. Let |idlObject| be the IDL [=interface type=] value that represents a reference to + |jsValue|. + 1. Let |idlArgs| be the result of + [=converting arguments for an asynchronous iterator method=] given |args|. + 1. Let |iterator| be a newly created [=default asynchronous iterator object=] for + |definition| with |idlObject| as its + [=default asynchronous iterator object/target=], "value" as its + [=default asynchronous iterator object/kind=], and + [=default asynchronous iterator object/is finished=] set to false. + 1. Run the [=asynchronous iterator initialization steps=] for |definition| with + |idlObject|, |iterator|, and |idlArgs|, if any such steps exist. + 1. Return |iterator|. + 1. Let |F| be [$CreateBuiltinFunction$](|steps|, « », |realm|). + 1. Perform [$SetFunctionName$](|F|, "values"). + 1. Perform [$SetFunctionLength$](|F|, 0). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|target|, "values", |F|). + 1. If |definition| has a [=value asynchronously iterable declaration=], then perform [=!=] + [$DefineMethodProperty$](|target|, {{%Symbol.asyncIterator%}}, |F|, false). +
+ +
+ To convert arguments for an asynchronous iterator method, + given an [=interface=] |definition| that has an [=asynchronously iterable declaration=] and a + [=list=] of JavaScript values |args|: + + 1. Let |idlArgs| be an empty list. + 1. Let |argCount| be the number of arguments of |definition|'s + [=asynchronously iterable declaration=], or 0 if the [=asynchronously iterable declaration=] + does not have an argument list. + 1. Let |i| be 0. + 1. While |i| < |argCount|: + 1. If |i| ≥ |args|'s [=list/size=], or if |args|[|i|] is undefined, + then: + 1. If the argument to the [=asynchronously iterable declaration=] at index |i| is + declared with a [=optional argument/default value=], then [=list/append=] that + default value to |idlArgs|. + 1. Otherwise, [=list/append=] to |idlArgs| the special value "missing". + 1. Otherwise, [=list/append=] to |idlArgs| the result of + [=converted to an IDL value|converting=] |args|[|i|] to the IDL type given in the + [=asynchronously iterable declaration=]'s argument list at index |i|. + 1. Set |i| to |i| + 1. + 1. Return |idlArgs|. + +

This is essentially a hyper-specialization of the + [=overload resolution algorithm=] for the case where no overloads are allowed and all arguments + are optional.

+
+ +
Default asynchronous iterator objects
+ +A default asynchronous iterator +object for a given [=interface=], target and iteration kind is an object whose \[[Prototype]] +[=/internal slot=] is the [=asynchronous iterator prototype object=] for the [=interface=]. + +A [=default asynchronous iterator object=] has internal values: + +* its target, which is an object whose + values are to be iterated, +* its kind, which is the iteration kind, +* its ongoing promise, which is a + {{Promise}} or null, +* its is finished, which is a boolean. + +Note: [=Default asynchronous iterator objects=] do not have [=class strings=]; when +Object.prototype.toString() is called on a +[=default asynchronous iterator object=] of a given [=interface=], the [=class string=] of the +[=asynchronous iterator prototype object=] of that [=interface=] is used. + + +
Asynchronous iterator prototype object
+ +The +asynchronous iterator prototype object +for a given [=interface=] is an object that exists for every interface that has an +[=asynchronously iterable declaration=]. +It serves as the prototype for [=default asynchronous iterator objects=] for the interface. + +The \[[Prototype]] [=/internal slot=] of an [=asynchronous iterator prototype object=] must be +{{%AsyncIteratorPrototype%}}. + +
+ + An [=asynchronous iterator prototype object=] must have a next data + property with attributes { \[[Writable]]: true, + \[[Enumerable]]: true, \[[Configurable]]: true } + and whose value is a [=built-in function object=] that behaves as follows: + + 1. Let |interface| be the [=interface=] for which the + [=asynchronous iterator prototype object=] exists. + + 1. Let |thisValidationPromiseCapability| be [=!=] [$NewPromiseCapability$]({{%Promise%}}). + + 1. Let |thisValue| be the this value. + 1. Let |object| be Completion(ToObject(|thisValue|)). + + 1. [$IfAbruptRejectPromise$](|object|, |thisValidationPromiseCapability|). + + 1. If |object| [=is a platform object=], then [=perform a security check=], passing: + * the platform object |object|, + * the identifier "next", and + * the type "method". + + If this threw an exception |e|, then: + 1. Perform [=!=] [$Call$](|thisValidationPromiseCapability|.\[[Reject]], + undefined, « |e| »). + 1. Return |thisValidationPromiseCapability|.\[[Promise]]. + + 1. If |object| is not a [=default asynchronous iterator object=] for |interface|, then: + 1. Let |error| be a new {{TypeError}}. + 1. Perform [=!=] [$Call$](|thisValidationPromiseCapability|.\[[Reject]], + undefined, « |error| »). + 1. Return |thisValidationPromiseCapability|.\[[Promise]]. + + 1. Let |nextSteps| be the following steps: + 1. Let |nextPromiseCapability| be [=!=] [$NewPromiseCapability$]({{%Promise%}}). + 1. If |object|'s [=default asynchronous iterator object/is finished=] is true, then: + 1. Let |result| be [$CreateIteratorResultObject$](undefined, + true). + 1. Perform [=!=] [$Call$](|nextPromiseCapability|.\[[Resolve]], + undefined, « |result| »). + 1. Return |nextPromiseCapability|.\[[Promise]]. + 1. Let |kind| be |object|'s [=default asynchronous iterator object/kind=]. + 1. Let |nextPromise| be the result of + [=get the next iteration result|getting the next iteration result=] with |object|'s + [=default asynchronous iterator object/target=] and |object|. + 1. Let |fulfillSteps| be the following steps, given |next|: + 1. Set |object|'s [=default asynchronous iterator object/ongoing promise=] to + null. + 1. If |next| is [=end of iteration=], then: + 1. Set |object|'s [=default asynchronous iterator object/is finished=] to true. + 1. Return [$CreateIteratorResultObject$](undefined, + true). + 1. Otherwise, if |interface| has a [=pair asynchronously iterable declaration=]: + 1. Assert: |next| is a [=value pair=]. + 1. Return the [=iterator result=] for |next| and |kind|. + 1. Otherwise: + 1. Assert: |interface| has a [=value asynchronously iterable declaration=]. + 1. Assert: |next| is a value of the type that appears in the declaration. + 1. Let |value| be |next|, [=converted to a JavaScript value=]. + 1. Return [$CreateIteratorResultObject$](|value|, false). + 1. Let |onFulfilled| be [$CreateBuiltinFunction$](|fulfillSteps|, « »). + 1. Let |rejectSteps| be the following steps, given |reason|: + 1. Set |object|'s [=default asynchronous iterator object/ongoing promise=] to + null. + 1. Set |object|'s [=default asynchronous iterator object/is finished=] to true. + 1. [=JavaScript/Throw=] |reason|. + 1. Let |onRejected| be [$CreateBuiltinFunction$](|rejectSteps|, « »). + 1. Perform [$PerformPromiseThen$](|nextPromise|, |onFulfilled|, |onRejected|, + |nextPromiseCapability|). + 1. Return |nextPromiseCapability|.\[[Promise]]. + + 1. Let |ongoingPromise| be |object|'s [=default asynchronous iterator object/ongoing promise=]. + + 1. If |ongoingPromise| is not null, then: + 1. Let |afterOngoingPromiseCapability| be [=!=] [$NewPromiseCapability$]({{%Promise%}}). + 1. Let |onSettled| be [$CreateBuiltinFunction$](|nextSteps|, « »). + 1. Perform [$PerformPromiseThen$](|ongoingPromise|, |onSettled|, |onSettled|, + |afterOngoingPromiseCapability|). + 1. Set |object|'s [=default asynchronous iterator object/ongoing promise=] to + |afterOngoingPromiseCapability|.\[[Promise]]. + + 1. Otherwise: + 1. Set |object|'s [=default asynchronous iterator object/ongoing promise=] to the result of + running |nextSteps|. + + 1. Return |object|'s [=default asynchronous iterator object/ongoing promise=]. +
+ +
+ + If an [=asynchronous iterator return=] algorithm is defined for the [=interface=], then the + [=asynchronous iterator prototype object=] must have a return data + property with attributes { \[[Writable]]: true, + \[[Enumerable]]: true, \[[Configurable]]: true } + and whose value is a [=built-in function object=], taking one argument |value|, that behaves as + follows: + + 1. Let |interface| be the [=interface=] for which the + [=asynchronous iterator prototype object=] exists. + + 1. Let |returnPromiseCapability| be [=!=] [$NewPromiseCapability$]({{%Promise%}}). + + 1. Let |thisValue| be the this value. + 1. Let |object| be Completion(ToObject(|thisValue|)). + + 1. [$IfAbruptRejectPromise$](|object|, |returnPromiseCapability|). + + 1. If |object| [=is a platform object=], then [=perform a security check=], passing: + * the platform object |object|, + * the identifier "return", and + * the type "method". + + If this threw an exception |e|, then: + 1. Perform [=!=] [$Call$](|returnPromiseCapability|.\[[Reject]], + undefined, « |e| »). + 1. Return |returnPromiseCapability|.\[[Promise]]. + + 1. If |object| is not a [=default asynchronous iterator object=] for |interface|, then: + 1. Let |error| be a new {{TypeError}}. + 1. Perform [=!=] [$Call$](|returnPromiseCapability|.\[[Reject]], + undefined, « |error| »). + 1. Return |returnPromiseCapability|.\[[Promise]]. + + 1. Let |returnSteps| be the following steps: + 1. Let |returnPromiseCapability| be [=!=] [$NewPromiseCapability$]({{%Promise%}}). + 1. If |object|'s [=default asynchronous iterator object/is finished=] is true, then: + 1. Let |result| be [$CreateIteratorResultObject$](|value|, true). + 1. Perform [=!=] [$Call$](|returnPromiseCapability|.\[[Resolve]], + undefined, « |result| »). + 1. Return |returnPromiseCapability|.\[[Promise]]. + 1. Set |object|'s [=default asynchronous iterator object/is finished=] to true. + 1. Return the result of running the [=asynchronous iterator return=] algorithm for + |interface|, given |object|'s [=default asynchronous iterator object/target=], |object|, + and |value|. + + 1. Let |ongoingPromise| be |object|'s [=default asynchronous iterator object/ongoing promise=]. + + 1. If |ongoingPromise| is not null, then: + 1. Let |afterOngoingPromiseCapability| be [=!=] [$NewPromiseCapability$]({{%Promise%}}). + 1. Let |onSettled| be [$CreateBuiltinFunction$](|returnSteps|, « »). + 1. Perform [$PerformPromiseThen$](|ongoingPromise|, |onSettled|, |onSettled|, + |afterOngoingPromiseCapability|). + 1. Set |object|'s [=default asynchronous iterator object/ongoing promise=] to + |afterOngoingPromiseCapability|.\[[Promise]]. + + 1. Otherwise: + 1. Set |object|'s [=default asynchronous iterator object/ongoing promise=] to the result of + running |returnSteps|. + + 1. Let |fulfillSteps| be the following steps: + 1. Return [$CreateIteratorResultObject$](|value|, true). + + 1. Let |onFulfilled| be [$CreateBuiltinFunction$](|fulfillSteps|, « »). + + 1. Perform [$PerformPromiseThen$](|object|'s [=default asynchronous iterator object/ongoing + promise=], |onFulfilled|, undefined, |returnPromiseCapability|). + + 1. Return |returnPromiseCapability|.\[[Promise]]. +
+ +The [=class string=] of an [=asynchronous iterator prototype object=] for a given [=interface=] is +the result of concatenating the [=identifier=] of the [=interface=] and the string +" AsyncIterator". + + +

Maplike declarations

+ +If an [=interface=] |A| is declared with +a [=maplike declaration=], then +there exists a number of additional properties on |A|'s +[=interface prototype object=]. +These additional properties are described in the sub-sections below. + +
size
+ +There must exist a size property on +|A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes + { \[[Get]]: |G|, \[[Enumerable]]: true, \[[Configurable]]: true }, + where |G| is the interface's map size getter, + defined below. +*
+ + The [=map size getter=] is a [=built-in function object=] + whose behavior when invoked is as follows: + + 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "size" and type "getter". + 1. Let |map| be the [=map entries=] of the IDL value + that represents a reference to |O|. + 1. Return |map|'s [=map/size=], [=converted to a JavaScript value=]. +
+ + The value of the [=function object=]'s length property is the Number value 0. + + The value of the [=function object=]'s name property is the String value "get size". + + +
%Symbol.iterator%
+ +There must exist a data property whose name is the {{%Symbol.iterator%}} symbol on +|A|'s [=interface prototype object=] +with attributes { \[[Writable]]: true, \[[Enumerable]]: false, \[[Configurable]]: true } +and whose value is the [=function object=] that is the value of +the entries property. + +
+ To create a map iterator + from a [=/map=] |map| + and a |kind| which is either "key+value", "key", or "value": + + 1. Let |closure| be a new [=/Abstract Closure=] with no parameters + that captures |map| and |kind| and performs the following steps when called: + 1. [=map/For each=] |key| → |value| of |map|: + 1. Set |key| and |value| to each [=converted to a JavaScript value=]. + 1. If |kind| is "key", let |result| be |key|. + 1. Else if |kind| is "value", let |result| be |value|. + 1. Else, let |result| be [$CreateArrayFromList$](« |key|, |value| »). + 1. Perform [=?=] [$GeneratorYield$]([$CreateIteratorResultObject$](|result|, false)). + + Note: The [=map/size=] of |map|, and the order of its entries, + might have changed while execution of this abstract operation + was paused by [$Yield$]. + 1. Return undefined. + 1. Return [$CreateIteratorFromClosure$](|closure|, "%MapIteratorPrototype%", {{%MapIteratorPrototype%}}). +
+ + +
entries
+ +There must exist an entries data property on +|A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + whose behavior when invoked is as follows: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "entries" and type "method". + 1. Let |map| be the [=map entries=] of the IDL value + that represents a reference to |O|. + 1. Return the result of [=creating a map iterator=] from |map| with kind "key+value". +
+ +The value of the [=function object=]'s length property is the Number value 0. + +The value of the [=function object=]'s name property is the String value "entries". + +
keys
+ +There must exist a keys data property on +|A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + whose behavior when invoked is as follows: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "keys" and type "method". + 1. Let |map| be the [=map entries=] of the IDL value + that represents a reference to |O|. + 1. Return the result of [=creating a map iterator=] from |map| with kind "key". +
+ +The value of the [=function object=]'s length property is the Number value 0. + +The value of the [=function object=]'s name property is the String value "keys". + + +
values
+ +There must exist a values data property on +|A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + whose behavior when invoked is as follows: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "values" and type "method". + 1. Let |map| be the [=map entries=] of the IDL value + that represents a reference to |O|. + 1. Return the result of [=creating a map iterator=] from |map| with kind "value". +
+ +The value of the [=function object=]'s length property is the Number value 0. + +The value of the [=function object=]'s name property is the String value "values". + + +
forEach
+ +There must exist a forEach data property on +|A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + whose behavior when invoked is as follows: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "forEach" and type "method". + 1. Let |map| be the [=map entries=] of the IDL value + that represents a reference to |O|. + 1. Let |callbackFn| be the first argument passed to the function, or undefined if not supplied. + 1. If [$IsCallable$](|callbackFn|) is false, [=JavaScript/throw=] a {{TypeError}}. + 1. Let |thisArg| be the second argument passed to the function, or undefined if not supplied. + 1. [=map/For each=] |key| → |value| of |map|: + 1. Let |jsKey| and |jsValue| be |key| and |value| [=converted to a JavaScript value=]. + 1. Perform [=?=] [$Call$](|callbackFn|, |thisArg|, « |jsValue|, |jsKey|, |O| »). + 1. Return undefined. +
+ +The value of the [=function object=]'s length property is the Number value 1. + +The value of the [=function object=]'s name property is the String value "forEach". + + +
get
+ +There must exist a get data property on +|A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + that behaves as follows when invoked: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "get" and type "method". + 1. Let |map| be the [=map entries=] of the IDL value + that represents a reference to |O|. + 1. Let |keyType| be the key type specified in the [=maplike declaration=]. + 1. Let |keyArg| be the first argument passed to this function, or undefined if not supplied. + 1. Let |key| be |keyArg| [=converted to an IDL value=] of type |keyType|. + 1. If |key| is -0, set |key| to +0. + 1. If |map|[|key|] [=map/exists=], then return |map|[|key|], + [=converted to a JavaScript value=]. +
+ +The value of the [=function object=]'s length property is the Number value 1. + +The value of the [=function object=]'s name property is the String value "get". + + +
has
+ +There must exist a has data property on +|A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + that behaves as follows when invoked: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "has" and type "method". + 1. Let |map| be the [=map entries=] of the IDL value + that represents a reference to |O|. + 1. Let |keyType| be the key type specified in the [=maplike declaration=]. + 1. Let |keyArg| be the first argument passed to this function, or undefined if not supplied. + 1. Let |key| be |keyArg| [=converted to an IDL value=] of type |keyType|. + 1. If |key| is -0, set |key| to +0. + 1. If |map|[|key|] [=map/exists=], then return true; + otherwise return false. +
+ +The value of the [=function object=]'s length property is the Number value 1. + +The value of the [=function object=]'s name property is the String value "has". + + +
set
+ +If |A| does not declare a [=member=] with identifier "set", +and |A| was declared with a read–write maplike declaration, +then there must exist a set data property +on |A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + that behaves as follows when invoked: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "set" and type "method". + 1. Let |map| be the [=map entries=] of the IDL value + that represents a reference to |O|. + 1. Let |keyType| be the key type specified in the [=maplike declaration=], and |valueType| be the value type. + 1. Let |keyArg| be the first argument passed to this function, or undefined if not supplied. + 1. Let |key| be |keyArg| [=converted to an IDL value=] of type |keyType|. + 1. If |key| is -0, set |key| to +0. + 1. Let |valueArg| be the second argument passed to this function, or undefined if not supplied. + 1. Let |value| be |valueArg| [=converted to an IDL value=] of type |valueType|. + 1. [=map/Set=] |map|[|key|] to |value|. + 1. Return |O|. +
+ +The value of the [=function object=]'s length property is the Number value 2. + +The value of the [=function object=]'s name property is the String value "set". + +If the interface does declare a set method, +it should similarly map a -0 key to +0, +and must return [=this=]. + + +
delete
+ +If |A| does not declare a [=member=] with identifier "delete", +and |A| was declared with a read–write maplike declaration, +then there must exist a delete data property +on |A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + that behaves as follows when invoked: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "delete" and type "method". + 1. Let |map| be the [=map entries=] of the IDL value + that represents a reference to |O|. + 1. Let |keyType| be the key type specified in the [=maplike declaration=]. + 1. Let |keyArg| be the first argument passed to this function, or undefined if not supplied. + 1. Let |key| be |keyArg| [=converted to an IDL value=] of type |keyType|. + 1. If |key| is -0, set |key| to +0. + 1. Let |retVal| be true if |map|[|key|] exists, + or else false. + 1. [=map/Remove=] |map|[|key|]. + 1. Return |retVal|. +
+ +The value of the [=function object=]'s length property is the Number value 1. + +The value of the [=function object=]'s name property is the String value "delete". + +If the interface does declare a delete method, +it should similarly map a -0 key to +0, +and must return a {{boolean}} indicating whether the key was present or not. + + +
clear
+ +If |A| does not declare a [=member=] with identifier "clear", +and |A| was declared with a read–write maplike declaration, +then there must exist a clear data property +on |A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + that behaves as follows when invoked: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "clear" and type "method". + 1. Let |map| be the [=map entries=] of the IDL value + that represents a reference to |O|. + 1. [=map/Clear=] |map|. + + Note: The [=/map=] is preserved because there may be existing + iterators, currently suspended, iterating over it. + 1. Return undefined. +
+ +The value of the [=function object=]'s length property is the Number value 0. + +The value of the [=function object=]'s name property is the String value "clear". + +If the interface does declare a clear method, +it must preserve the [=map entries=] object (rather than generating a new one) +and must return {{undefined}}. + + +

Setlike declarations

+ +If an [=interface=] |A| is declared with a [=setlike declaration=], +then there exists a number of additional properties on |A|'s [=interface prototype object=]. +These additional properties are described in the sub-sections below. + +
size
+ +A size property must exist on +|A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Get]]: |G|, \[[Enumerable]]: true, \[[Configurable]]: true }, + where |G| is the interface's set size getter, + defined below. +*
+ + The [=set size getter=] is a [=built-in function object=] + whose behavior when invoked is as follows: + + 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "size" and type "getter". + 1. Let |set| be the [=set entries=] of the IDL value + that represents a reference to |O|. + 1. Return |set|'s [=set/size=], [=converted to a JavaScript value=]. +
+ + The value of the [=function object=]'s length property is the Number value 0. + + The value of the [=function object=]'s name property is the String value "get size". + + +
%Symbol.iterator%
+ +There must exist a data property whose name is the {{%Symbol.iterator%}} symbol on +|A|'s [=interface prototype object=] +with attributes { \[[Writable]]: true, \[[Enumerable]]: false, \[[Configurable]]: true } +and whose value is the [=function object=] that is the value of +the values property. + +
+ To create a set iterator + from a [=/set=] |set| + and a |kind| which is either "key+value" or "value": + + 1. Let |closure| be a new [=/Abstract Closure=] with no parameters + that captures |set| and |kind| and performs the following steps when called: + 1. [=set/For each=] |entry| of |set|: + 1. Set |entry| to be |entry| [=converted to a JavaScript value=]. + 1. If |kind| is "value", let |result| be |entry|. + 1. Else, let |result| be [$CreateArrayFromList$](« |entry|, |entry| »). + 1. Perform [=?=] [$GeneratorYield$]([$CreateIteratorResultObject$](|result|, false)). + + Note: The [=set/size=] of |set|, and the order of its entries, + might have changed while execution of this abstract operation + was paused by [$Yield$]. + 1. Return undefined. + 1. Return [$CreateIteratorFromClosure$](|closure|, "%SetIteratorPrototype%", {{%SetIteratorPrototype%}}). +
+ + +
entries
+ +There must exist an entries data property on +|A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + whose behavior when invoked is as follows: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "entries" and type "method". + 1. Let |set| be the [=set entries=] of the IDL value + that represents a reference to |O|. + 1. Return the result of [=creating a set iterator=] from |set| with kind "key+value". +
+ +The value of the [=function object=]'s length property is +the Number value 0. + +The value of the [=function object=]'s name property is +the String value "entries". + + +
keys
+ +A keys data property must exist +on |A|'s [=interface prototype object=] +with attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true } +and whose value is the [=function object=] that is the value of +the values property. + + +
values
+ +There must exist a values data property on +|A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + whose behavior when invoked is as follows: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "values" and type "method". + 1. Let |set| be the [=set entries=] of the IDL value + that represents a reference to |O|. + 1. Return the result of [=creating a set iterator=] from |set| with kind "value". +
+ +The value of the [=function object=]'s length property is +the Number value 0. + +The value of the [=function object=]'s name property is +the String value "values". + + +
forEach
+ +There must exist a forEach data property on +|A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + whose behavior when invoked is as follows: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "forEach" and type "method". + 1. Let |set| be the [=set entries=] of the IDL value + that represents a reference to |O|. + 1. Let |callbackFn| be the first argument passed to the function, or undefined if not supplied. + 1. If [$IsCallable$](|callbackFn|) is false, [=JavaScript/throw=] a {{TypeError}}. + 1. Let |thisArg| be the second argument passed to the function, or undefined if not supplied. + 1. [=map/For each=] |value| of |set|: + 1. Let |jsValue| be |value| [=converted to a JavaScript value=]. + 1. Perform [=?=] [$Call$](|callbackFn|, |thisArg|, « |jsValue|, |jsValue|, |O|»). + 1. Return undefined. +
+ +The value of the [=function object=]'s length property is the Number value 1. + +The value of the [=function object=]'s name property is the String value "forEach". + + +
has
+ +There must exist a has data property on +|A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + that behaves as follows when invoked: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "has" and type "method". + 1. Let |set| be the [=set entries=] of the IDL value + that represents a reference to |O|. + 1. Let |valueType| be the value type specified in the [=setlike declaration=]. + 1. Let |valueArg| be the first argument passed to this function, or undefined if not supplied. + 1. Let |value| be |valueArg| [=converted to an IDL value=] of type |valueType|. + 1. If |value| is -0, set |value| to +0. + 1. If |set| [=set/contains=] |value|, then return true, + otherwise return false. +
+ +The value of the [=function object=]'s length property is a Number value 1. + +The value of the [=function object=]'s name property is the String value "has". + + +
add
+ +If |A| does not declare a [=member=] with identifier "add", +and |A| was declared with a read–write setlike declaration, +then there must exist an add data property +on |A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + that behaves as follows when invoked: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "add" and type "method". + 1. Let |set| be the [=set entries=] of the IDL value + that represents a reference to |O|. + 1. Let |valueType| be the value type specified in the [=setlike declaration=]. + 1. Let |valueArg| be the first argument passed to this function, or undefined if not supplied. + 1. Let |value| be |valueArg| [=converted to an IDL value=] of type |valueType|. + 1. If |value| is -0, set |value| to +0. + 1. [=set/Append=] |value| to |set|. + 1. Return |O|. +
+ +The value of the [=function object=]'s length property is the Number value 1. + +The value of the [=function object=]'s name property is the String value "add". + +If the interface does declare an add method, +it should similarly map a -0 value to +0, +and must return the value that was set. + + +
delete
+ +If |A| does not declare a [=member=] with identifier "delete", +and |A| was declared with a read–write setlike declaration, +then there must exist a delete data property +on |A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + that behaves as follows when invoked: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "delete" and type "method". + 1. Let |set| be |O|'s [=set entries=]. + 1. Let |valueType| be the value type specified in the [=setlike declaration=]. + 1. Let |valueArg| be the first argument passed to this function, or undefined if not supplied. + 1. Let |value| be |valueArg| [=converted to an IDL value=] of type |valueType|. + 1. If |value| is -0, set |value| to +0. + 1. Let |retVal| be true if |set| [=set/contains=] |value|, or else false. + 1. [=list/Remove=] |value| from |set|. + 1. Return |retVal|. +
+ +The value of the [=function object=]'s length property is the Number value 1. + +The value of the [=function object=]'s name property is the String value "delete". + +If the interface does declare a delete method, +it should similarly map a -0 value to +0, +and must return a {{boolean}} indicating whether the value was present or not. + + +
clear
+ +If |A| does not declare a [=member=] with identifier "clear", +and |A| was declared with a read–write setlike declaration, +then there must exist a clear data property +on |A|'s [=interface prototype object=] +with the following characteristics: + +* The property has attributes { \[[Writable]]: true, \[[Enumerable]]: true, \[[Configurable]]: true }. +* The value of the property is a [=built-in function object=] + that behaves as follows when invoked: + +
+ 1. Let |O| be the this value, [=implementation-checked=] against A with identifier "clear" and type "method". + 1. Let |set| be the [=set entries=] of the IDL value + that represents a reference to |O|. + 1. [=set/Empty=] |set|. + + Note: The [=/set=] is preserved because there may be existing + iterators, currently suspended, iterating over it. + 1. Return undefined. +
+ +The value of the [=function object=]'s length property is the Number value 0. + +The value of the [=function object=]'s name property is the String value "clear". + +If the interface does declare a clear method, +it must preserve the [=set entries=] object (rather than generating a new one) +and must return {{undefined}}. + + +

Platform objects implementing interfaces

+ +
+ A JavaScript value |value| is a platform object if [$Type$](|value|) is Object and + if |value| has a \[[PrimaryInterface]] internal slot. +
+ +
+ A JavaScript value |value| implements an [=interface=] |interface| + if |value| [=is a platform object=] and the [=inclusive inherited interfaces=] of + |value|.\[[PrimaryInterface]] [=list/contains=] |interface|. + + Specifications may reference the concept "|object| implements |interface|" + in various ways, including "|object| is an |interface| object". +
+ +Every [=platform object=] is associated with a [=realm=], just +as the [=initial objects=] are. +This realm is stored in the [=platform object=]'s \[[Realm]] slot. +It is the responsibility of specifications using Web IDL to state +which realm (or, by proxy, which global object) each platform +object is associated with. +In particular, the algorithms below associate the new [=platform object=] with +the realm given as an argument. + +
+ To create a new object implementing the interface |interface|, with a + [=realm=] |realm|, perform the following steps: + + 1. Return the result of [=internally create a new object implementing the + interface|internally creating a new object implementing=] |interface|, with |realm| and + undefined. +
+ +
+ To internally create a new object implementing the interface |interface|, with a + [=realm=] |realm| and a JavaScript value |newTarget|, perform the following steps: + + 1. Assert: |interface| is [=exposed=] in |realm|. + 1. If |newTarget| is undefined, then: + 1. Let |prototype| be the [=interface prototype object=] for |interface| in + |realm|. + 1. Otherwise: + 1. Assert: [$IsCallable$](|newTarget|) is true. + 1. Let |prototype| be [=?=] [$Get$](|newTarget|, "prototype"). + 1. If [$Type$](|prototype|) is not Object, then: + 1. Let |targetRealm| be [=?=] [$GetFunctionRealm$](|newTarget|). + 1. Set |prototype| to the [=interface prototype object=] for |interface| in + |targetRealm|. + 1. Let |instance| be [$MakeBasicObject$]( + « \[[Prototype]], \[[Extensible]], \[[Realm]], \[[PrimaryInterface]] »). + 1. Set |instance|.\[[Realm]] to |realm|. + 1. Set |instance|.\[[PrimaryInterface]] to |interface|. + 1. Set |instance|.\[[Prototype]] to |prototype|. + 1. Let |interfaces| be the [=inclusive inherited interfaces=] of |interface|. + 1. [=list/iterate|For every=] [=interface=] |ancestor interface| in |interfaces|: + 1. Let |unforgeables| be the value of the \[[Unforgeables]] slot of the [=interface + object=] of |ancestor interface| in |realm|. + 1. Let |keys| be [=!=] |unforgeables|.\[[OwnPropertyKeys]](). + 1. [=list|For each=] element |key| of |keys|: + 1. Let |descriptor| be [=!=] |unforgeables|.\[[GetOwnProperty]](|key|). + 1. Perform [=!=] [$DefinePropertyOrThrow$](|instance|, |key|, |descriptor|). + 1. If |interface| is declared with the [{{Global}}] [=extended attribute=], then: + 1. [=Define the regular operations=] of |interface| on |instance|, given |realm|. + 1. [=Define the regular attributes=] of |interface| on |instance|, given |realm|. + 1. [=Define the iteration methods=] of |interface| on |instance| given |realm|. + 1. [=Define the asynchronous iteration methods=] of |interface| on |instance| given |realm|. + 1. [=Define the global property references=] on |instance|, given |realm|. + 1. Set |instance|.\[[SetPrototypeOf]] as defined in [[#platform-object-setprototypeof]]. + 1. Otherwise, if |interfaces| contains an [=interface=] which + [=support indexed properties|supports indexed properties=], + [=support named properties|named properties=], or both: + 1. Set |instance|.\[[GetOwnProperty]] as defined in + [[#legacy-platform-object-getownproperty]]. + 1. Set |instance|.\[[Set]] as defined in + [[#legacy-platform-object-set]]. + 1. Set |instance|.\[[DefineOwnProperty]] as defined in + [[#legacy-platform-object-defineownproperty]]. + 1. Set |instance|.\[[Delete]] as defined in + [[#legacy-platform-object-delete]]. + 1. Set |instance|.\[[PreventExtensions]] as defined in + [[#legacy-platform-object-preventextensions]]. + 1. Set |instance|.\[[OwnPropertyKeys]] as defined in + [[#legacy-platform-object-ownpropertykeys]]. + 1. Return |instance|. +
+ +
+ To define the global property references on |target|, given [=realm=] |realm|, + perform the following steps: + + 1. Let |interfaces| be a [=list=] that contains every [=interface=] that is [=exposed=] in + |realm|. + 1. Sort |interfaces| in such a way that if |A| and |B| are [=list/items=] of |interfaces|, + and |A| [=interface/inherits=] from |B|, |A| has a higher index in |interfaces| than |B|. + 1. [=list/iterate|For every=] |interface| of |interfaces|: + 1. If |interface| is not declared with the [{{LegacyNoInterfaceObject}}] or + [{{LegacyNamespace}}] [=extended attributes=], then: + 1. Let |id| be |interface|'s [=identifier=]. + 1. Let |interfaceObject| be the result of [=create an interface object|creating + an interface object=] for |interface| with |id| in |realm|. + 1. Perform [$DefineMethodProperty$](|target|, |id|, |interfaceObject|, false). + 1. If the |interface| is declared with a [{{LegacyWindowAlias}}] [=extended attribute=], + and |target| implements the {{Window}} [=interface=], then: + 1. [=list/iterate|For every=] [=LegacyWindowAlias identifier|identifier=] |id| in + [{{LegacyWindowAlias}}]'s [=LegacyWindowAlias identifier|identifiers=]: + 1. Perform [$DefineMethodProperty$](|target|, |id|, |interfaceObject|, false). + 1. If the |interface| is declared with a [{{LegacyFactoryFunction}}] [=extended attribute=], + then: + 1. [=list/iterate|For every=] [=LegacyFactoryFunction identifier|identifier=] |id| in + [{{LegacyFactoryFunction}}]'s [=LegacyFactoryFunction identifier|identifiers=]: + 1. Let |legacyFactoryFunction| be the result of + [=create a legacy factory function|creating a legacy factory function=] with + |id| for |interface| in |realm|. + 1. Perform [$DefineMethodProperty$](|target|, |id|, |legacyFactoryFunction|, false). + 1. [=list/iterate|For every=] [=callback interface=] |interface| that is [=exposed=] in + |realm| and on which [=constants=] are defined: + 1. Let |id| be |interface|'s [=identifier=]. + 1. Let |interfaceObject| be the result of [=create a legacy callback interface + object|creating a legacy callback interface object=] for |interface| with |id| in |realm|. + 1. Perform [$DefineMethodProperty$](|target|, |id|, |interfaceObject|, false). + 1. [=list/iterate|For every=] [=namespace=] |namespace| that is [=exposed=] in + |realm|: + 1. Let |id| be |namespace|'s [=identifier=]. + 1. Let |namespaceObject| be the result of [=create a namespace object|creating a namespace object=] for |namespace| in |realm|. + 1. Perform [$DefineMethodProperty$](|target|, |id|, |namespaceObject|, false). +
+ +
+ The set of interfaces that a [=platform object=] [=implements=] does not change over + the lifetime of the object. + + Multiple [=platform objects=] with different [=realm/global objects=] will share + a reference to the same [=interface=] in their \[[PrimaryInterface]] internal + slots. For example, a page could contain a same-origin iframe, with the iframe's + method being called on the main page's element of the same kind, with no exception + thrown. + + [=Interface mixins=] do not participate directly in the evaluation of the [=implements=] + algorithm. Instead, each [=interface=] that the [=interface mixin=] is [=included=] in + has its own "copy" of each [=member=] of the [=interface mixin=], and the corresponding + [=creating an operation function|operation function=] checks that the receiver [=implements=] + the particular [=interface=] which [=includes=] the [=interface mixin=]. +
+ +
+ The primary interface of a [=platform object=] is + the value of the object's \[[PrimaryInterface]] internal slot, which is the most-derived + [=interface=] that it [=implements=]. +
+ +The [=realm=] that a given [=platform object=] +is associated with can change after it has been created. When +the [=realm=] associated with a platform object is changed, its +\[[Prototype]] [=/internal slot=] must be immediately +updated to be the [=interface prototype object=] +of the [=primary interface=] +from the [=platform object=]'s newly associated [=realm=]. + +Additionally, [=platform objects=] which implement an [=interface=] +which has a [{{Global}}] [=extended attribute=] +get properties declaratively from: + +* [[#js-stringifier]], +* [[#js-maplike]], and +* [[#js-setlike]]. + +Issue: Define those properties imperatively instead. + +

\[[SetPrototypeOf]]

+ +
+ + When the \[[SetPrototypeOf]] internal method of a [=platform object=] |O| that implements an + [=interface=] with the [{{Global}}] [=extended attribute=] is called with + JavaScript language value |V|, the following step is taken: + + 1. If |O|'s [=associated realm=]'s [=is global prototype chain mutable=] is true, + return [=?=] [$OrdinarySetPrototypeOf$](|O|, |V|). + 1. Return [=?=] SetImmutablePrototype(|O|, |V|). + +
+ +Note: For {{Window}} objects, it is unobservable whether this is implemented, since the presence of +the {{WindowProxy}} object ensures that \[[SetPrototypeOf]] is never called on a {{Window}} object +directly. For other global objects, however, this is necessary. + + +

Legacy platform objects

+ +[=Legacy platform objects=] will appear to have additional properties that correspond to their +[=indexed properties|indexed=] and [=named properties=]. These properties are not “real” own +properties on the object, but are made to look like they are by being exposed +by the \[[GetOwnProperty]] internal method . + +It is permissible for an object to implement multiple interfaces that support indexed properties. +However, if so, and there are conflicting definitions as to the object's +[=supported property indices=], +then it is undefined what additional properties the object will appear to +have, or what its exact behavior will be with regard to its indexed properties. +The same applies for named properties. + +The [=indexed property getter=] +that is defined on the derived-most interface that the +legacy platform object implements is the one that defines the behavior +when indexing the object with an [=array index=]. Similarly for +[=indexed property setters=]. +This way, the definitions of these special operations from +ancestor interfaces can be overridden. + +A property name is an unforgeable property name on a +given platform object |O| if the object implements an [=interface=] that +has an [=interface member=] with that identifier +and that interface member is [=unforgeable=] on any of +the interfaces that |O| implements. + +Support for [=getters=] is handled in [[#legacy-platform-object-getownproperty]], +and for [=setters=] in [[#legacy-platform-object-defineownproperty]] +and [[#legacy-platform-object-set]]. + +Additionally, [=legacy platform objects=] have internal methods as defined in: + +* [[#legacy-platform-object-delete]], +* [[#legacy-platform-object-preventextensions]], and +* [[#legacy-platform-object-ownpropertykeys]]. + + +

\[[GetOwnProperty]]

+ +
+ + The \[[GetOwnProperty]] internal method of every [=legacy platform object=] |O| + must behave as follows when called with property name |P|: + + 1. Return [=?=] LegacyPlatformObjectGetOwnProperty(|O|, |P|, false). +
+ + +

\[[Set]]

+ +
+ + The \[[Set]] internal method of every [=legacy platform object=] |O| + must behave as follows when called with + property name |P|, value |V|, and JavaScript language value |Receiver|: + + 1. If |O| and |Receiver| are the same object, then: + 1. If |O| [=implements=] an interface with an [=indexed property setter=] + and |P| [=is an array index=], then: + 1. [=Invoke the indexed property setter=] on |O| with |P| and |V|. + 1. Return true. + 1. If |O| [=implements=] an interface with a [=named property setter=] + and Type(|P|) is String, then: + 1. [=Invoke the named property setter=] on |O| with |P| and |V|. + 1. Return true. + 1. Let |ownDesc| be [=?=] LegacyPlatformObjectGetOwnProperty(|O|, |P|, true). + 1. Perform [=?=] OrdinarySetWithOwnDescriptor(|O|, |P|, |V|, |Receiver|, |ownDesc|). +
+ + +

\[[DefineOwnProperty]]

+ +
+ + When the \[[DefineOwnProperty]] internal method of a [=legacy platform object=] |O| + is called with property key |P| and [=Property Descriptor=] |Desc|, + the following steps must be taken: + + 1. If |O| [=support indexed properties|supports indexed properties=] and + |P| [=is an array index=], then: + 1. If the result of calling IsDataDescriptor(|Desc|) is + false, then return + false. + 1. If |O| does not implement an interface with an + [=indexed property setter=], then return false. + 1. [=Invoke the indexed property setter=] on |O| with |P| and |Desc|.\[[Value]]. + 1. Return true. + 1. If |O| [=support named properties|supports named properties=], + |O| does not implement an [=interface=] with the [{{Global}}] [=extended attribute=], + Type(|P|) is String, + and |P| is not an [=unforgeable property name=] + of |O|, then: + 1. Let |creating| be true if |P| is not a [=supported property name=], and false otherwise. + 1. If |O| [=implements=] an interface with the [{{LegacyOverrideBuiltIns}}] + [=extended attribute=] or |O| does not have an own property + named |P|, then: + 1. If |creating| is false and |O| does not implement an + interface with a [=named property setter=], then return false. + 1. If |O| [=implements=] an interface with a + [=named property setter=], then: + 1. If the result of calling IsDataDescriptor(|Desc|) is + false, then return + false. + 1. [=Invoke the named property setter=] on |O| with |P| and |Desc|.\[[Value]]. + 1. Return true. + 1. Return [=!=] OrdinaryDefineOwnProperty(|O|, |P|, |Desc|). +
+ + +

\[[Delete]]

+ +
+ + The \[[Delete]] internal method of every [=legacy platform object=] |O| + must behave as follows when called with property name |P|. + + 1. If |O| [=support indexed properties|supports indexed properties=] and + |P| [=is an array index=], then: + 1. Let |index| be the result of calling [=!=] ToUint32(|P|). + 1. If |index| is not a [=supported property indices|supported property index=], then return true. + 1. Return false. + 1. If |O| [=support named properties|supports named properties=], + |O| does not implement an [=interface=] with the [{{Global}}] [=extended attribute=] + and the result of calling the [=named property visibility algorithm=] + with property name |P| and object |O| is true, then: + 1. If |O| does not implement an interface with a [=named property deleter=], then return false. + 1. Let |operation| be the operation used to declare the named property deleter. + 1. If |operation| was defined without an [=identifier=], then: + 1. Perform the steps listed in the interface description to + [=delete an existing named property=] + with |P| as the name. + 1. If the steps indicated that the deletion failed, then return false. + 1. Otherwise, |operation| was defined with an identifier: + 1. Perform [=method steps=] of |operation| with |O| as [=this=] and « |P| » as the + argument values. + 1. If |operation| was declared with a [=return type=] of {{boolean}} + and the steps returned false, then return false. + 1. Return true. + 1. If |O| has an own property with name |P|, then: + 1. If the property is not configurable, then return false. + 1. Otherwise, remove the property from |O|. + 1. Return true. +
+ + +

\[[PreventExtensions]]

+ +
+ + When the \[[PreventExtensions]] internal method of a [=legacy platform object=] is called, + the following steps are taken: + + 1. Return false. + + Note: this keeps [=legacy platform objects=] extensible by + making \[[PreventExtensions]] fail for them. +
+ + +

\[[OwnPropertyKeys]]

+ +This document does not define a complete property enumeration order +for [=platform objects=] implementing [=interfaces=] +(or for platform objects representing exceptions). +However, it does for [=legacy platform objects=] by defining the \[[OwnPropertyKeys]] +internal method as follows. + +
+ + When the \[[OwnPropertyKeys]] internal method of a [=legacy platform object=] |O| is called, + the following steps are taken: + + 1. Let |keys| be a new empty [=list=] of JavaScript String and Symbol values. + 1. If |O| [=support indexed properties|supports indexed properties=], then [=list|for each=] |index| of |O|'s + [=supported property indices=], in ascending numerical order, [=list|append=] [=!=] ToString(|index|) to + |keys|. + 1. If |O| [=support named properties|supports named properties=], then [=list|for each=] |P| of |O|'s + [=supported property names=] that is visible according to the [=named property visibility algorithm=], + [=list|append=] |P| to |keys|. + 1. [=list|For each=] |P| of |O|'s own property keys that is a String, in ascending chronological order of + property creation, [=list|append=] |P| to |keys|. + 1. [=list|For each=] |P| of |O|'s own property keys that is a Symbol, in ascending chronological order of + property creation, [=list|append=] |P| to |keys|. + 1. Assert: |keys| has no duplicate items. + 1. Return |keys|. + +
+ +

Abstract operations

+ +
+ + To determine if a property name |P| is an [=array index=], the following algorithm is + applied: + + 1. If Type(|P|) is not String, then return false. + 1. Let |index| be CanonicalNumericIndexString(|P|). + 1. If |index| is undefined, then return false. + 1. If IsInteger(|index|) is false, + then return false. + 1. If |index| is −0, then return false. + 1. If |index| < 0, then return false. + 1. If |index| ≥ 232 − 1, then return false. + + Note: 232 − 1 is the maximum array length allowed by JavaScript. + 1. Return true. + +
+ +
+ + The named property visibility algorithm + is used to determine if a given named property is exposed on an object. + Some named properties are not exposed on an object depending on whether + the [{{LegacyOverrideBuiltIns}}] [=extended attribute=] was used. + The algorithm operates as follows, with property name |P| and object |O|: + + 1. If |P| is not a [=supported property name=] of |O|, then return false. + 1. If |O| has an own property named |P|, then return false. + + Note: This will include cases in which |O| has unforgeable properties, + because in practice those are always set up before objects have any supported property names, + and once set up will make the corresponding named properties invisible. + + 1. If |O| [=implements=] an interface that has the [{{LegacyOverrideBuiltIns}}] + [=extended attribute=], then return true. + 1. Let |prototype| be |O|.\[[GetPrototypeOf]](). + 1. While |prototype| is not null: + 1. If |prototype| is not a [=named properties object=], + and |prototype| has an own property named |P|, then return false. + 1. Set |prototype| to |prototype|.\[[GetPrototypeOf]](). + 1. Return true. +
+ +
+ + This ensures that for objects with named properties, property resolution is done in the following order: + + 1. Indexed properties. + 1. Own properties, including unforgeable attributes and operations. + 1. Then, if [{{LegacyOverrideBuiltIns}}]: + 1. Named properties. + 1. Properties from the prototype chain. + 1. Otherwise, if not [{{LegacyOverrideBuiltIns}}]: + 1. Properties from the prototype chain. + 1. Named properties. +
+ +
+ + To invoke an indexed property setter + on a [=platform object=] |O| with property name |P| and JavaScript value |V|, the following steps must be performed: + + 1. Let |index| be the result of calling [=?=] ToUint32(|P|). + 1. Let |creating| be true if |index| is not a [=supported property indices|supported property index=], + and false otherwise. + 1. Let |operation| be the operation used to declare the indexed property setter. + 1. Let |T| be the type of the second argument of |operation|. + 1. Let |value| be the result of [=converted to an IDL value|converting=] |V| to an IDL value of type |T|. + 1. If |operation| was defined without an [=identifier=], then: + 1. If |creating| is true, then perform the steps listed in the interface description to + [=set the value of a new indexed property=] + with |index| as the index and |value| as the value. + 1. Otherwise, |creating| is false. Perform the steps listed in the interface description to + [=set the value of an existing indexed property=] + with |index| as the index and |value| as the value. + 1. Otherwise, |operation| was defined with an identifier. Perform the [=method steps=] of + |operation| with |O| as [=this=] and « |index|, |value| » as the argument values. +
+ +
+ + To invoke a named property setter + on a [=platform object=] |O| with property name |P| and JavaScript value |V|, the following steps must be performed: + + 1. Let |creating| be true if |P| is not a [=supported property name=], and false otherwise. + 1. Let |operation| be the operation used to declare the named property setter. + 1. Let |T| be the type of the second argument of |operation|. + 1. Let |value| be the result of [=converted to an IDL value|converting=] |V| to an IDL value of type |T|. + 1. If |operation| was defined without an [=identifier=], then: + 1. If |creating| is true, then perform the steps listed in the interface description to + [=set the value of a new named property=] + with |P| as the name and |value| as the value. + 1. Otherwise, |creating| is false. Perform the steps listed in the interface description to + [=set the value of an existing named property=] + with |P| as the name and |value| as the value. + 1. Otherwise, |operation| was defined with an identifier. Perform the [=method steps=] of + |operation| with |O| as [=this=] and « |P|, |value| » as the argument values. +
+ +
+ + The LegacyPlatformObjectGetOwnProperty + abstract operation performs the following steps when called with + an object |O|, a property name |P|, and a boolean |ignoreNamedProps| value: + + 1. If |O| [=support indexed properties|supports indexed properties=] + and |P| [=is an array index=], then: + 1. Let |index| be the result of calling [=!=] ToUint32(|P|). + 1. If |index| is a [=supported property indices|supported property index=], then: + 1. Let |operation| be the operation used to declare the indexed property getter. + 1. Let |value| be an uninitialized variable. + 1. If |operation| was defined without an [=identifier=], then + set |value| to the result of performing the steps listed in the interface description to + [=determine the value of an indexed property=] + with |index| as the index. + 1. Otherwise, |operation| was defined with an identifier. Set |value| to the result + of performing the [=method steps=] of |operation| with |O| as [=this=] and « + |index| » as the argument values. + 1. Let |desc| be a newly created [=Property Descriptor=] with no fields. + 1. Set |desc|.\[[Value]] to the result of [=converted to a JavaScript value|converting=] + |value| to a JavaScript value. + 1. If |O| [=implements=] an interface with an [=indexed property setter=], then set + |desc|.\[[Writable]] to true, otherwise set it to + false. + 1. Set |desc|.\[[Enumerable]] and |desc|.\[[Configurable]] to true. + 1. Return |desc|. + 1. Set |ignoreNamedProps| to true. + 1. If |O| [=support named properties|supports named properties=] and + |ignoreNamedProps| is false, then: + 1. If the result of running the [=named property visibility algorithm=] with + property name |P| and object |O| is true, then: + 1. Let |operation| be the operation used to declare the named property getter. + 1. Let |value| be an uninitialized variable. + 1. If |operation| was defined without an [=identifier=], then + set |value| to the result of performing the steps listed in the interface description to + [=determine the value of a named property=] + with |P| as the name. + 1. Otherwise, |operation| was defined with an identifier. Set |value| to the result + of performing the [=method steps=] of |operation| with |O| as [=this=] and « |P| » + as the argument values. + 1. Let |desc| be a newly created [=Property Descriptor=] with no fields. + 1. Set |desc|.\[[Value]] to the result of [=converted to a JavaScript value|converting=] + |value| to a JavaScript value. + 1. If |O| [=implements=] an interface with a [=named property setter=], then set + |desc|.\[[Writable]] to true, otherwise set it to + false. + 1. If |O| [=implements=] an interface with the + [{{LegacyUnenumerableNamedProperties}}] + [=extended attribute=], + then set |desc|.\[[Enumerable]] to false, + otherwise set it to true. + 1. Set |desc|.\[[Configurable]] to true. + 1. Return |desc|. + 1. Return OrdinaryGetOwnProperty(|O|, |P|). +
+ +

Observable array exotic objects

+ +An observable array exotic object is a specific type of JavaScript +[=Proxy exotic object=] which is created using the proxy traps defined in this section. They are +defined in this manner because the JavaScript specification includes special treatment for +[=Proxy exotic objects=] that have Array instances as their proxy target, and we want +to ensure that [=observable array types=] are exposed to JavaScript code with this special treatment +intact. + +The proxy traps used by observable array exotic objects work to ensure a number of invariants beyond +those of normal Array instances: + +* The arrays have no holes, i.e. every property in the inclusive range 0 through + observableArray.length − 1 will be filled with a value compatible with the + specified Web IDL type, and no [=array index=] properties will exist outside that range. +* The property descriptors for important properties cannot be changed from their default + configuration; indexed properties always remain as configurable, enumerable, and writable data + properties, while the length property remains as a non-configurable, + non-enumerable, and writable data property. +* Adding additional properties to the array cannot be prevented using, for example, + Object.preventExtensions(). + +
+ To create an observable array exotic object + in a [=realm=] |realm|, given Web IDL type |T| and algorithms |setAlgorithm| and |deleteAlgorithm|: + + 1. Let |innerArray| be [=!=] [$ArrayCreate$](0). + 1. Let |handler| be [$OrdinaryObjectCreate$](null, + « \[[Type]], \[[SetAlgorithm]], \[[DeleteAlgorithm]], \[[BackingList]] »). + 1. Set |handler|.\[[Type]] to |T|. + 1. Set |handler|.\[[SetAlgorithm]] to |setAlgorithm|. + 1. Set |handler|.\[[DeleteAlgorithm]] to |deleteAlgorithm|. + 1. Let |defineProperty| be [$CreateBuiltinFunction$](the steps from [[#js-observable-array-defineProperty]], « », |realm|). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|handler|, "defineProperty", |defineProperty|). + 1. Let |deleteProperty| be [$CreateBuiltinFunction$](the steps from [[#js-observable-array-deleteProperty]], « », |realm|). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|handler|, "deleteProperty", |deleteProperty|). + 1. Let |get| be [$CreateBuiltinFunction$](the steps from [[#js-observable-array-get]], « », |realm|). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|handler|, "get", |get|). + 1. Let |getOwnPropertyDescriptor| be [$CreateBuiltinFunction$](the steps from [[#js-observable-array-getOwnPropertyDescriptor]], « », |realm|). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|handler|, "getOwnPropertyDescriptor", |getOwnPropertyDescriptor|). + 1. Let |has| be [$CreateBuiltinFunction$](the steps from [[#js-observable-array-has]], « », |realm|). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|handler|, "has", |has|). + 1. Let |ownKeys| be [$CreateBuiltinFunction$](the steps from [[#js-observable-array-ownKeys]], « », |realm|). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|handler|, "ownKeys", |ownKeys|). + 1. Let |preventExtensions| be [$CreateBuiltinFunction$](the steps from [[#js-observable-array-preventExtensions]], « », |realm|). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|handler|, "preventExtensions", |preventExtensions|). + 1. Let |set| be [$CreateBuiltinFunction$](the steps from [[#js-observable-array-set]], « », |realm|). + 1. Perform [=!=] [$CreateDataPropertyOrThrow$](|handler|, "set", |set|). + 1. Return [=!=] [$ProxyCreate$](|innerArray|, |handler|). +
+ +

defineProperty

+ +
+ The steps for the defineProperty proxy trap for + [=observable array exotic objects=], given |O|, |P|, and |descriptorObj| are as follows: + + 1. Let |handler| be the this value. + 1. Let |descriptor| be [=!=] [$ToPropertyDescriptor$](|descriptorObj|). + 1. If |P| is "length", then: + 1. If [$IsAccessorDescriptor$](|descriptor|) is true, then return + false. + 1. If |descriptor|.\[[Configurable]] is present and has the value true, + then return false. + 1. If |descriptor|.\[[Enumerable]] is present and has the value true, + then return false. + 1. If |descriptor|.\[[Writable]] is present and has the value false, + then return false. + 1. If |descriptor|.\[[Value]] is present, then return the result of + [=observable array exotic object/setting the length=] given |handler| and + |descriptor|.\[[Value]]. + 1. Return true. + 1. If |P| [=is an array index=], then: + 1. If [$IsAccessorDescriptor$](|descriptor|) is true, then return + false. + 1. If |descriptor|.\[[Configurable]] is present and has the value false, + then return false. + 1. If |descriptor|.\[[Enumerable]] is present and has the value false, + then return false. + 1. If |descriptor|.\[[Writable]] is present and has the value false, + then return false. + 1. If |descriptor|.\[[Value]] is present, then return the result of + [=observable array exotic object/setting the indexed value=] given |handler|, |P|, and + |descriptor|.\[[Value]]. + 1. Return true. + 1. Return [=?=] |O|.\[[DefineOwnProperty]](|P|, |descriptor|). +
+ +

deleteProperty

+ +
+ The steps for the deleteProperty proxy trap for + [=observable array exotic objects=], given |O| and |P|, are as follows: + + 1. Let |handler| be the this value. + 1. If |P| is "length", then return false. + 1. If |P| [=is an array index=], then: + 1. Let |oldLen| be |handler|.\[[BackingList]]'s [=list/size=]. + 1. Let |index| be [=!=] [$ToUint32$](|P|). + 1. If |index| ≠ |oldLen| − 1, then return + false. + 1. Perform the algorithm steps given by |handler|.\[[DeleteAlgorithm]], given + |handler|.\[[BackingList]][|index|] and |index|. + 1. [=list/Remove=] the last item from |handler|.\[[BackingList]]. + 1. Return true. + 1. Return [=?=] |O|.\[[Delete]](|P|). +
+ +

get

+ +
+ The steps for the get proxy trap for + [=observable array exotic objects=], given |O|, |P|, and |Receiver|, are as follows: + + 1. Let |handler| be the this value. + 1. Let |length| be |handler|.\[[BackingList]]'s [=list/size=]. + 1. If |P| is "length", then return |length|. + 1. If |P| [=is an array index=], then: + 1. Let |index| be [=!=] [$ToUint32$](|P|). + 1. If |index| ≥ |length|, then return undefined. + 1. Let |jsValue| be the result of [=converted to a JavaScript value|converting=] + |handler|.\[[BackingList]][|index|] to a JavaScript value. + 1. Assert: the above step never throws an exception. + 1. Return |jsValue|. + 1. Return [=?=] |O|.\[[Get]](|P|, |Receiver|). +
+ +

getOwnPropertyDescriptor

+ +
+ The steps for the getOwnPropertyDescriptor proxy trap for + [=observable array exotic objects=], given |O| and |P|, are as follows: + + 1. Let |handler| be the this value. + 1. Let |length| be |handler|.\[[BackingList]]'s [=list/size=]. + 1. If |P| is "length", then return [=!=] + [$FromPropertyDescriptor$](PropertyDescriptor{\[[Configurable]]: false, + \[[Enumerable]]: false, \[[Writable]]: true, + \[[Value]]: |length| }). + 1. If |P| [=is an array index=], then + 1. Let |index| be [=!=] [$ToUint32$](|P|). + 1. If |index| ≥ |length|, then return undefined. + 1. Let |jsValue| be the result of [=converted to a JavaScript value|converting=] + |handler|.\[[BackingList]][|index|] to a JavaScript value. + 1. Assert: the above step never throws an exception. + 1. Return [$FromPropertyDescriptor$](PropertyDescriptor{\[[Configurable]]: + true, \[[Enumerable]]: true, \[[Writable]]: + true, \[[Value]]: |jsValue| }). + 1. Return [$FromPropertyDescriptor$]([=?=] |O|.\[[GetOwnProperty]](|P|)). +
+ +

has

+ +
+ The steps for the has proxy trap for + [=observable array exotic objects=], given |O| and |P|, are as follows: + + 1. Let |handler| be the this value. + 1. If |P| is "length", then return true. + 1. If |P| [=is an array index=], then: + 1. Let |index| be [=!=] [$ToUint32$](|P|). + 1. If |index| < |handler|.\[[BackingList]]'s [=list/size=], then return + true. + 1. Return false. + 1. Return [=?=] |O|.\[[HasProperty]](|P|). +
+ +

ownKeys

+ +
+ The steps for the ownKeys proxy trap for + [=observable array exotic objects=], given |O|, are as follows: + + 1. Let |handler| be the this value. + 1. Let |length| be |handler|.\[[BackingList]]'s [=list/size=]. + 1. Let |keys| be an empty [=list=]. + 1. Let |i| be 0. + 1. [=While=] |i| < |length|: + 1. [=list/Append=] [=!=] [$ToString$](|i|) to |keys|. + 1. Set |i| to |i| + 1. + 1. [=list/Extend=] |keys| with [=!=] |O|.\[[OwnPropertyKeys]](). + 1. Return [$CreateArrayFromList$](|keys|). +
+ +

preventExtensions

+ +
+ The steps for the preventExtensions proxy trap for + [=observable array exotic objects=] are as follows: + + 1. Return false. +
+ +

set

+ +
+ The steps for the set proxy trap for + [=observable array exotic objects=], given |O|, |P|, |V|, and |Receiver|, are as follows: + + 1. Let |handler| be the this value. + 1. If |P| is "length", then return the result of + [=observable array exotic object/setting the length=] given |handler| and |V|. + 1. If |P| [=is an array index=], then return the result of + [=observable array exotic object/setting the indexed value=] given |handler|, |P|, and |V|. + 1. Return [=?=] |O|.\[[Set]](|P|, |V|, |Receiver|). +
+ +

Abstract operations

+ +
+ To set the length + of an observable array exotic object given |handler| and |newLen|: + + 1. Let |uint32Len| be [=?=] [$ToUint32$](|newLen|). + 1. Let |numberLen| be [=?=] [$ToNumber$](|newLen|). + 1. If |uint32Len| ≠ |numberLen|, then throw a {{RangeError}} exception. + 1. Let |oldLen| be |handler|.\[[BackingList]]'s [=list/size=]. + 1. If |uint32Len| > |oldLen|, then return false. + 1. Let |indexToDelete| be |oldLen| − 1. + 1. [=While=] |indexToDelete| ≥ |uint32Len|: + 1. Perform the algorithm steps given by |handler|.\[[DeleteAlgorithm]], given + |handler|.\[[BackingList]][|indexToDelete|] and |indexToDelete|. + 1. [=list/Remove=] the last item from |handler|.\[[BackingList]]. + 1. Set |indexToDelete| to |indexToDelete| − 1. + 1. Return true. +
+ +
+ To set the indexed value + of an observable array exotic object given |handler|, |P|, and |V|: + + 1. Let |oldLen| be |handler|.\[[BackingList]]'s [=list/size=]. + 1. Let |index| be [=!=] [$ToUint32$](|P|). + 1. If |index| > |oldLen|, return false. + 1. Let |idlValue| be the result of [=converted to an IDL value|converting=] + |V| to the type given by |handler|.\[[Type]]. + 1. If |index| < |oldLen|, then: + 1. Perform the algorithm steps given by |handler|.\[[DeleteAlgorithm]], given + |handler|.\[[BackingList]][|index|] and |index|. + 1. Perform the algorithm steps given by |handler|.\[[SetAlgorithm]], given |idlValue| and + |index|. + 1. If |index| = |oldLen|, then [=list/append=] |idlValue| to |handler|.\[[BackingList]]. + 1. Otherwise, set |handler|.\[[BackingList]][|index|] to |idlValue|. + 1. Return true. +
+ +

Callback interfaces

+ +As described in [[#idl-objects]], +[=callback interfaces=] can be +implemented in script by any JavaScript object. +The following cases explain how a [=callback interface=]'s [=operation=] is invoked on a given +object: + +* If the object is [=ECMAScript/callable=], then the implementation of the operation is the + callable object itself. +* Otherwise, the implementation of the operation is calling the result of invoking the + internal \[[Get]] method on the object with a property name that is the [=identifier=] of + the operation. + +Note that JavaScript objects need not have +properties corresponding to [=constants=] +on them to be considered as +implementing [=callback interfaces=] that happen +to have constants declared on them. + +A Web IDL arguments list is a [=list=] of values each of which is either an IDL value or +the special value “missing”, which represents a missing optional argument. + +
+ To convert a Web IDL arguments list to a + JavaScript arguments list, given a [=Web IDL arguments list=] |args|, perform the + following steps: + + 1. Let |jsArgs| be an empty [=list=]. + 1. Let |i| be 0. + 1. Let |count| be 0. + 1. While |i| < |args|'s [=list/size=]: + 1. If |args|[|i|] is the special value “missing”, then [=list/append=] + undefined to |jsArgs|. + 1. Otherwise, |args|[|i|] is an IDL value: + 1. Let |convertResult| be the result of [=converted to a JavaScript value|converting=] + |args|[|i|] to a JavaScript value. Rethrow any exceptions. + 1. [=list/Append=] |convertResult| to |jsArgs|. + 1. Set |count| to |i| + 1. + 1. Set |i| to |i| + 1. + 1. Truncate |jsArgs| to contain |count| items. + 1. Return |jsArgs|. +
+ +
+ + To call a user object's operation, + given a [=callback interface type=] value |value|, + operation name |opName|, [=Web IDL arguments list=] |args|, and optional + callback this value |thisArg|, + perform the following steps. + These steps will either return an IDL value or throw an exception. + + 1. Let |completion| be an uninitialized variable. + 1. If |thisArg| was not given, let |thisArg| be undefined. + 1. Let |O| be the JavaScript object corresponding to |value|. + 1. Let |realm| be |O|'s [=associated realm=]. + 1. Let |relevant settings| be |realm|'s [=realm/settings object=]. + 1. Let |stored settings| be |value|'s [=callback context=]. + 1. [=Prepare to run script=] with |relevant settings|. + 1. [=Prepare to run a callback=] with |stored settings|. + 1. Let |X| be |O|. + 1. If IsCallable(|O|) is false, then: + 1. Let |getResult| be Completion(Get(|O|, |opName|)). + 1. If |getResult| is an [=abrupt completion=], set |completion| + to |getResult| and jump to the step labeled return. + 1. Set |X| to |getResult|.\[[Value]]. + 1. If IsCallable(|X|) is false, + then set |completion| to [=Completion Record=] { \[[Type]]: throw, \[[Value]]: a + newly created {{TypeError}} object, \[[Target]]: empty }, and jump + to the step labeled return. + 1. Set |thisArg| to |O| (overriding the provided value). + 1. Let |jsArgs| be the result of [=Web IDL arguments list/converting=] |args| to a JavaScript + arguments list. If this throws an exception, set |completion| to the completion value + representing the thrown exception and jump to the step labeled + return. + 1. Let |callResult| be Completion(Call(|X|, |thisArg|, |jsArgs|)). + 1. If |callResult| is an [=abrupt completion=], set |completion| to + |callResult| and jump to the step labeled return. + 1. Set |completion| to the result of [=converted to an IDL value|converting=] + |callResult|.\[[Value]] to an IDL value of the same type as the operation's + return type. If this throws an exception, set |completion| to the completion value + representing the thrown exception. + 1. Return: at this + point |completion| will be set to an IDL value or an [=abrupt completion=]. + 1. [=Clean up after running a callback=] with |stored settings|. + 1. [=Clean up after running script=] with |relevant settings|. + 1. If |completion| is an IDL value, return |completion|. + 1. If |completion| is an [=abrupt completion=] and the operation has a [=return type=] + that is not a [=promise type=], throw |completion|.\[[Value]]. + 1. Let |rejectedPromise| be [=!=] Call({{%Promise.reject%}}, + {{%Promise%}}, «|completion|.\[[Value]]»). + 1. Return the result of [=converted to an IDL value|converting=] + |rejectedPromise| to the operation's return type. +
+ + +

Legacy callback interface object

+ +For every [=callback interface=] that is [=exposed=] in +a given [=realm=] +and on which [=constants=] are defined, +a corresponding property exists on the [=realm=]'s [=realm/global object=]. +The name of the property is the [=identifier=] of the [=callback interface=], +and its value is an object called the +legacy callback interface object. + +The [=legacy callback interface object=] for a given [=callback interface=] +is a [=built-in function object=]. +It has properties that correspond to the [=constants=] defined on that interface, +as described in sections [[#js-constants]]. + +Note: Since a [=legacy callback interface object=] is a [=function object=] +the typeof operator will return "function" +when applied to a [=legacy callback interface object=]. + +
+ + The [=legacy callback interface object=] for a given [=callback interface=] |interface| + with [=identifier=] |id| and in [=realm=] |realm| + is created as follows: + + 1. Let |steps| be the following steps: + 1. [=JavaScript/Throw=] a {{TypeError}}. + 1. Let |F| be CreateBuiltinFunction(|steps|, « », |realm|). + 1. Perform SetFunctionName(|F|, |id|). + 1. Perform SetFunctionLength(|F|, 0). + 1. [=Define the constants=] of |interface| on |F| given |realm|. + 1. Return |F|. +
+ + +

Invoking callback functions

+ +A JavaScript [=ECMAScript/callable=] object that is being +used as a [=callback function=] value is +called in a manner similar to how [=operations=] +on [=callback interface=] values are called (as +described in the previous section). + +
+ + To invoke a + [=callback function type=] value |callable| with a [=Web IDL arguments list=] |args|, + exception behavior |exceptionBehavior| (either "report" or "rethrow"), + and an optional [=callback this value|callback this value=] |thisArg|, + perform the following steps. + These steps will either return an IDL value or throw an exception. + + The |exceptionBehavior| argument must be supplied if, and only if, |callable|'s + [=return type=] is not a [=promise type=]. If |callable|'s return type is neither + {{undefined}} nor {{any}}, it must be "rethrow". + +
+ Until call sites are updated to respect this, specifications which fail to + provide a value here when it would be mandatory should be understood as + supplying "rethrow". +
+ + 1. Let |completion| be an uninitialized variable. + 1. If |thisArg| was not given, let |thisArg| be undefined. + 1. Let |F| be the JavaScript object corresponding to |callable|. + 1. If IsCallable(|F|) is false: + 1. Note: This is only possible when the [=callback function=] came from an attribute + marked with [{{LegacyTreatNonObjectAsNull}}]. + 1. Return the result of [=converted to an IDL value|converting=] + undefined to the callback function's return type. + 1. Let |realm| be |F|'s [=associated realm=]. + 1. Let |relevant settings| be |realm|'s [=realm/settings object=]. + 1. Let |stored settings| be |callable|'s [=callback context=]. + 1. [=Prepare to run script=] with |relevant settings|. + 1. [=Prepare to run a callback=] with |stored settings|. + 1. Let |jsArgs| be the result of [=Web IDL arguments list/converting=] |args| to a JavaScript + arguments list. If this throws an exception, set |completion| to the completion value + representing the thrown exception and jump to the step labeled + return. + 1. Let |callResult| be Completion(Call(|F|, |thisArg|, |jsArgs|)). + 1. If |callResult| is an [=abrupt completion=], set |completion| to + |callResult| and jump to the step labeled return. + 1. Set |completion| to the result of [=converted to an IDL value|converting=] + |callResult|.\[[Value]] to an IDL value of the same type as |callable|'s + return type. If this throws an exception, set |completion| to the completion value + representing the thrown exception. + 1. Return: at this + point |completion| will be set to an IDL value or an [=abrupt completion=]. + 1. [=Clean up after running a callback=] with |stored settings|. + 1. [=Clean up after running script=] with |relevant settings|. + 1. If |completion| is an IDL value, return |completion|. + 1. [=Assert=]: |completion| is an [=abrupt completion=]. + 1. If |exceptionBehavior| is "rethrow", throw |completion|.\[[Value]]. + 1. Otherwise, if |exceptionBehavior| is "report": + 1. [=Assert=]: |callable|'s [=return type=] is {{undefined}} or {{any}}. + 1. [=Report an exception=] |completion|.\[[Value]] for |realm|'s [=realm/global object=]. + 1. Return the unique {{undefined}} IDL value. + 1. [=Assert=]: |callable|'s [=return type=] is a [=promise type=]. + 1. Let |rejectedPromise| be [=!=] Call({{%Promise.reject%}}, + {{%Promise%}}, «|completion|.\[[Value]]»). + 1. Return the result of [=converted to an IDL value|converting=] + |rejectedPromise| to the callback function's return type. +
+ +Some callback functions are instead used as [=constructors=]. Such callback functions must not have +a return type that is a [=promise type=]. + +
+ + To construct a + [=callback function type=] value |callable| with a [=Web IDL arguments list=] |args|, + perform the following steps. + These steps will either return an IDL value or throw an exception. + + 1. Let |completion| be an uninitialized variable. + 1. Let |F| be the JavaScript object corresponding to |callable|. + 1. If IsConstructor(|F|) is false, throw a + {{TypeError}} exception. + 1. Let |realm| be |F|'s [=associated realm=]. + 1. Let |relevant settings| be |realm|'s [=realm/settings object=]. + 1. Let |stored settings| be |callable|'s [=callback context=]. + 1. [=Prepare to run script=] with |relevant settings|. + 1. [=Prepare to run a callback=] with |stored settings|. + 1. Let |jsArgs| be the result of [=Web IDL arguments list/converting=] |args| to a JavaScript + arguments list. If this throws an exception, set |completion| to the completion value + representing the thrown exception and jump to the step labeled + return. + 1. Let |callResult| be Completion(Construct(|F|, |jsArgs|)). + 1. If |callResult| is an [=abrupt completion=], set |completion| to + |callResult| and jump to the step labeled return. + 1. Set |completion| to the result of [=converted to an IDL value|converting=] + |callResult|.\[[Value]] to an IDL value of the same type as |callable|'s + return type. If this throws an exception, set |completion| to the completion value + representing the thrown exception. + 1. Return: at this + point |completion| will be set to an IDL value or an [=abrupt completion=]. + 1. [=Clean up after running a callback=] with |stored settings|. + 1. [=Clean up after running script=] with |relevant settings|. + 1. If |completion| is an [=abrupt completion=], throw |completion|.\[[Value]]. + 1. Return |completion|. +
+ + +

Namespaces

+ +For every [=namespace=] that is [=exposed=] in a given [=realm=], +a corresponding property exists on the [=realm=]'s [=realm/global object=]. +The name of the property is the [=identifier=] of the namespace, and its value is an object +called the namespace object. + +The characteristics of a namespace object are described in [[#namespace-object]]. + + +

Namespace object

+ +
+ + The namespace object for a given [=namespace=] |namespace| and [=realm=] |realm| + is created as follows: + + 1. Let |namespaceObject| be [$OrdinaryObjectCreate$](|realm|.\[[Intrinsics]].[[{{%Object.prototype%}}]]). + 1. [=Define the regular attributes=] of |namespace| on |namespaceObject| given |realm|. + 1. [=Define the regular operations=] of |namespace| on |namespaceObject| given |realm|. + 1. [=Define the constants=] of |namespace| on |namespaceObject| given |realm|. + 1. For each [=exposed=] [=interface=] |interface| which has the [{{LegacyNamespace}}] extended + attribute with the identifier of |namespace| as its argument, + 1. Let |id| be |interface|'s [=identifier=]. + 1. Let |interfaceObject| be the result of [=create an interface object|creating an + interface object=] for |interface| with |id| in |realm|. + 1. Perform [$DefineMethodProperty$](|namespaceObject|, |id|, |interfaceObject|, false). + 1. Return |namespaceObject|. +
+ +The [=class string=] of a [=namespace object=] is the [=namespace=]'s [=identifier=]. + + +

Exceptions

+ +

{{DOMException}} custom bindings

+ +In the JavaScript binding, the [=interface prototype object=] for {{DOMException}} +has its \[[Prototype]] [=/internal slot=] set to the intrinsic object {{%Error.prototype%}}, +as defined in the [=create an interface prototype object=] abstract operation. + +Additionally, if an implementation gives native {{Error}} objects special powers or +nonstandard properties (such as a stack property), +it should also expose those on {{DOMException}} objects. + +

Exception objects

+ +[=Simple exceptions=] are represented +by native JavaScript objects of the corresponding type. + +A {{DOMException}} is represented by a +[=platform object=] that implements the {{DOMException}} interface. + + +

Creating and throwing exceptions

+ + +
+ To [=exception/create=] a [=simple exception=] of type |T|: + + 1. Let |message| be an [=implementation-defined=] message appropriate for the exceptional + situation. The calling specification may contain information to to help implementations + construct this message. + + Implementations need to be cautious not to leak sensitive or secured information when + constructing this message, e.g., by including the URL of a cross-origin frame, or + information which could identify the user. + + 1. Let |args| be « |message| ». + + 1. Let |constructor| be [=current realm=].\[[Intrinsics]].[[%|T|%]]. + + 1. Return [=!=] [$Construct$](|constructor|, |args|). +
+ +
+ To [=exception/create=] a {{DOMException}} given a string |name|: + + 1. Assert: |name| appears in the DOMException names table. + + 1. Let |ex| be a [=new=] {{DOMException}} created in the [=current realm=]. + + 1. Set |ex|'s [=DOMException/name=] to |name|. + + 1. Set |ex|'s [=DOMException/message=] to an [=implementation-defined=] message appropriate for + the exceptional situation. The calling specification may contain information to to help + implementations construct this message. + + Implementations need to be cautious not to leak sensitive or secured information when + constructing this message, e.g., by including the URL of a cross-origin frame, or + information which could identify the user. + + 1. Return |ex|. +
+ +
+ To [=exception/create=] a {{DOMException}} derived interface given the [=interface=] + [=identifier=] |type| and additional initialization instructions: + + 1. Let |ex| be a [=new=] instance of the [=interface=] identified by |type|, created in the + [=current realm=]. + + 1. Set |ex|'s [=DOMException/name=] to |type|. + + 1. Set |ex|'s [=DOMException/message=] to an [=implementation-defined=] message appropriate for + the exceptional situation. The calling specification may contain information to to help + implementations construct this message. + + Implementations need to be cautious not to leak sensitive or secured information when + constructing this message, e.g., by including the URL of a cross-origin frame, or + information which could identify the user. + + 1. Perform any additional initialization on |ex| as described by the caller. + + 1. Return |ex|. +
+ +
+ To [=exception/throw=] an [=exception=]: + + 1. Let |O| be the result of [=exception/create|creating an exception=] with the same + arguments. + 1. Throw |O|. +
+ +
+ + The above algorithms restrict [=Exception objects|objects representing exceptions=] propagating + out of a [=function object=] to be ones that are associated with the [=realm=] of that + [=function object=] (i.e., the [=current realm=] at the time the function + executes). For example, consider the IDL: + +
+        [Exposed=Window]
+        interface MathUtils {
+          // If x is negative, throws a "NotSupportedError" DOMException.
+          double computeSquareRoot(double x);
+        };
+    
+ + If we apply computeSquareRoot to a MathUtils + object from a different [=realm=], then the exception thrown will be from the [=realm=] of the + method, not the object it is applied to: + +
+        const myMU = window.getMathUtils();          // A MathUtils object from this realm
+        const otherMU = otherWindow.getMathUtils();  // A MathUtils object from a different realm
+
+        myMU instanceof Object;                      // Evaluates to true.
+        otherMU instanceof Object;                   // Evaluates to false.
+        otherMU instanceof otherWindow.Object;       // Evaluates to true.
+
+        try {
+          otherMU.doComputation.call(myMU, -1);
+        } catch (e) {
+          console.assert(!(e instanceof DOMException));
+          console.assert(e instanceof otherWindow.DOMException);
+        }
+    
+
+ + +

Handling exceptions

+ +Unless specified otherwise, +whenever JavaScript runtime semantics are invoked due +to requirements in this document and +end due to an exception being thrown, that exception +must propagate to the caller, and if +not caught there, to its caller, and so on. + +Per [[#conventions]], an algorithm specified in this document may intercept thrown exceptions, either by specifying +the exact steps to take if an exception was thrown, or by explicitly handling [=abrupt completions=]. + +
+ + The following [=IDL fragment=] + defines two [=interfaces=] + and an [=exception=]. + The valueOf attribute on ExceptionThrower + is defined to throw an exception whenever an attempt is made + to get its value. + +
+        [Exposed=Window]
+        interface Dahut {
+          attribute DOMString type;
+        };
+
+        [Exposed=Window]
+        interface ExceptionThrower {
+          // This attribute always throws a NotSupportedError and never returns a value.
+          attribute long valueOf;
+        };
+    
+ + Assuming a JavaScript implementation supporting this interface, + the following code demonstrates how exceptions are handled: + +
+        var d = getDahut();              // Obtain an instance of Dahut.
+        var et = getExceptionThrower();  // Obtain an instance of ExceptionThrower.
+
+        try {
+          d.type = { toString: function() { throw "abc"; } };
+        } catch (e) {
+          // The string "abc" is caught here, since as part of the conversion
+          // from the native object to a string, the anonymous function
+          // was invoked, and none of the [[DefaultValue]], ToPrimitive or
+          // ToString algorithms are defined to catch the exception.
+        }
+
+        try {
+          d.type = { toString: { } };
+        } catch (e) {
+          // An exception is caught here, since an attempt is made to invoke
+          // [[Call]] on the native object that is the value of toString
+          // property.
+        }
+
+        try {
+          d.type = Symbol();
+        } catch (e) {
+          // An exception is caught here, since an attempt is made to invoke
+          // the JavaScript ToString abstract operation on a Symbol value.
+        }
+
+        d.type = et;
+        // An uncaught "NotSupportedError" DOMException is thrown here, since the
+        // [[DefaultValue]] algorithm attempts to get the value of the
+        // "valueOf" property on the ExceptionThrower object.  The exception
+        // propagates out of this block of code.
+    
+
+ + +

Common definitions

+ +This section specifies some common definitions that all +[=conforming implementations=] +must support. + + +

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;
+
+ +The {{ArrayBufferView}} typedef is used to represent +objects that provide a view on to an {{ArrayBuffer}} or +{{SharedArrayBuffer}} (when [{{AllowShared}}] is used). + + +

BufferSource

+ +
typedef (ArrayBufferView or ArrayBuffer) BufferSource;
+ +The {{BufferSource}} typedef is used to represent objects +that are either themselves an {{ArrayBuffer}} or which +provide a view on to an {{ArrayBuffer}}. + +Note: [{{AllowShared}}] cannot be used with {{BufferSource}} as {{ArrayBuffer}} does not support it. +Use {{AllowSharedBufferSource}} instead. + + +

AllowSharedBufferSource

+ +
typedef (ArrayBuffer or SharedArrayBuffer or [AllowShared] ArrayBufferView) AllowSharedBufferSource;
+ +The {{AllowSharedBufferSource}} typedef is used to represent objects +that are either themselves an {{ArrayBuffer}} or {{SharedArrayBuffer}} or which +provide a view on to an {{ArrayBuffer}} or {{SharedArrayBuffer}}. + + +

DOMException

+ +The {{DOMException}} type is an [=interface type=] defined by the following IDL +fragment: + +
+[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;
+};
+
+ +Note: as discussed in [[#js-DOMException-specialness]], the JavaScript binding imposes additional +requirements beyond the normal ones for [=interface types=]. + +Each {{DOMException}} object has an associated name and +message, both [=strings=]. + +The +new DOMException(|message|, |name|) +constructor steps are: + +1. Set [=this=]'s [=DOMException/name=] to |name|. +1. Set [=this=]'s [=DOMException/message=] to |message|. + +The name getter steps are to return +[=this=]'s [=DOMException/name=]. + +The message getter steps are to +return [=this=]'s [=DOMException/message=]. + +The code getter steps are to return the legacy +code indicated in the DOMException names table for [=this=]'s +[=DOMException/name=], or 0 if no such entry exists in the table. + +{{DOMException}} objects are [=serializable objects=]. + +Their [=serialization steps=], given value and serialized, are: + +
    +
  1. Set serialized.\[[Name]] to value's [=DOMException/name=].
  2. +
  3. Set serialized.\[[Message]] to value's [=DOMException/message=].
  4. +
  5. User agents should attach a serialized representation of any interesting accompanying data + which are not yet specified, notably the stack property, to + serialized.
  6. +
+ +Their [=deserialization steps=], given value and serialized, are: + +
    +
  1. Set value's [=DOMException/name=] to serialized.\[[Name]].
  2. +
  3. Set value's [=DOMException/message=] to serialized.\[[Message]].
  4. +
  5. If any other data is attached to serialized, then deserialize and attach it to + value.
  6. +
+ +

Function

+ +
callback Function = any (any... arguments);
+ +The {{Function}} [=callback function=] +type is used for representing function values with no restriction on what arguments +are passed to it or what kind of value is returned from it. + + +

VoidFunction

+ +
callback VoidFunction = undefined ();
+ +The {{VoidFunction}} [=callback function=] +type is used for representing function values that take no arguments and do not +return any value. + + +

Extensibility

+ +This section is informative. + +Extensions to language binding requirements can be specified +using [=extended attributes=] +that do not conflict with those defined in this document. Extensions for +private, project-specific use ought not be included in +[=IDL fragments=] +appearing in other specifications. It is recommended that extensions +that are required for use in other specifications be coordinated +with the group responsible for work on Web IDL, which +at the time of writing is the +W3C Web Platform Working Group, +for possible inclusion in a future version of this document. + +Extensions to any other aspect of the IDL language are +strongly discouraged. + + +

Legacy constructs

+ +This section is informative. + +Legacy Web IDL constructs exist only so that +legacy Web platform features can be specified. +They are generally prefixed with the "Legacy" string. +It is strongly discouraged to use legacy Web IDL constructs in specifications +unless required to specify the behavior of legacy Web platform features, +or for consistency with such features. +Editors who wish to use legacy Web IDL constructs are strongly advised to discuss this +by filing an issue +before proceeding. + +Marking a construct as legacy does not, in itself, +imply that it is about to be removed from this specification. +It does suggest however, that it is a good candidate +for future removal from this specification, +whenever various heuristics indicate that +the Web platform features it helps specify can be removed altogether +or can be modified to rely on non-legacy Web IDL constructs instead. + + +

Referencing this specification

+ +This section is informative. + +It is expected that other specifications that define Web platform interfaces +using one or more [=IDL fragments=] +will reference this specification. It is suggested +that those specifications include a sentence such as the following, +to indicate that the IDL is to be interpreted as described in this +specification: + +
+ + The IDL fragment in Appendix A of this specification must, in + conjunction with the IDL fragments defined in this specification's normative references, + be interpreted as required for conforming sets of IDL fragments, as described in the + “Web IDL” specification. \[WEBIDL] + +
+ +In addition, it is suggested that the conformance class for user +agents in referencing specifications be linked to the +[=conforming implementation=] class from this specification: + +
+ + A conforming FooML user agent must also be a + conforming implementation of the IDL fragment in Appendix A + of this specification, as described in the + “Web IDL” specification. \[WEBIDL] + +
+ + +

Privacy and Security Considerations

+ +This specification defines a conversion layer between JavaScript and IDL values. An incorrect +implementation of this layer can lead to security issues. + +This specification also provides the ability to use JavaScript values directly, through the +{{any}} and {{object}} IDL types. These values need to be handled carefully to avoid security +issues. In particular, user script can run in response to nearly any manipulation of these values, +and invalidate the expectations of specifications or implementations using them. + +This specification makes it possible to interact with {{SharedArrayBuffer}} objects, which can be +used to build timing attacks. Specifications that use these objects need to consider such attacks. + + +

Acknowledgments

+ +This section is informative. + +The editors would like to thank the following people for contributing +to this specification: +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 and, +Collin Xu. + +Special thanks also go to Sam Weinig for maintaining this document +while the editor was unavailable to do so. + +This standard is written by Edgar Chen (Mozilla, +echen@mozilla.com) and Tiancheng "Timothy" Gu +(timothygu99@gmail.com) with substantial contributions from +Boris Zbarsky (bzbarsky@mit.edu), +Cameron McCormack (cam@mcc.id.au), +and Tobie Langel +(tobie@unlockopen.com). + + +

IDL grammar

+ +This section defines an LL(1) grammar whose start symbol, +Definitions, matches an entire [=IDL fragment=]. + +Each production in the grammar has on its right hand side either a +non-zero sequence of terminal and non-terminal symbols, or an +epsilon (ε) which indicates no symbols. +Symbols that begin with an uppercase letter are non-terminal symbols. +Symbols in monospaced fonts are terminal symbols. +Symbols in sans-serif font that begin with a lowercase letter are terminal +symbols that are matched by the regular expressions (using Perl 5 regular +expression syntax [[!PERLRE]]) as follows: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
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]/
+ +The tokenizer operates on a sequence of [=scalar values=]. +When tokenizing, the longest possible match must be used. For example, if the input +text is “a1”, it is tokenized as a single identifier, +and not as a separate identifier and integer. +If the longest possible match could match one of the above named terminal symbols or +one of the other terminal symbols from the grammar, it must be tokenized as the latter. +Thus, the input text “long” is tokenized as the terminal symbol +long rather than an identifier called "long", +and “.” is tokenized as the terminal symbol +. rather than an other. + +The IDL syntax is case sensitive, both for the monospaced terminal symbols +used in the grammar and the values used for +identifier terminals. Thus, for +example, the input text “Const” is tokenized as +an identifier rather than the +terminal symbol const, an +[=interface=] with +[=identifier=] +"A" is distinct from one named "a", and an +[=extended attribute=] +[legacyfactoryfunction] will not be recognized as +the [{{LegacyFactoryFunction}}] +extended attribute. + +Implicitly, any number of whitespace and +comment terminals are allowed between every other terminal +in the input text being parsed. Such whitespace and +comment terminals are ignored while parsing. + +The following LL(1) grammar, starting with Definitions, +matches an [=IDL fragment=]: + +
+ +Note: The Other +non-terminal matches any single terminal symbol except for +(, ), +[, ], +{, } +and ,. + +While the ExtendedAttribute +non-terminal matches any non-empty sequence of terminal symbols (as long as any +parentheses, square brackets or braces are balanced, and the +, token appears only within those balanced brackets), +only a subset of those +possible sequences are used by the [=extended attributes=] +defined in this specification — see +[[#idl-extended-attributes]] +for the syntaxes that are used by these extended attributes. + + +

Document conventions

+ +The following typographic conventions are used in this document: + +* Defining instances of terms: example term +* Links to terms defined in this document or elsewhere: [=example term=] +* Grammar terminals: sometoken +* Grammar non-terminals: ExampleGrammarNonTerminal +* Grammar symbols: identifier +* IDL types: {{unsigned long}} +* JavaScript classes: {{Map}} +* JavaScript language types: Object +* Code snippets: a = b + obj.f() +* Scalar values: U+0030 (0) +* Extended attributes: [ExampleExtendedAttribute] +* Variable names in prose and algorithms: exampleVariableName. +* IDL informal syntax examples: +
+        [extended_attributes]
+        interface identifier {
+          /* interface_members... */
+        };
+    
+ + (Specific parts of the syntax discussed in surrounding prose are highlighted.) +* IDL grammar snippets: +
+        ExampleGrammarNonTerminal :
+            OtherNonTerminal "sometoken"
+            other AnotherNonTerminal
+            ε  // nothing
+    
+* Non-normative notes: + + Note: This is a note. + +* Non-normative examples: +
+ This is an example. +
+* Normative warnings: +

+ This is a warning. +

+* Code blocks: +
+        // This is an IDL code block.
+        [Exposed=Window]
+        interface Example {
+          attribute long something;
+        };
+    
+
+        // This is a JavaScript code block.
+        window.onload = function() { window.alert("loaded"); };
+    
+ +The following conventions are used in the algorithms in this document: + +* Algorithms use the [=ECMAScript/conventions=] of the JavaScript specification, + including the [=!=] and [=?=] notation for unwrapping [=Completion Records=]. +* Algorithms sometimes treat returning/throwing values and returning [=Completion Records=] + interchangeably. That is, an algorithm that uses return/throw terminology may be treated as + returning a [=Completion Record=], while one that returns a [=Completion Record=] may be treated as + returning a value or throwing an exception. Similarly, to catch exceptions, defining the + behavior to adopt when [=an exception was thrown=] and checking if the [=Completion Record=]'s + \[[Type]] field is “throw” are equivalent. +* [=Completion Records=] are extended by allowing them to contain values that are not JavaScript + values, such as Web IDL values. + + +

Conformance

+ +Everything in this specification is normative except for diagrams, +examples, notes and sections marked as being informative. + +This specification depends on the Infra Standard. [[!INFRA]] + +The following conformance classes are defined by this specification: + + : conforming set of IDL fragments + :: A set of [=IDL fragments=] is considered + to be a [=conforming set of IDL fragments=] if, taken together, they satisfy all of the + must-, + required- and shall-level + criteria in this specification that apply to IDL fragments. + : conforming implementation + :: A user agent is considered to be a + [=conforming implementation=] + relative to a [=conforming set of IDL fragments=] if it satisfies all of the must-, + required- and shall-level + criteria in this specification that apply to implementations for all language + bindings that the user agent supports. + : conforming JavaScript implementation + :: A user agent is considered to be a + [=conforming JavaScript implementation=] + relative to a [=conforming set of IDL fragments=] if it satisfies all of the must-, + required- and shall-level + criteria in this specification that apply to implementations for the JavaScript + language binding. + + +

This Living Standard includes material copied from W3C's +WebIDL [sic] Level 1, +which is available under the +W3C Software and Document License. + + +