W3C

Web IDL (Second Edition)

W3C Editor’s Draft 11 September 2014

This Version:
http://heycam.github.io/webidl/
Latest Version:
http://www.w3.org/TR/WebIDL/
Previous Versions:
http://www.w3.org/TR/2012/CR-WebIDL-20120419/
http://www.w3.org/TR/2012/WD-WebIDL-20120207/
http://www.w3.org/TR/2011/WD-WebIDL-20110927/
http://www.w3.org/TR/2011/WD-WebIDL-20110712/
http://www.w3.org/TR/2010/WD-WebIDL-20101021/
http://www.w3.org/TR/2008/WD-WebIDL-20081219/
http://www.w3.org/TR/2008/WD-WebIDL-20080829/
http://www.w3.org/TR/2008/WD-DOM-Bindings-20080410/
http://www.w3.org/TR/2007/WD-DOM-Bindings-20071017/
Participate:
Send feedback to public-script-coord@w3.org or file a bug (open bugs)
Editor:
Cameron McCormack, Mozilla Corporation <cam@mcc.id.au>

Abstract

This document 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 ECMAScript execution environments is also detailed in this document. It is expected that this document acts as a guide to implementors of already-published specifications, and that newly published specifications reference this document to ensure conforming implementations of interfaces are interoperable.

Status of This Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document is the 11 September 2014 Editor’s Draft of the Web IDL (Second Edition) specification. Please send comments about this document to public-script-coord@w3.org (archived).

This is the Second Edition of Web IDL, branched off from the Candidate Recommendation of the First Edition. This Second Edition includes new features that could not have been added to the First Edition without delaying its progress along the Recommendation track.

This document is produced by the Web Applications Working Group, part of the Rich Web Clients Activity in the W3C Interaction Domain. Changes made to this document can be found in the specification’s commit log on GitHub: recent changes, older changes.

There is a bug tracker for the specification.

Publication as an Editor’s Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

Table of Contents

1. Introduction

This section is informative.

Technical reports published by the W3C that include programming language interfaces have typically been described using the Object Management Group’s Interface Definition Language (IDL) [OMGIDL]. The IDL provides a means to describe these interfaces in a language independent manner. Usually, additional language binding appendices are included in such documents which detail how the interfaces described with the IDL correspond to constructs in the given language.

However, the bindings in these specifications for the language most commonly used on the web, ECMAScript, are consistently specified with low enough precision as to result in interoperability issues. In addition, each specification must describe the same basic information, such as DOM interfaces described in IDL corresponding to properties on the ECMAScript global object, or the unsigned long IDL type mapping to the Number type in ECMAScript.

This specification defines an IDL language similar to OMG IDL for use by specifications that define interfaces for Web APIs. A number of extensions are given to the IDL to support common functionality that previously must have been written in prose. In addition, precise language bindings for ECMAScript Edition 6 are given.

1.1. Typographic conventions

The following typographic conventions are used in this document:

  • Defining instances of terms: example term
  • Links to terms defined in this document: example term
  • Links to terms defined in other documents: example term
  • Grammar symbols: ExampleGrammarSymbol
  • IDL and ECMAScript types: ExampleType
  • Code snippets: a = b + obj.f()
  • Unicode characters: U+0030 DIGIT ZERO ("0")
  • Extended attributes: [ExampleExtendedAttribute]
  • Variable names in prose and algorithms: exampleVariableName.
  • IDL informal syntax examples:
    interface identifier {
      interface-members…
    };
    (Red text is used to highlight specific parts of the syntax discussed in surrounding prose.)
  • IDL grammar snippets:
    [5]ExampleGrammarSymbolOtherSymbol "sometoken"
     | AnotherSymbol
     | ε  // nothing
    (Each grammar rule is assigned a number for reference, shown on the left.)
  • Non-normative notes:
    Note

    This is a note.

  • Non-normative examples:
    Example

    This is an example.

  • Normative warnings:
    Warning

    This is a warning.

  • Code blocks:
    IDL
    // This is an IDL code block.
    interface Example {
      attribute long something;
    };
    ECMAScript
    // This is an ECMAScript code block.
    window.onload = function() { window.alert("loaded"); };

2. Conformance

Everything in this specification is normative except for diagrams, examples, notes and sections marked as being informative.

The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY” and “OPTIONAL” in this document are to be interpreted as described in Key words for use in RFCs to Indicate Requirement Levels [RFC2119].

The following conformance classes are defined by this specification:

conforming IDL fragment

An IDL fragment is considered to be a conforming IDL fragment if it satisfies 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 IDL fragment 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 ECMAScript implementation

A user agent is considered to be a conforming ECMAScript implementation relative to a conforming IDL fragment if it satisfies all of the MUST-, REQUIRED- and SHALL-level criteria in this specification that apply to implementations for the ECMAScript language binding.

3. 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 Appendix A 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 definitions, dictionaries, partial dictionary definitions, exceptions, typedefs and implements 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 section 3.11, while those specific to the ECMAScript language binding are discussed in section 4.3.

[extended-attributes]
interface identifier {
  interface-members…
};
[1]DefinitionsExtendedAttributeList Definition Definitions
 | ε
[2]DefinitionCallbackOrInterface
 | Partial
 | Dictionary
 | Exception
 | Enum
 | Typedef
 | ImplementsStatement
[3]CallbackOrInterface"callback" CallbackRestOrInterface
 | Interface
Example

The following is an example of an IDL fragment.

IDL
exception GraphicsException {
  DOMString reason;
};

interface Paint { };

interface SolidColor : Paint {
  attribute float red;
  attribute float green;
  attribute float blue;
};

interface Pattern : Paint {
  attribute DOMString imageURL;
};

[Constructor]
interface GraphicalWindow {
  readonly attribute unsigned long width;
  readonly attribute unsigned long height;

  attribute Paint currentPaint;

  void drawRectangle(float x, float y, float width, float height);

  void drawText(float x, float y, DOMString text);
};

Here, four interfaces and one exception 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 ECMAScript, the attributes on the IDL interfaces will be exposed as accessor properties and the operations as Function-valued data properties on a prototype object for all GraphicalWindow objects; each ECMAScript object that implements GraphicalWindow will have that prototype object in its prototype chain.

The [Constructor] that appears on GraphicalWindow is an extended attribute. This extended attribute causes a constructor to exist in ECMAScript implementations, so that calling new GraphicalWindow() would return a new object that implemented the interface.

3.1. Names

Every interface, partial interface definition, dictionary, partial dictionary definition, exception, enumeration, callback function and typedef (together called named definitions) and every constant, attribute, exception field 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, dictionary, exception, enum or callback keyword determines the identifier of that definition.
    interface interface-identifier { interface-members… };
    partial interface interface-identifier { interface-members… };
    exception exception-identifier { exception-members… };
    dictionary dictionary-identifier { dictionary-members… };
    partial dictionary dictionary-identifier { dictionary-members… };
    enum enumeration-identifier { enumeration-values… };
    callback callback-identifier = callback-signature;
  • For attributes, typedefs, exception fields and dictionary members, the final identifier token before the semicolon at the end of the declaration determines the identifier.
    interface identifier {
      attribute type attribute-identifier;
    };
    
    typedef type typedef-identifier;
    
    exception identifier {
      type exception-member-identifier;
    };
    
    dictionary identifier {
      type dictionary-member-identifier;
    };
  • For constants, the identifier token before the equals sign determines the identifier.
    const type constant-identifier = value;
  • 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 OptionalIdentifier 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.
    return-type operation-identifier(arguments…);
Note

Operations can have no identifier when they are being used to declare a 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 LOW LINE ("_") character (underscore) removed.

Note

A leading "_" 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 "_" 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.

return-type operation-identifier(argument-type argument-identifier, …);
[72]ArgumentNameKeyword "attribute"
 | "callback"
 | "const"
 | "creator"
 | "deleter"
 | "dictionary"
 | "enum"
 | "exception"
 | "getter"
 | "implements"
 | "inherit"
 | "interface"
 | "legacycaller"
 | "partial"
 | "required"
 | "serializer"
 | "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 LOW LINE ("_") character (underscore) 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 MUST NOT be “constructor”, “iterator”, “toString”, “toJSON”, or begin with a U+005F LOW LINE ("_") character. These are known as reserved identifiers.

Note

Further restrictions on identifier names for particular constructs may be made in later sections.

Within the set of IDL fragments that a given implementation supports, the identifier of every interface, dictionary, exception, enumeration, callback function and typedef MUST NOT be the same as the identifier of any other interface, dictionary, exception, enumeration, callback function 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.

Example

Therefore, the following IDL fragment is valid:

IDL
interface B : A {
  void f(ArrayOfLongs x);
};

interface A {
};

typedef long[] ArrayOfLongs;
Example

The following IDL fragment demonstrates how identifiers are given to definitions, interface members and exception members.

IDL
// Typedef identifier: "number"
typedef float number;

// Exception identifier: "FrameworkException"
exception FrameworkException {

  // Constant identifier: "ERR_NOT_FOUND"
  const long ERR_NOT_FOUND = 1;

  // Exception field identifier: "code"
  long code;
};

// Interface identifier: "System"
interface System {

  // Operation identifier:          "createObject"
  // Operation argument identifier: "interface"
  object createObject(DOMString _interface);

  // Operation argument identifier: "interface"
  object[] createObjectArray(DOMString interface);

  // Operation has no identifier; it declares a getter.
  getter DOMString (DOMString keyName);
};

// Interface identifier: "TextField"
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.

3.2. 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 or "callback" Interface) that declares some state and behavior that an object implementing that interface will expose.

interface identifier {
  interface-members…
};

An interface is a specification of a set of interface members (matching InterfaceMembers), which are the constants, attributes and operations that appear between the braces in the interface declaration. Attributes describe the state that an object implementing the interface 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.

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 COLON (":") character 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 no significance except in the case of overloading.

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.

Example

Consider the following two interfaces.

IDL
interface A {
  void f();
  void g();
};

interface B : A {
  void f();
  void g(DOMString x);
};

In the ECMAScript 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 ECMAScript 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 inherit from another interface, then the set is empty. Otherwise, the set includes the interface B that A 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.

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 implements statement can be used to define that objects implementing an interface will always also implement another interface.

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.

interface identifier {

  [extended-attributes]
  const type identifier = value;

  [extended-attributes]
  attribute type identifier;

  [extended-attributes]
  return-type identifier(arguments…);
};

A callback interface is an interface that uses the callback keyword at the start of its definition. Callback interfaces are ones that can be implemented by user objects and not by platform objects, as described in section 3.9 below.

callback interface identifier {
  interface-members…
};
Note

See also the similarly named callback function definition.

Callback interfaces MUST NOT inherit from any non-callback interfaces, and non-callback interfaces MUST NOT inherit from any callback interfaces. Callback interfaces MUST NOT have any consequential interfaces.

Static attributes and static operations MUST NOT be defined on a callback interface.

Warning

Specification authors SHOULD NOT define callback interfaces that have only a single operation, 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 user 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 ECMAScript language binding).

Editorial note

Perhaps this warning shouldn't apply if you are planning to extend the callback interface in the future. That's probably a good reason to start off with a single operation callback interface.

Editorial note

I think we need to support operations not being implemented on a given user object implementing a callback interface. If specs extending an existing callback interface, we probably want to be able to avoid calling the operations that aren't implemented (and having some default behavior instead). So we should perhaps define a term that means whether the operation is implemented, which in the ECMAScript binding would correspond to checking for the property's existence.

Note

Specification authors wanting to define APIs that take ECMAScript objects as “property bag” like function arguments are suggested to use dictionary types rather than callback interfaces.

For example, instead of this:

IDL
callback interface Options {
  attribute DOMString? option1;
  attribute DOMString? option2;
  attribute long? option3;
};

interface A {
  void doTask(DOMString type, Options options);
};

to be used like this:

ECMAScript
var a = getA();  // Get an instance of A.

a.doTask("something", { option1: "banana", option3: 100 });

instead write the following:

IDL
dictionary Options {
  DOMString? option1;
  DOMString? option2;
  long? option3;
};

interface A {
  void doTask(DOMString type, Options options);
};

The IDL for interfaces can be split into multiple parts by using partial interface definitions (matching "partial" PartialInterface). 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 inherits from another interface. Inheritance must be specified on the original interface definition.

Extended attributes can be specified on partial interface definitions, with some limitations. The following extended attributes MUST NOT be specified on partial interface definitions: [ArrayClass], [Constructor], [ImplicitThis], [MapClass], [NamedConstructor], [NoInterfaceObject].

Note

The above list of extended attributes is all of those defined in this document that are applicable to interfaces except for [Exposed], [Global], [OverrideBuiltins], [PrimaryGlobal] and [Unforgeable].

Any extended attribute specified on a partial interface definition is considered to appear on the interface itself.

The relevant language binding determines how interfaces correspond to constructs in the language.

The following extended attributes are applicable to interfaces: [ArrayClass], [Constructor], [Exposed], [Global], [ImplicitThis], [MapClass], [NamedConstructor], [NoInterfaceObject], [OverrideBuiltins]. [PrimaryGlobal], [Unforgeable].

[3]CallbackOrInterface"callback" CallbackRestOrInterface
 | Interface
[4]CallbackRestOrInterfaceCallbackRest
 | Interface
[5]Interface"interface" identifier Inheritance "{" InterfaceMembers "}" ";"
[6]Partial"partial" PartialDefinition
[7]PartialDefinitionPartialInterface
 | PartialDictionary
[8]PartialInterface"interface" identifier "{" InterfaceMembers "}" ";"
[9]InterfaceMembersExtendedAttributeList InterfaceMember InterfaceMembers
 | ε
[10]InterfaceMemberConst
 | AttributeOrOperationOrIterator
[20]Inheritance":" identifier
 | ε
Example

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.

IDL
interface Animal {
  attribute DOMString name;
};

interface Human : Animal {
  attribute Dog? pet;
};

interface Dog : Animal {
  attribute Human? owner;
};
Example

The following IDL fragment defines simplified versions of a few DOM interfaces, one of which is a callback interface.

IDL
interface Node {
  readonly attribute DOMString nodeName;
  readonly attribute Node? parentNode;
  Node appendChild(Node newChild);
  void addEventListener(DOMString type, EventListener listener);
};

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

Since the EventListener interface is annotated callback interface, user objects can implement it:

ECMAScript
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 a user object to implement Node, however:

ECMAScript
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.

3.2.1. Constants

A constant is a declaration (matching Const) used to bind a constant value to a name. Constants can appear on interfaces and exceptions.

Warning

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. Specification authors who wish to define constants are strongly advised to discuss this on the public-script-coord@w3.org mailing list before proceeding.

const type identifier = value;

The identifier of a constant MUST NOT be the same as the identifier of another interface member defined on the same interface or another exception member defined on the same exception. The identifier also MUST NOT be “prototype”.

The type of a constant (matching ConstType) MUST NOT be any type other than a primitive type or a nullable primitive type. If an identifier is used, it MUST reference a typedef whose type is a primitive type or a nullable 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), the null token, an integer token, a float 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 default value of a dictionary member or of an optional argument. Note that strings and the empty sequence [] 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 characters matched by the integer token.
  2. Let sign be −1 if S begins with U+002D HYPHEN-MINUS ("-"), and 1 otherwise.
  3. Let base be the base of the number based on the characters that follow the optional leading U+002D HYPHEN-MINUS ("-") character:
    U+0030 DIGIT ZERO ("0"), U+0058 LATIN CAPITAL LETTER X ("X")
    U+0030 DIGIT ZERO ("0"), U+0078 LATIN SMALL LETTER X ("x")
    The base is 16.
    U+0030 DIGIT ZERO ("0")
    The base is 8.
    Otherwise
    The base is 10.
  4. Let number be the result of interpreting all remaining characters following the optional leading U+002D HYPHEN-MINUS ("-") character and any characters indicating the base as an integer specified in base base.
  5. 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 section 3.10 below.

The value of a float 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 characters matched by the float token.
  2. Let value be the Mathematical Value that would be obtained if S were parsed as an ECMAScript NumericLiteral ([ECMA-262], section 11.8.3).
  3. If the float token is being used as the value for a float or unrestricted float, then the value of the float token is the IEEE 754 single-precision floating point number closest to result. Otherwise, the float token is being used as the value for a double or unrestricted double, and the value of the float 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 is 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 float 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 float token MUST NOT lie outside the valid range of values for its type, as given in section 3.10 below. 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 inner type is VT.

Constants are not associated with particular instances of the interface on which they appear. It is language binding specific whether constants are exposed on instances.

Note

The ECMAScript 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:

IDL
interface A {
  const short rambaldi = 47;
};

the constant value can be accessed in ECMAScript either as A.rambaldi or instanceOfA.rambaldi.

The following extended attributes are applicable to constants: [Exposed].

[28]Const"const" ConstType identifier "=" ConstValue ";"
[29]ConstValueBooleanLiteral
 | FloatLiteral
 | integer
 | "null"
[30]BooleanLiteral"true"
 | "false"
[31]FloatLiteralfloat
 | "-Infinity"
 | "Infinity"
 | "NaN"
[80]ConstTypePrimitiveType Null
 | identifier Null
Example

The following IDL fragment demonstrates how constants of the above types can be defined.

IDL
interface Util {
  const boolean DEBUG = false;
  const octet LF = 10;
  const unsigned long BIT_MASK = 0x0000fc00;
  const float AVOGADRO = 6.022e23;
};

exception Problem {
  const short ERR_UNKNOWN = 0;
  const short ERR_OUT_OF_MEMORY = 1;

  short errorCode;
};

3.2.2. Attributes

An attribute is an interface member (matching "static" AttributeRest, "stringifier" AttributeRest, or Attribute) 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
    attribute type identifier;
  2. static attributes, which are used to declare attributes that are not associated with a particular object implementing the interface
    static attribute type identifier;

If an attribute has no static keyword, then it declares a regular attribute. Otherwise, it declares a static attribute.

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 or typedef.

The type of the attribute, after resolving typedefs, MUST NOT be a nullable or non-nullable version of any of the following 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.

readonly attribute type identifier;

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 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, and inherit MUST NOT appear on a read only attribute or a static attribute.

interface Ancestor {
  readonly attribute TheType theIdentifier;
};

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 section 3.2.4.2 below for details.

stringifier attribute DOMString identifier;

If an implementation attempts to get or set the value of an attribute on a user object (for example, when a callback object has been supplied to the implementation), and that attempt results in an exception being thrown, then, unless otherwise specified, that exception will be propagated to the user code that caused the implementation to access the attribute. Similarly, if a value returned from getting the attribute cannot be converted to an IDL type, then any exception resulting from this will also be propagated to the user code that resulted in the implementation attempting to get the value of the attribute.

The following extended attributes are applicable to regular and static attributes: [Clamp], [EnforceRange], [EnsureUTF16], [Exposed], [SameObject], [TreatNullAs].

The following extended attributes are applicable only to regular attributes: [LenientThis], [PutForwards], [Replaceable], [Unforgeable].

[42]AttributeInherit AttributeRest
[43]AttributeRestReadOnly "attribute" Type AttributeName ";"
[46]Inherit"inherit"
 | ε
[47]ReadOnly"readonly"
 | ε
Example

The following IDL fragment demonstrates how attributes can be declared on an interface:

IDL
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;
};

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;
};

3.2.3. Operations

An operation is an interface member (matching "static" OperationRest, "stringifier" OperationRest, "serializer" OperationRest, ReturnType OperationRest 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
    return-type identifier(arguments…);
  2. special operations, which are used to declare special behavior on objects implementing the interface, such as object indexing and stringification
    special-keywords… return-type identifier(arguments…);
    special-keywords… return-type (arguments…);
  3. static operations, which are used to declare operations that are not associated with a particular object implementing the interface
    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 one or more special keywords 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 section 3.2.4 below for details on special operations.

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. 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.

The identifier of a static operation also MUST NOT 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 ReturnType) that appears before the operation’s optional identifier. A return type of void indicates that the operation returns no value. If the return type is an identifier followed by ?, then the identifier MUST identify an interface, dictionary, enumeration, callback function 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 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.

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.

return-type identifier([extended-attributes] type identifier, [extended-attributes] type identifier, …);
Example

The following IDL fragment demonstrates how regular operations can be declared on an interface:

IDL
interface Dimensions {
  attribute unsigned long width;
  attribute unsigned long height;
};

exception NoPointerDevice { };

interface Button {

  // An operation that takes no arguments and returns a boolean.
  boolean isMouseOver();

  // Overloaded operations.
  void setDimensions(Dimensions size);
  void setDimensions(unsigned long width, unsigned long height);
};

An 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.

return-type identifier(type... identifier);
return-type identifier(type identifier, type... identifier);

Extended attributes that take an argument list ([Constructor] and [NamedConstructor], of those defined in this specification) and callback functions are also considered to be variadic when the ... token is used in their argument lists.

Example

The following IDL fragment defines an interface that has two variadic operations:

IDL
interface IntegerSet {
  readonly attribute unsigned long cardinality;

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

In the ECMAScript binding, variadic operations are implemented by functions that can accept the subsequent arguments:

ECMAScript
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.

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 EQUALS SIGN ("=") and a value (matching DefaultValue), then that gives the optional argument its 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.

return-type identifier(type identifier, optional type identifier = value);

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 this argument is either the final argument or is followed only by optional arguments, then the argument MUST be specified as optional. Such arguments are always considered to have a default value of an empty dictionary, unless otherwise specified.

Note

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.

Dictionary types cannot have a default value specified explicitly, so the “unless otherwise specified” clause above can only be invoked for a union type that has a dictionary type as one of its flattened member types.

When a boolean literal token (true or false), the null token, an integer token, a float token or one of the three special floating point literal values (Infinity, -Infinity or NaN) is used as the default value, it is interpreted in the same way as for a constant.

Optional argument default values can also be specified using a string token, whose value is a DOMString or enumeration determined as follows:

  1. Let S be the sequence of characters matched by the string token with its leading and trailing U+0022 QUOTATION MARK ('"') characters removed.
  2. The value of the string token is the sequence of 16 bit unsigned integer code units (hereafter referred to just as code units) corresponding to the UTF-16 encoding of S.

If the type of the optional argument is an enumeration, then its 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 the type of the optional argument it is being used as the default value of. That type MUST be a sequence type or a nullable type.

Example

The following IDL fragment defines an interface with a single operation that can be invoked with two different argument list lengths:

IDL
interface ColorCreator {
  object createColor(float v1, float v2, float v3, optional float alpha);
};

It is equivalent to an interface that has two overloaded operations:

IDL
interface ColorCreator {
  object createColor(float v1, float v2, float v3);
  object createColor(float v1, float v2, float v3, float alpha);
};

If an implementation attempts to invoke an operation on a user object (for example, when a callback object has been supplied to the implementation), and that attempt results in an exception being thrown, then, unless otherwise specified, that exception will be propagated to the user code that caused the implementation to invoke the operation. Similarly, if a value returned from invoking the operation cannot be converted to an IDL type, then any exception resulting from this will also be propagated to the user code that resulted in the implementation attempting to invoke the operation.

The following extended attributes are applicable to operations: [Exposed], [NewObject], [TreatNullAs], [Unforgeable].

The following extended attributes are applicable to operation arguments: [Clamp], [EnforceRange], [EnsureUTF16], [TreatNullAs].

[17]DefaultValueConstValue
 | string
 | "[" "]"
[32]AttributeOrOperationOrIteratorSerializer
 | Stringifier
 | StaticMember
 | Attribute
 | OperationOrIterator
[48]OperationOrIteratorReturnType OperationOrIteratorRest
 | SpecialOperation
[49]SpecialOperationSpecial Specials ReturnType OperationRest
[50]SpecialsSpecial Specials
 | ε
[51]Special"getter"
 | "setter"
 | "creator"
 | "deleter"
 | "legacycaller"
[52]OperationOrIteratorRestIteratorRest
 | OperationRest
[56]OperationRestOptionalIdentifier "(" ArgumentList ")" ";"
[57]OptionalIdentifieridentifier
 | ε
[58]ArgumentListArgument Arguments
 | ε
[59]Arguments"," Argument Arguments
 | ε
[60]ArgumentExtendedAttributeList OptionalOrRequiredArgument
[61]OptionalOrRequiredArgument"optional" Type ArgumentName Default
 | Type Ellipsis ArgumentName
[62]ArgumentNameArgumentNameKeyword
 | identifier
[63]Ellipsis"..."
 | ε
[72]ArgumentNameKeyword "attribute"
 | "callback"
 | "const"
 | "creator"
 | "deleter"
 | "dictionary"
 | "enum"
 | "exception"
 | "getter"
 | "implements"
 | "inherit"
 | "interface"
 | "legacycaller"
 | "partial"
 | "required"
 | "serializer"
 | "setter"
 | "static"
 | "stringifier"
 | "typedef"
 | "unrestricted"
[91]ReturnTypeType
 | "void"

3.2.4. 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 one or more special keywords in an operation declaration.

There are seven 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 operation Keyword Purpose
Getters getter Defines behavior for when an object is indexed for property retrieval.
Setters setter Defines behavior for when an object is indexed for property assignment.
Creators creator Defines behavior for when an object is indexed for property creation.
Deleters deleter Defines behavior for when an object is indexed for property deletion.
Legacy callers legacycaller Defines behavior for when an object is called as if it were a function.
Stringifiers stringifier Defines how an object is converted into a DOMString.
Serializers serializer Defines how an object is converted into a serialized form.

Not all language bindings support all of the six 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.

Some language bindings, such as ECMAScript, do not distinguish assignment to an existing indexed or named property and the creation of a new one. Regardless, it is the creator that is invoked when an attempt is made to create a new indexed or named property, and the setter when the property already exists.

Example

The following IDL fragment defines an interface with a getter and a setter:

IDL
interface Dictionary {
  readonly attribute unsigned long propertyCount;

  getter float (DOMString propertyName);
  setter void (DOMString propertyName, float 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 prose descriptions of an interface’s operations.

Example

The following two interfaces are equivalent:

IDL
interface Dictionary {
  readonly attribute unsigned long propertyCount;

  getter float getProperty(DOMString propertyName);
  setter void setProperty(DOMString propertyName, float propertyValue);
};
IDL
interface Dictionary {
  readonly attribute unsigned long propertyCount;

  float getProperty(DOMString propertyName);
  void setProperty(DOMString propertyName, float propertyValue);

  getter float (DOMString propertyName);
  setter void (DOMString propertyName, float propertyValue);
};

A given special keyword MUST NOT appear twice on an operation.

Getters, setters, creators and deleters come in two varieties: ones that take a DOMString as a property name, known as named property getters, named property setters, named property creators and named property deleters, and ones that take an unsigned long as a property index, known as indexed property getters, indexed property setters, indexed property creators and indexed property deleters. See section 3.2.4.4 and section 3.2.4.5 for details.

On a given interface, there MUST exist at most one stringifier, at most one serializer, and at most one of each variety of getter, setter, creator and deleter. Multiple legacy callers can exist on an interface to specify overloaded calling behavior.

If an interface has a setter, creator or deleter of a given variety, then it MUST also have a getter of that variety.

Special operations declared using operations MUST NOT be variadic nor have any optional arguments.

Special operations MUST NOT be declared on callback interfaces.

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.

3.2.4.1. Legacy callers

When an interface has one or more legacy callers, it indicates that objects that implement the interface can be called as if they were functions. As mentioned above, legacy callers can be specified using an operation declared with the legacycaller keyword.

legacycaller return-type identifier(arguments…);
legacycaller return-type (arguments…);

If multiple legacy callers are specified on an interface, overload resolution is used to determine which legacy caller is invoked when the object is called as if it were a function.

Legacy callers MUST NOT be defined to return a promise type.

Warning

Legacy callers are universally recognised as an undesirable feature. They exist only so that legacy Web platform features can be specified. Legacy callers SHOULD NOT be used in specifications unless required to specify the behavior of legacy APIs, and even then this should be discussed on the public-script-coord@w3.org mailing list before proceeding.

Example

The following IDL fragment defines an interface with a legacy caller.

IDL
interface NumberQuadrupler {
  // This operation simply returns four times the given number x.
  legacycaller float compute(float x);
};

An ECMAScript implementation supporting this interface would allow a platform object that implements NumberQuadrupler to be called as a function:

ECMAScript
var f = getNumberQuadrupler();  // Obtain an instance of NumberQuadrupler.

f.compute(3);                   // This evaluates to 12.
f(3);                           // This also evaluates to 12.
3.2.4.2. Stringifiers

When an interface has a stringifier, it indicates that objects that implement the interface have a non-default conversion to a string. As mentioned above, stringifiers can be specified using an operation declared with the stringifier keyword.

stringifier DOMString identifier();
stringifier DOMString ();

If an operation used to declare a stringifier does not have an identifier, then prose accompanying the interface MUST define the stringification behavior of the interface. If the operation does have an identifier, then the object is converted to a string by invoking the operation to obtain the string.

Stringifiers declared with operations MUST be declared to take zero arguments and return a DOMString.

As a shorthand, if the stringifier keyword is declared using an operation with no identifier, then the operation’s return type and argument list can be omitted.

stringifier;
Example

The following two interfaces are equivalent:

IDL
interface A {
  stringifier DOMString ();
};
IDL
interface A {
  stringifier;
};

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. It also MUST NOT be placed on a static attribute.

stringifier attribute DOMString identifier;
[38]Stringifier"stringifier" StringifierRest
[39]StringifierRestAttributeRest
 | ReturnType OperationRest
 | ";"
Example

The following IDL fragment defines an interface that will stringify to the value of its name attribute:

IDL
[Constructor]
interface Student {
  attribute unsigned long id;
  stringifier attribute DOMString name;
};

In the ECMAScript 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:

ECMAScript
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.

IDL
[Constructor]
interface Student {
  attribute unsigned long id;
  attribute DOMString? familyName;
  attribute DOMString givenName;

  stringifier DOMString ();
};

Thus, prose is required to explain the stringification behavior, such as the following paragraph:

Objects that implement the Student interface must stringify as follows. If the value of the familyName attribute is null, the stringification of the object is the value of the givenName attribute. Otherwise, if the value of the familyName attribute is not null, the stringification of the object is the concatenation of the value of the givenName attribute, a single space character, and the value of the familyName attribute.

An ECMAScript implementation of the IDL would behave as follows:

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

var greeting = 'Hi ' + s;  // Now greeting == 'Hi Alan Smithee'.
3.2.4.3. Serializers

When an interface has a serializer, it indicates that objects provide a way for them to be converted into a serialized form. Serializers can be declared using the serializer keyword:

serializer;

Prose accompanying an interface that declares a serializer in this way MUST define the serialization behavior of the interface. Serialization behavior is defined as returning a serialized value of one of the following types:

How the serialization behavior is made available on an object in a language binding, and how exactly the abstract serialized value is converted into an appropriate concrete value, is language binding specific.

Note

In the ECMAScript language binding, serialization behavior is exposed as a toJSON method which returns the serialized value converted into an ECMAScript value that can be serialized to JSON by the JSON.stringify function. See section 4.5.8.2 below for details.

Serialization behavior can also be specified directly in IDL, rather than separately as prose. This is done by following the serializer keyword with a U+003D EQUALS SIGN ("=") character and a serialization pattern, which can take one of the following six forms:

  • A map with entries corresponding to zero or more attributes from the interface, and optionally attributes from an inherited interface:

    serializer = { attribute-identifier, attribute-identifier, … };
    serializer = { inherit, attribute-identifier, attribute-identifier, … };

    Each identifier MUST be the identifier of an attribute declared on the interface. The identified attributes all MUST have a serializable type.

    The inherit keyword MUST NOT be used unless the interface inherits from another that defines a serializer, and the closest such interface defines its serializer using this serialization pattern form or the following form (i.e. { attribute }).

    The serialization behavior for this form of serialization pattern is as follows:

    1. Let map be an empty map.
    2. If the inherit keyword was used, then set map to be the result of the serialization behavior of the closest inherited interface that declares a serializer.
    3. For each attribute identifier i in the serialization pattern, in order:
      1. Remove any entry in map with key name i.
      2. Let V be the value of the attribute with identifier i.
      3. Add an entry to map whose key name is i and whose value is result of converting V to a serialized value.
    4. Return map.
  • A map with entries corresponding to all attributes from the interface that have a serializable type, and optionally attributes from an inherited interface:

    serializer = { attribute };
    serializer = { inherit, attribute };

    The inherit keyword MUST NOT be used unless the interface inherits from another that defines a serializer, and the closest such interface defines its serializer using this serialization pattern form or the previous form.

    The serialization behavior for this form of serialization pattern is as follows:

    1. Let map be an empty map.
    2. If the inherit keyword was used, then set map to be the result of the serialization behavior of the closest inherited interface that declares a serializer.
    3. For each identifier i of an attribute on the interface whose type is a serializable type, in the order they appear on the interface:
      1. Remove any entry in map with key name i.
      2. Let V be the value of the attribute with identifier i.
      3. Add an entry to map whose key name is i and whose value is result of converting V to a serialized value.
    4. Return map.
  • A map with entries corresponding to the named properties:

    serializer = { getter };

    This form MUST NOT be used unless the interface or one it inherits from supports named properties and the return type of the named property getter is a serializable type.

    The serialization behavior for this form of serialization pattern is as follows:

    1. Let map be an empty map.
    2. For each supported property name n on the object, in order:
      1. Let V be the value of the named property with name n.
      2. Add an entry to map whose key name is i and whose value is result of converting V to a serialized value.
    3. Return map.
  • A list of value of zero or more attributes on the interface:

    serializer = [ attribute-identifier, attribute-identifier, … ];

    Each identifier MUST be the identifier of an attribute declared on the interface. The identified attributes all MUST have a serializable type.

    The serialization behavior for this form of serialization pattern is as follows:

    1. Let list be an empty list.
    2. For each attribute identifier i in the serialization pattern:
      1. Let V be the value of the attribute with identifier i.
      2. Append to list the value that is the result of converting V to a serialized value.
    3. Return list.
  • A list with entries corresponding to the indexed properties:

    serializer = [ getter ];

    This form MUST NOT be used unless the interface or one it inherits from supports indexed properties and the return type of the indexed property getter is a serializable type.

    The serialization behavior for this form of serialization pattern is as follows:

    1. Let list be an empty list.
    2. Let i be 0.
    3. While i is less than or equal to the greatest supported property index on the object:
      1. Let V be the value of the indexed property with index i if i is a supported property index, or null otherwise.
      2. Append to list the value that is the result of converting V to a serialized value.
      3. Set i to i + 1.
    4. Return map.
  • A single attribute:

    serializer = attribute-identifier;

    The identifier MUST be the identifier of an attribute declared on the interface, and this attribute MUST have a serializable type.

    The serialization behavior for this form of serialization pattern is as follows:

    1. Let V be the value of the attribute with the specified identifier.
    2. Return the result of converting V to a serialized value.
Note

Entries are added to maps in a particular order so that in the ECMAScript language binding it is defined what order properties are added to objects. This is because this order can influence the serialization that JSON.stringify can produce.

The list of serializable types and how they are converted to serialized values is as follows:

long long
converted by choosing the closest equivalent double value (as when converting a long long to an ECMAScript Number value)
unsigned long long
converted by choosing the closest equivalent double value (as when converting a unsigned long long to an ECMAScript Number value)
any other integer type
float
converted by choosing the equivalent double value
double
boolean
DOMString
Date
the same value of the respective type
an enumeration type
the equivalent DOMString value
a ByteString
the equivalent DOMString value where each code unit has the same value as the corresponding byte value
a nullable serializable type
converted to null if that is its value, otherwise converted as per its inner type
a union type where all of its member types are serializable types
converted as per its specific type
a sequence type that has a serializable type as its element type
converted to a list where each element is the result of converting its corresponding sequence element to a serialized value
a dictionary where all of its members have serializable types
converted to a map consisting of an entry for each dictionary member that is present, where the entry’s key is the identifier of the dictionary member and its value is the result of converting the dictionary member’s value to a serializable type
an interface type that has a serializer
converted by invoking the object’s serializer

Serializers can also be specified using an operation with the serializer keyword:

serializer type identifier();

Serializers declared with operations MUST be declared to take zero arguments and return a serializable type.

The serialization behavior of the interface with a serializer declared with an operation is the result of converting the value returned from invoking the operation to a serialized value.

[33]Serializer"serializer" SerializerRest
[34]SerializerRestOperationRest
 | "=" SerializationPattern
 | ε
[35]SerializationPattern"{" SerializationPatternMap "}"
 | "[" SerializationPatternList "]"
 | identifier
[36]SerializationPatternMap"getter"
 | "inherit" Identifiers
 | identifier Identifiers
 | ε
[37]SerializationPatternList"getter"
 | identifier Identifiers
 | ε
[93]Identifiers"," identifier Identifiers
 | ε
Example

The following IDL fragment defines an interface Transaction that has a serializer defines in prose:

IDL
interface Transaction {
  readonly attribute Account from;
  readonly attribute Account to;
  readonly attribute float amount;
  readonly attribute DOMString description;
  readonly attribute unsigned long number;

  serializer;
};

interface Account {
  DOMString name;
  unsigned long number;
};

The serializer could be defined as follows:

The serialization behavior of the Transaction interface is to run the following algorithm, where O is the object that implements Transaction:

  1. Let map be an empty map.
  2. Add an entry to map whose key is “from” and whose value is the serialized value of the number attribute on the Account object referenced by the from attribute on O.
  3. Add an entry to map whose key is “to” and whose value is the serialized value of the number attribute on the Account object referenced by the from attribute on O.
  4. For both of the attributes amount and description, add an entry to map whose key is the identifier of the attribute and whose value is the serialized value of the value of the attribute on O.
  5. Return map.

If it was acceptable for Account objects to be serializable on their own, then serialization patterns could be used to avoid having to define the serialization behavior in prose:

IDL
interface Transaction {
  readonly attribute Account from;
  readonly attribute Account to;
  readonly attribute float amount;
  readonly attribute DOMString description;
  readonly attribute unsigned long number;

  serializer = { from, to, amount, description };
};

interface Account {
  DOMString name;
  unsigned long number;

  serializer = number;
};

In the ECMAScript language binding, there would exist a toJSON method on Transaction objects:

ECMAScript
// Get an instance of Transaction.
var txn = getTransaction();

// Evaluates to an object like this:
// {
//   from: 1234
//   to: 5678
//   amount: 110.75
//   description: "dinner"
// }
txn.toJSON();

// Evaluates to a string like this:
// '{"from":1234,"to":5678,"amount":110.75,"description":"dinner"}'
JSON.stringify(txn);
3.2.4.4. Indexed properties

An interface that defines an indexed property getter is said to support indexed properties.

If an interface 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.

Indexed property getters and deleters MUST be declared to take a single unsigned long argument. Indexed property setters and creators MUST be declared to take two arguments, where the first is an unsigned long.

getter type identifier(unsigned long identifier);
setter type identifier(unsigned long identifier, type identifier);
creator type identifier(unsigned long identifier, type identifier);
deleter type identifier(unsigned long identifier);

getter type (unsigned long identifier);
setter type (unsigned long identifier, type identifier);
creator type (unsigned long identifier, type identifier);
deleter type (unsigned long identifier);

The following requirements apply to the definitions of indexed property getters, setters, creators and deleters:

  • 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 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 for a given property index and value.
  • If an indexed property creator was specified using an operation with an identifier, then the behavior that occurs when indexing the object for property creation with a given 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 creator did not have an identifier, then the interface definition must be accompanied by a description of how to set the value of a new indexed property for a given property index and value.
  • If an indexed 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 index is the same as if the operation is invoked, passing the index as the only argument. If the operation used to declare the indexed property deleter did not have an identifier, then the interface definition must be accompanied by a description of how to delete an existing indexed property for a given property index.
Note

Note that if an indexed property getter, setter or deleter is specified using an operation with an identifier, then indexing an object with an integer that is not a 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 ECMAScript language binding, a regular property lookup is done. For example, take the following IDL:

IDL
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:

ECMAScript
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".
Example

The following IDL fragment defines an interface OrderedMap which allows retrieving and setting values by name or by index number:

IDL
interface OrderedMap {
  readonly attribute unsigned long size;

  getter any getByIndex(unsigned long index);
  setter void setByIndex(unsigned long index, any value);
  deleter void removeByIndex(unsigned long index);

  getter any get(DOMString name);
  setter creator void set(DOMString name, any value);
  deleter void remove(DOMString name);
};

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 section 4.7, an ECMAScript implementation would create properties on a 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:

ECMAScript
// Assume map is a 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;   // If map.length > 1, then this will set the property named
                  // "1" on map to false, and then will do the equivalent of:
                  //
                  //   map.setByIndex(1, false)
                  //
                  // Otherwise, if map.length ≤ 1, then it will set the
                  // property but have no other effect (since an indexed property creator
                  // was not specified).

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;  // Regardless of whether there exists a named property named
                  // "berry", this will set the "berry" property to 123, and
                  // then 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")
3.2.4.5. Named properties

An interface that defines a named property getter is said to support named properties.

If an interface 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 and creators MUST be declared to take two arguments, where the first is a DOMString.

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

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

The following requirements apply to the definitions of named property getters, setters, creators 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 for a given property name and value.
  • If a named property creator was specified using an operation with an identifier, then the behavior that occurs when indexing the object for property creation with a given 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 creator did not have an identifier, then the interface definition must be accompanied by a description of 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, setter or 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.

3.2.5. 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.

Static attributes and operations MUST NOT be declared on callback interfaces.

[40]StaticMember"static" StaticMemberRest
[41]StaticMemberRestAttributeRest
 | ReturnType OperationRest
Example

The following IDL fragment defines an interface Circle that has a static operation declared on it:

IDL
interface Point { /* ... */ };

interface Circle {
  attribute float cx;
  attribute float cy;
  attribute float radius;

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

In the ECMAScript language binding, the Function object for triangulate and the accessor property for triangulationCount will exist on the interface object for Circle:

ECMAScript
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);

3.2.6. 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. If an interface has multiple legacy callers defined on it, then those legacy callers are also said to be overloaded. In the ECMAScript language binding, constructors can be overloaded too. There are some restrictions on the arguments that overloaded operations, legacy callers and constructors can be specified to take, and in order to describe these restrictions, the notion of an effective overload set is used.

Operations and legacy callers MUST NOT be overloaded across interface and partial interface definitions.

Note

For example, the overloads for both f and g are disallowed:

IDL
interface A {
  void f();
};

partial interface A {
  void f(float x);
  void g();
};

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

Note that the [Constructor] and [NamedConstructor] 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 [Constructor] or [NamedConstructor]), legacy caller or callback function. The algorithm to compute an effective overload set operates on one of the following six 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
For legacy callers
For constructors
For named constructors
For callback functions

An effective overload set is used, among other things, to determine whether there are ambiguities in the overloaded operations, constructors and callers specified on an interface.

The elements of an effective overload set are tuples of the form <callabletype list, optionality list>. If the effective overload set is for regular operations, static operations or legacy callers, then callable is an operation; if it is for constructors or named constructors, then callable is an extended attribute; and if it is for callback functions, then callable is the callback function itself. In all cases, type list is a list of IDL types, and 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 or corresponds to a variadic argument. Each tuple represents an allowable invocation of the operation, constructor, legacy caller 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 entries in an effective overload set identifying the same operation or constructor.

The algorithm below describes how to compute an effective overload set. The following input variables are used, if they are required:

  • the identifier of the operation or named constructor is A
  • the argument count is N
  • the interface is I
  • the callback function is C

Whenever an argument of an extended attribute is mentioned, it is referring to an argument of the extended attribute’s named argument list.

  1. Initialize S to ∅.
  2. Let F be a set with elements 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] extended attributes on interface I.
    For named constructors
    The elements of F are the [NamedConstructor] extended attributes on interface I whose named argument lists’ identifiers are A.
    For legacy callers
    The elements of F are the legacy callers defined on interface I.
    For callback functions
    The single element of F is the callback function itself, C.
  3. Let maxarg be the maximum number of arguments the operations, constructor extended attributes or callback functions in F are declared to take. For variadic operations and constructor extended attributes, the argument on which the ellipsis appears counts as a single argument.
    Note

    So void f(long x, long... y); is considered to be declared to take two arguments.

  4. Let m be the maximum of maxarg and N.
  5. For each operation, extended attribute or callback function X in F:
    1. Let n be the number of arguments X is declared to take.
    2. Let t0..n−1 be a list of types, where ti is the type of X’s argument at index i.
    3. Let o0..n−1 be a list of optionality values, where oi is “variadic” if X’s argument at index i is a final, variadic argument, “optional” if the argument is optional, and “required” otherwise.
    4. Add to S the tuple <Xt0..n−1, o0..n−1>.
    5. If X is declared to be variadic, then:
      1. Add to S the tuple <Xt0..n−2o0..n−2>.
        Note

        This leaves off the final, variadic argument.

      2. For every integer i, such that n ≤ i ≤ m−1:
        1. Let u0..i be a list of types, where uj = tj (for j < n) and uj = tn−1 (for j ≥ n).
        2. Let p0..i be a list of optionality values, where pj = oj (for j < n) and pj = “variadic” (for j ≥ n).
        3. Add to S the tuple <Xu0..ip0..i>.
    6. Initialize i to n−1.
    7. While i ≥ 0:
      1. If argument i of X is not optional, then break this loop.
      2. Otherwise, add to S the tuple <Xt0..i−1o0..i−1>.
      3. Set i to i−1.
    8. If n > 0 and all arguments of X are optional, then add to S the tuple <X, (), ()> (where “()” represents the empty list).
  6. The effective overload set is S.
Example

For the following interface:

IDL
interface A {
  /* f1 */ void f(DOMString a);
  /* f2 */ void f(Node a, DOMString b, float... c);
  /* f3 */ void f();
  /* f4 */ void f(Event a, DOMString b, optional DOMString c, float... 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, float), (required, required, variadic)>,
<f2, (Node, DOMString, float, float), (required, required, variadic, variadic)>,
<f3, (), ()>,
<f4, (Event, DOMString), (required, required)>,
<f4, (Event, DOMString, DOMString), (required, required, optional)>,
<f4, (Event, DOMString, DOMString, float), (required, required, optional, variadic)> }

Two types are distinguishable if at most one of the two includes a nullable type or is a dictionary type, and at least one of the following three conditions is true:

  1. The two types (taking their inner types if they are nullable types) appear 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:

    boolean numeric DOMString enumeration ByteString interface object callback
    function
    dictionary sequence<T> T[] Date RegExp
    boolean
    numeric
    DOMString
    enumeration
    ByteString
    interface (a) (b) (b) (b) (b)
    object
    callback function
    dictionary
    sequence<T>
    T[]
    Date
    RegExp
    1. The two identified interfaces are not the same, it is not possible for a single platform object to implement both interfaces, and it is not the case that both are callback interfaces.
    2. The interface type is not a callback interface.
  2. One type is a union type or nullable union type, the other is neither a union type nor a nullable union type, and each member type of the first is distinguishable with the second.
  3. Both types are either a union type or nullable union type, and each member type of the one is distinguishable with each member type of the other.
Note

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 entry in an effective overload set that has a given type list length, then for those entries there MUST be an index i such that for each pair of entries the types at index i are distinguishable. The lowest such index is termed the distinguishing argument index for the entries of the effective overload set with the given type list length.

Example

Consider the effective overload set shown in the previous example. There are multiple entries in the set with type lists 2, 3 and 4. For each of these type list lengths, the distinguishing argument index is 0, since Node and Event are distinguishable.

The following use of overloading however is invalid:

IDL
interface B {
  void f(DOMString x);
  void f(float x);
};

since DOMString and float are not distinguishable.

In addition, for each index j, where j is less than the distinguishing argument index for a given type list length, the types at index j in all of the entries’ type lists MUST be the same and the booleans in the corresponding list indicating argument optionality MUST be the same.

Example

The following is invalid:

IDL
interface B {
  /* f1 */ void f(DOMString w);
  /* f2 */ void f(long w, float x, Node y, Node z);
  /* f3 */ void f(float w, float x, DOMString y, Node z);
};

For argument count 4, the effective overload set is:

{ <f1, (DOMString), (required)>,
<f2, (long, float, Node, Node), (required, required, required, required)>,
<f3, (float, float, DOMString, Node), (required, required, required, required)> }

Looking at entries with type list length 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.

3.2.7. Iterators

An iterator is an interface member (matching ReturnType "iterator" OptionalIteratorInterface) that defines behavior that can be invoked on objects implementing the interface, which returns an iterator that allows values from the object to be iterated over.

Note

In the ECMAScript language binding, an iterator is exposed as a method named iterator on an interface prototype object which returns an iterator object.

Editorial note

This relies on the iterators strawman proposal which has not yet been incorporated into the ES6 specification.

iterated-type iterator;

The type on the left of the iterator keyword is the iterated type, which is the type of values the iterator will return.

Prose accompanying an interface that declares an iterator in this way MUST define the iterator behavior, which describes how to determine the first or next value to be provided by the iterator for a given target object that implements the interface. The iterator behavior MUST be described in terms of:

  1. a current iterator state, which at the time the iterator is first invoked is the uninitialized iterator state and in subsequent iterations is whatever value the iterator behavior defines it to be updated to, and
  2. the target object, which is the object whose values are being iterated over.

The iterator behavior MUST be defined so that it does one of the following three things:

  1. return an IDL value, which is the next value to be iterated over,
  2. not return a value, which means that no more values will be iterated over, or
  3. throw an exception.

Any value returned from the definition of iterator behavior for an interface MUST be of the same type as the iterated type.

Example

Consider the following interface SessionManager, which allows access to a number of Session objects:

IDL
interface SessionManager {
  Session getSessionForUser(DOMString username);
  readonly attribute unsigned long sessionCount;

  Session iterator;
};

interface Session {
  readonly attribute DOMString username;
  // ...
};

The behavior of the iterator could be defined like so:

The iterator behavior of the SessionManager interface is as follows:

  1. Let sessions be a list of open sessions sorted by username.
  2. If sessions is empty, then return no value.
  3. Let state be the current iterator state.
  4. If state is uninitialized, then:
    1. Let session be the first Session object in sessions.
    2. Set the iterator state to the username of session.
    3. Return session.
  5. Otherwise:
    1. If there is no Session object in sessions with a username that sorts after state, then return no value.
    2. Let session be the first Session object in sessions with a username that sorts after state.
    3. Set the iterator state to the username of session.
    4. Return session.

In the ECMAScript language binding, the interface prototype object for the SessionManager interface has an iterator method that when invoked returned a default iterator object, which itself has a next method that returns the next value to be iterated over. This also allows a SessionManager object to be used in a for..of loop:

ECMAScript
// Get an instance of SessionManager.
// Assume that it has sessions for two users, "anna" and "brian".
var sm = getSessionManager();

typeof SessionManager.prototype.iterator;  // Evaluates to "function"
var it = sm.iterator();                    // iterator() returns an iterator object
String(it);                                // Evaluates to "[object SessionManagerIterator]"
typeof it.next;                            // Evaluates to "function"

// This loop will alert "anna" and then "brian".
for (;;) {
  try {
    let session = it.next();
    window.alert(session.username);
  } catch (e) {
    String(e);                             // Evaluates to "[object StopIteration]"
  }
}

// This loop will also alert "anna" and then "brian".
for (let session of sm) {
  window.alert(session.username);
}

Iterators can be declared in a second way, where iteration is exposed through an object that implements a specific interface.

iterated-type iterator = interface-identifier;

The identifier that appears on the right hand side MUST identify an interface that has been declared to be an iterator object interface, which is done by placing an iterator object declaration on the interface:

interface interface-identifier {
  …
  iterated-type iterator object;
};

An iterator declared by identifying an iterator object interface MUST have the same type as listed in the iterator object declaration of the iterator object interface.

Prose accompanying an interface that declares an iterator in this way MUST define how an iterator object is created for an object that implements the interface. That definition MUST return an object that implements the iterator object interface or throw an exception.

Prose accompanying an iterator object interface MUST define the iterator object behavior, which describes how to determine the next value to be iterated over using the iterator object itself as the iterator’s state. As with iterator behavior, the iterator object behavior MUST be defined so that it does one of the following three things:

  1. return an IDL value, which is the next value to be iterated over,
  2. not return a value, which means that no more values will be iterated over, or
  3. throw an exception.

Any value returned from the definition of iterator object behavior for an interface MUST be of the same type as identified in the iterator object declaration.

There MUST NOT be an interface member on an iterator object interface or any of its consequential interfaces with the identifier “next”.

Note

This is because in the ECMAScript language binding, the interface prototype object for an iterator object interface has a next method.

Example

Consider the following interfaces, a variant of the previous example:

IDL
interface SessionManager {
  Session getSessionForUser(DOMString username);
  readonly attribute unsigned long sessionCount;

  Session iterator = SessionIterator;
};

interface Session {
  readonly attribute DOMString username;
  // ...
};

interface SessionIterator {
  readonly attribute unsigned long remainingSessions;
};

The SessionIterator interface provides some additional information that can be accessed while iterating: the remainingSessions attribute is defined to return the number of sessions remaining to be iterated over.

Since the iterator on SessionManager is declared by referencing SessionIterator, two things need to be defined: how to create an iterator object for a SessionManager, and what the iterator object behavior for a SessionIterator is. These could be defined like so:

An iterator object is created for a SessionManager as follows:

  1. Let manager be the SessionManager object.
  2. Let iterator be a newly created SessionIterator object which has stored internally (a) the SessionManager object it is iterating over, manager, and (b) the username of the last Session object that was returned, which initially is recorded as being undefined.
  3. Return iterator.

The iterator object behavior for a SessionIterator is as follows:

  1. Let iterator be the SessionIterator object.
  2. Let manager be the SessionManager object iterator is iterating over.
  3. Let username be the username of the last Session object that was returned by iterator.
  4. Let sessions be a list of open sessions from manager sorted by username.
  5. If sessions is empty, then return no value.
  6. If username is undefined, then:
    1. Let session be the first Session object in sessions.
    2. Store session’s username as the username of the last Session object that was returned by iterator.
    3. Return session.
  7. Otherwise:
    1. If there is no Session object in sessions with a username that sorts after username, then return no value.
    2. Let session be the first Session object in sessions with a username that sorts after username.
    3. Store session’s username as the username of the last Session object that was returned by iterator.
    4. Return session.

In the ECMAScript language binding, the value returned from the iterator method on a SessionManager object is a SessionIterator object, which itself has a next method that returns the next value to be iterated over:

ECMAScript
// Get an instance of SessionManager.
// Assume that it has sessions for two users, "anna" and "brian".
var sm = getSessionManager();

typeof SessionManager.prototype.iterator;  // Evaluates to "function"
var it = sm.iterator();                    // iterator() returns a SessionIterator object
String(it);                                // Evaluates to "[object SessionIterator]"
typeof SessionIterator.prototype.next;     // Evaluates to "function"

// This loop will alert "anna, 1 to go" and then "brian, 0 to go".
for (;;) {
  try {
    let session = it.next();
    window.alert(session.username + ", " + it.remainingSessions + " to go");
  } catch (e) {
    String(e);                             // Evaluates to "[object StopIteration]"
  }
}

// When using a for..of loop, the SessionIterator object is not accessible.
// This loop will also alert "anna" and then "brian".
for (let session of sm) {
  window.alert(session.username);
}

Amongst an interface and its consequential interfaces, there MUST be at most one iterator declaration and at most one iterator object declaration.

The following extended attributes are applicable to iterators: [Exposed].

No extended attributes defined in this specification are applicable to iterator object declarations.

[48]OperationOrIteratorReturnType OperationOrIteratorRest
 | SpecialOperation
[52]OperationOrIteratorRestIteratorRest
 | OperationRest
[53]IteratorRest"iterator" OptionalIteratorInterfaceOrObject ";"
[54]OptionalIteratorInterfaceOrObjectOptionalIteratorInterface
 | "object"
[55]OptionalIteratorInterface"=" identifier
 | ε

3.3. Dictionaries

A dictionary is a definition (matching Dictionary) used to define an associative array data type with a fixed, ordered set of key–value pairs, termed dictionary members, where keys are strings and values are of a particular type specified in the definition.

dictionary identifier {
  dictionary-members…
};

Dictionaries are always passed by value. In language bindings where a dictionary is represented by an object of some kind, passing a dictionary to a platform object will not result in a reference to the dictionary being kept by that object. Similarly, any dictionary returned from a platform object will be a copy and modifications made to it will not be visible to the platform object.

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 inherit from another dictionary, then the set is empty. Otherwise, the set includes the dictionary E that D inherits from and all of E’s inherited dictionaries.

A dictionary value of type D can have key–value pairs corresponding to the dictionary members defined on D and on any of D’s inherited dictionaries. On a given dictionary value, the presence of each dictionary member is optional, unless that member is specified as required. When specified in the dictionary value, a dictionary member is said to be present, otherwise it is not present. Dictionary members can also optionally have a default value, which is the value to use for the dictionary member when passing a value to a platform object that does not have a specified value. Dictionary members with default values are always considered to be present.

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 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.

dictionary identifier {
  type identifier;
};

If the identifier is followed by a U+003D EQUALS SIGN ("=") and a value (matching DefaultValue), then that gives the dictionary member its default value.

dictionary identifier {
  type identifier = value;
};

When a boolean literal token (true or false), the null token, an integer token, a float token, one of the three special floating point literal values (Infinity, -Infinity or NaN), a string token or the two token sequence [] used as the default value, it is interpreted in the same way as for an operation’s optional argument default value.

If the type of the dictionary member is an enumeration, then its 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 required dictionary member and must be present on the dictionary. A required dictionary member MUST NOT have a default value.

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:

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.

Note

For example, with the following definitions:

IDL
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 are required 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:

IDL
interface Something {
  void f(A a);
};

and this ECMAScript code:

ECMAScript
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.

Dictionaries MUST NOT be used as the type of an attribute, constant or exception field.

The following extended attributes are applicable to dictionaries: [Constructor], [Exposed].

The following extended attributes are applicable to dictionary members: [Clamp], [EnforceRange].

[6]Partial"partial" PartialDefinition
[7]PartialDefinitionPartialInterface
 | PartialDictionary
[11]Dictionary"dictionary" identifier Inheritance "{" DictionaryMembers "}" ";"
[12]DictionaryMembersExtendedAttributeList DictionaryMember DictionaryMembers
 | ε
[13]DictionaryMemberRequired Type identifier Default ";"
[15]PartialDictionary"dictionary" identifier "{" DictionaryMembers "}" ";"
[16]Default"=" DefaultValue
 | ε
[17]DefaultValueConstValue
 | string
 | "[" "]"
[20]Inheritance":" identifier
 | ε
Example

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:

IDL
[Constructor]
interface Point {
  attribute float x;
  attribute float y;
};

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

interface GraphicsContext {
  void drawRectangle(float width, float height, optional PaintOptions options);
};

In an ECMAScript implementation of the IDL, an Object can be passed in for the optional PaintOptions dictionary:

ECMAScript
// Get an instance of GraphicsContext.
var ctx = getGraphicsContext();

// Draw a rectangle.
ctx.drawRectangle(300, 200, { fillPattern: "red", position: new Point(10, 10) });

Both fillPattern and strokePattern are given default values, so if they are omitted, the definition of drawRectangle can assume that they have the given default values and not include explicit wording to handle their non-presence.

3.4. Exceptions

An exception is a definition (matching Exception) used to declare a class of exceptions that can be thrown by implementations.

exception identifier {
  exception-members…
};

Exceptions are different from interfaces in that they can have only constants and exception fields declared on them (together known as exception members), rather than the three types of interface members.

An exception can be defined to inherit from another exception. If the identifier of the exception is followed by a U+003A COLON (":") character and a identifier, then that identifier identifies the inherited exception. The identifier MUST identify an exception.

An exception MUST NOT be declared such that its inheritance hierarchy has a cycle. That is, an exception A cannot inherit from itself, nor can it inherit from another exception B that inherits from A, and so on.

An object that implements an exception that inherits from another also implements that inherited exception. The object therefore will also have members that correspond to the exception members from the inherited exception.

exception Base {
  exception-members…
};

exception Derived : Base {
  exception-members…
};

Exceptions have an associated message, a DOMString, which is exposed on an exception object in a language binding-specific manner.

Exceptions also have an associated name, also a DOMString, which is exposed on an exception object in a language binding-specific manner. The name of an exception is intended to be used to distinguish between the different kinds of exceptions that can be represented by the given IDL exception.

Each exception field (matching ExceptionField) is specified as a type (matching Type) followed by an identifier (given by an identifier token following the type). If the Type is an identifier or an identifier followed by ?, then the identifier MUST identify an interface, enumeration, callback function or typedef.

The type of the exception field, after resolving typedefs, MUST NOT be a nullable or non-nullable version of any of the following types:

Exception fields are similar to attributes in that they will correspond to attributes of the same name and type on exception objects that are thrown by implementations.

exception identifier {
  type identifier;
};

The identifier of an exception field MUST NOT be the same as that of another exception member, and it MUST NOT be “name” or “message”.

Each exception member can be preceded by a list of extended attributes (matching ExtendedAttributeList), which can control how the exception member will be handled in language bindings.

exception identifier {

  [extended-attributes]
  const type identifier = value;

  [extended-attributes]
  type identifier;
};

A number of predefined exceptions are also available to be thrown from specifications. These predefined exceptions correspond to the ECMAScript error objects ([ECMA-262], section 19.5). Specifically, the list of predefined exceptions is as follows: Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError and URIError. The meaning of each of these exceptions matches those of the corresponding Error object in the ECMAScript specification. These exceptions are not considered to have any exception members.

The identifier of an exception MUST NOT be the same as one of the predefined exceptions.

Exceptions can be thrown, optionally with a specific message and name, and with a set of values to assign to the exception’s fields. If a name is not specified, it is assumed to be the same as the identifier of the exception. The resulting behavior from throwing an exception is language binding-specific.

Note

See section 4.12 below for details on what throwing an exception entails in the ECMAScript language binding.

Warning

Authors of future Web platform specifications SHOULD NOT mint new IDL exceptions but instead should use DOMException and distinguish different kinds of exceptions by their name and not by an integer code. The name will be exposed in ECMAScript using a “name” property on the exception object. One valid reason to mint new IDL exceptions is if additional exception fields are required. If a predefined exception matches the meaning of the exception to be thrown, it SHOULD be used in preference to minting an exception name.

If new exception names are to be minted, their names SHOULD use the same naming scheme as the built-in ECMAScript error objects; for example, “HierarchyRequestError” or “NotFoundError”, if names are being given to the DOM Core exceptions. Any new IDL exceptions SHOULD be named similarly.

Note

There is no IDL syntax for declaring exception names. In prose, an exception of a particular name can be thrown by using wording like the following:

Throw a DOMException with name HierarchyRequestError and message “Cannot append that Node here”.

The following extended attribute is applicable to exceptions: [NoInterfaceObject].

No extended attributes defined in this specification are applicable to exception fields.

[18]Exception"exception" identifier Inheritance "{" ExceptionMembers "}" ";"
[19]ExceptionMembersExtendedAttributeList ExceptionMember ExceptionMembers
 | ε
[20]Inheritance":" identifier
 | ε
[64]ExceptionMemberConst
 | ExceptionField
[65]ExceptionFieldType identifier ";"
Example

The following example demonstrates how a reduced version of DOM Core’s DOMException might be defined for three of the existing types of exception and one new one. Specific types of DOMExceptions have historically been distinguished only by an integer code, but in this reformulation exception names are used instead. The new exception kind here is not given a legacy integer code.

IDL
exception DOMException {
  const unsigned short INDEX_SIZE_ERR = 1;
  const unsigned short DOMSTRING_SIZE_ERR = 2;
  const unsigned short HIERARCHY_REQUEST_ERR = 3;

  unsigned short code;
};

Assume that the specification defines that throwing a DOMException with a particular name uses a corresponding value for the code field, as follows:

NameValue of code
IndexSizeErrorINDEX_SIZE_ERR
DOMStringSizeErrorDOMSTRING_SIZE_ERR
HierarchyRequestErrorHIERARCHY_REQUEST_ERR
InsufficientBlingError0

In an ECMAScript implementation, the existing types of DOMExceptions could be distinguished by code, and the existing ones and the new ones could be distinguished by type:

ECMAScript
try {
  document.appendChild(document);
} catch (e) {
  // The traditional way, by looking at the code.
  if (e.code == DOMException.HIERARCHY_REQUEST_ERR) {
    ...
  }

  // By looking at the name.
  if (e.name == "HierarchyRequestError") {
    ...
  }
  if (e.name == "InsufficientBlingError") {
    e.code;  // This would evaluate to 0.
    ...
  }
}

Note that using e instanceof ExceptionClass can return false if the exception object comes from a different document than the global scope of the running script, even if the exception is an instance of the ExceptionClass in its own document. For this reason, authors are suggested not to use instanceof to perform exception type testing.

3.5. 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 { enumeration-values… };

The enumeration values are specified as a comma-separated list of string literals. The list of enumeration values MUST NOT include duplicates.

The behavior when a string value that is not one 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 ECMAScript binding, assignment of an invalid string value to an attribute is ignored, while passing such a value as an operation argument results in an exception being thrown.

No extended attributes defined in this specification are applicable to enumerations.

[21]Enum"enum" identifier "{" EnumValueList "}" ";"
[22]EnumValueListstring EnumValueListComma
[23]EnumValueListComma"," EnumValueListString
 | ε
[24]EnumValueListStringstring EnumValueListComma
 | ε
Example

The following IDL fragment defines an enumeration that is used as the type of an attribute and an operation argument:

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

interface Meal {
  attribute MealType type;
  attribute float size;     // in grams

  void initialize(MealType type, float size);
};

An ECMAScript 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.

ECMAScript
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.

3.6. Callback functions

Editorial note

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 ReturnType 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: [TreatNonObjectAsNull].

[3]CallbackOrInterface"callback" CallbackRestOrInterface
 | Interface
[4]CallbackRestOrInterfaceCallbackRest
 | Interface
[25]CallbackRestidentifier "=" ReturnType "(" ArgumentList ")" ";"
Example

The following IDL fragment defines a callback function used for an API that invokes a user-defined function when an operation is complete.

IDL
callback AsyncOperationCallback = void (DOMString status);

interface AsyncOperations {
  void performOperation(AsyncOperationCallback whenFinished);
};

In the ECMAScript language binding, a Function object is passed as the operation argument.

ECMAScript
var ops = getAsyncOperations();  // Get an instance of AsyncOperations.

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

3.7. 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 Type), and the identifier token following the type gives the name.

The Type MUST NOT identify the same or another typedef.

No extended attributes defined in this specification are applicable to typedefs.

[26]Typedef"typedef" Type identifier ";"
Example

The following IDL fragment demonstrates the use of typedefs to allow the use of a short identifier instead of a long sequence type.

IDL
interface Point {
  attribute float x;
  attribute float y;
};

typedef sequence<Point> Points;

interface Widget {
  boolean pointWithinBounds(Point p);
  boolean allPointsWithinBounds(Points ps);
};

3.8. Implements statements

An implements statement is a definition (matching ImplementsStatement) used to declare that all objects implementing an interface A (identified by the first identifier) MUST additionally implement interface B (identified by the second identifier), including all other interfaces that B inherits from.

identifier-A implements identifier-B;

Transitively, if objects implementing B are declared with an implements statement to additionally implement interface C, then all objects implementing A do additionally implement interface C.

The two identifiers MUST identify two different interfaces.

The interface identified on the left-hand side of an implements statement MUST NOT inherit from the interface identifier on the right-hand side, and vice versa. Both identified interfaces also MUST NOT be callback interfaces.

If each implements statement is considered to be an edge in a directed graph, from a node representing the interface on the left-hand side of the statement to a node representing the interface on the right-hand side, then this graph MUST NOT have any cycles.

Interfaces that a given object implements are partitioned into those that are considered supplemental interfaces and those that are not. An interface A is considered to be a supplemental interface of an object O if:

  • O implements a different interface B, and the IDL states that B implements A; or
  • O implements a different supplemental interface C, and C inherits from A.
Note

Specification authors are discouraged from writing implements statements where the interface on the left-hand side is a supplemental interface. For example, if author 1 writes:

IDL
interface Window { ... };
interface SomeFunctionality { ... };
Window implements SomeFunctionality;

and author 2 later writes:

IDL
interface Gizmo { ... };
interface MoreFunctionality { ... };
SomeFunctionality implements MoreFunctionality;
Gizmo implements SomeFunctionality;

then it might be the case that author 2 is unaware of exactly which interfaces already are used on the left-hand side of an implements SomeFunctionality statement, and so has required more objects implement MoreFunctionality than he or she expected.

Better in this case would be for author 2 to write:

IDL
interface Gizmo { ... };
interface MoreFunctionality { ... };
Gizmo implements SomeFunctionality;
Gizmo implements MoreFunctionality;

The consequential interfaces of an interface A are:

  • each interface B where the IDL states A implements B;
  • each interface that a consequential interface of A inherits from; and
  • each interface D where the IDL states that C implements D, where C is a consequential interface of A.

For a given interface, there MUST NOT be any member defined on any of its consequential interfaces whose identifier is the same as any other member defined on any of those consequential interfaces or on the original interface itself.

Note

For example, that precludes the following:

IDL
interface A { attribute long x; };
interface B { attribute long x; };
A implements B;  // B::x would clash with A::x

interface C { attribute long y; };
interface D { attribute long y; };
interface E : D { };
C implements E;  // D::y would clash with C::y

interface F { };
interface H { attribute long z; };
interface I { attribute long z; };
F implements H;
F implements I;  // H::z and I::z would clash when mixed in to F

No extended attributes defined in this specification are applicable to implements statements.

[27]ImplementsStatementidentifier "implements" identifier ";"
Example

The following IDL fragment defines two interfaces, stating that one interface is always implemented on objects implementing the other.

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

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

Entry implements Observable;

An ECMAScript implementation would thus have an “addEventListener” property in the prototype chain of every Entry:

ECMAScript
var e = getEntry();          // Obtain an instance of Entry.
typeof e.addEventListener;  // Evaluates to "function".

Note that it is not the case that all Observable objects implement Entry.

3.9. Objects implementing interfaces

In a given implementation of a set of IDL fragments, an object can be described as being a platform object, a user object, or neither. There are three kinds of object that are considered to be platform objects:

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 ECMAScript 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 ECMAScript 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 recognised 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 an ECMAScript 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 ECMAScript library that implement the Node interface will not be treated as platform objects that implement Node by the browser implementation.

User objects are those that authors would create, implementing callback interfaces that the Web APIs use to be able to invoke author-defined operations or to send and receive values to the author’s program through manipulating the object’s attributes. In a web page, an ECMAScript object that implements the EventListener interface, which is used to register a callback that the DOM Events implementation invokes, would be considered to be a user object.

Note that user objects can only implement callback interfaces and platform objects can only implement non-callback interfaces.

3.10. Types

This section lists the types supported by Web IDL, the set of values 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, unresticted float, double and unrestricted double.

The primitive types are boolean and the numeric types.

The object type and all interface types are known as object types.

Every type has a type name, which is a string, not necessarily unique, that identifies the type. Each sub-section below defines what the type name is for each type.

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.

[74]TypeSingleType
 | UnionType TypeSuffix
[75]SingleTypeNonAnyType
 | "any" TypeSuffixStartingWithArray
[76]UnionType"(" UnionMemberType "or" UnionMemberType UnionMemberTypes ")"
[77]UnionMemberTypeNonAnyType
 | UnionType TypeSuffix
 | "any" "[" "]" TypeSuffix
[78]UnionMemberTypes"or" UnionMemberType UnionMemberTypes
 | ε
[79]NonAnyTypePrimitiveType TypeSuffix
 | PromiseType Null
 | "ByteString" TypeSuffix
 | "DOMString" TypeSuffix
 | identifier TypeSuffix
 | "sequence" "<" Type ">" Null
 | "object" TypeSuffix
 | "Date" TypeSuffix
 | "RegExp" TypeSuffix
[80]ConstTypePrimitiveType Null
 | identifier Null
[81]PrimitiveTypeUnsignedIntegerType
 | UnrestrictedFloatType
 | "boolean"
 | "byte"
 | "octet"
[82]UnrestrictedFloatType"unrestricted" FloatType
 | FloatType
[83]FloatType"float"
 | "double"
[84]UnsignedIntegerType"unsigned" IntegerType
 | IntegerType
[85]IntegerType"short"
 | "long" OptionalLong
[86]OptionalLong"long"
 | ε
[87]PromiseType"Promise" "<" ReturnType ">"
[88]TypeSuffix"[" "]" TypeSuffix
 | "?" TypeSuffixStartingWithArray
 | ε
[89]TypeSuffixStartingWithArray"[" "]" TypeSuffix
 | ε
[90]Null"?"
 | ε

3.10.1. any

The any type is the union of all other possible non-union types. Its type name is “Any”.

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.)

3.10.2. boolean

The boolean type has two values: true and false.

boolean constant values in IDL are represented with the true and false tokens.

The type name of the boolean type is “Boolean”.

3.10.3. 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.

The type name of the byte type is “Byte”.

3.10.4. 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.

The type name of the octet type is “Octet”.

3.10.5. 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.

The type name of the short type is “Short”.

3.10.6. 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.

The type name of the unsigned short type is “UnsignedShort”.

3.10.7. 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.

The type name of the long type is “Long”.

3.10.8. 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.

The type name of the unsigned long type is “UnsignedLong”.

3.10.9. 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.

The type name of the long long type is “LongLong”.

3.10.10. 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.

The type name of the unsigned long long type is “UnsignedLongLong”.

3.10.11. 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 float tokens.

The type name of the float type is “Float”.

Warning

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 an ECMAScript Number.

3.10.12. 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 and non-finite. [IEEE-754]

unrestricted float constant values in IDL are represented with float tokens.

The type name of the unrestricted float type is “UnrestrictedFloat”.

3.10.13. 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 float tokens.

The type name of the double type is “Double”.

3.10.14. 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 and non-finite. [IEEE-754]

unrestricted double constant values in IDL are represented with float tokens.

The type name of the unrestricted double type is “UnrestrictedDouble”.

3.10.15. DOMString

The DOMString type corresponds to the set of all possible sequences of code units. Such sequences are commonly interpreted as UTF-16 encoded strings [RFC2781] although this is not required. While DOMString is defined to be an OMG IDL boxed sequence<unsigned short> valuetype in DOM Level 3 Core ([DOM3CORE], section 1.2.1), this document defines DOMString to be an intrinsic type so as to avoid special casing that sequence type in various situations where a string is required.

Note

Note also that null is not a value of type DOMString. To allow null, a nullable DOMString, written as DOMString? in IDL, needs to be used.

Nothing in this specification requires a DOMString value to be a valid UTF-16 string. For example, a DOMString value might include unmatched surrogate pair characters. However, authors of specifications using Web IDL might want to obtain a sequence of Unicode characters given a particular sequence of code units. The following algorithm defines a way to convert a DOMString to a sequence of Unicode characters:

  1. Let S be the DOMString value.
  2. Let n be the length of S.
  3. Initialize i to 0.
  4. Initialize U to be an empty sequence of Unicode characters.
  5. While i < n:
    1. Let c be the code unit in S at index i.
    2. Depending on the value of c:
      c < 0xD800 or c > 0xDFFF
      Append to U the Unicode character with code point c.
      0xDC00 ≤ c ≤ 0xDFFF
      Append to U a U+FFFD REPLACEMENT CHARACTER.
      0xD800 ≤ c ≤ 0xDBFF
      1. If i = n−1, then append to U a U+FFFD REPLACEMENT CHARACTER.
      2. Otherwise, i < n−1:
        1. Let d be the code unit in S at index i+1.
        2. If 0xDC00 ≤ d ≤ 0xDFFF, then:
          1. Let a be c & 0x3FF.
          2. Let b be d & 0x3FF.
          3. Append to U the Unicode character with code point 216+210a+b.
          4. Set i to i+1.
        3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a U+FFFD REPLACEMENT CHARACTER.
    3. Set i to i+1.
  6. Return U.

There is no way to represent a constant DOMString value in IDL, although DOMString dictionary member and operation optional argument default values can be specified using a string literal.

The type name of the DOMString type is “String”.

3.10.16. ByteString

The ByteString type corresponds to the set of all possible sequences of bytes. Such sequences might be interpreted as UTF-8 encoded strings [RFC3629] or strings in some other 8-bit-per-code-unit encoding, although this is not required.

There is no way to represent a constant ByteString value in IDL.

The type name of the ByteString type is “ByteString”.

Warning

Specifications SHOULD only use ByteString for interfacing with protocols that use bytes and strings interchangably, 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. Sequences, arrays or Typed Arrays with octet or byte elements SHOULD be used for holding 8 bit data rather than ByteString. [TYPEDARRAYS]

3.10.17. 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?.

The type name of the object type is “Object”.

3.10.18. 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.

For non-callback interfaces, an IDL value of the interface type is represented just by an object reference. For callback interfaces, 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 ECMAScript objects, the callback context is used to hold a reference to the incumbent script [HTML] at the time the Object value is converted to an IDL callback interface type value. See section 4.2.19 below.

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.

The type name of an interface type is the identifier of the interface.

3.10.19. 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.

There is no way to represent a constant dictionary value in IDL.

The type name of a dictionary type is the identifier of the dictionary.

3.10.20. 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 default values can be specified using a string literal.

The type name of an enumeration type is the identifier of the enumeration.

3.10.21. 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.

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 script [HTML] at the time an ECMAScript Object value is converted to an IDL callback function type value. See section 4.2.22 below.

There is no way to represent a constant callback function value in IDL.

The type name of a callback function type is the identifier of the callback function.

3.10.22. 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 QUESTION MARK ("?") character after an existing type. The inner type MUST NOT be any, another nullable type, or a union type that itself has 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 inner type would be represented, or with the null token.

The type name of a nullable type is the concatenation of the type name of the inner type T and the string “OrNull”.

Example

For example, a type that allows the values true, false and null is written as boolean?:

IDL
interface MyConstants {
  const boolean? ARE_WE_THERE_YET = 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:

IDL
interface Node {
  readonly attribute DOMString? namespaceURI;
  readonly attribute Node? parentNode;
  // ...
};

3.10.23. Sequences — sequence<T>

The sequence<T> type is a parameterized type whose values are (possibly zero-length) sequences 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.

There is no way to represent a constant sequence value in IDL.

Sequences MUST NOT be used as the type of an attribute, constant or exception field.

Note

This restriction exists so that it is clear to specification writers and API users that 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. Another option is to use an array type, which can be used as the type of an attribute.

The type name of a sequence type is the concatenation of the type name for T and the string “Sequence”.

3.10.24. Arrays — T[]

The T[] type is a parameterized type. The values of this type are non-null references to arrays of values of type T. Unlike sequences, arrays are passed by reference. Passing an array to a platform object could result in that array being modified by the object. An array returned from a platform object might also be modified by the object, and any modifications to the array performed by user code might be acted upon by the platform object.

The element type of an array MUST NOT be a sequence or dictionary type.

Arrays can either be fixed length or variable length. Fixed length arrays cannot have their length changed by user code after they have been created, while variable length arrays can. Unless otherwise specified, arrays are fixed length.

Arrays can also be designated as being read only. User code cannot modify the values of read only array elements. If an array is read only, then it is also implicitly fixed length.

There is no way to represent a constant array value in IDL.

The type name of an array type is the concatenation of the type name for T and the string “Array”.

Example

See section 4.2.25 for an example using array types.

3.10.25. 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” [ECMA-262]. See section 25.4 of the ECMAScript specification for details on the semantics of promise objects.

There is no way to represent a promise value in IDL.

The type name of a promise type is the concatenation of the type name for T and the string “Promise”.

3.10.26. 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.

Note

For example, you might write (Node or DOMString) or (float or float[]). When applying a [] or ? 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 (float or (Date or Event) or (Node or DOMString)?) the member types are float, (Date 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 is a set of types determined as follows:

  1. Let T be the union type.
  2. Initialize S to ∅.
  3. For each member type U of T:
    1. If U is a nullable type, then set U to be the inner type of U.
    2. If U is a union type, then add to S the flattened member types of U.
    3. Otherwise, U is not a union type. Add U to S.
  4. Return S.
Note

For example, the flattened member types of the union type (Node or (Date or Event) or (XMLHttpRequest or DOMString)? or (float[] or NodeList)[]) are the six types Node, Date, Event, XMLHttpRequest, DOMString and (float[] 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.
  2. Initialize n to 0.
  3. For each member type U of T:
    1. If U is a nullable type, then:
      1. Set n to n + 1.
      2. Set U to be the inner type of U.
    2. If U is a union type, then:
      1. Let m be the number of nullable member types of U.
      2. Set n to n + m.
  4. Return n.

The any type MUST NOT be used as a 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:

Each pair of flattened member types in a union type, T and U, MUST be distinguishable.

Union type constant values in IDL are represented in the same way that constant values of their member types would be represented.

The type name of a union type is formed by taking the type names of each member type, in order, and joining them with the string “Or”.

[76]UnionType"(" UnionMemberType "or" UnionMemberType UnionMemberTypes ")"
[77]UnionMemberTypeNonAnyType
 | UnionType TypeSuffix
 | "any" "[" "]" TypeSuffix
[78]UnionMemberTypes"or" UnionMemberType UnionMemberTypes
 | ε
[79]NonAnyTypePrimitiveType TypeSuffix
 | PromiseType Null
 | "ByteString" TypeSuffix
 | "DOMString" TypeSuffix
 | identifier TypeSuffix
 | "sequence" "<" Type ">" Null
 | "object" TypeSuffix
 | "Date" TypeSuffix
 | "RegExp" TypeSuffix

3.10.27. Date

The Date type is a type that represents an instant in time with millisecond accuracy. The instants in time that this type can represent are the same that can be represented with ECMAScript Date objects ([ECMA-262], section 20.3) – namely, every millisecond in the 200,000,000 days centered around midnight of 1 January, 1970 UTC, except for any millisecond that is part of an inserted leap second, because they cannot be represented by this type.

An additional value that this type can represent is one that indicates an indeterminate or undefined time, which we write as undefined.

There is no way to represent a constant Date value in IDL.

The type name of the Date type is “Date”.

3.10.28. RegExp

The RegExp type is a type whose values are references to objects that represent regular expressions. The particular regular expression language and the features it supports is language binding specific.

There is no way to represent a constant RegExp value in IDL.

The type name of the RegExp type is “RegExp”.

3.11. Extended attributes

An extended attribute is an annotation that can appear on definitions, interface members, exception 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 six grammar symbols to determine which form (or forms) it is in:

Grammar symbol Form Example
ExtendedAttributeNoArgs takes no arguments [Replaceable]
ExtendedAttributeArgList takes an argument list [Constructor(float x, float y)]
ExtendedAttributeNamedArgList takes a named argument list [NamedConstructor=Image(DOMString src)]
ExtendedAttributeIdent takes an identifier [PutForwards=name]
ExtendedAttributeIdentList takes an identifier list [Exposed=(Window,Worker)]
ExtendedAttributeTypePair takes a type pair [MapClass(DOMString, object)]

This specification defines a number of extended attributes that are applicable to the ECMAScript language binding, which are described in section 4.3. Each extended attribute definition will state which of the above six forms are allowed.

[66]ExtendedAttributeList"[" ExtendedAttribute ExtendedAttributes "]"
 | ε
[67]ExtendedAttributes"," ExtendedAttribute ExtendedAttributes
 | ε
[68]ExtendedAttribute "(" ExtendedAttributeInner ")" ExtendedAttributeRest
 | "[" ExtendedAttributeInner "]" ExtendedAttributeRest
 | "{" ExtendedAttributeInner "}" ExtendedAttributeRest
 | Other ExtendedAttributeRest
[69]ExtendedAttributeRestExtendedAttribute
 | ε
[70]ExtendedAttributeInner "(" ExtendedAttributeInner ")" ExtendedAttributeInner
 | "[" ExtendedAttributeInner "]" ExtendedAttributeInner
 | "{" ExtendedAttributeInner "}" ExtendedAttributeInner
 | OtherOrComma ExtendedAttributeInner
 | ε
[71]Other integer
 | float
 | identifier
 | string
 | other
 | "-"
 | "-Infinity"
 | "."
 | "..."
 | ":"
 | ";"
 | "<"
 | "="
 | ">"
 | "?"
 | "ByteString"
 | "Date"
 | "DOMString"
 | "Infinity"
 | "NaN"
 | "RegExp"
 | "any"
 | "boolean"
 | "byte"
 | "double"
 | "false"
 | "float"
 | "long"
 | "null"
 | "object"
 | "octet"
 | "or"
 | "optional"
 | "sequence"
 | "short"
 | "true"
 | "unsigned"
 | "void"
 | ArgumentNameKeyword
[73]OtherOrCommaOther
 | ","
[92]IdentifierListidentifier Identifiers
[93]Identifiers"," identifier Identifiers
 | ε
[94]ExtendedAttributeNoArgsidentifier
[95]ExtendedAttributeArgListidentifier "(" ArgumentList ")"
[96]ExtendedAttributeIdentidentifier "=" identifier
[97]ExtendedAttributeIdentListidentifier "=" "(" IdentifierList ")"
[98]ExtendedAttributeNamedArgListidentifier "=" identifier "(" ArgumentList ")"
[99]ExtendedAttributeTypePairidentifier "(" Type "," Type ")"

4. ECMAScript binding

This section describes how definitions written with the IDL defined in section 3 correspond to particular constructs in ECMAScript, as defined by the ECMAScript Language Specification 6th Edition [ECMA-262].

Objects defined in this section have internal properties as described in ECMA-262 sections 9.1 and 9.3.1 unless otherwise specified, in which case one or more of the following are redefined in accordance with the rules for exotic objects: [[Call]], [[DefineOwnProperty]], [[GetOwnProperty]] and [[Delete]] and [[HasInstance]].

To influence the result of calling Object.prototype.toString on an object, a class string is defined for some objects.

Note

Section 4.1 below describes how Object.prototype.toString takes an object’s class string into account.

Unless otherwise specified, the [[Extensible]] internal property of objects defined in this section has the value true.

Unless otherwise specified, the [[Prototype]] internal property of objects defined in this section is the Object prototype object.

If an object is defined to be a function object, then it has characteristics as follows:

Editorial note

The list above needs updating for the latest ES6 draft.

Algorithms in this section use the conventions described in ECMA-262 section 5.2, such as the use of steps and substeps, the use of mathematical operations, and so on. The ToBoolean, ToNumber, ToUint16, ToInt32, ToUint32, ToString, ToObject, IsAccessorDescriptor and IsDataDescriptor abstract operations and the Type(x) notation referenced in this section are defined in ECMA-262 sections 6 and 7.

When an algorithm says to “throw a SomethingError” then this means to construct a new ECMAScript SomethingError object and to throw it, just as the algorithms in ECMA-262 do.

When an algorithm says to “throw StopIteration” then this means to throw the unique StopIteration object.

Editorial note

The StopIteration value is currently defined in a strawman wiki page and this will need to updated once it has been added to the ES6 spec.

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.

Example

Consider the following algorithm:

  1. Let x be the ECMAScript value passed in to this algorithm.
  2. Let y be the result of calling ToString(x).
  3. 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.

4.1. ECMAScript environment

In an ECMAScript implementation of a given set of IDL fragments, there will exist a number of ECMAScript objects that correspond to definitions in those IDL fragments. These objects are termed the initial objects, and comprise the following:

Each ECMAScript global environment ([ECMA-262], section 8.2) MUST have its own unique set of each of the initial objects, created before control enters any ECMAScript execution context associated with the environment, but after the global object for that environment is created. The [[Prototype]]s of all initial objects in a given global environment MUST come from that same global environment.

Example

In an HTML user agent, multiple global environments 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:

HTML
<!DOCTYPE html>
<title>Different global environments</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>

Unless otherwise specified, each ECMAScript global environment exposes all interfaces and exceptions that the implementation supports. If a given ECMAScript global environment does not expose an interface or exception, then the requirements given in section 4.5 and section 4.10 are not followed for that interface or exception.

Note

This allows, for example, ECMAScript global environments for Web Workers to expose different sets of supported interfaces from those exposed in environments for Web pages.

As soon as any ECMAScript global environment is created, the following steps MUST be performed:

  1. Let F be a function object whose behavior when invoked is as follows:
    1. If O is a platform object, interface prototype object or exception interface prototype object, then return the String value that is the result of concatenating "[object ", O’s class string, and "]".
    2. Otherwise, return the result of calling %ObjProto_toString% ([ECMA-262], section 6.1.7.4) with O as its single argument value.
  2. Let P be the Object.prototype object.
  3. Call the [[DefineOwnProperty]] internal method on P with property name “toString”, Property Descriptor { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true, [[Value]]: F } and Boolean flag false.
Note

Requiring particular behavior of a replaced Object.prototype.toString rather than requiring exotic object semantics of the built-in Object.prototype.toString is done to avoid making it impossible to implement APIs described with Web IDL natively in ECMAScript with Proxies.

There is one built-in ECMAScript function that behaves differently for platform objects with this custom Object.prototype.toString behavior compared to the built-in Object.prototype.toString: Function.prototype.bind will return a new Function object with a length property with a non-zero value if the object has a legacy caller that takes at least one argument.

4.2. ECMAScript type mapping

This section describes how types in the IDL map to types in ECMAScript.

Each sub-section below describes how values of a given IDL type are represented in ECMAScript. For each IDL type, it is described how ECMAScript 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 ECMAScript values when returned from a platform object.

4.2.1. any

Since the IDL any type is the union of all other IDL types, it can correspond to any ECMAScript value type.

How to convert an ECMAScript value to an IDL any value depends on the type of the ECMAScript value:

The undefined value
The IDL value is an object reference to a special object that represents the ECMAScript undefined value.
The null value
The IDL value is the null object? reference.
A Boolean value
The IDL value is the boolean value that represents the same truth value.
A Number value
The IDL value is that which is obtained by following the rules for converting the Number to an IDL unrestricted double value, as described in section 4.2.15, below.
A String value
The IDL value is that which is obtained by following the rules for converting the String to an IDL DOMString value, as described in section 4.2.16, below.
An object value
The IDL value is an object value that references the same object.

An IDL any value is converted to an ECMAScript value as follows. If the value is an object reference to a special object that represents an ECMAScript undefined value, then it is converted to the ECMAScript undefined value. Otherwise, the rules for converting the specific type of the IDL any value as described in the remainder of this section are performed.

4.2.2. void

The only place that the void type may appear in IDL is as the return type of an operation. Functions on platform objects that implement an operation whose IDL specifies a void return type MUST return the undefined value.

ECMAScript functions that implement an operation whose IDL specifies a void return type MAY return any value, which will be discarded.

4.2.3. boolean

An ECMAScript value V is converted to an IDL boolean value by running the following algorithm:

  1. Let x be the result of computing ToBoolean(V).
  2. Return the IDL boolean value that is the one that represents the same truth value as the ECMAScript Boolean value x.

The IDL boolean value true is converted to the ECMAScript true value and the IDL boolean value false is converted to the ECMAScript false value.

4.2.4. byte

An ECMAScript value V is converted to an IDL byte value by running the following algorithm:

  1. Initialize x to ToNumber(V).
  2. If the conversion to an IDL value is being performed due to any of the following: then:
    1. If x is NaN, +∞, or −∞, then throw a TypeError.
    2. Set x to sign(x) * floor(abs(x)).
    3. If x < −27 or x > 27 − 1, then throw a TypeError.
    4. Return the IDL byte value that represents the same numeric value as x.
  3. If x is not NaN and the conversion to an IDL value is being performed due to any of the following: then:
    1. Set x to min(max(x, −27), 27 − 1).
    2. Round x to the nearest integer, choosing the even integer if it lies halfway between two, and choosing +0 rather than −0.
    3. Return the IDL byte value that represents the same numeric value as x.
  4. If x is NaN, +0, −0, +∞, or −∞, then return the IDL byte value that represents 0.
  5. Set x to sign(x) * floor(abs(x)).
  6. Set x to x modulo 28.
  7. If x ≥ 27, return the IDL byte value that represents the same numeric value as x − 28. Otherwise, return the IDL byte value that represents the same numeric value as x.

The result of converting an IDL byte value to an ECMAScript 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].

4.2.5. octet

An ECMAScript value V is converted to an IDL octet value by running the following algorithm:

  1. Initialize x to ToNumber(V).
  2. If the conversion to an IDL value is being performed due to any of the following: then:
    1. If x is NaN, +∞, or −∞, then throw a TypeError.
    2. Set x to sign(x) * floor(abs(x)).
    3. If x < 0 or x > 28 − 1, then throw a TypeError.
    4. Return the IDL octet value that represents the same numeric value as x.
  3. If x is not NaN and the conversion to an IDL value is being performed due to any of the following: then:
    1. Set x to min(max(x, 0), 28 − 1).
    2. Round x to the nearest integer, choosing the even integer if it lies halfway between two, and choosing +0 rather than −0.
    3. Return the IDL octet value that represents the same numeric value as x.
  4. If x is NaN, +0, −0, +∞, or −∞, then return the IDL octet value that represents 0.
  5. Set x to sign(x) * floor(abs(x)).
  6. Set x to x modulo 28.
  7. Return the IDL octet value that represents the same numeric value as x.

The result of converting an IDL octet value to an ECMAScript 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].

4.2.6. short

An ECMAScript value V is converted to an IDL short value by running the following algorithm:

  1. Initialize x to ToNumber(V).
  2. If the conversion to an IDL value is being performed due to any of the following: then:
    1. If x is NaN, +∞, or −∞, then throw a TypeError.
    2. Set x to sign(x) * floor(abs(x)).
    3. If x < −215 or x > 215 − 1, then throw a TypeError.
    4. Return the IDL short value that represents the same numeric value as x.
  3. If x is not NaN and the conversion to an IDL value is being performed due to any of the following: then:
    1. Set x to min(max(x, −215), 215 − 1).
    2. Round x to the nearest integer, choosing the even integer if it lies halfway between two, and choosing +0 rather than −0.
    3. Return the IDL short value that represents the same numeric value as x.
  4. If x is NaN, +0, −0, +∞, or −∞, then return the IDL short value that represents 0.
  5. Set x to sign(x) * floor(abs(x)).
  6. Set x to x modulo 216.
  7. If x ≥ 215, return the IDL short value that represents the same numeric value as x − 216. Otherwise, return the IDL short value that represents the same numeric value as x.

The result of converting an IDL short value to an ECMAScript 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].

4.2.7. unsigned short

An ECMAScript value V is converted to an IDL unsigned short value by running the following algorithm:

  1. Initialize x to ToNumber(V).
  2. If the conversion to an IDL value is being performed due to any of the following: then:
    1. If x is NaN, +∞, or −∞, then throw a TypeError.
    2. Set x to sign(x) * floor(abs(x)).
    3. If x < 0 or x > 216 − 1, then throw a TypeError.
    4. Return the IDL unsigned short value that represents the same numeric value as x.
  3. If x is not NaN and the conversion to an IDL value is being performed due to any of the following: then:
    1. Set x to min(max(x, 0), 216 − 1).
    2. Round x to the nearest integer, choosing the even integer if it lies halfway between two, and choosing +0 rather than −0.
    3. Return the IDL unsigned short value that represents the same numeric value as x.
  4. Set x to ToUint16(x).
  5. Return the IDL unsigned short value that represents the same numeric value as x.

The result of converting an IDL unsigned short value to an ECMAScript 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].

4.2.8. long

An ECMAScript value V is converted to an IDL long value by running the following algorithm:

  1. Initialize x to ToNumber(V).
  2. If the conversion to an IDL value is being performed due to any of the following: then:
    1. If x is NaN, +∞, or −∞, then throw a TypeError.
    2. Set x to sign(x) * floor(abs(x)).
    3. If x < −231 or x > 231 − 1, then throw a TypeError.
    4. Return the IDL long value that represents the same numeric value as x.
  3. If x is not NaN and the conversion to an IDL value is being performed due to any of the following: then:
    1. Set x to min(max(x, −231), 231 − 1).
    2. Round x to the nearest integer, choosing the even integer if it lies halfway between two, and choosing +0 rather than −0.
    3. Return the IDL long value that represents the same numeric value as x.
  4. Set x to ToInt32(x).
  5. Return the IDL long value that represents the same numeric value as x.

The result of converting an IDL long value to an ECMAScript 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].

4.2.9. unsigned long

An ECMAScript value V is converted to an IDL unsigned long value by running the following algorithm:

  1. Initialize x to ToNumber(V).
  2. If the conversion to an IDL value is being performed due to any of the following: then:
    1. If x is NaN, +∞, or −∞, then throw a TypeError.
    2. Set x to sign(x) * floor(abs(x)).
    3. If x < 0 or x > 232 − 1, then throw a TypeError.
    4. Return the IDL unsigned long value that represents the same numeric value as x.
  3. If x is not NaN and the conversion to an IDL value is being performed due to any of the following: then:
    1. Set x to min(max(x, 0), 232 − 1).
    2. Round x to the nearest integer, choosing the even integer if it lies halfway between two, and choosing +0 rather than −0.
    3. Return the IDL unsigned long value that represents the same numeric value as x.
  4. Set x to ToUint32(x).
  5. Return the IDL unsigned long value that represents the same numeric value as x.

The result of converting an IDL unsigned long value to an ECMAScript 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].

4.2.10. long long

An ECMAScript value V is converted to an IDL long long value by running the following algorithm:

  1. Initialize x to ToNumber(V).
  2. If the conversion to an IDL value is being performed due to any of the following: then:
    1. If x is NaN, +∞, or −∞, then throw a TypeError.
    2. Set x to sign(x) * floor(abs(x)).
    3. If x < −253 + 1 or x > 253 − 1, then throw a TypeError.
    4. Return the IDL long long value that represents the same numeric value as x.
  3. If x is not NaN and the conversion to an IDL value is being performed due to any of the following: then:
    1. Set x to min(max(x, −253 + 1), 253 − 1).
    2. Round x to the nearest integer, choosing the even integer if it lies halfway between two, and choosing +0 rather than −0.
    3. Return the IDL long long value that represents the same numeric value as x.
  4. If x is NaN, +0, −0, +∞, or −∞, then return the IDL long long value that represents 0.
  5. Set x to sign(x) * floor(abs(x)).
  6. Set x to x modulo 264.
  7. If x is greater than or equal to 263, then set x to x − 264.
  8. Return the IDL long long value that represents the same numeric value as x.

The result of converting an IDL long long value to an ECMAScript 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 ([ECMA-262], section 6.1.6). 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.

4.2.11. unsigned long long

An ECMAScript value V is converted to an IDL unsigned long long value by running the following algorithm:

  1. Initialize x to ToNumber(V).
  2. If the conversion to an IDL value is being performed due to any of the following: then:
    1. If x is NaN, +∞, or −∞, then throw a TypeError.
    2. Set x to sign(x) * floor(abs(x)).
    3. If x < 0 or x > 253 − 1, then throw a TypeError.
    4. Return the IDL unsigned long long value that represents the same numeric value as x.
  3. If x is not NaN and the conversion to an IDL value is being performed due to any of the following: then:
    1. Set x to min(max(x, 0), 253 − 1).
    2. Round x to the nearest integer, choosing the even integer if it lies halfway between two, and choosing +0 rather than −0.
    3. Return the IDL unsigned long long value that represents the same numeric value as x.
  4. If x is NaN, +0, −0, +∞, or −∞, then return the IDL unsigned long long value that represents 0.
  5. Set x to sign(x) * floor(abs(x)).
  6. Set x to x modulo 264.
  7. Return the IDL unsigned long long value that represents the same numeric value as x.

The result of converting an IDL unsigned long long value to an ECMAScript 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 ([ECMA-262], section 6.1.6). 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.

4.2.12. float

An ECMAScript value V is converted to an IDL float value by running the following algorithm:

  1. Let x be ToNumber(V).
  2. If x is NaN, +Infinity or −Infinity, then throw a TypeError.
  3. 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.
  4. 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 ([ECMA-262], section 6.1.6). (The two special values 2128 and −2128 are considered to have even significands for this purpose.)
  5. If y is 2128 or −2128, then throw a TypeError.
  6. If y is +0 and x is negative, return −0.
  7. Return y.

The result of converting an IDL float value to an ECMAScript value is the Number value that represents the same numeric value as the IDL float value.

4.2.13. unrestricted float

An ECMAScript value V is converted to an IDL unrestricted float value by running the following algorithm:

  1. Let x be ToNumber(V).
  2. 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].
  3. 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.
  4. 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 ([ECMA-262], section 6.1.6). (The two special values 2128 and −2128 are considered to have even significands for this purpose.)
  5. If y is 2128, return +∞.
  6. If y is −2128, return −∞.
  7. If y is +0 and x is negative, return −0.
  8. Return y.
Note

Since there is only a single ECMAScript 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 converting an IDL unrestricted float value to an ECMAScript value is a Number:

  • If the IDL unrestricted float value is a NaN, then the Number value is NaN.
  • Otherwise, the Number value is the one that represents the same numeric value as the IDL unrestricted float value.

4.2.14. double

An ECMAScript value V is converted to an IDL double value by running the following algorithm:

  1. Let x be ToNumber(V).
  2. If x is NaN, +Infinity or −Infinity, then throw a TypeError.
  3. Return the IDL double value that has the same numeric value as x.

The result of converting an IDL double value to an ECMAScript value is the Number value that represents the same numeric value as the IDL double value.

4.2.15. unrestricted double

An ECMAScript value V is converted to an IDL unrestricted double value by running the following algorithm:

  1. Let x be ToNumber(V).
  2. 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].
  3. Return the IDL unrestricted double value that has the same numeric value as x.
Note

Since there is only a single ECMAScript 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 converting an IDL unrestricted double value to an ECMAScript value is a Number:

  • If the IDL unrestricted double value is a NaN, then the Number value is NaN.
  • Otherwise, the Number value is the one that represents the same numeric value as the IDL unrestricted double value.

4.2.16. DOMString

An ECMAScript value V is converted to an IDL DOMString value by running the following algorithm:

  1. If V is null and the conversion to an IDL value is being performed due to any of the following: then return the DOMString value that represents the empty string.
  2. Let x be ToString(V).
  3. If the conversion to an IDL value is being performed due to any of the following: then:
    1. Let characters be the result of passing x to the DOMString to sequence of Unicode characters conversion algorithm.
    2. Set x to the DOMString value that represents the sequence of characters in characters in UTF-16.
  4. Return the IDL DOMString value that represents the same sequence of code units as the one the ECMAScript String value x represents.

The result of converting an IDL DOMString value to an ECMAScript value is the String value that represents the same sequence of code units that the IDL DOMString represents.

4.2.17. ByteString

An ECMAScript value V is converted to an IDL ByteString value by running the following algorithm:

  1. Let x be ToString(V).
  2. If the value of any element of x is greater than 255, then throw a TypeError.
  3. 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 converting an IDL ByteString value to an ECMAScript value is a String value whose length is the length of the ByteString, and the value of each element of which is the value of the corresponding element of the ByteString.

4.2.18. object

IDL object values are represented by ECMAScript Object values.

An ECMAScript value V is converted to an IDL object value by running the following algorithm:

  1. If Type(V) is not Object, then throw a TypeError.
  2. Return the IDL object value that is a reference to the same object as V.

The result of converting an IDL object value to an ECMAScript value is the Object value that represents a reference to the same object that the IDL object represents.

4.2.19. Interface types

IDL interface type values are represented by ECMAScript Object or Function values.

An ECMAScript value V is converted to an IDL interface type value by running the following algorithm (where I is the interface):

  1. If Type(V) is not Object, then throw a TypeError.
  2. If V is a platform object that implements I, then return the IDL interface type value that represents a reference to that platform object.
  3. If V is a user object that is considered to implement I according to the rules in section 4.8, then return the IDL interface type value that represents a reference to that user object, with the incumbent script as the callback context. [HTML]
  4. Throw a TypeError.

The result of converting an IDL interface type value to an ECMAScript value is the Object value that represents a reference to the same object that the IDL interface type value represents.

4.2.20. Dictionary types

IDL dictionary type values are represented by ECMAScript Object values. Properties on the object (or its prototype chain) correspond to dictionary members.

An ECMAScript value V is converted to an IDL dictionary type value by running the following algorithm (where D is the dictionary):

  1. If Type(V) is not Undefined, Null or Object, then throw a TypeError.
  2. If V is a native Date object or a native RegExp object, then throw a TypeError.
  3. Let dict be an empty dictionary value of type D; every dictionary member is initially considered to be not present.
  4. Let dictionaries be a list consisting of D and all of D’s inherited dictionaries, in order from least to most derived.
  5. For each dictionary dictionary in dictionaries, in order:
    1. For each dictionary member member declared on dictionary, in order:
      1. Let key be the identifier of member.
      2. Let value be an ECMAScript value, depending on Type(V):
        Undefined
        Null
        value is undefined.
        anything else
        value is the result of calling the [[Get]] internal method on V with property name key.
      3. If value is not undefined, then:
        1. Let idlValue be the result of converting value to an IDL value whose type is the type member is declared to be of.
        2. Set the dictionary member on dict with key name key to the value idlValue. This dictionary member is considered to be present.
      4. Otherwise, if value is undefined but the dictionary member has a default value, then:
        1. Let idlValue be the dictionary member’s default value.
        2. Set the dictionary member on dict with key name key to the value idlValue. This dictionary member is considered to be present.
      5. Otherwise, if value is undefined and the dictionary member is a required dictionary member, then throw a TypeError.
  6. Return dict.
Note

The order that dictionary members are looked up on the ECMAScript object are not necessarily the same as the object’s property enumeration order.

An IDL dictionary value V is converted to an ECMAScript Object value by running the following algorithm (where D is the dictionary):

  1. Let O be a new Object value created as if by the expression ({}).
  2. Let dictionaries be a list consisting of D and all of D’s inherited dictionaries, in order from least to most derived.
  3. For each dictionary dictionary in dictionaries, in order:
    1. For each dictionary member member declared on dictionary, in order:
      1. Let key be the identifier of member.
      2. If the dictionary member named key is present in V, then:
        1. Let idlValue be the value of member on V.
        2. Let value be the result of converting idlValue to an ECMAScript value.
        3. Call the [[DefineOwnProperty]] internal method on O with property name key, Property Descriptor { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true, [[Value]]: value } and Boolean flag false.
  4. Return O.

4.2.21. Enumeration types

IDL enumeration types are represented by ECMAScript String values.

An ECMAScript value V is converted to an IDL enumeration type value as follows (where E is the enumeration):

  1. Let S be the result of calling ToString(V).
  2. If S is not one of E’s enumeration values, then throw a TypeError.
  3. Return the enumeration value of type E that is equal to S.

The result of converting an IDL enumeration type value to an ECMAScript value is the String value that represents the same sequence of code units as the enumeration value.

4.2.22. Callback function types

IDL callback function types are represented by ECMAScript Function objects, except in the [TreatNonObjectAsNull] case, when they can be any object.

An ECMAScript value V is 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 callback function that is annotated with [TreatNonObjectAsNull], then throw a TypeError.
  2. Return the IDL callback function type value that represents a reference to the same object that V represents, with the incumbent script as the callback context. [HTML].

The result of converting an IDL callback function type value to an ECMAScript value is a reference to the same object that the IDL callback function type value represents.

4.2.23. Nullable types — T?

IDL nullable type values are represented by values of either the ECMAScript type corresponding to the inner IDL type, or the ECMAScript null value.

An ECMAScript value V is converted to an IDL nullable type T? value (where T is the 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 callback function that is annotated with [TreatNonObjectAsNull], then return the IDL nullable type T? value null.
  2. Otherwise, if V is null or undefined, then return the IDL nullable type T? value null.
  3. Otherwise, return the result of converting V using the rules for the inner IDL type T.

The result of converting an IDL nullable type value to an ECMAScript value is:

4.2.24. Sequences — sequence<T>

IDL sequence<T> values are represented by ECMAScript Array values.

An ECMAScript value V is converted to an IDL sequence<T> value as follows:

  1. If V is not an object, throw a TypeError.
  2. If V is a native Date object or a native RegExp object, throw a TypeError.
  3. Let method be the result of CheckIterable(V).
  4. ReturnIfAbrupt(method).
  5. If method is undefined, throw a TypeError.
  6. Return the result of creating a sequence of type sequence<T> from V and method.

An IDL sequence value S of type sequence<T> is converted to an ECMAScript Array object as follows:

  1. Let n be the length of S.
  2. Let A be a new Array object created as if by the expression [].
  3. Initialize i to be 0.
  4. While i < n:
    1. Let V be the value in S at index i.
    2. Let E be the result of converting V to an ECMAScript value.
    3. Let P be the result of calling ToString(i).
    4. Call the [[DefineOwnProperty]] internal method on A with property name P, Property Descriptor { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true, [[Value]]: E } and Boolean flag false.
    5. Set i to i + 1.
  5. Return A.
4.2.24.1. 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 iter be GetIterator(iterable, method).
  2. ReturnIfAbrupt(iter).
  3. Initialize i to be 0.
  4. Repeat
    1. Let next be IteratorStep(iter).
    2. ReturnIfAbrupt(next).
    3. If next is false, then return an IDL sequence value of type sequence<T> of length i, where the value of the element at index j is Sj.
    4. Let nextItem be IteratorValue(next).
    5. ReturnIfAbrupt(nextItem).
    6. Initialize Si to the result of converting nextItem to an IDL value of type T.
    7. Set i to i + 1.
Example

The following interface defines an attribute of a sequence type as well as an operation with an argument of a sequence type.

IDL
interface Canvas {

  sequence<DOMString> getSupportedImageCodecs();

  void drawPolygon(sequence<float> coordinates);
  sequence<float> getLastDrawnPolygon();

  // ...
};

In an ECMAScript 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<float>. 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.

ECMAScript

// 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<float>.
canvas.drawPolygon(a);

// Each element will be converted to a float 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(s);

// 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".

4.2.25. Arrays — T[]

IDL array values are represented by references to objects known as platform array objects, with particular characteristics that allow them to behave similarly to native Array objects. All platform array objects are platform objects, and thus each is associated with a particular global environment.

Note

Platform array objects differ from Array objects in the following ways:

  • they are never sparse
  • their elements are always data properties
  • an ECMAScript-to-IDL value conversion is always performed when storing an element
  • they stringify with Object.prototype.toString differently
  • their internal [[Extensible]] property value is always true

The value of the internal [[Prototype]] property of a platform array object MUST be %ArrayPrototype% ([ECMA-262], section 6.1.7.4) from its associated global environment.

Note

Note that some of the functions from the Array prototype object will not behave on a fixed length platform array object as they do on an Array object, since attempting to assign to the “length” property will fail. Similarly, some of the functions from the Array prototype object will not perform any useful operation on read only arrays.

The class string of a platform array object MUST be the type name of the array type.

Platform array objects appear to have a “length” property and a property for each element of the array. The values and behaviors of these properties are implemented by the internal [[GetOwnProperty]], [[DefineOwnProperty]] and [[Delete]] methods, which are also defined below.

Platform array objects cannot be fixed; if Object.freeze, Object.seal or Object.preventExtensions is called on one, the function MUST throw a TypeError.

An ECMAScript value V is converted to an IDL array value of type T[] as follows:

  1. If V is a platform array object whose element type is T, then return the array that the platform array object represents.
  2. Let values be the result of converting V to a sequence with element type T.
  3. Let n be the length of values.
  4. Return a new fixed length array of length n whose element values are the same as those in values.

An IDL array value V of type T[] is converted to an ECMAScript value as follows:

  • If V is already represented by a platform array object, then the ECMAScript value is that platform array object.
  • Otherwise, the ECMAScript value is a newly created platform array object that represents V.
Example

The following IDL defines an interface that has an unsigned short[] attribute.

IDL
[Constructor]
interface LotteryResults {
  readonly attribute unsigned short[] numbers;
};

Assuming that the array has a fixed length of 6, the following ECMAScript code illustrates how the array attribute in the above interface would behave:

ECMAScript
var results = new LotteryResults();  // results is a new platform object
                                     // implementing the LotteryResults interface.

var a = [4, 8, 15, 16, 23, 42];      // Numbers will be assigned into the array.
for (var i = 0; i < 6; i++) {
  results.numbers[i] = a[i];
}

results.numbers = a;                 // This has no effect, since numbers is
                                     // read only.

a[0] = 5;                            // Change the array.
results.numbers[0];                  // Evaluates to 4, since results.numbers is
                                     // not a reference to 'a'.

results.numbers[0] = 5;              // Modifies the array stored in the platform
                                     // object.
results.numbers[0];                  // Now evaluates to 5.

results.numbers[0] = 6.25;           // Assigns 6 to the first element of the array
                                     // since that is how 6.5 is converted to an
                                     // unsigned short.

results.numbers.length = 7;          // Has no effect, since numbers is
                                     // fixed length.
results.numbers[6];                  // Evaluates to undefined.

results.numbers.slice(0, 2);         // Evaluates to an Array [6, 8].

results.numbers.push(108);           // Has no effect, since the definition of
                                     // push() relies on calling [[Put]] on a
                                     // non-existent array index property
                                     // and on "length", both of which will
                                     // be silently ignored.

delete results.numbers[3];           // Has no effect and evaluates to false,
                                     // since the array index properties are
                                     // non-configurable.

If passing an Array object to a platform object expecting an IDL array value, a new platform array object will be created to represent an IDL array value determined from that Array. If the LotteryResults interface is instead defined as:

IDL
[Constructor]
interface LotteryResults {
  attribute unsigned short[] numbers;
};

then an Array object can be assigned to the “numbers” property. Unless the prose accompanying the interface said otherwise, this would result in a fixed length array of whatever length the Array has being assigned to the IDL attribute.

ECMAScript
var results = new LotteryResults();

results.numbers.length;       // Evaluates to 6.

var a = [1, 3, 5];

results.numbers = a;          // Assigns a fixed length IDL array of length 3 to
                              // the numbers attribute.

results.numbers;              // This now evaluates to a platform array object
                              // that represents the fixed length IDL array,
                              // not the Array object assigned in the previous
                              // statement.

results.numbers == a;         // Evaluates to false.

results.numbers.length;       // Evaluates to 3.

results.numbers.push(7);      // Silently ignored in non-strict mode.
results.numbers.length;       // So this still evaluates to 3.
4.2.25.1. Platform array object [[GetOwnProperty]] method

The internal [[GetOwnProperty]] method of every platform array object A with element type T MUST behave as follows when called with property name P:

  1. Let length be the length of the IDL array that A represents.
  2. If P is “length”, then:
    1. Let desc be a newly created Property Descriptor ([ECMA-262], section 6.2.4) with no fields.
    2. Set desc.[[Value]] to the Number value for length.
    3. Set desc.[[Writable]] to false if A represents a read only or fixed length array, and true otherwise.
    4. Set desc.[[Enumerable]] to false.
    5. Set desc.[[Configurable]] to false.
    6. Return desc.
  3. Otherwise, if P is an array index ([ECMA-262], section 9.4.2), then:
    1. Let index be ToUint32(P).
    2. If index ≥ length, then return undefined.
    3. Let value be the result of converting the indexth element of the IDL array that A represents to an IDL value of type T.
    4. Let desc be a newly created Property Descriptor ([ECMA-262], section 6.2.4) with no fields.
    5. Set desc.[[Value]] to value.
    6. Set desc.[[Writable]] to false if A represents a read only array, and true otherwise.
    7. Set desc.[[Enumerable]] and desc.[[Configurable]] to true.
    8. Return desc.
  4. Return the result of calling the default [[GetOwnProperty]] internal method ([ECMA-262], section 9.1.5) on A passing P as the argument.
4.2.25.2. Platform array object [[DefineOwnProperty]] method

The internal [[DefineOwnProperty]] method of every platform array object A with element type T MUST behave as follows when passed property name P, Property Descriptor Desc and boolean flag Throw. The term “Reject” is used in the same sense as that defined in ECMA-262, namely, to mean “If Throw is true, then throw a TypeError exception, otherwise return false”.

  1. Initialize oldLen to be the length of the IDL array that A represents.
  2. If P is “length”, then:
    1. If the result of calling IsDataDescriptor(Desc) is false, then Reject.
    2. Let newLen be ToUint32(Desc.[[Value]]).
    3. If newLen is not equal to ToNumber(Desc.[[Value]]), then throw a RangeError exception.
    4. If A represents a read only or fixed length IDL array, then Reject.
    5. If newLen > oldLen, then:
      1. Let value be the result of converting undefined to type T.
      2. Update the IDL array that A represents to have a length of newLen, and set every value of the IDL array at indices in the range [oldLennewLen) to value.
    6. Otherwise, if newLen < oldLen, then update the IDL array that A represents to have a length of newLen, discarding elements at indices in the range [newLenoldLen).
    7. Return true.
  3. Otherwise, if P is an array index ([ECMA-262], section 9.4.2), then:
    1. If the result of calling IsDataDescriptor(Desc) is false, then Reject.
    2. Let index be ToUint32(P).
    3. If indexoldLen, then:
      1. If A represents a read only or fixed length IDL array, then Reject.
      2. Let value be the result of converting undefined to type T.
      3. Update the IDL array that A represents to have a length of index + 1, and set every value of the IDL array at indices in the range [oldLenindex) to value.
    4. If A represents a read only IDL array, then Reject.
    5. Let newValue be the result of converting Desc.[[Value]] to an IDL value of type T.
    6. Set the indexth element of the IDL array that A represents to newValue.
    7. Return true.
  4. Set Desc.[[Configurable]] to true.
  5. Return the result of calling the default [[DefineOwnProperty]] internal method ([ECMA-262], section 9.1.6) on A passing P, Desc, and Throw as arguments.
4.2.25.3. Platform array object [[Delete]] method

The internal [[Delete]] method of every platform array object A with element type T MUST behave as follows when passed property name P.

  1. If P is “length”, then return false.
  2. Let length be the length of the IDL array that A represents.
  3. If P is an array index ([ECMA-262], section 9.4.2), then:
    1. Let index be ToUint32(P).
    2. If index < length, then false.
    3. Return true.
  4. If P has an own property with name P, then remove it.
  5. Return true.

4.2.26. Promise types — Promise<T>

IDL promise type values are represented by ECMAScript Promise objects.

An ECMAScript value V is converted to an IDL Promise<T> value as follows:

  1. Let resolve be the original value of %Promise%.resolve.
    Editorial note

    ECMAScript should grow a %Promise_resolve% well-known intrinsic object that can be referenced here.

  2. Let promise be the result of calling resolve with %Promise% as the this value and V as the single argument value.
  3. Return the IDL promise type value that is a reference to the same object as promise.

The result of converting an IDL promise type value to an ECMAScript value is the Promise value that represents a reference to the same object that the IDL promise type represents.

One can perform some steps once a promise is settled. There can be one or two sets of steps to perform, covering when the promise is fulfilled, rejected, or both. When a specification says to perform some steps once a promise is settled, the following steps MUST be followed:

  1. Let promise be the promise object of type Promise<T>.
  2. Let onFulfilled be a new function object whose behavior when invoked is as follows:
    1. If T is void, then:
      1. Return the result of performing any steps that were required to be run if the promise was fulfilled.
    2. Otherwise, T is a type other than void:
      1. Let V be the first argument to onFulfilled.
      2. Let value be the result of converting V to an IDL value of type T.
      3. If there are no steps that are required to be run if the promise was fulfilled, then return undefined.
      4. Otherwise, return the result of performing any steps that were required to be run if the promise was fulfilled, with value as the promise’s value.
  3. Let onRejected be a new function object whose behavior when invoked is as follows:
    1. Let R be the first argument to onRejected.
    2. Let reason be the result of converting R to an IDL value of type any.
    3. If there are no steps that are required to be run if the promise was rejected, then return undefined.
    4. Otherwise, return the result of performing any steps that were required to be run if the promise was rejected, with reason as the rejection reason.
  4. Let then be the result of calling the internal [[Get]] method of promise with property name “then”.
  5. If then is not callable, then throw a TypeError.
  6. Return the result of calling then with promise as the this value and onFulfilled and onRejected as its two arguments.
Editorial note

Include an example of how to write spec text using this term.

4.2.27. Union types

IDL union type values are represented by ECMAScript values that correspond to the union’s member types.

To convert an ECMAScript value V to an IDL union type value is done as follows:

  1. If the union type includes a nullable type and V is null or undefined, then return the IDL value null.
  2. Let types be the flattened member types of the union type.
  3. If V is a platform object, but not a platform array 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.
    2. If types includes object, then return the IDL value that is a reference to the object V.
  4. If V is a native Date object, then:
    1. If types includes Date, then return the result of converting V to Date.
    2. If types includes object, then return the IDL value that is a reference to the object V.
  5. If V is a native RegExp object, then:
    1. If types includes RegExp, then return the result of converting V to RegExp.
    2. If types includes object, then return the IDL value that is a reference to the object V.
  6. If IsCallable(V) is true, then:
    1. If types includes a callback function type, then return the result of converting V to that callback function type.
    2. If types includes object, then return the IDL value that is a reference to the object V.
  7. If V is null or undefined or is any kind of object except for a native Date object or a native RegExp object, then:
    1. If types includes a dictionary type, then return the result of converting V to that dictionary type.
  8. If V is any kind of object except for a native Date object or a native RegExp object, then:
    1. If types includes an array type, then return the result of converting V to that type.
    2. If types includes a sequence type, then
      1. Let method be the result of CheckIterable(V).
      2. ReturnIfAbrupt(method).
      3. If method is not undefined, return the result of creating a sequence of that type from V and method.
    3. If types includes a callback interface type, then return the result of converting V to that interface type.
    4. If types includes object, then return the IDL value that is a reference to the object V.
  9. If V is a Boolean value, then:
    1. If types includes a boolean, then return the result of converting V to boolean.
  10. If V is a Number value, then:
    1. If types includes a numeric type, then return the result of converting V to that numeric type.
  11. If types includes DOMString, an enumeration type or ByteString, then return the result of converting V to that type.
  12. If types includes a numeric type, then return the result of converting V to that numeric type.
  13. If types includes a boolean, then return the result of converting V to boolean.
  14. Throw a TypeError.

An IDL union type value is converted to an ECMAScript value as follows. If the value is an object reference to a special object that represents an ECMAScript undefined value, then it is converted to the ECMAScript undefined value. Otherwise, the rules for converting the specific type of the IDL union type value as described in this section (4.2).

4.2.28. Date

IDL Date values are represented by ECMAScript Date objects.

An ECMAScript value V is converted to an IDL Date value by running the following algorithm:

  1. If V is not an ECMAScript Date object, then throw a TypeError.
  2. If the time value of V is NaN, then return the undefined IDL Date value.
  3. Return the IDL Date value that represents the same time value as V.

An IDL Date value V is converted to an ECMAScript value by running the following the algorithm:

  1. If V is the undefined Date value, then return a newly constructed ECMAScript Date object whose time value is NaN.
  2. Otherwise, return a newly constructed ECMAScript Date object that represents the same millisecond as V.

Platform objects returning an ECMAScript Date object from attributes, operations or exception field do not hold on to a reference to the Date object. A script that modifies a Date object so retrieved cannot affect the platform object it was retrieved from.

4.2.29. RegExp

IDL RegExp values are represented by ECMAScript RegExp objects.

An ECMAScript value V is converted to an IDL RegExp value by running the following algorithm:

  1. If Type(V) is not Object, or the value of the internal [[NativeBrand]] property of V is not “RegExp”, then set V to be a newly created RegExp object created as if by the expression new RegExp(V), where RegExp is the standard built-in constructor with that name from the current global environment.
    Note

    Note that this can result in an exception being thrown, if V, when converted to a string, does not have valid regular expression syntax.

  2. Return the IDL RegExp value that is a reference to the same object as V.

The result of converting an IDL RegExp value to an ECMAScript value is the RegExp value that represents a reference to the same object that the IDL RegExp represents.

4.3. ECMAScript-specific extended attributes

This section defines a number of extended attributes whose presence affects only the ECMAScript binding.

4.3.1. [ArrayClass]

If the [ArrayClass] extended attribute appears on an interface that is not defined to inherit from another, it indicates that the internal [[Prototype]] property of its interface prototype object will be the Array prototype object rather than the Object prototype object. This allows Array methods to be used more easily with objects implementing the interface.

The [ArrayClass] extended attribute MUST take no arguments. It MUST NOT be used on an interface that has any inherited interfaces, or which is declared with the [MapClass] extended attribute.

Note

Interfaces using [ArrayClass] will need to define a “length” attribute of type unsigned long that exposes the length of the array-like object, in order for the inherited Array methods to operate correctly. Such interfaces would typically also support indexed properties, which would provide access to the array elements.

See section 4.5.4 for the specific requirements that the use of [ArrayClass] entails.

Example

The following IDL fragment defines two interfaces that use [ArrayClass].

IDL
[ArrayClass]
interface ItemList {
  attribute unsigned long length;
  getter object getItem(unsigned long index);
  creator setter object setItem(unsigned long index, object item);
  deleter void removeItem(unsigned long index);
};

[ArrayClass]
interface ImmutableItemList {
  readonly attribute unsigned long length;
  getter object getItem(unsigned long index);
};

In an ECMAScript implementation of the above two interfaces, with appropriate definitions for getItem, setItem and removeItem, Array methods to inspect and modify the array-like object can be used.

ECMAScript
var list = getItemList();  // Obtain an instance of ItemList.

list.concat();             // Clone the ItemList into an Array.
list.pop();                // Remove an item from the ItemList.
list.unshift({ });         // Insert an item at index 0.

ImmutableItemList has a read only length attribute and no indexed property setter, creator or deleter. The mutating Array methods will generally not succeed on objects implementing ImmutableItemList. The exact behavior depends on the definition of the Array methods themselves ([ECMA-262], section 22.1.3).

4.3.2. [Clamp]

If the [Clamp] extended attribute appears on an operation argument, writable attribute or dictionary member whose type is one of the integer types, it indicates that when an ECMAScript 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 take no arguments.

The [Clamp] extended attribute MUST NOT appear on a read only attribute, or an attribute, operation argument or dictionary member that is not of an integer type. It also MUST NOT be used in conjunction with the [EnforceRange] extended attribute.

See the rules for converting ECMAScript values to the various IDL integer types in section 4.2 for the specific requirements that the use of [Clamp] entails.

Example

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:

IDL
interface GraphicsContext {
  void setColor(octet red, octet green, octet blue);
  void setColorClamped([Clamp] octet red, [Clamp] octet green, [Clamp] octet blue);
};

In an ECMAScript implementation of the IDL, a call to setColorClamped with Number values that are out of range for an octet are clamped to the range [0, 255].

ECMAScript
// 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);

4.3.3. [Constructor]

If the [Constructor] extended attribute appears on an interface, it indicates that the interface object for this interface will have an [[Construct]] internal method, allowing objects implementing the interface to be constructed.

If it appears on a dictionary, then it indicates that the ECMAScript global object will have a property whose name is the identifier of the dictionary and whose value is a constructor function that can return an ECMAScript object that represents a dictionary value of the given type.

Multiple [Constructor] extended attributes may appear on a given interface or dictionary.

The [Constructor] extended attribute MUST either take no arguments or take an argument list. The bare form, [Constructor], has the same meaning as using an empty argument list, [Constructor()]. For each [Constructor] extended attribute on the interface, there will be a way to construct an object that implements the interface by passing the specified arguments.

The prose definition of a constructor MUST either return an IDL value of a type corresponding to the interface or dictionary the [Constructor] extended attribute appears on, or throw an exception.

If the [Constructor] extended attribute is specified on an interface, then the [NoInterfaceObject] extended attribute MUST NOT also be specified on that interface.

The [Constructor] extended attribute MUST NOT be used on a callback interface.

See section 4.5.1.1 below for details on how a constructor for an interface is to be implemented, and section 4.5.3 for how a constructor for a dictionary is to be implemented.

Example

The following IDL defines two interfaces. The second has the [Constructor] extended attribute, while the first does not.

IDL
interface NodeList {
  Node item(unsigned long index);
  readonly attribute unsigned long length;
};

[Constructor,
 Constructor(float radius)]
interface Circle {
  attribute float r;
  attribute float cx;
  attribute float cy;
  readonly attribute float circumference;
};

An ECMAScript implementation supporting these interfaces would have a [[Construct]] property on the Circle interface object which would return a new object that implements the interface. It would take either zero or one argument. The NodeList interface object would not have a [[Construct]] property.

ECMAScript
var x = new Circle();      // The 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.
Example

The following IDL defines a dictionary type with a constructor:

IDL
[Constructor(unsigned long patties, unsigned long cheeseSlices)]
dictionary BurgerOrder {
  unsigned long pattyCount;
  unsigned long cheeseSliceCount;
};

The constructor is defined with the following prose:

When the BurgerOrder constructor is invoked, it must return a dictionary value of type BurgerOrder whose pattyCount and cheeseSliceCount members are set to the values of the patties and cheeseSlices arguments, respectively.

An ECMAScript implementation supporting this dictionary type would have a constructor function on the global object that returns a plain object with properties corresponding to the dictionary’s members:

ECMAScript
typeof BurgerOrder;                                // Evaluates to "function".

var order = new BurgerOrder(1, 2);                 // Creates a new object.

order.hasOwnProperty("pattyCount");                // Evaluates to true.
order.pattyCount;                                  // Evaluates to 1.

Object.getPrototypeOf(order) == Object.prototype;  // Evaluates to true.

4.3.4. [EnforceRange]

If the [EnforceRange] extended attribute appears on an operation argument, writable regular attribute or dictionary member whose type is one of the integer types, it indicates that when an ECMAScript Number is converted to the IDL type, out of range values will cause an exception to be thrown, rather than converted to being a valid value using the operators that use a modulo operation (ToInt32, ToUint32, etc.). The Number will be rounded towards zero before being checked against its range.

The [EnforceRange] extended attribute MUST take no arguments.

The [EnforceRange] extended attribute MUST NOT appear on a read only attribute, a static attribute, or an attribute, operation argument or dictionary member that is not of an integer type. It also MUST NOT be used in conjunction with the [Clamp] extended attribute.

See the rules for converting ECMAScript values to the various IDL integer types in section 4.2 for the specific requirements that the use of [EnforceRange] entails.

Example

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:

IDL
interface GraphicsContext {
  void setColor(octet red, octet green, octet blue);
  void setColorEnforcedRange([EnforceRange] octet red, [EnforceRange] octet green, [EnforceRange] octet blue);
};

In an ECMAScript 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.

ECMAScript
// 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);

4.3.5. [EnsureUTF16]

If the [EnsureUTF16] extended attribute appears on an operation argument or writable attribute whose type is DOMString, it indicates that any ECMAScript String value passed in will modified to ensure that it is valid UTF-16. That is, it will replace any invalid surrogate code units with a U+FFFD REPLACEMENT CHARACTER by passing it through the DOMString to sequence of Unicode characters conversion algorithm.

The [EnsureUTF16] extended attribute MUST take no arguments.

See section 4.2.16 for the specific requirements that the use of [EnsureUTF16] entails.

Example

Consider the following IDL fragment, where the behavior of the operation is simply to return the value that is passed to it.

IDL
interface StringSanitizer {
  static DOMString sanitize([EnsureUTF16] DOMString s);
};

Due to the use of [EnsureUTF16], invalid UTF-16 surrogate code units will be replaced.

ECMAScript
function show(s) {
  return s.split("").map(function(c) { return c.charCodeAt(0); });
}

var s = "\uDC00\uD800\uDC00\uD800";  // The first and last code units are invalid surrogates.
show(s);                             // Evaluates to [0xdc00, 0xd800, 0xdc00, 0xd800].
show(StringSanitizer.sanitizer(s));  // Evaluates to [0xfffd, 0xd800, 0xdc00, 0xfffd].

4.3.6. [Exposed]

If the [Exposed] extended attribute appears on an interface, partial interface, an individual interface member, or dictionary with a constructor, it indicates that the interface, interface member or dictionary constructor is exposed on a particular set of global interfaces, rather than the default of being exposed only on the primary global interface.

The [Exposed] extended attribute MUST either take an identifier or take an identifier list. Each of the identifiers mentioned MUST be a global name.

Every construct that the [Exposed] extended attribute can be specified on has an exposure set, which is a set of interfaces defining which global environments the construct can be used in. The exposure set for a given construct is defined as follows:

If [Exposed] appears on an overloaded operation, then it MUST appear identically on all overloads.

The [Exposed] extended attribute MUST NOT be specified on both an interface member and a partial interface definition the interface member is declared on.

If [Exposed] appears on both an interface and one of its interface members, then the interface member's exposure set MUST be a subset of the interface's exposure set. An interface's exposure set MUST also be a subset of the exposure set of all of the interface's consequential interfaces.

The [Exposed] extended attribute MUST NOT be specified on a dictionary that does not also have a [Constructor] extended attribute.

An interface, interface member or dictionary is exposed in a given ECMAScript global environment if the ECMAScript global object implements an interface that is in the interface, interface member or dictionary's exposure set.

See section 4.5, section 4.5.3, section 4.5.6, section 4.5.7, section 4.5.8 and section 4.5.9 for the specific requirements that the use of [Exposed] entails.

Example

[Exposed] is intended to be used to control whether interfaces or individual interface members are available for use only in workers, only in the Window, or in both.

The following IDL fragment shows how that might be achieved:

IDL
[PrimaryGlobal]
interface Window {
  ...
};

// By using the same identifier Worker for both SharedWorkerGlobalScope
// and DedicatedWorkerGlobalScope, both can be addressed in an [Exposed]
// extended attribute at once.
[Global=Worker]
interface SharedWorkerGlobalScope : WorkerGlobalScope {
  ...
};

[Global=Worker]
interface DedicatedWorkerGlobalScope : WorkerGlobalScope {
  ...
};

// MathUtils is available for use in workers and on the main thread.
[Exposed=(Window,Worker)]
interface MathUtils {
  static 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 interface object, while
// doing so on the main thread will give you a ReferenceError.
[Exposed=Worker]
interface WorkerUtils {
  static void setPriority(double x);
};

// Node is only available on the main thread.  Evaluating Node
// in the global scope of a worker would give you a ReferenceError.
interface Node {
  ...
};

4.3.7. [ImplicitThis]

If the [ImplicitThis] extended attribute appears on an interface, it indicates that when a Function corresponding to one of the interface’s operations is invoked with the null or undefined value as the this value, that the ECMAScript global object will be used as the this value instead. This is regardless of whether the calling code is in strict mode.

The [ImplicitThis] extended attribute MUST take no arguments.

See section 4.5.8 for the specific requirements that the use of [ImplicitThis] entails.

Note

The [ImplicitThis] extended attribute is intended for use on the Window interface as defined in HTML5 ([HTML5], section 5.2).

Example

In the following example, the Window interface is defined with the [ImplicitThis] extended attribute.

IDL
[ImplicitThis]
interface Window {
  ...
  attribute DOMString name;
  void alert(DOMString message);
};

Since the Window object is used as the ECMAScript global object, calls to its functions can be made without an explicit object, even in strict mode:

ECMAScript
"use strict";

window.alert("hello");      // Calling alert with an explicit window object works.
alert("hello");             // This also works, even though we are in strict mode.
alert.call(null, "hello");  // As does passing null explicitly as the this value.

// This does not apply to getters for attributes on the interface, though.
// The following will throw a TypeError.
Object.getOwnPropertyDescriptor(Window.prototype, "name").get.call(null);

4.3.8. [Global] and [PrimaryGlobal]

If the [Global] or [PrimaryGlobal] extended attribute appears on an interface, it indicates that objects implementing this interface can be used as the global object in an ECMAScript environment, and that 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.
  2. Interface members from the interface (or consequential interfaces) will correspond to properties on the object itself rather than on interface prototype objects.
Note

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:

ECMAScript
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 ECMAScript, 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] or [PrimaryGlobal] extended attributes is used on an interface, then:

If [Global] or [PrimaryGlobal] 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] and [PrimaryGlobal] extended attribute MUST NOT be used on an interface that can have more than one object implementing it in the same ECMAScript global environment.

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] or [PrimaryGlobal] extended attribute, then there MUST NOT be more than one interface member across the interface and its consequential interfaces with the same identifier. There also MUST NOT be more than stringifier, more than one serializer, or more than one iterator across those interfaces.

Note

This is because all of the members of the interface and its consequential interfaces get flattened down on to the object that implements the interface.

The [Global] and [PrimaryGlobal] extended attributes can also be used to give a name to one or more global interfaces, which can then be referenced by the [Exposed] extended attribute.

The [Global] and [PrimaryGlobal] extended attributes MUST either take no arguments or take an identifier list.

If the [Global] or [PrimaryGlobal] extended attribute is declared with an identifier list argument, then those identifiers are the interface’s global names; otherwise, the interface has a single global name, which is the interface's identifier.

Note

The identifier argument list exists so that more than one global interface can be addressed with a single name in an [Exposed] extended attribute.

The [Global] and [PrimaryGlobal] extended attributes MUST NOT be declared on the same interface. The [PrimaryGlobal] extended attribute MUST be declared on at most one interface. The interface [PrimaryGlobal] is declared on, if any, is known as the primary global interface.

See section 4.5.5, section 4.7.2 and section 4.7.3 for the specific requirements that the use of [Global] and [PrimaryGlobal] entails for named properties, and section 4.5.6, section 4.5.7 and section 4.5.8 for the requirements relating to the location of properties corresponding to interface members.

Example

The [PrimaryGlobal] extended attribute is intended to be used by the Window interface as defined in HTML5 ([HTML5], section 5.2). ([Global] is intended to be used by worker global interfaces.) The Window interface exposes frames as properties on the Window object. Since the Window object also serves as the ECMAScript 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.

IDL
[PrimaryGlobal]
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:

HTML
<!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>

4.3.9. [LenientThis]

If the [LenientThis] 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 [LenientThis] extended attribute MUST take no arguments. It MUST NOT be used on a static attribute.

Warning

Specifications SHOULD NOT use [LenientThis] unless required for compatibility reasons. Specification authors who wish to use this feature are strongly advised to discuss this on the public-script-coord@w3.org mailing list before proceeding.

See the Attributes section below for how [LenientThis] is to be implemented.

Example

The following IDL fragment defines an interface that uses the [LenientThis] extended attribute.

IDL
interface Example {
  [LenientThis] attribute DOMString x;
  attribute DOMString y;
};

An ECMAScript 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.

ECMAScript
var example = getExample();  // Get an instance of Example.
var obj = { };

// Fine.
example.x;

// Ignored, since the this value is not an Example object and [LenientThis] is used.
Object.getOwnPropertyDescriptor(Example.prototype, "x").get.call(obj);

// Also ignored, since Example.prototype is not an Example object and [LenientThis] is used.
Example.prototype.x;

// Throws a TypeError, since Example.prototype is not an Example object.
Example.prototype.y;

4.3.10. [MapClass]

If the [MapClass] extended attribute appears on an interface that is not defined to inherit from another, it indicates that objects implementing the interface are “map-like”, and expose a set of optionally modifiable key–value pairs, where keys are unique.

Any object that implements an interface declared with the [MapClass] extended attribute MUST define what the list of map entries for the object are at any given time. Each map entry is a key–value pair, where the keys and values are IDL values. The list of map entries for an object is ordered.

The [MapClass] extended attribute MUST take a type pair. The first type listed is the interface’s map key type, and the second type is its map value type. Each of the object’s map entries MUST be defined to have a key whose type is the map key type and a value whose type is the map value type.

The keys in a given object’s map entries MUST be unique on that object.

The [MapClass] extended attribute MUST NOT be used on an interface that has any inherited interfaces or which is declared with the [ArrayClass], [Global] or [PrimaryGlobal] or extended attribute.

If an interface has been declared with the [MapClass] extended attribute, then the internal [[Prototype]] property of its interface prototype object will be the Map prototype object rather than the Object prototype object.

Note

This allows for two things. First, it allows generic Map methods to work on objects implementing the interface. Second, it allows objects implementing the interface to test instanceof Map.

The interface prototype object for an interface that has been declared with the [MapClass] extended attribute will gain properties that mimic those available on a native Map object, unless interface members with the same name are declared on the interface.

If an interface member with the identifier “clear”, “delete”, “forEach”, “get”, “has” or “set” is declared on the interface or any of its consequential interfaces, then it MUST be defined as in the IDL fragment below, where Interface is the interface, KeyType is the interface’s map key type and ValueType is the interface’s map value type:

IDL
void clear();
boolean delete(KeyType key);
void forEach(CallbackType callbackFn, optional any thisArg);
ValueType get(KeyType key);
boolean has(KeyType key);
Interface set(KeyType key, ValueType value);

If a “forEach” operation is defined, then CallbackType MUST be a callback function defined as follows:

IDL
callback CallbackType(ValueType value, KeyType key, Interface object);
Note

Although default implementations of the above operations will be supplied if not defined on the interface, specification authors can provide their own definitions as they may be able to provide versions of them with better performance characteristics than the default implementations or to provide some additional behavior.

An interface that is declared with the [MapClass] extended attribute MUST NOT have any interface member declared on it or any of its consequential interfaces with the identifier “size”, “entries”, “keys” or “values”.

Note

The interface prototype object of a [MapClass] interface will gain an accessor property named “size”, and Function object valued data properties named “entries”, “keys” and “values”, all of which mimic those available on a native Map object.

See section 4.5.4 and section 4.5.11 for the specific requirements that the use of [MapClass] entails.

Editorial note

Add an example.

4.3.11. [NamedConstructor]

If the [NamedConstructor] extended attribute appears on an interface, it indicates that the ECMAScript global object will have a property with the specified name whose value is a constructor function that can create objects that implement the interface. Multiple [NamedConstructor] extended attributes may appear on a given interface.

The [NamedConstructor] extended attribute MUST either take an identifier or take a named argument list. The first form, [NamedConstructor=identifier], has the same meaning as using an empty argument list, [NamedConstructor=identifier()]. For each [NamedConstructor] 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 function that is the value of the aforementioned property.

The identifier used for the named constructor MUST NOT be the same as that used by an [NamedConstructor] extended attribute on another interface, MUST NOT be the same as an identifier of an interface (or exception) that has an interface object (or exception interface object), and MUST NOT be one of the reserved identifiers.

The [NamedConstructor] extended attribute MUST NOT be used on a callback interface.

See section 4.5.2 below for details on how named constructors are to be implemented.

Example

The following IDL defines an interface that uses the [NamedConstructor] extended attribute.

IDL
[NamedConstructor=Audio,
 NamedConstructor=Audio(DOMString src)]
interface HTMLAudioElement : HTMLMediaElement {
  // ...
};

An ECMAScript implementation that supports this interface will allow the construction of HTMLAudioElement objects using the Audio constructor.

ECMAScript
typeof Audio;                   // Evaluates to 'function'.

var a1 = new Audio();           // Creates a new object that implements
                                // HTMLAudioElement, using the zero-argument
                                // constructor.

var a2 = new Audio('a.flac');   // Creates an HTMLAudioElement using the
                                // one-argument constructor.

4.3.12. [NewObject]

If the [NewObject] extended attribute appears on a regular or 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 take no arguments.

The [NewObject] extended attribute MUST NOT be used on anything other than a regular or static operation whose return type is an interface type.

Example

As an example, this extended attribute is suitable for use on the createElement operation on the Document interface ([DOM], section 6.5), since a new object should always be returned when it is called.

IDL
interface Document : Node {
  [NewObject] Element createElement(DOMString localName);
  ...
};

4.3.13. [NoInterfaceObject]

If the [NoInterfaceObject] extended attribute appears on an interface, it indicates that an interface object will not exist for the interface in the ECMAScript binding. Similarly, if it appears on an exception it indicates that an exception interface object will not exist for the exception in the ECMAScript binding.

Warning

The [NoInterfaceObject] extended attribute SHOULD NOT be used on interfaces that are not solely used as supplemental interfaces, unless there are clear Web compatibility reasons for doing so. Specification authors who wish to use this feature are strongly advised to discuss this on the public-script-coord@w3.org mailing list before proceeding.

The [NoInterfaceObject] extended attribute MUST take no arguments.

If the [NoInterfaceObject] extended attribute is specified on an interface, then the [Constructor] extended attribute MUST NOT also be specified on that interface. A [NamedConstructor] extended attribute is fine, however.

The [NoInterfaceObject] extended attribute MUST NOT be specified on an interface that has any static operations defined on it.

The [NoInterfaceObject] extended attribute MUST NOT be specified on a callback interface unless it has a constant declared on it. This is because callback interfaces without constants never have interface objects.

See section 4.2.19 and section 4.10 for the specific requirements that the use of [NoInterfaceObject] entails.

Example

The following IDL fragment defines two interfaces, one whose interface object is exposed on the ECMAScript global object, and one whose isn’t:

IDL
interface Storage {
  void addEntry(unsigned long key, any value);
};

[NoInterfaceObject]
interface Query {
  any lookupEntry(unsigned long key);
};

An ECMAScript implementation of the above IDL would allow manipulation of Storage’s prototype, but not Query’s.

ECMAScript
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

4.3.14. [OverrideBuiltins]

If the [OverrideBuiltins] extended attribute appears on an interface, it indicates that for a 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 [OverrideBuiltins] extended attribute MUST 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] or [PrimaryGlobal] 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.

See section 4.7.1 and section 4.7.3 for the specific requirements that the use of [OverrideBuiltins] entails.

Example

The following IDL fragment defines two interfaces, one that has a named property getter and one that does not.

IDL
interface StringMap {
  readonly attribute unsigned long length;
  getter DOMString lookup(DOMString key);
};

[OverrideBuiltins]
interface StringMap2 {
  readonly attribute unsigned long length;
  getter DOMString lookup(DOMString key);
};

In an ECMAScript implementation of these two interfaces, getting certain properties on objects implementing the interfaces will result in different values:

ECMAScript
// 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;

4.3.15. [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 take an identifier. Assuming that:

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 [Replaceable] extended attribute.

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 callback interface.

See the Attributes section below for how [PutForwards] is to be implemented.

Example

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:

IDL
interface Name {
  attribute DOMString full;
  attribute DOMString family;
  attribute DOMString given;
};

interface Person {
  [PutForwards=full] readonly attribute Name name;
  attribute unsigned short age;
};

In the ECMAScript binding, this would allow assignments to the “name” property:

ECMAScript
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.

4.3.16. [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 take no arguments.

An attribute with the [Replaceable] extended attribute MUST NOT also be declared with the [PutForwards] extended attribute.

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 callback interface.

See section 4.5.7 for the specific requirements that the use of [Replaceable] entails.

Example

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:

IDL
interface Counter {
  [Replaceable] readonly attribute unsigned long value;
  void increment();
};

Assigning to the “value” property on a platform object implementing Counter will shadow the property that corresponds to the attribute:

ECMAScript
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.

4.3.17. [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 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, an array type or object.

Example

As an example, this extended attribute is suitable for use on the implementation attribute on the Document interface ([DOM], section 6.5), since the same object is always returned for a given Document object.

IDL
interface Document : Node {
  [SameObject] readonly attribute DOMImplementation implementation;
  ...
};

4.3.18. [TreatNonObjectAsNull]

If the [TreatNonObjectAsNull] extended attribute appears on a callback function, then it indicates that any value assigned to an attribute whose type is a nullable callback function that is not an object will be converted to the null value.

Warning

Specifications SHOULD NOT use [TreatNonObjectAsNull] unless required to specify the behavior of legacy APIs or for consistency with these APIs. Specification authors who wish to use this feature are strongly advised to discuss this on the public-script-coord@w3.org mailing list before proceeding. At the time of writing, the only known valid use of [TreatNonObjectAsNull] is for the callback functions used as the type of event handler IDL attributes ([HTML5], section 6.1.6.1) such as onclick and onerror.

See section 4.2.23 for the specific requirements that the use of [TreatNonObjectAsNull] entails.

Example

The following IDL fragment defines an interface that has one attribute whose type is a [TreatNonObjectAsNull]-annotated callback function and another whose type is a callback function without the extended attribute:

IDL
[TreatNonObjectAsNull]
callback OccurrenceHandler = void (DOMString details);

callback ErrorHandler = void (DOMString details);

interface Manager {
  attribute OccurrenceHandler? handler1;
  attribute ErrorHandler? handler2;
};

In an ECMAScript implementation, assigning a value that is not an object (such as a Number value) to handler1 will have different behavior from that when assigning to handler2:

ECMAScript
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) {
}

manager.handler2 = function() { };
manager.handler2;            // Evaluates to the function.

manager.handler2 = 123;
manager.handler2;            // Evaluates to null.

4.3.19. [TreatNullAs]

If the [TreatNullAs] extended attribute appears on an attribute or operation argument whose type is DOMString, it indicates that a null value assigned to the attribute or passed as the operation argument 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 “”.

If [TreatNullAs] is specified on an operation itself, and that operation is on a callback interface, then it indicates that a user object implementing the interface will have the return value of the function that implements the operation handled in the same way as for operation arguments and attributes, as above.

The [TreatNullAs] extended attribute MUST take the identifier EmptyString.

The [TreatNullAs] extended attribute MUST NOT be specified on an operation argument, attribute or operation return value whose type is not DOMString.

Note

This means that even an attribute of type DOMString? must not use [TreatNullAs], since null is a valid value of that type.

The [TreatNullAs] extended attribute also MUST NOT be specified on an operation on a non-callback interface.

See section 4.2.16 for the specific requirements that the use of [TreatNullAs] entails.

Example

The following IDL fragment defines an interface that has one attribute with the [TreatNullAs] extended attribute, and one operation with an argument that has the extended attribute:

IDL
interface Dog {
  attribute DOMString name;
  [TreatNullAs=EmptyString] attribute DOMString owner;

  boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);
};

An ECMAScript implementation implementing the Dog interface would convert a null value assigned to the “name” property or passed as the argument to the isMemberOfBreed function to the empty string rather than "null":

ECMAScript
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.

4.3.20. [Unforgeable]

If the [Unforgeable] extended attribute appears on a non-static attribute or non-static operations, it indicates that the attribute or operation will be reflected as an ECMAScript 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.

If the [Unforgeable] extended attribute appears on an interface, it indicates that all of the non-static attributes and non-static operations declared on that interface and its consequential interfaces will be similarly reflected as own ECMAScript properties on objects that implement the interface, rather than on the prototype.

An attribute or operation is said to be unforgeable on a given interface A if any of the following are true:

The [Unforgeable] extended attribute MUST take no arguments.

The [Unforgeable] extended attribute MUST NOT appear on anything other than an attribute, non-static operation or an interface. If it does appear on an operation, then it MUST appear on all operations with the same identifier on that interface.

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 and all of its consequential interfaces MUST NOT have a non-static attribute or regular operation with the same identifier as X.

Note

For example, the following is disallowed:

IDL
interface A1 {
  [Unforgeable] readonly attribute DOMString x;
};
interface B1 : A1 {
  void x();  // Invalid; would be shadowed by A1's x.
};

interface B2 : A1 { };
B2 implements Mixin;
interface Mixin {
  void x();  // Invalid; B2's copy of x would be shadowed by A1's x.
};

[Unforgeable]
interface A2 {
  readonly attribute DOMString x;
};
interface B3 : A2 {
  void x();  // Invalid; would be shadowed by A2's x.
};

interface B4 : A2 { };
B4 implements Mixin;
interface Mixin {
  void x();  // Invalid; B4's copy of x would be shadowed by A2's x.
};

interface A3 { };
A3 implements A2;
interface B5 : A3 {
  void x();  // Invalid; would be shadowed by A3's mixed-in copy of A2's x.
};

See section 4.5.7, section 4.5.8, section 4.7, section 4.7.1 and section 4.7.3 for the specific requirements that the use of [Unforgeable] entails.

Example

The following IDL fragment defines an interface that has two attributes, one of which is designated as [Unforgeable]:

IDL
interface System {
  [Unforgeable] readonly attribute DOMString username;
  readonly attribute Date loginTime;
};

In an ECMAScript implementation of the interface, the username attribute will be exposed as a non-configurable property on the object itself:

ECMAScript
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 = new Date(new Date() - 3600000);
Object.defineProperty(System.prototype, "loginTime", { value: forgedLoginTime });

system.loginTime;  // So this now evaluates to forgedLoginTime.

4.4. 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 input to the security check is the platform object on which the operation invocation or attribute access is being done, and the ECMAScript global environment associated with the Function object that implements the operation or attribute.

Note

The expectation is that the HTML specification defines how a security check is performed, and that it will either throw an appropriate exception or return normally. [HTML]

4.5. Interfaces

For every interface that is exposed in a given ECMAScript global environment and:

a corresponding property MUST exist on the ECMAScript environment's global object. The name of the property is the identifier of the interface, and its value is an object called the interface object.

The property has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }. The characteristics of an interface object are described in section 4.5.1 below.

In addition, for every [NamedConstructor] extended attribute on an exposed interface, a corresponding property MUST exist on the ECMAScript global object. The name of the property is the identifier that occurs directly after the “=”, and its value is an object called a named constructor, which allows construction of objects that implement the interface. The property has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }. The characteristics of a named constructor are described in section 4.5.2 below.

4.5.1. Interface object

The interface object for a given non-callback interface is a function object. It has properties that correspond to the constants and static operations defined on that interface, as described in sections 4.5.6 and 4.5.8 below.

The value of the “prototype” property of an interface object for a non-callback interface MUST be an 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 section 4.5.4 below.

Note

Since an interface object for a non-callback interface is a function object, it will have a “prototype” property with attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }. It also means that the typeof operator will return "function" when applied to such an interface object.

The internal [[Prototype]] property of an interface object for a callback interface MUST be the Object.prototype object.

Note

Remember that interface objects for callback interfaces only exist if they have constants declared on them; when they do exist, they are not function objects.

4.5.1.1. Interface object [[Call]] method

If the interface is declared with a [Constructor] extended attribute, then the interface object can be called as a function to create an object that implements that interface. Interfaces that do not have a constructor will throw an exception when called as a function.

In order to define how overloaded constructor invocations are resolved, the overload resolution algorithm is defined. Its input is an effective overload set, S, and a list of ECMAScript values, arg0..n−1. 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.
  2. Initialize argcount to be min(maxargn).
  3. Remove from S all entries whose type list is not of length argcount.
  4. If S is empty, then throw a TypeError.
  5. Initialize d to −1.
  6. Initialize method to undefined.
  7. If there is more than one entry in S, then set d to be the distinguishing argument index for the entries of S.
  8. Initialize values to be an empty list, where each entry will be either an IDL value or the special value “missing”.
  9. Initialize i to 0.
  10. While i < d:
    1. Let V be argi.
    2. 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.

    3. Let optionality be the value at index i in the list of optionality values of any entry in S.
    4. If optionality is “optional” and V is undefined, then:
      1. If the argument at index i is declared with a default value, then append to values that default value.
      2. Otherwise, append to values the special value “missing”.
    5. Otherwise, append to values the result of converting V to IDL type type.
    6. Set i to i + 1.
  11. If i = d, then:
    1. Let V be argi.
      Note

      This is the argument that will be used to resolve which overload is selected.

    2. 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.
    3. 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, then remove from S all other entries.
    4. Otherwise: if V is a platform object – but not a platform array object – and there is an entry in S that has one of the following types at position i of its type list, then remove from S all other entries.
    5. Otherwise: if V is a Date object and there is an entry in S that has one of the following types at position i of its type list, then remove from S all other entries.
    6. Otherwise: if V is a RegExp object and there is an entry in S that has one of the following types at position i of its type list, then remove from S all other entries.
    7. 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, then remove from S all other entries.
    8. Otherwise: if V is any kind of object except for a native Date object, a native RegExp object, and there is an entry in S that has one of the following types at position i of its type list, and after performing the following steps,
      1. Let method be the result of CheckIterable(V).
      2. ReturnIfAbrupt(method).
      method is not undefined, then remove from S all other entries.
    9. Otherwise: if V is any kind of object except for a native Date object, a native RegExp object, and there is an entry in S that has one of the following types at position i of its type list, then remove from S all other entries.
    10. Otherwise: if V is a Boolean value, and there is an entry in S that has one of the following types at position i of its type list, then remove from S all other entries.
    11. Otherwise: if V is a Number value, and there is an entry in S that has one of the following types at position i of its type list, then remove from S all other entries.
    12. Otherwise: if there is an entry in S that has one of the following types at position i of its type list, then remove from S all other entries.
    13. Otherwise: if there is an entry in S that has one of the following types at position i of its type list, then remove from S all other entries.
    14. Otherwise: if there is an entry in S that has one of the following types at position i of its type list, then remove from S all other entries.
    15. 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.
    16. Otherwise: throw a TypeError.
  12. Let callable be the operation or extended attribute of the single entry in S.
  13. If i = d and method is not undefined, then
    1. Let V be argi.
    2. Let T be the type at index i in the type list of the remaining entry in S.
    3. Append to values the result of creating a sequence of type T from V and method.
    4. Set i to i + 1.
  14. While i < argcount:
    1. Let V be argi.
    2. Let type be the type at index i in the type list of the remaining entry in S.
    3. Let optionality be the value at index i in the list of optionality values of the remaining entry in S.
    4. If optionality is “optional” and V is undefined, then:
      1. If the argument at index i is declared with a default value, then append to values that default value.
      2. Otherwise, append to values the special value “missing”.
    5. Otherwise, append to values the result of converting V to IDL type type.
    6. Set i to i + 1.
  15. 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 default value, then append to values that default value.
    2. Otherwise, if callable’s argument at index i is not variadic, then append to values the special value “missing”.
    3. Set i to i + 1.
  16. Return the pair <callable, values>.
Note

The overload resolution algorithm performs both the identification of which overloaded operation, constructor, etc. is being called, and the conversion of the ECMAScript 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 ECMAScript 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 ECMAScript 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 ECMAScript value that is passed in at the distinguishing argument index to determine which IDL type it may 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. The inspection of the value at the distinguishing argument index does not have any side effects; the only side effects that come from running the overload resolution algorithm are those that come from converting the ECMAScript values to IDL values.

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 ECMAScript 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.

The internal [[Call]] method of the interface object behaves as follows, assuming arg0..n−1 is the list of argument values passed to the constructor, and I is the interface:

  1. If I was not declared with a [Constructor] extended attribute, then throw a TypeError.
  2. Let id be the identifier of interface I.
  3. Initialize S to the effective overload set for constructors with identifier id on interface I and with argument count n.
  4. Let <constructor, values> be the result of passing S and arg0..n−1 to the overload resolution algorithm.
  5. Let R be the result of performing the actions listed in the description of constructor with values as the argument values.
  6. Return the result of converting R to an ECMAScript interface type value I.

If the internal [[Call]] method of the interface object returns normally, then it MUST return an object that implements interface I. This object also MUST be associated with the ECMAScript global environment associated with the interface object.

Interface objects for non-callback interfaces MUST have a property named “length” with attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false } whose value is a Number. If the [Constructor] extended attribute, does not appear on the interface definition, then the value is 0. Otherwise, the value is determined as follows:

  1. Let id be the identifier of interface I.
  2. Initialize S to the effective overload set for constructors with identifier id on interface I and with argument count 0.
  3. Return the length of the shortest argument list of the entries in S.
4.5.1.2. Interface object [[HasInstance]] method

The internal [[HasInstance]] method of every interface object A MUST behave as follows, assuming V is the object argument passed to [[HasInstance]]:

  1. If V is not an object, return false.
  2. Let O be the result of calling the [[Get]] method of A with property name “prototype”.
  3. If O is not an object, throw a TypeError exception.
  4. If V is a platform object that implements the interface for which O is the interface prototype object, return true.
  5. Repeat:
    1. Set V to the value of the [[Prototype]] internal property of V.
    2. If V is null, return false.
    3. If O and V refer to the same object, return true.

4.5.2. Named constructors

A named constructor that exists due to one or more [NamedConstructor] extended attributes with a given identifier is a function object. It MUST have a [[Call]] internal property, which allows construction of objects that implement the interface on which the [NamedConstructor] extended attributes appear. It behaves as follows, assuming arg0..n−1 is the list of argument values passed to the constructor, id is the identifier of the constructor specified in the extended attribute named argument list, and I is the interface on which the [NamedConstructor] extended attribute appears:

  1. Initialize S to the effective overload set for constructors with identifier id on interface I and with argument count n.
  2. Let <constructor, values> be the result of passing S and arg0..n−1 to the overload resolution algorithm.
  3. Let R be the result of performing the actions listed in the description of constructor with values as the argument values.
  4. Return the result of converting R to an ECMAScript interface type value I.

If the internal [[Call]] method of the named constructor returns normally, then it MUST return an object that implements interface I. This object also MUST be associated with the ECMAScript global environment associated with the named constructor.

A named constructor MUST have a property named “length” with attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false } whose value is a Number determined as follows:

  1. Initialize S to the effective overload set for constructors with identifier id on interface I and with argument count 0.
  2. Return the length of the shortest argument list of the entries in S.

A named constructor MUST also have a property named “prototype” with attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false } whose value is the interface prototype object for the interface on which the [NamedConstructor] extended attribute appears.

4.5.3. Dictionary constructors

For every dictionary type that has one or more [Constructor] extended attributes and which is exposed in a given ECMAScript global environment, a corresponding property MUST exist on the ECMAScript environment's global object. The name of the property is the identifier of the dictionary, and its value is a function object called the dictionary constructor.

The property has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.

The internal [[Call]] method of the interface object behaves as follows, assuming arg0..n−1 is the list of argument values passed to the constructor, and D is the dictionary type:

  1. Let id be the identifier of dictionary type D.
  2. Initialize S to the effective overload set for constructors with identifier id on dictionary type D and with argument count n.
  3. Let <constructor, values> be the result of passing S and arg0..n−1 to the overload resolution algorithm.
  4. Let R be the result of performing the actions listed in the description of constructor with values as the argument values.
  5. Return the result of converting R, which is a dictionary value of type D, to an ECMAScript value.

If the internal [[Call]] method of the named constructor returns normally, then it MUST return an object that is associated with the ECMAScript global environment associated with the dictionary constructor.

A dictionary constructor object MUST have a property named “length” with attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false } whose value is a Number determined as follows:

  1. Let id be the identifier of the dictionary type.
  2. Initialize S to the effective overload set for constructors with identifier id on dictionary D and with argument count 0.
  3. Return the length of the shortest argument list of the entries in S.

4.5.4. Interface prototype object

There MUST exist an interface prototype object for every non-callback interface defined, regardless of whether the interface was declared with the [NoInterfaceObject] extended attribute. The interface prototype object for a particular interface has properties that correspond to the regular attributes and regular operations defined on that interface. These properties are described in more detail in sections 4.5.7 and 4.5.8 below.

As with the interface object, the interface prototype object also has properties that correspond to the constants defined on that interface, described in section 4.5.6 below.

If the [NoInterfaceObject] extended attribute was not specified on the interface, then the interface prototype object MUST also have a property named “constructor” with attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } whose value is a reference to the interface object for the interface.

The interface prototype object for a given interface A MUST have an internal [[Prototype]] property whose value is returned from the following steps:

  1. If A is declared with the [Global] or [PrimaryGlobal] extended attribute, then return the named properties object for A, as defined in section 4.5.5 below.
  2. Otherwise, if A is declared to inherit from another interface, then return the interface prototype object for the inherited interface.
  3. Otherwise, if A is declared with the [ArrayClass] extended attribute, then return %ArrayPrototype% ([ECMA-262], section 6.1.7.4).
  4. Otherwise, if A is declared with the [MapClass] extended attribute, then return %MapPrototype% ([ECMA-262], section 6.1.7.4).
  5. Otherwise, return %ObjectPrototype% ([ECMA-262], section 6.1.7.4). ([ECMA-262], section 15.2.4).
Note

The interface prototype object of an interface that is defined with the [NoInterfaceObject] extended attribute will be accessible if the interface is used as a non-supplemental interface. For example, with the following IDL:

IDL
[NoInterfaceObject]
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 gettings its internal [[Prototype]] property value – Object.getPrototypeOf(window.foo) in this example.

If the interface is used solely as a supplemental interface, then there will be no way to access its interface prototype object, since no object will have the interface prototype object as its internal [[Prototype]] property value. In such cases, it is an acceptable optimization for this object not to exist.

The class string of an interface prototype object is the concatenation of the interface’s identifier and the string “Prototype”.

4.5.5. Named properties object

For every interface declared with the [Global] or [PrimaryGlobal] extended attribute that supports named properties, there MUST exists an object known as the named properties object for that interface.

The named properties object for a given interface A MUST have an internal [[Prototype]] property whose value is returned from the following steps:

  1. If A is declared to inherit from another interface, then return the interface prototype object for the inherited interface.
  2. Otherwise, if A is declared with the [ArrayClass] extended attribute, then return %ArrayPrototype% ([ECMA-262], section 6.1.7.4).
  3. Otherwise, if A is declared with the [MapClass] extended attribute, then return %MapPrototype% ([ECMA-262], section 6.1.7.4).
  4. Otherwise, return %ObjectPrototype% ([ECMA-262], section 6.1.7.4).

The class string of a named properties object is the concatenation of the interface’s identifier and the string “Properties”.

4.5.5.1. Named properties object [[GetOwnProperty]] method

The internal [[GetOwnProperty]] method of every named properties object MUST behave as follows when called with object O and property name P:

  1. Let A be the interface for the named properties object O.
  2. Let object be the sole object from O’s ECMAScript global environment that implements A.
    Note

    For example, if the interface is the Window interface as defined in HTML5 ([HTML5], section 5.2), then the sole object will be this global environment’s window object.

  3. 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.
    2. Let value be an uninitialized variable.
    3. 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.
    4. 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.
    5. Let desc be a newly created Property Descriptor ([ECMA-262], section 6.2.4) with no fields.
    6. Set desc.[[Value]] to the result of converting value to an ECMAScript value.
    7. If the named property is defined to be unenumerable, then set desc.[[Enumerable]] to false, otherwise set it to true.
    8. Set desc.[[Writable]] to false and desc.[[Configurable]] to true.
    9. Return desc.
  4. Return the result of calling the default [[GetOwnProperty]] internal method ([ECMA-262], section 9.1.5) on O passing P as the argument.
4.5.5.2. Named properties object [[DefineOwnProperty]] method

The internal [[DefineOwnProperty]] method of every named properties object MUST behave as follows when called with object O and property name P. The term “Reject” is used as defined in section 4.2.25.2 above.

  1. Reject.
4.5.5.3. Named properties object [[Delete]] method

The internal [[Delete]] method of every named properties object MUST behave as follows when called with object O and property name P.

  1. Return false.

4.5.6. Constants

For each exposed constant defined on an interface A, there MUST be a corresponding property. The property has the following characteristics:

In addition, a property with the same characteristics MUST exist on the interface object, if that object exists.

4.5.7. Attributes

For each exposed attribute of the interface, whether it was declared on the interface itself or one of its consequential interfaces, there MUST exist a corresponding property. The characteristics of this property are as follows:

  • The name of the property is the identifier of the attribute.
  • The location of the property is determined as follows:
  • The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]: true, [[Configurable]]: configurable }, where:
  • The attribute getter is a Function object whose behavior when invoked is as follows:
    1. Let idlValue be an IDL value determined as follows.
    2. If the attribute is a regular attribute, then:
      1. Let I be the interface whose interface prototype object this property corresponding to the attribute appears on.
        Note

        This means that even if an implements statement was used to make an attribute available on the interface, I is the interface on the left hand side of the implements statement, and not the one that the attribute was originally declared on.

      2. Let O be the this value.
      3. If O is a platform object, then perform a security check on O with the ECMAScript global environment associated with this Function that implements the attribute getter.
      4. If O is not a platform object that implements I, then:
        1. If the attribute was specified with the [LenientThis] extended attribute, then return undefined.
        2. Otherwise, throw a TypeError.
      5. Set idlValue to be the result of performing the actions listed in the description of the attribute that occur when getting (or those listed in the description of the inherited attribute, if this attribute is declared to inherit its getter), with O as the object.
    3. Otherwise, the attribute is a static attribute. Set idlValue to be the result of performing the actions listed in the description of the attribute that occur when getting.
    4. Let V be the result of converting idlValue to an ECMAScript value.
    5. Return V.
    The value of the Function object’s “length” property is the Number value 0.
  • The attribute setter is undefined if the attribute is declared readonly and has neither a [PutForwards] nor a [Replaceable] extended attribute declared on it. Otherwise, it is a Function object whose behavior when invoked is as follows:
    1. If no arguments were passed to the Function, then throw a TypeError.
    2. Let V be the value of the first argument passed to the Function.
    3. If the attribute is a regular attribute, then:
      1. Let I be the interface whose interface prototype object this property corresponding to the attribute appears on.
      2. Let O be the this value.
      3. If O is a platform object, then perform a security check on O with the ECMAScript global environment associated with this Function that implements the attribute setter.
      4. Let validThis be true if O is a platform object that implements I, or false otherwise.
      5. If validThis is false and the attribute was not specified with the [LenientThis] extended attribute, then throw a TypeError.
      6. If the attribute is declared with a [Replaceable] extended attribute, then:
        1. Let P be the identifier of the attribute.
        2. Call the [[DefineOwnProperty]] method of O passing property name P, Property Descriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }, and false.
        3. Return undefined.
      7. If validThis is false, then return.
      8. If the attribute is declared with a [PutForwards] extended attribute, then:
        1. Let Q be the result of calling the [[Get]] method on O using the identifier of the attribute as the property name.
        2. If Q is not an object, then throw a TypeError.
        3. Let A be the attribute identified by the [PutForwards] extended attribute.
        4. Call the [[Put]] method on Q using the identifier of A as the property name and V as the value.
        5. Return.
    4. Let idlValue be an IDL value determined as follows:
      • If the type of the attribute is an enumeration, then:
        1. Let S be the result of calling ToString(V).
        2. If S is not one of the enumeration’s values, then return undefined.
        3. The value of idlValue is the enumeration value equal to S.
      • Otherwise, the type of the attribute is not an enumeration. The value of idlValue is the result of converting V to an IDL value.
    5. If the attribute is a regular attribute, then perform the actions listed in the description of the attribute that occur when setting, with O as the object and idlValue as the value.
    6. Otherwise, the attribute is a static attribute. Perform the actions listed in the description of the attribute that occur when setting with idlValue as the value.
    7. Return undefined.
    The value of the Function object’s “length” property is the Number value 1.
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

Note that 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.

4.5.8. Operations

For each unique identifier of an exposed operation defined on the interface, there MUST exist a corresponding property, unless the effective overload set for that identifier and operation and with an argument count of 0 has no entries. The characteristics of this property are as follows:

  • The name of the property is the identifier.
  • The location of the property is determined as follows:
  • The property has attributes { [[Writable]]: B, [[Enumerable]]: true, [[Configurable]]: B }, where B is false if the operation is unforgeable on the interface, and true otherwise.
  • The value of the property is a Function object whose behavior is as follows, assuming id is the identifier, arg0..n−1 is the list of argument values passed to the function:
    1. Try running the following steps:
      1. Let I be the interface whose interface prototype object (or interface object, for a static operation) this property corresponding to the operation appears on.
        Note

        This means that even if an implements statement was used to make an operation available on the interface, I is the interface on the left hand side of the implements statement, and not the one that the operation was originally declared on.

      2. Let O be a value determined as follows:
        • If the operation is a static operation, then O is null.
        • Otherwise, if the interface on which the operation appears has an [ImplicitThis] extended attribute, and the this value is null or undefined, then O is the ECMAScript global object associated with the Function object.
        • Otherwise, if the this value is not null, then O is the this value.
        • Otherwise, throw a TypeError.
      3. If O is a platform object, then perform a security check on O with the ECMAScript global environment associated with this Function that implements the operation.
      4. If O is not null and is also not a platform object that implements interface I, throw a TypeError.
      5. Initialize S to the effective overload set for regular operations (if the operation is a regular operation) or for static operations (if the operation is a static operation) with identifier id on interface I and with argument count n.
      6. Let <operation, values> be the result of passing S and arg0..n−1 to the overload resolution algorithm.
      7. Let R be the result of performing (on O, if the operation is not a static operation) the actions listed in the description of operation with values as the argument values.
      8. Return the result of converting R to an ECMAScript value of the type op is declared to return.
      And then, if an exception was thrown:
      1. If O has a return type that is a promise type, then:
        1. Let reject be the initial value of %Promise%.reject.
        2. Return the result of calling reject with %Promise% as the this object and the exception as the single argument value.
      2. Otherwise, end these steps and allow the exception to propagate.
  • The value of the Function object’s “length” property is a Number determined as follows:
    1. Let S be the effective overload set for regular operations (if the operation is a regular operation) or for static operations (if the operation is a static operation) with identifier id on interface I and with argument count 0.
    2. Return the length of the shortest argument list of the entries in S.
4.5.8.1. 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] or [PrimaryGlobal] 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 Function object, which behaves as follows:

    1. Let O be the result of calling ToObject on the this value.
    2. If O is a platform object, then perform a security check on O with the ECMAScript global environment associated with this Function that implements the stringifier.
    3. If O is not an object that implements the interface on which the stringifier was declared, then throw a TypeError.
    4. Let V be an uninitialized variable.
    5. Depending on where stringifier was specified:
      on an attribute
      Set V to the result of performing the actions listed in the description of the attribute that occur when getting (or those listed in the description of the inherited attribute, if this attribute is declared to inherit its getter), with O as the object.
      on an operation with an identifier
      Set V to the result of performing the actions listed in the description of the operation, using O as the this value and passing no arguments.
      on an operation with no identifier
      Set V to the result of performing the stringification behavior of the interface.
    6. Return the result of converting V to a String value.

    The value of the Function object’s “length” property is the Number value 0.

4.5.8.2. Serializers

If the interface has an exposed serializer, then a property MUST exist whose name is “toJSON”, with attributes { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true } and whose value is a Function object.

The location of the property is determined as follows:

The property’s Function object, when invoked, MUST behave as follows:

  1. Let O be the result of calling ToObject on the this value.
  2. If O is a platform object, then perform a security check on O with the ECMAScript global environment associated with this Function that implements the serializer.
  3. If O is not an object that implements the interface on which the serializer was declared, then throw a TypeError.
  4. Depending on how serializer was specified:
    on an operation with an identifier
    1. Return the result of performing the actions listed in the description of the operation, using O as the this value and passing no arguments.
    as a keyword, either with or without a serialization pattern
    1. Let S be the serialized value that is the result of invoking the serialization behavior of the interface for object O.
    2. Return the result of converting S to an ECMAScript value.

The following steps define how to convert a serialized value to an ECMAScript value:

  1. Let S be the serialized value.
  2. Depending on the type of S:
    a map
    1. Let O be a new object created as if by the expression ({}).
    2. For each entry in S, in the order they were added to the map:
      1. Let V be the result of converting the value of the entry to an ECMAScript value.
      2. Let P be the entry’s key.
      3. Call the [[DefineOwnProperty]] internal method of O passing property name P, Property Descriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }, and false as arguments.
    3. Return O.
    a list
    1. Let A be a new Array object created as if by the expression [].
    2. Let index be 0.
    3. While index is less than the number of elements in S:
      1. Let V be the result of converting the value of the element in S at index index to an ECMAScript value.
      2. Let P be ToString(index).
      3. Call the [[DefineOwnProperty]] internal method of O passing property name P, Property Descriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }, and false as arguments.
    4. Return A.
    any other serialized value
    1. Let V be the result of converting S to an ECMAScript value.
    2. Return V.

4.5.9. Iterators

If the interface has an exposed iterator or if the interface defines an indexed property getter, then a property MUST exist whose name is “iterator”, with attributes { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true } and whose value is a function object.

The location of the property is determined as follows:

If the interface is declared with the [Global] or [PrimaryGlobal] extended attribute, then the property exists on the single object that implements that interface. Otherwise, the property exists on the interface prototype object.

If the interface has an iterator, then the Function, when invoked, MUST behave as follows:

  1. Let object be the result of calling ToObject on the this value.
  2. If object is a platform object, then perform a security check on object with the ECMAScript global environment associated with this Function that implements the iterator.
  3. Let interface be the interface on which the iterator is declared.
  4. If object is not a platform object that implements interface, then throw a TypeError.
  5. Let iterator be an object determined depending on how the iterator was declared:
    identifying an iterator object interface
    iterator is the result of following the definition of how to create an iterator object for object.
    otherwise
    iterator is a newly created default iterator object for interface with object as its target.
  6. Return iterator.

If the interface does not have an iterator but does define an indexed property getter, then the Function object that is the value of the iterator property, when invoked, MUST behave as follows:

  1. Let object be the result of calling ToObject on the this value.
  2. If object is a platform object, then perform a security check on object with the ECMAScript global environment associated with this Function that implements the iterator.
  3. If object is not a platform object that implements the interface on which the iterator is defined, then throw a TypeError.
  4. Let proto be the [[ArrayIteratorPrototype]] object.
  5. Return a new object with internal properties { [[NativeBrand]]: NativeArrayIterator, [[Prototype]]: proto, [[Target]]: object, [[Index]]: 0 }.
Editorial note

Native array iterators are currently only defined in a strawman wiki page and this will need to updated once they have been added to the ES6 spec.

In either case, the value of the Function object’s “length” property is the Number value 0.

4.5.9.1. Default iterator objects

A default iterator object for a given interface and target is an object whose internal [[Prototype]] property is the iterator prototype object for the interface.

A default iterator object has two internal values:

  1. its target, which is an object whose values are to be iterated, and
  2. its state, which is an value that is used to track the state of the iterator.

The state of a default iterator object can be uninitialized, or it can be any value that the iterator behavior of the interface specifies, or it can be the special value finished. When a default iterator object is first created, its state begins uninitialized. Once it has iterated through all of the values of the target object, its state will be the special finished value.

The class string of a default iterator object for a given interface is the result of concatenting the identifier of the interface and the string “Iterator”.

4.5.9.2. Iterator prototype object

The iterator prototype object for a given interface is an object that exists for every interface that defines an iterator. It serves as the prototype for default iterator objects for the interface.

The internal [[Prototype]] property of an iterator prototype object MUST be the Object.prototype object.

An iterator prototype object MUST have a property named “next” with attributes { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true } and whose value is a function object that behaves as follows:

  1. Let interface be the interface for which the iterator prototype object exists.
  2. Let object be the result of calling ToObject on the this value.
  3. If object is a platform object, then perform a security check on object with the ECMAScript global environment associated with this Function that implements the iterator’s next method.
  4. If object is a platform object, then perform a security check on object with the ECMAScript global environment associated with this Function that implements the iterator’s next method.
  5. If object is not a default iterator object for interface, then throw a TypeError.
  6. Let target be object’s target.
  7. If object’s state is the special value finished, then throw StopIteration.
  8. Let value be the result of performing the steps listed as the iterator behavior of the interface for the target object, with the object’s state as the iterator state.
  9. If the iterator behavior returned no value, then throw StopIteration.
  10. Return value.

The class string of an iterator prototype object for a given interface is the result of concatenting the identifier of the interface and the string “Iterator”.

4.5.9.3. Iterator object interfaces

The interface prototype object for an iterator object interface MUST have a property named “next” with attributes { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true } and whose value is a function object that behaves as follows:

  1. Let interface be the iterator object interface.
  2. Let object be the result of calling ToObject on the this value.
  3. If object is a platform object, then perform a security check on object with the ECMAScript global environment associated with this Function that implements the iterator’s next method.
  4. If object is not a platform object that implements interface, then throw a TypeError.
  5. Let value be the result of performing the steps listed as the iterator object behavior of the interface for object.
  6. If the iterator object behavior returned returned no value, then throw StopIteration.
  7. Return value.

The value of the Function object’s “length” property is the Number value 0.

4.5.10. Initializing objects from iterables

Some objects, which are attempting to emulate map- and set-like interfaces, will want to accept iterables as constructor parameters and initialize themselves in this way. Here we provide some algorithms that can be invoked in order to do so in the same way as in the ECMAScript spec, so that those objects behave the same as the built-in Map and Set objects.

To add map elements from an iterable iterable to an object destination with adder method name adder, perform the following steps:

  1. If Type(destination) is not Object, then, throw a TypeError exception.
  2. If iterable is not present, let iterable be undefined.
  3. If iterable is either undefined or null, then let iter be undefined.
  4. Else,
    1. Let adder be the result of Get(destination, adder).
    2. ReturnIfAbrupt(adder).
    3. If IsCallable(adder) is false, throw a TypeError exception.
    4. Let iter be the result of GetIterator(iterable).
    5. ReturnIfAbrupt(iter).
  5. If iter is undefined, then return.
  6. Repeat
    1. Let next be the result of IteratorStep(iter).
    2. ReturnIfAbrupt(next).
    3. If next is false, then return NormalCompletion(destination).
    4. Let nextItem be IteratorValue(next).
    5. ReturnIfAbrupt(nextItem).
    6. If Type(nextItem) is not Object, then throw a TypeError exception.
    7. Let k be the result of Get(nextItem, '0').
    8. ReturnIfAbrupt(k).
    9. Let v be the result of Get(nextItem, '1').
    10. ReturnIfAbrupt(v).
    11. Let status be the result of calling the [[Call]] internal method of adder with destination as thisArgument and (k, v) as argumentsList.
    12. ReturnIfAbrupt(status).

4.5.11. Map members

If an interface A is declared with the [MapClass] extended attribute, then there exists a number of additional properties on A’s interface prototype object. These additional properties are described in the sub-sections below.

4.5.11.1. size

There MUST exist a property named “size” on A’s interface prototype object with the following characteristics:

  • The property has attributes { [[Get]]: G, [[Enumerable]]: false, [[Configurable]]: true }, where G is the interface’s map size getter, defined below.
  • The map size getter is a Function object whose behavior when invoked is as follows:

    1. Let O be the this value.
    2. If O is a platform object, then perform a security check on O with the ECMAScript global environment associated with this Function that implements the size property.
    3. If O is not an object that implements A, then throw a TypeError.
    4. Return the Number value that represents the number of map entries that O has.

    The value of the Function object’s “length” property is the Number value 0.

4.5.11.2. entries

There MUST exist a property named “entries” on A’s interface prototype object with the following characteristics:

  • The property has attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
  • The value of the property is a Function object behavior when invoked is as follows:
    1. Editorial note

      Define an iterator that yields map key–value pairs.

    The value of the Function object’s “length” property is the Number value 0.

4.5.11.3. keys

There MUST exist a property named “keys” on A’s interface prototype object with the following characteristics:

  • The property has attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
  • The value of the property is a Function object behavior when invoked is as follows:
    1. Editorial note

      Define an iterator that yields map entry keys.

    The value of the Function object’s “length” property is the Number value 0.

4.5.11.4. values

There MUST exist a property named “values” on A’s interface prototype object with the following characteristics:

  • The property has attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
  • The value of the property is a Function object behavior when invoked is as follows:
    1. Editorial note

      Define an iterator that yields map entry values.

    The value of the Function object’s “length” property is the Number value 0.

4.5.11.5. clear

If A and A’s consequential interfaces do not declare an interface member with the identifier “clear”, then a property with that name and the following characteristics MUST exist on A’s interface prototype object:

  • The property has attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
  • The value of the property is a Function object behavior when invoked is as follows:

    • Editorial note

      Define this to behave like:

      ECMAScript
      for (let k of [...this.keys()])
        this.delete(k);

    The value of the Function object’s “length” property is the Number value 0.

4.5.11.6. delete

If A and A’s consequential interfaces do not declare an interface member with the identifier “delete”, then a property with that name and the following characteristics MUST exist on A’s interface prototype object:

  • The property has attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
  • The value of the property is a Function object behavior when invoked is as follows:

    1. Let O be the this value.
    2. If O is a platform object, then perform a security check on O with the ECMAScript global environment associated with this Function that implements the delete method.
    3. If O is not a platform object that implements A, then throw a TypeError.
    4. Let arg be the first argument passed to the function, or undefined if one was not passed.
    5. Let key be the result of converting arg to an IDL value of the map key type.
    6. If O has no map entry with key key, then return the Boolean value false.
    7. Remove O’s map entry whose key is key.
    8. Return the Boolean value true.

    The value of the Function object’s “length” property is the Number value 1.

4.5.11.7. forEach

If A and A’s consequential interfaces do not declare an interface member with the identifier “forEach”, then a property with that name and the following characteristics MUST exist on A’s interface prototype object:

  • The property has attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
  • The value of the property is a Function object behavior when invoked is as follows:

    • Editorial note

      Define this to behave like:

      ECMAScript
      for (let [k, v] of this)
        callbackFn.call(thisArg, v, k, this);

    The value of the Function object’s “length” property is the Number value 1.

4.5.11.8. get

If A and A’s consequential interfaces do not declare an interface member with the identifier “get”, then a property with that name and the following characteristics MUST exist on A’s interface prototype object:

  • The property has attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
  • The value of the property is a Function object behavior when invoked is as follows:

    1. Let O be the this value.
    2. If O is a platform object, then perform a security check on O with the ECMAScript global environment associated with this Function that implements the get method.
    3. If O is not an object that implements A, then throw a TypeError.
    4. Let arg be the first argument passed to the function, or undefined if one was not passed.
    5. Let key be the result of converting arg to an IDL value of the map key type.
    6. If O has a map entry with key key, then return the result of converting that entry’s value to an ECMAScript value.
    7. Return undefined.

    The value of the Function object’s “length” property is the Number value 1.

Editorial note

Although the default implementation of get can return undefined, if an operation named “get” is defined then that cannot return undefined. How should we resolve this?

Editorial note

We should handle exceptions in get if the value type is a promise type, and convert them into a rejected promise.

4.5.11.9. has

If A and A’s consequential interfaces do not declare an interface member with the identifier “has”, then a property with that name and the following characteristics MUST exist on A’s interface prototype object:

  • The property has attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
  • The value of the property is a Function object behavior when invoked is as follows:

    1. Let O be the this value.
    2. If O is a platform object, then perform a security check on O with the ECMAScript global environment associated with this Function that implements the has method.
    3. If O is not an object that implements A, then throw a TypeError.
    4. Let arg be the first argument passed to the function, or undefined if one was not passed.
    5. Let key be the result of converting arg to an IDL value of the map key type.
    6. If O has a map entry with key key, then return the Boolean value true Otherwise, return the Boolean value false.

    The value of the Function object’s “length” property is the Number value 1.

4.5.11.10. set

If A and A’s consequential interfaces do not declare an interface member with the identifier “set”, then a property with that name and the following characteristics MUST exist on A’s interface prototype object:

  • The property has attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
  • The value of the property is a Function object behavior when invoked is as follows:

    1. Let O be the this value.
    2. If O is a platform object, then perform a security check on O with the ECMAScript global environment associated with this Function that implements the set method.
    3. If O is not an object that implements A, then throw a TypeError.
    4. Let arg1 be the first argument passed to the function, or undefined if one was not passed.
    5. Let arg2 be the second argument passed to the function, or undefined if one was not passed.
    6. Let key be the result of converting arg1 to an IDL value of the map key type.
    7. Let value be the result of converting arg2 to an IDL value of the map value type.
    8. If O has a map entry with key key, then update it in place to have a value of value.
    9. Otherwise, O does not have a map entry with key key. Append a new entry to O’s list of map entries with key key and value value.

    The value of the Function object’s “length” property is the Number value 2.

4.6. Implements statements

The interface prototype object of an interface A MUST have a copy of each property that corresponds to one of the constants, attributes or operations that exist on all of the interface prototype objects of A’s consequential interfaces. For operations, where the property is a data property with a Function object value, each copy of the property MUST have distinct Function objects. For attributes, each copy of the accessor property MUST have distinct Function objects for their getters, and similarly with their setters.

Note

When invoking an operation by calling a Function object that is the value of one of the copies that exists due to an implements statement, the this value is checked to ensure that it is an object that implements the interface corresponding to the interface prototype object that the property is on.

For example, consider the following IDL:

IDL
interface A {
  void f();
};

interface B { };
B implements A;

interface C { };
C implements A;

Attempting to call B.prototype.f on an object that implements A (but not B) or one that implements C will result in a TypeError being thrown. However, calling calling A.prototype.f on an object that implements B or one that implements C would succeed. This is handled by the algorithm in section 4.5.8 that defines how IDL operation invocation works in ECMAScript.

Similar behavior is required for the getter and setter Function objects that correspond to an IDL attributes, and this is handled in section 4.5.7.

4.7. Platform objects implementing interfaces

Every platform object is associated with a global environment, just as the initial objects are. It is the responsibility of specifications using Web IDL to state which global environment (or, by proxy, which global object) each platform object is associated with.

The primary interface of a platform object that implements one or more interfaces is the most-derived non-supplemental interface that it implements. The value of the internal [[Prototype]] property of the platform object is the interface prototype object of the primary interface from the platform object’s associated global environment.

The global environment that a given platform object is associated with can change after it has been created. When the global environment associated with a platform object is changed, its internal [[Prototype]] property MUST be immediately updated to be the interface prototype object of the primary interface from the platform object’s newly associated global environment.

Every platform object that implements an [Unforgeable]-annotated interface and which does not have a stringifier that is unforgeable on any of the interfaces it implements MUST have a property with the following characteristics:

  • The name of the property is “toString”.
  • The property has attributes { [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }.
  • The value of the property is a Function object whose behavior is the same as that of the toString function described in section 4.1 above. This Function object is the default unforgeable toString function. The value of the Function object’s “length” property is the Number value 0.

Every platform object that implements an [Unforgeable]-annotated interface and which does not have a serializer that is unforgeable on any of the interfaces it implements MUST have a property with the following characteristics:

  • The name of the property is “toJSON”.
  • The property has attributes { [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }.
  • The value of the property is undefined.

Every platform object that implements an [Unforgeable]-annotated interface MUST have a property with the following characteristics:

  • The name of the property is “valueOf”.
  • The property has attributes { [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }.
  • The value of the property is a Function object whose behavior is as follows:
    1. Return the this value.
    This Function object is the default unforgeable valueOf function. The value of the Function object’s “length” property is the Number value 0.

The class string of a platform object that implements one or more interfaces MUST be the identifier of the primary interface of the platform object.

4.7.1. Indexed and named properties

If a platform object implements an interface that supports indexed or named properties, the object will appear to have additional properties that correspond to the object’s 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.

However, when the [Global] or [PrimaryGlobal] extended attribute has been used, named properties are not exposed on the object but on another object in the prototype chain, the named properties object.

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, or if one of the interfaces is a supplemental interface for the platform object, 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 platform object implements is the one that defines the behavior when indexing the object with an array index. Similarly for indexed property setters, deleters and creators. This way, the definitions of these special operations from ancestor interfaces can be overridden.

Platform objects implementing an interface that supports indexed or named properties cannot be fixed; if Object.freeze, Object.seal or Object.preventExtensions is called on one of these objects, the function MUST throw a TypeError. Similarly, an interface prototype object that exposes named properties due to the use of [Global] or [PrimaryGlobal] also MUST throw a TypeError if one of the three functions above is called on it.

The name of each property that appears to exist due to an object supporting indexed properties is an array index property name, which is a property name P for which the following algorithm returns true:

  1. Let i be ToUint32(P).
  2. Let s be ToString(i).
  3. If sP or i = 232 − 1, then return false.
  4. Return true.

A property name is an unforgeable property name on a given platform object 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. If the object implements an [Unforgeable]-annotated interface, then “toString” and “valueOf” are also unforgeable property names on that object.

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 [OverrideBuiltins] extended attribute was used. The algorithm operates as follows, with property name P and object O:

  1. If P is an unforgeable property name on O, then return false.
  2. If O implements an interface with an [Unforgeable]-annotated attribute whose identifier is P, then return false.
  3. If P is not a supported property name of O, then return false.
  4. If O implements an interface that has the [OverrideBuiltins] extended attribute, then return true.
  5. If O has an own property named P, then return false.
  6. Initialize prototype to be the value of the internal [[Prototype]] property of O.
  7. While prototype is not null:
    1. If prototype is not a named properties object, and O has an own property named P, then return false.
    2. Set prototype to be the value of the internal [[Prototype]] property of prototype.
  8. Return true.
Note

This should ensure that for objects with named properties, property resolution is done in the following order:

  1. Indexed properties.
  2. Unforgeable attributes and operations.
  3. Then, if [OverrideBuiltins]:
    1. Named properties.
    2. Own properties.
    3. Properties from the prototype chain.
  4. Otherwise, if not [OverrideBuiltins]:
    1. Own properties.
    2. Properties from the prototype chain.
    3. Named properties.

Support for getters is handled by the platform object [[GetOwnProperty]] method defined in section 4.7.2, for creators and setters by the platform object [[DefineOwnProperty]] method defined in section 4.7.3, and for deleters by the platform object [[Delete]] method defined in section 4.7.4.

4.7.2. Platform object [[GetOwnProperty]] method

The internal [[GetOwnProperty]] method of every platform object O that implements an interface which supports indexed or named properties MUST behave as follows when called with property name P:

  1. Let ignore be false.
  2. If O supports indexed properties and P is an array index property name, then:
    1. Let index be the result of calling ToUint32(P).
    2. If index is a supported property index, then:
      1. Let operation be the operation used to declare the indexed property getter.
      2. Let value be an uninitialized variable.
      3. 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.
      4. Otherwise, operation was defined with an identifier. Set value to the result of performing the steps listed in the description of operation with index as the only argument value.
      5. Let desc be a newly created Property Descriptor ([ECMA-262], section 6.2.4) with no fields.
      6. Set desc.[[Value]] to the result of converting value to an ECMAScript value.
      7. If O implements an interface with an indexed property setter, then set desc.[[Writable]] to true, otherwise set it to false.
      8. Set desc.[[Enumerable]] and desc.[[Configurable]] to true.
      9. Return desc.
    3. Set ignore to true.
  3. If O supports named properties, O does not implement an interface with the [Global] or [PrimaryGlobal] extended attribute, the result of running the named property visibility algorithm with property name P and object O is true, and ignore is false, then:
    1. Let operation be the operation used to declare the named property getter.
    2. Let value be an uninitialized variable.
    3. 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.
    4. 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.
    5. Let desc be a newly created Property Descriptor ([ECMA-262], section 6.2.4) with no fields.
    6. Set desc.[[Value]] to the result of converting value to an ECMAScript value.
    7. If O implements an interface with a named property setter, then set desc.[[Writable]] to true, otherwise set it to false.
    8. If the named property is defined to be unenumerable, then set desc.[[Enumerable]] to false, otherwise set it to true.
    9. Set desc.[[Configurable]] to true.
    10. Return desc.
  4. Return the result of calling the default [[GetOwnProperty]] internal method ([ECMA-262], section 9.1.5) on O passing P as the argument.

4.7.3. Platform object [[DefineOwnProperty]] method

The internal [[DefineOwnProperty]] method of every platform object O that implements an interface which supports indexed or named properties MUST behave as follows when called with property name P, Property Descriptor Desc and boolean flag Throw. The term “Reject” is used as defined in section 4.2.25.2 above.

  1. If O supports indexed properties and P is an array index property name, then:
    1. If the result of calling IsDataDescriptor(Desc) is false, then Reject.
    2. Let index be the result of calling ToUint32(P).
    3. Let creating be true if index is not a supported property index, and false otherwise.
    4. If creating is true and O does not implement an interface with an indexed property creator, then Reject.
    5. If creating is false and O does not implement an interface with an indexed property setter, then Reject.
    6. Let operation be the operation used to declare the indexed property creator if creating is true, or the indexed property setter if creating is false.
    7. Let T be the type of the second argument of operation.
    8. Let value be the result of converting Desc.[[Value]] to an IDL value of type T.
    9. 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.
      2. 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.
    10. Otherwise, operation was defined with an identifier. Perform the steps listed in the description of operation with index and value as the two argument values.
    11. Return true.
  2. If O supports named properties, O does not implement an interface with the [Global] or [PrimaryGlobal] extended attribute 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.
    2. If O implements an interface with the [OverrideBuiltins] 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 Reject.
      2. If creating is false or O implements an interface with a named property creator, then:
        1. If the result of calling IsDataDescriptor(Desc) is false, then Reject.
        2. Let operation be the operation used to declare the named property creator if creating is true, or the named property setter if creating is false.
        3. Let T be the type of the second argument of operation.
        4. Let value be the result of converting Desc.[[Value]] to an IDL value of type T.
        5. 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.
          2. 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.
        6. Otherwise, operation was defined with an identifier. Perform the steps listed in the description of operation with index and value as the two argument values.
        7. Return true.
  3. If O does not implement an interface with the [Global] or [PrimaryGlobal] extended attribute, then set Desc.[[Configurable]] to true.
  4. Call the default [[DefineOwnProperty]] internal method ([ECMA-262], section 9.1.6) on O passing P, Desc, and Throw as arguments.

4.7.4. Platform object [[Delete]] method

The internal [[Delete]] method of every platform object O that implements an interface which supports indexed or named properties MUST behave as follows when called with property name P.

  1. If O supports indexed properties and P is an array index property name, then:
    1. Let index be the result of calling ToUint32(P).
    2. If index is not a supported property index, then return true.
    3. If O does not implement an interface with an indexed property deleter, then return false.
    4. Let operation be the operation used to declare the indexed property deleter.
    5. If operation was defined without an identifier, then:
      1. Perform the steps listed in the interface description to delete an existing indexed property with index as the index.
      2. If the steps indicated that the deletion failed, then false.
    6. Otherwise, operation was defined with an identifier:
      1. Perform the steps listed in the description of operation with index as the only argument value.
      2. If operation was declared with a return type of boolean and the steps returned false, then false.
    7. Return true.
  2. If O supports named properties, O does not implement an interface with the [Global] or [PrimaryGlobal] 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 false.
    2. Let operation be the operation used to declare the named property deleter.
    3. 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.
      2. If the steps indicated that the deletion failed, then false.
    4. Otherwise, operation was defined with an identifier:
      1. Perform the steps listed in the description of operation with P as the only argument value.
      2. If operation was declared with a return type of boolean and the steps returned false, then false.
    5. Return true.
  3. If O has an own property with name P, then:
    1. If the property is not configurable, then false.
    2. Otherwise, remove the property from O.
  4. Return true.

4.7.5. Platform object [[Call]] method

The internal [[Call]] method of every platform object O that implements an interface I with at least one legacy caller MUST behave as follows, assuming arg0..n−1 is the list of argument values passed to [[Call]]:

  1. Initialize S to the effective overload set for legacy callers on I and with argument count n.
  2. Let <operation, values> be the result of passing S and arg0..n−1 to the overload resolution algorithm.
  3. Perform the actions listed in the description of the legacy caller operation with values as the argument values.
  4. Return the result of converting the return value from those actions to an ECMAScript value of the type operation is declared to return (or undefined if operation is declared to return void).

4.7.6. Property enumeration

This document does not define a complete property enumeration order for all platform objects implementing interfaces (or for platform objects representing exceptions). However, if a platform object implements an interface that supports indexed or named properties, then properties on the object MUST be enumerated in the following order:

  1. If the object supports indexed properties, then the object’s supported property indices are enumerated first, in numerical order.
  2. If the object supports named properties, then the object’s supported property names that are visible according to the named property visibility algorithm and which are not stated to be unenumerable are enumerated next, in the order given in the definition of the set of supported property names.
  3. Finally, any enumerable own properties or properties from the object’s prototype chain are then enumerated, in no defined order.
Note

Future versions of the ECMAScript specification may define a total order for property enumeration.

4.8. User objects implementing callback interfaces

As described in section 3.9 above, callback interfaces can be implemented in script by an ECMAScript object. The following cases determine whether and how a given object is considered to be a user object implementing a callback interface:

  • If the interface is a single operation callback interface (defined below) then any object apart from a native Date object or native RegExp object is considered to implement the interface. The implementation of the operation (or set of overloaded operations) is as follows:
    • If the object is callable, then the implementation of the operation (or set of overloaded operations) is the callable object itself.
    • Otherwise, the object is not callable. The implementation of the operation (or set of overloaded operations) is the result of invoking the internal [[Get]] method on the object with a property name that is the identifier of the operation.
  • Otherwise, the interface is not a single operation callback interface. Any object that is not a native Date object or a native RegExp object is considered to implement the interface. For each operation declared on the interface with a given identifier, the implementation is the result of invoking [[Get]] on the object with a property name that is that identifier.

A single operation callback interface is a callback interface that:

A user object’s operation is called with a list of IDL argument values idlarg0..n−1 by following the algorithm below. The callback this value is the value to use as the this value when a callable object was supplied as the implementation of a single operation callback interface. By default, undefined is used as the callback this value, however this MAY be overridden by other specifications.

  1. Try running the following steps:
    1. Let V be the IDL callback interface type value that represents the user object implementing the interface.
    2. Let O be the ECMAScript object corresponding to V.
    3. Let X be the implementation of the operation. If the interface is a single operation callback interface and IsCallable(O) is true, then X is O. Otherwise, X is the result of calling the internal [[Get]] method of O with the identifier of the operation as the property name.
    4. If Type(X) is not Object, throw a TypeError exception.
    5. If IsCallable(X) is false, then throw a TypeError exception.
    6. Let this be O if the interface is not a single operation callback interface or if IsCallable(O) is false, and the callback this value otherwise.
    7. Let arg0..n−1 be a list of ECMAScript values, where argi is the result of converting idlargi to an ECMAScript value.
    8. Let script be the callback context associated with V.
    9. Push script on to the stack of incumbent scripts. [HTML]
    10. Let R be an uninitialized variable.
    11. Try running the following step:
      1. Set R to the result of invoking the [[Call]] method of X, providing this as the this value and arg0..n−1 as the argument values.
      And then, whether or not an exception was thrown:
      1. Pop script off the stack of incumbent scripts.
      2. If an exception was thrown, end these steps, and allow it to propagate.
    12. If the operation’s return type is void, return.
    13. Return the result of converting R to an IDL value of the same type as the operation’s return type.
    And then, if an exception was thrown:
    1. If the operation has a return type that is a promise type, then:
      1. Let reject be the initial value of %Promise%.reject.
      2. Return the result of calling reject with %Promise% as the this object and the exception as the single argument value.
    2. Otherwise, end these steps and allow the exception to propagate.

Note that ECMAScript objects need not have properties corresponding to constants on them to be considered as user objects implementing interfaces that happen to have constants declared on them.

The value of a user object’s attribute is retrieved using the following algorithm:

  1. Try running the following steps:
    1. Let V be the IDL callback interface type value that represents the user object implementing the interface.
    2. Let O be the ECMAScript object corresponding to V.
    3. Let P be the identifier of the attribute.
    4. Let script be the callback context associated with V.
    5. Push script on to the stack of incumbent scripts. [HTML]
    6. Let R be an uninitialized variable.
    7. Try running the following step:
      1. Set R to the result of invoking the [[Get]] method of O with property name P.
      And then, whether or not an exception was thrown:
      1. Pop script off the stack of incumbent scripts.
      2. If an exception was thrown, end these steps, and allow it to propagate.
    8. Return the result of converting R to an IDL value of the same type as the attribute’s type.
    And then, if an exception was thrown:
    1. If the operation has a return type that is a promise type, then:
      1. Let reject be the initial value of %Promise%.reject.
      2. Return the result of calling reject with %Promise% as the this object and the exception as the single argument value.
    2. Otherwise, end these steps and allow the exception to propagate.

The value of a user object’s attribute is set using the following algorithm:

  1. Let V be the IDL callback interface type value that represents the user object implementing the interface.
  2. Let O be the ECMAScript object corresponding to V.
  3. Let P be the identifier of the attribute.
  4. Let V be the IDL value to be assigned to the attribute.
  5. Let W be the result of converting V to an ECMAScript value.
  6. Let script be the callback context associated with V.
  7. Push script on to the stack of incumbent scripts. [HTML]
  8. Try running the following step:
    1. Invoke the [[Put]] method of O with property name P and value W.
    And then, whether or not an exception was thrown:
    1. Pop script off the stack of incumbent scripts.
    2. If an exception was thrown, end these steps, and allow it to propagate.

4.9. Invoking callback functions

An ECMAScript callable object that is being used as a callback function value is called in a manner similar to how operations on user objects are called (as described in the previous section). The callable object is called with a list of values arg0..n−1, each of which is either an IDL value of the special value “missing” (representing a missing optional argument), by following the algorithm below. By default, the callback this value when invoking a callback function is undefined, unless overridden by other specifications.

  1. Try running the following steps:
    1. Let V be the IDL callback function type value.
    2. Let F be the ECMAScript object corresponding to V.
    3. Let R be an uninitialized variable.
    4. If IsCallable(F) is false, then set R to the value undefined.
    5. Otherwise,
      1. Initialize values to be an empty list of ECMAScript values.
      2. Initialize count to 0.
      3. Initialize i to 0.
      4. While i < n:
        1. If argi is the special value “missing”, then append to values the ECMAScript undefined value.
        2. Otherwise, argi is an IDL value. Append to values the result of converting argi to an ECMAScript value, and set count to i + 1.
        3. Set i to i + 1.
      5. Truncate values to have length count.
      6. Let script be the callback context associated with V.
      7. Push script on to the stack of incumbent scripts. [HTML]
      8. Try running the following step:
        1. Set R to the result of invoking the [[Call]] method of F, providing the callback this value as the this value and values as the argument values.
        And then, whether or not an exception was thrown:
        1. Pop script off the stack of incumbent scripts.
        2. If an exception was thrown, end these steps, and allow it to propagate.
    6. If the callback function’s return type is void, return.
    7. Return the result of converting R to an IDL value of the same type as the callback function’s return type.
    And then, if an exception was thrown:
    1. If the callback function has a return type that is a promise type, then:
      1. Let reject be the initial value of %Promise%.reject.
      2. Return the result of calling reject with %Promise% as the this object and the exception as the single argument value.
    2. Otherwise, end these steps and allow the exception to propagate.

4.10. Exceptions

For every exception that is not declared with the [NoInterfaceObject] extended attribute, a corresponding property MUST exist on the ECMAScript global object. The name of the property is the identifier of the exception, and its value is an object called the exception interface object, which provides access to any constants that have been associated with the exception. The property has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.

4.10.1. Exception interface object

The exception interface object for a given exception MUST be a function object.

If any constants have been declared on the exception, then the exception interface object will have properties corresponding to these constants as described in section 4.10.3 below.

The exception interface object MUST also have a property named “prototype” with attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false } whose value is an object called the exception interface prototype object. This object also provides access to the constants that are declared on the exception.

4.10.1.1. Exception interface object [[Call]] method

The internal [[Call]] method of an exception interface object MUST behave as follows, assuming arg0..n−1 is the list of argument values passed to the function, and E is the exception corresponding to the exception interface object:

  1. Let O be a new object whose [[Prototype]] internal property is set to the exception interface prototype object and whose class string is the identifier of E.
  2. If n > 0 and arg0 is not undefined, then:
    1. Let S be the result of calling ToString(arg0).
    2. Call the [[DefineOwnProperty]] internal method of O passing “message”, Property Descriptor { [[Value]]: S, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }, and false as arguments.
      Note

      This shadows the “message” property from Error.prototype, whose initial value is the empty string.

  3. Return O.

4.10.2. Exception interface prototype object

There MUST exist an exception interface prototype object for every exception defined, regardless of whether the exception was declared with the [NoInterfaceObject] extended attribute. The exception interface prototype object for a particular exception has properties that correspond to the constants and exception fields defined on the exception. These properties are described in more detail in sections 4.10.3 and 4.10.4, below.

The exception interface prototype object for a given exception MUST have an internal [[Prototype]] property whose value is returned from the following steps:

Note

As with interface prototype objects, exception interface prototype objects can be accessible even if declared with [NoInterfaceObject] since it is possible to get the internal [[Prototype]] property of an exception object.

The class string of an exception interface prototype object is the concatenation of the exception’s identifier and the string “Prototype”.

There MUST be a property named “name” on the exception interface prototype object with attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } and whose value is the identifier of the exception.

Note

If an exception is thrown with a specific name, then the rules in section 4.12 below will create a shadowing “name” property on the exception object itself.

If the [NoInterfaceObject] extended attribute was not specified on the exception, then there MUST also be a property named “constructor” on the exception interface prototype object with attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } and whose value is a reference to the exception interface object for the exception.

4.10.3. Constants

For each constant defined on the exception, there MUST be a corresponding property on the exception interface prototype object. The property has the following characteristics:

  • The name of the property is the identifier of the constant.
  • The value of the property is the ECMAScript value that is equivalent to the constant’s IDL value, according to the rules in section 4.2 above.
  • The property has attributes { [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }.

If there exists an exception interface object for the exception, then it MUST also have a property with the same characteristics.

4.10.4. Exception fields

For each exception field, there MUST be a corresponding property on the exception interface prototype object, whose characteristics are as follows:

  • The name of the property is the identifier of the exception field.
  • The property has attributes { [[Get]]: G, [[Enumerable]]: true, [[Configurable]]: true }, where G is the exception field getter, defined below.
  • The exception field getter is a Function object whose behavior when invoked is as follows:
    1. Let O be the result of calling ToObject on the this value.
    2. If O is a platform object, then perform a security check on O with the ECMAScript global environment associated with this Function that implements the exception field getter.
    3. If O is not a platform object representing an exception for the exception on which the exception field was declared, then throw a TypeError.
    4. Let idlValue be the IDL value of O’s exception field.
    5. Let V be the result of converting the idlValue to an ECMAScript value.
    6. Return V.
    Editorial note

    This technically needs to wrap up exceptions in a rejected promise, if the exception field is declared to be a promise type. But exceptions are going away.

    The value of the Function object’s “length” property is the Number value 0.

4.11. Exception objects

Objects representing particular IDL exceptions are platform objects. Such objects can only represent a single exception, and also cannot simultaneously represent an exception and implement an interface.

Every platform object representing an exception in ECMAScript is associated with a global environment, just as the initial objects are. When an exception object is created by calling an exception interface object, either normally or as part of a new expression, then the global environment of the newly created object is associated with MUST be the same as for the interface object itself.

The value of the internal [[Prototype]] property of the exception object MUST be the exception interface prototype object from the global environment the exception object is associated with.

The value of the internal [[NativeBrand]] property of the exception object MUST be “Error”.

The class string of the exception object MUST be the identifier of the exception.

Note

The intention is for exception objects to be just like the other various native Error objects that the ECMAScript specification defines, apart from responding differently to being passed to Object.prototype.toString. If an implementation places non-standard properties on native Error objects, exposing for example stack traces or error line numbers, then these ought to be exposed on exception objects too.

Objects representing predefined exceptions are simply native ECMAScript objects of the corresponding type.

4.12. Throwing exceptions

First, we define the current global environment as the result of running the following algorithm:

  1. Let F be the Function object used as the this value in the top-most call on the ECMAScript call stack where F corresponds to an IDL attribute, operation, indexed property, named property, constructor, named constructor, stringifier, exception constructor or exception field getter.
  2. If F corresponds to an attribute, operation or stringifier, then return the global environment associated with the interface that definition appears on.
  3. Otherwise, if F corresponds to an indexed or named property, then return the global environment associated with the interface that the index or named property getter, setter, creator or deleter was defined on.
  4. Otherwise, if F is a named constructor for an interface, or is an interface object for an interface that is a constructor, then return the global environment associated with that interface.
  5. Otherwise, if F is an exception field getter, then return the global environment associated with the exception on which the exception field was defined.
  6. Otherwise, F is an exception interface object that is a constructor. Return the global environment associated with that exception.

When an IDL exception or predefined exception E is to be thrown, with optional name N, optional message M and, if the exception is not a predefined exception, a required specification on the values to assign to the exception’s fields (both inherited and those specified on the exception itself), the following steps MUST be followed:

  1. Let args be a list of ECMAScript values. If the optional message M was specified, then this list has a single element whose value is the result of converting M to a String value. Otherwise, the list is empty.
  2. Let G be the current global environment.
  3. Let X be an object determined based on the type of E:
    E is an IDL exception
    X is the exception interface object for E from the global environment G.
    E is a predefined exception
    X is the constructor for the corresponding ECMAScript error from the global environment G.
  4. Let O be the result of calling X as a function with args as the argument list.
  5. If the optional name N was specified, then call the [[DefineOwnProperty]] internal method of O passing “name”, Property Descriptor { [[Value]]: N, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }, and false as arguments.
  6. Set the exception fields of O to be as specified in the invocation of this algorithm.
  7. Throw O.
Note

The above algorithm does not restrict platform objects representing exceptions propagating out of a Function to be ones that are associated with the global environment where that Function object originated. For example, consider the IDL:

IDL
exception NumberError { };

interface A {

  /**
   * Calls computeSquareRoot on m, passing x as its argument.
   */
  float doComputation(MathUtils m, float x);
};

interface MathUtils {
  /**
   * If x is negative, throws a NumberError exception.  Otherwise, returns
   * the square root of x.
   */
  float computeSquareRoot(float x);
};

If we pass a MathUtils object from a different global environment to doComputation, then the exception thrown will be from that global environment:

ECMAScript
var a = getA();                          // An A object from this global environment.
var m = otherWindow.getMathUtils();      // A MathUtils object from a different global environment.

a instanceof Object;                     // Evaluates to true.
m instanceof Object;                     // Evaluates to false.
m instanceof otherWindow.Object;         // Evaluates to true.

try {
  a.doComputation(m, -1);
} catch (e) {
  e instanceof NumberError;              // Evaluates to false.
  e instanceof otherWindow.NumberError;  // Evaluates to true.
}

Any requirements in this document to throw an instance of an ECMAScript built-in Error MUST use the built-in from the current global environment.

4.13. Handling exceptions

None of the algorithms or processing requirements in the ECMAScript language binding catch ECMAScript exceptions. Whenever an ECMAScript Function is invoked due to requirements in this section and that Function ends due to an exception being thrown, that exception MUST propagate to the caller, and if not caught there, to its caller, and so on.

Example

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.

IDL
interface Dahut {
  attribute DOMString type;
};

exception SomeException {
};

interface ExceptionThrower {
  // This attribute always throws a SomeException and never returns a value.
  attribute long valueOf;
};

Assuming an ECMAScript implementation supporting this interface, the following code demonstrates how exceptions are handled:

ECMAScript
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.
}

d.type = et;
// An uncaught SomeException exception 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.

5. Common definitions

This section specifies some common definitions that all conforming implementations MUST support.

5.1. DOMTimeStamp

IDL
typedef unsigned long long DOMTimeStamp;

The DOMTimeStamp type is used for representing a number of milliseconds, either as an absolute time (relative to some epoch) or as a relative amount of time. Specifications that use this type will need to define how the number of milliseconds is to be interpreted.

5.2. Function

IDL
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.

5.3. VoidFunction

IDL
callback VoidFunction = void ();

The VoidFunction callback function type is used for representing function values that take no arguments and do not return any value.

6. 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 should 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 Applications Working Group, for possible inclusion in a future version of this document.

Extensions to any other aspect of the IDL language are strongly discouraged.

7. Referencing this specification

This section is informative.

It is expected that other specifications that define Web platform interfaces using a conforming IDL fragment 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 be interpreted as required for conforming 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]

8. Acknowledgements

This section is informative.

The editor would like to thank the following people for contributing to this specification: Glenn Adams, David Andersson, L. David Baron, Art Barstow, Nils Barth, Robin Berjon, David Bruant, Jan-Ivar Bruaroey, Marcos Cáceres, Giovanni Campagna, Domenic Denicola, Michael Dyck, Brendan Eich, João Eiras, Gorm Haug Eriksen, Sigbjorn Finne, David Flanagan, Aryeh Gregor, Dimitry Golubovsky, James Graham, Aryeh Gregor, 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, Magnus Kristiansen, Travis Leithead, Jim Ley, Kevin Lindsey, Jens Lindström, Peter Linss, 呂康豪 (Kang-Hao Lu), Mark Miller, Ms2ger, Andrew Oakley, 岡坂 史紀 (Shiki Okasaka), Jason Orendorff, Olli Pettay, Simon Pieters, Andrei Popescu, François Remy, Tim Renouf, Alex Russell, Takashi Sakamoto, Doug Schepers, Jonas Sicking, Garrett Smith, Geoffrey Sneddon, Jungkee Song, Josh Soref, Maciej Stachowiak, Anton Tayanovskyy, Peter Van der Beken, Jeff Walden, Allen Wirfs-Brock, Collin Xu and Boris Zbarsky.

Special thanks also go to Sam Weinig for maintaining this document while the editor was unavailable to do so.

A. 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 within quotes are terminal symbols that are matched with the exact text between the quotes. Symbols 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]*)/
float = /-?(([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 Unicode characters [UNICODE]. 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 quoted terminal symbols from the grammar, it MUST be tokenized as the quoted terminal symbol. Thus, the input text “long” is tokenized as the quoted terminal symbol "long" rather than an identifier called “long”, and “.” is tokenized as the quoted terminal symbol "." rather than an other.

The IDL syntax is case sensitive, both for the quoted 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 quoted terminal symbol "const", an interface with identifier “A” is distinct from one named “a”, and an extended attribute [constructor] will not be recognized as the [Constructor] 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:

[1]DefinitionsExtendedAttributeList Definition Definitions
 | ε
[2]DefinitionCallbackOrInterface
 | Partial
 | Dictionary
 | Exception
 | Enum
 | Typedef
 | ImplementsStatement
[3]CallbackOrInterface"callback" CallbackRestOrInterface
 | Interface
[4]CallbackRestOrInterfaceCallbackRest
 | Interface
[5]Interface"interface" identifier Inheritance "{" InterfaceMembers "}" ";"
[6]Partial"partial" PartialDefinition
[7]PartialDefinitionPartialInterface
 | PartialDictionary
[8]PartialInterface"interface" identifier "{" InterfaceMembers "}" ";"
[9]InterfaceMembersExtendedAttributeList InterfaceMember InterfaceMembers
 | ε
[10]InterfaceMemberConst
 | AttributeOrOperationOrIterator
[11]Dictionary"dictionary" identifier Inheritance "{" DictionaryMembers "}" ";"
[12]DictionaryMembersExtendedAttributeList DictionaryMember DictionaryMembers
 | ε
[13]DictionaryMemberRequired Type identifier Default ";"
[14]Required"required"
 | ε
[15]PartialDictionary"dictionary" identifier "{" DictionaryMembers "}" ";"
[16]Default"=" DefaultValue
 | ε
[17]DefaultValueConstValue
 | string
 | "[" "]"
[18]Exception"exception" identifier Inheritance "{" ExceptionMembers "}" ";"
[19]ExceptionMembersExtendedAttributeList ExceptionMember ExceptionMembers
 | ε
[20]Inheritance":" identifier
 | ε
[21]Enum"enum" identifier "{" EnumValueList "}" ";"
[22]EnumValueListstring EnumValueListComma
[23]EnumValueListComma"," EnumValueListString
 | ε
[24]EnumValueListStringstring EnumValueListComma
 | ε
[25]CallbackRestidentifier "=" ReturnType "(" ArgumentList ")" ";"
[26]Typedef"typedef" Type identifier ";"
[27]ImplementsStatementidentifier "implements" identifier ";"
[28]Const"const" ConstType identifier "=" ConstValue ";"
[29]ConstValueBooleanLiteral
 | FloatLiteral
 | integer
 | "null"
[30]BooleanLiteral"true"
 | "false"
[31]FloatLiteralfloat
 | "-Infinity"
 | "Infinity"
 | "NaN"
[32]AttributeOrOperationOrIteratorSerializer
 | Stringifier
 | StaticMember
 | Attribute
 | OperationOrIterator
[33]Serializer"serializer" SerializerRest
[34]SerializerRestOperationRest
 | "=" SerializationPattern
 | ε
[35]SerializationPattern"{" SerializationPatternMap "}"
 | "[" SerializationPatternList "]"
 | identifier
[36]SerializationPatternMap"getter"
 | "inherit" Identifiers
 | identifier Identifiers
 | ε
[37]SerializationPatternList"getter"
 | identifier Identifiers
 | ε
[38]Stringifier"stringifier" StringifierRest
[39]StringifierRestAttributeRest
 | ReturnType OperationRest
 | ";"
[40]StaticMember"static" StaticMemberRest
[41]StaticMemberRestAttributeRest
 | ReturnType OperationRest
[42]AttributeInherit AttributeRest
[43]AttributeRestReadOnly "attribute" Type AttributeName ";"
[44]AttributeNameAttributeNameKeyword
 | identifier
[45]AttributeNameKeyword"required"
[46]Inherit"inherit"
 | ε
[47]ReadOnly"readonly"
 | ε
[48]OperationOrIteratorReturnType OperationOrIteratorRest
 | SpecialOperation
[49]SpecialOperationSpecial Specials ReturnType OperationRest
[50]SpecialsSpecial Specials
 | ε
[51]Special"getter"
 | "setter"
 | "creator"
 | "deleter"
 | "legacycaller"
[52]OperationOrIteratorRestIteratorRest
 | OperationRest
[53]IteratorRest"iterator" OptionalIteratorInterfaceOrObject ";"
[54]OptionalIteratorInterfaceOrObjectOptionalIteratorInterface
 | "object"
[55]OptionalIteratorInterface"=" identifier
 | ε
[56]OperationRestOptionalIdentifier "(" ArgumentList ")" ";"
[57]OptionalIdentifieridentifier
 | ε
[58]ArgumentListArgument Arguments
 | ε
[59]Arguments"," Argument Arguments
 | ε
[60]ArgumentExtendedAttributeList OptionalOrRequiredArgument
[61]OptionalOrRequiredArgument"optional" Type ArgumentName Default
 | Type Ellipsis ArgumentName
[62]ArgumentNameArgumentNameKeyword
 | identifier
[63]Ellipsis"..."
 | ε
[64]ExceptionMemberConst
 | ExceptionField
[65]ExceptionFieldType identifier ";"
[66]ExtendedAttributeList"[" ExtendedAttribute ExtendedAttributes "]"
 | ε
[67]ExtendedAttributes"," ExtendedAttribute ExtendedAttributes
 | ε
[68]ExtendedAttribute "(" ExtendedAttributeInner ")" ExtendedAttributeRest
 | "[" ExtendedAttributeInner "]" ExtendedAttributeRest
 | "{" ExtendedAttributeInner "}" ExtendedAttributeRest
 | Other ExtendedAttributeRest
[69]ExtendedAttributeRestExtendedAttribute
 | ε
[70]ExtendedAttributeInner "(" ExtendedAttributeInner ")" ExtendedAttributeInner
 | "[" ExtendedAttributeInner "]" ExtendedAttributeInner
 | "{" ExtendedAttributeInner "}" ExtendedAttributeInner
 | OtherOrComma ExtendedAttributeInner
 | ε
[71]Other integer
 | float
 | identifier
 | string
 | other
 | "-"
 | "-Infinity"
 | "."
 | "..."
 | ":"
 | ";"
 | "<"
 | "="
 | ">"
 | "?"
 | "ByteString"
 | "Date"
 | "DOMString"
 | "Infinity"
 | "NaN"
 | "RegExp"
 | "any"
 | "boolean"
 | "byte"
 | "double"
 | "false"
 | "float"
 | "long"
 | "null"
 | "object"
 | "octet"
 | "or"
 | "optional"
 | "sequence"
 | "short"
 | "true"
 | "unsigned"
 | "void"
 | ArgumentNameKeyword
[72]ArgumentNameKeyword "attribute"
 | "callback"
 | "const"
 | "creator"
 | "deleter"
 | "dictionary"
 | "enum"
 | "exception"
 | "getter"
 | "implements"
 | "inherit"
 | "interface"
 | "legacycaller"
 | "partial"
 | "required"
 | "serializer"
 | "setter"
 | "static"
 | "stringifier"
 | "typedef"
 | "unrestricted"
[73]OtherOrCommaOther
 | ","
[74]TypeSingleType
 | UnionType TypeSuffix
[75]SingleTypeNonAnyType
 | "any" TypeSuffixStartingWithArray
[76]UnionType"(" UnionMemberType "or" UnionMemberType UnionMemberTypes ")"
[77]UnionMemberTypeNonAnyType
 | UnionType TypeSuffix
 | "any" "[" "]" TypeSuffix
[78]UnionMemberTypes"or" UnionMemberType UnionMemberTypes
 | ε
[79]NonAnyTypePrimitiveType TypeSuffix
 | PromiseType Null
 | "ByteString" TypeSuffix
 | "DOMString" TypeSuffix
 | identifier TypeSuffix
 | "sequence" "<" Type ">" Null
 | "object" TypeSuffix
 | "Date" TypeSuffix
 | "RegExp" TypeSuffix
[80]ConstTypePrimitiveType Null
 | identifier Null
[81]PrimitiveTypeUnsignedIntegerType
 | UnrestrictedFloatType
 | "boolean"
 | "byte"
 | "octet"
[82]UnrestrictedFloatType"unrestricted" FloatType
 | FloatType
[83]FloatType"float"
 | "double"
[84]UnsignedIntegerType"unsigned" IntegerType
 | IntegerType
[85]IntegerType"short"
 | "long" OptionalLong
[86]OptionalLong"long"
 | ε
[87]PromiseType"Promise" "<" ReturnType ">"
[88]TypeSuffix"[" "]" TypeSuffix
 | "?" TypeSuffixStartingWithArray
 | ε
[89]TypeSuffixStartingWithArray"[" "]" TypeSuffix
 | ε
[90]Null"?"
 | ε
[91]ReturnTypeType
 | "void"
[92]IdentifierListidentifier Identifiers
[93]Identifiers"," identifier Identifiers
 | ε
[94]ExtendedAttributeNoArgsidentifier
[95]ExtendedAttributeArgListidentifier "(" ArgumentList ")"
[96]ExtendedAttributeIdentidentifier "=" identifier
[97]ExtendedAttributeIdentListidentifier "=" "(" IdentifierList ")"
[98]ExtendedAttributeNamedArgListidentifier "=" identifier "(" ArgumentList ")"
[99]ExtendedAttributeTypePairidentifier "(" Type "," Type ")"
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 section 3.11 for the syntaxes that are used by these extended attributes.

B. References

B.1. Normative references

[ECMA-262]
ECMAScript Language Specification, 6th Edition, A. Wirfs-Brock, Editor. Ecma International, 8 November 2013 (Working Draft).
Available at http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts

Unofficial HTML version available at http://people.mozilla.org/~jorendorff/es6-draft.html.
[IEEE-754]
IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-1985). Institute of Electrical and Electronics Engineers, 1985.
[PERLRE]
Perl regular expressions (Perl 5.8.8). The Perl Foundation, February 2006.
Available at http://www.perl.com/doc/manual/html/pod/perlre.html.
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels, S. Bradner. IETF, March 1997.
Available at http://tools.ietf.org/html/rfc2119.
[RFC2781]
UTF-16, an encoding of ISO 10646, P. Hoffmann and F. Yergeau. IETF, February 2000.
Available at http://tools.ietf.org/html/rfc2781.
[RFC3629]
UTF-8, a transformation format of ISO 10646, F. Yergeau. IETF, November 2003.
Available at http://tools.ietf.org/html/rfc3629.
[TYPEDARRAYS]
Typed Array Specification, V. Vukicevic and K. Russell, eds. The Khronos Group, 08 February 2011.
Available at https://www.khronos.org/registry/typedarray/specs/1.0/.
[UNICODE]
The Unicode Standard, Version 6.0 or later. The Unicode Consortium. Mountain View, California, 2011. ISBN 978-1-936213-01-6.
Available at http://www.unicode.org/versions/Unicode6.0.0/.

B.2. Informative references

[DOM]
DOM Standard. A. van Kesteren, A. Gregor and Ms2ger, Editors. WHATWG, 22 July 2013.
Available at http://dom.spec.whatwg.org/.
[DOM3CORE]
Document Object Model (DOM) Level 3 Core Specification. A. Le Hors, et al., Editors. World Wide Web Consortium, April 2004.
Available at http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/.
[HTML5]
HTML5. I. Hickson, Editor. World Wide Web Consortium, May 2011.
Available at http://www.w3.org/TR/2011/WD-html5-20110525/.
[OMGIDL]
CORBA 3.1 – OMG IDL Syntax and Semantics chapter. Object Management Group, January 2008.
Available at http://www.omg.org/cgi-bin/doc?formal/08-01-04.pdf.
[WEBIDL-JAVA]
Java langage binding for Web IDL. World Wide Consortium, work in progress.
Available at http://dev.w3.org/2006/webapi/WebIDL/java.html.

C. Changes

This section is informative.

The following is a list of substantial changes to the document on each publication. For the list of changes during the development of the First Edition of this specification, see that document's Changes appendix.

Current editor’s draft
  • Rewrote ES to IDL sequence conversion so that any iterable is convertible to a sequence.

  • Added grammar production for Promise<T> types and allowed T to be void.

  • Added a definition to "initialize an object from an iterable", which behaves like the Map constructor.

  • Added a default value [] that can be used for sequence-typed operation argument default values and dictionary member default values.

  • Added promise types.

  • Added the [EnsureUTF16] extended attribute.

  • Added the [NewObject] and [SameObject] extended attributes.

  • Added the [MapClass] extended attribute.

  • Allowed [Constructor] to be specified on dictionaries.

  • Added a RegExp type.

  • Added iterators that can be declared on interfaces.

  • Added an iterator method to objects with indexed properties.

  • Updated to ECMAScript 6th Edition.

  • Added serializers.

  • Added a ByteString type, for representing 8 bit strings without a particular encoding as ECMAScript String values.

  • Added static attributes.

  • Added a way to mark dictionary members as required.

  • Allowed hyphens in identifiers after the first character.

  • Fix [Exposed] text to make it clear that the value on the interface, if any, is used as the value for its members by default.

  • Fixed the grammar for extended attributes that take an identifier list, such as [Exposed].

  • Add a term "unenumerable" to allow named properties to be exposed as properties with [[Enumerable]] set to false.

  • Added the [Exposed] and [PrimaryGlobal] extended attributes and allowed an identifier to be used with [Global].

  • Removed [TreatUndefinedAs].

  • Renamed [TreatNonCallableAsNull] to [TreatNonObjectAsNull] and changed its semantics to allow any object. Changed callback function invocation to be a no-op when the object is not callable, which can now happen in the [TreatNonObjectAsNull] case.

  • Changed the default this value for callbacks from null to undefined.

  • Removed the requirement for named properties objects to be function objects.

  • Disallowed properties from being defined on a named properties object.

  • Fixed infinite loop in named property visibility algorithm.

  • Made stringifiers and serializers not use [[Get]] or [[Call]] for the their attribute or operation delegated behavior.

  • Allowed trailing optional comma in enum lists.

  • Disallowed static interface members from being defined on a callback interface.

  • Added a hook to do a security check when invoking an operation or accessing an attribute.

  • Defined how callbacks influence the incumbent script.

  • Changed how callback functions are invoked to support missing optional arguments.

  • Renamed [NamedPropertiesObject] to [Global], which now also causes properties for interface members to appear on the object itself rather than on the interface prototype object.

  • Split out boolean from the other primitive types. Made boolean, numeric types and DOMString distinguishable.

  • Required a getter to be present on an interface if it has a setter, creator or delete.

  • Extended [Unforgeable] to apply to operations and interfaces.

  • Allowed all operation arguments to be specified as being optional and changed back to the behavior of undefined being treated as a missing optional argument value. Modified the effective overload set and overload resolution algorithms to take this into account, as well as allowing an undefined value passed as the argument value at the distinguishing index to select the overload with an optional argument at that index. Also removed [TreatUndefinedAs=Missing].

  • Changed the ECMAScript to IDL dictionary conversion algorithm to treat a property with the value undefined as missing.

  • Removed the ability to put extended attributes after the typedef keyword, as that feature is unused.

  • Fixed the long long and unsigned long long conversion algorithms to correctly identify the range of contiguous, exactly, uniquely representable integers you can get from a Number.

  • Clarified that Function objects for operations and attribute getters and setters are distinct on each interface they are mixed in to using an implements statement, and that each copy of the Function works only on objects that implement the interface whose interface prototype object the Function object is on.

  • Mention the named properties object in the list of initial objects.

  • Added back a custom [[HasInstance]] on interface objects to allow objects from other windows to be considered instanceof them.

  • Fixed conversion of Number values to any by using the conversion algorithm for unrestricted double.

  • Allowed an identifier to be “prototype” for any construct except constants and static operations.

  • Fixed a bug in the user object definition where the internal [[Call]] method would be treated as the implementation of an operation even if the callback interface had more than one operation.

  • Further tweaked the overload resolution algorithm and union type conversion algorithm for consistency.

  • Lifted the restriction on [Unforgeable] appearing on an IDL attribute if another interface inherits from the one the attribute is declared on, but required that the inheriting interface not have an attribute with the same identifier.

  • Made attribute setters throw if no argument was passed to them, instead of assuming undefined.

  • Prevented dictionaries from referencing themselves.

  • Made sequences, arrays and dictionaries undistingishable again, thereby allowing non-Array ECMAScript objects to be converted to sequence and array types.

  • Added a requirement to state what the values of an exception’s fields are when throwing it.

  • Changed the “length” property on Function objects for IDL operations to return the smallest number of required arguments.

  • Clarified that dictionaries may not be nullable when used as the type of an operation argument or dictionary member.

  • Specify the value of the “length” property on interface objects that do not have constructors.

  • Do not treat array index properties as named properties if an object supports both indexed and named properties.

  • Require that dictionary type arguments followed by optional arguments must also be optional, and that such optional arguments always are assumed to have a default value of an empty dictionary. Also disallow dictionary types from being used inside nullable types and from being considered distinguishable from nullable types.