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
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.
2. 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
The different kinds of definitions that can appear in an IDL fragment are: interfaces, partial interface definitions, namespaces, partial namespace definitions, dictionaries, partial dictionary definitions, typedefs and implements statements. These are all defined in the following sections.
Each definition (matching
[extended_attributes] interface identifier { /* interface_members... */ };
Definitions : ExtendedAttributeList Definition Definitions ε
Definition : CallbackOrInterface Namespace Partial Dictionary Enum Typedef ImplementsStatement
CallbackOrInterface : "callback" CallbackRestOrInterface Interface
The following is an example of an IDL fragment.
interface Paint { }; interface SolidColor : Paint { attribute double red; attribute double green; attribute double 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(double x, double y, double width, double height); void drawText(double x, double y, DOMString text); };
Here, four interfaces are being defined.
The GraphicalWindow
interface has two read only attributes,
one writable attribute, and two operations defined on it. Objects that implement the GraphicalWindow
interface
will expose these attributes and operations in a manner appropriate to the
particular language being used.
In ECMAScript, the attributes on the IDL interfaces will be exposed as accessor
properties and the operations as 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.
2.1. Names
Every interface, partial interface definition, namespace, partial namespace definition, dictionary, partial dictionary definition, enumeration, callback function and typedef (together called named definitions)
and every constant, attribute,
and dictionary member has an identifier, as do some operations.
The identifier is determined by an
-
For named definitions, the
identifier token that appears directly after theinterface ,namespace ,dictionary ,enum orcallback keyword determines the identifier of that definition.interface interface_identifier { /* interface_members... */ }; partial interface interface_identifier { /* interface_members... */ }; namespace namespace_identifier { /* namespace_members... */ }; partial namespace namespace_identifier { /* namespace_members... */ }; dictionary dictionary_identifier { /* dictionary_members... */ }; partial dictionary dictionary_identifier { /* dictionary_members... */ }; enum enumeration_identifier { "enum", "values" /* , ... */ }; callback callback_identifier = return_type (/* arguments... */);
-
For attributes, typedefs 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; dictionary identifier { type dictionary_member_identifier; };
-
For constants, the
identifier token before the equals sign determines the identifier.const type constant_identifier = 42;
-
For operations, the
identifier token that appears after the return type but before the opening parenthesis (that is, one that is matched as part of theOptionalIdentifier grammar symbol in anOperationRest ) determines the identifier of the operation. If there is no suchidentifier token, then the operation does not have an identifier.interface interface_identifier { return_type operation_identifier(/* arguments... */); };
Note: Operations can have no identifier when they are being used to declare a special kind of operation, such as a getter or setter.
For all of these constructs, the identifier is the value of the
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
interface interface_identifier { return_type operation_identifier(argument_type argument_identifier /* , ... */); };
ArgumentNameKeyword : "attribute" "callback" "const" "deleter" "dictionary" "enum" "getter" "implements" "inherit" "interface" "iterable" "legacycaller" "maplike" "namespace" "partial" "required" "setlike" "setter" "static" "stringifier" "typedef" "unrestricted"
If an
The identifier of any of the abovementioned IDL constructs must not be “constructor”, “toString”, or begin with a U+005F LOW LINE ("_") character. These are known as reserved identifiers.
Although the “toJSON” identifier is not a reserved identifier, it must only be used for regular operations that convert objects to JSON types, as described in §2.2.3.1 toJSON.
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, namespace, dictionary, enumeration, callback function and typedef must not be the same as the identifier of any other interface, namespace, dictionary, 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.
Therefore, the following IDL fragment is valid:
interface B : A { void f(SequenceOfLongs x); }; interface A { }; typedef sequence<long> SequenceOfLongs;
The following IDL fragment demonstrates how identifiers are given to definitions and interface members.
// Typedef identifier: "number" typedef double number; // Interface identifier: "System" interface System { // Operation identifier: "createObject" // Operation argument identifier: "interface" object createObject(DOMString _interface); // Operation argument identifier: "interface" sequence<object> getObjects(DOMString interface); // Operation has no identifier; it declares a getter. getter DOMString (DOMString keyName); }; // Interface identifier: "TextField" 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.
2.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 identifier { /* interface_members... */ };
An interface is a specification of a set of interface members (matching
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 significance for property enumeration in the ECMAScript binding.
Interfaces may specify an interface member that has the same name as one from an inherited interface. Objects that implement the derived interface will expose the member on the derived interface. It is language binding specific whether the overridden member can be accessed on the object.
Consider the following two interfaces.
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
interface identifier { [extended_attributes] const type constant_identifier = 42; [extended_attributes] attribute type identifier; [extended_attributes] return_type identifier(/* arguments... */); };
A callback interface is
an interface that uses the
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.
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
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.
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.
Specification authors wanting to define APIs that take ECMAScript objects as “property bag” like function arguments are suggested to use dictionaries rather than callback interfaces.
For example, instead of this:
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:
var a = getA(); // Get an instance of A. a.doTask("something", { option1: "banana", option3: 100 });
instead write the following:
dictionary Options { DOMString? option1; DOMString? option2; long? option3; }; interface A { void doTask(DOMString type, optional Options options); };
The IDL for interfaces can be split into multiple parts by using partial interface definitions
(matching
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:
[Constructor
],
[LegacyArrayClass
],
[LegacyWindowAlias
],
[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
[SecureContext
].
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:
[Constructor
],
[Exposed
],
[Global
],
[LegacyArrayClass
],
[LegacyWindowAlias
],
[NamedConstructor
],
[NoInterfaceObject
],
[OverrideBuiltins
],
[PrimaryGlobal
], and
[SecureContext
].
CallbackRestOrInterface : CallbackRest Interface
Interface : "interface" identifier Inheritance "{" InterfaceMembers "}" ";"
Partial : "partial" PartialDefinition
PartialDefinition : PartialInterface PartialDictionary Namespace
PartialInterface : "interface" identifier "{" InterfaceMembers "}" ";"
InterfaceMembers : ExtendedAttributeList InterfaceMember InterfaceMembers ε
InterfaceMember : Const Operation Stringifier StaticMember Iterable ReadOnlyMember ReadWriteAttribute ReadWriteMaplike ReadWriteSetlike
Inheritance : ":" identifier ε
The following IDL fragment demonstrates the definition of two mutually referential interfaces.
Both Human
and Dog
inherit from Animal
. Objects that implement
either of those two interfaces will thus have a name
attribute.
interface Animal { attribute DOMString name; }; interface Human : Animal { attribute Dog? pet; }; interface Dog : Animal { attribute Human? owner; };
The following IDL fragment defines simplified versions of a few DOM interfaces, one of which is a callback interface.
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:
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:
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.
2.2.1. Constants
A constant is a declaration (matching
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 constant_identifier = 42;
The identifier of a constant must not be the same as the identifier of another interface member defined on the same interface. The identifier also must not be “length”, “name” or “prototype”.
Note: These three names are the names of properties that exist on all
The type of a constant (matching
The
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 boolean
values true
and false
.
The value of an
-
Let S be the sequence of characters matched by the
integer token. -
Let sign be −1 if S begins with U+002D HYPHEN-MINUS ("-"), and 1 otherwise.
-
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.
- U+0030 DIGIT ZERO ("0"), U+0058 LATIN CAPITAL LETTER X ("X")
-
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.
-
Return sign × number.
The type of an
-
Let S be the sequence of characters matched by the
float token. -
Let result be the Mathematical Value that would be obtained if S were parsed as an ECMAScript NumericLiteral.
-
If the
float token is being used as the value for afloat
orunrestricted float
, then the value of thefloat token is the IEEE 754 single-precision floating point number closest to result. -
Otherwise, the
float token is being used as the value for adouble
orunrestricted double
, and the value of thefloat token is the IEEE 754 double-precision floating point number closest to result. [IEEE-754]
The value of a constant value specified as
- Type
unrestricted float
, constant valueInfinity -
The value is the IEEE 754 single-precision positive infinity value.
- Type
unrestricted double
, constant valueInfinity -
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 valueNaN -
The value is the IEEE 754 single-precision NaN value with the bit pattern 0x7fc00000.
- Type
unrestricted double
, constant valueNaN -
The value is the IEEE 754 double-precision NaN value with the bit pattern 0x7ff8000000000000.
The type of a float
or double
.
The value of the
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.
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:
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
],
[SecureContext
].
Const : "const" ConstType identifier "=" ConstValue ";"
ConstValue : BooleanLiteral FloatLiteral integer "null"
BooleanLiteral : "true" "false"
FloatLiteral : float "-Infinity" "Infinity" "NaN"
ConstType : PrimitiveType Null identifier Null
The following IDL fragment demonstrates how constants of the above types can be defined.
interface Util { const boolean DEBUG = false; const octet LF = 10; const unsigned long BIT_MASK = 0x0000fc00; const double AVOGADRO = 6.022e23; };
2.2.2. Attributes
An attribute is an interface member (matching
-
regular attributes, which are those used to declare that objects implementing the interface will have a data field member with the given identifier
interface interface_identifier { attribute type identifier; };
-
static attributes, which are used to declare attributes that are not associated with a particular object implementing the interface
interface interface_identifier { static attribute type identifier; };
If an attribute has no
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
The type of the attribute, after resolving typedefs, must not be a nullable or non-nullable version of any of the following types:
-
a union type that has a nullable or non-nullable sequence type, dictionary, or record as one of its flattened member types
The attribute is read only if the
interface interface_identifier { readonly attribute type identifier; };
Attributes whose type is a promise type must be read only. Additionally, they cannot have
any of the extended attributes [LenientSetter
], [PutForwards
], [Replaceable
], or
[SameObject
].
A regular attribute that is not read only can be declared to inherit its getter from an ancestor interface. This can be used to make a read only attribute
in an ancestor interface be writable on a derived interface. An attribute inherits its getter if
its declaration includes
interface Ancestor { readonly attribute TheType theIdentifier; }; interface Derived : Ancestor { inherit attribute TheType theIdentifier; };
When the
interface interface_identifier { 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:
[Exposed
],
[SameObject
],
[SecureContext
].
The following extended attributes are applicable only to regular attributes:
[LenientSetter
],
[LenientThis
],
[PutForwards
],
[Replaceable
],
[Unforgeable
].
ReadOnlyMember : "readonly" ReadOnlyMemberRest
ReadOnlyMemberRest : AttributeRest ReadWriteMaplike ReadWriteSetlike
ReadWriteAttribute : "inherit" ReadOnly AttributeRest AttributeRest
AttributeRest : "attribute" TypeWithExtendedAttributes AttributeName ";"
AttributeName : AttributeNameKeyword identifier
AttributeNameKeyword : "required"
ReadOnly : "readonly" ε
The following IDL fragment demonstrates how attributes can be declared on an interface:
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; };
2.2.3. Operations
An operation is an interface member (matching
-
regular operations, which are those used to declare that objects implementing the interface will have a method with the given identifier
interface interface_identifier { return_type identifier(/* arguments... */); };
-
special operations, which are used to declare special behavior on objects implementing the interface, such as object indexing and stringification
interface interface_identifier { /* special_keywords... */ return_type identifier(/* arguments... */); /* special_keywords... */ return_type (/* arguments... */); };
-
static operations, which are used to declare operations that are not associated with a particular object implementing the interface
interface interface_identifier { static return_type identifier(/* arguments... */); };
If an operation has an identifier but no
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 void
indicates that the operation returns no value.
If the return type is an identifier followed by
An operation’s arguments (matching
Note: For expressiveness, the identifier of an operation argument can also be specified
as one of the keywords matching the
If the
If the operation argument type, after resolving typedefs, is a nullable type, its inner type must not be a dictionary type.
interface interface_identifier { return_type identifier(type identifier, type identifier /* , ... */); };
The identifier of each argument must not be the same as the identifier of another argument in the same operation declaration.
Each argument can be preceded by a list of extended attributes (matching
interface interface_identifier { return_type identifier([extended_attributes] type identifier, [extended_attributes] type identifier /* , ... */); };
The following IDL fragment demonstrates how regular operations can be declared on an interface:
interface Dimensions { attribute unsigned long width; attribute unsigned long height; }; 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
interface interface_identifier { 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
The following IDL fragment defines an interface that has two variadic operations:
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:
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
interface interface_identifier { return_type identifier(type identifier, optional type identifier); };
Optional arguments can also have a default value specified. If the argument’s identifier is followed by a U+003D EQUALS SIGN ("=") and a value (matching
interface interface_identifier { return_type identifier(type identifier, optional type identifier = "value"); };
It is strongly suggested not to use a default value of boolean
-typed arguments,
as this can be confusing for authors who might otherwise expect the default
conversion of
If the type of an argument is a dictionary type or a union type that has a dictionary as one of its flattened member types, and that dictionary type and its ancestors have no required members, and the 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.
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 (
-
Let S be the sequence of Unicode scalar values matched by the
string token with its leading and trailing U+0022 QUOTATION MARK ('"') characters removed. -
Depending on the type of the argument:
DOMString
- an enumeration type
-
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. ByteString
-
The value of the
string token is the sequence of 8 bit unsigned integer code units corresponding to the UTF-8 encoding of S. USVString
-
The value of the
string token is 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 as the type of the optional
argument it is being used as the default value of. That type
must be a sequence type, a nullable type whose inner type is a sequence type or a union type or nullable union type
that has a sequence type in its flattened member types.
The following IDL fragment defines an interface with a single operation that can be invoked with two different argument list lengths:
interface ColorCreator { object createColor(double v1, double v2, double v3, optional double alpha); };
It is equivalent to an interface that has two overloaded operations:
interface ColorCreator { object createColor(double v1, double v2, double v3); object createColor(double v1, double v2, double v3, double 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:
[Default
],
[Exposed
],
[NewObject
],
[SecureContext
],
[Unforgeable
].
DefaultValue : ConstValue string "[" "]"
Operation : ReturnType OperationRest SpecialOperation
SpecialOperation : Special Specials ReturnType OperationRest
Specials : Special Specials ε
Special : "getter" "setter" "deleter" "legacycaller"
OperationRest : OptionalIdentifier "(" ArgumentList ")" ";"
OptionalIdentifier : identifier ε
ArgumentList : Argument Arguments ε
Arguments : "," Argument Arguments ε
Argument : ExtendedAttributeList "optional" TypeWithExtendedAttributes ArgumentName Default ExtendedAttributeList Type Ellipsis ArgumentName
ArgumentName : ArgumentNameKeyword identifier
Ellipsis : "..." ε
ReturnType : Type "void"
2.2.3.1. toJSON
By declaring a toJSON
regular operation,
an interface specifies how to convert the objects that implement it to JSON types.
The toJSON
regular operation is reserved for this usage.
It must take zero arguments and return a JSON type.
The JSON types are:
-
nullable types whose inner type is a JSON type,
-
annotated types whose inner type is a JSON type,
-
union types whose member types are JSON types,
-
sequence types whose parameterized type is a JSON type,
-
frozen array types whose parameterized type is a JSON type,
-
dictionaries where all of their members are JSON types,
-
records where all of their values are JSON types,
-
interface types that have a
toJSON
operation declared on themselves or one of their inherited or consequential interfaces.
How the toJSON
regular operation is made available on an object in a language binding,
and how exactly the JSON types are converted into a JSON string,
is language binding specific.
Note: In the ECMAScript language binding,
this is done by exposing a toJSON
method
which returns the JSON type converted into an ECMAScript value
that can be turned into a JSON string
by the JSON.stringify
function.
Additionaly, in the ECMAScript language binding,
the toJSON
operation can take a [Default
] extended attribute,
in which case the default toJSON operation is exposed instead.
The following IDL fragment defines an interface Transaction
that has a toJSON
method defined in prose:
interface Transaction { readonly attribute DOMString from; readonly attribute DOMString to; readonly attribute double amount; readonly attribute DOMString description; readonly attribute unsigned long number; TransactionJSON toJSON(); }; dictionary TransactionJSON { Account from; Account to; double amount; DOMString description; };
The toJSON
regular operation of Transaction
interface could be defined as follows:
To invoke the toJSON()
operation of the Transaction
interface, run the following steps:
-
Let json be a new
TransactionJSON
dictionary. -
For each attribute identifier attr in « "from", "to", "amount", "description" »:
-
Let value be result of getting the underlying value of the attribute identified by attr, given this
Transaction
object. -
Set json[attr] to value.
-
-
Return json.
In the ECMAScript language binding, there would exist a toJSON()
method on Transaction
objects:
// Get an instance of Transaction. var txn = getTransaction(); // Evaluates to an object like this: // { // from: "Bob", // to: "Alice", // amount: 50, // description: "books" // } txn.toJSON(); // Evaluates to a string like this: // '{"from":"Bob","to":"Alice","amount":50,"description":"books"}' JSON.stringify(txn);
2.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 five 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 | Defines behavior for when an object is indexed for property retrieval. | |
Setters | Defines behavior for when an object is indexed for property assignment or creation. | |
Deleters | Defines behavior for when an object is indexed for property deletion. | |
Legacy callers | Defines behavior for when an object is called as if it were a function. | |
Stringifiers | Defines how an object is converted into a DOMString .
|
Not all language bindings support all of the five kinds of special object behavior. When special operations are declared using operations with no identifier, then in language bindings that do not support the particular kind of special operations there simply will not be such functionality.
The following IDL fragment defines an interface with a getter and a setter:
interface Dictionary { readonly attribute unsigned long propertyCount; getter double (DOMString propertyName); setter void (DOMString propertyName, double propertyValue); };
In language bindings that do not support property getters and setters, objects implementing Dictionary will not have that special behavior.
Defining a special operation with an identifier is equivalent to separating the special operation out into its own declaration without an identifier. This approach is allowed to simplify prose descriptions of an interface’s operations.
The following two interfaces are equivalent:
interface Dictionary { readonly attribute unsigned long propertyCount; getter double getProperty(DOMString propertyName); setter void setProperty(DOMString propertyName, double propertyValue); };
interface Dictionary { readonly attribute unsigned long propertyCount; double getProperty(DOMString propertyName); void setProperty(DOMString propertyName, double propertyValue); getter double (DOMString propertyName); setter void (DOMString propertyName, double propertyValue); };
A given special keyword must not appear twice on an operation.
Getters and setters come in two varieties: ones that
take a DOMString
as a property name,
known as named property getters and named property setters,
and ones that take an unsigned long
as a property index, known as indexed property getters and indexed property setters.
There is only one variety of deleter: named property deleters.
See §2.2.4.3 Indexed properties and §2.2.4.4 Named properties for details.
On a given interface, there must exist at most one stringifier, at most one named property deleter, and at most one of each variety of getter and setter. Multiple legacy callers can exist on an interface to specify overloaded calling behavior.
If an interface has a setter of a given variety, then it must also have a getter of that variety. If it has a named property deleter, then it must also have a named property getter.
Special operations declared using operations must not be variadic nor have any optional arguments.
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.
2.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
interface interface_identifier { 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 can only be defined on interfaces that also support indexed or named properties.
Note: This artificial restriction allows bundling all interfaces with exotic object behavior into a single platform object category: legacy platform objects. This is possible because all existing interfaces which have a legacy caller also supports indexed or named properties.
Legacy callers must not be defined to return a promise type.
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.
The following IDL fragment defines an interface with a legacy caller.
interface NumberQuadrupler { // This operation simply returns four times the given number x. legacycaller double compute(double x); };
An ECMAScript implementation supporting this interface would
allow a platform object that implements NumberQuadrupler
to be called as a function:
var f = getNumberQuadrupler(); // Obtain an instance of NumberQuadrupler. f.compute(3); // This evaluates to 12. f(3); // This also evaluates to 12.
2.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
interface interface_identifier { 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
interface interface_identifier { stringifier; };
The following two interfaces are equivalent:
interface A { stringifier DOMString (); };
interface A { stringifier; };
The DOMString
or USVString
.
It also must not be placed on
a static attribute.
interface interface_identifier { stringifier attribute DOMString identifier; };
Stringifier : "stringifier" StringifierRest
StringifierRest : ReadOnly AttributeRest ReturnType OperationRest ";"
The following IDL fragment defines an interface that will stringify to the value of its name
attribute:
[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:
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.
[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 thefamilyName
attribute isnull , the stringification of the object is the value of thegivenName
attribute. Otherwise, if the value of thefamilyName
attribute is notnull , the stringification of the object is the concatenation of the value of thegivenName
attribute, a single space character, and the value of thefamilyName
attribute.
An ECMAScript implementation of the IDL would behave as follows:
var s = new Student(); s.id = 12345679; s.familyName = 'Smithee'; s.givenName = 'Alan'; var greeting = 'Hi ' + s; // Now greeting == 'Hi Alan Smithee'.
2.2.4.3. Indexed properties
An interface that defines an indexed property getter is said to support indexed properties. By extension, a platform object is said to support indexed properties if it implements an interface that itself does.
If an interface supports indexed properties, then the interface definition must be accompanied by a description of what indices the object can be indexed with at any given time. These indices are called the supported property indices.
Interfaces that support indexed properties must define an integer-typed attribute named “length”.
Indexed property getters must
be declared to take a single unsigned long
argument.
Indexed property setters must
be declared to take two arguments, where the first is an unsigned long
.
interface interface_identifier { getter type identifier(unsigned long identifier); setter type identifier(unsigned long identifier, type identifier); getter type (unsigned long identifier); setter type (unsigned long identifier, type identifier); };
The following requirements apply to the definitions of indexed property getters and setters:
-
If an indexed property getter was specified using an operation with an identifier, then the value returned when indexing the object with a given supported property index is the value that would be returned by invoking the operation, passing the index as its only argument. If the operation used to declare the indexed property getter did not have an identifier, then the interface definition must be accompanied by a description of how to determine the value of an indexed property for a given index.
-
If an indexed property setter was specified using an operation with an identifier, then the behavior that occurs when indexing the object for property assignment with a given supported property index and value is the same as if the operation is invoked, passing the index as the first argument and the value as the second argument. If the operation used to declare the indexed property setter did not have an identifier, then the interface definition must be accompanied by a description of how to set the value of an existing indexed property and how to set the value of a new indexed property for a given property index and value.
Note that if an indexed property getter or setter 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:
interface A { getter DOMString toWord(unsigned long index); };
Assume that an object implementing A
has supported property indices in the range 0 ≤ index < 2. Also assume that toWord is defined to return
its argument converted into an English word. The behavior when invoking the operation with an out of range index
is different from indexing the object directly:
var a = getA(); a.toWord(0); // Evalautes to "zero". a[0]; // Also evaluates to "zero". a.toWord(5); // Evaluates to "five". a[5]; // Evaluates to undefined, since there is no property "5".
The following IDL fragment defines an interface OrderedMap
which allows
retrieving and setting values by name or by index number:
interface OrderedMap { readonly attribute unsigned long size; getter any getByIndex(unsigned long index); setter void setByIndex(unsigned long index, any value); getter any get(DOMString name); setter void set(DOMString name, any value); };
Since all of the special operations are declared using
operations with identifiers, the only additional prose
that is necessary is that which describes what keys those sets
have. Assuming that the get()
operation is
defined to return 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 §3.9 Legacy platform objects,
an ECMAScript implementation would create
properties on a legacy platform object implementing OrderedMap
that correspond to
entries in both the named and indexed property sets.
These properties can then be used to interact
with the object in the same way as invoking the object’s
methods, as demonstrated below:
// Assume map is a legacy platform object implementing the OrderedMap interface. var map = getOrderedMap(); var x, y; x = map[0]; // If map.length > 0, then this is equivalent to: // // x = map.getByIndex(0) // // since a property named "0" will have been placed on map. // Otherwise, x will be set to undefined, since there will be // no property named "0" on map. map[1] = false; // This will do the equivalent of: // // map.setByIndex(1, false) y = map.apple; // If there exists a named property named "apple", then this // will be equivalent to: // // y = map.get('apple') // // since a property named "apple" will have been placed on // map. Otherwise, y will be set to undefined, since there // will be no property named "apple" on map. map.berry = 123; // This will do the equivalent of: // // map.set('berry', 123) delete map.cake; // If a named property named "cake" exists, then the "cake" // property will be deleted, and then the equivalent to the // following will be performed: // // map.remove("cake")
2.2.4.4. Named properties
An interface that defines a named property getter is said to support named properties. By extension, a platform object is said to support named properties if it implements an interface that itself does.
If an interface supports named properties, then the interface definition must be accompanied by a description of the ordered set of names that can be used to index the object at any given time. These names are called the supported property names.
Named property getters and deleters must
be declared to take a single DOMString
argument.
Named property setters must
be declared to take two arguments, where the first is a DOMString
.
interface interface_identifier { getter type identifier(DOMString identifier); setter type identifier(DOMString identifier, type identifier); deleter type identifier(DOMString identifier); getter type (DOMString identifier); setter type (DOMString identifier, type identifier); deleter type (DOMString identifier); };
The following requirements apply to the definitions of named property getters, setters and deleters:
-
If a named property getter was specified using an operation with an identifier, then the value returned when indexing the object with a given supported property name is the value that would be returned by invoking the operation, passing the name as its only argument. If the operation used to declare the named property getter did not have an identifier, then the interface definition must be accompanied by a description of how to determine the value of a named property for a given property name.
-
If a named property setter was specified using an operation with an identifier, then the behavior that occurs when indexing the object for property assignment with a given supported property name and value is the same as if the operation is invoked, passing the name as the first argument and the value as the second argument. If the operation used to declare the named property setter did not have an identifier, then the interface definition must be accompanied by a description of how to set the value of an existing named property and how to set the value of a new named property for a given property name and value.
-
If a named property deleter was specified using an operation with an identifier, then the behavior that occurs when indexing the object for property deletion with a given supported property name is the same as if the operation is invoked, passing the name as the only argument. If the operation used to declare the named property deleter did not have an identifier, then the interface definition must be accompanied by a description of how to delete an existing named property for a given property name.
Note: As with indexed properties, if an named property getter, 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.
2.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
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.
StaticMember : "static" StaticMemberRest
StaticMemberRest : ReadOnly AttributeRest ReturnType OperationRest
The following IDL fragment defines an interface Circle
that has a static
operation declared on it:
interface Point { /* ... */ }; interface Circle { attribute double cx; attribute double cy; attribute double radius; static readonly attribute long triangulationCount; static Point triangulate(Circle c1, Circle c2, Circle c3); };
In the ECMAScript language binding, the triangulate
and the accessor property for triangulationCount
will exist on the interface object for Circle
:
var circles = getCircles(); // an Array of Circle objects typeof Circle.triangulate; // Evaluates to "function" typeof Circle.triangulationCount; // Evaluates to "number" Circle.prototype.triangulate; // Evaluates to undefined Circle.prototype.triangulationCount; // Also evaluates to undefined circles[0].triangulate; // As does this circles[0].triangulationCount; // And this // Call the static operation var triangulationPoint = Circle.triangulate(circles[0], circles[1], circles[2]); // Find out how many triangulations we have done window.alert(Circle.triangulationCount);
2.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.
For example, the overloads for both f and g are disallowed:
interface A { void f(); }; partial interface A { void f(double 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
-
-
the interface on which the operations are to be found
-
the identifier of the operations
-
the number of arguments to be passed
-
- For legacy callers
-
-
the interface on which the legacy callers are to be found
-
the number of arguments to be passed
-
- For constructors
-
-
the interface on which the [
Constructor
] extended attributes are to be found -
the number of arguments to be passed
-
- For named constructors
-
-
the interface on which the [
NamedConstructor
] extended attributes are to be found -
the identifier of the named constructors
-
the number of arguments to be passed
-
- For callback functions
-
-
the number of arguments to be passed
An effective overload set is used, among other things, to determine whether there are ambiguities in the overloaded operations, constructors and callers specified on an interface.
The elements of an effective overload set are tuples of the form <callable, type 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 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.
-
Initialize S to ∅.
-
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.
-
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. -
Let m be the maximum of maxarg and N.
-
For each operation, extended attribute or callback function X in F:
-
Let n be the number of arguments X is declared to take.
-
Let t0..n−1 be a list of types, where ti is the type of X’s argument at index i.
-
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.
-
Add to S the tuple <X, t0..n−1, o0..n−1>.
-
If X is declared to be variadic, then:
-
For every integer i, such that n ≤ i ≤ m−1:
-
Let u0..i be a list of types, where uj = tj (for j < n) and uj = tn−1 (for j ≥ n).
-
Let p0..i be a list of optionality values, where pj = oj (for j < n) and pj = “variadic” (for j ≥ n).
-
Add to S the tuple <X, u0..i, p0..i>.
-
-
-
Initialize i to n−1.
-
While i ≥ 0:
-
If argument i of X is not optional (i.e., it is not marked as
optional
and is not a final, variadic argument), then break this loop. -
Otherwise, add to S the tuple <X, t0..i−1, o0..i−1>.
Note: if i is 0, this means to add to S the tuple <X, « », « »> (where "« »" represents an empty list).
-
Set i to i−1.
-
-
-
The effective overload set is S.
For the following interface:
interface A { /* f1 */ void f(DOMString a); /* f2 */ void f(Node a, DOMString b, double... c); /* f3 */ void f(); /* f4 */ void f(Event a, DOMString b, optional DOMString c, double... d); };
assuming Node
and Event
are two other interfaces of which no object can implement both,
the effective overload set for regular operations with
identifier f
and argument count 4 is:
{ <f1, (DOMString), (required)>, <f2, (Node, DOMString), (required, required)>, <f2, (Node, DOMString, double), (required, required, variadic)>, <f2, (Node, DOMString, double, double), (required, required, variadic, variadic)>, <f3, (), ()>, <f4, (Event, DOMString), (required, required)>, <f4, (Event, DOMString, DOMString), (required, required, optional)>, <f4, (Event, DOMString, DOMString, double), (required, required, optional, variadic)> }
Two types are distinguishable if the following algorithm returns true.
-
If one type includes a nullable type and the other type either includes a nullable type, is a union type with flattened member types including a dictionary type, or is a dictionary type, return false.
-
If both types are either a union type or nullable union type, return true if each member type of the one is distinguishable with each member type of the other, or false otherwise.
-
If one type is a union type or nullable union type, return true if each member type of the union type is distinguishable with the non-union type, or false otherwise.
-
Consider the two "innermost" types derived by taking each type’s inner type if it is an annotated type, and then taking its inner type inner type if the result is a nullable type. If these two innermost types appear or are in categories appearing in the following table and there is a “●” mark in the corresponding entry or there is a letter in the corresponding entry and the designated additional requirement below the table is satisfied, then return true. Otherwise return false.
Categories:
- interface-like
- dictionary-like
- sequence-like
-
-
sequence<T>
-
FrozenArray
<T>
-
booleannumeric typesstring typesobjectsymbolinterface-likecallback functiondictionary-likesequence-likeboolean ● ● ● ● ● ● ● ● numeric types ● ● ● ● ● ● ● string types ● ● ● ● ● ● object ● symbol ● ● ● ● interface-like (a) ● ● ● callback function ● dictionary-like ● sequence-like -
The two identified interface-like types are not the same, and no single platform object implements both interface-like types.
double
andDOMString
are distinguishable because there is a ● at the intersection of numeric types with string types.double
andlong
are not distinguishable because they are both numeric types, and there is no ● or letter at the intersection of numeric types with numeric types.Given:callback interface CBIface { attribute DOMString attr1; }; interface Iface { attribute DOMString attr2; }; dictionary Dict { DOMString field1; };
CBIface
is distinguishable fromIface
because there’s a ● at the intersection of dictionary-like and interface-like, but it is not distinguishable fromDict
because there’s no ● at the intersection of dictionary-like and itself.Promise types do not appear in the above table, and as a consequence are not distinguishable with any other type.
If there is more than one 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.
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:
interface B { void f(DOMString x); void f(USVString x); };
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 optionality values at index j in all of the entries’ optionality lists must be the same.
The following is invalid:
interface B { /* f1 */ void f(DOMString w); /* f2 */ void f(long w, double x, Node y, Node z); /* f3 */ void f(double w, double x, DOMString y, Node z); };
For argument count 4, the effective overload set is:
{ <f1, (DOMString), (required)>, <f2, (long, double, Node, Node), (required, required, required, required)>, <f3, (double, double, DOMString, Node), (required, required, required, required)> }
Looking at 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.
2.2.7. Iterable declarations
An interface can be declared to be iterable by using an iterable declaration (matching
interface interface_identifier { iterable<value_type>; iterable<key_type, value_type>; };
Objects implementing an interface that is declared to be iterable support being iterated over to obtain a sequence of values.
Note: In the ECMAScript language binding, an interface that is iterable will have “entries”, “forEach”, “keys”, “values” and @@iterator properties on its interface prototype object.
If a single type parameter is given, then the interface has a value iterator and provides values of the specified type. If two type parameters are given, then the interface has a pair iterator and provides value pairs, where the first value is a key and the second is the value associated with the key.
A value iterator must only be declared on an interface that supports indexed properties. The value-type of the value iterator must be the same as the type returned by the indexed property getter. A value iterator is implicitly defined to iterate over the object’s indexed properties.
A pair iterator must not be declared on an interface that supports indexed properties. Prose accompanying an interface with a pair iterator must define what the list of value pairs to iterate over is.
The ECMAScript forEach method that is generated for a value iterator invokes its callback like Array.prototype.forEach does, and the forEach method for a pair iterator invokes its callback like Map.prototype.forEach does.
Since value iterators are currently allowed only on interfaces that support indexed properties, it makes sense to use an Array-like forEach method. There may be a need for value iterators (a) on interfaces that do not support indexed properties, or (b) with a forEach method that instead invokes its callback like Set.protoype.forEach (where the key is the same as the value). If you’re creating an API that needs such a forEach method, please send a request to public-script-coord@w3.org.
Note: This is how array iterator objects work. For interfaces that support indexed properties, the iterator objects returned by “entries”, “keys”, “values” and @@iterator are actual array iterator objects.
Interfaces with iterable declarations must not have any interface members named “entries”, “forEach”, “keys” or “values”, or have any inherited or consequential interfaces that have interface members with these names.
Consider the following interface SessionManager
, which allows access to
a number of Session
objects:
interface SessionManager { Session getSessionForUser(DOMString username); readonly attribute unsigned long sessionCount; iterable<Session>; }; interface Session { readonly attribute DOMString username; // ... };
The behavior of the iterator could be defined like so:
The values to iterate over are the open
Session
objects on theSessionManager
sorted by username.Fix reference to removed definition for "values to iterate over".
In the ECMAScript language binding, the interface prototype object for the SessionManager
interface has a values
method that is a function, which, when invoked,
returns an iterator object that itself has a next
method that returns the
next value to be iterated over. It has values
and entries
methods that iterate over the indexes of the list of session objects
and [index, session object] pairs, respectively. It also has
a @@iterator method that allows a SessionManager
to be used in a for..of
loop:
// Get an instance of SessionManager. // Assume that it has sessions for two users, "anna" and "brian". var sm = getSessionManager(); typeof SessionManager.prototype.values; // Evaluates to "function" var it = sm.values(); // values() returns an iterator object String(it); // Evaluates to "[object SessionManager Iterator]" typeof it.next; // Evaluates to "function" // This loop will alert "anna" and then "brian". for (;;) { let result = it.next(); if (result.done) { break; } let session = result.value; window.alert(session.username); } // This loop will also alert "anna" and then "brian". for (let session of sm) { window.alert(session.username); }
An interface must not have more than one iterable declaration. The inherited and consequential interfaces of an interface with an iterable declaration must not also have an iterable declaration. An interface with an iterable declaration and its inherited and consequential interfaces must not have a maplike declaration or setlike declaration.
The following extended attributes are applicable to iterable declarations:
[Exposed
],
[SecureContext
].
Iterable : "iterable" "<" TypeWithExtendedAttributes OptionalType ">" ";"
OptionalType : "," TypeWithExtendedAttributes ε
2.2.8. Maplike declarations
An interface can be declared to be maplike by using a maplike declaration (matching
interface interface_identifier { readonly maplike<key_type, value_type>; maplike<key_type, value_type>; };
Objects implementing an interface that is declared to be maplike represent an ordered list of key–value pairs known as its map entries. The types used for the keys and values are given in the angle brackets of the maplike declaration. Keys are required to be unique.
The map entries of an object implementing a maplike interface is empty at the of the object’s creation. Prose accompanying the interface can describe how the map entries of an object change.
Maplike interfaces support an API for querying the map entries
appropriate for the language binding. If the
Note: In the ECMAScript language binding, the API for interacting
with the map entries is similar to that available on ECMAScript
Maplike interfaces must not have any interface members named “entries”, “forEach”, “get”, “has”, “keys”, “size”, or “values”, or have any inherited or consequential interfaces that have interface members with these names. Read–write maplike interfaces must not have any attributes or constants named “clear”, “delete”, or “set”, or have any inherited or consequential interfaces that have attributes or constants with these names.
Note: Operations named “clear”, “delete”, or “set” are allowed on read–write maplike interfaces and will prevent the default implementation of these methods being added to the interface prototype object in the ECMAScript language binding. This allows the default behavior of these operations to be overridden.
An interface must not have more than one maplike declaration. The inherited and consequential interfaces of a maplike interface must not also have a maplike declaration. A maplike interface and its inherited and consequential interfaces must not have an iterable declaration or setlike declaration.
ReadWriteMaplike : MaplikeRest
MaplikeRest : "maplike" "<" TypeWithExtendedAttributes "," TypeWithExtendedAttributes ">" ";"
No extended attributes defined in this specification are applicable to maplike declarations.
2.2.9. Setlike declarations
An interface can be declared to be setlike by using a setlike declaration (matching
interface interface_identifier { readonly setlike<type>; setlike<type>; };
Objects implementing an interface that is declared to be setlike represent an ordered list of values known as its set entries. The type of the values is given in the angle brackets of the setlike declaration. Values are required to be unique.
The set entries of an object implementing a setlike interface is empty at the of the object’s creation. Prose accompanying the interface can describe how the set entries of an object change.
Setlike interfaces support an API for querying the set entries
appropriate for the language binding. If the
Note: In the ECMAScript language binding, the API for interacting
with the set entries is similar to that available on ECMAScript
Setlike interfaces must not have any interface members named “entries”, “forEach”, “has”, “keys”, “size”, or “values”, or have any inherited or consequential interfaces that have interface members with these names.. Read–write setlike interfaces must not have any attributes or constants named “add”, “clear”, or “delete”, or have any inherited or consequential interfaces that have attributes or constants with these names.
Note: Operations named “add”, “clear”, or “delete” are allowed on read–write setlike interfaces and will prevent the default implementation of these methods being added to the interface prototype object in the ECMAScript language binding. This allows the default behavior of these operations to be overridden.
An interface must not have more than one setlike declaration. The inherited and consequential interfaces of a setlike interface must not also have a setlike declaration. A setlike interface and its inherited and consequential interfaces must not have an iterable declaration or maplike declaration.
ReadWriteSetlike : SetlikeRest
SetlikeRest : "setlike" "<" TypeWithExtendedAttributes ">" ";"
No extended attributes defined in this specification are applicable to setlike declarations.
2.3. Namespaces
A namespace is a definition (matching
namespace identifier { /* namespace_members... */ };
A namespace is a specification of a set of namespace members (matching
As with interfaces, the IDL for namespaces can be split into multiple parts by using partial namespace definitions
(matching
namespace SomeNamespace { /* namespace_members... */ }; partial namespace SomeNamespace { /* namespace_members... */ };
Note: As with partial interface definitions, partial namespace definitions are intended for use as a specification editorial aide, allowing the definition of a namespace to be separated over more than one section of the document, and sometimes multiple documents.
The order that members appear in has significance for property enumeration in the ECMAScript binding.
Note that unlike interfaces or dictionaries, namespaces do not create types.
Of the extended attributes defined in this specification, only the [Exposed
] and [SecureContext
] extended attributes are applicable to
namespaces.
Namespace : "namespace" identifier "{" NamespaceMembers "}" ";"
NamespaceMembers : ExtendedAttributeList NamespaceMember NamespaceMembers ε
NamespaceMember : ReturnType OperationRest "readonly" AttributeRest
The following IDL fragment defines an namespace.
namespace VectorUtils { readonly attribute Vector unit; double dotProduct(Vector x, Vector y); Vector crossProduct(Vector x, Vector y); };
An ECMAScript implementation would then expose a global property named VectorUtils
which was a simple object (with prototype %ObjectPrototype%) with enumerable data properties for each declared operation, and
enumerable get-only accessors for each declared attribute:
Object.getPrototypeOf(VectorUtils); // Evaluates to Object.prototype. Object.keys(VectorUtils); // Evaluates to ["dotProduct", "crossProduct"]. Object.getOwnPropertyDescriptor(VectorUtils, "dotProduct"); // Evaluates to { value: <a function>, enumerable: true, configurable: true, writable: true }. Object.getOwnPropertyDescriptor(VectorUtils, "unit"); // Evaluates to { get: <a function>, enumerable: true, configurable: true }.
2.4. Dictionaries
A dictionary is a definition (matching
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.
In the ECMAScript binding, a value of
An ordered map with string keys can be implicitly treated as a dictionary value of a specific dictionary D if all of its entries correspond to dictionary members, in the correct order and with the correct types, and with appropriate entries for any required dictionary members.
As with operation argument default values,
it is strongly suggested not to use boolean
-typed dictionary members,
as this can be confusing for authors who might otherwise expect the default
conversion of
Each dictionary member (matching
If the type of the dictionary member, after resolving typedefs, is a nullable type, its inner type must not be a dictionary type.
dictionary identifier { type identifier; };
If the identifier is followed by a U+003D EQUALS SIGN ("=") and a value (matching
dictionary identifier { type identifier = "value"; };
When a boolean literal token (
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
dictionary identifier { required type identifier; };
The type of a dictionary member must not include the dictionary it appears on. A type includes a dictionary D if at least one of the following is true:
-
the type is D
-
the type is a dictionary that inherits from D
-
the type is a nullable type whose inner type includes D
-
the type is a sequence type or frozen array whose element type includes D
-
the type is a union type, one of whose member types includes D
-
the type is a dictionary, one of whose members or inherited members has a type that includes D
-
the type is
record<K, V>
where V includes D
As with interfaces, the IDL for dictionaries can be split into multiple parts
by using partial dictionary definitions
(matching
dictionary SomeDictionary { /* dictionary_members... */ }; partial dictionary SomeDictionary { /* dictionary_members... */ };
Note: As with partial interface definitions, partial dictionary definitions are intended for use as a specification editorial aide, allowing the definition of an interface to be separated over more than one section of the document, and sometimes multiple documents.
The order of the dictionary members on a given dictionary is such that inherited dictionary members are ordered before non-inherited members, and the dictionary members on the one dictionary definition (including any partial dictionary definitions) are ordered lexicographically by the Unicode codepoints that comprise their identifiers.
For example, with the following definitions:
dictionary B : A { long b; long a; }; dictionary A { long c; long g; }; dictionary C : B { long e; long f; }; partial dictionary A { long h; long d; };
the order of the dictionary members of a dictionary value of type C
is
c, d, g, h, a, b, e, f.
Dictionaries 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:
interface Something { void f(A a); };
and this ECMAScript code:
var something = getSomething(); // Get an instance of Something. var x = 0; var dict = { }; Object.defineProperty(dict, "d", { get: function() { return ++x; } }); Object.defineProperty(dict, "c", { get: function() { return ++x; } }); something.f(dict);
The order that the dictionary members are fetched in determines
what values they will be taken to have. Since the order for A
is defined to be c then d,
the value for c will be 1 and the value for d will be 2.
The identifier of a dictionary member must not be the same as that of another dictionary member defined on the dictionary or on that dictionary’s inherited dictionaries.
Dictionaries must not be used as the type of an attribute or constant.
The following extended attributes are applicable to dictionaries:
[Constructor
],
[Exposed
],
[SecureContext
],
Dictionary : "dictionary" identifier Inheritance "{" DictionaryMembers "}" ";"
DictionaryMembers : DictionaryMember DictionaryMembers ε
DictionaryMember : ExtendedAttributeList "required" TypeWithExtendedAttributes identifier Default ";" ExtendedAttributeList Type identifier Default ";"
PartialDictionary : "dictionary" identifier "{" DictionaryMembers "}" ";"
Default : "=" DefaultValue ε
One use of dictionary types is to allow a number of optional arguments to an operation without being constrained as to the order they are specified at the call site. For example, consider the following IDL fragment:
[Constructor] interface Point { attribute double x; attribute double y; }; dictionary PaintOptions { DOMString? fillPattern = "black"; DOMString? strokePattern = null; Point position; }; interface GraphicsContext { void drawRectangle(double width, double height, optional PaintOptions options); };
In an ECMAScript implementation of the IDL, an PaintOptions
dictionary:
// 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.
2.5. Exceptions
An exception is a type of object that
represents an error and which can be thrown or treated as a first
class value by implementations. Web IDL does not allow exceptions
to be defined, but instead has a number of pre-defined exceptions
that specifications can reference and throw in their definition of
operations, attributes, and so on. Exceptions have an error name,
a DOMString
,
which is the type of error the exception represents, and a message, which is an optional,
user agent-defined value that provides human readable details of the error.
There are two kinds of exceptions available to be thrown from specifications. The first is a simple exception, which is identified by one of the following types:
These correspond to all of the ECMAScript error objects (apart from
The second kind of exception is a DOMException
,
which is an exception that encapsulates a name and an optional integer code,
for compatibility with historically defined exceptions in the DOM.
For simple exceptions, the error name is the type of the exception.
For a DOMException
, the error name must be one of the names
listed in the error names table below.
The table also indicates the DOMException
's integer code for that error name,
if it has one.
There are two types that can be used to refer to exception objects: DOMException
and Error
,
where the latter encompasses simple exceptions and DOMException
.
This allows for example an operation to be declared to have a DOMException
return type or an attribute to be of type Error
.
Simple exceptions can be created by providing their error name.
A DOMException
can be created by providing its error name followed by DOMException
.
Exceptions can also be thrown, by providing the
same details required to create one.
The resulting behavior from creating and throwing an exception is language binding-specific.
Note: See §3.13.3 Creating and throwing exceptions for details on what creating and throwing an exception entails in the ECMAScript language binding.
Here is are some examples of wording to use to create and throw exceptions.
To throw a new simple exception named TypeError
:
Throw a TypeError
.
To throw a new DOMException
with error name "NotAllowedError
":
Throw an "NotAllowedError
"DOMException
.
To create a new DOMException
with error name "SyntaxError
":
Let object be a newly created "SyntaxError
"DOMException
.
2.5.1. Error names
The error names table below lists all the allowed error names
for DOMException
, a description, and legacy code values.
The DOMException
names marked as deprecated are kept for legacy purposes but their usage is discouraged.
Note: If an error name is not listed here, please file a bug as indicated at the top of this specification and it will be addressed shortly. Thanks!
Name | Description | Legacy code name and value |
---|---|---|
" "
| Deprecated. Use RangeError instead.
| (1)
|
" "
| Deprecated. Use RangeError instead.
| (2)
|
" "
| The operation would yield an incorrect node tree. | (3)
|
" "
| The object is in the wrong document. | (4)
|
" "
| The string contains invalid characters. | (5)
|
" "
| Deprecated. | (6)
|
" "
| The object can not be modified. | (7)
|
" "
| The object can not be found here. | (8)
|
" "
| The operation is not supported. | (9)
|
" "
| The attribute is in use. | (10)
|
" "
| The object is in an invalid state. | (11)
|
" "
| The string did not match the expected pattern. | (12)
|
" "
| The object can not be modified in this way. | (13)
|
" "
| The operation is not allowed by Namespaces in XML. [XML-NAMES] | (14)
|
" "
| Deprecated. Use TypeError for invalid arguments,
"NotSupportedError " DOMException for unsupported operations, and
"NotAllowedError " DOMException for denied requests instead.
| (15)
|
" "
| Deprecated. | (16)
|
" "
| Deprecated. Use TypeError instead.
| (17)
|
" "
| The operation is insecure. | (18)
|
" "
| A network error occurred. | (19)
|
" "
| The operation was aborted. | (20)
|
" "
| The given URL does not match another URL. | (21)
|
" "
| The quota has been exceeded. | (22)
|
" "
| The operation timed out. | (23)
|
" "
| The supplied node is incorrect or has an incorrect ancestor for this operation. | (24)
|
" "
| The object can not be cloned. | (25)
|
" "
| The encoding operation (either encoded or decoding) failed. | — |
" "
| The I/O read operation failed. | — |
" "
| The operation failed for an unknown transient reason (e.g. out of memory). | — |
" "
| A mutation operation in a transaction failed because a constraint was not satisfied. | — |
" "
| Provided data is inadequate. | — |
" "
| A request was placed against a transaction which is currently not active, or which is finished. | — |
" "
| The mutating operation was attempted in a "readonly" transaction. | — |
" "
| An attempt was made to open a database using a lower version than the existing version. | — |
" "
| The operation failed for an operation-specific reason. | — |
" "
| The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission. | — |
2.6. Enumerations
An enumeration is a definition (matching DOMString
values that can be assigned to an attribute or passed to an operation.
enum identifier { "enum", "values" /* , ... */ };
The enumeration values are specified
as a comma-separated list of
It is strongly suggested that enumeration values be all lowercase,
and that multiple words be separated using dashes or not be
separated at all, unless there is a specific reason to use another
value naming scheme. For example, an enumeration value that
indicates an object should be created could be named "createobject"
or "create-object"
.
Consider related uses of enumeration values when deciding whether
to dash-separate or not separate enumeration value words so that
similar APIs are consistent.
The behavior when a string value that is not 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.
Enum : "enum" identifier "{" EnumValueList "}" ";"
EnumValueList : string EnumValueListComma
EnumValueListComma : "," EnumValueListString ε
EnumValueListString : string EnumValueListComma ε
The following IDL fragment defines an enumeration that is used as the type of an attribute and an operation argument:
enum MealType { "rice", "noodles", "other" }; interface Meal { attribute MealType type; attribute double size; // in grams void initialize(MealType type, double 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.
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.
2.7. Callback functions
The “Custom DOM Elements” spec wants to use callback function types for platform object provided functions. Should we rename “callback functions” to just “functions” to make it clear that they can be used for both purposes?
A callback function is a definition (matching
callback 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
Callback functions must not be used as the type of a constant.
The following extended attribute is applicable to callback functions:
[TreatNonObjectAsNull
].
CallbackRest : identifier "=" ReturnType "(" ArgumentList ")" ";"
The following IDL fragment defines a callback function used for an API that invokes a user-defined function when an operation is complete.
callback AsyncOperationCallback = void (DOMString status); interface AsyncOperations { void performOperation(AsyncOperationCallback whenFinished); };
In the ECMAScript language binding, a
var ops = getAsyncOperations(); // Get an instance of AsyncOperations. ops.performOperation(function(status) { window.alert("Operation finished, status is " + status + "."); });
2.8. Typedefs
A typedef is a definition (matching
typedef type identifier;
The type being given a new name is specified after the
The
No extended attributes defined in this specification are applicable to typedefs.
Typedef : "typedef" TypeWithExtendedAttributes identifier ";"
The following IDL fragment demonstrates the use of typedefs to allow the use of a short identifier instead of a long sequence type.
interface Point { attribute double x; attribute double y; }; typedef sequence<Point> Points; interface Widget { boolean pointWithinBounds(Point p); boolean allPointsWithinBounds(Points ps); };
2.9. Implements statements
An implements statement is a definition
(matching
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.
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:
interface Window { /* ... */ }; interface SomeFunctionality { /* ... */ }; Window implements SomeFunctionality;
and author 2 later writes:
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:
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.
For example, that precludes the following:
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.
ImplementsStatement : identifier "implements" identifier ";"
The following IDL fragment defines two interfaces, stating that one interface is always implemented on objects implementing the other.
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
:
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
.
2.10. 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 two kinds of object that are considered to be platform objects:
-
objects representing an IDL
DOMException
.
Legacy platform objects are platform objects that implement an interface which
does not have a [Global
] or [PrimaryGlobal
] extended attribute, supports indexed or named properties,
and may have one or multiple legacy callers.
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.
2.11. 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
, unrestricted float
, double
and unrestricted double
.
The primitive types are boolean
and the numeric types.
The string types are DOMString
, all enumeration types, ByteString
and USVString
.
The exception types are Error
and DOMException
.
The typed array types are Int8Array
, Int16Array
, Int32Array
, Uint8Array
, Uint16Array
, Uint32Array
, Uint8ClampedArray
, Float32Array
and Float64Array
.
The buffer source types are ArrayBuffer
, DataView
,
and the typed array types.
The object
type,
all interface types and the exception 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.
Type : SingleType UnionType Null
TypeWithExtendedAttributes : ExtendedAttributeList SingleType ExtendedAttributeList UnionType Null
SingleType : NonAnyType "any"
UnionType : "(" UnionMemberType "or" UnionMemberType UnionMemberTypes ")"
UnionMemberType : ExtendedAttributeList NonAnyType UnionType Null
UnionMemberTypes : "or" UnionMemberType UnionMemberTypes ε
NonAnyType : PromiseType ε PrimitiveType Null StringType Null identifier Null "sequence" "<" TypeWithExtendedAttributes ">" Null "object" Null "symbol" Null "Error" Null BufferRelatedType Null "FrozenArray" "<" TypeWithExtendedAttributes ">" Null RecordType Null
PrimitiveType : UnsignedIntegerType UnrestrictedFloatType "boolean" "byte" "octet"
UnrestrictedFloatType : "unrestricted" FloatType FloatType
FloatType : "float" "double"
UnsignedIntegerType : "unsigned" IntegerType IntegerType
IntegerType : "short" "long" OptionalLong
OptionalLong : "long" ε
StringType : "ByteString" "DOMString" "USVString"
PromiseType : "Promise" "<" ReturnType ">"
RecordType : "record" "<" StringType "," TypeWithExtendedAttributes ">"
Null : "?" ε
2.11.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.)
2.11.2. boolean
The boolean
type has two values: true
and false
.
boolean
constant values in IDL are
represented with the
The type name of the boolean
type is “Boolean”.
2.11.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
The type name of the byte
type is “Byte”.
2.11.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
The type name of the octet
type is “Octet”.
2.11.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
The type name of the short
type is “Short”.
2.11.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
The type name of the unsigned short
type is “UnsignedShort”.
2.11.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
The type name of the long
type is “Long”.
2.11.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
The type name of the unsigned long
type is “UnsignedLong”.
2.11.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
The type name of the long long
type is “LongLong”.
2.11.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
The type name of the unsigned long long
type is “UnsignedLongLong”.
2.11.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
The type name of the float
type is “Float”.
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
2.11.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, non-finite, and special "not a number" values (NaNs). [IEEE-754]
unrestricted float
constant values in IDL are
represented with
The type name of the unrestricted float
type is “UnrestrictedFloat”.
2.11.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
The type name of the double
type is “Double”.
2.11.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, non-finite, and special "not a number" values (NaNs). [IEEE-754]
unrestricted double
constant values in IDL are
represented with
The type name of the unrestricted double
type is “UnrestrictedDouble”.
2.11.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 §The DOMString Type,
this document defines DOMString
to be an intrinsic type
so as to avoidspecial casing that sequence type
in various situations where a string is required.
Note: Note also that DOMString
.
To allow 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 scalar values given a particular sequence of code units.
The following algorithm defines a way to convert a DOMString to a sequence of Unicode scalar values:
-
Let S be the
DOMString
value. -
Let n be the length of S.
-
Initialize i to 0.
-
Initialize U to be an empty sequence of Unicode characters.
-
While i < n:
-
Let c be the code unit in S at index i.
-
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
-
-
If i = n−1, then append to U a U+FFFD REPLACEMENT CHARACTER.
-
Otherwise, i < n−1:
-
Let d be the code unit in S at index i+1.
-
If 0xDC00 ≤ d ≤ 0xDFFF, then:
-
Let a be c & 0x3FF.
-
Let b be d & 0x3FF.
-
Append to U the Unicode character with code point 216+210a+b.
-
Set i to i+1.
-
-
Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a U+FFFD REPLACEMENT CHARACTER.
-
-
-
Set i to i+1.
-
-
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
The type name of the DOMString
type is “String”.
2.11.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, although ByteString
dictionary member and operation optional argument default values
can be specified using a
The type name of the ByteString
type is “ByteString”.
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, frozen arrays or Typed Arrays with octet
or byte
elements should be used for holding
8 bit data rather than ByteString
.
2.11.17. USVString
The USVString
type
corresponds to the set of all possible sequences of Unicode scalar values,
which are all of the Unicode code points apart from the
surrogate code points.
There is no way to represent a constant USVString
value in IDL, although USVString
dictionary member and operation optional argument default values
can be specified using a
The type name of the USVString
type is “USVString”.
Specifications should only use USVString
for APIs that perform
text processing and need a string of Unicode
scalar values to operate on. Most APIs that use strings
should instead be using DOMString
,
which does not make any interpretations of the code units in the string. When in doubt, use DOMString
.
2.11.18. 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 object?
.
The type name of the object
type is “Object”.
2.11.19. symbol
The symbol
type corresponds to the set of all possible symbol values. Symbol values are opaque,
non-object
values which nevertheless have identity (i.e., are only equal to themselves).
There is no way to represent a constant symbol
value in IDL.
The type name of the symbol
type is “Symbol”.
2.11.20. 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 settings object at the time the
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
The type name of an interface type is the identifier of the interface.
2.11.21. Dictionary types
An identifier that identifies a dictionary is used to refer to a type that corresponds to the set of all dictionaries that adhere to the dictionary definition.
The literal syntax for ordered maps may also be used to represent dictionaries, when it is implicitly understood from context that the map is being treated as an instance of a specific dictionary type. However, there is no way to represent a constant dictionary value inside IDL fragments.
The type name of a dictionary type is the identifier of the dictionary.
2.11.22. 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
The type name of an enumeration type is the identifier of the enumeration.
2.11.23. 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 settings object at
the time an ECMAScript
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.
2.11.24. 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
-
any
, -
a Promise type,
-
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
The type name of a nullable type is the concatenation of the type name of the inner type T and the string “OrNull”.
For example, a type that allows the values boolean?
:
interface MyConstants { const boolean? ARE_WE_THERE_YET = false; };
The following interface has two attributes: one whose value can
be a DOMString
or the Node
object or the
interface Node { readonly attribute DOMString? namespaceURI; readonly attribute Node? parentNode; // ... };
2.11.25. Sequence types — sequence<T>
The sequence<T> type is a parameterized type whose values are (possibly zero-length) lists of values of type T.
Sequences are always passed by value. In language bindings where a sequence is represented by an object of some kind, passing a sequence to a platform object will not result in a reference to the sequence being kept by that object. Similarly, any sequence returned from a platform object will be a copy and modifications made to it will not be visible to the platform object.
The literal syntax for lists may also be used to represent sequences, when it is implicitly understood from context that the list is being treated as a sequences. However, there is no way to represent a constant sequence value inside IDL fragments.
Sequences must not be used as the type of an attribute or constant.
Note: This restriction exists so that it is clear to specification writers and API users that 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.
The type name of a sequence type is the concatenation of the type name for T and the string “Sequence”.
Any list can be implicitly treated as a sequence<T>
, as long as it contains
only items that are of type T.
2.11.26. Record types — record<K, V>
A record type is a parameterized type whose values are ordered maps with keys that are instances of K and values that are instances of V. K must be one
of DOMString
, USVString
, or ByteString
.
The literal syntax for ordered maps may also be used to represent records, when it is implicitly understood from context that the map is being treated as a record. However, there is no way to represent a constant record value inside IDL fragments.
Records are always passed by value. In language bindings where a record is represented by an object of some kind, passing a record to a platform object will not result in a reference to the record being kept by that object. Similarly, any record returned from a platform object will be a copy and modifications made to it will not be visible to the platform object.
Records must not be used as the type of an attribute or constant.
The type name of a record type is the concatenation of the type name for K, the type name for V and the string “Record”.
Any ordered map can be implicitly treated as a record<K, V>
, as long as
it contains only entries whose keys are all of of type K and whose values are all of type V.
2.11.27. Promise types — Promise<T>
A promise type is a parameterized type whose values are references to objects that “is used as a place holder for the eventual results of a deferred (and possibly asynchronous) computation result of an asynchronous operation”. See section 25.4 of the ECMAScript specification for details on the semantics of promise objects.
Promise types are non-nullable, but T may be nullable.
There is no way to represent a promise value in IDL.
The type name of a promise type is the concatenation of the type name for T and the string “Promise”.
2.11.28. 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
For example, you might write (Node or DOMString)
or (double or sequence<double>)
. When applying a (Node or DOMString)?
.
Note that the member types of a union type do not descend into nested union types. So for (double or (sequence<long> or Event) or (Node or DOMString)?)
the member types
are double
, (sequence<long> or Event)
and (Node or DOMString)?
.
Like the any
type, values of
union types have a specific type,
which is the particular member type that matches the value.
The flattened member types of a union type, possibly annotated, is a set of types determined as follows:
-
Let T be the union type.
-
Initialize S to ∅.
-
For each member type U of T:
-
If U is an annotated type, then set U to be the inner type of U.
-
If U is a nullable type, then set U to be the inner type of U.
-
If U is a union type, then add to S the flattened member types of U.
-
Otherwise, U is not a union type. Add U to S.
-
-
Return S.
Note: For example, the flattened member types of the union type (Node or (sequence<long> or Event) or (XMLHttpRequest or DOMString)? or sequence<(sequence<double> or NodeList)>)
are the six types Node
, sequence<long>
, Event
, XMLHttpRequest
, DOMString
and sequence<(sequence<double> or NodeList)>
.
The number of nullable member types of a union type is an integer determined as follows:
-
Let T be the union type.
-
Initialize n to 0.
-
For each member type U of T:
-
If U is a nullable type, then:
-
Set n to n + 1.
-
Set U to be the inner type of U.
-
-
If U is a union type, then:
-
Let m be the number of nullable member types of U.
-
Set n to n + m.
-
-
-
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:
-
the type is a nullable type, or
-
the type is an annotated type and its inner type is a nullable type, or
-
the type is a union type and its number of nullable member types is 1.
Each pair of flattened member types in a union type, T and U, must be distinguishable.
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”.
2.11.29. Annotated types
Additional types can be created from existing ones by specifying certain extended attributes on the existing types. Such types are called annotated types, and the types they annotate are called inner types.
[Clamp] long
defines a new annotated type, whose behavior is based on that of
the inner type long
, but modified as specified by the [Clamp
]
extended attribute. The following extended attributes are applicable to types:
[Clamp
],
[EnforceRange
], and
[TreatNullAs
].
-
Let extended attributes be a new empty set.
-
If type appears as part of a
TypeWithExtendedAttributes production, append each of the extended attributes present in the production’sExtendedAttributeList to extended attributes. -
If type is a member type of a union type U, append each of the extended attributes associated with U to extended attributes.
-
If type appears as part of a
Type production directly within anArgument production, append to extended attributes all of the extended attributes present in the production’sExtendedAttributeList that are applicable to types.interface I { void f([XAttr] long attrib); };
Note that this is an example of this step only if [
XAttr
] is applicable to types; otherwise [XAttr
] applies to the argument, and not the argument’s type. -
If type appears as part of a
Type production directly within anDictionaryMember production, append to extended attributes all of the extended attributes present in the production’sExtendedAttributeList that are applicable to types.dictionary D { [XAttr] long member; };
Note that this is an example of this step only if [
XAttr
] is applicable to types; otherwise [XAttr
] applies to the dictionary member, and not the member’s type. -
If type is a typedef, append the extended attributes associated with the type being given a new name to extended attributes.
-
Return extended attributes.
For any type, the extended attributes associated with it must only contain extended attributes that are applicable to types.
The type name of a type associated with extended attributes is the concatenation of the type name of the original type with the set of strings corresponding to the identifiers of each extended attribute associated with the type, sorted in lexicographic order.
2.11.30. Error
The Error
type corresponds to the
set of all possible non-null references to exception objects,
including simple exceptions and DOMException
objects.
There is no way to represent a constant Error
value in IDL.
The type name of the Error
type is “Error”.
2.11.31. Buffer source types
There are a number of types that correspond to sets of all possible non-null references to objects that represent a buffer of data or a view on to a buffer of data. The table below lists these types and the kind of buffer or view they represent.
Type | Kind of buffer |
---|---|
ArrayBuffer
| An object that holds a pointer (which may be null) to a buffer of a fixed number of bytes |
DataView
| A view on to an ArrayBuffer that allows typed access to integers and floating point values stored at arbitrary offsets into the buffer
|
Int8Array ,Int16Array ,Int32Array
| A view on to an ArrayBuffer that exposes it as an array of two’s complement signed integers of the given size in bits
|
Uint8Array ,Uint16Array ,Uint32Array
| A view on to an ArrayBuffer that exposes it as an array of unsigned integers of the given size in bits
|
Uint8ClampedArray
| A view on to an ArrayBuffer that exposes it as an array of unsigned 8 bit integers with clamped conversions
|
Float32Array ,Float64Array
| A view on to an ArrayBuffer that exposes it as an array of IEEE 754 floating point numbers of the given size in bits
|
Note: These types all correspond to classes defined in ECMAScript.
There is no way to represent a constant value of any of these types in IDL.
The type name of all of these types is the name of the type itself.
At the specification prose level, IDL buffer source types are simply references to objects. To inspect or manipulate the bytes inside the buffer, specification prose must first either get a reference to the bytes held by the buffer source or get a copy of the bytes held by the buffer source. With a reference to the buffer source’s bytes, specification prose can get or set individual byte values using that reference.
Extreme care must be taken when writing specification text that gets a reference to the bytes held by a buffer source, as the underyling data can easily be changed by the script author or other APIs at unpredictable times. If you are using a buffer source type as an operation argument to obtain a chunk of binary data that will not be modified, it is strongly recommended to get a copy of the buffer source’s bytes at the beginning of the prose defining the operation.
Requiring prose to explicitly get a reference to or copy of the bytes is intended to help specification reviewers look for problematic uses of these buffer source types.
When designing APIs that take a buffer, it is recommended to use the BufferSource
typedef rather than ArrayBuffer
or any of the view types.
When designing APIs that create and return a buffer, it is recommended
to use the ArrayBuffer
type rather than Uint8Array
.
Attempting to get a reference to or get a copy of the bytes held by a buffer source when the ArrayBuffer
has been detached will fail in a language binding-specific manner.
Note: See §3.2.25 Buffer source types below for how interacting with buffer source types works in the ECMAScript language binding.
We should include an example of specification text that uses these types and terms.
BufferRelatedType : "ArrayBuffer" "DataView" "Int8Array" "Int16Array" "Int32Array" "Uint8Array" "Uint16Array" "Uint32Array" "Uint8ClampedArray" "Float32Array" "Float64Array"
2.11.32. Frozen array types — FrozenArray<T>
A frozen array type is a parameterized type whose values are references to objects that hold a fixed length array of unmodifiable values. The values in the array are of type T.
Since FrozenArray<T> values are references, they are unlike sequence types, which are lists of values that are passed by value.
There is no way to represent a constant frozen array value in IDL.
The type name of a frozen array type is the concatenation of the type name for T and the string “Array”.
2.12. Extended attributes
An extended attribute is an annotation
that can appear on
definitions, types, interface members, namespace members, dictionary members,
and operation arguments, and
is used to control how language bindings will handle those constructs.
Extended attributes are specified with an
The
Grammar symbol | Form | Example |
---|---|---|
| takes no arguments | [Replaceable]
|
| takes an argument list | [Constructor(double x, double y)]
|
| takes a named argument list | [NamedConstructor=Image(DOMString src)]
|
| takes an identifier | [PutForwards=name]
|
| takes an identifier list | [Exposed=(Window,Worker)]
|
This specification defines a number of extended attributes that are applicable to the ECMAScript language binding, which are described in §3.3 ECMAScript-specific extended attributes. Each extended attribute definition will state which of the above five forms are allowed.
ExtendedAttributeList : "[" ExtendedAttribute ExtendedAttributes "]" ε
ExtendedAttributes : "," ExtendedAttribute ExtendedAttributes ε
ExtendedAttribute : "(" ExtendedAttributeInner ")" ExtendedAttributeRest "[" ExtendedAttributeInner "]" ExtendedAttributeRest "{" ExtendedAttributeInner "}" ExtendedAttributeRest Other ExtendedAttributeRest
ExtendedAttributeRest : ExtendedAttribute ε
ExtendedAttributeInner : "(" ExtendedAttributeInner ")" ExtendedAttributeInner "[" ExtendedAttributeInner "]" ExtendedAttributeInner "{" ExtendedAttributeInner "}" ExtendedAttributeInner OtherOrComma ExtendedAttributeInner ε
Other : integer float identifier string other "-" "-Infinity" "." "..." ":" ";" "<" "=" ">" "?" "ByteString" "DOMString" "FrozenArray" "Infinity" "NaN" "USVString" "any" "boolean" "byte" "double" "false" "float" "long" "null" "object" "octet" "or" "optional" "sequence" "short" "true" "unsigned" "void" ArgumentNameKeyword BufferRelatedType
OtherOrComma : Other ","
IdentifierList : identifier Identifiers
Identifiers : "," identifier Identifiers ε
ExtendedAttributeNoArgs : identifier
ExtendedAttributeArgList : identifier "(" ArgumentList ")"
ExtendedAttributeIdent : identifier "=" identifier
ExtendedAttributeIdentList : identifier "=" "(" IdentifierList ")"
ExtendedAttributeNamedArgList : identifier "=" identifier "(" ArgumentList ")"
3. ECMAScript binding
This section describes how definitions written with the IDL defined in §2 Interface definition language 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]], [[Set]], [[DefineOwnProperty]], [[GetOwnProperty]], and [[Delete]].
Other specifications may override the definitions of any internal method of a platform object that is an instance of an interface.
As overriding internal ECMAScript object methods is a low level operation and can result in objects that behave differently from ordinary objects, this facility should not be used unless necessary for security or compatibility. The expectation is that this will be used for Location objects and possibly WindowProxy objects.
Unless otherwise specified, the [[Extensible]] internal property
of objects defined in this section has the value
Unless otherwise specified, the [[Prototype]] internal property
of objects defined in this section is the
Some objects described in this section are defined to have a class string, which is the string to include in the string returned from Object.prototype.toString. If an object has a class string, then the object must, at the time it is created, have a property whose name is the @@toStringTag symbol and whose value is the specified string.
Should define whether @@toStringTag is writable, enumerable and configurable. All @@toStringTag properties in the ES6 spec are non-writable and non-enumerable, and configurable.
If an object is defined to be a function object, then it has characteristics as described in ECMA-262 section 9.3.
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
Note that algorithm steps can call in to other algorithms and abstract operations and not explicitly handle exceptions that are thrown from them. When an exception is thrown by an algorithm or abstract operation and it is not explicitly handled by the caller, then it is taken to end the algorithm and propagate out to its caller, and so on.
Consider the following algorithm:
-
Let x be the ECMAScript value passed in to this algorithm.
-
Let y be the result of calling ToString(x).
-
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.
3.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 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.
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:
<!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 that the implementation supports. If a given ECMAScript global environment does not expose an interface, then the requirements given in §3.6 Interfaces are not followed for that interface.
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.
Although at the time of this writing the ECMAScript specification does not reflect this, every ECMAScript object must have an associated Realm. The mechanisms for associating objects with Realms are, for now, underspecified. However, we note that in the case of platform objects, the associated Realm is equal to the object’s relevant Realm, and for non-exotic function objects (i.e. not callable proxies, and not bound functions) the associated Realm is equal to the value of the function object’s [[Realm]] internal slot.
3.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.
Note that the sub-sections and algorithms below also apply to annotated types created by applying extended attributes to the types named in their headers.
3.2.1. any
Since the IDL any
type
is the union of all other IDL types, it can correspond to any
ECMAScript value type.
An ECMAScript value V is converted to an IDL any
value by running the following algorithm:
-
If V is
undefined , then return anobject
reference to a special object that represents the ECMAScriptundefined value. -
If V is
null , then return thenull object?
reference. -
If Type(V) is Boolean, then return the
boolean
value that represents the same truth value. -
If Type(V) is Number, then return the result of converting V to an
unrestricted double
. -
If Type(V) is String, then return the result of converting V to a
DOMString
. -
If Type(V) is Symbol, then return the result of converting V to a
symbol
. -
If Type(V) is Object, then return an IDL
object
value that references V.
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 any
value
as described in the remainder of this section are performed.
3.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
ECMAScript functions that implement an operation whose IDL
specifies a void
return type
may return any value, which will be discarded.
3.2.3. boolean
The IDL boolean
value true
is converted to
the ECMAScript boolean
value false
is converted to the ECMAScript
3.2.4. Integer types
Mathematical operations used in this section, including those defined in ECMA-262 section 5.2, are to be understood as computing exact mathematical results on mathematical real numbers.
In effect, where x is a
3.2.4.1. byte
An ECMAScript value V is converted to an IDL byte
value by running the following algorithm:
-
Let x be ? ConvertToInt(V, 8, "signed").
-
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 byte
value.
The
3.2.4.2. octet
An ECMAScript value V is converted to an IDL octet
value by running the following algorithm:
-
Let x be ? ConvertToInt(V, 8, "unsigned").
-
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 octet
value.
The
3.2.4.3. short
An ECMAScript value V is converted to an IDL short
value by running the following algorithm:
-
Let x be ? ConvertToInt(V, 16, "signed").
-
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 short
value.
The
3.2.4.4. unsigned short
An ECMAScript value V is converted to an IDL unsigned short
value by running the following algorithm:
-
Let x be ? ConvertToInt(V, 16, "unsigned").
-
Return the IDL
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 unsigned short
value.
The
3.2.4.5. long
An ECMAScript value V is converted to an IDL long
value by running the following algorithm:
-
Let x be ? ConvertToInt(V, 32, "signed").
-
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 long
value.
The
3.2.4.6. unsigned long
An ECMAScript value V is converted to an IDL unsigned long
value by running the following algorithm:
-
Let x be ? ConvertToInt(V, 32, "unsigned").
-
Return the IDL
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 unsigned long
value.
The
3.2.4.7. long long
An ECMAScript value V is converted to an IDL long long
value by running the following algorithm:
-
Let x be ? ConvertToInt(V, 64, "signed").
-
Return the IDL
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 long long
,
choosing the numeric value with an even significand if there are
two equally close values.
If the long long
is in the range
[−253 + 1, 253 − 1], then the long long
.
3.2.4.8. unsigned long long
An ECMAScript value V is converted to an IDL unsigned long long
value by running the following algorithm:
-
Let x be ? ConvertToInt(V, 64, "unsigned").
-
Return the IDL
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 unsigned long long
,
choosing the numeric value with an even significand if there are
two equally close values.
If the unsigned long long
is less than or equal to 253 − 1,
then the unsigned long long
.
3.2.4.9. Abstract operations
ConvertToInt(V, bitLength, signedness):
-
If bitLength is 64, then:
-
Let upperBound be 253 − 1.
-
If signedness is "unsigned", then let lowerBound be 0.
-
Otherwise let lowerBound be −253 + 1.
Note: this ensures
long long
types associated with [EnforceRange
] or [Clamp
] extended attributes are representable in ECMAScript’s Number type as unambiguous integers.
-
-
Otherwise, if signedness is "unsigned", then:
-
Let lowerBound be 0.
-
Let upperBound be 2bitLength − 1.
-
-
Otherwise:
-
Let lowerBound be -2bitLength − 1.
-
Let upperBound be 2bitLength − 1 − 1.
-
-
If x is −0, then set x to +0.
-
If the conversion is to an IDL type associated with the [
EnforceRange
] extended attribute, then:-
If x is
NaN , +∞, or −∞, then throw aTypeError . -
Set x to ! IntegerPart(x).
-
If x < lowerBound or x > upperBound, then throw a
TypeError . -
Return x.
-
-
If x is not
NaN and the conversion is to an IDL type associated with the [Clamp
] extended attribute, then: -
If x is
NaN , +0, +∞, or −∞, then return +0. -
Set x to ! IntegerPart(x).
-
Set x to x modulo 2bitLength.
-
If signedness is "signed" and x ≥ 2bitLength − 1, then return x − 2bitLength.
-
Otherwise, return x.
3.2.5. float
An ECMAScript value V is converted to an IDL float
value by running the following algorithm:
-
If x is
NaN , +∞, or −∞, then throw aTypeError . -
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.
-
Let y be the number in S that is closest to x, selecting the number with an even significand if there are two equally close values. (The two special values 2128 and −2128 are considered to have even significands for this purpose.)
-
If y is 2128 or −2128, then throw a
TypeError . -
If y is +0 and x is negative, return −0.
-
Return y.
The result of converting an IDL float
value to an ECMAScript
value is the float
value.
3.2.6. unrestricted float
An ECMAScript value V is converted to an IDL unrestricted float
value by running the following algorithm:
-
If x is
NaN , then return the IDLunrestricted float
value that represents the IEEE 754 NaN value with the bit pattern 0x7fc00000 [IEEE-754]. -
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.
-
Let y be the number in S that is closest to x, selecting the number with an even significand if there are two equally close values. (The two special values 2128 and −2128 are considered to have even significands for this purpose.)
-
If y is 2128, return +∞.
-
If y is −2128, return −∞.
-
If y is +0 and x is negative, return −0.
-
Return y.
Note: Since there is only a single ECMAScript
The result of converting an IDL unrestricted float
value to an ECMAScript
value is a
-
If the IDL
unrestricted float
value is a NaN, then theNumber value isNaN . -
Otherwise, the
Number value is the one that represents the same numeric value as the IDLunrestricted float
value.
3.2.7. double
The result of converting an IDL double
value to an ECMAScript
value is the double
value.
3.2.8. unrestricted double
An ECMAScript value V is converted to an IDL unrestricted double
value by running the following algorithm:
-
If x is
NaN , then return the IDLunrestricted double
value that represents the IEEE 754 NaN value with the bit pattern 0x7ff8000000000000 [IEEE-754]. -
Return the IDL
unrestricted double
value that represents the same numeric value as x.
Note: Since there is only a single ECMAScript
The result of converting an IDL unrestricted double
value to an ECMAScript
value is a
-
If the IDL
unrestricted double
value is a NaN, then theNumber value isNaN . -
Otherwise, the
Number value is the one that represents the same numeric value as the IDLunrestricted double
value.
3.2.9. DOMString
An ECMAScript value V is converted to an IDL DOMString
value by running the following algorithm:
-
If V is
null and the conversion is to an IDL type associated with the [TreatNullAs
] extended attribute, then return theDOMString
value that represents the empty string. -
Let x be ToString(V).
-
Return the IDL
DOMString
value that represents the same sequence of code units as the one the ECMAScriptString value x represents.
The result of converting an IDL DOMString
value to an ECMAScript
value is the DOMString
represents.
3.2.10. ByteString
An ECMAScript value V is converted to an IDL ByteString
value by running the following algorithm:
-
Let x be ToString(V).
-
If the value of any element of x is greater than 255, then throw a
TypeError . -
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 ByteString
,
and the value of each element of which is the value of the corresponding element
of the ByteString
.
3.2.11. USVString
An ECMAScript value V is converted to an IDL USVString
value by running the following algorithm:
-
Let string be the result of converting V to a
DOMString
. -
Return an IDL
USVString
value that is the result of converting string to a sequence of Unicode scalar values.
An IDL USVString
value is converted to an ECMAScript value by running the following algorithm:
-
Let scalarValues be the sequence of Unicode scalar values the
USVString
represents. -
Let string be the sequence of code units that results from encoding scalarValues in UTF-16.
-
Return the
String value that represents the same sequence of code units as string.
3.2.12. object
IDL object
values are represented by ECMAScript
The result of converting an IDL object
value to an ECMAScript
value is the object
represents.
3.2.13. symbol
IDL symbol
values are represented by ECMAScript
The result of converting an IDL symbol
value to an
ECMAScript value is the symbol
represents.
3.2.14. Interface types
IDL interface type values are represented by ECMAScript
An ECMAScript value V is converted to an IDL interface type value by running the following algorithm (where I is the interface):
-
If V is a platform object that implements I, then return the IDL interface type value that represents a reference to that platform object.
-
If V is a user object that is considered to implement I according to the rules in §3.10 User objects implementing callback interfaces, then return the IDL interface type value that represents a reference to that user object, with the incumbent settings object as the callback context.
-
Throw a
TypeError .
The result of converting an IDL interface type value to an ECMAScript value is the
3.2.15. Dictionary types
IDL dictionary type values are represented
by ECMAScript
An ECMAScript value V is converted to an IDL dictionary type value by running the following algorithm (where D is the dictionary type):
-
If Type(V) is not Undefined, Null or Object, then throw a
TypeError . -
Let dict be an empty dictionary value of type D; every dictionary member is initially considered to be not present.
-
Let dictionaries be a list consisting of D and all of D’s inherited dictionaries, in order from least to most derived.
-
For each dictionary dictionary in dictionaries, in order:
-
For each dictionary member member declared on dictionary, in lexicographical order:
-
Let key be the identifier of member.
-
Let value be an ECMAScript value, depending on Type(V):
-
If value is not
undefined , then:-
Let idlValue be the result of converting value to an IDL value whose type is the type member is declared to be of.
-
Set the dictionary member on dict with key name key to the value idlValue. This dictionary member is considered to be present.
-
-
Otherwise, if value is
undefined but member has a default value, then:-
Let idlValue be member’s default value.
-
Set the dictionary member on dict with key name key to the value idlValue. This dictionary member is considered to be present.
-
-
Otherwise, if value is
undefined and member is a required dictionary member, then throw aTypeError .
-
-
-
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
-
Let O be ! ObjectCreate(%ObjectPrototype%).
-
Let dictionaries be a list consisting of D and all of D’s inherited dictionaries, in order from least to most derived.
-
For each dictionary dictionary in dictionaries, in order:
-
For each dictionary member member declared on dictionary, in lexicographical order:
-
Let key be the identifier of member.
-
If the dictionary member named key is present in V, then:
-
Let idlValue be the value of member on V.
-
Let value be the result of converting idlValue to an ECMAScript value.
-
Perform ! CreateDataProperty(O, key, value).
-
-
-
-
Return O.
3.2.16. Enumeration types
IDL enumeration types are represented by ECMAScript
An ECMAScript value V is converted to an IDL enumeration type value as follows (where E is the enumeration):
-
Let S be the result of calling ToString(V).
-
If S is not one of E’s enumeration values, then throw a
TypeError . -
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
3.2.17. Callback function types
IDL callback function types are represented by ECMAScript 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:
-
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 aTypeError . -
Return the IDL callback function type value that represents a reference to the same object that V represents, with the incumbent settings object as the callback context.
The result of 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.
3.2.18. 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
An ECMAScript value V is converted to an IDL nullable type T?
value (where T is the inner type) as follows:
-
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 typeT?
valuenull . -
Otherwise, if V is
null orundefined , then return the IDL nullable typeT?
valuenull . -
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:
-
If the IDL nullable type
T?
value isnull , then the ECMAScript value isnull . -
Otherwise, the ECMAScript value is the result of converting the IDL nullable type value to the inner IDL type
T
.
3.2.19. Sequences — sequence<T>
IDL sequence<T> values are represented by
ECMAScript
An ECMAScript value V is converted to an IDL sequence<T> value as follows:
-
Let method be the result of GetMethod(V, @@iterator).
-
ReturnIfAbrupt(method).
-
If method is
undefined , throw aTypeError . -
Return the result of creating a sequence from V and method.
An IDL sequence value S of type sequence<T> is converted to an ECMAScript
-
Let n be the length of S.
-
Let A be a new
Array object created as if by the expression[]
. -
Initialize i to be 0.
-
While i < n:
-
Let V be the value in S at index i.
-
Let E be the result of converting V to an ECMAScript value.
-
Let P be the result of calling ToString(i).
-
Call CreateDataProperty(A, P, E).
-
Set i to i + 1.
-
-
Return A.
3.2.19.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:
-
Let iter be GetIterator(iterable, method).
-
ReturnIfAbrupt(iter).
-
Initialize i to be 0.
-
Repeat
-
Let next be IteratorStep(iter).
-
ReturnIfAbrupt(next).
-
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. -
Let nextItem be IteratorValue(next).
-
ReturnIfAbrupt(nextItem).
-
Initialize Si to the result of converting nextItem to an IDL value of type T.
-
Set i to i + 1.
-
The following interface defines an attribute of a sequence type as well as an operation with an argument of a sequence type.
interface Canvas { sequence<DOMString> getSupportedImageCodecs(); void drawPolygon(sequence<double> coordinates); sequence<double> getLastDrawnPolygon(); // ... };
In an ECMAScript implementation of this interface, an sequence<DOMString>
, while an sequence<double>
. The getSupportedImageCodecs()
function is called a new drawPolygon
no reference
will be kept after the call completes.
// Obtain an instance of Canvas. Assume that getSupportedImageCodecs() // returns a sequence with two DOMString values: "image/png" and "image/svg+xml". var canvas = getCanvas(); // An Array object of length 2. var supportedImageCodecs = canvas.getSupportedImageCodecs(); // Evaluates to "image/png". supportedImageCodecs[0]; // Each time canvas.getSupportedImageCodecs() is called, it returns a // new Array object. Thus modifying the returned Array will not // affect the value returned from a subsequent call to the function. supportedImageCodecs[0] = "image/jpeg"; // Evaluates to "image/png". canvas.getSupportedImageCodecs()[0]; // This evaluates to false, since a new Array object is returned each call. canvas.getSupportedImageCodecs() == canvas.getSupportedImageCodecs(); // An Array of Numbers... var a = [0, 0, 100, 0, 50, 62.5]; // ...can be passed to a platform object expecting a sequence<double>. canvas.drawPolygon(a); // Each element will be converted to a double by first calling ToNumber(). // So the following call is equivalent to the previous one, except that // "hi" will be alerted before drawPolygon() returns. a = [false, '', { valueOf: function() { alert('hi'); return 100; } }, 0, '50', new Number(62.5)]; canvas.drawPolygon(a); // Modifying an Array that was passed to drawPolygon() is guaranteed not to // have an effect on the Canvas, since the Array is effectively passed by value. a[4] = 20; var b = canvas.getLastDrawnPolygon(); alert(b[4]); // This would alert "50".
3.2.20. Records — record<K, V>
IDL record<K, V> values are represented by
ECMAScript
An ECMAScript value O is converted to an IDL record<K, V>
value as follows:
-
Let result be a new empty instance of
record<K, V>
. -
Let keys be ? O.[[OwnPropertyKeys]]().
-
For each key of keys:
-
Let desc be ? O.[[GetOwnProperty]](key).
-
If desc is not
undefined and desc.[[Enumerable]] istrue :-
Let typedKey be key converted to an IDL value of type K.
-
Let typedValue be value converted to an IDL value of type V.
-
Set result[typedKey] to typedValue.
Note: it’s possible that typedKey is already in result, if O is a proxy object.
-
-
-
Return result.
An IDL record<…>
value D is converted to an ECMAScript value as follows:
-
Let result be ! ObjectCreate(%ObjectPrototype%).
-
For each key → value of D:
-
Let esKey be key converted to an ECMAScript value.
-
Let esValue be value converted to an ECMAScript value.
-
Let created be ! CreateDataProperty(result, esKey, esValue).
-
Assert: created is
true .
-
-
Return result.
Passing the ECMAScript value {b: 3, a: 4}
as a record<DOMString, double>
argument
would result in the IDL value «[ "b" → 3, "a" → 4 ]».
Records only consider own enumerable properties, so given an IDL operation record<DOMString, double>
identity(record<DOMString, double> arg)
which returns its
argument, the following code passes its assertions:
let proto = {a: 3, b: 4}; let obj = {__proto__: proto, d: 5, c: 6} Object.defineProperty(obj, "e", {value: 7, enumerable: false}); let result = identity(obj); console.assert(result.a === undefined); console.assert(result.b === undefined); console.assert(result.e === undefined); let entries = Object.entries(result); console.assert(entries[0][0] === "d"); console.assert(entries[0][1] === 5); console.assert(entries[1][0] === "c"); console.assert(entries[1][1] === 6);
Record keys and values can be constrained, although keys can only be constrained among the three string types. The following conversions have the described results:
Value | Passed to type | Result |
---|---|---|
{"😞": 1}
| record<ByteString, double>
| |
{"\uD83D": 1}
| record<USVString, double>
| «[ "\uFFFD" → 1 ]» |
{"\uD83D": {hello: "world"}}
| record<DOMString, double>
| «[ "\uD83D" → 0 ]» |
3.2.21. Promise types — Promise<T>
IDL promise type values are
represented by ECMAScript
An ECMAScript value V is converted to an IDL PromiseT value as follows:
-
Let resolve be the original value of %Promise%.resolve.
ECMAScript should grow a %Promise_resolve% well-known intrinsic object that can be referenced here.
-
Let promise be the result of calling resolve with %Promise% as the
this value and V as the single argument value. -
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
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:
-
Let promise be the promise object of type Promise<T>.
-
Let onFulfilled be a new function object whose behavior when invoked is as follows:
-
If T is
void
, then:-
Return the result of performing any steps that were required to be run if the promise was fulfilled.
-
-
Otherwise, T is a type other than
void
:-
Let V be the first argument to onFulfilled.
-
Let value be the result of converting V to an IDL value of type T.
-
If there are no steps that are required to be run if the promise was fulfilled, then return
undefined . -
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.
-
-
-
Let onRejected be a new function object whose behavior when invoked is as follows:
-
Let R be the first argument to onRejected.
-
Let reason be the result of converting R to an IDL value of type
any
. -
If there are no steps that are required to be run if the promise was rejected, then return
undefined . -
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.
-
-
Let then be the result of calling the internal [[Get]] method of promise with property name “then”.
-
Return the result of calling then with promise as the
this value and onFulfilled and onRejected as its two arguments.
Include an example of how to write spec text using this term.
3.2.22. 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:
-
If the union type includes a nullable type and V is
null orundefined , then return the IDL valuenull . -
Let types be the flattened member types of the union type.
-
If V is
null orundefined , then:-
If types includes a dictionary type, then return the result of converting V to that dictionary type.
-
-
If V is a platform object, then:
-
If types includes an interface type that V implements, then return the IDL value that is a reference to the object V.
-
If types includes
object
, then return the IDL value that is a reference to the object V.
-
-
If V is a
DOMException
platform object, then:-
If types includes
DOMException
orError
, then return the result of converting V to that type. -
If types includes
object
, then return the IDL value that is a reference to the object V.
-
-
If Type(V) is Object and V has an [[ErrorData]] internal slot), then:
-
If types includes
Error
, then return the result of converting V toError
. -
If types includes
object
, then return the IDL value that is a reference to the object V.
-
-
If Type(V) is Object and V has an [[ArrayBufferData]] internal slot, then:
-
If types includes
ArrayBuffer
, then return the result of converting V toArrayBuffer
. -
If types includes
object
, then return the IDL value that is a reference to the object V.
-
-
If Type(V) is Object and V has a [[DataView]] internal slot, then:
-
If types includes
DataView
, then return the result of converting V toDataView
. -
If types includes
object
, then return the IDL value that is a reference to the object V.
-
-
If Type(V) is Object and V has a [[TypedArrayName]] internal slot, then:
-
If types includes a typed array type whose name is the value of V’s [[TypedArrayName]] internal slot, then return the result of converting V to that type.
-
If types includes
object
, then return the IDL value that is a reference to the object V.
-
-
If IsCallable(V) is true, then:
-
If types includes a callback function type, then return the result of converting V to that callback function type.
-
If types includes
object
, then return the IDL value that is a reference to the object V.
-
-
If Type(V) is Object, then:
-
If types includes a sequence type, then
-
Let method be the result of GetMethod(V, @@iterator).
-
ReturnIfAbrupt(method).
-
If method is not
undefined , return the result of creating a sequence of that type from V and method.
-
-
If types includes a frozen array type, then
-
Let method be the result of GetMethod(V, @@iterator).
-
ReturnIfAbrupt(method).
-
If method is not
undefined , return the result of creating a frozen array of that type from V and method.
-
-
If types includes a dictionary type, then return the result of converting V to that dictionary type.
-
If types includes a record type, then return the result of converting V to that record type.
-
If types includes a callback interface type, then return the result of converting V to that interface type.
-
If types includes
object
, then return the IDL value that is a reference to the object V.
-
-
If Type(V) is Boolean, then:
-
If types includes a
boolean
, then return the result of converting V toboolean
.
-
-
If Type(V) is Number, then:
-
If types includes a numeric type, then return the result of converting V to that numeric type.
-
-
If types includes a string type, then return the result of converting V to that type.
-
If types includes a numeric type, then return the result of converting V to that numeric type.
-
If types includes a
boolean
, then return the result of converting V toboolean
. -
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
3.2.23. Error
IDL Error
values are represented
by native ECMAScript DOMException
platform objects.
An ECMAScript value V is converted to an IDL Error
value by running the following algorithm:
-
If Type(V) is not Object, or V does not have an [[ErrorData]] internal slot, then throw a
TypeError . -
Return the IDL
Error
value that is a reference to the same object as V.
The result of converting an IDL Error
value to an ECMAScript
value is the Error
represents.
3.2.24. DOMException
IDL DOMException
values are represented by
ECMAScript
An ECMAScript value V is converted to an IDL DOMException
value by running the following algorithm:
-
If Type(V) is not Object, or V is not a platform object that represents a
DOMException
, then throw aTypeError . -
Return the IDL
DOMException
value that is a reference to the same object as V.
The result of converting an IDL DOMException
value to an ECMAScript
value is the DOMException
represents.
3.2.25. Buffer source types
Values of the IDL buffer source types are represented by objects of the corresponding ECMAScript class, with the additional restriction
that unless the type is associated with the
[AllowShared
] extended attribute, they can only be backed by ECMAScript ArrayBuffer
objects, and not SharedArrayBuffer
objects.
An ECMAScript value V is converted to an IDL ArrayBuffer
value by running the following algorithm:
-
If Type(V) is not Object, or V does not have an [[ArrayBufferData]] internal slot, then throw a
TypeError . -
If the conversion is not to an IDL type associated with the [
AllowShared
] extended attribute, and IsSharedArrayBuffer(V) is true, then throw aTypeError . -
Return the IDL
ArrayBuffer
value that is a reference to the same object as V.
An ECMAScript value V is converted to an IDL DataView
value by running the following algorithm:
-
If Type(V) is not Object, or V does not have a [[DataView]] internal slot, then throw a
TypeError . -
If the conversion is not to an IDL type associated with the [
AllowShared
] extended attribute, and IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true, then throw aTypeError . -
Return the IDL
DataView
value that is a reference to the same object as V.
An ECMAScript value V is converted to an IDL Int8Array
, Int16Array
, Int32Array
, Uint8Array
, Uint16Array
, Uint32Array
, Uint8ClampedArray
, Float32Array
or Float64Array
value
by running the following algorithm:
-
Let T be the IDL type V is being converted to.
-
Let typedArrayName be the name of T’s inner type if T is an annotated type, or the name of T otherwise.
-
If Type(V) is not Object, or V does not have a [[TypedArrayName]] internal slot with a value equal to typedArrayName, then throw a
TypeError . -
If the conversion is not to an IDL type associated with the [
AllowShared
] extended attribute, and IsSharedArrayBuffer(V.[[ViewedArrayBuffer]]) is true, then throw aTypeError . -
Return the IDL value of type T that is a reference to the same object as V.
The result of converting an IDL value of any buffer source type to an ECMAScript value is the
When getting a reference to or getting a copy of the bytes held by a buffer source that is an ECMAScript ArrayBuffer
, DataView
or typed array object, these steps must be followed:
-
Let O be the ECMAScript object that is the buffer source.
-
Initialize arrayBuffer to O.
-
Initialize offset to 0.
-
Initialize length to 0.
-
If O has a [[ViewedArrayBuffer]] internal slot, then:
-
Set arrayBuffer to the value of O’s [[ViewedArrayBuffer]] internal slot.
-
If arrayBuffer is
undefined , then throw aTypeError . -
Set offset to the value of O’s [[ByteOffset]] internal slot.
-
Set length to the value of O’s [[ByteLength]] internal slot.
-
-
Otherwise, set length to the value of O’s [[ArrayBufferByteLength]] internal slot.
-
If IsDetachedBuffer(O), then throw a
TypeError . -
Let data be the value of O’s [[ArrayBufferData]] internal slot.
-
Return a reference to or copy of (as required) the length bytes in data starting at byte offset offset.
To detach an ArrayBuffer
, these steps must be followed:
-
Let O be the ECMAScript object that is the
ArrayBuffer
. -
Perform ! DetachArrayBuffer(O).
3.2.26. Frozen arrays — FrozenArray<T>
Values of frozen array types are represented by frozen ECMAScript
An ECMAScript value V is converted to an IDL FrozenArray<T> value by running the following algorithm:
-
Let values be the result of converting V to IDL type sequence<T>.
-
Return the result of creating a frozen array from values.
To create a frozen array from a sequence of values of type T, follow these steps:
-
Let array be the result of converting the sequence of values of type T to an ECMAScript value.
-
Perform SetIntegrityLevel(array,
"frozen"
). -
Return array.
The result of converting an IDL FrozenArray<T> value to an ECMAScript
value is the
3.2.26.1. Creating a frozen array from an iterable
To create an IDL value of type FrozenArray<T> given an iterable iterable and an iterator getter method, perform the following steps:
-
Let values be the result of creating a sequence of type sequence<T> from iterable and method.
-
Return the result of creating a frozen array from values.
3.3. ECMAScript-specific extended attributes
This section defines a number of extended attributes whose presence affects only the ECMAScript binding.
3.3.1. [AllowShared]
If the [AllowShared
] extended attribute appears on one of the buffer source types, it
creates a new IDL type that allows the buffer source type to be backed by an ECMAScript SharedArrayBuffer
, instead of only by a non-shared ArrayBuffer
.
The [AllowShared
] extended attribute must take no arguments.
A type that is not a buffer source type must not be associated with the [AllowShared
] extended attribute.
See the rules for converting ECMAScript values to IDL buffer source types in §3.2.25 Buffer source types for the specific requirements that the use of [AllowShared
] entails.
AllowShared
] extended
attribute, while the other does not:
interface RenderingContext { void readPixels(long width, long height, BufferSource pixels); void readPixelsShared(long width, long height, [AllowShared] BufferSource pixels); };
With this definition, a call to readPixels
with an SharedArrayBuffer
instance, or any typed array or DataView
backed by one, will throw a TypeError
exception. In contrast, a call to readPixelsShared
will allow such
objects as input.
3.3.2. [Clamp]
If the [Clamp
] extended attribute appears on one of the integer types, it creates a new
IDL type such that that when an ECMAScript
The [Clamp
]
extended attribute must take no arguments.
A type annotated with the [Clamp
] extended attribute must not appear in a read only attribute. A type must not be associated with both the
[Clamp
] and [EnforceRange
] extended attributes. A type that is not an integer type must
not be associated with the [Clamp
] extended attribute.
See the rules for converting ECMAScript values to the various IDL integer
types in §3.2.4 Integer types for the specific requirements that the use of
[Clamp
] entails.
In the following IDL fragment,
two operations are declared that
take three octet
arguments; one uses
the [Clamp
] extended attribute on all three arguments, while the other does not:
interface GraphicsContext { void setColor(octet red, octet green, octet blue); void setColorClamped([Clamp] octet red, [Clamp] octet green, [Clamp] octet blue); };
A call to setColorClamped
with octet
are clamped to the range [0, 255].
// Get an instance of GraphicsContext. var context = getGraphicsContext(); // Calling the non-[Clamp] version uses ToUint8 to coerce the Numbers to octets. // This is equivalent to calling setColor(255, 255, 1). context.setColor(-1, 255, 257); // Call setColorClamped with some out of range values. // This is equivalent to calling setColorClamped(0, 255, 255). context.setColorClamped(-1, 255, 257);
3.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.
Multiple [Constructor
] extended
attributes may appear on a given interface.
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
the [Constructor
]
extended attribute appears on, or throw an exception.
The [Constructor
] and
[NoInterfaceObject
]
extended attributes must not be specified on the same interface.
The [Constructor
] extended attribute
must not be used on a callback interface.
See §3.6.1 Interface object for details on how a constructor for an interface is to be implemented.
The following IDL defines two interfaces. The second has the
[Constructor
] extended
attribute, while the first does not.
interface NodeList { Node item(unsigned long index); readonly attribute unsigned long length; }; [Constructor, Constructor(double radius)] interface Circle { attribute double r; attribute double cx; attribute double cy; readonly attribute double 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.
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.
3.3.4. [Default]
If the [Default
] extended attribute appears on a regular operation,
then it indicates that steps described in the corresponding default operation must be carried out when the operation is invoked.
The [Default
] extended attribute must take no arguments.
The [Default
] extended attribute must not
be used on anything other than a regular operation for which a corresponding default operation has been defined.
As an example, the [Default
] extended attribute is suitable
for use on toJSON
regular operations:
interface Animal { attribute DOMString name; attribute unsigned short age; [Default] object toJSON(); }; interface Human : Animal { attribute Dog? pet; [Default] object toJSON(); }; interface Dog : Animal { attribute DOMString? breed; };
In the ECMAScript language binding, there would exist a toJSON()
method on Animal
, Human
,
and (via inheritance) Dog
objects:
// Get an instance of Human. var alice = getHuman(); // Evaluates to an object like this (notice how "pet" still holds // an instance of Dog at this point): // // { // name: "Alice", // age: 59, // pet: Dog // } alice.toJSON(); // Evaluates to an object like this (notice how "breed" is absent, // as the Dog interface doesn’t declare a default toJSON operation): // // { // name: "Tramp", // age: 6 // } alice.pet.toJSON(); // Evaluates to a string like this: // '{"name":"Alice","age":59,"pet":{"name":"Tramp","age":6}}' JSON.stringify(alice);
3.3.5. [EnforceRange]
If the [EnforceRange
] extended attribute appears on one of the integer types, it creates
a new IDL type such that that when an ECMAScript
The [EnforceRange
]
extended attribute must take no arguments.
A type annotated with the [EnforceRange
] extended attribute must not appear in a read only attribute. A type must not be associated with both the [Clamp
] and [EnforceRange
] extended attributes. A type that is not an integer type must not be associated with the
[Clamp
] extended attribute.
See the rules for converting ECMAScript values to the various IDL integer
types in §3.2 ECMAScript type mapping for the specific requirements that the use of
[EnforceRange
] entails.
In the following IDL fragment,
two operations are declared that
take three octet
arguments; one uses
the [EnforceRange
] extended attribute on all three arguments, while the other does not:
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 octet
will result in an exception being
thrown.
// Get an instance of GraphicsContext. var context = getGraphicsContext(); // Calling the non-[EnforceRange] version uses ToUint8 to coerce the Numbers to octets. // This is equivalent to calling setColor(255, 255, 1). context.setColor(-1, 255, 257); // When setColorEnforcedRange is called, Numbers are rounded towards zero. // This is equivalent to calling setColor(0, 255, 255). context.setColorEnforcedRange(-0.9, 255, 255.2); // The following will cause a TypeError to be thrown, since even after // rounding the first and third argument values are out of range. context.setColorEnforcedRange(-1, 255, 256);
3.3.6. [Exposed]
If the [Exposed
] extended attribute appears on an interface, partial interface, namespace, partial namespace, or
an individual interface member or namespace member,
it indicates that the construct 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 the [
Exposed
] extended attribute is specified on the construct, then the exposure set is the set of all interfaces that have a global name that is listed in the extended attribute’s argument. -
If the [
Exposed
] extended attribute does not appear on a construct, then its exposure set is defined implicitly, depending on the type of construct:- interface
- namespace
-
The exposure set of the interface or namespace only contains the primary global interface.
- partial interface
- partial namespace
-
The exposure set of the partial interface or namespace is the exposure set of the original interface or namespace definition.
- interface member
-
The exposure set of the interface member is the exposure set of the interface or partial interface the member is declared on.
- namespace member
-
The exposure set of the namespace member is the exposure set of the namespace or partial namespace the member is declared on.
- interface
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.
Similarly, the [Exposed
] extended attribute
must not be specified on both a namespace
member and a partial namespace definition the namespace member is declared on.
If [Exposed
] appears an interface member, then
the interface member’s exposure set must be a subset of the exposure set of the interface or partial interface it’s a
member of. Similarly, if [Exposed
] appears on a
namespace member, then the namespace member’s exposure set must be a
subset of the exposure set of the
namespace or partial namespace it’s a member of.
An interface’s exposure set must be a subset of the exposure set of all of the interface’s consequential interfaces.
If an interface X inherits from another interface Y then the exposure set of X must be a subset of the exposure set of Y.
An interface, namespace, interface member, or namespace member is exposed in a given ECMAScript global environment if the ECMAScript global object implements an interface that is in the construct’s exposure set, and either:
-
the relevant settings object for the ECMAScript global object is a secure context; or
-
the construct is not available only in secure contexts.
Note: Since it is not possible for the relevant settings object for an ECMAScript global object to change whether it is a secure context or not over time, an implementation’s decision to create properties for an interface or interface member can be made once, at the time the initial objects are created.
See §3.6 Interfaces, §3.6.6 Constants, §3.6.7 Attributes, §3.6.8 Operations and §3.6.9 Common iterator behavior for the specific requirements that the use of
[Exposed
] entails.
[Exposed
]
is intended to be used to control whether interfaces, namespaces, or individual
interface or namespace 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:
[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 { // ... }; // Dimensions is available for use in workers and on the main thread. [Exposed=(Window,Worker), Constructor(double width, double height)] interface Dimensions { readonly attribute double width; readonly attribute double height; }; // WorkerNavigator is only available in workers. Evaluating WorkerNavigator // in the global scope of a worker would give you its interface object, while // doing so on the main thread will give you a ReferenceError. [Exposed=Worker] interface WorkerNavigator { // ... }; // Node is only available on the main thread. Evaluating Node // in the global scope of a worker would give you a ReferenceError. interface Node { // ... }; // MathUtils is available for use in workers and on the main thread. [Exposed=(Window,Worker)] namespace MathUtils { double someComplicatedFunction(double x, double y); }; // WorkerUtils is only available in workers. Evaluating WorkerUtils // in the global scope of a worker would give you its namespace object, while // doing so on the main thread will give you a ReferenceError. [Exposed=Worker] namespace WorkerUtils { void setPriority(double x); }; // NodeUtils is only available in the main thread. Evaluating NodeUtils // in the global scope of a worker would give you a ReferenceError. namespace NodeUtils { DOMString getAllText(Node node); };
3.3.7. [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:
-
Any named properties will be exposed on an object in the prototype chain – the named properties object – rather than on the object itself.
-
Interface members from the interface (or consequential interfaces) will correspond to properties on the object itself rather than on interface prototype objects.
Placing named properties on an object in the prototype chain is done so that variable declarations and bareword assignments will shadow the named property with a property on the global object itself.
Placing properties corresponding to interface members on the object itself will mean that common feature detection methods like the following will work:
var indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB; var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || ...;
Because of the way variable declarations are handled in
ECMAScript, the code above would result in the window.indexedDB
and window.requestAnimationFrame
evaluating
to
If the [Global
] or [PrimaryGlobal
] extended attributes is
used on an interface, then:
-
The interface must not define a named property setter.
-
The interface must not define indexed property getters or setters.
-
The interface must not also be declared with the [
OverrideBuiltins
] extended attribute. -
The interface must not inherit from another interface with the [
OverrideBuiltins
] extended attribute. -
Any other interface must not inherit from it.
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
one stringifier or more than one iterable declaration, maplike declaration or setlike declaration 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 §3.6.5 Named properties object for the specific requirements that the use of
[Global
] and [PrimaryGlobal
]
entails for named properties,
and §3.6.6 Constants, §3.6.7 Attributes and §3.6.8 Operations for the requirements relating to the location of properties
corresponding to interface members.
The [PrimaryGlobal
] extended attribute is intended
to be used by the Window
interface.
([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.
[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:
<!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>
3.3.8. [LegacyArrayClass]
If the [LegacyArrayClass
] 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
The [LegacyArrayClass
] extended attribute
must take no arguments.
It must not be used on an interface that
has any inherited interfaces.
Note: Interfaces using [LegacyArrayClass
] 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
See §3.6.3 Interface prototype object for the
specific requirements that the use of [LegacyArrayClass
]
entails.
The following IDL fragment defines two interfaces that use [LegacyArrayClass
].
[LegacyArrayClass] interface ItemList { attribute unsigned long length; getter object getItem(unsigned long index); setter object setItem(unsigned long index, object item); }; [LegacyArrayClass] 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,
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. The
mutating ImmutableItemList
.
The exact behavior depends on the definition of the Array methods themselves.
3.3.9. [LegacyUnenumerableNamedProperties]
If the [LegacyUnenumerableNamedProperties
] extended attribute appears on a interface that supports named properties,
it indicates that all the interface’s named properties are unenumerable.
The [LegacyUnenumerableNamedProperties
]
extended attribute must take no arguments and must not appear on an interface
that does not define a named property getter.
If the [LegacyUnenumerableNamedProperties
]
extended attribute is specified on an interface, then it applies to all its derived interfaces and
must not be specified on any of them.
See §3.9.7 Property enumeration for the specific requirements that the use of
[LegacyUnenumerableNamedProperties
]
entails.
3.3.10. [LegacyWindowAlias]
If the [LegacyWindowAlias
] extended attribute appears on an interface,
it indicates that the primary global interface will have a property
for each identifier mentioned in the extended attribute,
whose value is the interface object for the interface.
The [LegacyWindowAlias
] extended attribute must either take an identifier or take an identifier list.
The LegacyWindowAlias
]'s identifiers.
Each of the identifiers of [LegacyWindowAlias
]
must not be the same as one used by a [LegacyWindowAlias
]
extended attribute on this interface or another interface,
must not be the same as the identifier used by a [NamedConstructor
]
extended attribute on this interface or another interface,
must not be the same as an identifier of an interface that has an interface object,
and must not be one of the reserved identifiers.
The [LegacyWindowAlias
] and [NoInterfaceObject
]
extended attributes must not be specified on the same interface.
The [LegacyWindowAlias
] extended attribute must not be specified
on an interface that does not include the primary global interface in its exposure set.
The [LegacyWindowAlias
] extended attribute must not be specified
on a callback interface.
An interface must not have more than one [LegacyWindowAlias
] extended attributes specified.
See §3.6 Interfaces for details on how legacy window aliases are to be implemented.
[LegacyWindowAlias
] extended attributes are an undesirable feature.
They exist only so that legacy Web platform features can be specified.
They should not be used in specifications
unless required to specify the behavior of legacy APIs.
The following IDL defines an interface that uses the
[LegacyWindowAlias
] extended attribute.
[Constructor, LegacyWindowAlias=WebKitCSSMatrix] interface DOMMatrix : DOMMatrixReadOnly { // ... };
An ECMAScript implementation that supports this interface will
expose two properties on the Window
object with the same value
and the same characteristics;
one for exposing the interface object normally,
and one for exposing it with a legacy name.
WebKitCSSMatrix === DOMMatrix; // Evaluates to true. var m = new WebKitCSSMatrix(); // Creates a new object that // implements DOMMatrix. m.constructor === DOMMatrix; // Evaluates to true. m.constructor === WebKitCSSMatrix; // Evaluates to true. {}.toString.call(m); // Evaluates to '[object DOMMatrix]'.
3.3.11. [LenientSetter]
If the [LenientSetter
] extended attribute appears on a read only regular attribute,
it indicates that a no-op setter will be generated for the attribute’s
accessor property. This results in erroneous assignments to the property
in strict mode to be ignored rather than causing an exception to be thrown.
Specifications should not use [LenientSetter
]
unless required for compatibility reasons. Pages have been observed
where authors have attempted to polyfill an IDL attribute by assigning
to the property, but have accidentally done so even if the property
exists. In strict mode, this would cause an exception to be thrown,
potentially breaking page. Without [LenientSetter
],
this could prevent a browser from shipping the feature.
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 [LenientThis
] extended attribute
must take no arguments.
It must not be used on anything other than
a read only regular attribute.
An attribute with the [LenientSetter
]
extended attribute must not also be declared
with the [PutForwards
]
or [Replaceable
] extended attributes.
The [LenientSetter
] extended attribute must not be used on an attribute declared on a namespace.
See the Attributes section for how
[LenientSetter
] is to be implemented.
The following IDL fragment defines an interface that uses the
[LenientSetter
] extended
attribute.
interface Example { [LenientSetter] readonly attribute DOMString x; readonly attribute DOMString y; };
An ECMAScript implementation that supports this interface will have a setter on the accessor property that correspond to x, which allows any assignment to be ignored in strict mode.
"use strict"; var example = getExample(); // Get an instance of Example. // Fine; while we are in strict mode, there is a setter that is a no-op. example.x = 1; // Throws a TypeError, since we are in strict mode and there is no setter. example.y = 1;
3.3.12. [LenientThis]
If the [LenientThis
] extended attribute appears on a regular attribute,
it indicates that invocations of the attribute’s getter or setter
with a
The [LenientThis
] extended attribute
must take no arguments.
It must not be used on a static attribute.
The [LenientThis
] extended attribute must not be used on an attribute declared on a namespace.
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 for how
[LenientThis
]
is to be implemented.
The following IDL fragment defines an interface that uses the
[LenientThis
] extended
attribute.
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.
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;
3.3.13. [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 NamedConstructor
]'s identifier.
The first form, [NamedConstructor=
,
has the same meaning as using an empty argument list, [NamedConstructor=
.
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 a [NamedConstructor
]
extended attribute on another interface, must not
be the same as an identifier used by a [LegacyWindowAlias
]
extended attribute on this interface or another interface,
must not be the same as an identifier of an interface
that has an interface object,
and must not be one of the reserved identifiers.
The [NamedConstructor
] extended attribute
must not be used on a callback interface.
See §3.6.2 Named constructors for details on how named constructors are to be implemented.
[NamedConstructor
] extended attributes are an undesirable feature.
They exist only so that legacy Web platform features can be specified.
They should not be used in specifications
unless required to specify the behavior of legacy APIs.
Known APIs requiring the use of [NamedConstructor
] extended attributes are: Audio
, Option
and Image
.
The following IDL defines an interface that uses the
[NamedConstructor
] extended
attribute.
[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.
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.
3.3.14. [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 or
a promise type.
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.
interface Document : Node { [NewObject] Element createElement(DOMString localName); // ... };
3.3.15. [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.
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.
An interface that does not have the [NoInterfaceObject
] extended
attribute specified must not inherit
from an interface that has the [NoInterfaceObject
] extended
attribute specified.
See §3.6 Interfaces for the specific requirements that the use of
[NoInterfaceObject
] entails.
The following IDL fragment defines two interfaces, one whose interface object is exposed on the ECMAScript global object, and one whose isn’t:
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.
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
3.3.16. [OverrideBuiltins]
If the [OverrideBuiltins
] extended attribute appears on an interface,
it indicates that for a legacy platform object implementing the interface,
properties corresponding to all of
the object’s supported property names will appear to be on the object,
regardless of what other properties exist on the object or its
prototype chain. This means that named properties will always shadow
any properties that would otherwise appear on the object.
This is in contrast to the usual behavior, which is for named properties
to be exposed only if there is no property with the
same name on the object itself or somewhere on its prototype chain.
The [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 §3.9 Legacy platform objects and §3.9.3 [[DefineOwnProperty]] for the specific requirements that the use of
[OverrideBuiltins
] entails.
The following IDL fragment defines two interfaces, one that has a named property getter and one that does not.
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:
// 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;
3.3.17. [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:
-
A is the attribute on which the [
PutForwards
] extended attribute appears, -
I is the interface on which A is declared,
-
J is the interface type that A is declared to be of, and
-
N is the identifier argument of the extended attribute,
then there must be another attribute B declared on J whose identifier is N. Assignment of a value to the attribute A on an object implementing I will result in that value being assigned to attribute B of the object that A references, instead.
Note that [PutForwards
]-annotated attributes can be
chained. That is, an attribute with the [PutForwards
] extended attribute can refer to an attribute that itself has that extended attribute.
There must not exist a cycle in a
chain of forwarded assignments. A cycle exists if, when following
the chain of forwarded assignments, a particular attribute on
an interface is
encountered more than once.
An attribute with the [PutForwards
]
extended attribute must not also be declared
with the [LenientSetter
] or
[Replaceable
] extended attributes.
The [PutForwards
]
extended attribute must not be used
on an attribute that
is not read only.
The [PutForwards
] extended attribute
must not be used on a static attribute.
The [PutForwards
] extended attribute
must not be used on an attribute declared on
a callback interface or namespace.
See the Attributes section for how
[PutForwards
]
is to be implemented.
The following IDL fragment defines interfaces for names and people.
The [PutForwards
] extended
attribute is used on the name
attribute
of the Person
interface to indicate
that assignments to that attribute result in assignments to the full
attribute of the Person
object:
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:
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.
3.3.18. [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 [LenientSetter
] or
[PutForwards
] extended attributes.
The [Replaceable
]
extended attribute must not be used
on an attribute that
is not read only.
The [Replaceable
] extended attribute
must not be used on a static attribute.
The [Replaceable
] extended attribute
must not be used on an attribute declared on
a callback interface.
See §3.6.7 Attributes for the specific requirements that the use of
[Replaceable
] entails.
The following IDL fragment defines an interface with an operation that increments a counter, and an attribute that exposes the counter’s value, which is initially 0:
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:
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.
3.3.19. [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 or object
.
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.
interface Document : Node { [SameObject] readonly attribute DOMImplementation implementation; // ... };
3.3.20. [SecureContext]
If the [SecureContext
] extended attribute appears on an interface, partial interface, namespace, partial namespace, interface member, or namespace member,
it indicates that the construct is exposed
only within a secure context.
The [SecureContext
]
extended attribute must take no arguments.
The [SecureContext
]
extended attribute must not
be used on anything other than an interface, partial interface, namespace, partial namespace, interface member, or namespace member.
Whether a construct that the [SecureContext
] extended attribute can be specified on is available only in secure contexts is defined as follows:
-
If the [
SecureContext
] extended attribute is specified on the construct, then it is available only in secure contexts. -
Otherwise, if the [
SecureContext
] extended attribute does not appear on a construct, then whether it is available only in secure contexts depends on the type of construct:- interface
- namespace
-
The interface or namespace is not available only in secure contexts.
- partial interface
- partial namespace
-
The partial interface or partial namespace is available only in secure contexts if and only if the original interface or namespace definition is.
- interface member
-
The interface member is available only in secure contexts if and only if the interface or partial interface the member is declared on is.
- namespace member
-
The namespace member is available only in secure contexts if and only if the namspace or partial namespace the member is declared on is.
- interface
Note: Whether a construct is available only in secure contexts influences whether it is exposed in a given ECMAScript global environment.
If [SecureContext
] appears on an overloaded operation,
then it must appear on all overloads.
The [SecureContext
] extended attribute
must not be specified on both an interface member and the
interface or partial interface definition the interface member is declared on, or
on both a namespace member and the namespace or partial namespace definition the
namespace member is declared on.
An interface without the [SecureContext
] extended attribute
must not inherit from another interface
that does specify [SecureContext
].
The following IDL fragment defines an interface with one operation that is executable from all contexts, and two which are executable only from secure contexts.
interface PowerfulFeature { // This call will succeed in all contexts. Promise <Result> calculateNotSoSecretResult(); // This operation will not be exposed to a non-secure context. In such a context, // there will be no "calculateSecretResult" property on PowerfulFeature.prototype. [SecureContext] Promise<Result> calculateSecretResult(); // The same applies here: the attribute will not be exposed to a non-secure context, // and in a non-secure context there will be no "secretBoolean" property on // PowerfulFeature.prototype. [SecureContext] readonly attribute boolean secretBoolean; };
3.3.21. [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
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 such as onclick
and onerror
.
See §3.2.18 Nullable types — T? for the specific requirements that the use of
[TreatNonObjectAsNull
] entails.
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:
callback OccurrenceHandler = void (DOMString details); [TreatNonObjectAsNull] 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
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.
3.3.22. [TreatNullAs]
If the [TreatNullAs
] extended attribute appears on the DOMString
type, it creates a new
IDL type such that that when an ECMAScript "null"
, which is the default, it will be converted to the empty string.
The [TreatNullAs
] extended attribute must take the identifier EmptyString
.
The [TreatNullAs
] extended attribute must not be associated with a type that is not DOMString
.
Note: This means that even DOMString?
must not use [TreatNullAs
], since
See §3.2.9 DOMString for the specific requirements that the use of [TreatNullAs
] entails.
interface Dog { attribute DOMString name; attribute [TreatNullAs=EmptyString] DOMString owner; boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName); };
An ECMAScript implementation implementing the Dog
interface would convert a owner
property or passed as the
argument to the isMemberOfBreed
function
to the empty string rather than "null"
:
var d = getDog(); // Assume d is a platform object implementing the Dog // interface. d.name = null; // This assigns the string "null" to the .name // property. d.owner = null; // This assigns the string "" to the .owner property. d.isMemberOfBreed(null); // This passes the string "" to the isMemberOfBreed // function.
3.3.23. [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.
An attribute or operation is said to be unforgeable on a given interface A if the
attribute or operation is declared on A or one of A’s consequential interfaces, and is
annotated with the [Unforgeable
] extended attribute.
The [Unforgeable
]
extended attribute must take no arguments.
The [Unforgeable
]
extended attribute must not appear on
anything other than an attribute or a
non-static operation. If it does
appear on an operation, then
it must appear on all operations with
the same identifier on that interface.
The [Unforgeable
] extended attribute must not be used on an attribute declared on a namespace.
If an attribute or operation X is unforgeable on an interface A, and A is one of the inherited interfaces of another interface B, then B and all of its consequential interfaces must not have a non-static attribute or regular operation with the same identifier as X.
For example, the following is disallowed:
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. };
See §3.6.7 Attributes, §3.6.8 Operations, §3.8 Platform objects implementing interfaces, §3.9 Legacy platform objects and §3.9.3 [[DefineOwnProperty]] for the specific requirements that the use of
[Unforgeable
] entails.
The following IDL fragment defines
an interface that has two attributes,
one of which is designated as [Unforgeable
]:
interface System { [Unforgeable] readonly attribute DOMString username; readonly attribute long long loginTime; };
In an ECMAScript implementation of the interface, the username attribute will be exposed as a non-configurable property on the object itself:
var system = getSystem(); // Get an instance of System. system.hasOwnProperty("username"); // Evaluates to true. system.hasOwnProperty("loginTime"); // Evaluates to false. System.prototype.hasOwnProperty("username"); // Evaluates to false. System.prototype.hasOwnProperty("loginTime"); // Evaluates to true. try { // This call would fail, since the property is non-configurable. Object.defineProperty(system, "username", { value: "administrator" }); } catch (e) { } // This defineProperty call would succeed, because System.prototype.loginTime // is configurable. var forgedLoginTime = 5; Object.defineProperty(System.prototype, "loginTime", { value: forgedLoginTime }); system.loginTime; // So this now evaluates to forgedLoginTime.
3.3.24. [Unscopable]
If the [Unscopable
] extended attribute appears on a regular attribute or regular operation, it
indicates that an object that implements an interface with the given
interface member will not include its property name in any object
environment record with it as its base object. The result of this is
that bare identifiers matching the property name will not resolve to
the property in a with
statement. This is achieved by
including the property name on the interface prototype object’s @@unscopables property’s value.
The [Unscopable
]
extended attribute must take no arguments.
The [Unscopable
]
extended attribute must not appear on
anything other than a regular attribute or regular operation.
The [Unscopable
] extended attribute must not be used on an attribute declared on a namespace.
See §3.6.3 Interface prototype object for the specific requirements that the use of
[Unscopable
] entails.
For example, with the following IDL:
interface Thing { void f(); [Unscopable] g(); };
the “f” property an be referenced with a bare identifier
in a with
statement but the “g” property cannot:
var thing = getThing(); // An instance of Thing with (thing) { f; // Evaluates to a Function object. g; // Throws a ReferenceError. }
3.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 security check takes the following three inputs:
-
the platform object on which the operation invocation or attribute access is being done,
-
the identifier of the operation or attribute, and
-
the type of the
Function object – “method” (when it corresponds to an IDL operation), or “getter” or “setter” (when it corresponds to the getter or setter function of an IDL attribute).
Note: The HTML Standard defines how a security check is performed. [HTML]
3.5. Overload resolution algorithm
In order to define how overloaded function 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:
-
Let maxarg be the length of the longest type list of the entries in S.
-
Initialize argcount to be min(maxarg, n).
-
Remove from S all entries whose type list is not of length argcount.
-
If S is empty, then throw a
TypeError . -
Initialize d to −1.
-
Initialize method to
undefined . -
If there is more than one entry in S, then set d to be the distinguishing argument index for the entries of S.
-
Initialize values to be an empty list, where each entry will be either an IDL value or the special value “missing”.
-
Initialize i to 0.
-
While i < d:
-
Let V be argi.
-
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.
-
Let optionality be the value at index i in the list of optionality values of any entry in S.
-
If optionality is “optional” and V is
undefined , then:-
If the argument at index i is declared with a default value, then append to values that default value.
-
Otherwise, append to values the special value “missing”.
-
-
Otherwise, append to values the result of converting V to IDL type type.
-
Set i to i + 1.
-
-
If i = d, then:
-
Let V be argi.
Note: This is the argument that will be used to resolve which overload is selected.
-
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. -
Otherwise: if V is
null orundefined , and there is an entry in S that has one of the following types at position i of its type list,-
an annotated type whose inner type is one of the above types
-
a union type or annotated union type that includes a nullable type or that has a dictionary type in its flattened members
then remove from S all other entries.
-
Otherwise: if V is a platform object, and there is an entry in S that has one of the following types at position i of its type list,
-
an interface type that V implements
-
a nullable version of any of the above types
-
an annotated type whose inner type is one of the above types
-
a union type, nullable union type, or annotated union type that has one of the above types in its flattened member types
then remove from S all other entries.
-
-
Otherwise: if V is a
DOMException
platform object and there is an entry in S that has one of the following types at position i of its type list,-
a nullable version of either of the above types
-
an annotated type whose inner type is one of the above types
-
a union type, nullable union type, or annotated union type that has one of the above types in its flattened member types
then remove from S all other entries.
-
Otherwise: if Type(V) is Object, V has an [[ErrorData]] internal slot, and there is an entry in S that has one of the following types at position i of its type list,
-
a nullable version of either of the above types
-
an annotated type whose inner type is one of the above types
-
a union type, nullable union type, or annotated union type that has one of the above types in its flattened member types
then remove from S all other entries.
-
Otherwise: if Type(V) is Object, V has an [[ArrayBufferData]] internal slot, and there is an entry in S that has one of the following types at position i of its type list,
-
a nullable version of either of the above types
-
an annotated type whose inner type is one of the above types
-
a union type, nullable union type, or annotated union type that has one of the above types in its flattened member types
then remove from S all other entries.
-
Otherwise: if Type(V) is Object, V has a [[DataView]] internal slot, and there is an entry in S that has one of the following types at position i of its type list,
-
a nullable version of either of the above types
-
an annotated type whose inner type is one of the above types
-
a union type, nullable union type, or annotated union type that has one of the above types in its flattened member types
then remove from S all other entries.
-
Otherwise: if Type(V) is Object, V has a [[TypedArrayName]] internal slot, and there is an entry in S that has one of the following types at position i of its type list,
-
a typed array type whose name is equal to the value of V’s [[TypedArrayName]] internal slot
-
a nullable version of either of the above types
-
an annotated type whose inner type is one of the above types
-
a union type, nullable union type, or annotated union type that has one of the above types in its flattened member types
then remove from S all other entries.
-
-
Otherwise: if IsCallable(V) is true, and there is an entry in S that has one of the following types at position i of its type list,
-
a callback function type
-
a nullable version of any of the above types
-
an annotated type whose inner type is one of the above types
-
a union type, nullable union type, or annotated union type that has one of the above types in its flattened member types
then remove from S all other entries.
-
-
Otherwise: if Type(V) is Object and there is an entry in S that has one of the following types at position i of its type list,
-
a nullable version of any of the above types
-
an annotated type whose inner type is one of the above types
-
a union type, nullable union type, or annotated union type that has one of the above types in its flattened member types
and after performing the following steps,
-
Let method be the result of GetMethod(V, @@iterator).
-
ReturnIfAbrupt(method).
method is not
undefined , then remove from S all other entries. -
Otherwise: if Type(V) is Object and there is an entry in S that has one of the following types at position i of its type list,
-
a callback interface type
-
a nullable version of any of the above types
-
an annotated type whose inner type is one of the above types
-
a union type, nullable union type, or annotated union type that has one of the above types in its flattened member types
then remove from S all other entries.
-
-
Otherwise: if Type(V) is Boolean and there is an entry in S that has one of the following types at position i of its type list,
-
an annotated type whose inner type is one of the above types
-
a union type, nullable union type, or annotated union type that has one of the above types in its flattened member types
then remove from S all other entries.
-
Otherwise: if Type(V) is Number and there is an entry in S that has one of the following types at position i of its type list,
-
an annotated type whose inner type is one of the above types
-
a union type, nullable union type, or annotated union type that has one of the above types in its flattened member types
then remove from S all other entries.
-
Otherwise: if there is an entry in S that has one of the following types at position i of its type list,
-
a nullable version of any of the above types
-
an annotated type whose inner type is one of the above types
-
a union type, nullable union type, or annotated union type that has one of the above types in its flattened member types
then remove from S all other entries.
-
Otherwise: if there is an entry in S that has one of the following types at position i of its type list,
-
an annotated type whose inner type is one of the above types
-
a union type, nullable union type, or annotated union type that has one of the above types in its flattened member types
then remove from S all other entries.
-
Otherwise: if there is an entry in S that has one of the following types at position i of its type list,
-
an annotated type whose inner type is one of the above types
-
a union type, nullable union type, or annotated union type that has one of the above types in its flattened member types
then remove from S all other entries.
-
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. -
Otherwise: throw a
TypeError .
-
-
Let callable be the operation or extended attribute of the single entry in S.
-
If i = d and method is not
undefined , then-
Let V be argi.
-
Let T be the type at index i in the type list of the remaining entry in S.
-
If T is a sequence type, then append to values the result of creating a sequence of type T from V and method.
-
Otherwise, T is a frozen array type. Append to values the result of creating a frozen array of type T from V and method.
-
Set i to i + 1.
-
-
While i < argcount:
-
Let V be argi.
-
Let type be the type at index i in the type list of the remaining entry in S.
-
Let optionality be the value at index i in the list of optionality values of the remaining entry in S.
-
If optionality is “optional” and V is
undefined , then:-
If the argument at index i is declared with a default value, then append to values that default value.
-
Otherwise, append to values the special value “missing”.
-
-
Otherwise, append to values the result of converting V to IDL type type.
-
Set i to i + 1.
-
-
While i is less than the number of arguments callable is declared to take:
-
If callable’s argument at index i is declared with a default value, then append to values that default value.
-
Otherwise, if callable’s argument at index i is not variadic, then append to values the special value “missing”.
-
Set i to i + 1.
-
-
Return the pair <callable, values>.
The overload resolution algorithm performs both the identification of which overloaded operation, constructor, etc. is being called, and the conversion of the 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
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,
Optional arguments corresponding to a final, variadic argument do not treat
3.6. Interfaces
For every non-callback interface that is exposed in
a given ECMAScript global environment and that is not declared with
the [NoInterfaceObject
] extended attribute,
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]]:
If the [LegacyWindowAlias
] extended attribute was specified on an exposed interface,
then for each identifier in [LegacyWindowAlias
]'s identifiers there must be a corresponding property on the primary global interface.
The name of the property is the given identifier,
and its value is a reference to the interface object for the interface.
The property has the attributes
{ [[Writable]]:
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 [NamedConstructor
]'s identifier,
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]]:
3.6.1. Interface object
The interface object for a given interface is a function object. It has properties that correspond to the constants and static operations defined on that interface, as described in sections §3.6.6 Constants and §3.6.8 Operations.
If the interface is declared with a [Constructor
] extended attribute,
then the interface object can be called as a constructor
to create an object that implements that interface.
Calling that interface as a function will throw an exception.
Interface objects whose interfaces are not declared
with a [Constructor
] extended attribute will throw when called,
both as a function and as a constructor.
An interface object for a non-callback interface has an associated object called the interface prototype object. This object has properties that correspond to the regular attributes and regular operations defined on the interface, and is described in more detail in §3.6.3 Interface prototype object.
Note: Since an interface object is a function object the typeof
operator will return "function" when applied to an interface object.
The interface object for a given non-callback interface I with identifier id and in Realm realm is created as follows:
-
Let steps be the following steps:
-
If I was not declared with a [
Constructor
] extended attribute, then throw aTypeError . -
Let arg0..n−1 be the passed arguments.
-
Let id be the identifier of interface I.
-
Initialize S to the effective overload set for constructors with identifier id on interface I and with argument count n.
-
Let <constructor, values> be the result of passing S and arg0..n−1. to the overload resolution algorithm.
-
Let R be the result of performing the actions listed in the description of constructor with values as the argument values. Rethrow any exceptions.
-
Let O be the result of converting R to an ECMAScript interface type value I.
-
Assert: O is an object that implements I.
-
Assert: O.[[Realm]] is equal to F.[[Realm]].
-
Return O.
-
-
Let constructorProto be the %FunctionPrototype% of realm.
-
If I inherits from some other interface P, then set constructorProto to the interface object of P in realm.
-
Let F be ! CreateBuiltinFunction(realm, steps, constructorProto).
-
Perform ! SetFunctionName(F, id).
-
Let length be 0.
-
If I was declared with a [
Constructor
] extended attribute, then-
Initialize S to the effective overload set for constructors with identifier id on interface I and with argument count 0.
-
Set length to the length of the shortest argument list of the entries in S.
-
-
Perform ! DefinePropertyOrThrow(F, "length", PropertyDescriptor{[[Value]]: length, [[Writable]]:
false , [[Enumerable]]:false , [[Configurable]]:true }). -
Let proto be the interface prototype object of interface I.
-
Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: proto, [[Writable]]:
false , [[Enumerable]]:false , [[Configurable]]:false }).
3.6.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 allows constructing objects that
implement the interface on which the
[NamedConstructor
] extended attributes appear.
If the actions listed in the description of the constructor return normally, then those steps must return an object that implements interface I. This object’s relevant Realm must be the same as that of the named constructor.
The named constructor with identifier id for a given interface I in Realm realm is created as follows:
-
Let steps be the following steps:
-
Let arg0..n−1 be the passed arguments.
-
Initialize S to the effective overload set for constructors with identifier id on interface I and with argument count n.
-
Let <constructor, values> be the result of passing S and arg0..n−1 to the overload resolution algorithm.
-
Let R be the result of performing the actions listed in the description of constructor with values as the argument values.
-
Return the result of converting R to an ECMAScript interface type value I.
-
Let F be ! CreateBuiltinFunction(realm, steps, %FunctionPrototype% of realm).
-
Perform ! SetFunctionName(F, id).
-
Initialize S to the effective overload set for constructors with identifier id on interface I and with argument count 0.
-
Let length be the length of the shortest argument list of the entries in S.
-
Perform ! DefinePropertyOrThrow(F, "length", PropertyDescriptor{[[Value]]: length, [[Writable]]:
false , [[Enumerable]]:false , [[Configurable]]:true }). -
Let proto be the interface prototype object of interface I.
-
Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: proto, [[Writable]]:
false , [[Enumerable]]:false , [[Configurable]]:false }).
3.6.3. 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 §3.6.7 Attributes and §3.6.8 Operations.
As with the interface object, the interface prototype object also has properties that correspond to the constants defined on that interface, described in §3.6.8 Operations.
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]]:
The interface prototype object for a given interface A must have an internal [[Prototype]] property whose value is returned from the following steps:
-
If A is declared with the [
Global
] or [PrimaryGlobal
] extended attribute, and A supports named properties, then return the named properties object for A, as defined in §3.6.5 Named properties object. -
Otherwise, if A is declared to inherit from another interface, then return the interface prototype object for the inherited interface.
-
Otherwise, if A is declared with the [
LegacyArrayClass
] extended attribute, then return %ArrayPrototype%. -
Otherwise, return %ObjectPrototype%.
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:
[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.
If the interface or any of its consequential interfaces has any interface member declared with
the [Unscopable
] extended attribute,
then there must be a property on the
interface prototype object whose name is the @@unscopables symbol
and whose value is an object created as follows:
-
Let object be a new object created as if by the expression
({})
. -
For each of the aforementioned interface members declared with the [
Unscopable
] extended attribute, call CreateDataProperty(object, the identifier of the interface member,true ). -
Return object.
If the interface is declared with the [Global
] or
[PrimaryGlobal
] extended attribute, or the interface is in the set
of inherited interfaces for any
other interface that is declared with one of these attributes, then the interface prototype object must be an immutable prototype exotic object.
The class string of an interface prototype object is the concatenation of the interface’s identifier and the string “Prototype”.
3.6.4. Legacy callback interface object
For every callback interface that is exposed in
a given ECMAScript global environment
and on which constants are defined,
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 legacy callback interface object.
The property has the attributes { [[Writable]]:
The legacy callback interface object for a given callback interface is a function object. It has properties that correspond to the constants defined on that interface, as described in sections §3.6.6 Constants.
Note: Since a legacy callback interface object is a function object the typeof
operator will return "function"
when applied to a legacy callback interface object.
The legacy callback interface object for a given callback interface with identifier id and in Realm realm is created as follows:
-
Let steps be the following steps:
-
Throw a
TypeError .
-
-
Let F be ! CreateBuiltinFunction(realm, steps, the %FunctionPrototype% of realm).
-
Perform ! SetFunctionName(F, id).
-
Perform ! DefinePropertyOrThrow(F, "length", PropertyDescriptor{[[Value]]: 0, [[Writable]]:
false , [[Enumerable]]:false , [[Configurable]]:true }).
3.6.5. Named properties object
For every interface declared with the
[Global
] or [PrimaryGlobal
] extended attribute that supports named properties,
there must exist an object known as the named properties object for that interface on which named properties are exposed.
The named properties object for a given interface A must have an internal [[Prototype]] property whose value is returned from the following steps:
-
If A is declared to inherit from another interface, then return the interface prototype object for the inherited interface.
-
Otherwise, if A is declared with the [
LegacyArrayClass
] extended attribute, then return %ArrayPrototype%. -
Otherwise, return %ObjectPrototype%.
The class string of a named properties object is the concatenation of the interface’s identifier and the string “Properties”.
3.6.5.1. [[GetOwnProperty]]
When the [[GetOwnProperty]] internal method of a named properties object O is called with property key P, the following steps are taken:
-
Let A be the interface for the named properties object O.
-
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, then the sole object will be this global environment’s window object. -
If the result of running the named property visibility algorithm with property name P and object object is true, then:
-
Let operation be the operation used to declare the named property getter.
-
Let value be an uninitialized variable.
-
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.
-
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.
-
Let desc be a newly created Property Descriptor with no fields.
-
Set desc.[[Value]] to the result of converting value to an ECMAScript value.
-
If A implements an interface with the [
LegacyUnenumerableNamedProperties
] extended attribute, then set desc.[[Enumerable]] tofalse , otherwise set it totrue . -
Set desc.[[Writable]] to
true and desc.[[Configurable]] totrue . -
Return desc.
-
-
Return OrdinaryGetOwnProperty(O, P).
3.6.5.2. [[DefineOwnProperty]]
When the [[DefineOwnProperty]] internal method of a named properties object is called, the following steps are taken:
-
Return
false .
3.6.5.3. [[Delete]]
When the [[Delete]] internal method of a named properties object is called, the following steps are taken:
-
Return
false .
3.6.5.4. [[SetPrototypeOf]]
When the [[SetPrototypeOf]] internal method of a named properties object is called, the same algorithm must be executed as is defined for the [[SetPrototypeOf]] internal method of an immutable prototype exotic object.
3.6.5.5. [[PreventExtensions]]
When the [[PreventExtensions]] internal method of a named properties object is called, the following steps are taken:
-
Return
false .
Note: this keeps named properties object extensible by making [[PreventExtensions]] fail.
3.6.6. Constants
For each exposed constant defined on an interface A, there must be a corresponding property. The property has the following characteristics:
-
The name of the property is the identifier of the constant.
-
The location of the property is determined as follows:
-
If the interface was declared with the [
Global
] or [PrimaryGlobal
] extended attribute, then the property exists on the single object that implements the interface. -
Otherwise, if the interface is a consequential interface of a [
Global
]- or [PrimaryGlobal
] annotated interface, then the property exists on the single object that implements the [Global
]- or [PrimaryGlobal
]-annotated interface as well as on the consequential interface’s interface prototype object. -
Otherwise, if the interface has an interface prototype object, then the property exists on it.
-
-
The value of the property is that which is obtained by converting the constant’s IDL value to an ECMAScript value.
-
The property has attributes { [[Writable]]:
false , [[Enumerable]]:true , [[Configurable]]:false }.
In addition, a property with the same characteristics must exist on the interface object or the legacy callback interface object, if either of those objects exists.
3.6.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:
-
If the attribute is a static attribute, then there is a single corresponding property and it exists on the interface’s interface object.
-
Otherwise, if the attribute 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, if the interface is a consequential interface of a [
Global
]- or [PrimaryGlobal
]-annotated interface, then the property exists on the single object that implements the [Global
]- or [PrimaryGlobal
]-annotated interface as well as on the consequential interface’s interface prototype object. -
Otherwise, the property exists solely on the interface’s interface prototype object.
-
-
The property has attributes { [[Get]]: G, [[Set]]: S, [[Enumerable]]:
true , [[Configurable]]: configurable }, where:-
configurable is
false if the attribute was declared with the [Unforgeable
] extended attribute andtrue otherwise; -
G is the attribute getter created given the attribute, the interface (or the interface it’s being mixed in to, if the interface is actually a mixin), and the relevant Realm of the object that is the location of the property; and
-
S is the attribute setter created given the attribute, the interface (or the interface it’s being mixed in to, if the interface is actually a mixin), and the relevant Realm of the object that is the location of the property.
-
The attribute getter is created as follows, given an attribute attribute, a namespace or interface target, and a Realm realm:
-
Let steps be the following series of steps:
-
Try running the following steps:
-
Let O be
null . -
If target is an interface, and attribute is a regular attribute:
-
If the
this value isnull orundefined , set O to realm’s global object. (This will subsequently cause aTypeError in a few steps, if the global object does not implement target and [LenientThis
] is not specified.) -
Otherwise, set O to the
this value. -
If O is a platform object, then perform a security check, passing O, attribute’s identifier, and "getter".
-
If O is not a platform object that implements the interface target, then:
-
If attribute was specified with the [
LenientThis
] extended attribute, then returnundefined . -
Otherwise, throw a
TypeError .
-
-
-
Let R be the result of getting the underlying value of attribute given O.
-
Return the result of converting R to an ECMAScript value of the type attribute is declared as.
-
And then, if an exception was thrown:
-
If attribute’s type is a promise type, then:
-
Otherwise, end these steps and allow the exception to propagate.
-
-
Let F be ! CreateBuiltinFunction(realm, steps, the %FunctionPrototype% of realm).
-
Let name be the string "get " prepended to attribute’s identifier.
-
Perform ! SetFunctionName(F, name).
-
Perform ! DefinePropertyOrThrow(F, "length", PropertyDescriptor{[[Value]]: 0, [[Writable]]:
false , [[Enumerable]]:false , [[Configurable]]:true }). -
Return F.
The attribute setter is created as follows, given an attribute attribute, an interface target, and a Realm realm:
-
If attribute is read only and does not have a [
LenientSetter
], [PutForwards
] or [Replaceable
] extended attribute, returnundefined ; there is no attribute setter function. -
Assert: attribute’s type is not a promise type.
-
Let steps be the following series of steps:
-
If no arguments were passed, then throw a
TypeError . -
Let V be the value of the first argument passed.
-
Let id be attribute’s identifier.
-
Let O be
null . -
If attribute is a regular attribute:
-
If the
this value isnull orundefined , set O to realm’s global object. (This will subsequently cause aTypeError in a few steps, if the global object does not implement target and [LenientThis
] is not specified.) -
Otherwise, set O to the
this value. -
If O is a platform object, then perform a security check, passing O, id, and "setter".
-
Let validThis be true if O is a platform object that implements the interface target, or false otherwise.
-
If validThis is false and attribute was not specified with the [
LenientThis
] extended attribute, then throw aTypeError . -
If attribute is declared with the [
Replaceable
] extended attribute, then:-
Perform ? CreateDataProperty(O, id, V).
-
Return
undefined .
-
-
If validThis is false, then return
undefined . -
If attribute is declared with a [
LenientSetter
] extended attribute, then returnundefined . -
If attribute is declared with a [
PutForwards
] extended attribute, then:
-
-
Let idlValue be determined as follows:
- attribute’s type is an enumeration
-
-
If S is not one of the enumeration’s values, then return
undefined . -
Otherwise, idlValue is the enumeration value equal to S.
- Otherwise
- idlValue is the result of converting V to an IDL value of attribute’s type.
-
Perform the actions listed in the description of attribute that occur on setting, on O if O is not
null . -
Return
undefined
-
-
Let F be ! CreateBuiltinFunction(realm, steps, the %FunctionPrototype% of realm).
-
Let name be the string "set " prepended to id.
-
Perform ! SetFunctionName(F, name).
-
Perform ! DefinePropertyOrThrow(F, "length", PropertyDescriptor{[[Value]]: 1, [[Writable]]:
false , [[Enumerable]]:false , [[Configurable]]:true }). -
Return F.
Note: Although there is only a single property for an IDL attribute, since
accessor property getters and setters are passed a
Note: Attempting to assign to a property corresponding to a read only attribute results in different behavior depending on whether the script doing so is in strict mode.
When in strict mode, such an assignment will result in a
3.6.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:
-
If the operation is static, then the property exists on the interface object.
-
Otherwise, if the operation 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, if the interface is a consequential interface of a [
Global
]- or [PrimaryGlobal
]-annotated interface, then the property exists on the single object that implements the [Global
]- or [PrimaryGlobal
]-annotated interface as well as on the consequential interface’s interface prototype object. -
Otherwise, the property exists solely on the interface’s interface prototype object.
-
-
The property has attributes { [[Writable]]: B, [[Enumerable]]:
true , [[Configurable]]: B }, where B isfalse if the operation is unforgeable on the interface, andtrue otherwise. -
The value of the property is the result of creating an operation function given the operation, the interface (or the interface it’s being mixed in to, if the interface is actually a mixin), and the relevant Realm of the object that is the location of the property.
Note: that is, even if an implements statement was used to make an operation available on the interface, we pass in the interface on the left-hand side of the implements statement, and not the really-a-mixin interface on the right-hand side, where the operation was originally declared.
The above description has some bugs, especially around partial interfaces. See issue #164.
For namespaces, the properties corresponding to each declared operation are described in §3.12.1 Namespace object. (We hope to eventually move interfaces to the same explicit property-installation style as namespaces.)
-
Let id be op’s identifier.
-
Let steps be the following series of steps, given function argument values arg0..n−1:
-
Try running the following steps:
-
Let O be
null . -
If target is an interface, and op is not a static operation:
-
If the
this value isnull orundefined , set O to realm’s global object. (This will subsequently cause aTypeError in a few steps, if the global object does not implement target.) -
Otherwise, set O to the
this value. -
If O is a platform object, then perform a security check, passing O, id, and "method".
-
If O is not a platform object that implements the interface target, throw a
TypeError .
-
-
Let S be the effective overload set for regular operations (if op is a regular operation) or for static operations (if op is a static operation) with identifier id on target and with argument count n.
-
Let <operation, values> be the result of passing S and arg0..n−1 to the overload resolution algorithm.
-
Let R be
null . -
If operation is declared with a [
Default
] extended attribute, then:-
Set R be the result of performing the actions listed in operation’s corresponding default operation on O, with values as the argument values.
-
-
Otherwise:
-
Set R be the result of performing the actions listed in the description of operation, on O if O is not
null , with values as the argument values. -
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:
-
If op has a return type that is a promise type, then:
-
Otherwise, end these steps and allow the exception to propagate.
-
-
Let F be ! CreateBuiltinFunction(realm, steps, the %FunctionPrototype% of realm).
-
Perform ! SetFunctionName(F, id).
-
Let S be the effective overload set for regular operations (if op is a regular operation) or for static operations (if op is a static operation) with identifier id on target and with argument count 0.
-
Let length be the length of the shortest argument list in the entries in S.
-
Perform ! DefinePropertyOrThrow(F, "length", PropertyDescriptor{[[Value]]: length, [[Writable]]:
false , [[Enumerable]]:false , [[Configurable]]:true }). -
Return F.
3.6.8.1. Default operations
Only regular operations which have a corresponding default operation defined below
may be declared with a [Default
] extended attribute.
3.6.8.1.1. Default toJSON operation
The corresponding default operation of the toJSON
operation is the default toJSON operation.
The return type of the default toJSON operation must be object
.
To invoke the default toJSON operation of interface I on O, run the the following steps:
-
Let map be a new ordered map.
-
Let stack be the result of creating an inheritance stack for interface I.
-
Invoke collect attribute values on O, passing it stack and map as arguments.
-
Let result be ! ObjectCreate(%ObjectPrototype%).
-
For each key → value of map,
-
Let k be key converted to an ECMAScript value.
-
Let v be value converted to an ECMAScript value.
-
Perform ! CreateDataProperty(result, k, v).
-
-
Return result.
To invoke the collect attribute values abstract operation on O with stack stack and ordered map map as arguments, run the the following steps:
-
Let I be the result of popping from stack.
-
If a
toJSON
operation with a [Default
] extended attribute is declared on I, then for each exposed regular attribute attr that is an interface member of I, in order:-
Let id be the identifier of attr.
-
Let value be the result of getting the underlying value of attr given O.
-
-
For each implements statements where the left-hand side identifier references I:
-
Let rhs be the interface represented by the right-hand side identifier.
-
Let interfaces be the result of creating an inheritance stack for interface rhs.
-
Invoke collect attribute values on O, passing it interfaces and map as arguments.
-
-
If stack is not empty, then invoke collect attribute values on O, passing it stack and map as arguments.
To create an inheritance stack for interface I, run the the following steps:
The following IDL fragment defines a number of interfaces which are inherited or consequential interfaces of A
,
as show in the below inheritance tree.
F* | C E - I* | | B* - D* | G* - A - H*
Interfaces markes with an asterisk ("*")
declare a toJSON
operation with a [Default
] extended attribute.
interface A : B { attribute DOMString a; }; interface B : C { [Default] object toJSON(); attribute DOMString b; }; interface C { attribute DOMString c; }; interface D : E { [Default] object toJSON(); attribute DOMString d; }; interface E : F { attribute DOMString e; }; interface F { [Default] object toJSON(); attribute DOMString f; }; interface G { [Default] object toJSON(); attribute DOMString g; }; interface H { [Default] object toJSON(); attribute DOMString h; }; interface I { [Default] object toJSON(); attribute DOMString i; }; A implements G; A implements H; B implements D; E implements I;
Calling the toJSON()
method of an object
implementing interface A
defined above
would return the following JSON object:
{ "b": "...", "f": "...", "i": "...", "d": "...", "g": "...", "h": "..." }
An object implementing interface B
would return:
{ "b": "...", "f": "...", "i": "...", "d": "..." }
3.6.8.2. 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 isfalse if the stringifier is unforgeable on the interface, andtrue otherwise. -
The value of the property is a
Function object, which behaves as follows:-
Let O be the result of calling ToObject on the
this value. -
If O is a platform object, then perform a security check, passing:
-
the platform object O,
-
the identifier of the stringifier, and
-
the type “method”.
-
-
If O is not an object that implements the interface on which the stringifier was declared, then throw a
TypeError . -
Let V be an uninitialized variable.
-
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.
-
Return the result of converting V to a
String value.
-
-
The value of the
Function object’s “length” property is theNumber value0 . -
The value of the
Function object’s “name” property is theString value “toString”.
3.6.9. Common iterator behavior
3.6.9.1. @@iterator
If the interface has any of the following:
-
an indexed property getter and an integer-typed attribute named “length”
then a property must exist
whose name is the @@iterator symbol, with attributes
{ [[Writable]]:
The location of the property is determined as follows:
-
If the interface was declared with the [
Global
] or [PrimaryGlobal
] extended attribute, then the property exists on the single object that implements the interface. -
Otherwise, if the interface is a consequential interface of a [
Global
]- or [PrimaryGlobal
]-annotated interface, then the property exists on the single object that implements the [Global
]- or [PrimaryGlobal
]-annotated interface as well as on the consequential interface’s interface prototype object. -
Otherwise, the property exists solely on the interface’s interface prototype object.
If the interface defines an indexed property getter,
then the
If the interface has a pair iterator,
then the
-
Let object be the result of calling ToObject on the
this value. -
If object is a platform object, then perform a security check, passing:
-
the platform object object,
-
the identifier “@@iterator”, and
-
the type “method”.
-
-
Let interface be the interface the iterable declaration is on.
-
If object is not a platform object that implements interface, then throw a
TypeError . -
Let iterator be a newly created default iterator object for interface with object as its target and iterator kind “key+value”.
-
Return iterator.
If the interface has a maplike declaration or setlike declaration,
then the
-
Let object be the result of calling ToObject on the
this value. -
If object is a platform object, then perform a security check, passing:
-
the platform object object,
-
the identifier “@@iterator”, and
-
the type “method”.
-
-
If object is not a platform object that implements the interface on which the maplike declaration or setlike declaration is defined, then throw a
TypeError . -
If the interface has a maplike declaration, then:
-
Let backing be the value of the [[BackingMap]] internal slot of object.
-
Return CreateMapIterator(backing,
"key+value"
).
-
-
Otherwise:
-
Let backing be the value of the [[BackingSet]] internal slot of object.
-
Return CreateSetIterator(backing,
"value"
).
-
The value of the @@iterator
The value of the @@iterator
3.6.9.2. forEach
If the interface has any of the following:
then a property named “forEach” must exist with attributes
{ [[Writable]]:
The location of the property is determined as follows:
-
If the interface was declared with the [
Global
] or [PrimaryGlobal
] extended attribute, then the property exists on the single object that implements the interface. -
Otherwise, if the interface is a consequential interface of a [
Global
]- or [PrimaryGlobal
]-annotated interface, then the property exists on the single object that implements the [Global
]- or [PrimaryGlobal
]-annotated interface as well as on the consequential interface’s interface prototype object. -
Otherwise, the property exists solely on the interface’s interface prototype object.
If the interface defines an indexed property getter,
then the
If the interface has a pair iterator,
then the
interface Iterable { void forEach(Function callback, optional any thisArg); };
with the following prose definition:
-
Let O be the
this value. -
Let pairs be the list of value pairs to iterate over.
-
Let i be 0.
-
While i is less than the length of pairs:
-
Let pair be the entry in pairs at index i.
-
Let key be pair’s key.
-
Let value be pair’s value.
-
Invoke callback with thisArg (or
undefined , if the argument was not supplied) as the callback this value and value, key and O as its arguments. -
Update pairs to the current list of value pairs to iterate over.
-
Set i to i + 1.
-
If the interface has a maplike declaration or setlike declaration then
the
-
Let object be the result of calling ToObject on the
this value. -
If object is a platform object, then perform a security check, passing:
-
the platform object object,
-
the identifier “forEach”, and
-
the type “method”.
-
-
Let interface be the interface on which the maplike declaration or setlike declaration is declared.
-
If object is not a platform object that implements interface, then throw a
TypeError . -
Let callbackFn be the value of the first argument passed to the function, or
undefined if the argument was not supplied. -
If IsCallable(callbackFn) is
false , throw aTypeError . -
Let thisArg be the value of the second argument passed to the function, or
undefined if the argument was not supplied. -
Let backing be the value of the [[BackingMap]] internal slot of object, if the interface has a maplike declaration, or the [[BackingSet]] internal slot of object otherwise.
-
Let callbackWrapper be a
Function that, when invoked, behaves as follows:-
Let v and k be the first two arguments passed to the function.
-
Let thisArg be the
this value. -
Call(callbackFn, thisArg, «v, k, object»).
Note: The callbackWrapper function simply calls the incoming callbackFn with object as the third argument rather than its internal [[BackingMap]] or [[BackingSet]] object.
Can the script author observe that callbackWrapper might be a new function every time forEach is called? What’s the best way of specifying that there’s only one function that has captured an environment?
-
-
Let forEach be the result of calling the [[Get]] internal method of backing with “forEach” and backing as arguments.
-
If IsCallable(forEach) is
false , throw aTypeError . -
Call(forEach, backing, «callbackWrapper, thisArg»).
-
Return
undefined .
The value of the
The value of the
3.6.10. Iterable declarations
3.6.10.1. entries
If the interface has an iterable declaration,
then a property named “entries” must exist with attributes
{ [[Writable]]:
The location of the property is determined as follows:
-
If the interface was declared with the [
Global
] or [PrimaryGlobal
] extended attribute, then the property exists on the single object that implements the interface. -
Otherwise, if the interface is a consequential interface of a [
Global
]- or [PrimaryGlobal
]-annotated interface, then the property exists on the single object that implements the [Global
]- or [PrimaryGlobal
]-annotated interface as well as on the consequential interface’s interface prototype object. -
Otherwise, the property exists solely on the interface’s interface prototype object.
If the interface has a value iterator,
then the
If the interface has a pair iterator,
then the
3.6.10.2. keys
If the interface has an iterable declaration,
then a property named “keys” must exist with attributes
{ [[Writable]]:
The location of the property is determined as follows:
-
If the interface was declared with the [
Global
] or [PrimaryGlobal
] extended attribute, then the property exists on the single object that implements the interface. -
Otherwise, if the interface is a consequential interface of a [
Global
]- or [PrimaryGlobal
]-annotated interface, then the property exists on the single object that implements the [Global
]- or [PrimaryGlobal
]-annotated interface as well as on the consequential interface’s interface prototype object. -
Otherwise, the property exists solely on the interface’s interface prototype object.
If the interface has a value iterator,
then the
If the interface has a pair iterator,
then the
-
Let object be the result of calling ToObject on the
this value. -
If object is a platform object, then perform a security check, passing:
-
the platform object object,
-
the identifier “keys”, and
-
the type “method”.
-
-
Let interface be the interface on which the iterable declaration is declared on.
-
If object is not a platform object that implements interface, then throw a
TypeError . -
Let iterator be a newly created default iterator object for interface with object as its target and iterator kind “key”.
-
Return iterator.
The value of the
The value of the
3.6.10.3. values
If the interface has an iterable declaration,
then a property named “values” must exist
with attributes { [[Writable]]:
The location of the property is determined as follows:
-
If the interface was declared with the [
Global
] or [PrimaryGlobal
] extended attribute, then the property exists on the single object that implements the interface. -
Otherwise, if the interface is a consequential interface of a [
Global
]- or [PrimaryGlobal
]-annotated interface, then the property exists on the single object that implements the [Global
]- or [PrimaryGlobal
]-annotated interface as well as on the consequential interface’s interface prototype object. -
Otherwise, the property exists solely on the interface’s interface prototype object.
If the interface has a value iterator,
then the
If the interface has a pair iterator,
then the
-
Let object be the result of calling ToObject on the
this value. -
If object is a platform object, then perform a security check, passing:
-
the platform object object,
-
the identifier “entries”, and
-
the type “method”.
-
-
Let interface be the interface on which the iterable declaration is declared on.
-
If object is not a platform object that implements interface, then throw a
TypeError . -
Let iterator be a newly created default iterator object for interface with object as its target and iterator kind “value”.
-
Return iterator.
The value of the
The value of the
3.6.10.4. Default iterator objects
A default iterator object for a given interface, target and iteration kind is an object whose internal [[Prototype]] property is the iterator prototype object for the interface.
A default iterator object has three internal values:
-
its target, which is an object whose values are to be iterated,
-
its kind, which is the iteration kind,
-
its index, which is the current index into the values value to be iterated.
Note: Default iterator objects are only used for pair iterators; value iterators, as they are currently restricted to iterating over an object’s supported indexed properties, use standard ECMAScript Array iterator objects.
When a default iterator object is first created, its index is set to 0.
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”.
3.6.10.5. Iterator prototype object
The iterator prototype object for a given interface is an object that exists for every interface that has a pair iterator. It serves as the prototype for default iterator objects for the interface.
The internal [[Prototype]] property of an iterator prototype object must be %IteratorPrototype%.
An iterator prototype object must have a property named “next” with attributes
{ [[Writable]]:
-
Let interface be the interface for which the iterator prototype object exists.
-
Let object be the result of calling ToObject on the
this value. -
If object is a platform object, then perform a security check, passing:
-
the platform object object,
-
the identifier “next”, and
-
the type “method”.
-
-
If object is not a default iterator object for interface, then throw a
TypeError . -
Let index be object’s index.
-
Let kind be object’s kind.
-
Let values be the list of value pairs to iterate over.
-
Let len be the length of values.
-
If index is greater than or equal to len, then return CreateIterResultObject(
undefined ,true ). -
Let pair be the entry in values at index index.
-
Set object’s index to index + 1.
-
Let result be a value determined by the value of kind:
- key
-
-
Let idlKey be pair’s key.
-
Let key be the result of converting idlKey to an ECMAScript value.
-
result is key.
-
- value
-
-
Let idlValue be pair’s value.
-
Let value be the result of converting idlValue to an ECMAScript value.
-
result is value.
-
- key+value
-
-
Let idlKey be pair’s key.
-
Let idlValue be pair’s value.
-
Let key be the result of converting idlKey to an ECMAScript value.
-
Let value be the result of converting idlValue to an ECMAScript value.
-
Let array be the result of performing ArrayCreate(2).
-
Call CreateDataProperty(array, "0", key).
-
Call CreateDataProperty(array, "1", value).
-
result is array.
-
-
Return CreateIterResultObject(result,
false ).
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”.
3.6.11. Maplike declarations
Any object that implements an interface that has a maplike declaration must have a [[BackingMap]] internal slot, which is
initially set to a newly created
If an interface A is declared with a maplike declaration, then there exists a number of additional properties on A’s interface prototype object. These additional properties are described in the sub-sections below.
Some of the properties below are defined to have a function object value that forwards to the internal map object for a given function name. Such functions behave as follows when invoked:
-
Let O be the
this value. -
Let arguments be the list of arguments passed to this function.
-
Let name be the function name.
-
If O is a platform object, then perform a security check, passing:
-
the platform object O,
-
an identifier equal to name, and
-
the type “method”.
-
-
If O is not an object that implements A, then throw a
TypeError . -
Let map be the
Map object that is the value of O’s [[BackingMap]] internal slot. -
Let function be the result of calling the [[Get]] internal method of map passing name and map as arguments.
-
If IsCallable(function) is
false , then throw aTypeError . -
Return Call(function, map, arguments).
3.6.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:-
Let O be the
this value. -
If O is a platform object, then perform a security check, passing:
-
the platform object O,
-
the identifier “size”, and
-
the type “getter”.
-
-
If O is not an object that implements A, then throw a
TypeError . -
Let map be the
Map object that is the value of O’s [[BackingMap]] internal slot. -
Return the result of calling the [[Get]] internal method of map passing “size” and map as arguments.
The value of the
Function object’s “length” property is theNumber value0 .The value of the
Function object’s “name” property is theString value “size”. -
3.6.11.2. entries
A property named “entries” must exist on A’s interface prototype object with attributes { [[Writable]]:
3.6.11.3. keys and values
For both of “keys” and “values”, there must exist a property with that name 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 that forwards that name to the internal map object.
The value of the
The value of the
3.6.11.4. get and has
For both of “get” and “has”, there must exist a property with that name 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 that behaves as follows when invoked:-
Let O be the
this value. -
Let name be the name of the property – “get” or “has”.
-
If O is a platform object, then perform a security check, passing:
-
the platform object O,
-
an identifier equal to name, and
-
the type “method”.
-
-
If O is not an object that implements A, then throw a
TypeError . -
Let map be the
Map object that is the value of O’s [[BackingMap]] internal slot. -
Let keyType be the key type specified in the maplike declaration.
-
Let function be the result of calling the [[Get]] internal method of map passing name and map as arguments.
-
Let keyArg be the first argument passed to this function, or
undefined if not supplied. -
Let keyIDL be the result of converting keyArg to an IDL value of type keyType.
-
Let key be the result of converting keyIDL to an ECMAScript value.
-
Return Call(function, map, «key»).
-
The value of the
The value of the
3.6.11.5. clear
If A and A’s consequential interfaces do not declare an interface member with identifier “clear”, and A was declared with a read–write maplike declaration, then a property named “clear” 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 that forwards “clear” to the internal map object.
The value of the
The value of the
3.6.11.6. delete
If A and A’s consequential interfaces do not declare an interface member with identifier “delete”, and A was declared with a read–write maplike declaration, then a property named “delete” 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 that behaves as follows when invoked:-
Let O be the
this value. -
If O is a platform object, then perform a security check, passing:
-
the platform object O,
-
the identifier “delete”, and
-
the type “method”.
-
-
If O is not an object that implements A, then throw a
TypeError . -
Let map be the
Map object that is the value of O’s [[BackingMap]] internal slot. -
Let keyType be the key type specified in the maplike declaration.
-
Let function be the result of calling the [[Get]] internal method of map passing “delete” and map as arguments.
-
Let keyArg be the first argument passed to this function, or
undefined if not supplied. -
Let keyIDL be the result of converting keyArg to an IDL value of type keyType.
-
Let key be the result of converting keyIDL to an ECMAScript value.
-
Return Call(function, map, «key»).
-
The value of the
The value of the
3.6.11.7. set
If A and A’s consequential interfaces do not declare an interface member with identifier “set”, and A was declared with a read–write maplike declaration, then a property named “set” 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 that behaves as follows when invoked:-
Let O be the
this value. -
If O is a platform object, then perform a security check, passing:
-
the platform object O,
-
the identifier “set”, and
-
the type “method”.
-
-
If O is not an object that implements A, then throw a
TypeError . -
Let map be the
Map object that is the value of O’s [[BackingMap]] internal slot. -
Let keyType and valueType be the key and value types specified in the maplike declaration.
-
Let function be the result of calling the [[Get]] internal method of map passing “set” and map as arguments.
-
Let keyArg be the first argument passed to this function, or
undefined if not supplied. -
Let valueArg be the second argument passed to this function, or
undefined if not supplied. -
Let keyIDL be the result of converting keyArg to an IDL value of type keyType.
-
Let valueIDL be the result of converting valueArg to an IDL value of type valueType.
-
Let key be the result of converting keyIDL to an ECMAScript value.
-
Let value be the result of converting valueIDL to an ECMAScript value.
-
Return O.
-
The value of the
The value of the
3.6.12. Setlike declarations
Any object that implements an interface that has a setlike declaration must have a [[BackingSet]] internal slot, which is
initially set to a newly created
If an interface A is declared with a setlike declaration, then there exists a number of additional properties on A’s interface prototype object. These additional properties are described in the sub-sections below.
Some of the properties below are defined to have a function object value that forwards to the internal set object for a given function name. Such functions behave as follows when invoked:
-
Let O be the
this value. -
Let arguments be the list of arguments passed to this function.
-
Let name be the function name.
-
If O is a platform object, then perform a security check, passing:
-
the platform object O,
-
an identifier equal to name, and
-
the type “method”.
-
-
If O is not an object that implements A, then throw a
TypeError . -
Let set be the
Set object that is the value of O’s [[BackingSet]] internal slot. -
Let function be the result of calling the [[Get]] internal method of set passing name and set as arguments.
-
If IsCallable(function) is
false , then throw aTypeError . -
Return Call(function, set, arguments).
3.6.12.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 set size getter, defined below. -
The set size getter is a
Function object whose behavior when invoked is as follows:-
Let O be the
this value. -
If O is a platform object, then perform a security check, passing:
-
the platform object O,
-
the identifier “size”, and
-
the type “getter”.
-
-
If O is not an object that implements A, then throw a
TypeError . -
Let set be the
Set object that is the value of O’s [[BackingSet]] internal slot. -
Return the result of calling the [[Get]] internal method of set passing “size” and set as arguments.
The value of the
Function object’s “length” property is theNumber value0 .The value of the
Function object’s “name” property is theString value “size”. -
3.6.12.2. values
A property named “values” must exist on A’s interface prototype object with attributes { [[Writable]]:
3.6.12.3. entries and keys
For both of “entries” and “keys”, there must exist a property with that name 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 that forwards that name to the internal set object.
The value of the
The value of the
3.6.12.4. has
There must exist a property with named “has” 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 that behaves as follows when invoked:-
Let O be the
this value. -
If O is a platform object, then perform a security check, passing:
-
the platform object O,
-
the identifier “has”, and
-
the type “method”.
-
-
If O is not an object that implements A, then throw a
TypeError . -
Let set be the
Set object that is the value of O’s [[BackingSet]] internal slot. -
Let type be the value type specified in the setlike declaration.
-
Let function be the result of calling the [[Get]] internal method of set passing “has” and set as arguments.
-
Let arg be the first argument passed to this function, or
undefined if not supplied. -
Let idlValue be the result of converting arg to an IDL value of type type.
-
Let value be the result of converting idlValue to an ECMAScript value.
-
Call(function, set, «value»).
-
The value of the
The value of the
3.6.12.5. add and delete
For both of “add” and “delete”, if:
-
A and A’s consequential interfaces do not declare an interface member with a matching identifier, and
-
A was declared with a read–write setlike declaration,
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 that behaves as follows when invoked:-
Let O be the
this value. -
Let name be the name of the property – “add” or “delete”.
-
If O is a platform object, then perform a security check, passing:
-
the platform object O,
-
an identifier equal to name, and
-
the type “method”.
-
-
If O is not an object that implements A, then throw a
TypeError . -
Let set be the
Set object that is the value of O’s [[BackingSet]] internal slot. -
Let type be the value type specified in the setlike declaration.
-
Let function be the result of calling the [[Get]] internal method of set passing name and set as arguments.
-
Let arg be the first argument passed to this function, or
undefined if not supplied. -
Let idlValue be the result of converting arg to an IDL value of type type.
-
Let value be the result of converting idlValue to an ECMAScript value.
-
If name is "delete", then retun result.
-
Otherwise, return O.
-
The value of the
The value of the
3.6.12.6. clear
If A and A’s consequential interfaces do not declare an interface member with a matching identifier, and A was declared with a read–write setlike declaration, then a property named “clear” 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 that forwards “clear” to the internal set object.
The value of the
The value of the
3.7. 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, operations, iterable declarations, maplike declarations and setlike declarations 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
When invoking an operation by calling
a
For example, consider the following 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 A.prototype.f
on an object that implements B
or one that implements C
would succeed. This is handled by the algorithm in §3.6.8 Operations that defines how IDL operation invocation works in ECMAScript.
Similar behavior is required for the getter and setter
3.8. 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.
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.
3.8.1. [[SetPrototypeOf]]
The internal [[SetPrototypeOf]] method of every platform object that implements an interface with the [Global
] or [PrimaryGlobal
] extended attribute must execute the same algorithm as is defined for the
[[SetPrototypeOf]] internal method of an immutable prototype exotic object.
Note: For Window
objects, it is unobservable whether this is implemented, since the presence of
the WindowProxy
object ensures that [[SetPrototypeOf]] is never called on a Window
object
directly. For other global objects, however, this is necessary.
3.9. Legacy platform objects
Legacy platform objects will appear to have additional properties that correspond to their indexed and named properties. These properties are not “real” own properties on the object, but are made to look like they are by being exposed by the [[GetOwnProperty]] internal method .
It is permissible for an object to implement multiple interfaces that support indexed properties. However, if so, and there are conflicting definitions as to the object’s supported property indices, or if one of the interfaces is a supplemental interface for the legacy 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 legacy platform object implements is the one that defines the behavior when indexing the object with an array index. Similarly for indexed property setters. This way, the definitions of these special operations from ancestor interfaces can be overridden.
A property name is an unforgeable property name on a given platform object if the object implements an interface that has an interface member with that identifier and that interface member is unforgeable on any of the interfaces that O implements.
Support for getters is handled in §3.9.1 [[GetOwnProperty]], and for setters in §3.9.3 [[DefineOwnProperty]] and §3.9.2 [[Set]].
3.9.1. [[GetOwnProperty]]
The internal [[GetOwnProperty]] method of every legacy platform object O must behave as follows when called with property name P:
-
Return LegacyPlatformObjectGetOwnProperty(O, P,
false ).
3.9.2. [[Set]]
The internal [[Set]] method of every legacy platform object O must behave as follows when called with property name P, value V, and ECMAScript language value Receiver:
-
If O and Receiver are the same object, then:
-
If O supports indexed properties, P is an array index property name, and O implements an interface with an indexed property setter, then:
-
Invoke the indexed property setter with P and V.
-
Return
true .
-
-
If O supports named properties, Type(P) is String, P is not an array index property name, and O implements an interface with a named property setter, then:
-
Invoke the named property setter with P and V.
-
Return
true .
-
-
-
Let ownDesc be LegacyPlatformObjectGetOwnProperty(O, P,
true ). -
Perform ? OrdinarySet(O, P, V, Receiver) from step 3 onwards with its internal "ownDesc" variable set to ownDesc.
3.9.3. [[DefineOwnProperty]]
When the internal [[DefineOwnProperty]] method of a legacy platform object O is called with property key P and Property Descriptor Desc, the following steps must be taken:
-
If O supports indexed properties and P is an array index property name, then:
-
If the result of calling IsDataDescriptor(Desc) is
false , then returnfalse . -
If O does not implement an interface with an indexed property setter, then return
false . -
Invoke the indexed property setter with P and Desc.[[Value]].
-
Return
true .
-
-
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:-
Let creating be true if P is not a supported property name, and false otherwise.
-
If O implements an interface with the [
OverrideBuiltins
] extended attribute or O does not have an own property named P, then:-
If creating is false and O does not implement an interface with a named property setter, then return
false . -
If O implements an interface with a named property setter, then:
-
If the result of calling IsDataDescriptor(Desc) is
false , then returnfalse . -
Invoke the named property setter with P and Desc.[[Value]].
-
Return
true .
-
-
-
-
If O does not implement an interface with the [
Global
] or [PrimaryGlobal
] extended attribute, then set Desc.[[Configurable]] totrue . -
Return OrdinaryDefineOwnProperty(O, P, Desc).
3.9.4. [[Delete]]
The internal [[Delete]] method of every legacy platform object O must behave as follows when called with property name P.
-
If O supports indexed properties and P is an array index property name, then:
-
Let index be the result of calling ToUint32(P).
-
If index is not a supported property index, then return
true . -
Return
false .
-
-
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:-
If O does not implement an interface with a named property deleter, then return
false . -
Let operation be the operation used to declare the named property deleter.
-
If operation was defined without an identifier, then:
-
Perform the steps listed in the interface description to delete an existing named property with P as the name.
-
If the steps indicated that the deletion failed, then return
false .
-
-
Otherwise, operation was defined with an identifier:
-
Perform the steps listed in the description of operation with P as the only argument value.
-
If operation was declared with a return type of
boolean
and the steps returnedfalse , then returnfalse .
-
-
Return
true .
-
-
If O has an own property with name P, then:
-
If the property is not configurable, then return
false . -
Otherwise, remove the property from O.
-
-
Return
true .
3.9.5. [[Call]]
The internal [[Call]] method of legacy platform object that implements an interface I must behave as follows, assuming arg0..n−1 is the list of argument values passed to [[Call]]:
-
If I has no legacy callers, throw a
TypeError . -
Initialize S to the effective overload set for legacy callers on I and with argument count n.
-
Let <operation, values> be the result of passing S and arg0..n−1 to the overload resolution algorithm.
-
Perform the actions listed in the description of the legacy caller operation with values as the argument values.
-
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 returnvoid
).
3.9.6. [[PreventExtensions]]
When the [[PreventExtensions]] internal method of a legacy platform object is called, the following steps are taken:
-
Return
false .
Note: this keeps legacy platform objects extensible by making [[PreventExtensions]] fail for them.
3.9.7. Property enumeration
This document does not define a complete property enumeration order for platform objects implementing interfaces (or for platform objects representing exceptions). However, for legacy platform objects, properties on the object must be enumerated in the following order:
-
If the object supports indexed properties, then the object’s supported property indices are enumerated first, in numerical order.
-
If the object supports named properties and doesn’t implement an interface with the [
LegacyUnenumerableNamedProperties
] extended attribute, then the object’s supported property names that are visible according to the named property visibility algorithm are enumerated next, in the order given in the definition of the set of supported property names. -
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.
3.9.8. Abstract operations
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:
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:
-
If P is not a supported property name of O, then return false.
-
If O has an own property named P, then return false.
Note: This will include cases in which O has unforgeable properties, because in practice those are always set up before objects have any supported property names, and once set up will make the corresponding named properties invisible.
-
If O implements an interface that has the [
OverrideBuiltins
] extended attribute, then return true. -
Initialize prototype to be the value of the internal [[Prototype]] property of O.
-
While prototype is not null:
-
If prototype is not a named properties object, and prototype has an own property named P, then return false.
-
Set prototype to be the value of the internal [[Prototype]] property of prototype.
-
-
Return true.
This should ensure that for objects with named properties, property resolution is done in the following order:
-
Indexed properties.
-
Own properties, including unforgeable attributes and operations.
-
Then, if [
OverrideBuiltins
]:-
Named properties.
-
Properties from the prototype chain.
-
-
Otherwise, if not [
OverrideBuiltins
]:-
Properties from the prototype chain.
-
Named properties.
-
To invoke an indexed property setter with property name P and ECMAScript value V, the following steps must be performed:
-
Let index be the result of calling ToUint32(P).
-
Let creating be true if index is not a supported property index, and false otherwise.
-
Let operation be the operation used to declare the indexed property setter.
-
Let T be the type of the second argument of operation.
-
Let value be the result of converting V to an IDL value of type T.
-
If operation was defined without an identifier, then:
-
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.
-
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.
-
-
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.
To invoke a named property setter with property name P and ECMAScript value V, the following steps must be performed:
-
Let creating be true if P is not a supported property name, and false otherwise.
-
Let operation be the operation used to declare the named property setter.
-
Let T be the type of the second argument of operation.
-
Let value be the result of converting V to an IDL value of type T.
-
If operation was defined without an identifier, then:
-
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.
-
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.
-
-
Otherwise, operation was defined with an identifier. Perform the steps listed in the description of operation with P and value as the two argument values.
The LegacyPlatformObjectGetOwnProperty abstract operation performs the following steps when called with an object O, a property name P, and a boolean ignoreNamedProps value:
-
If O supports indexed properties and P is an array index property name, then:
-
Let index be the result of calling ToUint32(P).
-
If index is a supported property index, then:
-
Let operation be the operation used to declare the indexed property getter.
-
Let value be an uninitialized variable.
-
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.
-
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.
-
Let desc be a newly created Property Descriptor with no fields.
-
Set desc.[[Value]] to the result of converting value to an ECMAScript value.
-
If O implements an interface with an indexed property setter, then set desc.[[Writable]] to
true , otherwise set it tofalse . -
Set desc.[[Enumerable]] and desc.[[Configurable]] to
true . -
Return desc.
-
-
Set ignoreNamedProps to true.
-
-
If O supports named properties, the result of running the named property visibility algorithm with property name P and object O is true, and ignoreNamedProps is false, then:
-
Let operation be the operation used to declare the named property getter.
-
Let value be an uninitialized variable.
-
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.
-
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.
-
Let desc be a newly created Property Descriptor with no fields.
-
Set desc.[[Value]] to the result of converting value to an ECMAScript value.
-
If O implements an interface with a named property setter, then set desc.[[Writable]] to
true , otherwise set it tofalse . -
If O implements an interface with the [
LegacyUnenumerableNamedProperties
] extended attribute, then set desc.[[Enumerable]] tofalse , otherwise set it totrue . -
Set desc.[[Configurable]] to
true . -
Return desc.
-
-
Return OrdinaryGetOwnProperty(O, P).
3.10. User objects implementing callback interfaces
As described in §2.10 Objects implementing interfaces, 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 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 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.
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.
A single operation callback interface is a callback interface that:
-
is not declared to inherit from another interface,
-
has no attributes, and
-
has one or more regular operations that all have the same identifier, and no others.
A Web IDL arguments list is a list of values each of which is either an IDL value or the special value “missing”, which represents a missing optional argument.
-
Let esArgs be an empty list.
-
Let i be 0.
-
Let count be 0.
-
While i < args’s size:
-
If args[i] is the special value “missing”, then append
undefined to esArgs. -
Otherwise, args[i] is an IDL value:
-
Let convertResult be the result of converting args[i] to an ECMAScript value. Rethrow any exceptions.
-
Append convertResult to esArgs.
-
Set count to i + 1.
-
-
Set i to i + 1.
-
-
Truncate esArgs to contain count items.
-
Return esArgs.
To call a user object’s operation, given a callback interface type value value, sometimes-optional operation name opName, Web IDL arguments list args, and optional callback this value thisArg, perform the following steps. These steps will either return an IDL value or throw an exception.
-
Let completion be an uninitialized variable.
-
If thisArg was not given, let thisArg be
undefined . -
Let O be the ECMAScript object corresponding to value.
-
Let realm be O’s associated Realm.
-
Let relevant settings be realm’s settings object.
-
Let stored settings be value’s callback context.
-
Prepare to run script with relevant settings.
-
Prepare to run a callback with stored settings.
-
Determine the implementation of the operation, X:
-
If value’s interface is a single operation callback interface and ! IsCallable(O) is true, then set X to O.
-
Otherwise, opName must be supplied:
-
-
If ! IsCallable(X) is
false , then set completion to a new Completion{[[Type]]: throw, [[Value]]: a newly createdTypeError object, [[Target]]: empty}, and jump to the step labeled return. -
If value’s interface is not a single operation callback interface, or if ! IsCallable(O) is
false , set thisArg to O (overriding the provided value). -
Let esArgs be the result of converting args to an ECMAScript arguments list. If this throws an exception, set completion to the completion value representing the thrown exception and jump to the step labeled return.
-
Let callResult be Call(X, thisArg, esArgs).
-
If callResult is an abrupt completion, set completion to callResult and jump to the step labeled return.
-
Set completion to the result of converting callResult.[[Value]] to an IDL value of the same type as the operation’s return type.
-
Return: at this point completion will be set to an ECMAScript completion value.
-
Clean up after running a callback with stored settings.
-
Clean up after running script with relevant settings.
-
If completion is a normal completion, return completion.
-
If completion is an abrupt completion and the operation has a return type that is not a promise type, return completion.
-
Let reject be the initial value of %Promise%.reject.
-
Let rejectedPromise be the result of calling reject with %Promise% as the
this value and completion.[[Value]] as the single argument value. -
Return the result of converting rejectedPromise to the operation’s return type.
-
To get a user object’s attribute value, given a callback interface type value object and attribute name attributeName, perform the following steps. These steps will either return an IDL value or throw an exception.
-
Let completion be an uninitialized variable.
-
Let O be the ECMAScript object corresponding to object.
-
Let realm be O’s associated Realm.
-
Let relevant settings be realm’s settings object.
-
Let stored settings be object’s callback context.
-
Prepare to run script with relevant settings.
-
Prepare to run a callback with stored settings.
-
Let getResult be Get(O, attributeName).
-
If getResult is an abrupt completion, set completion to getResult and jump to the step labeled return.
-
Set completion to the result of converting getResult.[[Value]] to an IDL value of the same type as the attribute’s type.
-
Return: at this point completion will be set to an ECMAScript completion value.
-
Clean up after running a callback with stored settings.
-
Clean up after running script with relevant settings.
-
If completion is a normal completion, return completion.
-
If completion is an abrupt completion and the attribute’s type is not a promise type, return completion.
-
Let reject be the initial value of %Promise%.reject.
-
Let rejectedPromise be the result of calling reject with %Promise% as the
this value and completion.[[Value]] as the single argument value. -
Return the result of converting rejectedPromise to the attribute’s type.
-
To set a user object’s attribute value, given a callback interface type value object, attribute name attributeName, and IDL value value, perform the following steps. These steps will not return anything, but could throw an exception.
-
Let completion be an uninitialized variable.
-
Let O be the ECMAScript object corresponding to object.
-
Let realm be O’s associated Realm.
-
Let relevant settings be realm’s settings object.
-
Let stored settings be object’s callback context.
-
Prepare to run script with relevant settings.
-
Prepare to run a callback with stored settings.
-
Let convertResult be the result of converting value to an ECMAScript value.
-
If convertResult is an abrupt completion, set completion to convertResult and jump to the step labeled return.
-
Set completion to Set(O, attributeName, convertResult.[[Value]],
true ). -
Return: at this point completion will be set to an ECMAScript completion value, which is either an abrupt completion or a normal completion for the value
true (as returned by Set).-
Clean up after running a callback with stored settings.
-
Clean up after running script with relevant settings.
-
If completion is an abrupt completion, return completion.
-
Return NormalCompletion(
void
).
-
3.11. 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).
To invoke a callback function type value callable with a Web IDL arguments list args and an optional callback this value thisArg, perform the following steps. These steps will either return an IDL value or throw an exception.
-
Let completion be an uninitialized variable.
-
If thisArg was not given, let thisArg be
undefined . -
Let F be the ECMAScript object corresponding to callable.
-
If ! IsCallable(F) is
false :-
If the callback function’s return type is
void
, return.Note: This is only possible when the callback function came from an attribute marked with [
TreatNonObjectAsNull
]. -
Return the result of converting
undefined to the callback function’s return type.
-
-
Let realm be F’s associated Realm.
-
Let relevant settings be realm’s settings object.
-
Let stored settings be callable’s callback context.
-
Prepare to run script with relevant settings.
-
Prepare to run a callback with stored settings.
-
Let esArgs be the result of converting args to an ECMAScript arguments list. If this throws an exception, set completion to the completion value representing the thrown exception and jump to the step labeled return.
-
Let callResult be Call(F, thisArg, esArgs).
-
If callResult is an abrupt completion, set completion to callResult and jump to the step labeled return.
-
Set completion to the result of converting callResult.[[Value]] to an IDL value of the same type as the operation’s return type.
-
Return: at this point completion will be set to an ECMAScript completion value.
-
Clean up after running a callback with stored settings.
-
Clean up after running script with relevant settings.
-
If completion is a normal completion, return completion.
-
If completion is an abrupt completion and the callback function has a return type that is not a promise type, return completion.
-
Let reject be the initial value of %Promise%.reject.
-
Let rejectedPromise be the result of calling reject with %Promise% as the
this value and completion.[[Value]] as the single argument value. -
Return the result of converting rejectedPromise to the callback function’s return type.
-
Some callback functions are instead used as constructors. Such callback functions must not have a return type that is a promise type.
To construct a callback function type value callable with a Web IDL arguments list args, perform the following steps. These steps will either return an IDL value or throw an exception.
-
Let completion be an uninitialized variable.
-
Let F be the ECMAScript object corresponding to callable.
-
If ! IsConstructor(F) is
false , throw aTypeError exception. -
Let realm be F’s associated Realm.
-
Let relevant settings be realm’s settings object.
-
Let stored settings be callable’s callback context.
-
Prepare to run script with relevant settings.
-
Prepare to run a callback with stored settings.
-
Let esArgs be the result of converting args to an ECMAScript arguments list. If this throws an exception, set completion to the completion value representing the thrown exception and jump to the step labeled return.
-
Let callResult be Construct(F, esArgs).
-
If callResult is an abrupt completion, set completion to callResult and jump to the step labeled return.
-
Set completion to the result of converting callResult.[[Value]] to an IDL value of the same type as the operation’s return type.
-
Return: at this point completion will be set to an ECMAScript completion value.
-
Clean up after running a callback with stored settings.
-
Clean up after running script with relevant settings.
-
Return completion.
-
3.12. Namespaces
For every namespace that 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 namespace, and its value is an object called the namespace object.
The property has the attributes
{ [[Writable]]:
3.12.1. Namespace object
The namespace object for a given namespace namespace and Realm realm is created as follows:
-
Let namespaceObject be ! ObjectCreate(the %ObjectPrototype% of realm).
-
For each exposed regular attribute attr that is a namespace member of this namespace,
-
Let F be the result of creating an attribute getter given attr, namespace, and realm.
-
Let newDesc be the PropertyDescriptor{[[Get]]: F, [[Enumerable]]:
true , [[Configurable]]:true }. -
Perform ! DefinePropertyOrThrow(namespaceObject, attr’s identifier, newDesc).
-
-
For each exposed regular operation op that is a namespace member of this namespace,
-
Let F be the result of creating an operation function given op, namespace, and realm.
-
Perform ! CreateDataProperty(namespaceObject, op’s identifier, F).
-
3.13. Exceptions
3.13.1. DOMException
custom bindings
In the ECMAScript binding, the DOMException
type has some additional requirements:
-
Unlike normal interface types, the interface prototype object for
DOMException
must have as its [[Prototype]] the intrinsic object %ErrorPrototype%. -
If an implementation gives native
Error objects special powers or nonstandard properties (such as astack
property), it should also expose those onDOMException
instances.
3.13.2. Exception objects
Simple exceptions are represented by native ECMAScript objects of the corresponding type.
A DOMException
is represented by a platform object that implements the DOMException
interface.
3.13.3. Creating and throwing exceptions
To create a simple exception or DOMException
E, with a string giving the error name N for the DOMException
case and optionally a string giving a user
agent-defined message M:
-
If M was not specified, let M be
undefined . -
Let args be a list of ECMAScript values determined based on the type of E:
- E is
DOMException
-
args is «M, N».
- E is a simple exception
-
args is «M».
- E is
-
Let X be an object determined based on the type of E:
- E is
DOMException
-
X is the
DOMException
interface object from the current Realm. - E is a simple exception
-
X is the constructor for the corresponding ECMAScript error from the current Realm.
- E is
To throw a simple exception or DOMException
, with a string giving the error name for the DOMException
case and optionally a string giving a user
agent-defined message:
-
Let O be the result of creating an exception with the same arguments.
-
Throw O.
The above algorithms restrict objects representing exceptions propagating
out of a
interface MathUtils { // If x is negative, throws a "NotSupportedError" DOMException. double computeSquareRoot(double x); };
If we apply computeSquareRoot
to a MathUtils
object from a different Realm, then the exception thrown will be from the Realm of the
method, not the object it is applied to:
const myMU = window.getMathUtils(); // A MathUtils object from this Realm const otherMU = otherWindow.getMathUtils(); // A MathUtils object from a different Realm myMU instanceof Object; // Evaluates to true. otherMU instanceof Object; // Evaluates to false. otherMU instanceof otherWindow.Object; // Evaluates to true. try { otherMU.doComputation.call(myMU, -1); } catch (e) { console.assert(!(e instanceof DOMException)); console.assert(e instanceof otherWindow.DOMException); }
3.13.4. Handling exceptions
None of the algorithms or processing requirements in the
ECMAScript language binding catch ECMAScript exceptions. Whenever
an ECMAScript
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.
interface Dahut { attribute DOMString type; }; interface ExceptionThrower { // This attribute always throws a NotSupportedError and never returns a value. attribute long valueOf; };
Assuming an ECMAScript implementation supporting this interface, the following code demonstrates how exceptions are handled:
var d = getDahut(); // Obtain an instance of Dahut. var et = getExceptionThrower(); // Obtain an instance of ExceptionThrower. try { d.type = { toString: function() { throw "abc"; } }; } catch (e) { // The string "abc" is caught here, since as part of the conversion // from the native object to a string, the anonymous function // was invoked, and none of the [[DefaultValue]], ToPrimitive or // ToString algorithms are defined to catch the exception. } try { d.type = { toString: { } }; } catch (e) { // An exception is caught here, since an attempt is made to invoke // [[Call]] on the native object that is the value of toString // property. } d.type = et; // An uncaught "NotSupportedError" DOMException is thrown here, since the // [[DefaultValue]] algorithm attempts to get the value of the // "valueOf" property on the ExceptionThrower object. The exception // propagates out of this block of code.
4. Common definitions
This section specifies some common definitions that all conforming implementations must support.
4.1. ArrayBufferView
typedef (Int8Array or Int16Array or Int32Array or Uint8Array or Uint16Array or Uint32Array or Uint8ClampedArray or Float32Array or Float64Array or DataView) ArrayBufferView;
The ArrayBufferView
typedef is used to represent
objects that provide a view on to an ArrayBuffer
.
4.2. BufferSource
typedef (ArrayBufferView or ArrayBuffer) BufferSource;
The BufferSource
typedef is used to represent objects
that are either themselves an ArrayBuffer
or which
provide a view on to an ArrayBuffer
.
4.3. DOMException
The DOMException
type is an interface type defined by the following IDL
fragment:
[ Exposed=(Window,Worker), Constructor(optional DOMStringmessage
= "", optional DOMStringname
= "Error") ] interface DOMException { // but see below note about ECMAScript binding readonly attribute DOMString name; readonly attribute DOMString message; readonly attribute unsigned short code; const unsigned short INDEX_SIZE_ERR = 1; const unsigned short DOMSTRING_SIZE_ERR = 2; const unsigned short HIERARCHY_REQUEST_ERR = 3; const unsigned short WRONG_DOCUMENT_ERR = 4; const unsigned short INVALID_CHARACTER_ERR = 5; const unsigned short NO_DATA_ALLOWED_ERR = 6; const unsigned short NO_MODIFICATION_ALLOWED_ERR = 7; const unsigned short NOT_FOUND_ERR = 8; const unsigned short NOT_SUPPORTED_ERR = 9; const unsigned short INUSE_ATTRIBUTE_ERR = 10; const unsigned short INVALID_STATE_ERR = 11; const unsigned short SYNTAX_ERR = 12; const unsigned short INVALID_MODIFICATION_ERR = 13; const unsigned short NAMESPACE_ERR = 14; const unsigned short INVALID_ACCESS_ERR = 15; const unsigned short VALIDATION_ERR = 16; const unsigned short TYPE_MISMATCH_ERR = 17; const unsigned short SECURITY_ERR = 18; const unsigned short NETWORK_ERR = 19; const unsigned short ABORT_ERR = 20; const unsigned short URL_MISMATCH_ERR = 21; const unsigned short QUOTA_EXCEEDED_ERR = 22; const unsigned short TIMEOUT_ERR = 23; const unsigned short INVALID_NODE_TYPE_ERR = 24; const unsigned short DATA_CLONE_ERR = 25; };
Note: as discussed in §3.13.1 DOMException custom bindings, the ECMAScript binding imposes additional requirements beyond the normal ones for interface types.
Each DOMException
object has an associated name and message, both JavaScript strings.
The
constructor, when invoked, must run these steps:DOMException(message, name)
-
Let e be a new
DOMException
object. -
Set e’s name to name.
-
Set e’s message to message.
-
Return e.
The
attribute’s getter must return this name
DOMException
object’s name.
The
attribute’s getter must return this message
DOMException
object’s message.
The
attribute’s getter must return the
legacy code indicated in the error names table for this code
DOMException
object’s name, or 0 if no such entry exists in the table.
4.4. DOMTimeStamp
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.
4.5. Function
callback Function = any (any... arguments
);
The Function
callback function type is used for representing function values with no restriction on what arguments
are passed to it or what kind of value is returned from it.
4.6. VoidFunction
callback VoidFunction = void ();
The VoidFunction
callback function type is used for representing function values that take no arguments and do not
return any value.
5. 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 Platform Working Group, for possible inclusion in a future version of this document.
Extensions to any other aspect of the IDL language are strongly discouraged.
6. Referencing this specification
This section is informative.
It is expected that other specifications that define Web platform interfaces using one or more IDL fragments will reference this specification. It is suggested that those specifications include a sentence such as the following, to indicate that the IDL is to be interpreted as described in this specification:
The IDL fragment in Appendix A of this specification must, in conjunction with the IDL fragments defined in this specification’s normative references, be interpreted as required for conforming sets of IDL fragments, as described in the “Web IDL” specification. [WEBIDL]
In addition, it is suggested that the conformance class for user agents in referencing specifications be linked to the conforming implementation class from this specification:
A conforming FooML user agent must also be a conforming implementation of the IDL fragment in Appendix A of this specification, as described in the “Web IDL” specification. [WEBIDL]
7. 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, Chris Dumez, 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, Takeshi Kurosawa, Yves Lafon, Travis Leithead, Jim Ley, Kevin Lindsey, Jens Lindström, Peter Linss, 呂康豪 (Kang-Hao Lu), Kyle Machulis, 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, Jeffrey Yasskin and Collin Xu.
Special thanks also go to Sam Weinig for maintaining this document while the editor was unavailable to do so.
IDL grammar
This section defines an LL(1) grammar whose start symbol,
Each production in the grammar has on its right hand side either a non-zero sequence of terminal and non-terminal symbols, or an epsilon (ε) which indicates no symbols. Symbols that begin with an uppercase letter are non-terminal symbols. Symbols in monospaced fonts are terminal symbols. Symbols in sans-serif font that begin with a lowercase letter are terminal symbols that are matched by the regular expressions (using Perl 5 regular expression syntax [PERLRE]) as follows:
=
| /-?([1-9][0-9]*|0[Xx][0-9A-Fa-f]+|0[0-7]*)/
| |
=
| /-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+)/
| |
=
| /_?[A-Za-z][0-9A-Z_a-z-]*/
| |
=
| /"[^"]*"/
| |
=
| /[\t\n\r ]+/
| |
=
| /\/\/.*|\/\*(.|\n)*?\*\//
| |
=
| /[^\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
The IDL syntax is case sensitive, both for the quoted terminal symbols
used in the grammar and the values used for constructor
] will not be recognized as
the [Constructor
]
extended attribute.
Implicitly, any number of
The following LL(1) grammar, starting with
Note: The
While the
Document conventions
The following typographic conventions are used in this document:
-
Defining instances of terms: example term
-
Links to terms defined in this document or elsewhere: example term
-
Grammar terminals:
sometoken -
Grammar non-terminals:
ExampleGrammarNonTerminal -
Grammar symbols:
identifier -
IDL 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... */ };
(Specific parts of the syntax discussed in surrounding prose are highlighted.)
-
IDL grammar snippets:
ExampleGrammarNonTerminal : OtherNonTerminal "sometoken" other AnotherNonTerminal ε // nothing
-
Non-normative notes:
Note: This is a note.
-
Non-normative examples:
-
Normative warnings:
This is a warning.
-
Code blocks:
// This is an IDL code block. interface Example { attribute long something; };
// This is an ECMAScript code block. window.onload = function() { window.alert("loaded"); };
The following conventions are used in the algorithms in this document:
-
Algorithms use the conventions of the ECMAScript specification, including the ! and ? notation for unwrapping completion records.
-
Algorithms sometimes treat returning/throwing values and returning completion records interchangeably. That is, an algorithm that uses return/throw terminology may be treated as returning a completion record, while one that returns a completion record may be treated as returning a value or throwing an exception.
-
Completion records are extended by allowing them to contain values that are not ECMAScript values, such as Web IDL values.
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].
Requirements phrased in the imperative as part of algorithms (such as “strip any leading space characters” or “return false and abort these steps”) are to be interpreted with the meaning of the key word (“must”, “should”, “may”, etc) used in introducing the algorithm.
Conformance requirements phrased as algorithms or specific steps can be implemented in any manner, so long as the end result is equivalent. In particular, the algorithms defined in this specification are intended to be easy to understand and are not intended to be performant. Implementers are encouraged to optimize.
The following conformance classes are defined by this specification:
- conforming set of IDL fragments
-
A set of IDL fragments is considered to be a conforming set of IDL fragments if, taken together, they satisfy all of the must-, required- and shall-level criteria in this specification that apply to IDL fragments.
- conforming implementation
-
A user agent is considered to be a conforming implementation relative to a conforming set of IDL fragments if it satisfies all of the must-, required- and shall-level criteria in this specification that apply to implementations for all language bindings that the user agent supports.
- conforming ECMAScript implementation
-
A user agent is considered to be a conforming ECMAScript implementation relative to a conforming set of IDL fragments if it satisfies all of the must-, required- and shall-level criteria in this specification that apply to implementations for the ECMAScript language binding.