潇洒的野马 · 南阳市积极开展义务植树活动-南阳市退役军人事务局· 2 周前 · |
烦恼的哑铃 · IEEE Fellows Program ...· 3 月前 · |
沉稳的汉堡包 · CyweeMotion x MIJIA | ...· 4 月前 · |
任性的蘑菇 · 彻底搞懂Kotlin的高阶函数、匿名函数、L ...· 6 月前 · |
儒雅的松鼠 · ant design ...· 6 月前 · |
This standard defines an interface definition language, Web IDL, that can be used to describe interfaces that are intended to be implemented in web browsers.
DOMException
error names
DOMException
derived interfaces
defineProperty
deleteProperty
get
getOwnPropertyDescriptor
has
ownKeys
preventExtensions
set
DOMException
custom bindings
This section is informative.
This standard defines an interface definition language, Web IDL, that can be used to describe interfaces that are intended to be implemented in web browsers. Web IDL is an IDL variant with a number of features that allow the behavior of common script objects in the web platform to be specified more readily. How interfaces described with Web IDL correspond to constructs within JavaScript execution environments is also detailed here.
Concretely, Web IDL provides a syntax for specifying the surface APIs of web platform objects, as well as JavaScript bindings that detail how those APIs manifest as JavaScript constructs. This ensures common tasks, such as installing global properties, processing numeric inputs, or exposing iteration behavior, remain uniform across web platform specifications: such specifications describe their interfaces using Web IDL, and then use prose to specify API-specific details.
The term "JavaScript" is used to refer to ECMA-262, rather than the official term ECMAScript, since the term JavaScript is more widely known.
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 , interface mixins , partial mixin definitions , callback functions , callback interfaces , namespaces , partial namespace definitions , dictionaries , partial dictionary definitions , typedefs and includes statements . These are all defined in the following sections.
Each
definition
(matching
[extended_attributes ]interface identifier { /* interface_members... */Definitions ::ExtendedAttributeList Definition Definitions Definition ::CallbackOrInterfaceOrMixin Namespace Partial Dictionary Typedef IncludesStatement The following is an example of an IDL fragment.
[Exposed =Window ]interface Paint { }; [Exposed =Window ]interface SolidColor :Paint {attribute double red ;attribute double green ;attribute double blue ; [Exposed =Window ]interface Pattern :Paint {attribute DOMString imageURL ; [Exposed =Window ]interface GraphicalWindow {constructor ();readonly attribute unsigned long width ;readonly attribute unsigned long height ;attribute Paint currentPaint ;undefined drawRectangle (double x ,double y ,double width ,double height );undefined drawText (double x ,double y ,DOMString text );Here, four interfaces are being defined. The
GraphicalWindow
interface has two read only attributes, one writable attribute, and two operations defined on it. Objects that implement theGraphicalWindow
interface will expose these attributes and operations in a manner appropriate to the particular language being used.In JavaScript, the attributes on the IDL interfaces will be exposed as accessor properties and the operations as data properties whose value is a built-in function object on a prototype object for all
GraphicalWindow
objects; each JavaScript object that implementsGraphicalWindow
will have that prototype object in its prototype chain.The constructor operation that appears on
GraphicalWindow
causes a constructor to exist in JavaScript implementations, so that callingnew GraphicalWindow()
would return a new object that implemented the interface.All interfaces have the [
Exposed
] extended attribute, which ensures the interfaces are only available in realms whose global object is aWindow
object.2.1. Names
Every interface, partial interface definition, namespace, partial namespace definition, dictionary, partial dictionary definition, enumeration, callback function, callback interface and typedef (together called named definitions) and every constant, attribute, and dictionary member has an identifier, as do some operations. The identifier is determined by an
identifier token somewhere in the declaration:For named definitions, the
identifier token that appears directly after 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... */);callback interface callback_interface_identifier { /* interface_members... */ };For attributes, typedefs and dictionary members, the final
identifier token before the semicolon at the end of the declaration determines the identifier.[extended_attributes ]interface identifier {attribute type attribute_identifier ;typedef type typedef_identifier ;dictionary identifier {type dictionary_member_identifier ;For constants, the
identifier token before the equals sign determines the identifier.const type constant_identifier = 42;For operations, the
identifier token that appears after the return type but before the opening parenthesis (that is, one that is matched as part of theOptionalOperationName 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
identifier token with any leading U+005F (_) removed.Note: A leading U+005F (_) is used to escape an identifier from looking like a reserved word so that, for example, an interface named "
interface
" can be defined. The leading U+005F (_) is dropped to unescape the identifier.Operation arguments can take a slightly wider set of identifiers. In an operation declaration, the identifier of an argument is specified immediately after its type and is given by either an
identifier token or by one of the keywords that match theArgumentNameKeyword symbol. If one of these keywords is used, it need not be escaped with a leading underscore.interface interface_identifier {return_type operation_identifier (argument_type argument_identifier /* , ... */);ArgumentNameKeyword ::async attribute callback const constructor deleter dictionary getter includes inherit interface iterable maplike mixin namespace partial readonly required setlike setter static stringifier typedef unrestricted If an
identifier token is used, then the identifier of the operation argument is the value of that token with any leading U+005F (_) removed. If instead one of theArgumentNameKeyword keyword token is used, then the identifier of the operation argument is simply that token.The identifier of any of the abovementioned IDL constructs (except operation arguments) must not be "
constructor
", "toString
", or begin with a U+005F (_). These are known as reserved identifiers.Although the "
toJSON
" identifier is not a reserved identifier, it must only be used for regular operations that convert objects to JSON types, as described in § 2.5.3.1 toJSON.Note: Further restrictions on identifier names for particular constructs can be made in later sections.
Within the set of IDL fragments that a given implementation supports, the identifier of every interface, namespace, dictionary, enumeration, callback function, callback interface and typedef must not be the same as the identifier of any other interface, namespace, dictionary, enumeration, callback function, callback interface or typedef.
Within an IDL fragment, a reference to a definition need not appear after the declaration of the referenced definition. References can also be made across IDL fragments.
Therefore, the following IDL fragment is valid:
[Exposed =Window ]interface B :A {undefined f (SequenceOfLongs x ); [Exposed =Window ]interface A {typedef sequence <long >SequenceOfLongs ;The following IDL fragment demonstrates how identifiers are given to definitions and interface members.
// Typedef identifier: "number"typedef double number ; // Interface identifier: "System" [Exposed =Window ]interface System { // Operation identifier: "createObject" // Operation argument identifier: "interface"object createObject (DOMString _interface ); // Operation argument identifier: "interface"sequence <object >getObjects (DOMString interface ); // Operation has no identifier; it declares a getter.getter DOMString (DOMString keyName ); // Interface identifier: "TextField" [Exposed =Window ]interface TextField { // Attribute identifier: "const"attribute boolean _const ; // Attribute identifier: "value"attribute DOMString ?_value ;Note that while the second attribute on the
TextField
interface need not have been escaped with an underscore (because "value
" is not a keyword in the IDL grammar), it is still unescaped to obtain the attribute’s identifier.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 InterfaceRest ) that declares some state and behavior that an object implementing that interface will expose.[extended_attributes ]interface identifier { /* interface_members... */An interface is a specification of a set of interface members (matching
InterfaceMembers ). These are the members that appear between the braces in the interface declaration.Interfaces in Web IDL describe how objects that implement the interface behave. In bindings for object oriented languages, it is expected that an object that implements a particular IDL interface provides ways to inspect and modify the object’s state and to invoke the behavior described by the interface.
An interface can be defined to inherit from another interface. If the identifier of the interface is followed by a U+003A (:) and an identifier, then that identifier identifies the inherited interface. An object that implements an interface that inherits from another also implements that inherited interface. The object therefore will also have members that correspond to the interface members from the inherited interface.
interface identifier :identifier_of_inherited_interface { /* interface_members... */The order that members appear in has significance for property enumeration in the JavaScript binding.
Interfaces may specify an interface member that has the same name as one from an inherited interface. Objects that implement the derived interface will expose the member on the derived interface. It is language binding specific whether the overridden member can be accessed on the object.
Consider the following two interfaces.
[Exposed =Window ]interface A {undefined f ();undefined g (); [Exposed =Window ]interface B :A {undefined f ();undefined g (DOMString x );In the JavaScript language binding, an instance of
B
will have a prototype chain that looks like the following:[Object.prototype: the Object prototype object] [A.prototype: interface prototype object for A] [B.prototype: interface prototype object for B] [instanceOfB]Calling
instanceOfB.f()
in JavaScript will invoke the f defined onB
. However, the f fromA
can still be invoked on an object that implementsB
by callingA.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.
The list of inclusive inherited interfaces of an interface I is defined as follows:Let result be « ».
Let interface be I.
While interface is not null:
Append interface to result.
Set interface to the interface that I inherits from, if any, and null otherwise.
Return result.
Note that general multiple inheritance of interfaces is not supported, and objects also cannot implement arbitrary sets of interfaces. Objects can be defined to implement a single given interface A, which means that it also implements all of A’s inherited interfaces. In addition, an includes statement can be used to define that objects implementing an interface A will always also include the members of the interface mixins A includes.
Each interface member can be preceded by a list of extended attributes (matching
ExtendedAttributeList ), which can control how the interface member will be handled in language bindings.[extended_attributes ]interface identifier { [extended_attributes ]const type constant_identifier = 42; [extended_attributes ]attribute type identifier ; [extended_attributes ]return_type identifier (/* arguments... */);The IDL for interfaces can be split into multiple parts by using partial interface definitions (matching
partial interface PartialInterfaceRest ). The identifier of a partial interface definition must be the same as the identifier of an interface definition. All of the members that appear on each of the partial interfaces are considered to be members of the interface itself.interface SomeInterface { /* interface_members... */partial interface SomeInterface { /* interface_members... */Note: Partial interface definitions are intended for use as a specification editorial aide, allowing the definition of an interface to be separated over more than one section of the document, and sometimes multiple documents.
The order of appearance of an interface definition and any of its partial interface definitions does not matter.
Note: A partial interface definition cannot specify that the interface inherits from another interface. Inheritance is to be specified on the original interface definition.
The relevant language binding determines how interfaces correspond to constructs in the language.
The following extended attributes are applicable to interfaces: [
CrossOriginIsolated
], [Exposed
], [Global
], [LegacyFactoryFunction
], [LegacyNoInterfaceObject
], [LegacyOverrideBuiltIns
], [LegacyWindowAlias
], and [SecureContext
].The following extended attributes are applicable to partial interfaces: [
CrossOriginIsolated
], [Exposed
], [LegacyOverrideBuiltIns
], and [SecureContext
].Interfaces must be annotated with an [
Exposed
] extended attribute.The qualified name of an interface interface is defined as follows:
Let identifier be the identifier of interface.
If interface has a [
LegacyNamespace
] extended attribute, then:Let namespace be the identifier argument of the [
LegacyNamespace
] extended attribute.Return the concatenation of « namespace, identifier » with separator U+002E (.).
Return identifier.
CallbackOrInterfaceOrMixin ::callback CallbackRestOrInterface interface InterfaceOrMixin InterfaceOrMixin ::InterfaceRest MixinRest InterfaceRest ::identifier Inheritance { InterfaceMembers } ; Partial ::partial PartialDefinition PartialDefinition ::interface PartialInterfaceOrPartialMixin PartialDictionary Namespace PartialInterfaceOrPartialMixin ::PartialInterfaceRest MixinRest PartialInterfaceRest ::identifier { PartialInterfaceMembers } ; InterfaceMembers ::ExtendedAttributeList InterfaceMember InterfaceMembers InterfaceMember ::PartialInterfaceMember Constructor PartialInterfaceMembers ::ExtendedAttributeList PartialInterfaceMember PartialInterfaceMembers PartialInterfaceMember ::Const Operation Stringifier StaticMember Iterable AsyncIterable ReadOnlyMember ReadWriteAttribute ReadWriteMaplike ReadWriteSetlike InheritAttribute Inheritance ::: identifier The following IDL fragment demonstrates the definition of two mutually referential interfaces. Both
Human
andDog
inherit fromAnimal
. Objects that implement either of those two interfaces will thus have aname
attribute.[Exposed =Window ]interface Animal {attribute DOMString name ; [Exposed =Window ]interface Human :Animal {attribute Dog ?pet ; [Exposed =Window ]interface Dog :Animal {attribute Human ?owner ;The following IDL fragment defines simplified versions of a DOM interfaces and a callback interface.
[Exposed =Window ]interface Node {readonly attribute DOMString nodeName ;readonly attribute Node ?parentNode ;Node appendChild (Node newChild );undefined addEventListener (DOMString type ,EventListener listener );callback interface EventListener {undefined handleEvent (Event event );Plain objects can implement a callback interface like
EventListener
:var node= getNode(); // Obtain an instance of Node. var listener= { handleEvent: function ( event) { // ... node. addEventListener( "click" , listener); // This works. node. addEventListener( "click" , function () { ... }); // As does this. It is not possible for such an object to implement an interface like
Node
, however:var node= getNode(); // Obtain an instance of Node. var newNode= { nodeName: "span" , parentNode: null , appendChild: function ( newchild) { // ... addEventListener: function ( type, listener) { // ... node. appendChild( newNode); // This will throw a TypeError exception. 2.3. Interface mixins
An interface mixin is a definition (matching
interface MixinRest) that declares state and behavior that can be included by one or more interfaces, and that are exposed by objects that implement an interface that includes the interface mixin. interface mixin identifier { /* mixin_members... */Note: Interface mixins, much like partial interfaces, are intended for use as a specification editorial aide, allowing a coherent set of functionalities to be grouped together, and included in multiple interfaces, possibly across documents. They are not meant to be exposed through language bindings. Guidance on when to choose partial interfaces, interface mixins, or partial interface mixins can be found in § 2.3.1 Using mixins and partials.
An interface mixin is a specification of a set of interface mixin members (matching
MixinMembers ), which are the constants, regular operations, regular attributes, and stringifiers that appear between the braces in the interface mixin declaration.These constants, regular operations, regular attributes, and stringifiers describe the behaviors that can be implemented by an object, as if they were specified on the interface that includes them.
Static attributes, static operations, special operations, and iterable, asynchronously iterable, maplike, and setlike declarations cannot appear in interface mixin declarations.
As with interfaces, the IDL for interface mixins can be split into multiple parts by using partial interface mixin definitions (matching
partial interface MixinRest ). The identifier of a partial interface mixin definition must be the same as the identifier of an interface mixin definition. All of the members that appear on each of the partial interface mixin definitions are considered to be members of the interface mixin itself, and—by extension—of the interfaces that include the interface mixin.interface mixin SomeMixin { /* mixin_members... */partial interface mixin SomeMixin { /* mixin_members... */The order that members appear in has significance for property enumeration in the JavaScript binding.
Note that unlike interfaces or dictionaries, interface mixins do not create types.
Of the extended attributes defined in this specification, only the [
CrossOriginIsolated
], [Exposed
], and [SecureContext
] extended attributes are applicable to interface mixins.An includes statement is a definition (matching
IncludesStatement ) used to declare that all objects implementing an interface I (identified by the first identifier) must additionally include the members of interface mixin M (identified by the second identifier). Interface I is said to include interface mixin M.interface_identifier includes mixin_identifier ;The first identifier must reference a interface I. The second identifier must reference an interface mixin M.
Each member of M is considered to be a member of each interface I, J, K, … that includes M, as if a copy of each member had been made. So for a given member m of M, interface I is considered to have a member mI, interface J is considered to have a member mJ, interface K is considered to have a member mK, and so on. The host interfaces of mI, mJ, and mK, are I, J, and K respectively.
Note: In JavaScript, this implies that each regular operation declared as a member of interface mixin M, and exposed as a data property with a built-in function object value, is a distinct built-in function object in each interface prototype object whose associated interface includes M. Similarly, for attributes, each copy of the accessor property has distinct built-in function objects for its getters and setters.
The order of appearance of includes statements affects the order in which interface mixin are included by their host interface.
Member order isn’t clearly specified, in particular when interface mixins are defined in separate documents. It is discussed in issue #432.
No extended attributes defined in this specification are applicable to includes statements.
The following IDL fragment defines an interface,
Entry
, and an interface mixin,Observable
. The includes statement specifies thatObservable
’s members are always included on objects implementingEntry
.interface Entry {readonly attribute unsigned short entryType ; // ...interface mixin Observable {undefined addEventListener (DOMString type ,EventListener listener ,boolean useCapture ); // ...Entry includes Observable ;A JavaScript implementation would thus have an
addEventListener
property in the prototype chain of everyEntry
:var e= getEntry(); // Obtain an instance of Entry. typeof e. addEventListener; // Evaluates to "function". CallbackOrInterfaceOrMixin ::callback CallbackRestOrInterface interface InterfaceOrMixin InterfaceOrMixin ::InterfaceRest MixinRest Partial ::partial PartialDefinition PartialDefinition ::interface PartialInterfaceOrPartialMixin PartialDictionary Namespace MixinRest ::mixin identifier { MixinMembers } ; MixinMembers ::ExtendedAttributeList MixinMember MixinMembers MixinMember ::Const RegularOperation Stringifier OptionalReadOnly AttributeRest IncludesStatement ::identifier includes identifier ; 2.3.1. Using mixins and partials
This section is informative.
Interface mixins allow the sharing of attributes, constants, and operations across multiple interfaces. If you’re only planning to extend a single interface, you might consider using a partial interface instead.
For example, instead of:
interface mixin WindowSessionStorage {readonly attribute Storage sessionStorage ;Window includes WindowSessionStorage ;partial interface Window {readonly attribute Storage sessionStorage ;Additionally, you can rely on extending interface mixins exposed by other specifications to target common use cases, such as exposing a set of attributes, constants, or operations across both window and worker contexts.
For example, instead of the common but verbose:
interface mixin GlobalCrypto {readonly attribute Crypto crypto ;Window includes GlobalCrypto ;WorkerGlobalScope includes GlobalCrypto ;you can extend the
WindowOrWorkerGlobalScope
interface mixin using a partial interface mixin:partial interface mixin WindowOrWorkerGlobalScope {readonly attribute Crypto crypto ;2.4. Callback interfaces
A callback interface is a definition matching
callback interface identifier { CallbackInterfaceMembers } ; . It can be implemented by any object, as described in § 2.12 Objects implementing interfaces.Note: A callback interface is not an interface. The name and syntax are left over from earlier versions of this standard, where these concepts had more in common.
A callback interface is a specification of a set of callback interface members (matching
CallbackInterfaceMembers ). These are the members that appear between the braces in the interface declaration.callback interface identifier { /* interface_members... */Note: See also the similarly named callback function definition.
Callback interfaces must define exactly one regular operation.
Specification authors should not define callback interfaces unless required to describe the requirements of existing APIs. Instead, a callback function should be used.
The definition of
EventListener
as a callback interface is an example of an existing API that needs to allow objects with a given property (in this casehandleEvent
) to be considered to implement the interface. For new APIs, and those for which there are no compatibility concerns, using a callback function will allow only a function object (in the JavaScript language binding).Callback interfaces which declare constants must be annotated with an [
Exposed
] extended attribute.CallbackRestOrInterface ::CallbackRest interface identifier { CallbackInterfaceMembers } ; CallbackInterfaceMembers ::ExtendedAttributeList CallbackInterfaceMember CallbackInterfaceMembers CallbackInterfaceMember ::Const RegularOperation 2.5. Members
Interfaces, interface mixins, and namespaces are specifications of a set of members (respectively matching
InterfaceMembers ,MixinMembers , andNamespaceMembers ), which are the constants, attributes, operations, and other declarations that appear between the braces of their declarations. Attributes describe the state that an object implementing the interface, interface mixin, or namespace will expose, and operations describe the behaviors that can be invoked on the object. Constants declare named constant values that are exposed as a convenience to users of objects in the system.When an interface includes an interface mixin, each member of the interface mixin is also considered a member of the interface. In contrast, inherited interface members are not considered members of the interface.
The constructor steps, getter steps, setter steps, and method steps for the various members defined on an interface or interface mixin have access to a this value, which is an IDL value of the interface type that the member is declared on or that includes the interface mixin the member is declared on.
Setter steps also have access to the given value, which is an IDL value of the type the attribute is declared as.
Interfaces, interface mixins, callback interfaces and namespaces each support a different set of members, which are specified in § 2.2 Interfaces, § 2.3 Interface mixins, § 2.4 Callback interfaces, and § 2.6 Namespaces, and summarized in the following informative table:
2.5.1. Constants
A constant is a declaration (matching
Const) used to bind a constant value to a name. Constants can appear on interfaces and callback interfaces. Constants have in the past primarily been used to define named integer codes in the style of an enumeration. The Web platform is moving away from this design pattern in favor of the use of strings. Editors who wish to use this feature are strongly advised to discuss this by filing an issue before proceeding.
const type constant_identifier = 42;The identifier of a constant must not be the same as the identifier of another interface member or callback interface member defined on the same interface or callback interface. The identifier also must not be "
length
", "name
" or "prototype
".Note: These three names are the names of properties that are defined on the interface object in the JavaScript language binding.
The type of a constant (matching
ConstType ) must not be any type other than a primitive type. If an identifier is used, it must reference a typedef whose type is a primitive type.The
ConstValue part of a constant declaration gives the value of the constant, which can be one of the two boolean literal tokens (true andfalse ), aninteger token, adecimal token, or one of the three special floating point constant values (-Infinity ,Infinity andNaN ).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, the empty sequence
[] , and the default dictionary{} cannot be used as the value of a constant.The value of the boolean literal tokens
true andfalse are the IDLboolean
valuestrue
andfalse
.The value of an
integer token is an integer whose value is determined as follows:Let S be the sequence of scalar values matched by the
integer token.Let sign be −1 if S begins with U+002D (-), and 1 otherwise.
Let base be the base of the number based on the scalar values that follow the optional leading U+002D (-):
U+0030 (0), U+0058 (X) U+0030 (0), U+0078 (x) The base is 16.
U+0030 (0) The base is 8.
Otherwise The base is 10.
Let number be the result of interpreting all remaining scalar values following the optional leading U+002D (-) character and any scalar values indicating the base as an integer specified in base base.
Return sign × number.
The type of an
The value of ainteger token is the same as the type of the constant, dictionary member or optional argument it is being used as the value of. The value of theinteger token must not lie outside the valid range of values for its type, as given in § 2.13 Types.decimal token is either an IEEE 754 single-precision floating point number or an IEEE 754 double-precision floating point number, depending on the type of the constant, dictionary member or optional argument it is being used as the value for, determined as follows:Let S be the sequence of scalar values matched by the
decimal token.Let result be the Mathematical Value that would be obtained if S were parsed as a JavaScript
NumericLiteral .If the
decimal token is being used as the value for afloat
orunrestricted float
, then the value of thedecimal token is the IEEE 754 single-precision floating point number closest to result.Otherwise, the
decimal token is being used as the value for adouble
orunrestricted double
, and the value of thedecimal token is the IEEE 754 double-precision floating point number closest to result. [IEEE-754]The value of a constant value specified as
Infinity ,-Infinity , orNaN is either an IEEE 754 single-precision floating point number or an IEEE 754 double-precision floating point number, depending on the type of the constant, dictionary member, or optional argument it is being used as the value for:Type unrestricted float
, constant 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
decimal token is the same as the type of the constant, dictionary member or optional argument it is being used as the value of. The value of thedecimal token must not lie outside the valid range of values for its type, as given in § 2.13 Types. Also,Infinity ,-Infinity andNaN must not be used as the value of afloat
ordouble
.The value of the
null token is the specialnull value that is a member of the nullable types. The type of thenull token is the same as the type of the constant, dictionary member or optional argument it is being used as the value of.If VT is the type of the value assigned to a constant, and DT is the type of the constant, dictionary member or optional argument itself, then these types must be compatible, which is the case if DT and VT are identical, or DT is a nullable type whose inner type is VT.
Constants are not associated with particular instances of the interface or callback interface on which they appear. It is language binding specific whether constants are exposed on instances.
The JavaScript language binding does however allow constants to be accessed through objects implementing the IDL interfaces on which the constants are declared. For example, with the following IDL:
[Exposed =Window ]interface A {const short rambaldi = 47;the constant value can be accessed in JavaScript either as
A.rambaldi
orinstanceOfA.rambaldi
.The following extended attributes are applicable to constants: [
CrossOriginIsolated
], [Exposed
], and [SecureContext
].Const ::const ConstType identifier = ConstValue ; ConstValue ::BooleanLiteral FloatLiteral integer BooleanLiteral ::false FloatLiteral ::decimal -Infinity Infinity ConstType ::PrimitiveType identifier The following IDL fragment demonstrates how constants of the above types can be defined.
[Exposed =Window ]interface Util {const boolean DEBUG =false ;const octet LF = 10;const unsigned long BIT_MASK = 0x0000fc00;const double AVOGADRO = 6.022e23;2.5.2. Attributes
An attribute is an interface member or namespace member (matching
inherit AttributeRest ,static OptionalReadOnly AttributeRest ,stringifier OptionalReadOnly AttributeRest ,OptionalReadOnly AttributeRest , orAttributeRest ) that is used to declare data fields with a given type and identifier whose value can be retrieved and (in some cases) changed. There are two kinds of attributes: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
static keyword, then it declares a regular attribute. Otherwise, it declares a static attribute. Note that in addition to being interface members, read only regular attributes can be namespace members as well.The getter steps of an attribute attr should be introduced using text of the form “The
attr
getter steps are:” followed by a list, or “Theattr
getter steps are to” followed by an inline description.The setter steps of an attribute attr should be introduced using text of the form “The
attr
setter steps are:” followed by a list, or “Theattr
setter steps are to” followed by an inline description.Note: When defining getter steps, you implicitly have access to this. When defining setter steps, you implicitly have access to this and the given value.
The identifier of an attribute must not be the same as the identifier of another interface member defined on the same interface. The identifier of a static attribute must not be "
prototype
".The type of the attribute is given by the type (matching
Type ) that appears after theattribute keyword. If theType is an identifier or an identifier followed by? , then the identifier must identify an interface, enumeration, callback function, callback interface or typedef.The type of the attribute, after resolving typedefs, must not be a nullable 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
readonly keyword is used before theattribute keyword. An object that implements the interface on which a read only attribute is defined will not allow assignment to that attribute. It is language binding specific whether assignment is simply disallowed by the language, ignored or an exception is thrown.interface interface_identifier {readonly attribute type identifier ;Attributes whose type is a promise type must be read only. Additionally, they cannot have any of the extended attributes [
LegacyLenientSetter
], [PutForwards
], [Replaceable
], or [SameObject
].A regular attribute that is not read only can be declared to inherit its getter from an ancestor interface. This can be used to make a read only attribute in an ancestor interface be writable on a derived interface. An attribute inherits its getter if its declaration includes
inherit in the declaration. The read only attribute from which the attribute inherits its getter is the attribute with the same identifier on the closest ancestor interface of the one on which the inheriting attribute is defined. The attribute whose getter is being inherited must be of the same type as the inheriting attribute.Note: The grammar ensures that
inherit does not appear on a read only attribute or a static attribute.[Exposed =Window ]interface Ancestor {readonly attribute TheType theIdentifier ; [Exposed =Window ]interface Derived :Ancestor {inherit attribute TheType theIdentifier ;When the
stringifier keyword is used in a regular attribute declaration, it indicates that objects implementing the interface will be stringified to the value of the attribute. See § 2.5.5 Stringifiers for details.interface interface_identifier {stringifier attribute DOMString identifier ;The following extended attributes are applicable to regular and static attributes: [
CrossOriginIsolated
], [Exposed
], [SameObject
], and [SecureContext
].The following extended attributes are applicable only to regular attributes: [
LegacyLenientSetter
], [LegacyLenientThis
], [PutForwards
], [Replaceable
], [LegacyUnforgeable
].ReadOnlyMember ::readonly ReadOnlyMemberRest ReadOnlyMemberRest ::AttributeRest MaplikeRest SetlikeRest ReadWriteAttribute ::AttributeRest InheritAttribute ::inherit AttributeRest AttributeRest ::attribute TypeWithExtendedAttributes AttributeName ; AttributeName ::AttributeNameKeyword identifier AttributeNameKeyword ::async required OptionalReadOnly ::readonly The following IDL fragment demonstrates how attributes can be declared on an interface:
[Exposed =Window ]interface Animal { // A simple attribute that can be set to any string value.readonly attribute DOMString name ; // An attribute whose value can be assigned to.attribute unsigned short age ; [Exposed =Window ]interface Person :Animal { // An attribute whose getter behavior is inherited from Animal, and need not be // specified in the description of Person.inherit attribute DOMString name ;2.5.3. Operations
An operation is an interface member, callback interface member or namespace member (matching
static RegularOperation ,stringifier ,RegularOperation orSpecialOperation ) that defines a behavior that can be invoked on objects implementing the interface. There are three kinds of operation: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_keyword */return_type identifier (/* arguments... */); /* special_keyword */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
static keyword, then it declares a regular operation. If the operation has a special keyword used in its declaration (that is, any keyword matchingSpecial , or thestringifier keyword), then it declares a special operation. A single operation can declare both a regular operation and a special operation; see § 2.5.6 Special operations for details on special operations. Note that in addition to being interface members, regular operations can also be callback interface members and namespace members.If an operation has no identifier, then it must be declared to be a special operation using one of the special keywords.
The identifier of a regular operation or static operation must not be the same as the identifier of a constant or attribute defined on the same interface, callback interface or namespace. The identifier of a static operation must not be "
prototype
".Note: The identifier can be the same as that of another operation on the interface, however. This is how operation overloading is specified.
Note: The identifier of a static operation can be the same as the identifier of a regular operation defined on the same interface.
The return type of the operation is given by the type (matching
Type ) that appears before the operation’s optional identifier. If the return type is an identifier followed by? , then the identifier must identify an interface, dictionary, enumeration, callback function, callback interface or typedef.An operation’s arguments (matching
ArgumentList ) are given between the parentheses in the declaration. Each individual argument is specified as a type (matchingType ) followed by an identifier (matchingArgumentName ).Note: For expressiveness, the identifier of an operation argument can also be specified as one of the keywords matching the
ArgumentNameKeyword symbol without needing to escape it.If the
Type of an operation argument is an identifier followed by? , then the identifier must identify an interface, enumeration, callback function, callback interface, or typedef. If the operation argument type is an identifier not followed by? , then the identifier must identify any one of those definitions or a dictionary.If the operation argument type, after resolving typedefs, is a nullable type, its inner type must not be a dictionary type.
interface interface_identifier {return_type identifier (type identifier ,type identifier /* , ... */);The identifier of each argument must not be the same as the identifier of another argument in the same operation declaration.
Each argument can be preceded by a list of extended attributes (matching
ExtendedAttributeList ), which can control how a value passed as the argument will be handled in language bindings.interface interface_identifier {return_type identifier ([extended_attributes ]type identifier , [extended_attributes ]type identifier /* , ... */);The following IDL fragment demonstrates how regular operations can be declared on an interface:
[Exposed =Window ]interface Dimensions {attribute unsigned long width ;attribute unsigned long height ; [Exposed =Window ]interface Button { // An operation that takes no arguments and returns a boolean.boolean isMouseOver (); // Overloaded operations.undefined setDimensions (Dimensions size );undefined setDimensions (unsigned long width ,unsigned long height );An operation or constructor operation is considered to be variadic if the final argument uses the
... token just after the argument type. Declaring an operation to be variadic indicates that the operation can be invoked with any number of arguments after that final argument. Those extra implied formal arguments are of the same type as the final explicit argument in the operation declaration. The final argument can also be omitted when invoking the operation. An argument must not be declared with the... token unless it is the final argument in the operation’s argument list.interface interface_identifier {return_type identifier (type ...identifier );return_type identifier (type identifier ,type ...identifier );Extended attributes that take an argument list ([
LegacyFactoryFunction
], of those defined in this specification) and callback functions are also considered to be variadic when the... token is used in their argument lists.The following IDL fragment defines an interface that has two variadic operations:
[Exposed =Window ]interface IntegerSet {readonly attribute unsigned long cardinality ;undefined union (long ...ints );undefined intersection (long ...ints );In the JavaScript binding, variadic operations are implemented by functions that can accept the subsequent arguments:
var s= getIntegerSet(); // Obtain an instance of IntegerSet. s. union(); // Passing no arguments corresponding to 'ints'. s. union( 1 , 4 , 7 ); // Passing three arguments corresponding to 'ints'. A binding for a language that does not support variadic functions might specify that an explicit array or list of integers be passed to such an operation.
An argument is considered to be an optional argument if it is declared with the
optional keyword. The final argument of a variadic operation is also considered to be an optional argument. Declaring an argument to be optional indicates that the argument value can be omitted when the operation is invoked. The final argument in an operation must not explicitly be declared to be optional if the operation is variadic.interface interface_identifier {return_type identifier (type identifier ,optional type identifier );Optional arguments can also have a default value specified. If the argument’s identifier is followed by a U+003D (=) and a value (matching
DefaultValue ), then that gives the optional argument its default value. The implicitly optional final argument of a variadic operation must not have a default value specified. The default value is the value to be assumed when the operation is called with the corresponding argument omitted.interface interface_identifier {return_type identifier (type identifier ,optional type identifier = "value");It is strongly suggested not to use a default value of
true forboolean
-typed arguments, as this can be confusing for authors who might otherwise expect the default conversion ofundefined to be used (i.e.,false ). [API-DESIGN-PRINCIPLES]If the type of an argument is a dictionary type or a union type that has a dictionary type as one of its flattened member types, and that dictionary type and its ancestors have no 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 and have a default value provided.
This is to encourage API designs that do not require authors to pass an empty dictionary value when they wish only to use the dictionary’s default values.
Usually the default value provided will be
{} , but in the case of a union type that has a dictionary type as one of its flattened member types a default value could be provided that initializes some other member of the union.When a boolean literal token (
true orfalse ), thenull token, aninteger token, adecimal token or one of the three special floating point literal values (Infinity ,-Infinity orNaN ) is used as the default value, it is interpreted in the same way as for a constant.When the
Optional argument default values can also be specified using aundefined token is used as the default value, the value is the IDLundefined
value.string token, whose value is a string type determined as follows:Let S be the sequence of scalar values matched by the
string token with its leading and trailing U+0022 (") scalar values removed.Depending on the type of the argument:
DOMString
USVString
an enumeration type The value of the
string token is S.ByteString
Assert: S doesn’t contain any code points higher than U+00FF.
The value of the
string token is the isomorphic encoding of S.If the type of the optional argument is an enumeration, then its 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.Optional argument default values can also be specified using the two token value
{} , which represents a default-initialized (as if from ESnull or an object with no properties) dictionary value. The type of this value is the same as the type of the optional argument it is being used as the default value of. That type must be a dictionary type, or a union type that has a dictionary type in its flattened member types.The following IDL fragment defines an interface with a single operation that can be invoked with two different argument list lengths:
[Exposed =Window ]interface ColorCreator {object createColor (double v1 ,double v2 ,double v3 ,optional double alpha );It is equivalent to an interface that has two overloaded operations:
[Exposed =Window ]interface ColorCreator {object createColor (double v1 ,double v2 ,double v3 );object createColor (double v1 ,double v2 ,double v3 ,double alpha );The following IDL fragment defines an interface with an operation that takes a dictionary argument:
dictionary LookupOptions {boolean caseSensitive =false ; [Exposed =Window ]interface AddressBook {boolean hasAddressForName (USVString name ,optional LookupOptions options = {});If
hasAddressForName
is called with only one argument, the second argument will be a default-initializedLookupOptions
dictionary, which will causecaseSensitive
to be set tofalse .The following extended attributes are applicable to operations: [
CrossOriginIsolated
], [Default
], [Exposed
], [LegacyUnforgeable
], [NewObject
], and [SecureContext
].The method steps of an operation operation should be introduced using text of the form “The
operation(arg1, arg2, ...)
method steps are:” followed by a list, or “Theoperation(arg1, arg2, ...)
method steps are to” followed by an inline description.Note: When defining method steps, you implicitly have access to this.
DefaultValue ::ConstValue string undefined Operation ::RegularOperation SpecialOperation RegularOperation ::Type OperationRest SpecialOperation ::Special RegularOperation Special ::getter setter deleter OperationRest ::OptionalOperationName ( ArgumentList ) ; OptionalOperationName ::OperationName OperationName ::OperationNameKeyword identifier OperationNameKeyword ::includes ArgumentList ::Argument Arguments Arguments ::, Argument Arguments Argument ::ExtendedAttributeList ArgumentRest ArgumentRest ::optional TypeWithExtendedAttributes ArgumentName Default Type Ellipsis ArgumentName ArgumentName ::ArgumentNameKeyword identifier Ellipsis ::ArgumentNameKeyword ::async attribute callback const constructor deleter dictionary getter includes inherit interface iterable maplike mixin namespace partial readonly required setlike setter static stringifier typedef unrestricted 2.5.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,
typedefs whose type being given a new name is a JSON type,
sequence types whose parameterized type is a JSON type,
frozen array types whose parameterized type is a JSON type,
dictionary types where the types of all members declared on the dictionary and all its inherited dictionaries 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 interfaces.How the
toJSON
regular operation is made available on an object in a language binding, and how exactly the JSON types are converted into a JSON string, is language binding specific.Note: In the JavaScript language binding, this is done by exposing a
toJSON
method which returns the JSON type converted into a JavaScript value that can be turned into a JSON string by theJSON.stringify()
function. Additionally, in the JavaScript language binding, thetoJSON
operation can take a [Default
] extended attribute, in which case the default toJSON steps are exposed instead.The following IDL fragment defines an interface
Transaction
that has atoJSON
method defined in prose:[Exposed =Window ]interface Transaction {readonly attribute DOMString from ;readonly attribute DOMString to ;readonly attribute double amount ;readonly attribute DOMString description ;readonly attribute unsigned long number ;TransactionJSON toJSON ();dictionary TransactionJSON {Account from ;Account to ;double amount ;DOMString description ;The
toJSON
regular operation ofTransaction
interface could be defined as follows:The
toJSON()
method steps are:Let json be a new map.
For each attribute identifier attr in « "from", "to", "amount", "description" »:
Let value be the result of running the getter steps of attr on this.
Set json[attr] to value.
Return json.
In the JavaScript language binding, there would exist a
toJSON()
method onTransaction
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.5.4. Constructor operations
If an interface has a constructor operation member (matching
Constructor ), it indicates that it is possible to create objects that implement the interface using a constructor.Multiple constructor operations may appear on a given interface. For each constructor operation on the interface, there will be a way to attempt to construct an instance by passing the specified arguments.
The constructor steps of a constructor operation that is a member of an interface named interface should be introduced using text of the form “The
new interface(arg1, arg2, ...)
constructor steps are:” followed by a list, or “Thenew interface(arg1, arg2, ...)
constructor steps are to” followed by an inline description.The constructor steps must do nothing, initialize the value passed as this, or throw an exception.
If the constructor does not initialize this, one can write “The
new Example(init)
constructor steps are to do nothing.”See § 3.7.1 Interface object for details on how a constructor operation is to be implemented.
The following IDL defines two interfaces. The second has constructor operations, while the first does not.
[Exposed =Window ]interface NodeList {Node item (unsigned long index );readonly attribute unsigned long length ; [Exposed =Window ]interface Circle {constructor ();constructor (double radius );attribute double r ;attribute double cx ;attribute double cy ;readonly attribute double circumference ;A JavaScript implementation supporting these interfaces would implement a [[Construct]] internal method on the
Circle
interface object which would return a new object that implements the interface. It would take either zero or one argument.It is unclear whether the
NodeList
interface object would implement a [[Construct]] internal method. In any case, trying to use it as a constructor will cause aTypeError
to be thrown.var x= new Circle(); // This uses the zero-argument constructor to create a // reference to a platform object that implements the // Circle interface. var y= new Circle( 1.25 ); // This also creates a Circle object, this time using // the one-argument constructor. var z= new NodeList(); // This would throw a TypeError, since no // constructor is declared. Constructor ::constructor ( ArgumentList ) ; ArgumentList ::Argument Arguments Arguments ::, Argument Arguments Argument ::ExtendedAttributeList ArgumentRest ArgumentRest ::optional TypeWithExtendedAttributes ArgumentName Default Type Ellipsis ArgumentName ArgumentName ::ArgumentNameKeyword identifier Ellipsis ::ArgumentNameKeyword ::async attribute callback const constructor deleter dictionary getter includes inherit interface iterable maplike mixin namespace partial readonly required setlike setter static stringifier typedef unrestricted 2.5.5. Stringifiers
When an interface has a stringifier, it indicates that objects that implement the interface have a non-default conversion to a string. Stringifiers can be specified using a
stringifier keyword, which creates a stringifier operation when used alone.interface interface_identifier {stringifier ;Prose accompanying the interface must define the stringification behavior of the interface.
The
stringifier keyword can also be placed on an attribute. In this case, the string to convert the object to is the value of the attribute. Thestringifier keyword must not be placed on an attribute unless it is declared to be of typeDOMString
orUSVString
. It also must not be placed on a static attribute.interface interface_identifier {stringifier attribute DOMString identifier ;On a given interface, there must exist at most one stringifier.
Stringifier ::stringifier StringifierRest StringifierRest ::OptionalReadOnly AttributeRest The following IDL fragment defines an interface that will stringify to the value of its
name
attribute:[Exposed =Window ]interface Student {constructor ();attribute unsigned long id ;stringifier attribute DOMString name ;In the JavaScript binding, using a
Student
object in a context where a string is expected will result in the value of the object’sname
property being used:var s= new Student(); s. id= 12345678 ; s. name= '周杰倫' ; var greeting= 'Hello, ' + s+ '!' ; // Now greeting == 'Hello, 周杰倫!'. The following IDL fragment defines an interface that has custom stringification behavior that is not specified in the IDL itself.
[Exposed =Window ]interface Student {constructor ();attribute unsigned long id ;attribute DOMString ?familyName ;attribute DOMString givenName ;stringifier ;Thus, there needs to be prose to explain the stringification behavior. We assume that the
familyName
andgivenName
attributes are backed by family name and given name concepts, respectively.The stringification behavior steps are:
If this's family name is null, then return this's given name.
Return the concatenation of this's given name, followed by U+0020 SPACE, followed by this's family name.
A JavaScript implementation of the IDL would behave as follows:
var s= new Student(); s. id= 12345679 ; s. familyName= 'Smithee' ; s. givenName= 'Alan' ; var greeting= 'Hi ' + s; // Now greeting == 'Hi Alan Smithee'. 2.5.6. Special operations
A special operation is a declaration of a certain kind of special behavior on objects implementing the interface on which the special operation declarations appear. Special operations are declared by using a special keyword in an operation declaration.
There are three kinds of special operations. The table below indicates for a given kind of special operation what special keyword is used to declare it and what the purpose of the special operation is:
Special operation Keyword Purpose Gettersgetter Defines behavior for when an object is indexed for property retrieval. Setterssetter Defines behavior for when an object is indexed for property assignment or creation. Deletersdeleter Defines behavior for when an object is indexed for property deletion.Not all language bindings support all of the four kinds of special object behavior. When special operations are declared using operations with no identifier, then in language bindings that do not support the particular kind of special operations there simply will not be such functionality.
The following IDL fragment defines an interface with a getter and a setter:
[Exposed =Window ]interface Dictionary {readonly attribute unsigned long propertyCount ;getter double (DOMString propertyName );setter undefined (DOMString propertyName ,double propertyValue );In language bindings that do not support property getters and setters, objects implementing Dictionary will not have that special behavior.
Defining a special operation with an identifier is equivalent to separating the special operation out into its own declaration without an identifier. This approach is allowed to simplify method steps of an interface’s operations.
The following two interfaces are equivalent:
[Exposed =Window ]interface Dictionary {readonly attribute unsigned long propertyCount ;getter double getProperty (DOMString propertyName );setter undefined setProperty (DOMString propertyName ,double propertyValue );[Exposed =Window ]interface Dictionary {readonly attribute unsigned long propertyCount ;double getProperty (DOMString propertyName );undefined setProperty (DOMString propertyName ,double propertyValue );getter double (DOMString propertyName );setter undefined (DOMString propertyName ,double propertyValue );A given special keyword must not appear twice on an operation.
Getters and setters come in two varieties: ones that take a
DOMString
as a property name, known as named property getters and named property setters, and ones that take anunsigned 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.5.6.1 Indexed properties and § 2.5.6.2 Named properties for details.On a given interface, there must exist at most one named property deleter, and at most one of each variety of getter and setter.
If an interface has a setter of a given variety, then it must also have a getter of that variety. If it has a named property deleter, then it must also have a named property getter.
Special operations declared using operations must not be variadic nor have any optional arguments.
If an object implements more than one interface that defines a given special operation, then it is undefined which (if any) special operation is invoked for that operation.
2.5.6.1. 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 anunsigned 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 JavaScript language binding, a regular property lookup is done. For example, take the following IDL:
[Exposed =Window ]interface A {getter DOMString toWord (unsigned long index );Assume that an object implementing
A
has supported property indices in the range 0 ≤ index < 2. Also assume that toWord is defined to return its argument converted into an English word. The behavior when invoking the operation with an out of range index is different from indexing the object directly:var a= getA(); a. toWord( 0 ); // Evalautes to "zero". a[ 0 ]; // Also evaluates to "zero". a. toWord( 5 ); // Evaluates to "five". a[ 5 ]; // Evaluates to undefined, since there is no property "5". The following IDL fragment defines an interface
OrderedMap
which allows retrieving and setting values by name or by index number:[Exposed =Window ]interface OrderedMap {readonly attribute unsigned long size ;getter any getByIndex (unsigned long index );setter undefined setByIndex (unsigned long index ,any value );getter any get (DOMString name );setter undefined set (DOMString name ,any value );Since all of the special operations are declared using operations with identifiers, the only additional prose that is necessary is that which describes what keys those sets have. Assuming that the
get()
operation is defined to returnnull if an attempt is made to look up a non-existing entry in theOrderedMap
, 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, a JavaScript implementation would create properties on a legacy platform object implementing
OrderedMap
that correspond to entries in both the named and indexed property sets. These properties can then be used to interact with the object in the same way as invoking the object’s methods, as demonstrated below:// Assume map is a legacy platform object implementing the OrderedMap interface. var map= getOrderedMap(); var x, y; x= map[ 0 ]; // If map.length > 0, then this is equivalent to: // x = map.getByIndex(0) // since a property named "0" will have been placed on map. // Otherwise, x will be set to undefined, since there will be // no property named "0" on map. map[ 1 ] = false ; // This will do the equivalent of: // map.setByIndex(1, false) y= map. apple; // If there exists a named property named "apple", then this // will be equivalent to: // y = map.get('apple') // since a property named "apple" will have been placed on // map. Otherwise, y will be set to undefined, since there // will be no property named "apple" on map. map. berry= 123 ; // This will do the equivalent of: // map.set('berry', 123) delete map. cake; // If a named property named "cake" exists, then the "cake" // property will be deleted, and then the equivalent to the // following will be performed: // map.remove("cake") 2.5.6.2. 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 aDOMString
.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.5.7. Static attributes and operations
Static attributes and static operations are ones that are not associated with a particular instance of the interface on which it is declared, and is instead associated with the interface itself. Static attributes and operations are declared by using the
static keyword in their declarations.It is language binding specific whether it is possible to invoke a static operation or get or set a static attribute through a reference to an instance of the interface.
StaticMember ::static StaticMemberRest StaticMemberRest ::OptionalReadOnly AttributeRest RegularOperation The following IDL fragment defines an interface
Circle
that has a static operation declared on it:[Exposed =Window ]interface Point { /* ... */ }; [Exposed =Window ]interface Circle {attribute double cx ;attribute double cy ;attribute double radius ;static readonly attribute long triangulationCount ;static Point triangulate (Circle c1 ,Circle c2 ,Circle c3 );In the JavaScript language binding, the function object for
triangulate
and the accessor property fortriangulationCount
will exist on the interface object forCircle
: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.5.8. Overloading
If a regular operation or static operation defined on an interface has an identifier that is the same as the identifier of another operation on that interface of the same kind (regular or static), then the operation is said to be overloaded. When the identifier of an overloaded operation is used to invoke one of the operations on an object that implements the interface, the number and types of the arguments passed to the operation determine which of the overloaded operations is actually invoked. Constructor operations can be overloaded too. There are some restrictions on the arguments that overloaded operations and constructors can be specified to take, and in order to describe these restrictions, the notion of an effective overload set is used.
A set of overloaded operations must either:
contain no operations whose return type is a promise type;
only contain operations whose return type is a promise type.
Operations must not be overloaded across interface, partial interface, interface mixin, and partial interface mixin definitions.
For example, the overloads for both f and g are disallowed:
[Exposed =Window ]interface A {undefined f ();partial interface A {undefined f (double x );undefined g ();partial interface A {undefined g (DOMString x );Note that constructor operations and [
LegacyFactoryFunction
] extended attributes are disallowed from appearing on partial interface definitions, so there is no need to also disallow overloading for constructors.An effective overload set represents the allowable invocations for a particular operation, constructor (specified with a constructor operation or [
LegacyFactoryFunction
]), or callback function. The algorithm to compute the effective overload set operates on one of the following four types of IDL constructs, and listed with them below are the inputs to the algorithm needed to compute the set.For regular operations For static operations the interface on which the operations are to be found
the identifier of the operations
the number of arguments to be passed
For constructors the interface on which the constructor operations are to be found
the number of arguments to be passed
For legacy factory functions the interface on which the [
LegacyFactoryFunction
] extended attributes are to be foundthe identifier of the legacy factory function
the number of arguments to be passed
An effective overload set is used, among other things, to determine whether there are ambiguities in the overloaded operations and constructors specified on an interface.
The items of an effective overload set are tuples of the form (callable, type list, optionality list) whose items are described below:
A callable is an operation if the effective overload set is for regular operations, static operations, or constructor operations; and it is an extended attribute if the effective overload set is for legacy factory functions.
A type list is a list of IDL types.
An optionality list is a list of three possible optionality values – "required", "optional" or "variadic" – indicating whether the argument at a given index was declared as being optional or corresponds to a variadic argument.
Each tuple represents an allowable invocation of the operation, constructor, or callback function with an argument value list of the given types. Due to the use of optional arguments and variadic operations and constructors, there may be multiple items in an effective overload set identifying the same operation or constructor.
The algorithm below describes how to compute the effective overload set. The following input variables are used, if they are required:the identifier of the operation or legacy factory function is A
the argument count is N
the interface is I
Whenever an argument of an extended attribute is mentioned, it is referring to an argument of the extended attribute’s named argument list.
Let S be an ordered set.
Let F be an ordered set with items as follows, according to the kind of effective overload set:
For regular operations The elements of F are the regular operations with identifier A defined on interface I.
For static operations The elements of F are the static operations with identifier A defined on interface I.
For constructors The elements of F are the constructor operations on interface I.
For legacy factory functions The elements of F are the [
LegacyFactoryFunction
] extended attributes on interface I whose named argument lists' identifiers are A.Let maxarg be the maximum number of arguments the operations, legacy factory functions, or callback functions in F are declared to take. For variadic operations and legacy factory functions, the argument on which the ellipsis appears counts as a single argument.
Note: So
undefined f(long x, long... y);
is considered to be declared to take two arguments.Let max be max(maxarg, N).
For each operation or extended attribute X in F:
Let arguments be the list of arguments X is declared to take.
Let n be the size of arguments.
Let types be a type list.
Let optionalityValues be an optionality list.
For each argument in arguments:
Append the type of argument to types.
Append "variadic" to optionalityValues if argument is a final, variadic argument, "optional" if argument is optional, and "required" otherwise.
Append the tuple (X, types, optionalityValues) to S.
If X is declared to be variadic, then:
For each i in the range n to max − 1, inclusive:
Let t be a type list.
Let o be an optionality list.
For each j in the range 0 to n − 1, inclusive:
Append types[j] to t.
Append optionalityValues[j] to o.
For each j in the range n to i, inclusive:
Append types[n − 1] to t.
Append "variadic" to o.
Append the tuple (X, t, o) to S.
Let i be n − 1.
While i ≥ 0:
If arguments[i] is not optional (i.e., it is not marked as "optional" and is not a final, variadic argument), then break.
Let t be a type list.
Let o be an optionality list.
For each j in the range 0 to i − 1, inclusive:
Append types[j] to t.
Append optionalityValues[j] to o.
Append the tuple (X, t, o) to S.
Note: if i is 0, this means to add to S the tuple (X, « », « »); (where "« »" represents an empty list).
Set i to i − 1.
Return S.
interface A { /* f1 */undefined f (DOMString a ); /* f2 */undefined f (Node a ,DOMString b ,double ...c ); /* f3 */undefined f (); /* f4 */undefined f (Event a ,DOMString b ,optional DOMString c ,double ...d );assuming
(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 »)Node
andEvent
are two other interfaces of which no object can implement both, the effective overload set for regular operations with identifierf
and argument count 4 is: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.
None of the following pairs are distinguishable:
and
double
?Dictionary1
(Interface1 or
andlong
)?(Interface2 or
DOMString
)?(Interface1 or
andlong
?)(Interface2 or
DOMString
)?(Interface1 or
andlong
?)(Interface2 or
DOMString
?)(Dictionary1 or
andlong
)(Interface2 or
DOMString
)?(Dictionary1 or
andlong
)(Interface2 or
DOMString
?)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 The two identified interface-like types are not the same, and no single platform object implements both interface-like types.
The types are distinguishable, but there is a separate restriction on their use in overloading below. Please also note the advice about using unions of these types.
A callback function that does not have [
LegacyTreatNonObjectAsNull
] extended attribute is distinguishable from a type in the dictionary-like category.For example, when converting an ECMAScript value to union type which includes a callback function and a dictionary-like type, if the value is callable, then it is converted to a callback function. Otherwise, it is converted to a dictionary-like type.double
andDOMString
are distinguishable because there is a ● at the intersection of numeric types with string types.Given: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.callback interface CBIface {undefined handle (); [Exposed =Window ]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 item in an effective overload set that has a given type list size, then for those items there must be an index i such that for each pair of items the types at index i are distinguishable. The lowest such index is termed the distinguishing argument index for the items of the effective overload set with the given type list size.
An effective overload set must not contain more than one item with the same type list size, where one item has a
bigint
argument at the distinguishing argument index and another has a numeric type argument at the distinguishing argument index.Consider the effective overload set shown in the previous example. There are multiple items in the set with type lists 2, 3 and 4. For each of these type list size, the distinguishing argument index is 0, since
Node
andEvent
are distinguishable.The following use of overloading however is invalid:
[Exposed =Window ]interface B {undefined f (DOMString x );undefined f (USVString x );since
DOMString
andUSVString
are not distinguishable.In addition, for each index j, where j is less than the distinguishing argument index for a given type list size, the types at index j in all of the items' type lists must be the same, and the optionality values at index j in all of the items' optionality lists must be the same.
The following is invalid:
[Exposed =Window ]interface B { /* f1 */undefined f (DOMString w ); /* f2 */undefined f (long w ,double x ,Node y ,Node z ); /* f3 */undefined f (double w ,double x ,DOMString y ,Node z );For argument count 4, the effective overload set is:
(f1, « DOMString », « required »), (f2, « long, double, Node, Node », « required, required, required, required »), (f3, « double, double, DOMString, Node », « required, required, required, required »)Looking at items with type list size 4, the distinguishing argument index is 2, since
Node
andDOMString
are distinguishable. However, since the arguments in these two overloads at index 0 are different, the overloading is invalid.2.5.8.1. Overloading vs. union types
This section is informative.
For specifications defining IDL operations, it might seem that overloads and a combination of union types and optional arguments have some feature overlap.
It is first important to note that overloads have different behaviors than union types or optional arguments, and one cannot be fully defined using the other (unless, of course, additional prose is provided, which can defeat the purpose of the Web IDL type system). For example, consider the
stroke()
operations defined on theCanvasDrawPath
interface [HTML]:interface CanvasDrawPathExcerpt {undefined stroke ();undefined stroke (Path2D path );Per the JavaScript language binding, calling
stroke(undefined)
on an object implementingCanvasDrawPathExcerpt
would attempt to call the second overload, yielding aTypeError
sinceundefined cannot be converted to aPath2D
. However, if the operations were instead defined with optional arguments and merged into one,interface CanvasDrawPathExcerptOptional {undefined stroke (optional Path2D path );the overload resolution algorithm would treat the path argument as missing given the same call
stroke(undefined)
, and not throw any exceptions.Note: For this particular example, the latter behavior is actually what Web developers would generally expect. If
CanvasDrawPath
were to be designed today, optional arguments would be used forstroke()
.Additionally, there are semantic differences as well. Union types are usually used in the sense that "any of the types would work in about the same way". In contrast, overloaded operations are designed to map well to language features such as C++ overloading, and are usually a better fit for operations with more substantial differences in what they do given arguments of different types. However, in most cases, operations with such substantial differences are best off with different names to avoid confusion for Web developers, since the JavaScript language does not provide language-level overloading. As such, overloads are rarely appropriate for new APIs, instead often appearing in legacy APIs or in specialized circumstances.
That being said, we offer the following recommendations and examples in case of difficulties to determine what Web IDL language feature to use:
In the unusual case where the operation needs to return values of different types for different argument types, overloading will result in more expressive IDL fragments. This is almost never appropriate API design, and separate operations with distinct names usually are a better choice for such cases.
Suppose there is an operation
calculate()
that accepts along
,DOMString
, orCalculatableInterface
(an interface type) as its only argument, and returns a value of the same type as its argument. It would be clearer to write the IDL fragment using overloaded operations asinterface A {long calculate (long input );DOMString calculate (DOMString input );CalculatableInterface calculate (CalculatableInterface input );than using a union type with a typedef as
typedef (long or DOMString or CalculatableInterface )Calculatable ;interface A {Calculatable calculate (Calculatable input );which does not convey the fact that the return value is always of the same type as input.
If the specified
calculate()
is a new API and does not have any compatibility concerns, it is suggested to use different names for the overloaded operations, perhaps asinterface A {long calculateNumber (long input );DOMString calculateString (DOMString input );CalculatableInterface calculateCalculatableInterface (CalculatableInterface input );which allows Web developers to write explicit and unambiguous code.
When the operation has significantly different semantics for different argument types or lengths, overloading is preferred. Again, in such scenarios, it is usually better to create separate operations with distinct names, but legacy APIs sometimes follow this pattern.
As an example, the
supports(property, value)
andsupports(conditionText)
operations of theCSS
interface are defined as the following IDL fragment [CSS3-CONDITIONAL] [CSSOM].partial interface CSS {static boolean supports (CSSOMString property ,CSSOMString value );static boolean supports (CSSOMString conditionText );Using optional arguments one can rewrite the IDL fragment as follows:
partial interface CSSExcerptOptional {static boolean supports (CSSOMString propertyOrConditionText ,optional CSSOMString value );Even though the IDL is shorter in the second version, two distinctively different concepts are conflated in the first argument. Without overloads, the question "is property or conditionText paired with value?" is much more difficult to answer without reading the method steps of the operation. This makes the second version remarkably less readable than the first.
Another consideration is that the method steps for overloaded operations can be specified in separate blocks, which can aid in both reading and writing specifications. This is not the case for optional arguments. This means that in the first case the specification author can write the method steps of the operations as:
The
supports(property, value)
method steps are:The
supports(conditionText)
method steps are:Yet using value as an optional argument, the specification author has to use more boilerplate-style text to effectively replicate the overload resolution algorithm.
The
supports(propertyOrConditionText, value)
method steps are:If value is given, then:
Let property be propertyOrConditionText.
Otherwise:
Let conditionText be propertyOrConditionText.
If the two overloads have little to no shared parts, it is better to leave overload resolution to the IDL mechanism.
If the operation accepts multiple types for multiple arguments with no coupling between types of different arguments, union types can sometimes be the only viable solution.
typedef (long long or DOMString or CalculatableInterface )SupportedArgument ;interface A {undefined add (SupportedArgument operand1 ,SupportedArgument operand2 );For the
add()
operation above, to specify it using overloads would requireinterface A {undefined add (long long operand1 ,long long operand2 );undefined add (long long operand1 ,DOMString operand2 );undefined add (long long operand1 ,CalculatableInterface operand2 );undefined add (DOMString operand1 ,long long operand2 );undefined add (DOMString operand1 ,DOMString operand2 );undefined add (DOMString operand1 ,CalculatableInterface operand2 );undefined add (CalculatableInterface operand1 ,long long operand2 );undefined add (CalculatableInterface operand1 ,DOMString operand2 );undefined add (CalculatableInterface operand1 ,CalculatableInterface operand2 );and nine times the corresponding prose!
Specification authors are encouraged to treat missing argument and
undefined argument the same way in the JavaScript language binding.Given the following IDL fragment:
interface A {undefined foo ();undefined foo (Node ?arg );Using the JavaScript language binding, calling
foo(undefined)
andfoo(null)
would both run the steps corresponding to thefoo(arg)
operation, with arg set to null, whilefoo()
alone would go to the first overload. This can be a surprising behavior for many API users. Instead, specification authors are encouraged to use an optional argument, which would categorize bothfoo()
andfoo(undefined)
as "arg is missing".interface A {undefined foo (optional Node ?arg );In general, optionality is best expressed using the
optional keyword, and not using overloads.When the case fits none of the categories above, it is up to the specification author to choose the style, since it is most likely that either style would sufficiently and conveniently describe the intended behavior. However, the definition and conversion algorithms of union types and optional arguments are simpler to implement and reason about than those of overloads, and usually result in more idiomatic APIs in the JavaScript language binding. Thus, unless any other considerations apply, union types, optional arguments, or both are the default choice.
Specifications are also free to mix and match union types and overloads, if the author finds it appropriate and convenient.
2.5.9. Iterable declarations
An interface can be declared to be iterable by using an iterable declaration (matching
Iterable ) in the body of the interface.interface interface_identifier {iterable <value_type >;iterable <key_type ,value_type >;Objects implementing an interface that is declared to be iterable support being iterated over to obtain a sequence of values.
Note: In the JavaScript language binding, an interface that is iterable will have
entries
,forEach
,keys
,values
, and%Symbol.iterator%
properties on its interface prototype object.If a single type parameter is given, then the interface has a value iterator and provides values of the specified type. If two type parameters are given, then the interface has a pair iterator and provides value pairs with the given types.
A value pair, given a key type and a value type, is a struct with two items:
an item whose name is "key", which is referred to as the value pair's key, and whose value is an IDL value of the key type;
an item whose name is "value", which is referred to as the value pair's value, and whose value is an IDL value of the value type.
A value iterator must only be declared on an interface that 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 a list of value pairs for each instance of the interface, which is the list of value pairs to iterate over.
The JavaScript forEach method that is generated for a value iterator invokes its callback like Array.prototype.forEach does, and the forEach method for a pair iterator invokes its callback like Map.prototype.forEach does.
Since value iterators are currently allowed only on interfaces that support indexed properties, it makes sense to use an Array-like forEach method. There could be a need for value iterators (a) on interfaces that do not support indexed properties, or (b) with a forEach method that instead invokes its callback like Set.prototype.forEach (where the key is the same as the value). If you’re creating an API that needs such a forEach method, please file an issue.
Note: This is how array iterator objects work. For interfaces that support indexed properties, the iterator objects returned by
entries
,keys
,values
, and%Symbol.iterator%
are actual array iterator objects.Interfaces with an iterable declaration must not have any attributes, constants, or regular operations named "
entries
", "forEach
", "keys
", or "values
", or have any inherited interfaces that have attributes, constants, or regular operations with these names.Consider the following interface
SessionManager
, which allows access to a number ofSession
objects keyed by username:[Exposed =Window ]interface SessionManager {Session getSessionForUser (DOMString username );iterable <DOMString ,Session >; [Exposed =Window ]interface Session {readonly attribute DOMString username ; // ...The behavior of the iterator could be defined like so:
The value pairs to iterate over are the list of value pairs with the key being the username and the value being the open
Session
object on theSessionManager
object corresponding to that username, sorted by username.In the JavaScript language binding, the interface prototype object for the
SessionManager
interface has avalues
method that is a function, which, when invoked, returns an iterator object that itself has anext
method that returns the next value to be iterated over. It haskeys
andentries
methods that iterate over the usernames of session objects and username/Session
object pairs, respectively. It also has a%Symbol.iterator%
method that allows aSessionManager
to be used in afor..of
loop that has the same value as theentries
method:// Get an instance of SessionManager. // Assume that it has sessions for two users, "anna" and "brian". var sm= getSessionManager(); typeof SessionManager. prototype. values; // Evaluates to "function" var it= sm. values(); // values() returns an iterator object String( it); // Evaluates to "[object SessionManager Iterator]" typeof it. next; // Evaluates to "function" // This loop will log "anna" and then "brian". for (;;) { let result= it. next(); if ( result. done) { break ; let session= result. value; console. log( session. username); // This loop will also log "anna" and then "brian". for ( let usernameof sm. keys()) { console. log( username); // Yet another way of accomplishing the same. for ( let [ username, session] of sm) { console. log( username); An interface must not have more than one iterable declaration. The inherited interfaces of an interface with an iterable declaration must not also have an iterable declaration. An interface with an iterable declaration and its inherited interfaces must not have a maplike declaration, setlike declaration, or asynchronously iterable declaration.
The following extended attributes are applicable to iterable declarations: [
CrossOriginIsolated
], [Exposed
], and [SecureContext
].Iterable ::iterable < TypeWithExtendedAttributes OptionalType > ; OptionalType ::, TypeWithExtendedAttributes 2.5.10. Asynchronously iterable declarations
An interface can be declared to be asynchronously iterable by using an asynchronously iterable declaration (matching
AsyncIterable ) in the body of the interface.interface interface_identifier {async iterable <value_type >;async iterable <value_type >(/* arguments... */);async iterable <key_type ,value_type >;async iterable <key_type ,value_type >(/* arguments... */);Objects that implement an interface that is declared to be asynchronously iterable support being iterated over asynchronously to obtain a sequence of values.
If a single type parameter is given, then the interface has a value asynchronously iterable declaration and asynchronously provides values of the specified type. If two type parameters are given, then the interface has a pair asynchronously iterable declaration and asynchronously provides value pairs with the given types.
If given, an asynchronously iterable declaration's arguments (matching
In the JavaScript language binding, an interface that is asynchronously iterable will haveArgumentList ) must all be optional arguments.%Symbol.asyncIterator%
andvalues
properties on its interface prototype object. If the interface has a pair asynchronously iterable declaration, it will additionally haveentries
andkeys
properties. All of these methods can be passed optional arguments, which correspond to the argument list in the asynchronously iterable declaration, and are processed by the asynchronous iterator initialization steps, if any exist.With this in mind, the requirement that all arguments be optional ensures that, in the JavaScript binding,
for
-await
-of
can work directly on instances of the interface, sincefor
-await
-of
calls the%Symbol.asyncIterator%
method with no arguments.Prose accompanying an interface with an asynchronously iterable declaration must define a get the next iteration result algorithm. This algorithm receives the instance of the interface that is being iterated, as well as the async iterator itself (which can be useful for storing state). It must return a
Promise
that either rejects, resolves with a special end of iteration value to signal the end of the iteration, or resolves with one of the following:for value asynchronously iterable declarations: a value of the type given in the declaration;
for pair asynchronously iterable declarations: a tuple containing a value of the first type given in the declaration, and a value of the second type given in the declaration.
The prose may also define an asynchronous iterator return algorithm. This algorithm receives the instance of the interface that is being iterated, the async iterator itself, and a single argument value of type
any
. This algorithm is invoked in the case of premature termination of the async iterator. It must return aPromise
; if that promise fulfills, its fulfillment value will be ignored, but if it rejects, that failure will be passed on to users of the async iterator API.In the JavaScript binding, this algorithm allows customizing the behavior when the async iterator’s
return()
method is invoked. This most commonly occurs when abreak
orreturn
statement causes an exit from afor
-await
-of
loop.We could add a similar hook for
throw()
. So far there has been no need, but if you are creating an API that needs such capabilities, please file an issue.The prose may also define asynchronous iterator initialization steps. These receive the instance of the interface being iterated, the newly-created iterator object, and a list of IDL values representing the arguments passed, if any.
Interfaces with an asynchronously iterable declaration must not have any attributes, constants, or regular operations named "
entries
", "keys
", or "values
", or have any inherited interfaces that have attributes, constants, or regular operations with these names.Consider the following interface
SessionManager
, which allows access to a number ofSession
objects keyed by username:[Exposed =Window ]interface SessionManager {Session getSessionForUser (DOMString username );async iterable <DOMString ,Session >; [Exposed =Window ]interface Session {readonly attribute DOMString username ; // ...The behavior of the iterator could be defined like so:
The asynchronous iterator initialization steps for a
SessionManager
async iterator iterator are:Set iterator’s current state to "not yet started".
To get the next iteration result for a
SessionManager
manager and its async iterator iterator:Let promise be a new promise.
Let key be the following value, if it exists, or null otherwise:
If iterator’s current state is "not yet started" the smallest username in manager’s open sessions, in lexicographical order
Otherwise the smallest username in manager’s open sessions that is greater than iterator’s current state, in lexicographical order
Note: iterator’s current state might no longer be present in the open sessions.
If key is null, then:
Resolve promise with end of iteration.
Otherwise:
Let session be the
Session
object corresponding to key.Resolve promise with (username, session).
Set iterator’s current state to username.
Return promise.
In the JavaScript language binding, the interface prototype object for the
SessionManager
interface has avalues
method that is a function, which, when invoked, returns an asynchronous iterator object that itself has anext
method that returns the next value to be iterated over. It haskeys
andentries
methods that iterate over the usernames of session objects and (username,Session
) object pairs, respectively. It also has a%Symbol.asyncIterator%
method that allows aSessionManager
to be used in afor await..of
loop that has the same value as theentries
method:// Get an instance of SessionManager. // Assume that it has sessions for two users, "anna" and "brian". var sm= getSessionManager(); typeof SessionManager. prototype. values; // Evaluates to "function" var it= sm. values(); // values() returns an iterator object typeof it. next; // Evaluates to "function" // This loop will log "anna" and then "brian". for await ( let usernameof sm. keys()) { console. log( username); // Yet another way of accomplishing the same. for await ( let [ username, session] of sm) { console. log( username); An interface must not have more than one asynchronously iterable declaration. The inherited interfaces of an interface with an asynchronously iterable declaration must not also have an asynchronously iterable declaration. An interface with an asynchronously iterable declaration and its inherited interfaces must not have a maplike declaration, setlike declaration, or iterable declaration.
The following extended attributes are applicable to asynchronously iterable declarations: [
CrossOriginIsolated
], [Exposed
], and [SecureContext
].these extended attributes are not currently taken into account. When they are, the effect will be as you would expect.
AsyncIterable ::async iterable < TypeWithExtendedAttributes OptionalType > OptionalArgumentList ; OptionalArgumentList ::( ArgumentList ) 2.5.11. Maplike declarations
An interface can be declared to be maplike by using a maplike declaration (matching
ReadWriteMaplike orreadonly MaplikeRest ) in the body of the interface.interface interface_identifier {readonly maplike <key_type ,value_type >;maplike <key_type ,value_type >;Objects implementing an interface that is declared to be maplike represent an ordered map of key–value pairs, initially empty, known as that object’s map entries. The types used for the keys and values are given in the angle brackets of the maplike declaration. Keys are required to be unique.
Specification authors can modify the contents of the map entries, which will automatically be reflected in the contents of the object as observed by JavaScript code.
Maplike interfaces support an API for querying the map entries appropriate for the language binding. If the
readonly keyword is not used, then it also supports an API for modifying the map entries.Note: In the JavaScript language binding, the API for interacting with the map entries is similar to that available on JavaScript
Map
objects. If thereadonly keyword is used, this includesentries
,forEach
,get
,has
,keys
,values
,%Symbol.iterator%
methods, and asize
getter. For read–write maplikes, it also includesclear
,delete
, andset
methods.Maplike interfaces must not have any attributes, constants, or regular operations named "
entries
", "forEach
", "get
", "has
", "keys
", "size
", or "values
", or have any inherited interfaces that have attributes, constants, or regular operations with these names.Read–write maplike interfaces must not have any attributes or constants named "
clear
", "delete
", or "set
", or have any inherited interfaces that have attributes or constants with these names.Note: Read-write maplike interfaces can have regular operations named "
clear
", "delete
", or "set
", which will override the default implementation of those methods (defined in § 3.7.11 Maplike declarations). If such regular operations are defined, they must match the input and output expectations of each method, defined in their default implementation sections.An interface must not have more than one maplike declaration. The inherited interfaces of a maplike interface must not also have a maplike declaration. A maplike interface and its inherited interfaces must not have an iterable declaration, an asynchronously iterable declaration, a setlike declaration, or an indexed property getter.
ReadOnlyMember ::readonly ReadOnlyMemberRest ReadOnlyMemberRest ::AttributeRest MaplikeRest SetlikeRest ReadWriteMaplike ::MaplikeRest MaplikeRest ::maplike < TypeWithExtendedAttributes , TypeWithExtendedAttributes > ; No extended attributes defined in this specification are applicable to maplike declarations.
Add example.
2.5.12. Setlike declarations
An interface can be declared to be setlike by using a setlike declaration (matching
ReadWriteSetlike orreadonly SetlikeRest ) in the body of the interface.interface interface_identifier {readonly setlike <type >;setlike <type >;Objects implementing an interface that is declared to be setlike represent an ordered set of values, initially empty, known as that object’s set entries. The type of the values is given in the angle brackets of the setlike declaration. Values are required to be unique.
Specification authors can modify the contents of the set entries, which will automatically be reflected in the contents of the object as observed by JavaScript code.
Setlike interfaces support an API for querying the set entries appropriate for the language binding. If the
readonly keyword is not used, then it also supports an API for modifying the set entries.Note: In the JavaScript language binding, the API for interacting with the set entries is similar to that available on JavaScript
Set
objects. If thereadonly keyword is used, this includesentries
,forEach
,has
,keys
,values
,%Symbol.iterator%
methods, and asize
getter. For read–write setlikes, it also includesadd
,clear
, anddelete
methods.Setlike interfaces must not have any attributes, constants, or regular operations named "
entries
", "forEach
", "has
", "keys
", "size
", or "values
", or have any inherited interfaces that have attributes, constants, or regular operations with these names.Read–write setlike interfaces must not have any attributes or constants named "
add
", "clear
", or "delete
", or have any inherited interfaces that have attributes or constants with these names.Note: Read-write setlike interfaces can have regular operations named "
add
", "clear
", or "delete
", which will override the default implementation of those methods (defined in § 3.7.12 Setlike declarations). If such regular operations are defined, they must match the input and output expectations of each method, defined in their default implementation sections.An interface must not have more than one setlike declaration. The inherited interfaces of a setlike interface must not also have a setlike declaration. A setlike interface and its inherited interfaces must not have an iterable declaration, an asynchronously iterable declaration, a maplike declaration, or an indexed property getter.
ReadOnlyMember ::readonly ReadOnlyMemberRest ReadOnlyMemberRest ::AttributeRest MaplikeRest SetlikeRest ReadWriteSetlike ::SetlikeRest SetlikeRest ::setlike < TypeWithExtendedAttributes > ; No extended attributes defined in this specification are applicable to setlike declarations.
Add example.
2.6. Namespaces
A namespace is a definition (matching
Namespace) that declares a global singleton with associated behaviors. namespace identifier { /* namespace_members... */A namespace is a specification of a set of namespace members (matching
NamespaceMembers ), which are the regular operations, read only regular attributes, and constants that appear between the braces in the namespace declaration. These operations and attributes describe the behaviors packaged into the namespace.As with interfaces, the IDL for namespaces can be split into multiple parts by using partial namespace definitions (matching
partial Namespace ). The identifier of a partial namespace definition must be the same as the identifier of a namespace definition. All of the members that appear on each of the partial namespace definitions are considered to be members of the namespace itself.namespace SomeNamespace { /* namespace_members... */partial namespace SomeNamespace { /* namespace_members... */Note: As with partial interface definitions, partial namespace definitions are intended for use as a specification editorial aide, allowing the definition of a namespace to be separated over more than one section of the document, and sometimes multiple documents.
The order that members appear in has significance for property enumeration in the JavaScript binding.
Note that unlike interfaces or dictionaries, namespaces do not create types.
Of the extended attributes defined in this specification, only the [
CrossOriginIsolated
], [Exposed
], and [SecureContext
] extended attributes are applicable to namespaces.Namespaces must be annotated with the [
Exposed
] extended attribute.Partial ::partial PartialDefinition PartialDefinition ::interface PartialInterfaceOrPartialMixin PartialDictionary Namespace Namespace ::namespace identifier { NamespaceMembers } ; NamespaceMembers ::ExtendedAttributeList NamespaceMember NamespaceMembers NamespaceMember ::RegularOperation readonly AttributeRest Const The following IDL fragment defines a namespace.
namespace VectorUtils {readonly attribute Vector unit ;double dotProduct (Vector x ,Vector y );Vector crossProduct (Vector x ,Vector y );A JavaScript implementation would then expose a global
VectorUtils
data property which was a simple object (with prototype%Object.prototype%
) with enumerable data properties for each declared operation, and enumerable get-only accessors for each declared attribute:Object. getPrototypeOf( VectorUtils); // Evaluates to Object.prototype. Object. keys( VectorUtils); // Evaluates to ["dotProduct", "crossProduct"]. Object. getOwnPropertyDescriptor( VectorUtils, "dotProduct" ); // Evaluates to { value: <a function>, enumerable: true, configurable: true, writable: true }. Object. getOwnPropertyDescriptor( VectorUtils, "unit" ); // Evaluates to { get: <a function>, enumerable: true, configurable: true }. 2.7. Dictionaries
A dictionary is a definition (matching
Dictionary) used to define an ordered map data type with a fixed, ordered set of entries, termed dictionary members, where keys are strings and values are of a particular type specified in the definition. dictionary identifier { /* dictionary_members... */Dictionary instances do not retain a reference to their language-specific representations (e.g., the corresponding JavaScript object). So for example, returning a dictionary from an operation will result in a new JavaScript object being created from the current values of the dictionary. And, an operation that accepts a dictionary as an argument will perform a one-time conversion from the given JavaScript value into the dictionary, based on the current properties of the JavaScript object. Modifications to the dictionary will not be reflected in the corresponding JavaScript object, and vice-versa.
Dictionaries must not be used as the type of an attribute or constant.
A dictionary can be defined to inherit from another dictionary. If the identifier of the dictionary is followed by a colon and a identifier, then that identifier identifies the inherited dictionary. The identifier must identify a dictionary.
A dictionary must not be declared such that its inheritance hierarchy has a cycle. That is, a dictionary A cannot inherit from itself, nor can it inherit from another dictionary B that inherits from A, and so on.
dictionary Base { /* dictionary_members... */dictionary Derived :Base { /* dictionary_members... */The inherited dictionaries of a given dictionary D is the set of all dictionaries that D inherits from, directly or indirectly. If D does not 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.
Dictionary members can be specified as required, meaning that converting a language-specific value to a dictionary requires providing a value for that member. Any dictionary member that is not required is optional.
Note that specifying dictionary members as required only has an observable effect when converting other representations of dictionaries (like a JavaScript value supplied as an argument to an operation) to an IDL dictionary. Specification authors should leave the members optional in all other cases, including when a dictionary type is used solely as the return type of operations.
A given dictionary value of type D can have entries for each of the dictionary members defined on D and on any of D’s inherited dictionaries. Dictionary members that are specified as required, or that are specified as having a default value, will always have such corresponding entries. Other members' entries might or might not exist in the dictionary value.
In the JavaScript binding, a value of
undefined for the property corresponding to a dictionary member is treated the same as omitting that property. Thus, it will cause an error if the member is required, or will trigger the default value if one is present, or will result in no entry existing in the dictionary value otherwise.As with operation argument default values, it is strongly encouraged not to use
true as the default value forboolean
-typed dictionary members, as this can be confusing for authors who might otherwise expect the default conversion ofundefined to be used (i.e.,false ). [API-DESIGN-PRINCIPLES]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, as long as those entries have the correct types, and there are entries present for any required or defaulted dictionary members.
dictionary Descriptor {DOMString name ;sequence <unsigned long >serviceIdentifiers ;A
Descriptor
dictionary could be created as in the following steps:Let identifiers be « 1, 3, 7 ».
Return «[ "name" → "test", "serviceIdentifiers" → identifiers ]».
Each dictionary member (matching
DictionaryMember ) is specified as a type (matchingType ) followed by an identifier (given by anidentifier token following the type). The identifier is the key name of the key–value pair. If theType is an identifier followed by? , then the identifier must identify an interface, enumeration, callback function, callback interface or typedef. If the dictionary member type is an identifier not followed by? , then the identifier must identify any one of those definitions or a dictionary.If the type of the dictionary member, after resolving typedefs, is a nullable type, its inner type must not be a dictionary type.
dictionary identifier {type identifier ;If the identifier for an optional dictionary member is followed by a U+003D (=) and a value (matching
DefaultValue ), then that gives the dictionary member its default value, which is the value used by default when author code or specification text does not provide a value for that member.dictionary identifier {type identifier = "value";When a boolean literal token (
true orfalse ), thenull token, aninteger token, adecimal token, one of the three special floating point literal values (Infinity ,-Infinity orNaN ), astring token, the two token sequence[] , or the two token sequence{} is used as the default value, it is interpreted in the same way as for an operation's optional argument default value.If the type of the dictionary member is an enumeration, then its default value if specified must be one of the enumeration’s values.
If the type of the dictionary member is preceded by the
required keyword, the member is considered a required dictionary member.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 DAs with interfaces, the IDL for dictionaries can be split into multiple parts by using partial dictionary definitions (matching
partial Dictionary ). The identifier of a partial dictionary definition must be the same as the identifier of a dictionary definition. All of the members that appear on each of the partial dictionary definitions are considered to be members of the dictionary itself.dictionary SomeDictionary { /* dictionary_members... */partial dictionary SomeDictionary { /* dictionary_members... */Note: As with partial interface definitions, partial dictionary definitions are intended for use as a specification editorial aide, allowing the definition of an interface to be separated over more than one section of the document, and sometimes multiple documents.
The order of the dictionary members on a given dictionary is such that inherited dictionary members are ordered before non-inherited members, and the dictionary members on the one dictionary definition (including any partial dictionary definitions) are ordered lexicographically by the Unicode codepoints that comprise their identifiers.
For example, with the following definitions:
dictionary B :A {long b ;long a ;dictionary A {long c ;long g ;dictionary C :B {long e ;long f ;partial dictionary A {long h ;long d ;the order of the dictionary members of a dictionary value of type
C
is c, d, g, h, a, b, e, f.Dictionaries need to have their members ordered because in some language bindings the behavior observed when passing a dictionary value to a platform object depends on the order the dictionary members are fetched. For example, consider the following additional interface:
[Exposed =Window ]interface Something {undefined f (A a );and this JavaScript code:
var something= getSomething(); // Get an instance of Something. var x= 0 ; var dict= { }; Object. defineProperty( dict, "d" , { get: function () { return ++ x; } }); Object. defineProperty( dict, "c" , { get: function () { return ++ x; } }); something. f( dict); The order that the dictionary members are fetched in determines what values they will be taken to have. Since the order for
A
is defined to be c then d, the value for c will be 1 and the value for d will be 2.The identifier of a dictionary member must not be the same as that of another dictionary member defined on the dictionary or on that dictionary’s inherited dictionaries.
No extended attributes are applicable to dictionaries.
Partial ::partial PartialDefinition PartialDefinition ::interface PartialInterfaceOrPartialMixin PartialDictionary Namespace Dictionary ::dictionary identifier Inheritance { DictionaryMembers } ; DictionaryMembers ::DictionaryMember DictionaryMembers DictionaryMember ::ExtendedAttributeList DictionaryMemberRest DictionaryMemberRest ::required TypeWithExtendedAttributes identifier ; Type identifier Default ; PartialDictionary ::dictionary identifier { DictionaryMembers } ; Default ::= DefaultValue DefaultValue ::ConstValue string undefined Inheritance ::: identifier One use of dictionary types is to allow a number of optional arguments to an operation without being constrained as to the order they are specified at the call site. For example, consider the following IDL fragment:
[Exposed =Window ]interface Point {constructor ();attribute double x ;attribute double y ;dictionary PaintOptions {DOMString fillPattern = "black";DOMString strokePattern ;Point position ; [Exposed =Window ]interface GraphicsContext {undefined drawRectangle (double width ,double height ,optional PaintOptions options );In a JavaScript implementation of the IDL, an Object can be passed in for the optional
PaintOptions
dictionary:// Get an instance of GraphicsContext. var ctx= getGraphicsContext(); // Draw a rectangle. ctx. drawRectangle( 300 , 200 , { fillPattern: "red" , position: new Point( 10 , 10 ) }); The members of
PaintOptions
are optional. IffillPattern
is omitted, the definition ofdrawRectangle
can assume that it has the given default values and not include explicit wording to handle its omission.drawRectangle
needs to explicitly handle the case wherestrokePattern
andposition
are omitted.2.8. Exceptions
An exception is a type of object that represents an error and which can be thrown or treated as a first class value by implementations. Web IDL has a number of pre-defined exceptions that specifications can reference and throw in their definition of operations, attributes, and so on. Custom exception types can also be defined, as interfaces that inherit from
DOMException
.A simple exception is identified by one of the following types:
EvalError
RangeError
ReferenceError
TypeError
URIError
These correspond to all of the JavaScript error objects (apart from
SyntaxError
andError
, which are deliberately omitted as they are reserved for use by the JavaScript parser and by authors, respectively). The meaning of each simple exception matches its corresponding error object in the JavaScript specification.The second kind of exception is a
DOMException
, which provides further programmatically-introspectable detail on the error that occurred by giving a name. Such names are drawn from theDOMException
names table below.As
DOMException
is an interface type, it can be used as a type in IDL. This allows for example an operation to be declared to have aDOMException
return type. This is generally a bad pattern, however, as exceptions are meant to be thrown and not returned.The final kind of exception is a derived interface of
DOMException
. These are more complicated, and thus described in the dedicated section § 2.8.2 DOMException derived interfaces.Simple exceptions can be created by providing their type name. A
DOMException
can be created by providing its name followed byDOMException
. Exceptions can also be thrown, by providing the same details required to create one. In both cases, the caller may provide additional information about what the exception indicates, which is useful when constructing the exception’s message.Here is are some examples of wording to use to create and throw exceptions. To throw a new simple exception whose type is
TypeError
:To throw a new
DOMException
with name "NotAllowedError
":Throw a "
NotAllowedError
"DOMException
.To create a new
DOMException
with name "SyntaxError
":Let object be a newly created "
SyntaxError
"DOMException
.To reject a promise with a new
DOMException
with name "OperationError
":Reject p with an "OperationError
"DOMException
.An example of including additional information used to construct the exception message would
Throw a "SyntaxError
"DOMException
indicating that the given value had disallowed trailing spaces.Such additional context is most helpful to implementers when it is not immediately obvious why the exception is being thrown, e.g., because there are many different steps in the algorithm which throw a "
SyntaxError
"DOMException
. In contrast, if your specification throws a "NotAllowedError
"DOMException
immediately after checking if the user has provided permission to use a given feature, it’s fairly obvious what sort of message the implementation ought to construct, and so specifying it is not necessary.The resulting behavior from creating and throwing an exception is language binding specific.
See § 3.14.3 Creating and throwing exceptions for details on what creating and throwing an exception entails in the JavaScript language binding.
2.8.1. Base
DOMException
error namesThe
DOMException
names table below lists all the allowed names for instances of the baseDOMException
interface, along with a description of what such names mean, and legacy numeric error code values.Interfaces inheriting from
DOMException
, in the manner described in § 2.8.2 DOMException derived interfaces, will have their own names, not listed in this table.When creating or throwing a
DOMException
, specifications must use one of these names. If a specification author believes none of these names are a good fit for their case, they must file an issue to discuss adding a new name to the shared namespace, so that the community can coordinate such efforts. Note that adding new use-case-specific names is only important if you believe web developers will discriminate multiple error conditions arising from a single API.The
DOMException
names marked as deprecated are kept for legacy purposes, but their usage is discouraged.Note: Don’t confuse the "
Description Legacy code name and value "SyntaxError
"DOMException
defined here with JavaScript’sSyntaxError
. "SyntaxError
"DOMException
is used to report parsing errors in web APIs, for example when parsing selectors, while the JavaScriptSyntaxError
is reserved for the JavaScript parser. To help disambiguate this further, always favor the "SyntaxError
"DOMException
notation over just usingSyntaxError
to refer to theDOMException
. [DOM]IndexSizeError
" Deprecated. UseRangeError
instead.INDEX_SIZE_ERR
(1) "HierarchyRequestError
" The operation would yield an incorrect node tree. [DOM]HIERARCHY_REQUEST_ERR
(3) "WrongDocumentError
" The object is in the wrong document. [DOM]WRONG_DOCUMENT_ERR
(4) "InvalidCharacterError
" The string contains invalid characters.INVALID_CHARACTER_ERR
(5) "NoModificationAllowedError
" The object can not be modified.NO_MODIFICATION_ALLOWED_ERR
(7) "NotFoundError
" The object can not be found here.NOT_FOUND_ERR
(8) "NotSupportedError
" The operation is not supported.NOT_SUPPORTED_ERR
(9) "InUseAttributeError
" The attribute is in use by another element. [DOM]INUSE_ATTRIBUTE_ERR
(10) "InvalidStateError
" The object is in an invalid state.INVALID_STATE_ERR
(11) "SyntaxError
" The string did not match the expected pattern.SYNTAX_ERR
(12) "InvalidModificationError
" The object can not be modified in this way.INVALID_MODIFICATION_ERR
(13) "NamespaceError
" The operation is not allowed by Namespaces in XML. [XML-NAMES]NAMESPACE_ERR
(14) "InvalidAccessError
" Deprecated. UseTypeError
for invalid arguments, "NotSupportedError
"DOMException
for unsupported operations, and "NotAllowedError
"DOMException
for denied requests instead.INVALID_ACCESS_ERR
(15) "TypeMismatchError
" Deprecated. UseTypeError
instead.TYPE_MISMATCH_ERR
(17) "SecurityError
" The operation is insecure.SECURITY_ERR
(18) "NetworkError
" A network error occurred.NETWORK_ERR
(19) "AbortError
" The operation was aborted.ABORT_ERR
(20) "URLMismatchError
" Deprecated.URL_MISMATCH_ERR
(21) "QuotaExceededError
" The quota has been exceeded.QUOTA_EXCEEDED_ERR
(22) "TimeoutError
" The operation timed out.TIMEOUT_ERR
(23) "InvalidNodeTypeError
" The supplied node is incorrect or has an incorrect ancestor for this operation. [DOM]INVALID_NODE_TYPE_ERR
(24) "DataCloneError
" The object can not be cloned.DATA_CLONE_ERR
(25) "EncodingError
" The encoding operation (either encoded or decoding) failed. "NotReadableError
" The I/O read operation failed. "UnknownError
" The operation failed for an unknown transient reason (e.g. out of memory). "ConstraintError
" A mutation operation in a transaction failed because a constraint was not satisfied. [INDEXEDDB] "DataError
" Provided data is inadequate. "TransactionInactiveError
" A request was placed against a transaction which is currently not active, or which is finished. [INDEXEDDB] "ReadOnlyError
" The mutating operation was attempted in a "readonly" transaction. [INDEXEDDB] "VersionError
" An attempt was made to open a database using a lower version than the existing version. [INDEXEDDB] "OperationError
" The operation failed for an operation-specific reason. "NotAllowedError
" The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission. "OptOutError
" The user opted out of the process.2.8.2.
DOMException
derived interfacesWhen an exception needs to carry additional programmatically-introspectable information, beyond what can be provided with a
DOMException
's name, specification authors can create an interface which inherits fromDOMException
. Such interfaces need to follow certain rules, in order to have a predictable shape for developers. Specifically:The identifier of the interface must end with
Error
, and must not be any of the names in theDOMException
names table.The interface must have a constructor operation which sets the instance’s name to the interface’s identifier.
Their constructor operation must take as its first parameter an optional
DOMString
named message defaulting to the empty string, and must set the instance’s message to message.Their constructor operation should take as its second parameter a dictionary containing the additional information that needs to be exposed.
They should have read only attributes, whose names are the same as the members of the constructor dictionary, which return the values accepted by the constructor operation.
They should be serializable objects, whose serialization steps and deserialization steps preserve the additional information.
These requirements mean that the inherited
The definition for acode
property of these interfaces will always return 0.DOMException
derived interface which carries along an additional "protocol error code", which is derived from what the server sent over some some hypothetical network protocol "protocol X", could look something like this:[Exposed =Window ,Serializable ]interface ProtocolXError :DOMException {constructor (optional DOMString message = "",ProtocolXErrorOptions options );readonly attribute unsigned long long errorCode ;dictionary ProtocolXErrorOptions {required [EnforceRange ]unsigned long long errorCode ;Every
TheProtocolXError
instance has an error code, a number.new ProtocolXError(message, options)
constructor steps are:Set this's name to "
ProtocolXError
".Set this's message to message.
Set this's error code to options["
errorCode
"].Their serialization steps, given value and serialized, are:
ProtocolXError
objects are serializable objects.Run the
DOMException
serialization steps given value and serialized.Set serialized.[[ErrorCode]] to value’s error code.
Their deserialization steps, given serialized and value, are:Run the
DOMException
deserialization steps given serialized and value.Set value’s error code to serialized.[[ErrorCode]].
To create or throw a
DOMException
derived interface, supply its interface identifier as well as the additional information needed to construct it.To throw an instance of the
ProtocolXError
exemplified above:Throw a
ProtocolXError
whose error code is 42.2.9. Enumerations
An enumeration is a definition (matching
Enum) used to declare a type whose valid values are a set of predefined strings. Enumerations can be used to restrict the possible DOMString
values that can be assigned to an attribute or passed to an operation.enum identifier {"enum" ,"values" /* , ... */ };The enumeration values are specified as a comma-separated list of
string literals. The list of enumeration values must not include duplicates.It is strongly suggested that enumeration values be all lowercase, and that multiple words be separated using dashes or not be separated at all, unless there is a specific reason to use another value naming scheme. For example, an enumeration value that indicates an object should be created could be named "
createobject
" or "create-object
". Consider related uses of enumeration values when deciding whether to dash-separate or not separate enumeration value words so that similar APIs are consistent.The behavior when a string value that is not a valid enumeration value is used when assigning to an attribute, or passed as an operation argument, whose type is the enumeration, is language binding specific.
Note: In the JavaScript binding, assignment of an invalid string value to an attribute is ignored, while passing such a value in other contexts (for example as an operation argument) results in an exception being thrown.
No extended attributes defined in this specification are applicable to enumerations.
Enum ::enum identifier { EnumValueList } ; EnumValueList ::string EnumValueListComma EnumValueListComma ::, EnumValueListString EnumValueListString ::string EnumValueListComma The following IDL fragment defines an enumeration that is used as the type of an attribute and an operation argument:
enum MealType {"rice" ,"noodles" ,"other" }; [Exposed =Window ]interface Meal {attribute MealType type ;attribute double size ; // in gramsundefined initialize (MealType type ,double size );A JavaScript implementation would restrict the strings that can be assigned to the type property or passed to the initializeMeal function to those identified in the enumeration.
var meal= getMeal(); // Get an instance of Meal. meal. initialize( "rice" , 200 ); // Operation invoked as normal. try { meal. initialize( "sandwich" , 100 ); // Throws a TypeError. } catch ( e) { meal. type= "noodles" ; // Attribute assigned as normal. meal. type= "dumplings" ; // Attribute assignment ignored. meal. type== "noodles" ; // Evaluates to true. 2.10. Callback functions
The “Custom DOM Elements” spec wants to use callback function types for platform object provided functions. Should we rename “callback functions” to just “functions” to make it clear that they can be used for both purposes?
A callback function is a definition (matching
callback CallbackRest) used to declare a function type. callback identifier =return_type (/* arguments... */);Note: See also the similarly named callback interfaces.
The identifier on the left of the equals sign gives the name of the callback function and the return type and argument list (matching
Type andArgumentList ) on the right side of the equals sign gives the signature of the callback function type.Callback functions must not be used as the type of a constant.
The following extended attribute is applicable to callback functions: [
LegacyTreatNonObjectAsNull
].CallbackOrInterfaceOrMixin ::callback CallbackRestOrInterface interface InterfaceOrMixin CallbackRest ::identifier = Type ( ArgumentList ) ; The following IDL fragment defines a callback function used for an API that invokes a user-defined function when an operation is complete.
callback AsyncOperationCallback =undefined (DOMString status ); [Exposed =Window ]interface AsyncOperations {undefined performOperation (AsyncOperationCallback whenFinished );In the JavaScript language binding, a function object is passed as the operation argument.
var ops= getAsyncOperations(); // Get an instance of AsyncOperations. ops. performOperation( function ( status) { window. alert( "Operation finished, status is " + status+ "." ); 2.11. Typedefs
A typedef is a definition (matching
Typedef) used to declare a new name for a type. This new name is not exposed by language bindings; it is purely used as a shorthand for referencing the type in the IDL. typedef type identifier ;The type being given a new name is specified after the
typedef keyword (matchingTypeWithExtendedAttributes ), and theidentifier token following the type gives the name.The
Type must not be the identifier of the same or another typedef.No extended attributes defined in this specification are applicable to typedefs.
Typedef ::typedef TypeWithExtendedAttributes identifier ; The following IDL fragment demonstrates the use of typedefs to allow the use of a short identifier instead of a long sequence type.
[Exposed =Window ]interface Point {attribute double x ;attribute double y ;typedef sequence <Point >Points ; [Exposed =Window ]interface Widget {boolean pointWithinBounds (Point p );boolean allPointsWithinBounds (Points ps );2.12. Objects implementing interfaces
In a given implementation of a set of IDL fragments, an object can be described as being a platform object.
Platform objects are objects that implement an interface.
Legacy platform objects are platform objects that implement an interface which does not have a [
Global
] extended attribute, and which supports indexed properties, named properties, or both.In a browser, for example, the browser-implemented DOM objects (implementing interfaces such as
Node
andDocument
) that provide access to a web page’s contents to JavaScript running in the page would be platform objects. These objects might be exotic objects, implemented in a language like C++, or they might be native JavaScript objects. Regardless, an implementation of a given set of IDL fragments needs to be able to recognize all platform objects that are created by the implementation. This might be done by having some internal state that records whether a given object is indeed a platform object for that implementation, or perhaps by observing that the object is implemented by a given internal C++ class. How exactly platform objects are recognized by a given implementation of a set of IDL fragments is implementation specific.All other objects in the system would not be treated as platform objects. For example, assume that a web page opened in a browser loads a JavaScript library that implements DOM Core. This library would be considered to be a different implementation from the browser provided implementation. The objects created by the JavaScript library that implement the
Node
interface will not be treated as platform objects that implementNode
by the browser implementation.Callback interfaces, on the other hand, can be implemented by any JavaScript object. This allows Web APIs to invoke author-defined operations. For example, the DOM Events implementation allows authors to register callbacks by providing objects that implement the
EventListener
interface.2.13. Types
This section lists the types supported by Web IDL, the set of values or Infra type corresponding to each type, and how constants of that type are represented.
The following types are known as integer types:
byte
,octet
,short
,unsigned short
,long
,unsigned long
,long long
andunsigned long long
.The following types are known as numeric types: the integer types,
float
,unrestricted float
,double
andunrestricted double
.The primitive types are
bigint
,boolean
and the numeric types.The string types are
DOMString
, all enumeration types,ByteString
andUSVString
.The buffer types are
ArrayBuffer
andSharedArrayBuffer
.The typed array types are
Int8Array
,Int16Array
,Int32Array
,Uint8Array
,Uint16Array
,Uint32Array
,Uint8ClampedArray
,BigInt64Array
,BigUint64Array
,Float16Array
,Float32Array
, andFloat64Array
.The buffer view types are
DataView
and the typed array types.The buffer source types are the buffer types and the buffer view types.
The
object
type, all interface types, and all callback interface types are known as object types.When conversions are made from language binding specific types to IDL types in order to invoke an operation or assign a value to an attribute, all conversions necessary will be performed before the specified functionality of the operation or attribute assignment is carried out. If the conversion cannot be performed, then the operation will not run or the attribute will not be updated. In some language bindings, type conversions could result in an exception being thrown. In such cases, these exceptions will be propagated to the code that made the attempt to invoke the operation or assign to the attribute.
Type ::SingleType UnionType Null TypeWithExtendedAttributes ::ExtendedAttributeList Type SingleType ::DistinguishableType PromiseType UnionType ::( UnionMemberType or UnionMemberType UnionMemberTypes ) UnionMemberType ::ExtendedAttributeList DistinguishableType UnionType Null UnionMemberTypes ::or UnionMemberType UnionMemberTypes DistinguishableType ::PrimitiveType Null StringType Null identifier Null sequence < TypeWithExtendedAttributes > Null object Null symbol Null BufferRelatedType Null FrozenArray < TypeWithExtendedAttributes > Null ObservableArray < TypeWithExtendedAttributes > Null RecordType Null undefined Null ConstType ::PrimitiveType identifier PrimitiveType ::UnsignedIntegerType UnrestrictedFloatType boolean octet bigint UnrestrictedFloatType ::unrestricted FloatType FloatType FloatType ::float double UnsignedIntegerType ::unsigned IntegerType IntegerType IntegerType ::short long OptionalLong OptionalLong ::StringType ::ByteString DOMString USVString PromiseType ::Promise < Type > RecordType ::record < StringType , TypeWithExtendedAttributes > Null ::2.13.1. any
The
any
type is the union of all other possible non-union types.The
any
type is like a discriminated union type, in that each of its values has a specific non-any
type associated with it. For example, one value of theany
type is theunsigned long
150, while another is thelong
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.13.2. undefined
The
undefined
type has a unique value.
undefined
constant values in IDL are represented with theundefined token.
undefined
must not be used as the type of an argument in any circumstance (in an operation, callback function, constructor operation, etc), or as the type of a dictionary member, whether directly or in a union. Instead, use an optional argument or a non-required dictionary member.Note: This value was previously spelled
void
, and more limited in how it was allowed to be used.2.13.3. boolean
The
boolean
type has two values:true
andfalse
.
boolean
constant values in IDL are represented with thetrue andfalse tokens.2.13.4. byte
The
byte
type is a signed integer type that has values in the range [−128, 127].
byte
constant values in IDL are represented withinteger tokens.2.13.5. octet
The
octet
type is an unsigned integer type that has values in the range [0, 255].
octet
constant values in IDL are represented withinteger tokens.2.13.6. short
The
short
type is a signed integer type that has values in the range [−32768, 32767].
short
constant values in IDL are represented withinteger tokens.2.13.7. 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 withinteger tokens.2.13.8. long
The
long
type is a signed integer type that has values in the range [−2147483648, 2147483647].
long
constant values in IDL are represented withinteger tokens.2.13.9. 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 withinteger tokens.2.13.10. 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 withinteger tokens.2.13.11. 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 withinteger tokens.2.13.12. 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 withdecimal tokens.Unless there are specific reasons to use a 32-bit floating point type, specifications should use
double
rather thanfloat
, since the set of values that adouble
can represent more closely matches a JavaScript Number.2.13.13. 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 withdecimal tokens.2.13.14. 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 withdecimal tokens.2.13.15. 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 withdecimal tokens.2.13.16. bigint
The
bigint
type is an arbitrary integer type, unrestricted in range.
bigint
constant values in IDL are represented withinteger tokens.2.13.17. DOMString
The
DOMString
type corresponds to strings.Note:
null is not a value of typeDOMString
. To allownull , a nullableDOMString
, written asDOMString?
in IDL, needs to be used.Note: A
DOMString
value might include unmatched surrogate code points. UseUSVString
if this is not desirable.There is no way to represent a constant
DOMString
value in IDL, althoughDOMString
dictionary member default values and operation optional argument default values can be set to the value of astring literal.2.13.18. ByteString
The
ByteString
type corresponds to byte sequences.There is no way to represent a constant
ByteString
value in IDL, althoughByteString
dictionary member default values and operation optional argument default values can be set to the value of astring literal.Specifications should only use
ByteString
for interfacing with protocols that use bytes and strings interchangeably, such as HTTP. In general, strings should be represented withDOMString
values, even if it is expected that values of the string will always be in ASCII or some 8-bit character encoding. Sequences or frozen arrays withoctet
orbyte
elements,Uint8Array
, orInt8Array
should be used for holding 8-bit data rather thanByteString
.2.13.19. USVString
The
USVString
type corresponds to scalar value strings. Depending on the context, these can be treated as sequences of either 16-bit unsigned integer code units or scalar values.There is no way to represent a constant
USVString
value in IDL, althoughUSVString
dictionary member default values and operation optional argument default values can be set to the value of astring literal.Specifications should only use
USVString
for APIs that perform text processing and need a string of scalar values to operate on. Most APIs that use strings should instead be usingDOMString
, which does not make any interpretations of the code units in the string. When in doubt, useDOMString
.2.13.20. object
The
object
type corresponds to the set of all possible non-null object references.There is no way to represent a constant
object
value in IDL.To denote a type that includes all possible object references plus the
null value, use the nullable typeobject?
.2.13.21. 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.2.13.22. Interface types
An identifier that identifies an interface is used to refer to a type that corresponds to the set of all possible non-null references to objects that implement that interface.
An IDL value of the interface type is represented just by an object reference.
There is no way to represent a constant object reference value for a particular interface type in IDL.
To denote a type that includes all possible references to objects implementing the given interface plus the
null value, use a nullable type.2.13.23. Callback interface types
An identifier that identifies a callback interface is used to refer to a type that corresponds to the set of all possible non-null references to objects.
An IDL value of the interface type is represented by a tuple of an object reference and a callback context. The callback context is a language binding specific value, and is used to store information about the execution context at the time the language binding specific object reference is converted to an IDL value.
Note: For JavaScript objects, the callback context is used to hold a reference to the incumbent settings object at the time the Object value is converted to an IDL callback interface type value. See § 3.2.16 Callback interface types.
There is no way to represent a constant object reference value for a particular callback interface type in IDL.
To denote a type that includes all possible references to objects plus the
null value, use a nullable type.2.13.24. 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.
2.13.25. 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 and operation optional argument default values can be set to the value of astring literal.2.13.26. Callback function types
An identifier that identifies a callback function is used to refer to a type whose values are references to objects that are functions with the given signature.
Note: If the [
LegacyTreatNonObjectAsNull
] extended attribute is specified on the definition of the callback function, the values can be references to objects that are not functions.An IDL value of the callback function type is represented by a tuple of an object reference and a callback context.
Note: As with callback interface types, the callback context is used to hold a reference to the incumbent settings object at the time a JavaScript Object value is converted to an IDL callback function type value. See § 3.2.19 Callback function types.
There is no way to represent a constant callback function value in IDL.
2.13.27. Nullable types — T?
A nullable type is an IDL type constructed from an existing type (called the inner type), which just allows the additional value
null to be a member of its set of values. Nullable types are represented in IDL by placing a U+003F (?) character after an existing type. The inner type must not be:
any
,a promise type,
another nullable type, or
a union type that itself includes a nullable type or has a dictionary type as one of its flattened member types.
Note: Although dictionary types can in general be nullable, they cannot when used as the type of an operation argument or a dictionary member.
Nullable type constant values in IDL are represented in the same way that constant values of their inner type would be represented, or with the
null token.For example, a type that allows the values
true ,false andnull is written asboolean?
:[Exposed =Window ]interface NetworkFetcher {undefined get (optional boolean ?areWeThereYet =false );The following interface has two attributes: one whose value can be a
DOMString
or thenull value, and another whose value can be a reference to aNode
object or thenull value:[Exposed =Window ]interface Node {readonly attribute DOMString ?namespaceURI ;readonly attribute Node ?parentNode ; // ...2.13.28. 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.
Any list can be implicitly treated as a
sequence<T>
, as long as it contains only items that are of type T.2.13.29. 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
, orByteString
.The literal syntax for ordered maps may also be used to represent records, when it is implicitly understood from context that the map is being treated as a record. However, there is no way to represent a constant record value inside IDL fragments.
Records are always passed by value. In language bindings where a record is represented by an object of some kind, passing a record to a platform object will not result in a reference to the record being kept by that object. Similarly, any record returned from a platform object will be a copy and modifications made to it will not be visible to the platform object.
Records must not be used as the type of an attribute or constant.
Any ordered map can be implicitly treated as a
record<K, V>
, as long as it contains only entries whose keys are all of of type K and whose values are all of type V.2.13.30. Promise types — Promise<T>
A promise type is a parameterized type whose values are references to objects that “is used as a place holder for the eventual results of a deferred (and possibly asynchronous) computation result of an asynchronous operation”. See section 25.4 of the JavaScript specification for details on the semantics of promise objects.
Promise types are non-nullable, but T may be nullable.
There is no way to represent a promise value in IDL.
2.13.31. Union types
A union type is a type whose set of values is the union of those in two or more other types. Union types (matching
UnionType) are written as a series of types separated by the or keyword with a set of surrounding parentheses. The types which comprise the union type are known as the union’s member types.For example, you might write
(Node or DOMString)
or(double or sequence<double>)
. When applying a? suffix to a union type as a whole, it is placed after the closing parenthesis, as in(Node or DOMString)?
.Note that the member types of a union type do not descend into nested union types. So for
(double or (sequence<long> or Event) or (Node or DOMString)?)
the member types aredouble
,(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 typesNode
,sequence<long>
,Event
,XMLHttpRequest
,DOMString
andsequence<(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.
It is possible to create a union of
bigint
and a numeric type. However, this is generally only supposed to be used for interfaces such as NumberFormat, which formats the values rather than using them in calculations. It would not be appropriate to accept such a union, only to then convert values of the numeric type to abigint
for further processing, as this runs the risk of introducing precision errors. Please file an issue before using this feature.A type includes undefined if:
the type is
undefined
, orthe type is a nullable type and its inner type includes undefined, or
the type is an annotated type and its inner type includes undefined, or
the type is a union type and one of its member types includes undefined.
Union type constant values in IDL are represented in the same way that constant values of their member types would be represented.
UnionType ::( UnionMemberType or UnionMemberType UnionMemberTypes ) UnionMemberType ::ExtendedAttributeList DistinguishableType UnionType Null UnionMemberTypes ::or UnionMemberType UnionMemberTypes DistinguishableType ::PrimitiveType Null StringType Null identifier Null sequence < TypeWithExtendedAttributes > Null object Null symbol Null BufferRelatedType Null FrozenArray < TypeWithExtendedAttributes > Null ObservableArray < TypeWithExtendedAttributes > Null RecordType Null undefined Null 2.13.32. 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 typelong
, but modified as specified by the [Clamp
] extended attribute.The following extended attributes are applicable to types: [
The extended attributes associated with an IDL type type are determined as follows:AllowResizable
], [AllowShared
], [Clamp
], [EnforceRange
], and [LegacyNullToEmptyString
].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.[Exposed =Window ]interface I {attribute [XAttr ]long attrib ;undefined f1 (sequence <[XAttr ]long >arg );undefined f2 (optional [XAttr ]long arg );maplike <[XAttr2 ]DOMString , [XAttr3 ]long >;dictionary D {required [XAttr ]long member ;If type is a member type of a union type U, append each of the extended attributes associated with U to extended attributes.
[Exposed =Window ]interface I {attribute [XAttr ] (long or Node )attrib ;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.[Exposed =Window ]interface I {undefined f ([XAttr ]long attrib );Note that this is an example of this step only if [
XAttr
] is applicable to types; otherwise [XAttr
] applies to the argument, and not the argument’s type.If type appears as part of a
Type production directly within aDictionaryMember 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.
typedef [XAttr ]long xlong ;Return extended attributes.
For any type, the extended attributes associated with it must only contain extended attributes that are applicable to types.
2.13.33. 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.
Kind of bufferArrayBuffer
An object that holds a pointer (which can be null) to a buffer of a fixed number of bytesSharedArrayBuffer
An object that holds a pointer (which cannot be null) to a shared buffer of a fixed number of bytesDataView
A view on to a buffer type instance that allows typed access to integers and floating point values stored at arbitrary offsets into the bufferInt8Array
A view on to a buffer type instance that exposes it as an array of two’s complement signed integers of the given size in bitsInt16Array
Int32Array
BigInt64Array
Uint8Array
A view on to a buffer type instance that exposes it as an array of unsigned integers of the given size in bitsUint16Array
Uint32Array
BigUint64Array
Uint8ClampedArray
A view on to a buffer type instance that exposes it as an array of unsigned 8-bit integers with clamped conversionsFloat16Array
A view on to a buffer type instance that exposes it as an array of IEEE 754 floating point numbers of the given size in bits; Float16Array corresponds to the ECMAScript proposal [PROPOSAL-FLOAT16ARRAY].Float32Array
Float64Array
Note: These types all correspond to classes defined in JavaScript.
There is no way to represent a constant value of any of these types in IDL.
At the specification prose level, IDL buffer source types are simply references to objects. To inspect or manipulate the bytes inside the buffer, specification prose needs to use the algorithms in § 3.2.25 Buffer source types.
BufferRelatedType ::ArrayBuffer SharedArrayBuffer DataView Int8Array Int16Array Int32Array Uint8Array Uint16Array Uint32Array Uint8ClampedArray BigInt64Array BigUint64Array Float16Array Float32Array Float64Array 2.13.34. Frozen array types — FrozenArray<T>
A frozen array type is a parameterized type whose values are references to objects that hold a fixed length array of unmodifiable values. The values in the array are of type T.
Frozen array types must only be used as the type of regular attributes or static attributes defined on an interface.
The following IDL fragment defines an interface with two frozen array attributes, one read only and one not.[Exposed =Window ]interface PersonalPreferences {readonly attribute FrozenArray <DOMString >favoriteColors ;attribute FrozenArray <DOMString >favoriteFoods ;undefined randomizeFavoriteColors ();The behavior of these attributes could be defined like so:
EachPersonalPreferences
has associated favorite colors, aFrozenArray
<DOMString
>, initially equal to the result of creating a frozen array from « "purple
", "aquamarine
" ».Each
PersonalPreferences
has an associated favorite foods, aFrozenArray
<DOMString
>, initially equal to the result of creating a frozen array from the empty list.The
favoriteColors
getter steps are to return this's favorite colors.The
favoriteFoods
getter steps are to return this's favorite foods.The
favoriteFoods
setter steps are to set this's favorite foods to the given value.The
randomizeFavoriteColors()
method steps are:Let newFavoriteColors be a list of two strings representing colors, chosen randomly.
Set this's favorite colors to the result of creating a frozen array from newFavoriteColors.
Since FrozenArray<T> values are references, they are unlike sequence types, which are lists of values that are passed by value.
There is no way to represent a constant frozen array value in IDL.
2.13.35. Observable array types — ObservableArray<T>
An observable array type is a parameterized type whose values are references to a combination of a mutable list of objects of type T, as well as behavior to perform when author code modifies the contents of the list.
The parameterized type T must not be a dictionary type, sequence type, record type, or observable array type. However, T may be nullable.
Similar to sequence types and frozen array types, observable array types wrap around JavaScript array types, imposing additional semantics on their usage.
Observable array types must only be used as the type of regular attributes defined on an interface.
For an attribute whose type is an observable array type, specification authors can specify a series of algorithms:
set an indexed value, which accepts an IDL value that is about to be set in the observable array, and the index at which it is being set;
delete an indexed value, which accepts an IDL value that is about to be removed from the observable array, and the index from which it is being removed.
Both of these algorithms are optional, and if not provided, the default behavior will be to do nothing. Either algorithm may throw an exception, e.g., to reject invalid values.
Note that when JavaScript code sets an existing index to a new value, this will first call the delete an indexed value algorithm to remove the existing value, and then the set an indexed value algorithm with the new value.
Every regular attribute whose type is an observable array type has a backing list, which is a list, initially empty. Specification authors can modify the contents of the backing list, which will automatically be reflected in the contents of the observable array as observed by JavaScript code. Similarly, any modifications by JavaScript code to the contents of the observable array will be reflected back into the backing list, after passing through the set an indexed value and delete an indexed value algorithms.
There is no way to represent a constant observable array value in IDL.
The following IDL fragment defines an interface with an observable array attribute:[Exposed =Window ]interface Building {attribute ObservableArray <Employee >employees ;The behavior of the attribute could be defined like so:
The set an indexed value algorithm forBuilding
’semployees
attribute, given employee and index, is:If employee is not allowed to enter the building today, then throw a "
NotAllowedError
"DOMException
.If index is greater than 200, then throw a "
QuotaExceededError
"DOMException
.Put employee to work!
The delete an indexed value algorithm for
Building
’semployees
attribute, given employee and index, is:Alert security that employee has left the building.
Then, JavaScript code could manipulate the
employees
property in various ways:// Get an instance of Building. const building= getBuilding(); building. employees. push( new Employee( "A" )); building. employees. push( new Employee( "B" )); building. employees. push( new Employee( "C" )); building. employees. splice( 2 , 1 ); const employeeB= building. employees. pop(); building. employees= [ new Employee( "D" ), employeeB, new Employee( "C" )]; building. employees. length= 0 ; // Will throw: building. employees. push( "not an Employee; a string instead" ); All of these manipulations would pass through the above-defined set an indexed value algorithm, potentially throwing if the conditions described there were met. They would also perform the appropriate side effects listed there and in the delete an indexed value algorithm.
Another thing to note about the above code example is how all of the JavaScript array methods from
%Array.prototype%
work on the observable array. Indeed, it fully behaves like anArray
instance:const normalArray= []; // If building.employees were defined as an indexed property getter interface: normalArray // would contains a single item, building.employees. // For observable arrays (and frozen arrays): normalArray contains all of the items inside // of building.employees. normalArray. concat( building. employees); // names is a JavaScript Array. const names= building. employees. map( employee=> employee. name); // Passes various brand checks: console. assert( building. employeesinstanceof Array); console. assert( Array. isArray( building. employees)); console. assert( building. employees. constructor === Array); // Even is treated as an array by JSON.stringify! (Note the outer []s.) console. assert( JSON. stringify( building. employees) === `[{}]` ); 2.14. Extended attributes
An extended attribute is an annotation that can appear on definitions, types as annotated types, interface members, interface mixin members, callback interface members, namespace members, dictionary members, and operation arguments, and is used to control how language bindings will handle those constructs. Extended attributes are specified with an
ExtendedAttributeList , which is a square bracket enclosed, comma separated list ofExtendedAttribute s.The
Grammar symbol ExampleExtendedAttribute grammar symbol matches nearly any sequence of tokens, however the extended attributes defined in this document only accept a more restricted syntax. Any extended attribute encountered in an IDL fragment is matched against the following five grammar symbols to determine which form (or forms) it is in:ExtendedAttributeNoArgs takes no arguments[Replaceable]
ExtendedAttributeArgList takes an argument list Not currently used; previously used by[Constructor(double x, double y)]
ExtendedAttributeNamedArgList takes a named argument list[LegacyFactoryFunction=Image(DOMString src)]
ExtendedAttributeIdent takes an identifier[PutForwards=name]
ExtendedAttributeIdentList takes an identifier list[Exposed=(Window,Worker)]
ExtendedAttributeWildcard takes a wildcard[Exposed=*]
This specification defines a number of extended attributes that are applicable to the JavaScript language binding, which are described in § 3.3 Extended attributes. Each extended attribute definition will state which of the above five forms are allowed.
ExtendedAttributeList ::[ ExtendedAttribute ExtendedAttributes ] ExtendedAttributes ::, ExtendedAttribute ExtendedAttributes ExtendedAttribute ::( ExtendedAttributeInner ) ExtendedAttributeRest [ ExtendedAttributeInner ] ExtendedAttributeRest { ExtendedAttributeInner } ExtendedAttributeRest Other ExtendedAttributeRest ExtendedAttributeRest ::ExtendedAttribute ExtendedAttributeInner ::( ExtendedAttributeInner ) ExtendedAttributeInner [ ExtendedAttributeInner ] ExtendedAttributeInner { ExtendedAttributeInner } ExtendedAttributeInner OtherOrComma ExtendedAttributeInner Other ::integer decimal identifier string other -Infinity ByteString DOMString FrozenArray Infinity ObservableArray Promise USVString bigint boolean double false float object octet optional record sequence short symbol unsigned undefined ArgumentNameKeyword BufferRelatedType OtherOrComma ::Other IdentifierList ::identifier Identifiers Identifiers ::, identifier Identifiers ExtendedAttributeNoArgs ::identifier ExtendedAttributeArgList ::identifier ( ArgumentList ) ExtendedAttributeIdent ::identifier = identifier ExtendedAttributeWildcard ::identifier = * ExtendedAttributeIdentList ::identifier = ( IdentifierList ) ExtendedAttributeNamedArgList ::identifier = identifier ( ArgumentList ) 3. JavaScript binding
This section describes how definitions written with the IDL defined in § 2 Interface definition language correspond to particular constructs in JavaScript, as defined by the ECMAScript Language Specification [ECMA-262].
Unless otherwise specified, objects defined in this section are ordinary objects as described in ECMAScript § 10.1 Ordinary Object Internal Methods and Internal Slots, and if the object is a function object, ECMAScript § 10.3 Built-in Function Objects.
This section may redefine certain internal methods and internal slots of objects. Other specifications may also override the definitions of any internal method or internal slots of a platform object that is an instance of an interface. These objects with changed semantics shall be treated in accordance with the rules for exotic objects.
As overriding internal JavaScript object methods is a low level operation and can result in objects that behave differently from ordinary objects, this facility should not be used unless necessary for security or compatibility. This is currently used to define the
HTMLAllCollection
andLocation
interfaces. [HTML]Unless otherwise specified, exotic objects defined in this section and other specifications have the same internal slots as ordinary objects, and all of the internal methods for which alternative definitions are not given are the same as those of ordinary objects.
Unless otherwise specified, the [[Extensible]] internal slot of objects defined in this section has the value
true .Unless otherwise specified, the [[Prototype]] internal slot of objects defined in this section is
%Object.prototype%
.Some objects described in this section are defined to have a class string, which is the string to include in the string returned from
Object.prototype.toString
.If an object has a class string classString, then the object must, at the time it is created, have a property whose name is the
%Symbol.toStringTag%
symbol with PropertyDescriptor{[[Writable]]:false , [[Enumerable]]:false , [[Configurable]]:true , [[Value]]: classString}.Algorithms in this section use the conventions described in ECMAScript § 5.2 Algorithm Conventions, such as the use of steps and substeps, the use of mathematical operations, and so on. This section may also reference abstract operations and notations defined in other parts of ECMA-262.
When an algorithm says to throw a
SomethingError
then this means to construct a new JavaScriptSomethingError
object in the current realm and to throw it, just as the algorithms in ECMA-262 do.Note that algorithm steps can call in to other algorithms and abstract operations and not explicitly handle exceptions that are thrown from them. When an exception is thrown by an algorithm or abstract operation and it is not explicitly handled by the caller, then it is taken to end the algorithm and propagate out to its caller, and so on.
Consider the following algorithm:
Let x be the JavaScript 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. JavaScript environment
In a JavaScript implementation of a given set of IDL fragments, there will exist a number of JavaScript objects that correspond to definitions in those IDL fragments. These objects are termed the initial objects, and comprise the following:
legacy callback interface objects
the function objects that correspond to operations
the function objects that correspond to stringifiers
Each realm must have its own unique set of each of the initial objects, created before control enters any JavaScript execution context associated with the realm, but after the global object for that realm is created. The [[Prototype]]s of all initial objects in a given realm must come from that same realm.
In an HTML user agent, multiple realms can exist when multiple frames or windows are created. Each frame or window will have its own set of initial objects, which the following HTML document demonstrates:
<!DOCTYPE html> < title > Different Realms</ title > < iframe id = a ></ iframe > < script > var iframe= document. getElementById( "a" ); var w= iframe. contentWindow; // The global object in the frame Object== w. Object; // Evaluates to false, per ECMA-262 Node== w. Node; // Evaluates to false iframeinstanceof w. Node; // Evaluates to false iframeinstanceof w. Object; // Evaluates to false iframe. appendChildinstanceof Function; // Evaluates to true iframe. appendChildinstanceof w. Function; // Evaluates to false </ script > Note: All interfaces define which realms they are exposed in. This allows, for example, realms for Web Workers to expose different sets of supported interfaces from those exposed in realms for Web pages.
Although at the time of this writing the JavaScript specification does not reflect this, every JavaScript object must have an associated realm. The mechanisms for associating objects with realms are, for now, underspecified. However, we note that in the case of platform objects, the associated realm is equal to the object’s relevant realm, and for non-exotic function objects (i.e. not callable proxies, and not bound functions) the associated realm is equal to the value of the function object's [[Realm]] internal slot.
3.2. JavaScript type mapping
This section describes how types in the IDL map to types in JavaScript.
Each sub-section below describes how values of a given IDL type are represented in JavaScript. For each IDL type, it is described how JavaScript values are converted to an IDL value when passed to a platform object expecting that type, and how IDL values of that type are converted to JavaScript values when returned from a platform object.
Note that the sub-sections and algorithms below also apply to annotated types created by applying extended attributes to the types named in their headers.
3.2.1. any
Since the IDL
any
type is the union of all other IDL types, it can correspond to any JavaScript value type.A JavaScript value V is converted to an IDL
any
value by running the following algorithm:If V is
undefined , then return the uniqueundefined
IDL value.If V is
null , then return thenull object?
reference.If V is a Boolean, then return the
boolean
value that represents the same truth value.If V is a Number, then return the result of converting V to an
unrestricted double
.If V is a BigInt, then return the result of converting V to a
bigint
.If V is a String, then return the result of converting V to a
DOMString
.If V is a Symbol, then return the result of converting V to a
symbol
.If V is an Object, then return an IDL
object
value that references V.An IDL
any
value is converted to a JavaScript value according to the rules for converting the specific type of the IDLany
value as described in the remainder of this section.3.2.2. undefined
A JavaScript value V is converted to an IDL
undefined
value by returning the uniqueundefined
value, ignoring V.The unique IDL
undefined
value is converted to the JavaScriptundefined value.3.2.3. boolean
A JavaScript value V is converted to an IDL
boolean
value by running the following algorithm:Let x be the result of computing ToBoolean(V).
Return the IDL
boolean
value that is the one that represents the same truth value as the JavaScript Boolean value x.The IDL
boolean
valuetrue
is converted to the JavaScripttrue value and the IDLboolean
valuefalse
is converted to the JavaScriptfalse value.3.2.4. Integer types
Mathematical operations used in this section, including those defined in ECMAScript § 5.2 Algorithm Conventions, are to be understood as computing exact mathematical results on mathematical real numbers.
In effect, where x is a Number value, “operating on x” is shorthand for “operating on the mathematical real number that represents the same numeric value as x”.
3.2.4.1. byte
A JavaScript 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 a JavaScript value is a Number that represents the same numeric value as the IDLbyte
value. The Number value will be an integer in the range [−128, 127].3.2.4.2. octet
A JavaScript 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 a JavaScript value is a Number that represents the same numeric value as the IDLoctet
value. The Number value will be an integer in the range [0, 255].3.2.4.3. short
A JavaScript 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 a JavaScript value is a Number that represents the same numeric value as the IDLshort
value. The Number value will be an integer in the range [−32768, 32767].3.2.4.4. unsigned short
A JavaScript 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
unsigned short
value that represents the same numeric value as x.The result of converting an IDL
unsigned short
value to a JavaScript value is a Number that represents the same numeric value as the IDLunsigned short
value. The Number value will be an integer in the range [0, 65535].3.2.4.5. long
A JavaScript 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 a JavaScript value is a Number that represents the same numeric value as the IDLlong
value. The Number value will be an integer in the range [−2147483648, 2147483647].3.2.4.6. unsigned long
A JavaScript 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
unsigned long
value that represents the same numeric value as x.The result of converting an IDL
unsigned long
value to a JavaScript value is a Number that represents the same numeric value as the IDLunsigned long
value. The Number value will be an integer in the range [0, 4294967295].3.2.4.7. long long
A JavaScript 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 long
value that represents the same numeric value as x.The result of converting an IDL
long long
value to a JavaScript value is a Number value that represents the closest numeric value to thelong long
, choosing the numeric value with an even significand if there are two equally close values. If thelong long
is in the range [−253 + 1, 253 − 1], then the Number will be able to represent exactly the same value as thelong long
.3.2.4.8. unsigned long long
A JavaScript 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
unsigned long long
value that represents the same numeric value as x.The result of converting an IDL
unsigned long long
value to a JavaScript value is a Number value that represents the closest numeric value to theunsigned long long
, choosing the numeric value with an even significand if there are two equally close values. If theunsigned long long
is less than or equal to 253 − 1, then the Number will be able to represent exactly the same value as theunsigned long long
.3.2.4.9. Abstract operations
IntegerPart(n):
If n < 0, then return -1 × r.
Otherwise, return r.
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 JavaScript’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:Set x to min(max(x, lowerBound), upperBound).
Round x to the nearest integer, choosing the even integer if it lies halfway between two, and choosing +0 rather than −0.
Return x.
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
A JavaScript 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 a JavaScript value is the Number value that represents the same numeric value as the IDLfloat
value.3.2.6. unrestricted float
A JavaScript 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 JavaScript
NaN value, it must be canonicalized to a particular single precision IEEE 754 NaN value. The NaN value mentioned above is chosen simply because it is the quiet NaN with the lowest value when its bit pattern is interpreted as an unsigned 32-bit integer.The result of converting an IDL
unrestricted float
value to a JavaScript value is a Number:If the IDL
unrestricted float
value is a NaN, then the Number value isNaN .Otherwise, the Number value is the one that represents the same numeric value as the IDL
unrestricted float
value.3.2.7. double
A JavaScript value V is converted to an IDL
double
value by running the following algorithm:If x is
NaN , +∞, or −∞, then throw aTypeError
.Return the IDL
double
value that represents the same numeric value as x.The result of converting an IDL
double
value to a JavaScript value is the Number value that represents the same numeric value as the IDLdouble
value.3.2.8. unrestricted double
A JavaScript 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 JavaScript
NaN value, it must be canonicalized to a particular double precision IEEE 754 NaN value. The NaN value mentioned above is chosen simply because it is the quiet NaN with the lowest value when its bit pattern is interpreted as an unsigned 64-bit integer.The result of converting an IDL
unrestricted double
value to a JavaScript value is a Number:If the IDL
unrestricted double
value is a NaN, then the Number value isNaN .Otherwise, the Number value is the one that represents the same numeric value as the IDL
unrestricted double
value.3.2.9. bigint
A JavaScript value V is converted to an IDL
bigint
value by running the following algorithm:Return the IDL
bigint
value that represents the same numeric value as x.A JavaScript value V is converted to an IDL numeric type T or
bigint
value by running the following algorithm:If x is a BigInt, then
Return the IDL
bigint
value that represents the same numeric value as x.Assert: x is a Number.
Return the result of converting x to T.
3.2.10. DOMString
A JavaScript 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 [LegacyNullToEmptyString
] extended attribute, then return theDOMString
value that represents the empty string.Return the IDL
DOMString
value that represents the same sequence of code units as the one the JavaScript String value x represents.The result of converting an IDL
DOMString
value to a JavaScript value is the String value that represents the same sequence of code units that the IDLDOMString
represents.3.2.11. ByteString
A JavaScript value V is converted to an IDL
ByteString
value by running the following algorithm: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 a JavaScript value is a String value whose length is the length of theByteString
, and the value of each element of which is the value of the corresponding element of theByteString
.3.2.12. USVString
A JavaScript 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 scalar values.A JavaScript value V is converted to an IDL
object
value by running the following algorithm:If V is not an Object, then throw a
TypeError
.Return the IDL
object
value that is a reference to the same object as V.The result of converting an IDL
object
value to a JavaScript value is the Object value that represents a reference to the same object that the IDLobject
represents.3.2.14. symbol
IDL
A JavaScript value V is converted to an IDLsymbol
values are represented by JavaScript Symbol values.symbol
value by running the following algorithm:If V is not a Symbol, then throw a
TypeError
.Return the IDL
symbol
value that is a reference to the same symbol as V.The result of converting an IDL
symbol
value to a JavaScript value is the Symbol value that represents a reference to the same symbol that the IDLsymbol
represents.3.2.15. Interface types
IDL interface type values are represented by JavaScript Object values (including function objects).
A JavaScript value V is converted to an IDL interface type value by running the following algorithm (where I is the interface):
If V implements I, then return the IDL interface type value that represents a reference to that platform object.
The result of converting an IDL interface type value to a JavaScript value is the Object value that represents a reference to the same object that the IDL interface type value represents.
3.2.16. Callback interface types
IDL callback interface type values are represented by JavaScript Object values (including function objects).
A JavaScript value V is converted to an IDL callback interface type value by running the following algorithm:
If V is not an Object, then throw a
TypeError
.Return the IDL callback interface type value that represents a reference to V, with the incumbent settings object as the callback context.
The result of converting an IDL callback interface type value to a JavaScript value is the Object value that represents a reference to the same object that the IDL callback interface type value represents.
3.2.17. Dictionary types
IDL dictionary type values are represented by JavaScript Object values. Properties on the object (or its prototype chain) correspond to dictionary members.
A JavaScript value jsDict is converted to an IDL dictionary type value by running the following algorithm (where D is the dictionary type):
If jsDict is not an Object and jsDict is neither
undefined nornull , then throw aTypeError
.Let idlDict be an empty ordered map, representing a dictionary of type D.
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 jsDict is either
undefined ornull , then:Let jsMemberValue be
undefined .Otherwise,
Let jsMemberValue be ? Get(jsDict, key).
If jsMemberValue is not
undefined , then:Let idlMemberValue be the result of converting jsMemberValue to an IDL value whose type is the type member is declared to be of.
Set idlDict[key] to idlMemberValue.
Otherwise, if jsMemberValue is
undefined but member has a default value, then:Let idlMemberValue be member’s default value.
Set idlDict[key] to idlMemberValue.
Otherwise, if jsMemberValue is
undefined and member is required, then throw aTypeError
.Return idlDict.
Note: The order that dictionary members are looked up on the JavaScript object are not necessarily the same as the object’s property enumeration order.
An IDL dictionary value V is converted to a JavaScript Object value by running the following algorithm (where D is the dictionary):
Let O be OrdinaryObjectCreate(
%Object.prototype%
).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 V[key] exists, then:
Let idlValue be V[key].
Let value be the result of converting idlValue to a JavaScript value.
Perform ! CreateDataPropertyOrThrow(O, key, value).
Recall that if member has a default value, then key will always exist in V.
Return O.
3.2.18. Enumeration types
IDL enumeration types are represented by JavaScript String values.
A JavaScript 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 a JavaScript value is the String value that represents the same sequence of code units as the enumeration value.
3.2.19. Callback function types
IDL callback function types are represented by JavaScript function objects, except in the [
LegacyTreatNonObjectAsNull
] case, when they can be any object.A JavaScript value V is converted to an IDL 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 [LegacyTreatNonObjectAsNull
], 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 a JavaScript value is a reference to the same object that the IDL callback function type value represents.
3.2.20. Nullable types — T?
IDL nullable type values are represented by values of either the JavaScript type corresponding to the inner IDL type, or the JavaScript
null value.A JavaScript value V is converted to an IDL nullable type
T?
value (where T is the inner type) as follows:If V is not an 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 [
LegacyTreatNonObjectAsNull
], then return the IDL nullable typeT?
valuenull .Otherwise, if V is
undefined , and T includes undefined, return the uniqueundefined
value.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
then the JavaScript value isT
.null .Otherwise, the JavaScript value is the result of converting the IDL nullable type value to the inner IDL type
T
.3.2.21. Sequences — sequence<T>
IDL sequence<T> values are represented by JavaScript Array values.
A JavaScript value V is converted to an IDL sequence<T> value as follows:
If V is not an Object, throw a
TypeError
.Let method be ? GetMethod(V,
%Symbol.iterator%
).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 a JavaScript Array object as follows:
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 a JavaScript value.
Let P be the result of calling ! ToString(i).
Perform ! CreateDataPropertyOrThrow(A, P, E).
Set i to i + 1.
Return A.
3.2.21.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 iteratorRecord be ? GetIteratorFromMethod(iterable, method).
Initialize i to be 0.
Repeat
Let next be ? IteratorStepValue(iteratorRecord).
If next is
done , then return an IDL sequence value of type sequence<T> of length i, where the value of the element at index j is Sj.Initialize Si to the result of converting next 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.
[Exposed =Window ]interface Canvas {sequence <DOMString >getSupportedImageCodecs ();undefined drawPolygon (sequence <double >coordinates );sequence <double >getLastDrawnPolygon (); // ...In a JavaScript implementation of this interface, an Array object with elements of type String is used to represent a
sequence<DOMString>
, while an Array with elements of type Number represents asequence<double>
. The Array objects are effectively passed by value; every time thegetSupportedImageCodecs()
function is called a new Array is returned, and whenever an Array is passed todrawPolygon
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.22. Records — record<K, V>
IDL record<K, V> values are represented by JavaScript Object values.
A JavaScript value O is converted to an IDL
record<K, V>
value as follows:If O is not an Object, throw a
TypeError
.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 K is
USVString
and key contains unpaired surrogates.Return result.
Let jsKey be key converted to a JavaScript value.
Let jsValue be value converted to a JavaScript value.
Let created be ! CreateDataProperty(result, jsKey, jsValue).
Assert: created is
true .Return result.
Passing the JavaScript value
{b: 3, a: 4}
as arecord<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>
TypeError
{"\uD83D": 1}
record<USVString, double>
«[ "\uFFFD
" → 1 ]»{"\uD83D": {hello: "world"}}
record<DOMString, double>
«[ "\uD83D
" → 0 ]»3.2.23. Promise types — Promise<T>
IDL promise type values are represented by JavaScript PromiseCapability records.
A JavaScript value V is converted to an IDL
Promise<T>
value as follows:Let promiseCapability be ? NewPromiseCapability(
%Promise%
).Perform ? Call(promiseCapability.[[Resolve]],
undefined , « V »).Return promiseCapability.
The result of converting an IDL promise type value to a JavaScript value is the value of the [[Promise]] field of the record that IDL promise type represents.
3.2.23.1. Creating and manipulating Promises
To create a new
Promise<T>
in a realm realm, perform the following steps:Let constructor be realm.[[Intrinsics]].[[
%Promise%
]].Return ? NewPromiseCapability(constructor).
To create a resolved promise of type
Promise<T>
, with x (a value of type T) in a realm realm, perform the following steps:Let value be the result of converting x to a JavaScript value.
Let constructor be realm.[[Intrinsics]].[[
%Promise%
]].Let promiseCapability be ? NewPromiseCapability(constructor).
Perform ! Call(promiseCapability.[[Resolve]],
undefined , « value »).Return promiseCapability.
To create a rejected promise of type
Promise<T>
, with reason r (a JavaScript value) in a realm realm, perform the following steps:Let constructor be realm.[[Intrinsics]].[[
%Promise%
]].Let promiseCapability be ? NewPromiseCapability(constructor).
Perform ! Call(promiseCapability.[[Reject]],
undefined , « r »).Return promiseCapability.
To resolve a
Promise<T>
p with x (a value of type T), perform the following steps:If x is not given, then let it be the
undefined
value.Let value be the result of converting x to a JavaScript value.
Perform ! Call(p.[[Resolve]],
undefined , « value »).If T is
undefined
, then the x argument is optional, allowing a simpler "resolve p" usage.To reject a
Promise<T>
p with reason r (a JavaScript value), perform the following steps:Perform ! Call(p.[[Reject]],
undefined , « r »).To react to a
Promise<T>
promise, given one or two sets of steps to perform, covering when the promise is fulfilled, rejected, or both, perform the following steps:Let onFulfilledSteps be the following steps given argument V:
Let value be the result of converting V to an IDL value of type T.
If there is a set of steps to be run if the promise was fulfilled, then let result be the result of performing them, given value if T is not
undefined
. Otherwise, let result be value.Return result, converted to a JavaScript value.
Let onFulfilled be CreateBuiltinFunction(onFulfilledSteps, « »):
Let onRejectedSteps be the following steps given argument R:
Let reason be the result of converting R to an IDL value of type
any
.If there is a set of steps to be run if the promise was rejected, then let result be the result of performing them, given reason. Otherwise, let result be a promise rejected with reason.
Return result, converted to a JavaScript value.
Let onRejected be CreateBuiltinFunction(onRejectedSteps, « »):
Let constructor be promise.[[Promise]].[[Realm]].[[Intrinsics]].[[
%Promise%
]].Let newCapability be ? NewPromiseCapability(constructor).
Note: Not all callers will use the returned
Promise
. Implementations might wish to avoid creating newCapability in those cases.Perform PerformPromiseThen(promise.[[Promise]], onFulfilled, onRejected, newCapability).
Return newCapability.
Note: This algorithm will behave in a very similar way to the
promise.then()
method. In particular, if the steps return a value of type U orPromise<U>
, this algorithm returns aPromise<U>
as well.To perform some steps upon fulfillment of a
Promise<T>
promise given some steps steps taking a value of type T, perform the following steps:Return the result of reacting to promise:
If promise was fulfilled with value v, then:
Perform steps with v.
To perform some steps upon rejection of a
Promise<T>
promise given some steps steps taking a JavaScript value, perform the following steps:Return the result of reacting to promise:
If promise was rejected with reason r, then:
Perform steps with r.
To wait for all with a list of
Promise<T>
values promises, with success steps successSteps that take a list of T values and failure steps failureSteps that take a rejection reasonany
value, perform the following steps:Let fullfilledCount be 0.
Let rejected be false.
Let rejectionHandlerSteps be the following steps given arg:
If rejected is true, abort these steps.
Set rejected to true.
Perform failureSteps given arg.
Let rejectionHandler be CreateBuiltinFunction(rejectionHandlerSteps, « »):
Let total be promises’s size.
If total is 0, then:
Queue a microtask to perform successSteps given « ».
Return.
Let index be 0.
Let result be a list containing total null values.
For each promise of promises:
Let promiseIndex be index.
Let fulfillmentHandler be the following steps given arg:
Set result[promiseIndex] to arg.
Set fullfilledCount to fullfilledCount + 1.
If fullfilledCount equals total, then perform successSteps given result.
Let fulfillmentHandler be CreateBuiltinFunction(fulfillmentHandler, « »):
Perform PerformPromiseThen(promise, fulfillmentHandler, rejectionHandler).
Set index to index + 1.
To get a promise for waiting for all with a list of
Promise<T>
values promises and a realm realm, perform the following steps:Let promise be a new promise of type
Promise<sequence<T>>
in realm.Let successSteps be the following steps, given results:
Resolve promise with results.
Let failureSteps be the following steps, given reason:
Reject promise with reason.
Wait for all with promises, given successSteps and failureSteps.
Return promise.
This definition is useful when you wish to aggregate the results of multiple promises, and then produce another promise from them, in the same way that
To mark as handled aPromise.all()
functions for JavaScript code. If you do not need to produce another promise, then waiting for all is likely better.Promise<T>
promise, set promise.[[Promise]].[[PromiseIsHandled]] to true.This definition is useful for promises for which you expect rejections to often be ignored; it ensures such promises do not cause
unhandledrejection
events. The most common use case is for promise properties, which the web developer might or might not consult. An example is thewritableStreamWriter.closed
promise.3.2.23.2. Examples
delay
is an operation that returns a promise that will be fulfilled in a number of milliseconds. It illustrates how simply you can resolve a promise, with one line of prose.interface I {Promise <undefined >delay (unrestricted double ms );The
delay(ms)
method steps are:Let realm be this's relevant realm.
Let taskSource be some appropriate task source.
If ms is NaN, let ms be +0; otherwise let ms be the maximum of ms and +0.
Let p be a new promise in realm.
Run the following steps in parallel:
Wait ms milliseconds.
Queue a task on taskSource to resolve p.
Return p.
The
validatedDelay
operation is much like thedelay
function, except it will validate its arguments. This shows how to use rejected promises to signal immediate failure before even starting any asynchronous operations.interface I {Promise <undefined >validatedDelay (unrestricted double ms );The
validatedDelay(ms)
method steps are:Let realm be this's relevant realm.
Let taskSource be some appropriate task source.
If ms is NaN, return a promise rejected with a
TypeError
in realm.If ms < 0, return a promise rejected with a
RangeError
in realm.Let p be a new promise in realm.
Run the following steps in parallel:
Wait ms milliseconds.
Queue a task on taskSource to resolve p.
Return p.
addDelay
is an operation that adds an extra number of milliseconds of delay between promise settling and the returned promise settling.interface I {Promise <any >addDelay (Promise <any >promise ,unrestricted double ms );The
addDelay(ms, promise)
method steps are:Let realm be this's relevant realm.
Let taskSource be some appropriate task source.
If ms is NaN, let ms be +0; otherwise let ms be the maximum of ms and +0.
Let p be a new promise in realm.
React to promise:
If promise was fulfilled with value v, then:
Run the following steps in parallel:
Wait ms milliseconds.
Queue a task on taskSource to resolve p with v.
If promise was rejected with reason r, then:
Run the following steps in parallel:
Wait ms milliseconds.
Queue a task on taskSource to reject p with r.
environment.ready
is an attribute that signals when some part of some environment, e.g. a DOM document, becomes "ready". It illustrates how to encode environmental asynchronicity.interface Environment {readonly attribute Promise <undefined >ready ;Every
Environment
object must have a ready promise, which is aPromise<undefined>
.The
ready
attribute getter steps are:Return this's ready promise.
To create an
Environment
object in a realm realm, perform the following steps:Let taskSource be some appropriate task source.
Let environment be new
Environment
object in realm.Set environment’s ready promise to a new promise in realm.
Run the following steps in parallel:
Do some asynchronous work.
If environment becomes ready successfully, then queue a task on taskSource to resolve environment’s ready promise.
If environment fails to become ready, then queue a task on taskSource to reject environment’s ready promise with a "
NetworkError
"DOMException
.Return environment.
addBookmark
is an operation that requests that the user add the current web page as a bookmark. It’s drawn from some iterative design work and illustrates a more real-world scenario of appealing to environmental asynchrony, as well as immediate rejections.interface I {Promise <undefined >addBookmark ();The
addBookmark()
method steps are:Let taskSource be some appropriate task source.
If this method was not invoked as a result of explicit user action, return a promise rejected with a "
SecurityError
"DOMException
.If the document’s mode of operation is standalone, return a promise rejected with a "
NotSupportedError
"DOMException
.Let promise be a new promise.
Let info be the result of getting a web application’s metadata.
Run the following steps in parallel:
Using info, and in a manner that is user-agent specific, allow the end user to make a choice as to whether they want to add the bookmark.
If the end-user aborts the request to add the bookmark (e.g., they hit escape, or press a "cancel" button), then queue a task on taskSource to reject promise with an "
AbortError
"DOMException
.Otherwise, queue a task on taskSource to resolve promise.
Return promise.
Several places in [SERVICE-WORKERS] use get a promise to wait for all.
batchRequest
illustrates a simplified version of one of their uses. It takes as input a sequence of URLs, and returns a promise for a sequence ofResponse
objects created by fetching the corresponding URL. If any of the fetches fail, it will return a promise rejected with that failure.interface I {Promise <sequence <Response >>batchRequest (sequence <USVString >urls );The
batchRequest(urls)
method steps are:Let responsePromises be « ».
For each url of urls:
Let p be the result of calling
fetch()
with url.Append p to responsePromises.
Let p be the result of getting a promise to wait for all with responsePromises.
Return p.
3.2.24. Union types
IDL union type values are represented by JavaScript values that correspond to the union’s member types.
To convert a JavaScript value V to an IDL union type value is done as follows:
If the union type includes undefined and V is
undefined , then return the uniqueundefined
value.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 an Object, V has an [[ArrayBufferData]] internal slot, and IsSharedArrayBuffer(V) is false, 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 V is an Object, V, has an [[ArrayBufferData]] internal slot, and IsSharedArrayBuffer(V) is true, then:
If types includes
SharedArrayBuffer
, then return the result of converting V toSharedArrayBuffer
.If types includes
object
, then return the IDL value that is a reference to the object V.If V is an 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 V is an 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 V is an Object, then:
If types includes a sequence type, then
Let method be ? GetMethod(V,
%Symbol.iterator%
).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 ? GetMethod(V,
%Symbol.iterator%
).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 callback interface type.
If types includes
object
, then return the IDL value that is a reference to the object V.If V is a Boolean, then:
If types includes
boolean
, then return the result of converting V toboolean
.If V is a Number, then:
If types includes a numeric type, then return the result of converting V to that numeric type.
If V is a BigInt, then:
If types includes
bigint
, then return the result of converting V tobigint
If types includes a string type, then return the result of converting V to that type.
If types includes a numeric type and
bigint
, then return the result of converting V to either that numeric type orbigint
.If types includes a numeric type, then return the result of converting V to that numeric type.
If types includes
boolean
, then return the result of converting V toboolean
.If types includes
bigint
, then return the result of converting V tobigint
.An IDL union type value is converted to a JavaScript value according to the rules for converting the specific type of the IDL union type value as described in this section (§ 3.2 JavaScript type mapping).
3.2.25. Buffer source types
A value of an IDL
ArrayBuffer
is represented by an object of the corresponding JavaScript class. If it is not associated with the [AllowResizable
] extended attribute, it can only be backed by JavaScriptArrayBuffer
objects V for which IsResizableArrayBuffer(V) is false.A value of an IDL
SharedArrayBuffer
is represented by an object of the corresponding JavaScript class. If it is not associated with the [AllowResizable
] extended attribute, it can only be backed by JavaScriptSharedArrayBuffer
objects V for which IsResizableArrayBuffer(V) is false.Values of the IDL buffer view types are represented by objects of the corresponding JavaScript class, with the following additional restrictions on those objects.
If the type is not associated with either the [ AllowResizable
] or [AllowShared
] extended attribute, if applicable, they can only be backed by JavaScriptArrayBuffer
objects V for which IsResizableArrayBuffer(V) is false.If the type is associated with the [ AllowResizable
] extended attribute but not with the [AllowShared
] extended attribute, if applicable, they can only be backed by JavaScriptArrayBuffer
objects.If the type is associated with the [ AllowShared
] extended attribute but not with the [AllowResizable
] extended attribute, they can only be backed by JavaScriptArrayBuffer
andSharedArrayBuffer
objects V for which IsResizableArrayBuffer(V) is false.If the type is associated with both the [ AllowResizable
] and the [AllowShared
] extended attributes, they can be backed by any JavaScriptArrayBuffer
orSharedArrayBuffer
object.A JavaScript value V is converted to an IDL
ArrayBuffer
value by running the following algorithm:If V is not an Object, or V does not have an [[ArrayBufferData]] internal slot, then throw a
TypeError
.If IsSharedArrayBuffer(V) is true, then throw a
TypeError
.If the conversion is not to an IDL type associated with the [
AllowResizable
] extended attribute, and IsResizableArrayBuffer(V) is true, then throw aTypeError
.Return the IDL
ArrayBuffer
value that is a reference to the same object as V.A JavaScript value V is converted to an IDL
SharedArrayBuffer
value by running the following algorithm:If V is not an Object, or V does not have an [[ArrayBufferData]] internal slot, then throw a
TypeError
.If IsSharedArrayBuffer(V) is false, then throw a
TypeError
.If the conversion is not to an IDL type associated with the [
AllowResizable
] extended attribute, and IsResizableArrayBuffer(V) is true, then throw aTypeError
.Return the IDL
SharedArrayBuffer
value that is a reference to the same object as V.A JavaScript value V is converted to an IDL
DataView
value by running the following algorithm:If V is not an 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
.If the conversion is not to an IDL type associated with the [
AllowResizable
] extended attribute, and IsResizableArrayBuffer(V.[[ViewedArrayBuffer]]) is true, then throw aTypeError
.Return the IDL
DataView
value that is a reference to the same object as V.A JavaScript value V is converted to an IDL
Int8Array
,Int16Array
,Int32Array
,Uint8Array
,Uint16Array
,Uint32Array
,Uint8ClampedArray
,BigInt64Array
,BigUint64Array
,Float16Array
,Float32Array
, orFloat64Array
value by running the following algorithm:Let T be the IDL type V is being converted to.
If V is not an Object, or V does not have a [[TypedArrayName]] internal slot with a value equal to T’s name, 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
.If the conversion is not to an IDL type associated with the [
AllowResizable
] extended attribute, and IsResizableArrayBuffer(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 a JavaScript value is the Object value that represents a reference to the same object that the IDL value represents.To create anArrayBuffer
from a byte sequence bytes in a realm realm:Let jsArrayBuffer be ? AllocateArrayBuffer(realm.[[Intrinsics]].[[
%ArrayBuffer%
]], bytes’s length).Let arrayBuffer be the result of converting jsArrayBuffer to an IDL value of type
ArrayBuffer
.Write bytes into arrayBuffer.
Return arrayBuffer.
To create aSharedArrayBuffer
from a byte sequence bytes in a realm realm:Let jsSharedArrayBuffer be ? AllocateSharedArrayBuffer(realm.[[Intrinsics]].[[
%SharedArrayBuffer%
]], bytes’s length).Let sharedArrayBuffer be the result of converting jsSharedArrayBuffer to an IDL value of type
SharedArrayBuffer
.Write bytes into sharedArrayBuffer.
Return sharedArrayBuffer.
To create one of theArrayBufferView
types from a byte sequence bytes in a realm realm:Assert: if the type is not
DataView
, then bytes’s length modulo the element size of that type is 0.Let arrayBuffer be the result of creating an
ArrayBuffer
from bytes in realm.Let jsArrayBuffer be the result of converting arrayBuffer to a JavaScript value.
Let constructor be the appropriate constructor from realm.[[Intrinsics]] for the type of
ArrayBufferView
being created.Let jsView be ! Construct(constructor, « jsArrayBuffer »).
Return the result of converting jsView into the given type.
To get a copy of the bytes held by the buffer source given a buffer source type instance bufferSource:Let jsBufferSource be the result of converting bufferSource to a JavaScript value.
Let jsArrayBuffer be jsBufferSource.
Let offset be 0.
Let length be 0.
If jsBufferSource has a [[ViewedArrayBuffer]] internal slot, then:
Set jsArrayBuffer to jsBufferSource.[[ViewedArrayBuffer]].
Set offset to jsBufferSource.[[ByteOffset]].
Set length to jsBufferSource.[[ByteLength]].
Otherwise:
Assert: jsBufferSource is an
ArrayBuffer
orSharedArrayBuffer
object.Set length to jsBufferSource.[[ArrayBufferByteLength]].
If IsDetachedBuffer(jsArrayBuffer) is true, then return the empty byte sequence.
Let bytes be a new byte sequence of length equal to length.
For i in the range offset to offset + length − 1, inclusive, set bytes[i − offset] to GetValueFromBuffer(jsArrayBuffer, i, Uint8, true, Unordered).
Return bytes.
The byte length of a buffer source type instance bufferSource is the value returned by the following steps:Let jsBufferSource be the result of converting bufferSource to a JavaScript value.
If jsBufferSource has a [[ViewedArrayBuffer]] internal slot, then return jsBufferSource.[[ByteLength]].
Return jsBufferSource.[[ArrayBufferByteLength]].
The underlying buffer of a buffer source type instance bufferSource is the value returned by the following steps:If bufferSource is a buffer type instance, then return bufferSource.
Let jsBufferView be the result of converting bufferSource to a JavaScript value.
Let jsBuffer be jsBufferView.[[ViewedArrayBuffer]].
If IsSharedArrayBuffer(jsBuffer) is false, then return the result of converting jsBuffer to an IDL value of type
ArrayBuffer
.Return the result of converting jsBuffer to an IDL value of type
To write a byte sequence bytes into a buffer type instance arrayBuffer, optionally given a startingOffset (default 0):SharedArrayBuffer
.Let jsArrayBuffer be the result of converting arrayBuffer to a JavaScript value.
Assert: bytes’s length ≤ jsArrayBuffer.[[ArrayBufferByteLength]] − startingOffset.
For i in the range startingOffset to startingOffset + bytes’s length − 1, inclusive, perform SetValueInBuffer(jsArrayBuffer, i, Uint8, bytes[i - startingOffset], true, Unordered).
To write a byte sequence bytes into anArrayBufferView
view, optionally given a startingOffset (default 0):Let jsView be the result of converting view to a JavaScript value.
Assert: bytes’s length ≤ jsView.[[ByteLength]] − startingOffset.
Assert: if view is not a
DataView
, then bytes’s length modulo the element size of view’s type is 0.Let arrayBuffer be the result of converting jsView.[[ViewedArrayBuffer]] to an IDL value of type
ArrayBuffer
.Write bytes into arrayBuffer with startingOffset set to jsView.[[ByteOffset]] + startingOffset.
Extreme care must be taken when writing specification text that writes into a buffer source type instance, as the underlying data can easily be changed by the script author or other APIs at unpredictable times. This is especially true if aSharedArrayBuffer
object is involved.For the non-shared cases, a more recommended pattern is to transfer the
To detach anArrayBuffer
first if possible, to ensure the writes cannot overlap with other modifications, and then give the newArrayBuffer
instance to author code as necessary. Alternately, you can get a copy of the bytes held by the buffer source, modify those bytes, and then use them to create a newArrayBuffer
orArrayBufferView
to give back to author code.ArrayBuffer
arrayBuffer:Let jsArrayBuffer be the result of converting arrayBuffer to a JavaScript value.
Perform ? DetachArrayBuffer(jsArrayBuffer).
This will throw an exception if jsArrayBuffer has an [[ArrayBufferDetachKey]] that is not undefined, such as is the case with the value of
WebAssembly.Memory
'sbuffer
attribute. [WASM-JS-API-1]Detaching a buffer that is already detached is a no-op.
A buffer source type instance bufferSource is detached if the following steps return true:Let jsArrayBuffer be the result of converting bufferSource to a JavaScript value.
If jsArrayBuffer has a [[ViewedArrayBuffer]] internal slot, then set jsArrayBuffer to jsArrayBuffer.[[ViewedArrayBuffer]].
Return IsDetachedBuffer(jsArrayBuffer).
A buffer source type instance bufferSource is transferable if the following steps return true:Let jsArrayBuffer be the result of converting bufferSource to a JavaScript value.
If jsArrayBuffer has a [[ViewedArrayBuffer]] internal slot, then set jsArrayBuffer to jsArrayBuffer.[[ViewedArrayBuffer]].
If IsSharedArrayBuffer(jsArrayBuffer) is true, then return false.
If IsDetachedBuffer(jsArrayBuffer) is true, then return false.
If jsArrayBuffer.[[ArrayBufferDetachKey]] is not
undefined , then return false.Return true.
To transfer anArrayBuffer
arrayBuffer, optionally given a realm targetRealm:Let jsArrayBuffer be the result of converting arrayBuffer to a JavaScript value.
If IsDetachedBuffer(jsArrayBuffer) is false, then throw a
TypeError
.Let arrayBufferData be jsArrayBuffer.[[ArrayBufferData]].
Let arrayBufferByteLength be jsArrayBuffer.[[ArrayBufferByteLength]].
Perform ? DetachArrayBuffer(jsArrayBuffer).
If targetRealm is not given, let targetRealm be the current realm.
Let jsTransferred be ? AllocateArrayBuffer(targetRealm.[[Intrinsics]].[[
%ArrayBuffer%
]], 0).Set jsTransferred.[[ArrayBufferData]] to arrayBufferData.
Set jsTransferred.[[ArrayBufferByteLength]] to arrayBufferByteLength.
Return the result of converting jsTransferred to an IDL value of type
This will throw an exception under any of the following circumstances:ArrayBuffer
.arrayBuffer cannot be detached, for the reasons explained in that algorithm’s definition;
arrayBuffer is already detached;
Sufficient memory cannot be allocated in realm. Generally this will only be the case if realm is in a different agent cluster than the one in which arrayBuffer was allocated. If they are in the same agent cluster, then implementations will just change the backing pointers to get the same observable results with better performance and no allocations.
3.2.26. Frozen arrays — FrozenArray<T>
Values of frozen array types are represented by frozen JavaScript Array object references.
A JavaScript value V is converted to an IDL 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 a JavaScript value.
Perform ! SetIntegrityLevel(array, "
frozen
").Return array.
The result of converting an IDL FrozenArray<T> value to a JavaScript value is the Object value that represents a reference to the same object that the IDL FrozenArray<T> represents.
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.2.27. Observable arrays — ObservableArray<T>
Values of observable array types are represented by observable array exotic objects.
Instead of the usual conversion algorithms, observable array types have special handling as part of the attribute getter and attribute setter algorithms.
In the JavaScript binding, JavaScript objects that represent platform objects have a backing observable array exotic object for each regular attribute of an observable array type. These are created and managed as part of the define the attributes algorithm.
The backing list for an observable array attribute in the JavaScript binding, given a platform object obj and an attribute attribute, is the list returned by the following algorithm:Assert: obj implements an interface with the regular attribute attribute.
Let oa be obj’s backing observable array exotic object for attribute.
Return oa.[[ProxyHandler]].[[BackingList]].
3.3. Extended attributes
This section defines a number of extended attributes whose presence affects the JavaScript binding.
3.3.1. [AllowResizable]
If the [
AllowResizable
] extended attribute appears on a buffer type, it creates a new IDL type that allows for the respective corresponding JavaScriptArrayBuffer
orSharedArrayBuffer
object to be resizable.If the [
AllowResizable
] extended attribute appears on one of the buffer view types and the [AllowShared
] extended attribute does not, it creates a new IDL type that allows the buffer view type to be backed by a JavaScriptArrayBuffer
that is resizable, instead of only by a fixed-lengthArrayBuffer
.If the [
AllowResizable
] extended attribute and the [AllowShared
] extended attribute both appear on one of the buffer view types, it creates a new IDL type that allows the buffer view type to be additionally backed by a JavaScriptSharedArrayBuffer
that is growable.The [
AllowResizable
] extended attribute must take no arguments.A type that is not a buffer source type must not be associated with the [
AllowResizable
] extended attribute.See the rules for converting JavaScript values to IDL buffer source types in § 3.2.25 Buffer source types for the specific requirements that the use of [
AllowResizable
] entails.See the example in § 3.3.2 [AllowShared] for example usage of both [
AllowResizable
] and [AllowShared
].3.3.2. [AllowShared]
If the [
AllowShared
] extended attribute appears on one of the buffer view types, it creates a new IDL type that allows the object to be backed by anSharedArrayBuffer
instead of only by anArrayBuffer
.The [
AllowShared
] extended attribute must take no arguments.A type that is not a buffer view type must not be associated with the [
AllowShared
] extended attribute.See the rules for converting JavaScript values to IDL buffer view types in § 3.2.25 Buffer source types for the specific requirements that the use of [
The following IDL fragment demonstrates the possible combinations of the [AllowShared
] entails.AllowResizable
] and [AllowShared
] extended attribute:[Exposed =Window ]interface ExampleBufferFeature {undefined writeInto (ArrayBufferView dest );undefined writeIntoResizable ([AllowResizable ]ArrayBufferView dest );undefined writeIntoShared ([AllowShared ]ArrayBufferView dest );undefined writeIntoSharedResizable ([AllowResizable ,AllowShared ]ArrayBufferView dest );With this definition,
A call to writeInto
with any buffer view type backed by either a resizableArrayBuffer
instance or aSharedArrayBuffer
instance, will throw aTypeError
exception.A call to writeIntoResizable
with any buffer view type backed by aSharedArrayBuffer
instance, will throw aTypeError
exception.A call to writeIntoShared
with any buffer view type backed by a resizableArrayBuffer
instance or a growableSharedArrayBuffer
instance, will throw aTypeError
exception.A call to writeIntoSharedResizable
will accept any buffer view type backed by aArrayBuffer
instance or aSharedArrayBuffer
instance.3.3.3. [Clamp]
If the [
Clamp
] extended attribute appears on one of the integer types, it creates a new IDL type such that that when a JavaScript Number is converted to the IDL type, out-of-range values will be clamped to the range of valid values, rather than using the operators that use a modulo operation (ToInt32, ToUint32, etc.).The [
Clamp
] extended attribute must 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 JavaScript 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:[Exposed =Window ]interface GraphicsContext {undefined setColor (octet red ,octet green ,octet blue );undefined setColorClamped ([Clamp ]octet red , [Clamp ]octet green , [Clamp ]octet blue );A call to
setColorClamped
with Number values that are out of range for anoctet
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.4. [CrossOriginIsolated]
If the [
CrossOriginIsolated
] extended attribute appears on an interface, partial interface, interface mixin, partial interface mixin, callback interface, namespace, partial namespace, interface member, interface mixin member, or namespace member, it indicates that the construct is exposed only within an environment whose cross-origin isolated capability is true. The [CrossOriginIsolated
] extended attribute must not be used on any other construct.The [
CrossOriginIsolated
] extended attribute must take no arguments.If [
CrossOriginIsolated
] appears on an overloaded operation, then it must appear on all overloads.The [
CrossOriginIsolated
] extended attribute must not be specified both onan interface member and its interface or partial interface;
an interface mixin member and its interface mixin or partial interface mixin;
a namespace member and its namespace or partial namespace.
Note: This is because adding the [
CrossOriginIsolated
] extended attribute on a member when its containing definition is also annotated with the [CrossOriginIsolated
] extended attribute does not further restrict the exposure of the member.An interface without the [
CrossOriginIsolated
] extended attribute must not inherit from another interface that does specify [CrossOriginIsolated
].The following IDL fragment defines an interface with one operation that is executable from all contexts, and two which are executable only from cross-origin isolated contexts.
[Exposed =Window ]interface ExampleFeature { // This call will succeed in all contexts.Promise <Result >calculateNotSoSecretResult (); // This operation will not be exposed to a non-isolated context. In such a context, // there will be no "calculateSecretResult" property on ExampleFeature.prototype. [CrossOriginIsolated ]Promise <Result >calculateSecretResult (); // The same applies here: the attribute will not be exposed to a non-isolated context, // and in such a context there will be no "secretBoolean" property on // ExampleFeature.prototype. [CrossOriginIsolated ]readonly attribute boolean secretBoolean ; // HighResolutionTimer will not be exposed in a non-isolated context, nor will its members. // In such a context, there will be no "HighResolutionTimer" property on Window. [Exposed =Window ,CrossOriginIsolated ]interface HighResolutionTimer {DOMHighResTimeStamp getHighResolutionTime (); // The interface mixin members defined below will never be exposed in a non-isolated // context, regardless of whether the interface that includes them is. That is, in // non-isolated context, there will be no "snap" property on ExampleFeature.prototype. [CrossOriginIsolated ]interface mixin Snapshotable {Promise <boolean >snap ();ExampleFeature includes Snapshotable ; // On the other hand, the following interface mixin members will be exposed to a // non-isolated context when included by a host interface that doesn’t have the // [CrossOriginIsolated] extended attribute. That is, in a non-isolated context, there will // be a "log" property on ExampleFeature.prototype.interface mixin Loggable {Promise <boolean >log ();ExampleFeature includes Loggable ;3.3.5. [Default]
If the [
Default
] extended attribute appears on a regular operation, then it indicates that the appropriate default method steps must be carried out when the operation is invoked.The [
Default
] extended attribute must take no arguments.The [
Default
] extended attribute must not be used on anything other than a regular operation that has default method steps defined.As an example, the [
Default
] extended attribute is suitable for use ontoJSON
regular operations:[Exposed =Window ]interface Animal {attribute DOMString name ;attribute unsigned short age ; [Default ]object toJSON (); [Exposed =Window ]interface Human :Animal {attribute Dog ?pet ; [Default ]object toJSON (); [Exposed =Window ]interface Dog :Animal {attribute DOMString ?breed ;In the JavaScript language binding, there would exist a
toJSON()
method onAnimal
,Human
, and (via inheritance)Dog
objects:// Get an instance of Human. var alice= getHuman(); // Evaluates to an object like this (notice how "pet" still holds // an instance of Dog at this point): // name: "Alice", // age: 59, // pet: Dog alice. toJSON(); // Evaluates to an object like this (notice how "breed" is absent, // as the Dog interface doesn’t use the default toJSON steps): // name: "Tramp", // age: 6 alice. pet. toJSON(); // Evaluates to a string like this: // '{"name":"Alice","age":59,"pet":{"name":"Tramp","age":6}}' JSON. stringify( alice); 3.3.6. [EnforceRange]
If the [
EnforceRange
] extended attribute appears on one of the integer types, it creates a new IDL type such that that when a JavaScript Number is converted to the IDL type, out-of-range values will cause an exception to be thrown, rather than being converted to a valid value using using the operators that use a modulo operation (ToInt32, ToUint32, etc.). The Number will be rounded toward zero before being checked against its range.The [
EnforceRange
] extended attribute must 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 [EnforceRange
] extended attribute.See the rules for converting JavaScript values to the various IDL integer types in § 3.2 JavaScript type mapping for the specific requirements that the use of [
EnforceRange
] entails.In the following IDL fragment, two operations are declared that take three
octet
arguments; one uses the [EnforceRange
] extended attribute on all three arguments, while the other does not:[Exposed =Window ]interface GraphicsContext {undefined setColor (octet red ,octet green ,octet blue );undefined setColorEnforcedRange ([EnforceRange ]octet red , [EnforceRange ]octet green , [EnforceRange ]octet blue );In a JavaScript implementation of the IDL, a call to setColorEnforcedRange with Number values that are out of range for an
octet
will result in an exception being thrown.// Get an instance of GraphicsContext. var context= getGraphicsContext(); // Calling the non-[EnforceRange] version uses ToUint8 to coerce the Numbers to octets. // This is equivalent to calling setColor(255, 255, 1). context. setColor( - 1 , 255 , 257 ); // When setColorEnforcedRange is called, Numbers are rounded towards zero. // This is equivalent to calling setColor(0, 255, 255). context. setColorEnforcedRange( - 0.9 , 255 , 255.2 ); // The following will cause a TypeError to be thrown, since even after // rounding the first and third argument values are out of range. context. setColorEnforcedRange( - 1 , 255 , 256 ); 3.3.7. [Exposed]
When the [
Exposed
] extended attribute appears on an interface, partial interface, interface mixin, partial interface mixin, callback interface, namespace, partial namespace, or an individual interface member, interface mixin member, or namespace member, it indicates that the construct is exposed on that particular set of global interfaces.The [
Exposed
] extended attribute must either take an identifier, take an identifier list or take a wildcard. Each of the identifiers mentioned must be a global name of some interface and be unique.The own exposure set is either a set of identifiers or the special value
*
, defined as follows:If the [ Exposed
] extended attribute takes an identifier IThe own exposure set is the set « I ».
If the [ Exposed
] extended attribute takes an identifier list IThe own exposure set is the set I.
If the [ Exposed
] extended attribute takes a wildcardThe own exposure set is
*
.
[Exposed=*]
is to be used with care. It is only appropriate when an API does not expose significant new capabilities. If the API might be restricted or disabled in some environments, it is preferred to list the globals explicitly.The exposure set intersection of a construct C and interface-or-null H is defined as follows:
Assert: C is an interface member, interface mixin member, namespace member, partial interface, partial interface mixin, partial namespace, or interface mixin.
Assert: H is an interface or null.
If H is null, return C’s own exposure set.
If C’s own exposure set is
*
, return H’s exposure set.If H’s exposure set is
*
, return C’s own exposure set.Return the intersection of C’s own exposure set and H’s exposure set.
To get the exposure set of a construct C, run the following steps:Assert: C is an interface, callback interface, namespace, interface member, interface mixin member, or namespace member.
Let H be C’s host interface if C is an interface mixin member, or null otherwise.
If C is an interface member, interface mixin member, or namespace member, then:
If the [
Exposed
] extended attribute is specified on C, return the exposure set intersection of C and H.Set C to the interface, partial interface, interface mixin, partial interface mixin, namespace, or partial namespace C is declared on.
If C is a partial interface, partial interface mixin, or partial namespace, then:
If the [
Exposed
] extended attribute is specified on C, return the exposure set intersection of C and H.Set C to the original interface, interface mixin, or namespace definition of C.
If C is an interface mixin, then:
Assert: H is not null.
If the [
Exposed
] extended attribute is specified on C, return the exposure set intersection of C and H.Set C to H.
Assert: C is an interface, callback interface or namespace.
Assert: The [
Exposed
] extended attribute is specified on C.Return C’s own exposure set.
If [
Exposed
] appears on an overloaded operation, then it must appear identically on all overloads.The [
Exposed
] extended attribute must not be specified both on an interface member, interface mixin member, or namespace member, and on the partial interface, partial interface mixin, or partial namespace definition the member is declared on.Note: This is because adding an [
Exposed
] extended attribute on a partial interface, partial interface mixin, or partial namespace is shorthand for annotating each of its members.If [
Exposed
] appears on a partial interface or partial namespace, then the partial’s own exposure set must be a subset of the exposure set of the partial’s original interface or namespace.If [
Exposed
] appears on an interface or namespace member, then the member's exposure set must be a subset of the exposure set of the interface or namespace it is a member of.If [
Exposed
] appears both on a partial interface mixin and its original interface mixin, then the partial interface mixin's own exposure set must be a subset of the interface mixin's own exposure set.If [
Exposed
] appears both on an interface mixin member and the interface mixin it is a member of, then the interface mixin members's own exposure set must be a subset of the interface mixin's own exposure set.If an interface X inherits from another interface Y then the exposure set of X must be a subset of the exposure set of Y.
Note: As an interface mixin can be included by different interfaces, the exposure set of its members is a function of the interface that includes them. If the interface mixin member, partial interface mixin, or interface mixin is annotated with an [
An interface, callback interface, namespace, or member construct is exposed in a given realm realm if the following steps return true:Exposed
] extended attribute, then the interface mixin member's exposure set is the intersection of the relevant construct’s own exposure set with the host interface's exposure set. Otherwise, it is the host interface's exposure set.If construct’s exposure set is not
*
, and realm.[[GlobalObject]] does not implement an interface that is in construct’s exposure set, then return false.If realm’s settings object is not a secure context, and construct is conditionally exposed on [
SecureContext
], then return false.If realm’s settings object's cross-origin isolated capability is false, and construct is conditionally exposed on [
CrossOriginIsolated
], then return false.Return true.
An interface, callback interface, namespace, or member construct is conditionally exposed on a given extended attribute exposure condition if the following steps return true:Assert: construct is an interface, callback interface, namespace, interface member, interface mixin member, or namespace member.
Let H be construct’s host interface if construct is an interface mixin member, or null otherwise.
If construct is an interface member, interface mixin member, or namespace member, then:
If the exposure condition extended attribute is specified on construct, then return true.
Otherwise, set construct to be the interface, partial interface, interface mixin, partial interface mixin, namespace, or partial namespace construct is declared on.
If construct is a partial interface, partial interface mixin, or partial namespace, then:
If the exposure condition extended attribute is specified on construct, then return true.
Otherwise, set construct to be the original interface, interface mixin, or namespace definition of construct.
If construct is an interface mixin, then:
If the exposure condition extended attribute is specified on construct, then return true.
Otherwise, set construct to H.
Assert: construct is an interface, callback interface or namespace.
If the exposure condition extended attribute is specified on construct, then return true.
Otherwise, return false.
Note: Since it is not possible for the relevant settings object for a JavaScript global object to change whether it is a secure context or cross-origin isolated capability over time, an implementation’s decision to create properties for an interface or interface member can be made once, at the time the initial objects are created.
See § 3.7 Interfaces, § 3.7.5 Constants, § 3.7.6 Attributes, § 3.7.7 Operations, and for the specific requirements that the use of [
Exposed
] entails.[
Exposed
] is intended to be used to control whether interfaces, callback interfaces, namespaces, or individual interface, mixin or namespace members are available for use in workers,Worklet
,Window
, or any combination of the above.The following IDL fragment shows how that might be achieved:
[Exposed =Window ,Global =Window ]interface Window { // ... // By using the same identifier Worker for both SharedWorkerGlobalScope // and DedicatedWorkerGlobalScope, both can be addressed in an [Exposed] // extended attribute at once. [Exposed =Worker ,Global =Worker ]interface SharedWorkerGlobalScope :WorkerGlobalScope { // ... [Exposed =Worker ,Global =Worker ]interface DedicatedWorkerGlobalScope :WorkerGlobalScope { // ... // Dimensions is available for use in workers and on the main thread. [Exposed =(Window ,Worker )]interface Dimensions {constructor (double width ,double height );readonly attribute double width ;readonly attribute double height ; // WorkerNavigator is only available in workers. Evaluating WorkerNavigator // in the global scope of a worker would give you its interface object, while // doing so on the main thread will give you a ReferenceError. [Exposed =Worker ]interface WorkerNavigator { // ... // Node is only available on the main thread. Evaluating Node // in the global scope of a worker would give you a ReferenceError. [Exposed =Window ]interface Node { // ... // MathUtils is available for use in workers and on the main thread. [Exposed =(Window ,Worker )]namespace MathUtils {double someComplicatedFunction (double x ,double y ); // WorkerUtils is only available in workers. Evaluating WorkerUtils // in the global scope of a worker would give you its namespace object, while // doing so on the main thread will give you a ReferenceError. [Exposed =Worker ]namespace WorkerUtils {undefined setPriority (double x ); // NodeUtils is only available in the main thread. Evaluating NodeUtils // in the global scope of a worker would give you a ReferenceError. [Exposed =Window ]namespace NodeUtils {DOMString getAllText (Node node );3.3.8. [Global]
If the [
Global
] extended attribute appears on an interface, it indicates that objects implementing this interface will be used as the global object in a realm.The [
Global
] extended attribute also defines the global names for the interface:If the [ Global
] extended attribute takes an identifier« the given identifier »
If the [ Global
] extended attribute takes an identifier listthe identifier list
The [
Global
] extended attribute must be one of the forms given above.Note: The global names for the interface are the identifiers that can be used to reference it in the [
Exposed
] extended attribute. A single name can be shared across multiple different global interfaces, allowing an interface to more easily use [Exposed
] to expose itself to all of them at once. For example, "Worker
" is used to refer to several distinct types of threading-related global interfaces.For these global interfaces, the structure of the prototype chain and how properties corresponding to interface members will be reflected on the prototype objects will be different from other interfaces. Specifically:
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 will correspond to properties on the object itself rather than on interface prototype objects.
All realms have an is global prototype chain mutable boolean, which can be set when the realm is created. Its value can not change during the lifetime of the realm. By default it is set to false.
This allows the
ShadowRealm
global to have a mutable prototype.Placing named properties on an object in the prototype chain is done so that variable declarations and bareword assignments will shadow the named property with a property on the global object itself.
Placing properties corresponding to interface members on the object itself will mean that common feature detection methods like the following will work:
var indexedDB= window. indexedDB|| window. webkitIndexedDB|| window. mozIndexedDB|| window. msIndexedDB; var requestAnimationFrame= window. requestAnimationFrame|| window. mozRequestAnimationFrame|| ...; Because of the way variable declarations are handled in JavaScript, the code above would result in the
window.indexedDB
andwindow.requestAnimationFrame
evaluating toundefined , as the shadowing variable property would already have been created before the assignment is evaluated.If the [
Global
] extended attributes is used on an interface, then:The interface must not define a named property setter.
The interface must not define indexed property getters or setters.
The interface must not define a constructor operation.
The interface must not also be declared with the [
LegacyOverrideBuiltIns
] extended attribute.The interface must not inherit from another interface with the [
LegacyOverrideBuiltIns
] extended attribute.Any other interface must not inherit from it.
If [
Global
] is specified on a partial interface definition, then that partial interface definition must be the part of the interface definition that defines the named property getter.The [
Global
] extended attribute must not be used on an interface that can have more than one object implementing it in the same realm.Note: This is because the named properties object, which exposes the named properties, is in the prototype chain, and it would not make sense for more than one object’s named properties to be exposed on an object that all of those objects inherit from.
If an interface is declared with the [
Global
] extended attribute, then there must not be more than one member across the interface with the same identifier. There also must not be more than one stringifier or more than one iterable declaration, asynchronously iterable declaration, maplike declaration or setlike declaration across those interfaces.Note: This is because all of the members of the interface get flattened down on to the object that implements the interface.
See § 3.7.4 Named properties object for the specific requirements that the use of [
Global
] entails for named properties, and § 3.7.5 Constants, § 3.7.6 Attributes and § 3.7.7 Operations for the requirements relating to the location of properties corresponding to interface members.The
Window
interface exposes frames as properties on theWindow
object. Since theWindow
object also serves as the JavaScript global object, variable declarations or assignments to the named properties will result in them being replaced by the new value. Variable declarations for attributes will not create a property that replaces the existing one.[Exposed =Window ,Global =Window ]interface Window {getter any (DOMString name );attribute DOMString name ; // ...The following HTML document illustrates how the named properties on the
Window
object can be shadowed, and how the property for an attribute will not be replaced when declaring a variable of the same name:<!DOCTYPE html> < title > Variable declarations and assignments on Window</ title > < iframe name = abc ></ iframe > <!-- Shadowing named properties --> < script > window. abc; // Evaluates to the iframe’s Window object. abc= 1 ; // Shadows the named property. window. abc; // Evaluates to 1. </ script > <!-- Preserving properties for IDL attributes --> < script > Window. prototype. def= 2 ; // Places a property on the prototype. window. hasOwnProperty( "length" ); // Evaluates to true. length; // Evaluates to 1. def; // Evaluates to 2. </ script > < script > var length; // Variable declaration leaves existing property. length; // Evaluates to 1. var def; // Variable declaration creates shadowing property. def; // Evaluates to undefined. </ script > 3.3.9. [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 theDocument
interface, since a new object is always returned when it is called. [DOM][Exposed =Window ]interface Document :Node { [NewObject ]Element createElement (DOMString localName ); // ...3.3.10. [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 [LegacyLenientSetter
] or [Replaceable
] extended attributes.The [
PutForwards
] extended attribute must not be used on an attribute that is not read only.The [
PutForwards
] extended attribute must not be used on a static attribute.The [
PutForwards
] extended attribute must not be used on an attribute declared on a namespace.See the Attributes section for how [
PutForwards
] is to be implemented.The following IDL fragment defines interfaces for names and people. The [
PutForwards
] extended attribute is used on thename
attribute of thePerson
interface to indicate that assignments to that attribute result in assignments to thefull
attribute of thePerson
object:[Exposed =Window ]interface Name {attribute DOMString full ;attribute DOMString family ;attribute DOMString given ; [Exposed =Window ]interface Person { [PutForwards =full ]readonly attribute Name name ;attribute unsigned short age ;In the JavaScript binding, this would allow assignments to the
name
property:var p= getPerson(); // Obtain an instance of Person. p. name= 'John Citizen' ; // This statement... p. name. full= 'John Citizen' ; // ...has the same behavior as this one. 3.3.11. [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 [LegacyLenientSetter
] or [PutForwards
] extended attributes.The [
Replaceable
] extended attribute must not be used on an attribute that is not read only.The [
Replaceable
] extended attribute must not be used on a static attribute.The [
Replaceable
] extended attribute must not be used on an attribute declared on a namespace.See § 3.7.6 Attributes for the specific requirements that the use of [
Replaceable
] entails.The following IDL fragment defines an interface with an operation that increments a counter, and an attribute that exposes the counter’s value, which is initially 0:
[Exposed =Window ]interface Counter { [Replaceable ]readonly attribute unsigned long value ;undefined increment ();Assigning to the
value
property on a platform object implementingCounter
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.12. [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 orobject
.As an example, this extended attribute is suitable for use on the
implementation
attribute on theDocument
interface since the same object is always returned for a givenDocument
object. [DOM][Exposed =Window ]interface Document :Node { [SameObject ]readonly attribute DOMImplementation implementation ; // ...3.3.13. [SecureContext]
If the [
SecureContext
] extended attribute appears on an interface, partial interface, interface mixin, partial interface mixin, callback interface, namespace, partial namespace, interface member, interface mixin member, or namespace member, it indicates that the construct is exposed only within a secure context. The [SecureContext
] extended attribute must not be used on any other construct.The [
SecureContext
] extended attribute must take no arguments.If [
SecureContext
] appears on an overloaded operation, then it must appear on all overloads.The [
SecureContext
] extended attribute must not be specified both onan interface member and its interface or partial interface;
an interface mixin member and its interface mixin or partial interface mixin;
a namespace member and its namespace or partial namespace.
Note: This is because adding the [
SecureContext
] extended attribute on a member when its containing definition is also annotated with the [SecureContext
] extended attribute does not further restrict the exposure of the member.An interface without the [
SecureContext
] extended attribute must not inherit from another interface that does specify [SecureContext
].[
SecureContext
] must not be specified on a construct is that is conditionally exposed on [CrossOriginIsolated
]. (Doing so would be redundant, since every environment which is cross-origin isolated is also a secure context.)The following IDL fragment defines an interface with one operation that is executable from all contexts, and two which are executable only from secure contexts.
[Exposed =Window ]interface ExampleFeature { // This call will succeed in all contexts.Promise <Result >calculateNotSoSecretResult (); // This operation will not be exposed to a non-secure context. In such a context, // there will be no "calculateSecretResult" property on ExampleFeature.prototype. [SecureContext ]Promise <Result >calculateSecretResult (); // The same applies here: the attribute will not be exposed to a non-secure context, // and in a non-secure context there will be no "secretBoolean" property on // ExampleFeature.prototype. [SecureContext ]readonly attribute boolean secretBoolean ; // HeartbeatSensor will not be exposed in a non-secure context, nor will its members. // In such a context, there will be no "HeartbeatSensor" property on Window. [Exposed =Window ,SecureContext ]interface HeartbeatSensor {Promise <float >getHeartbeatsPerMinute (); // The interface mixin members defined below will never be exposed in a non-secure context, // regardless of whether the interface that includes them is. That is, in a non-secure // context, there will be no "snap" property on ExampleFeature.prototype. [SecureContext ]interface mixin Snapshotable {Promise <boolean >snap ();ExampleFeature includes Snapshotable ; // On the other hand, the following interface mixin members will be exposed to a non-secure // context when included by a host interface that doesn’t have the [SecureContext] extended // attribute. That is, in a non-secure context, there will be a "log" property on // ExampleFeature.prototype.interface mixin Loggable {Promise <boolean >log ();ExampleFeature includes Loggable ;3.3.14. [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 awith
statement. This is achieved by including the property name on the interface prototype object's%Symbol.unscopables%
property’s value.The [
Unscopable
] extended attribute must 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.7.3 Interface prototype object for the specific requirements that the use of [
Unscopable
] entails.For example, with the following IDL:
[Exposed =Window ]interface Thing {undefined f (); [Unscopable ]g ();the
f
property can be referenced with a bare identifier in awith
statement but theg
property cannot:var thing= getThing(); // An instance of Thing with ( thing) { f; // Evaluates to a Function object. g; // Throws a ReferenceError. 3.4. Legacy extended attributes
This section defines a number of extended attributes whose presence affects the JavaScript binding. Unlike those in § 3.3 Extended attributes, these exist only so that legacy Web platform features can be specified. They should not be used in specifications, unless required to specify the behavior of legacy APIs.
Editors who believe they have a good reason for using these extended attributes are strongly advised to discuss this by filing an issue before proceeding.
3.4.1. [LegacyFactoryFunction]
Instead of using this feature, give your interface a constructor operation.
If the [
LegacyFactoryFunction
] extended attribute appears on an interface, it indicates that the JavaScript global object will have a property with the specified name whose value is a function that can create objects that implement the interface. Multiple [LegacyFactoryFunction
] extended attributes may appear on a given interface.The [
LegacyFactoryFunction
] extended attribute must take a named argument list. Theidentifier that occurs directly after the “= ” is the [LegacyFactoryFunction
]'s identifier. For each [LegacyFactoryFunction
] extended attribute on the interface, there will be a way to construct an object that implements the interface by passing the specified arguments to the constructor that is the value of the aforementioned property.The identifier used for the legacy factory function must not be the same as that used by a [
LegacyFactoryFunction
] extended attribute on another interface, must not be the same as an identifier used by a [LegacyWindowAlias
] extended attribute on this interface or another interface, must not be the same as an identifier of an interface that has an interface object, and must not be one of the reserved identifiers.The [
LegacyFactoryFunction
] and [Global
] extended attributes must not be specified on the same interface.See § 3.7.2 Legacy factory functions for details on how legacy factory functions are to be implemented.
The following IDL defines an interface that uses the [
LegacyFactoryFunction
] extended attribute.[Exposed =Window ,LegacyFactoryFunction =Audio (DOMString src )]interface HTMLAudioElement :HTMLMediaElement { // ...A JavaScript implementation that supports this interface will allow the construction of
HTMLAudioElement
objects using theAudio
function.typeof Audio; // Evaluates to 'function'. var a2= new Audio( 'a.flac' ); // Creates an HTMLAudioElement using the // one-argument constructor. As an additional legacy quirk, these factory functions will have a
prototype
property equal to theprototype
of the original interface:console. assert( Audio. prototype=== HTMLAudioElement. prototype); 3.4.2. [LegacyLenientSetter]
If the [
LegacyLenientSetter
] extended attribute appears on a read only regular attribute, it indicates that a no-op setter will be generated for the attribute’s accessor property. This results in erroneous assignments to the property in strict mode to be ignored rather than causing an exception to be thrown.Pages have been observed where authors have attempted to polyfill an IDL attribute by assigning to the property, but have accidentally done so even if the property exists. In strict mode, this would cause an exception to be thrown, potentially breaking page. Without [
LegacyLenientSetter
], this could prevent a browser from shipping the feature.The [
LegacyLenientSetter
] extended attribute must take no arguments. It must not be used on anything other than a read only regular attribute.An attribute with the [
LegacyLenientSetter
] extended attribute must not also be declared with the [PutForwards
] or [Replaceable
] extended attributes.The [
LegacyLenientSetter
] extended attribute must not be used on an attribute declared on a namespace.See the Attributes section for how [
LegacyLenientSetter
] is to be implemented.The following IDL fragment defines an interface that uses the [
LegacyLenientSetter
] extended attribute.[Exposed =Window ]interface Example { [LegacyLenientSetter ]readonly attribute DOMString x ;readonly attribute DOMString y ;A JavaScript implementation that supports this interface will have a setter on the accessor property that correspond to x, which allows any assignment to be ignored in strict mode.
"use strict" ; var example= getExample(); // Get an instance of Example. // Fine; while we are in strict mode, there is a setter that is a no-op. example. x= 1 ; // Throws a TypeError, since we are in strict mode and there is no setter. example. y= 1 ; 3.4.3. [LegacyLenientThis]
If the [
LegacyLenientThis
] extended attribute appears on a regular attribute, it indicates that invocations of the attribute’s getter or setter with athis value that is not an object that implements the interface on which the attribute appears will be ignored.The [
LegacyLenientThis
] extended attribute must take no arguments. It must not be used on a static attribute.The [
LegacyLenientThis
] extended attribute must not be used on an attribute declared on a namespace.See the Attributes section for how [
LegacyLenientThis
] is to be implemented.The following IDL fragment defines an interface that uses the [
LegacyLenientThis
] extended attribute.[Exposed =Window ]interface Example { [LegacyLenientThis ]attribute DOMString x ;attribute DOMString y ;A JavaScript implementation that supports this interface will allow the getter and setter of the accessor property that corresponds to x to be invoked with something other than an
Example
object.var example= getExample(); // Get an instance of Example. var obj= { }; // Fine. example. x; // Ignored, since the this value is not an Example object and [LegacyLenientThis] is used. Object. getOwnPropertyDescriptor( Example. prototype, "x" ). get. call( obj); // Also ignored, since Example.prototype is not an Example object and [LegacyLenientThis] is used. Example. prototype. x; // Throws a TypeError, since Example.prototype is not an Example object. Example. prototype. y; 3.4.4. [LegacyNamespace]
Instead of using this feature, interface names can be formed with a naming convention of starting with a particular prefix for a set of interfaces, as part of the identifier, without the intervening dot.
If the [
LegacyNamespace
] extended attribute appears on an interface, it indicates that the interface object for this interface will not be created as a property of the global object, but rather as a property of the namespace identified by the argument to the extended attribute.The [
LegacyNamespace
] extended attribute must take an identifier. This identifier must be the identifier of a namespace definition.The [
LegacyNamespace
] and [LegacyNoInterfaceObject
] extended attributes must not be specified on the same interface.See § 3.13.1 Namespace object for details on how an interface is exposed on a namespace.
The following IDL fragment defines a namespace and an interface which uses [LegacyNamespace
] to be defined inside of it.namespace Foo { }; [LegacyNamespace =Foo ]interface Bar {constructor ();In a JavaScript implementation of the above namespace and interface, the constructor Bar can be accessed as follows:
var instance= new Foo. Bar(); 3.4.5. [LegacyNoInterfaceObject]
If the [
LegacyNoInterfaceObject
] extended attribute appears on an interface, it indicates that an interface object will not exist for the interface in the JavaScript binding.The [
LegacyNoInterfaceObject
] extended attribute must take no arguments.The [
LegacyNoInterfaceObject
] extended attribute must not be specified on an interface that has any constructors or static operations defined on it.An interface that does not have the [
LegacyNoInterfaceObject
] extended attribute specified must not inherit from an interface that has the [LegacyNoInterfaceObject
] extended attribute specified.See § 3.7 Interfaces for the specific requirements that the use of [
LegacyNoInterfaceObject
] entails.The following IDL fragment defines two interfaces, one whose interface object is exposed on the JavaScript global object, and one whose isn’t:
[Exposed =Window ]interface Storage {undefined addEntry (unsigned long key ,any value ); [Exposed =Window ,LegacyNoInterfaceObject ]interface Query {any lookupEntry (unsigned long key );A JavaScript implementation of the above IDL would allow manipulation of
Storage
’s prototype, but notQuery
’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.4.6. [LegacyNullToEmptyString]
If the [
LegacyNullToEmptyString
] extended attribute appears on theDOMString
orUSVString
type, it creates a new IDL type such that that when a JavaScriptnull is converted to the IDL type, it will be handled differently from its default handling. Instead of being stringified to "null
", which is the default, it will be converted to the empty string.The [
LegacyNullToEmptyString
] extended attribute must not be associated with a type that is notDOMString
orUSVString
.Note: This means that even
DOMString?
must not use [LegacyNullToEmptyString
], sincenull is a valid value of that type.See § 3.2.10 DOMString for the specific requirements that the use of [
The following IDL fragment defines an interface that has one attribute whose type has the extended attribute, and one operation whose argument’s type has the extended attribute:LegacyNullToEmptyString
] entails.[Exposed =Window ]interface Dog {attribute DOMString name ;attribute [LegacyNullToEmptyString ]DOMString owner ;boolean isMemberOfBreed ([LegacyNullToEmptyString ]DOMString breedName );A JavaScript implementation implementing the
Dog
interface would convert anull value assigned to theowner
property or passed as the argument to theisMemberOfBreed
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.4.7. [LegacyOverrideBuiltIns]
If the [
LegacyOverrideBuiltIns
] extended attribute appears on an interface, it indicates that for a legacy platform object implementing the interface, properties corresponding to all of the object’s supported property names will appear to be on the object, regardless of what other properties exist on the object or its prototype chain. This means that named properties will always shadow any properties that would otherwise appear on the object. This is in contrast to the usual behavior, which is for named properties to be exposed only if there is no property with the same name on the object itself or somewhere on its prototype chain.The [
LegacyOverrideBuiltIns
] extended attribute must take no arguments and must not appear on an interface that does not define a named property getter or that also is declared with the [Global
] extended attribute. If the extended attribute is specified on a partial interface definition, then that partial interface definition must be the part of the interface definition that defines the named property getter.If the [
LegacyOverrideBuiltIns
] extended attribute is specified on a partial interface definition, it is considered to appear on the interface itself.See § 3.9 Legacy platform objects and § 3.9.3 [[DefineOwnProperty]] for the specific requirements that the use of [
LegacyOverrideBuiltIns
] entails.The following IDL fragment defines two interfaces, one that has a named property getter and one that does not.
[Exposed =Window ]interface StringMap {readonly attribute unsigned long length ;getter DOMString lookup (DOMString key ); [Exposed =Window ,LegacyOverrideBuiltIns ]interface StringMap2 {readonly attribute unsigned long length ;getter DOMString lookup (DOMString key );In a JavaScript implementation of these two interfaces, getting certain properties on objects implementing the interfaces will result in different values:
// Obtain an instance of StringMap. Assume that it has "abc", "length" and // "toString" as supported property names. var map1= getStringMap(); // This invokes the named property getter. map1. abc; // This fetches the "length" property on the object that corresponds to the // length attribute. map1. length; // This fetches the "toString" property from the object’s prototype chain. map1. toString; // Obtain an instance of StringMap2. Assume that it also has "abc", "length" // and "toString" as supported property names. var map2= getStringMap2(); // This invokes the named property getter. map2. abc; // This also invokes the named property getter, despite the fact that the "length" // property on the object corresponds to the length attribute. map2. length; // This too invokes the named property getter, despite the fact that "toString" is // a property in map2’s prototype chain. map2. toString; 3.4.8. [LegacyTreatNonObjectAsNull]
If the [
LegacyTreatNonObjectAsNull
] extended attribute appears on a callback function, then it indicates that any value assigned to an attribute whose type is a nullable callback function will be converted more loosely: if the value is not an object, it will be converted to null, and if the value is not callable, it will be converted to a callback function value that does nothing when called.See § 3.2.20 Nullable types — T?, § 3.2.19 Callback function types and § 3.12 Invoking callback functions for the specific requirements that the use of [
LegacyTreatNonObjectAsNull
] entails.The following IDL fragment defines an interface that has one attribute whose type is a [
LegacyTreatNonObjectAsNull
]-annotated callback function and another whose type is a callback function without the extended attribute:callback OccurrenceHandler =undefined (DOMString details ); [LegacyTreatNonObjectAsNull ]callback ErrorHandler =undefined (DOMString details ); [Exposed =Window ]interface Manager {attribute OccurrenceHandler ?handler1 ;attribute ErrorHandler ?handler2 ;In a JavaScript implementation, assigning a value that is not an object (such as a Number value), or that is not callable to handler1 will have different behavior from that when assigning to handler2:
var manager= getManager(); // Get an instance of Manager. manager. handler1= function () { }; manager. handler1; // Evaluates to the function. try { manager. handler1= 123 ; // Throws a TypeError. } catch ( e) { try { manager. handler1= {}; // Throws a TypeError. } catch ( e) { manager. handler2= function () { }; manager. handler2; // Evaluates to the function. manager. handler2= 123 ; manager. handler2; // Evaluates to null. manager. handler2= {}; manager. handler2; // Evaluates to the object.