Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.
This document defines an interface definition language, Web IDL, that can be used to describe interfaces that are intended to be implemented in web browsers. Web IDL is an IDL variant with a number of features that allow the behavior of common script objects in the web platform to be specified more readily. How interfaces described with Web IDL correspond to constructs within ECMAScript execution environments is also detailed in this document. It is expected that this document acts as a guide to implementors of already-published specifications, and that newly published specifications reference this document to ensure conforming implementations of interfaces are interoperable.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
This document is the 19 April 2012 Candidate Recommendation of the Web IDL specification. Please send comments about this document to public-script-coord@w3.org (archived).
This document will remain a Candidate Recommendation until at least 19 July 2012. See the Candidate Recommendation exit criteria section for details on the criteria that must be met before this document can progress to the Proposed Recommendation stage, and for the features that are considered at risk and which may be dropped from the specification without the document returning to a Last Call Working Draft. As yet there is no implementation report available.
This document is produced by the Web Applications Working Group, part of the Rich Web Clients Activity in the W3C Interaction Domain. Changes made to this document can be found in the W3C public CVS server.
There is a bug tracker for the specification. Issues raised during the three Last Call comment periods are tracked in the following documents:
Publication as a Candidate Recommendation does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This section is informative.
Technical reports published by the W3C that include programming language interfaces have typically been described using the Object Management Group’s Interface Definition Language (IDL) [OMGIDL]. The IDL provides a means to describe these interfaces in a language independent manner. Usually, additional language binding appendices are included in such documents which detail how the interfaces described with the IDL correspond to constructs in the given language.
However, the bindings in these specifications for the language most commonly used on the web, ECMAScript, are consistently specified with low enough precision as to result in interoperability issues. In addition, each specification must describe the same basic information, such as DOM interfaces described in IDL corresponding to properties on the ECMAScript global object, or the unsigned long IDL type mapping to the Number type in ECMAScript.
This specification defines an IDL language similar to OMG IDL for use by specifications that define interfaces for Web APIs. A number of extensions are given to the IDL to support common functionality that previously must have been written in prose. In addition, precise language bindings for ECMAScript Edition 5.1 are given.
The following typographic conventions are used in this document:
a = b + obj.f()
interface identifier { interface-members… };(Red text is used to highlight specific parts of the syntax discussed in surrounding prose.)
[5] | ExampleGrammarSymbol | → | OtherSymbol "sometoken" | AnotherSymbol | ε // nothing |
This is a note.
This is an example.
This is a warning.
// This is an IDL code block.
interface Example {
attribute long something;
};
// This is an ECMAScript code block.
window.onload = function() { window.alert("loaded"); };
Everything in this specification is normative except for diagrams, examples, notes and sections marked as being informative.
The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY” and “OPTIONAL” in this document are to be interpreted as described in Key words for use in RFCs to Indicate Requirement Levels [RFC2119].
The following conformance classes are defined by this specification:
An IDL fragment is considered to be a conforming IDL fragment if it satisfies all of the MUST-, REQUIRED- and SHALL-level criteria in this specification that apply to IDL fragments.
A user agent is considered to be a conforming implementation relative to a conforming IDL fragment if it satisfies all of the MUST-, REQUIRED- and SHALL-level criteria in this specification that apply to implementations for all language bindings that the user agent supports.
A user agent is considered to be a conforming ECMAScript implementation relative to a conforming IDL fragment if it satisfies all of the MUST-, REQUIRED- and SHALL-level criteria in this specification that apply to implementations for the ECMAScript language binding.
This section describes a language, Web IDL, which can be used to define interfaces for APIs in the Web platform. A specification that defines Web APIs can include one or more IDL fragments that describe the interfaces (the state and behavior that objects can exhibit) for the APIs defined by that specification. An IDL fragment is a sequence of definitions that matches the Definitions grammar symbol. The set of IDL fragments that an implementation supports is not ordered. See Appendix A for the complete grammar and an explanation of the notation used.
The different kinds of definitions that can appear in an IDL fragment are: interfaces, partial interface definitions, dictionaries, partial dictionary definitions, exceptions, typedefs and implements statements. These are all defined in the following sections.
Each definition (matching Definition) can be preceded by a list of extended attributes (matching ExtendedAttributeList), which can control how the definition will be handled in language bindings. The extended attributes defined by this specification that are language binding agnostic are discussed in section 3.11, while those specific to the ECMAScript language binding are discussed in section 4.3.
[extended-attributes] interface identifier { interface-members… };
[1] | Definitions | → | ExtendedAttributeList Definition Definitions | ε |
[2] | Definition | → | CallbackOrInterface | Partial | Dictionary | Exception | Enum | Typedef | ImplementsStatement |
[3] | CallbackOrInterface | → | "callback" CallbackRestOrInterface | Interface |
The following is an example of an IDL fragment.
exception GraphicsException {
DOMString reason;
};
interface Paint { };
interface SolidColor : Paint {
attribute float red;
attribute float green;
attribute float blue;
};
interface Pattern : Paint {
attribute DOMString imageURL;
};
[Constructor]
interface GraphicalWindow {
readonly attribute unsigned long width;
readonly attribute unsigned long height;
attribute Paint currentPaint;
void drawRectangle(float x, float y, float width, float height);
void drawText(float x, float y, DOMString text);
};
Here, four interfaces and one exception are being defined. The GraphicalWindow interface has two read only attributes, one writable attribute, and two operations defined on it. Objects that implement the GraphicalWindow interface will expose these attributes and operations in a manner appropriate to the particular language being used.
In ECMAScript, the attributes on the IDL interfaces will be exposed as accessor properties and the operations as Function-valued data properties on a prototype object for all GraphicalWindow objects; each ECMAScript object that implements GraphicalWindow will have that prototype object in its prototype chain.
The [Constructor] that appears on GraphicalWindow
is an extended attribute.
This extended attribute causes a constructor to exist in ECMAScript implementations,
so that calling new GraphicalWindow()
would return a new object
that implemented the interface.
Every interface, partial interface definition, dictionary, partial dictionary definition, exception, enumeration, callback function and typedef (together called named definitions) and every constant, attribute, exception field and dictionary member has an identifier, as do some operations. The identifier is determined by an identifier token somewhere in the declaration:
interface
,
dictionary
, exception
, enum
or callback
keyword
determines the identifier of that definition.
interface interface-identifier { interface-members… }; partial interface interface-identifier { interface-members… }; exception exception-identifier { exception-members… }; dictionary dictionary-identifier { dictionary-members… }; partial dictionary dictionary-identifier { dictionary-members… }; enum enumeration-identifier { enumeration-values… }; callback callback-identifier = callback-signature;
interface identifier { attribute type attribute-identifier; }; typedef type typedef-identifier; exception identifier { type exception-member-identifier; }; dictionary identifier { type dictionary-member-identifier; };
const type constant-identifier = value;
return-type operation-identifier(arguments…);
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 single leading U+005F LOW LINE ("_") character (underscore) removed.
A leading "_" is used to escape an identifier from looking like a reserved word so that, for example, an interface named “interface” can be defined. The leading "_" is dropped to unescape the identifier.
Operation arguments can take a slightly wider set of identifiers. In an operation declaration, the identifier of an argument is specified immediately after its type and is given by either an identifier token or by one of the keywords that match the ArgumentNameKeyword symbol. If one of these keywords is used, it need not be escaped with a leading underscore.
return-type operation-identifier(argument-type argument-identifier, …);
[55] | ArgumentNameKeyword | → |
"attribute" | "callback" | "const" | "creator" | "deleter" | "dictionary" | "enum" | "exception" | "getter" | "implements" | "inherit" | "interface" | "legacycaller" | "partial" | "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 single leading U+005F LOW LINE ("_") character (underscore) removed. If instead one of the ArgumentNameKeyword keyword token is used, then the identifier of the operation argument is simply that token.
The identifier of any of the abovementioned IDL constructs MUST NOT be “prototype”, “constructor”, “toString” or begin with a U+005F LOW LINE ("_") character. These are known as reserved identifiers.
Within the set of IDL fragments that a given implementation supports, the identifier of every interface, dictionary, exception, enumeration, callback function and typedef MUST NOT be the same as the identifier of any other interface, dictionary, exception, enumeration, callback function or typedef
Within an IDL fragment, a reference to a definition need not appear after the declaration of the referenced definition. References can also be made across IDL fragments.
Therefore, the following IDL fragment is valid:
interface B : A {
void f(ArrayOfLongs x);
};
interface A {
};
typedef long[] ArrayOfLongs;
The following IDL fragment demonstrates how identifiers are given to definitions, interface members and exception members.
// Typedef identifier: "number"
typedef float number;
// Exception identifier: "FrameworkException"
exception FrameworkException {
// Constant identifier: "ERR_NOT_FOUND"
const long ERR_NOT_FOUND = 1;
// Exception field identifier: "code"
long code;
};
// Interface identifier: "System"
interface System {
// Operation identifier: "createObject"
// Operation argument identifier: "interface"
object createObject(DOMString _interface);
// Operation argument identifier: "interface"
object[] createObjectArray(DOMString interface);
// Operation has no identifier; it declares a getter.
getter DOMString (DOMString keyName);
};
// Interface identifier: "TextField"
interface TextField {
// Attribute identifier: "const"
attribute boolean _const;
// Attribute identifier: "value"
attribute DOMString? _value;
};
Note that while the second attribute on the TextField interface need not have been escaped with an underscore (because “value” is not a keyword in the IDL grammar), it is still unescaped to obtain the attribute’s identifier.
IDL fragments are used to describe object oriented systems. In such systems, objects are entities that have identity and which are encapsulations of state and behavior. An interface is a definition (matching Interface or "callback" Interface) that declares some state and behavior that an object implementing that interface will expose.
interface identifier { interface-members… };
An interface is a specification of a set of interface members (matching InterfaceMembers), which are the constants, attributes and operations that appear between the braces in the interface declaration. Attributes describe the state that an object implementing the interface will expose, and operations describe the behaviors that can be invoked on the object. Constants declare named constant values that are exposed as a convenience to users of objects in the system.
Interfaces in Web IDL describe how objects that implement the interface behave. In bindings for object oriented languages, it is expected that an object that implements a particular IDL interface provides ways to inspect and modify the object's state and to invoke the behavior described by the interface.
An interface can be defined to inherit from another interface. If the identifier of the interface is followed by a U+003A COLON (":") character and an identifier, then that identifier identifies the inherited interface. An object that implements an interface that inherits from another also implements that inherited interface. The object therefore will also have members that correspond to the interface members from the inherited interface.
interface identifier : identifier-of-inherited-interface { interface-members… };
The order that members appear in has no significance except in the case of overloading.
Interfaces may specify an interface member that has the same name as one from an inherited interface. Objects that implement the derived interface will expose the member on the derived interface. It is language binding specific whether the overridden member can be accessed on the object.
Consider the following two interfaces.
interface A {
void f();
void g();
};
interface B : A {
void f();
void g(DOMString x);
};
In the ECMAScript language binding, an instance of B will have a prototype chain that looks like the following:
[Object.prototype: the Object prototype object] ↑ [A.prototype: interface prototype object for A] ↑ [B.prototype: interface prototype object for B] ↑ [instanceOfB]
Calling instanceOfB.f()
in ECMAScript will invoke the f defined
on B. However, the f from A
can still be invoked on an object that implements B by
calling A.prototype.f.call(instanceOfB)
.
The inherited interfaces of a given interface A is the set of all interfaces that A inherits from, directly or indirectly. If A does not inherit from another interface, then the set is empty. Otherwise, the set includes the interface B that A inherits from and all of B’s inherited interfaces.
An interface MUST NOT be declared such that its inheritance hierarchy has a cycle. That is, an interface A cannot inherit from itself, nor can it inherit from another interface B that inherits from A, and so on.
Note that general multiple inheritance of interfaces is not supported, and objects also cannot implement arbitrary sets of interfaces. Objects can be defined to implement a single given interface A, which means that it also implements all of A’s inherited interfaces. In addition, an implements statement can be used to define that objects implementing an interface will always also implement another interface.
Each interface member can be preceded by a list of extended attributes (matching ExtendedAttributeList), which can control how the interface member will be handled in language bindings.
interface identifier { [extended-attributes] const type identifier = value; [extended-attributes] attribute type identifier; [extended-attributes] return-type identifier(arguments…); };
A callback interface is
an interface
that uses the callback
keyword at the start of
its definition. Callback interfaces are ones that can be
implemented by user objects
and not by platform objects,
as described in section 3.9
below.
callback interface identifier { interface-members… };
See also the similarly named callback function definition.
Callback interfaces MUST not inherit from any non-callback interfaces, and all of a callback interface’s inherited interfaces MUST NOT have any consequential interfaces.
Specification authors SHOULD NOT define callback interfaces that have only a single operation, unless required to describe the requirements of existing APIs. Instead, a callback function SHOULD used.
The definition of EventListener as a callback interface is an example of an existing API that needs to allow user objects with a given property (in this case “handleEvent”) to be considered to implement the interface. For new APIs, and those for which there are no compatibility concerns, using a callback function will allow only a Function object (in the ECMAScript language binding).
Specification authors wanting to define APIs that take ECMAScript objects as “property bag” like function arguments are suggested to use dictionary types rather than callback interfaces.
For example, instead of this:
callback interface Options {
attribute DOMString? option1;
attribute DOMString? option2;
attribute long? option3;
};
interface A {
void doTask(DOMString type, Options options);
};
to be used like this:
var a = getA(); // Get an instance of A.
a.doTask("something", { option1: "banana", option3: 100 });
instead write the following:
dictionary Options {
DOMString? option1;
DOMString? option2;
long? option3;
};
interface A {
void doTask(DOMString type, Options options);
};
The IDL for interfaces can be split into multiple parts by using partial interface definitions (matching "partial" PartialInterface). The identifier of a partial interface definition MUST be the same as the identifier of an interface definition. All of the members that appear on each of the partial interfaces are considered to be members of the interface itself.
interface SomeInterface { interface-members… }; partial interface SomeInterface { interface-members… };
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.
Extended attributes can be specified on partial interface definitions, with some limitations. The following extended attributes MUST NOT be specified on partial interface definitions: [ArrayClass], [Constructor], [ImplicitThis], [NamedConstructor], [NoInterfaceObject].
The above list of extended attributes is all of those defined in this document that are applicable to interfaces except for [OverrideBuiltins] and [NamedPropertiesObject].
Any extended attribute specified on a partial interface definition is considered to appear on the interface itself.
The relevant language binding determines how interfaces correspond to constructs in the language.
The following extended attributes are applicable to interfaces: [ArrayClass], [Constructor], [ImplicitThis], [NamedConstructor], [NamedPropertiesObject], [NoInterfaceObject], [OverrideBuiltins].
[3] | CallbackOrInterface | → | "callback" CallbackRestOrInterface | Interface |
[4] | CallbackRestOrInterface | → | CallbackRest | Interface |
[5] | Interface | → | "interface" identifier Inheritance "{" InterfaceMembers "}" ";" |
[6] | Partial | → | "partial" PartialDefinition |
[7] | PartialDefinition | → | PartialInterface | PartialDictionary |
[8] | PartialInterface | → | "interface" identifier "{" InterfaceMembers "}" ";" |
[9] | InterfaceMembers | → | ExtendedAttributeList InterfaceMember InterfaceMembers | ε |
[10] | InterfaceMember | → | Const | AttributeOrOperation |
[19] | Inheritance | → | ":" identifier | ε |
The following IDL fragment
demonstrates the definition of two mutually referential interfaces.
Both Human and Dog
inherit from Animal. Objects that implement
either of those two interfaces will thus have a name
attribute.
interface Animal {
attribute DOMString name;
};
interface Human : Animal {
attribute Dog? pet;
};
interface Dog : Animal {
attribute Human? owner;
};
The following IDL fragment defines simplified versions of a few DOM interfaces, one of which is a callback interface.
interface Node {
readonly attribute DOMString nodeName;
readonly attribute Node? parentNode;
Node appendChild(Node newChild);
void addEventListener(DOMString type, EventListener listener);
};
callback interface EventListener {
void handleEvent(Event event);
};
Since the EventListener interface is annotated callback interface, user objects can implement it:
var node = getNode(); // Obtain an instance of Node.
var listener = {
handleEvent: function(event) {
...
}
};
node.addEventListener("click", listener); // This works.
node.addEventListener("click", function() { ... }); // As does this.
It is not possible for a user object to implement Node, however:
var node = getNode(); // Obtain an instance of Node.
var newNode = {
nodeName: "span",
parentNode: null,
appendChild: function(newchild) {
...
},
addEventListener: function(type, listener) {
...
}
};
node.appendChild(newNode); // This will throw a TypeError exception.
A constant is a declaration (matching Const) used to bind a constant value to a name. Constants can appear on interfaces and exceptions.
Constants have in the past primarily been used to define named integer codes in the style of an enumeration. The Web platform is moving away from this design pattern in favor of the use of strings. Specification authors who wish to define constants are strongly advised to discuss this on the public-script-coord@w3.org mailing list before proceeding.
const type identifier = value;
The identifier of a constant MUST NOT be the same as the identifier of another interface member defined on the same interface or another exception member defined on the same exception.
The type of a constant (matching ConstType) MUST NOT be any type other than a primitive type or a nullable primitive type. If an identifier is used, it MUST reference a typedef whose type is a primitive type or a nullable primitive type.
The ConstValue part of a
constant declaration gives the value of the constant, which can be
one of the two boolean literal tokens (true
and false
),
the null
token, an
integer token,
a float token,
or one of the three special floating point constant values
(-Infinity
, Infinity
and NaN
).
These values – in addition to strings – can also be used to specify the default value of a dictionary member or of an optional argument. Note that strings cannot be used as the value of a constant.
The value of the boolean literal tokens true
and
false
are the IDL boolean values
true and false.
The value of an integer token is an integer whose value is determined as follows:
The type of an integer token is the same as the type of the constant, dictionary member or optional argument it is being used as the value of. The value of the integer token MUST NOT lie outside the valid range of values for its type, as given in section 3.10 below.
The value of a float token is either an IEEE 754 single-precision floating point number or an IEEE 754 double-precision floating point number, depending on the type of the constant, dictionary member or optional argument it is being used as the value for, determined as follows:
The value of a constant value specified as
Infinity
, -Infinity
or NaN
is either
an IEEE 754 single-precision floating point number or an IEEE 754
double-precision floating point number, depending on the type of the
constant, dictionary member or optional argument is is being used as the
value for:
Infinity
Infinity
-Infinity
-Infinity
NaN
NaN
The type of a float token is the same
as the type of the constant, dictionary member or optional argument it is being used as the value of. The value of the
float token MUST NOT
lie outside the valid range of values for its type, as given in
section 3.10 below.
Also, Infinity
, -Infinity
and NaN
MUST NOT
be used as the value of a float
or double.
The value of the null
token is the special
null value that is a member of the
nullable types. The type of
the null
token is the same as the
type of the constant, dictionary member or optional argument it is being used as the value of.
If VT is the type of the value assigned to a constant, and DT is the type of the constant, dictionary member or optional argument itself, then these types MUST be compatible, which is the case if DT and VT are identical, or DT is a nullable type whose inner type is VT.
Constants are not associated with particular instances of the interface on which they appear. It is language binding specific whether constants are exposed on instances.
The ECMAScript language binding does however allow constants to be accessed through objects implementing the IDL interfaces on which the constants are declared. For example, with the following IDL:
interface A {
const short rambaldi = 47;
};
the constant value can be accessed in ECMAScript either as
A.rambaldi
or instanceOfA.rambaldi
.
No extended attributes defined in this specification are applicable to constants.
[26] | Const | → | "const" ConstType identifier "=" ConstValue ";" |
[27] | ConstValue | → | BooleanLiteral | FloatLiteral | integer | "null" |
[28] | BooleanLiteral | → | "true" | "false" |
[29] | FloatLiteral | → | float | "-" "Infinity" | "Infinity" | "NaN" |
[63] | ConstType | → | PrimitiveType Null | identifier Null |
The following IDL fragment demonstrates how constants of the above types can be defined.
interface Util {
const boolean DEBUG = false;
const octet LF = 10;
const unsigned long BIT_MASK = 0x0000fc00;
const float AVOGADRO = 6.022e23;
};
exception Problem {
const short ERR_UNKNOWN = 0;
const short ERR_OUT_OF_MEMORY = 1;
short errorCode;
};
An attribute is an interface member (matching "stringifier" Attribute or Attribute) that is used to declare that objects implementing the interface will have a member with the given identifier whose value can be retrieved and (in some cases) changed.
attribute type identifier;
The identifier of an attribute MUST NOT be the same as the identifier of another interface member defined on the same interface.
The type of the attribute is given by the type (matching Type)
that appears after the attribute
keyword.
If the Type is an
identifier
or an identifier followed by ?
, then the identifier MUST
identify an interface, enumeration,
callback function or typedef.
The type of the attribute MUST NOT be a
sequence type or
nullable sequence type,
and it MUST NOT be a
union type if
one of its member types
(or one of its member types’s member types, and so on)
is a sequence type or
nullable sequence type.
The attribute is read only if the
readonly
keyword is used before the attribute
keyword.
An object that implements the interface on which a read only attribute
is defined will not allow assignment to that attribute. It is language
binding specific whether assignment is simply disallowed by the language,
ignored or an exception is thrown.
readonly attribute type identifier;
An attribute that is not read only
can be declared to inherit its getter
from an ancestor interface. This can be used to make a read only attribute
in an ancestor interface be writable on a derived interface. An attribute
inherits its getter if
its declaration includes inherit
in the declaration.
The read only attribute from which the attribute inherits its getter
is the attribute with the same identifier on the closest ancestor interface
of the one on which the inheriting attribute is defined. The attribute
whose getter is being inherited MUST be
of the same type as the inheriting attribute, and inherit
MUST NOT appear on a read only attribute.
interface Ancestor { readonly attribute TheType theIdentifier; }; interface Derived : Ancestor { inherit attribute TheType theIdentifier; };
When the stringifier
keyword is used
in an attribute declaration, it indicates that objects implementing the
interface will be stringified to the value of the attribute. See
section 3.2.4.2
below for details.
stringifier attribute DOMString identifier;
If an implementation attempts to get or set the value of an attribute on a user object (for example, when a callback object has been supplied to the implementation), and that attempt results in an exception being thrown, then, unless otherwise specified, that exception will be propagated to the user code that caused the implementation to access the attribute. Similarly, if a value returned from getting the attribute cannot be converted to an IDL type, then any exception resulting from this will also be propagated to the user code that resulted in the implementation attempting to get the value of the attribute.
The following extended attributes are applicable to attributes: [Clamp], [EnforceRange], [LenientThis], [PutForwards], [Replaceable], [TreatNullAs], [TreatUndefinedAs], [Unforgeable].
[30] | AttributeOrOperation | → | "stringifier" StringifierAttributeOrOperation | Attribute | Operation |
[31] | StringifierAttributeOrOperation | → | Attribute | OperationRest | ";" |
[32] | Attribute | → | Inherit ReadOnly "attribute" Type identifier ";" |
[33] | Inherit | → | "inherit" | ε |
[34] | ReadOnly | → | "readonly" | ε |
The following IDL fragment demonstrates how attributes can be declared on an interface:
interface Animal {
// A simple attribute that can be set to any string value.
readonly attribute DOMString name;
// An attribute whose value can be assigned to.
attribute unsigned short age;
};
interface Person : Animal {
// An attribute whose getter behavior is inherited from Animal, and need not be
// specified in the description of Person.
inherit attribute DOMString name;
};
An operation is an interface member (matching "stringifier" OperationRest or Operation) that defines a behavior that can be invoked on objects implementing the interface. There are three kinds of operation:
return-type identifier(arguments…);
special-keywords… return-type identifier(arguments…); special-keywords… return-type (arguments…);
static return-type identifier(arguments…);
If an operation has an identifier but no static
keyword, then it declares a regular operation.
If the operation has one or more
special keywords
used in its declaration (that is, any keyword matching
Special, or
the stringifier
keyword),
then it declares a special operation. A single operation can declare
both a regular operation and a special operation; see
section 3.2.4 below
for details on special operations.
If an operation has no identifier, then it MUST be declared to be a special operation using one of the special keywords.
The identifier of a regular operation or static operation MUST NOT be the same as the identifier of a constant or attribute defined on the same interface.
The identifier can be the same as that of another operation on the interface, however. This is how operation overloading is specified.
The identifier of a static operation also MUST NOT be the same as the identifier of a regular operation defined on the same interface.
The return type of the operation is given
by the type (matching ReturnType)
that appears before the operation’s optional identifier.
A return type of void
indicates that the operation returns no value.
If the return type is an
identifier or an identifier followed by ?
,
then the identifier MUST
identify an interface, dictionary, enumeration,
callback function or typedef.
An operation’s arguments (matching ArgumentList) are given between the parentheses in the declaration. Each individual argument is specified as a type (matching Type) followed by an identifier (matching ArgumentName).
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 or an identifier
followed by ?
,
then the identifier MUST identify an interface, dictionary,
enumeration, callback function
or typedef.
return-type identifier(type identifier, type identifier, …);
The identifier of each argument MUST NOT be the same as the identifier of another argument in the same operation declaration.
Each argument can be preceded by a list of extended attributes (matching ExtendedAttributeList), which can control how a value passed as the argument will be handled in language bindings.
return-type identifier([extended-attributes] type identifier, [extended-attributes] type identifier, …);
The following IDL fragment demonstrates how regular operations can be declared on an interface:
interface Dimensions {
attribute unsigned long width;
attribute unsigned long height;
};
exception NoPointerDevice { };
interface Button {
// An operation that takes no arguments and returns a boolean.
boolean isMouseOver();
// Overloaded operations.
void setDimensions(Dimensions size);
void setDimensions(unsigned long width, unsigned long height);
};
An operation is considered to be variadic
if the final argument uses the ...
token just
after the argument type. Declaring an operation to be variadic indicates that
the operation can be invoked with any number of arguments after that final argument.
Those extra implied formal arguments are of the same type as the final explicit
argument in the operation declaration. The final argument can also be omitted
when invoking the operation. An argument MUST NOT
be declared with the ...
token unless it
is the final argument in the operation’s argument list.
return-type identifier(type... identifier); return-type identifier(type identifier, type... identifier);
Extended attributes
that take an argument list
([Constructor] and
[NamedConstructor], of those
defined in this specification) and callback functions
are also considered to be variadic
when the ...
token is used in their argument lists.
The following IDL fragment defines an interface that has two variadic operations:
interface IntegerSet {
readonly attribute unsigned long cardinality;
void union(long... ints);
void intersection(long... ints);
};
In the ECMAScript binding, variadic operations are implemented by functions that can accept the subsequent arguments:
var s = getIntegerSet(); // Obtain an instance of IntegerSet.
s.union(); // Passing no arguments corresponding to 'ints'.
s.union(1, 4, 7); // Passing three arguments corresponding to 'ints'.
A binding for a language that does not support variadic functions might specify that an explicit array or list of integers be passed to such an operation.
An argument is considered to be an optional argument
if it is declared with the 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. An argument MUST NOT
be declared to be optional unless all subsequent arguments to the
operation are also optional. Also, the final argument in an
operation MUST NOT be declared to be
optional if the operation is variadic.
return-type identifier(type identifier, optional type identifier);
Optional arguments can also have a default value specified. If the argument’s identifier is followed by a U+003D EQUALS SIGN ("=") and a value (matching DefaultValue), then that gives the optional argument its default value. The implicitly optional final argument of a variadic operation MUST NOT have a default value specified. The default value is the value to be assumed when the operation is called with the corresponding argument omitted.
return-type identifier(type identifier, optional type identifier = value);
If an optional argument has a default value, then all following arguments (except for the final argument if the operation is variadic) MUST also have a default value.
When a boolean literal token (true
or false
),
the null
token,
an integer token, a
float token or one of
the three special floating point literal values (Infinity
,
-Infinity
or NaN
) is used as the
default value,
it is interpreted in the same way as for a constant.
Optional argument default values can also be specified using a string
token, whose value is a DOMString or
enumeration determined as follows:
If the type of the optional argument is an enumeration, then its default value if specified MUST be one of the enumeration’s values.
Web IDL operations do not support being called with omitted optional arguments unless all subsequent optional arguments are also omitted. Bindings for languages that do support function calling in this way will fail such calls in a language binding specific manner.
ECMAScript, the only language for which bindings are specified in this document, does not support function calling like this.
The following IDL fragment defines an interface with a single operation that can be invoked with two different argument list lengths:
interface ColorCreator {
object createColor(float v1, float v2, float v3, optional float alpha);
};
It is equivalent to an interface that has two overloaded operations:
interface ColorCreator {
object createColor(float v1, float v2, float v3);
object createColor(float v1, float v2, float v3, float alpha);
};
If an implementation attempts to invoke an operation on a user object (for example, when a callback object has been supplied to the implementation), and that attempt results in an exception being thrown, then, unless otherwise specified, that exception will be propagated to the user code that caused the implementation to invoke the operation. Similarly, if a value returned from invoking the operation cannot be converted to an IDL type, then any exception resulting from this will also be propagated to the user code that resulted in the implementation attempting to invoke the operation.
The following extended attributes are applicable to operations: [TreatNullAs], [TreatUndefinedAs].
The following extended attributes are applicable to operation arguments: [Clamp], [EnforceRange], [TreatNullAs], [TreatUndefinedAs].
A special operation is a declaration of a certain kind of special behavior on objects implementing the interface on which the special operation declarations appear. Special operations are declared by using one or more special keywords in an operation declaration.
There are six kinds of special operations. The table below indicates for a given kind of special operation what special keyword is used to declare it and what the purpose of the special operation is:
Special operation | Keyword | Purpose |
---|---|---|
Getters | getter |
Defines behavior for when an object is indexed for property retrieval. |
Setters | setter |
Defines behavior for when an object is indexed for property assignment. |
Creators | creator |
Defines behavior for when an object is indexed for property creation. |
Deleters | deleter |
Defines behavior for when an object is indexed for property deletion. |
Legacy callers | legacycaller |
Defines behavior for when an object is called as if it were a function. |
Stringifiers | stringifier |
Defines how an object is converted into a DOMString. |
Not all language bindings support all of the six kinds of special object behavior. When special operations are declared using operations with no identifier, then in language bindings that do not support the particular kind of special operations there simply will not be such functionality.
Some language bindings, such as ECMAScript, do not distinguish assignment to an existing indexed or named property and the creation of a new one. Regardless, it is the creator that is invoked when an attempt is made to create a new indexed or named property, and the setter when the property already exists.
The following IDL fragment defines an interface with a getter and a setter:
interface Dictionary {
readonly attribute unsigned long propertyCount;
getter float (DOMString propertyName);
setter void (DOMString propertyName, float propertyValue);
};
In language bindings that do not support property getters and setters, objects implementing Dictionary will not have that special behavior.
Defining a special operation with an identifier is equivalent to separating the special operation out into its own declaration without an identifier. This approach is allowed to simplify prose descriptions of an interface’s operations.
The following two interfaces are equivalent:
interface Dictionary {
readonly attribute unsigned long propertyCount;
getter float getProperty(DOMString propertyName);
setter void setProperty(DOMString propertyName, float propertyValue);
};
interface Dictionary {
readonly attribute unsigned long propertyCount;
float getProperty(DOMString propertyName);
void setProperty(DOMString propertyName, float propertyValue);
getter float (DOMString propertyName);
setter void (DOMString propertyName, float propertyValue);
};
A given special keyword MUST NOT appear twice on an operation.
Getters, setters, creators and deleters come in two varieties: ones that take a DOMString as a property name, known as named property getters, named property setters, named property creators and named property deleters, and ones that take an unsigned long as a property index, known as indexed property getters, indexed property setters, indexed property creators and indexed property deleters. See section 3.2.4.3 and section 3.2.4.4 for details.
On a given interface, there MUST exist at most one stringifier and at most one of each variety of getter, setter, creator and deleter. Multiple legacy callers can exist on an interface to specify overloaded calling behavior.
Special operations declared using operations MUST NOT be variadic nor have any optional arguments.
Special operations MUST NOT be declared on callback interfaces.
If an object implements more than one interface that defines a given special operation, then it is undefined which (if any) special operation is invoked for that operation.
When an interface has one or more
legacy callers, it indicates that objects that implement
the interface can be called as if they were functions. As mentioned above,
legacy callers can be specified using an operation
declared with the legacycaller
keyword.
legacycaller return-type identifier(arguments…); legacycaller return-type (arguments…);
If multiple legacy callers are specified on an interface, overload resolution is used to determine which legacy caller is invoked when the object is called as if it were a function.
Legacy callers are universally recognised as an undesirable feature. They exist only so that legacy Web platform features can be specified. Legacy callers SHOULD NOT be used in specifications unless required to specify the behavior of legacy APIs, and even then this should be discussed on the public-script-coord@w3.org mailing list before proceeding.
The following IDL fragment defines an interface with a legacy caller.
interface NumberQuadrupler {
// This operation simply returns four times the given number x.
legacycaller float compute(float x);
};
An ECMAScript implementation supporting this interface would allow a platform object that implements NumberQuadrupler to be called as a function:
var f = getNumberQuadrupler(); // Obtain an instance of NumberQuadrupler.
f.compute(3); // This evaluates to 12.
f(3); // This also evaluates to 12.
When an interface has a
stringifier, it indicates that objects that implement
the interface have a non-default conversion to a string. As mentioned above,
stringifiers can be specified using an operation
declared with the stringifier
keyword.
stringifier DOMString identifier(); stringifier DOMString ();
If an operation used to declare a stringifier does not have an identifier, then prose accompanying the interface MUST define the stringification behavior of the interface. If the operation does have an identifier, then the object is converted to a string by invoking the operation to obtain the string.
Stringifiers declared with operations MUST be declared to take zero arguments and return a DOMString.
As a shorthand, if the stringifier
keyword
is declared using an operation with no identifier, then the
operation’s return type and
argument list can be omitted.
stringifier;
The following two interfaces are equivalent:
interface A {
stringifier DOMString ();
};
interface A {
stringifier;
};
The stringifier
keyword
can also be placed on an attribute.
In this case, the string to convert the object to is the
value of the attribute. The stringifier
keyword
MUST NOT be placed on an attribute unless
it is declared to be of type DOMString.
stringifier attribute DOMString identifier;
The following IDL fragment defines an interface that will stringify to the value of its name attribute:
[Constructor]
interface Student {
attribute unsigned long id;
stringifier attribute DOMString name;
};
In the ECMAScript binding, using a Student object in a context where a string is expected will result in the value of the object’s “name” property being used:
var s = new Student();
s.id = 12345678;
s.name = '周杰倫';
var greeting = 'Hello, ' + s + '!'; // Now greeting == 'Hello, 周杰倫!'.
The following IDL fragment defines an interface that has custom stringification behavior that is not specified in the IDL itself.
[Constructor]
interface Student {
attribute unsigned long id;
attribute DOMString? familyName;
attribute DOMString givenName;
stringifier DOMString ();
};
Thus, prose is required to explain the stringification behavior, such as the following paragraph:
Objects that implement the Student interface must stringify as follows. If the value of the familyName attribute is null, the stringification of the object is the value of the givenName attribute. Otherwise, if the value of the familyName attribute is not null, the stringification of the object is the concatenation of the value of the givenName attribute, a single space character, and the value of the familyName attribute.
An ECMAScript implementation of the IDL would behave as follows:
var s = new Student();
s.id = 12345679;
s.familyName = 'Smithee';
s.givenName = 'Alan';
var greeting = 'Hi ' + s; // Now greeting == 'Hi Alan Smithee'.
An interface that defines an indexed property getter, indexed property setter, indexed property creator and/or an indexed property deleter is said to support indexed properties.
If an interface supports indexed properties, then the interface definition MUST be accompanied by a description of what indices the object can be indexed with at any given time. These indices are called the supported property indices.
Indexed property getters and deleters MUST be declared to take a single unsigned long argument. Indexed property setters and creators MUST be declared to take two arguments, where the first is an unsigned long.
getter type identifier(unsigned long identifier); setter type identifier(unsigned long identifier, type identifier); creator type identifier(unsigned long identifier, type identifier); deleter type identifier(unsigned long identifier); getter type (unsigned long identifier); setter type (unsigned long identifier, type identifier); creator type (unsigned long identifier, type identifier); deleter type (unsigned long identifier);
The following requirements apply to the definitions of indexed property getters, setters, creators and deleters:
Note that if an indexed property getter, setter or deleter is specified using an operation with an identifier, then indexing an object with an integer that is not a supported property index does not necessarily elicit the same behavior as invoking the operation with that index. The actual behavior in this case is language binding specific.
In the ECMAScript langauge binding, a regular property lookup is done. For example, take the following IDL:
interface A {
getter DOMString toWord(unsigned long index);
};
Assume that an object implementing A has supported property indices in the range 0 ≤ index < 2. Also assume that toWord is defined to return its argument converted into an English word. The behavior when invoking the operation with an out of range index is different from indexing the object directly:
var a = getA();
a.toWord(0); // Evalutes to "zero".
a[0]; // Also evaluates to "zero".
a.toWord(5); // Evaluates to "five".
a[5]; // Evaluates to undefined, since there is no property "5".
The following IDL fragment defines an interface OrderedMap which allows retrieving and setting values by name or by index number:
interface OrderedMap {
readonly attribute unsigned long size;
getter any getByIndex(unsigned long index);
setter void setByIndex(unsigned long index, any value);
deleter void removeByIndex(unsigned long index);
getter any get(DOMString name);
setter creator void set(DOMString name, any value);
deleter void remove(DOMString name);
};
Since all of the special operations are declared using
operations with identifiers, the only additional prose
that is necessary is that which describes what keys those sets
have. Assuming that the get()
operation is
defined to return null if an
attempt is made to look up a non-existing entry in the
OrderedMap, then the following
two sentences would suffice:
An object map implementing OrderedMap supports indexed properties with indices in the range 0 ≤ index <
map.size
.Such objects also support a named property for every name that, if passed to
get()
, would return a non-null value.
As described in section 4.6, an ECMAScript implementation would create properties on a platform object implementing OrderedMap that correspond to entries in both the named and indexed property sets. These properties can then be used to interact with the object in the same way as invoking the object’s methods, as demonstrated below:
// Assume map is a platform object implementing the OrderedMap interface.
var map = getOrderedMap();
var x, y;
x = map[0]; // If map.length > 0, then this is equivalent to:
//
// x = map.getByIndex(0)
//
// since a property named "0" will have been placed on map.
// Otherwise, x will be set to undefined, since there will be
// no property named "0" on map.
map[1] = false; // If map.length > 1, then this will set the property named
// "1" on map to false, and then will do the equivalent of:
//
// map.setByIndex(1, false)
//
// Otherwise, if map.length ≤ 1, then it will set the
// property but have no other effect (since an indexed property creator
// was not specified).
y = map.apple; // If there exists a named property named "apple", then this
// will be equivalent to:
//
// y = map.get('apple')
//
// since a property named "apple" will have been placed on
// map. Otherwise, y will be set to undefined, since there
// will be no property named "apple" on map.
map.berry = 123; // Regardless of whether there exists a named property named
// "berry", this will set the "berry" property to 123, and
// then do the equivalent of:
//
// map.set('berry', 123)
delete map.cake; // If a named property named "cake" exists, then the "cake"
// property will be deleted, and then the equivalent to the
// following will be performed:
//
// map.remove("cake")
An interface that defines a named property getter, named property setter, named property creator and/or a named property deleter is said to support named properties.
If an interface supports named properties, then the interface definition MUST be accompanied by a description of the ordered set of names that can be used to index the object at any given time. These names are called the supported property names.
Named property getters and deleters MUST be declared to take a single DOMString argument. Named property setters and creators MUST be declared to take two arguments, where the first is a DOMString.
getter type identifier(DOMString identifier); setter type identifier(DOMString identifier, type identifier); creator type identifier(DOMString identifier, type identifier); deleter type identifier(DOMString identifier); getter type (DOMString identifier); setter type (DOMString identifier, type identifier); creator type (DOMString identifier, type identifier); deleter type (DOMString identifier);
The following requirements apply to the definitions of named property getters, setters, creators and deleters:
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.
A static operation is one that is
not called on a particular instance of the interface
on which it is declared, and is instead associated with the interface
itself. Static operations are declared by using the
static
keyword in an operation
declaration.
It is language binding specific whether it is possible to invoke a static operation through a reference to an instance of the interface.
Static operations MUST NOT be declared on callback interfaces.
The following IDL fragment defines an interface Circle that has a static operation declared on it:
interface Point { /* ... */ };
interface Circle {
attribute float cx;
attribute float cy;
attribute float radius;
static Point triangulate(Circle c1, Circle c2, Circle c3);
};
In the ECMAScript language binding, the Function object for
triangulate
will exist on the interface object
for Circle:
var circles = getCircles(); // an Array of Circle objects
typeof Circle.triangulate; // Evaluates to "function"
Circle.prototype.triangulate; // Evaluates to undefined
circles[0].triangulate; // Also evaluates to undefined
// Call the static operation
var triangulationPoint = Circle.triangulate(circles[0], circles[1], circles[2]);
If a regular operation or static operation defined on an interface has an identifier that is the same as the identifier of another operation on that interface of the same kind (regular or static), then the operation is said to be overloaded. When the identifier of an overloaded operation is used to invoke one of the operations on an object that implements the interface, the number and types of the arguments passed to the operation determine which of the overloaded operations is actually invoked. If an interface has multiple legacy callers defined on it, then those legacy callers are also said to be overloaded. In the ECMAScript language binding, constructors can be overloaded too. There are some restrictions on the arguments that overloaded operations, legacy callers and constructors can be specified to take, and in order to describe these restrictions, the notion of an effective overload set is used.
Operations and legacy callers MUST NOT be overloaded across interface and partial interface definitions.
For example, the overloads for both f and g are disallowed:
interface A {
void f();
};
partial interface A {
void f(float x);
void g();
};
partial interface A {
void g(DOMString x);
};
Note that the [Constructor] and [NamedConstructor] extended attributes are disallowed from appearing on partial interface definitions, so there is no need to also disallow overloading for constructors.
An effective overload set represents the allowable invocations for a particular operation, constructor (specified with [Constructor] or [NamedConstructor]), legacy caller or callback function. The algorithm to compute an effective overload set operates on one of the following six types of IDL constructs, and listed with them below are the inputs to the algorithm needed to compute the set.
An effective overload set is used, among other things, to determine whether there are ambiguities in the overloaded operations, constructors and callers specified on an interface.
The elements of an effective overload set are pairs of the form <callable, type list>. If the effective overload set is for regular operations, static operations or legacy callers, then callable is an operation; if it is for constructors or named constructors, then callable is an extended attribute; and if it is for callback functions, then callable is the callback function itself. In all cases, type list is a list of IDL types. Each pair represents an allowable invocation of the operation, constructor, legacy caller or callback function with an argument value list of the given types. Due to the use of optional arguments and variadic operations and constructors, there may be multiple entries in an effective overload set identifying the same operation or constructor.
The algorithm below describes how to compute an effective overload set. The following input variables are used, if they are required:
Whenever an argument of an extended attribute is mentioned, it is referring to an argument of the extended attribute’s named argument list.
So void f(long x, long... y);
is considered to be declared to take two arguments.
For the following interface:
interface A {
/* f1 */ void f(DOMString a);
/* f2 */ void f(Node a, DOMString b, float... c);
/* f3 */ void f();
/* f4 */ void f(Event a, DOMString b, optional DOMString c, float... d);
};
assuming Node and Event
are two other interfaces of which no object can implement both,
the effective overload set
for regular operations with
identifier f
and argument count 4 is:
Two types are distinguishable if at most one of the two is a nullable type and at least one of the following three conditions is true:
The two types (taking their inner types if they are nullable types) appear in the following table and there is a “●” mark in the corresponding entry or there is a letter in the corresponding entry and the designated additional requirement below the table is satisfied:
primitive | DOMString | enumeration | interface | object | callback function |
dictionary | sequence<T> | T[] | Date | |
---|---|---|---|---|---|---|---|---|---|---|
primitive | ● | ● | ● | ● | ● | ● | ● | |||
DOMString | ● | ● | ● | ● | ● | ● | ● | |||
enumeration | ● | ● | ● | ● | ● | ● | ● | |||
interface | (a) | (b) | (b) | (b) | (b) | ● | ||||
object | ||||||||||
callback function | ● | |||||||||
dictionary | ● | ● | ● | |||||||
sequence<T> | ● | |||||||||
T[] | ● | |||||||||
Date |
If there is more than one entry in an effective overload set that has a given type list length, then for those entries there MUST be an index i such that for each pair of entries the types at index i are distinguishable. The lowest such index is termed the distinguishing argument index for the entries of the effective overload set with the given type list length.
Consider the effective overload set shown in the previous example. There are multiple entries in the set with type lists 2, 3 and 4. For each of these type list lengths, the distinguishing argument index is 0, since Node and Event are distinguishable.
The following use of overloading however is invalid:
interface B {
void f(DOMString x);
void f(float x);
};
In addition, for each index j, where j is less than the distinguishing argument index for a given type list length, the types at index j in all of the entries’ type lists MUST be the same.
The following is invalid:
interface B {
/* f1 */ void f(DOMString w);
/* f2 */ void f(long w, float x, Node y, Node z);
/* f3 */ void f(float w, float x, DOMString y, Node z);
};
For argument count 4, the effective overload set is:
Looking at entries with type list length 4, the distinguishing argument index is 2, since Node and DOMString are distinguishable. However, since the arguments in these two overloads at index 0 are different, the overloading is invalid.
A dictionary is a definition (matching Dictionary) used to define an associative array data type with a fixed, ordered set of key–value pairs, termed dictionary members, where keys are strings and values are of a particular type specified in the definition.
dictionary identifier { dictionary-members… };
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, an interface A cannot inherit from itself, nor can it inherit from another interface B that inherits from A, and so on.
dictionary Base { dictionary-members… }; dictionary Derived : Base { dictionary-members… };
The inherited dictionaries of a given dictionary D is the set of all dictionaries that D inherits from, directly or indirectly. If D does not inherit from another dictionary, then the set is empty. Otherwise, the set includes the dictionary E that D inherits from and all of E’s inherited dictionaries.
A dictionary value of type D can have key–value pairs corresponding to the dictionary members defined on D and on any of D’s inherited dictionaries. On a given dictionary value, the presence of each dictionary member is optional. When specified in the dictionary value, a dictionary member is said to be present, otherwise it is not present. Dictionary members can also optionally have a default value, which is the value the dictionary member is to be considered to have when not present.
Each dictionary member (matching
DictionaryMember) is specified
as a type (matching Type) followed by an
identifier
(given by an identifier token following
the type). The identifier is the key name of the key–value pair.
If the Type
is an identifier or an
identifier followed by ?
, then the identifier
MUST identify an
interface, dictionary, enumeration,
callback function or typedef.
dictionary identifier { type identifier; };
If the identifier is followed by a U+003D EQUALS SIGN ("=") and a value (matching DefaultValue), then that gives the dictionary member its default value.
dictionary identifier { type identifier = value; };
When a boolean literal token (true
or false
),
the null
token,
an integer token, a
float token,
one of the three special floating point literal values (Infinity
,
-Infinity
or NaN
) or
a string token 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.
As with interfaces, the IDL for dictionaries can be split into multiple parts by using partial dictionary definitions (matching "partial" Dictionary). The identifier of a partial dictionary definition MUST be the same as the identifier of a dictionary definition. All of the members that appear on each of the partial dictionary definitions are considered to be members of the dictionary itself.
dictionary SomeDictionary { dictionary-members… }; partial dictionary SomeDictionary { dictionary-members… };
As with partial interface definitions, partial dictionary definitions are intended for use as a specification editorial aide, allowing the definition of an interface to be separated over more than one section of the document, and sometimes multiple documents.
The order of the dictionary members on a given dictionary is such that inherited dictionary members are ordered before non-inherited members, and the dictionary members on the one dictionary definition (including any partial dictionary definitions) are ordered lexicographically by the Unicode codepoints that comprise their identifiers.
For example, with the following definitions:
dictionary B : A {
long b;
long a;
};
dictionary A {
long c;
long g;
};
dictionary C : B {
long e;
long f;
};
partial dictionary A {
long h;
long d;
};
the order of the dictionary members of a dictionary value of type C is c, d, g, h, a, b, e, f.
Dictionaries are required to have their members ordered because in some language bindings the behavior observed when passing a dictionary value to a platform object depends on the order the dictionary members are fetched. For example, consider the following additional interface:
interface Something {
void f(A a);
};
and this ECMAScript code:
var something = getSomething(); // Get an instance of Something.
var x = 0;
var dict = { };
Object.defineProperty(dict, "d", { get: function() { return ++x; } });
Object.defineProperty(dict, "c", { get: function() { return ++x; } });
something.f(dict);
The order that the dictionary members are fetched in determines what values they will be taken to have. Since the order for A is defined to be c then d, the value for c will be 1 and the value for d will be 2.
The identifier of a dictionary member MUST NOT be the same as that of another dictionary member defined on the dictionary or on that dictionary’s inherited dictionaries.
Dictionaries MUST NOT be used as the type of an attribute, constant or exception field.
No extended attributes defined in this specification are applicable to dictionaries.
The following extended attributes are applicable to dictionary members: [Clamp], [EnforceRange].
[6] | Partial | → | "partial" PartialDefinition |
[7] | PartialDefinition | → | PartialInterface | PartialDictionary |
[11] | Dictionary | → | "dictionary" identifier Inheritance "{" DictionaryMembers "}" ";" |
[12] | DictionaryMembers | → | ExtendedAttributeList DictionaryMember DictionaryMembers | ε |
[13] | DictionaryMember | → | Type identifier Default ";" |
[14] | PartialDictionary | → | "dictionary" identifier "{" DictionaryMembers "}" ";" |
[15] | Default | → | "=" DefaultValue | ε |
[16] | DefaultValue | → | ConstValue | string |
[19] | 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:
[Constructor]
interface Point {
attribute float x;
attribute float y;
};
dictionary PaintOptions {
DOMString? fillPattern = "black";
DOMString? strokePattern = null;
Point position;
};
interface GraphicsContext {
void drawRectangle(float width, float height, optional PaintOptions options);
};
In an ECMAScript implementation of the IDL, an Object can be passed in for the optional PaintOptions dictionary:
// Get an instance of GraphicsContext.
var ctx = getGraphicsContext();
// Draw a rectangle.
ctx.drawRectangle(300, 200, { fillPattern: "red", position: new Point(10, 10) });
Both fillPattern and strokePattern are given default values, so if they are omitted, the definition of drawRectangle can assume that they have the given default values and not include explicit wording to handle their non-presence.
An exception is a definition (matching Exception) used to declare a class of exceptions that can be thrown by implementations.
exception identifier { exception-members… };
Exceptions are different from interfaces in that they can have only constants and exception fields declared on them (together known as exception members), rather than the three types of interface members.
An exception can be defined to inherit from another exception. If the identifier of the exception is followed by a U+003A COLON (":") character and a identifier, then that identifier identifies the inherited exception. The identifier MUST identify an exception.
An exception MUST NOT be declared such that its inheritance hierarchy has a cycle. That is, an interface A cannot inherit from itself, nor can it inherit from another interface B that inherits from A, and so on.
An object that implements an exception that inherits from another also implements that inherited exception. The object therefore will also have members that correspond to the exception members from the inherited exception.
exception Base { exception-members… }; exception Derived : Base { exception-members… };
Exceptions have an associated message, a DOMString, which is exposed on an exception object in a language binding-specific manner.
Exceptions also have an associated type, also a DOMString, which is exposed on an exception object in a language binding-specific manner. The type of an exception is intended to be used to distinguish between the different kinds of exceptions that can be represented by the given IDL exception.
Each exception field (matching
ExceptionField) is specified
as a type (matching Type) followed by an
identifier
(given by an identifier token following
the type). If the Type
is an identifier or
an identifier followed by ?
, then the identifier
MUST identify an
interface, enumeration,
callback function or typedef.
The type of the exception field MUST NOT be a
sequence type or
nullable sequence type,
and it it MUST NOT be a
union type if
one of its member types
(or one of its member types’s member types, and so on)
is a sequence type or
nullable
sequence type.
Exception fields are similar to attributes in that they will correspond to attributes of the same name and type on exception objects that are thrown by implementations.
exception identifier { type identifier; };
The identifier of an exception field MUST NOT be the same as that of another exception member, and it MUST NOT be “name” or “message”.
Each exception member can be preceded by a list of extended attributes (matching ExtendedAttributeList), which can control how the exception member will be handled in language bindings.
exception identifier { [extended-attributes] const type identifier = value; [extended-attributes] type identifier; };
A number of predefined exceptions are also available to be thrown from specifications. These predefined exceptions correspond to the ECMAScript error objects ([ECMA-262], section 15.11). Specifically, the list of predefined exceptions is as follows: Error, EvalError, RangeError, ReferenceError, SyntaxError, TypeError and URIError. The meaning of each of these exceptions matches those of the corresponding Error object in the ECMAScript specification. These exceptions are not considered to have any exception members.
The identifier of an exception MUST NOT be the same as one of the predefined exceptions.
Exceptions can be thrown, optionally with a specific message and type, the behavior of which again is language binding-specific. If a type is not specified, it is assumed to be the same as the identifier of the exception.
See section 4.11 below for details on what throwing an exception entails in the ECMAScript language binding.
Authors of future Web platform specifications SHOULD NOT mint new IDL exceptions but instead should use DOMException and distinguish different kinds of exceptions by their type and not by an integer code. The type will be exposed in ECMAScript using a “name” property on the exception object. One valid reason to mint new IDL exceptions is if additional exception fields are required. If a predefined exception matches the meaning of the exception to be thrown, it SHOULD be used in preference to minting an exception type.
If new exception types are to be minted, their names SHOULD use the same naming scheme as the built-in ECMAScript error objects; for example, “HierarchyRequestError” or “NotFoundError”, if types are being given to the DOM Core exceptions. Any new IDL exceptions SHOULD be named similarly.
There is no IDL syntax for declaring exception types. In prose, an exception of a particular type can be thrown by using wording like the following:
Throw a DOMException of type HierarchyRequestError with message “Cannot append that Node here”.
The following extended attribute is applicable to exceptions: [NoInterfaceObject].
No extended attributes defined in this specification are applicable to exception fields.
[17] | Exception | → | "exception" identifier Inheritance "{" ExceptionMembers "}" ";" |
[18] | ExceptionMembers | → | ExtendedAttributeList ExceptionMember ExceptionMembers | ε |
[19] | Inheritance | → | ":" identifier | ε |
[47] | ExceptionMember | → | Const | ExceptionField |
[48] | ExceptionField | → | Type identifier ";" |
The following example demonstrates how a reduced version of DOM Core’s DOMException might be defined for three of the existing exception types and one new type. Exception types have historically been distinguished only by an integer code. The new exception type here is not.
exception DOMException {
const unsigned short INDEX_SIZE_ERR = 1;
const unsigned short DOMSTRING_SIZE_ERR = 2;
const unsigned short HIERARCHY_REQUEST_ERR = 3;
unsigned short code;
};
Assume that the specification defines that throwing a DOMException of a particular type uses a corresponding value for the code field, as follows:
Type | Value of code |
---|---|
IndexSizeError | INDEX_SIZE_ERR |
DOMStringSizeError | DOMSTRING_SIZE_ERR |
HierarchyRequestError | HIERARCHY_REQUEST_ERR |
InsufficientBlingError | 0 |
In an ECMAScript implementation, the types of DOMExceptions could be distinguished by code, and the existing ones and the new ones could be distinguished by type:
try {
document.appendChild(document);
} catch (e) {
// The traditional way, by looking at the code.
if (e.code == DOMException.HIERARCHY_REQUEST_ERR) {
...
}
// By looking at the name.
if (e.name == "HierarchyRequestError") {
...
}
if (e.name == "InsufficientBlingError") {
e.code; // This would evaluate to 0.
...
}
}
Note that using e instanceof ExceptionClass
can return false
if the exception object comes from a
different document than the global scope of the running script, even if
the exception is an instance of the ExceptionClass in
its own document. For this reason, authors are suggested not to use
instanceof
to perform exception type testing.
An enumeration is a definition (matching Enum) used to declare a type whose valid values are a set of predefined strings. Enumerations can be used to restrict the possible DOMString values that can be assigned to an attribute or passed to an operation.
enum identifier { enumeration-values… };
The enumeration values are specified as a comma-separated list of string literals. The list of enumeration values MUST NOT include duplicates.
The behavior when a string value that is not one a valid enumeration value is used when assigning to an attribute, or passed as an operation argument, whose type is the enumeration, is language binding specific.
In the ECMAScript binding, assignment of an invalid string value to an attribute is ignored, while passing such a value as an operation argument results in an exception being thrown.
No extended attributes defined in this specification are applicable to enumerations.
[20] | Enum | → | "enum" identifier "{" EnumValueList "}" ";" |
[21] | EnumValueList | → | string EnumValues |
[22] | EnumValues | → | "," string EnumValues | ε |
The following IDL fragment defines an enumeration that is used as the type of an attribute and an operation argument:
enum MealType { "rice", "noodles", "other" };
interface Meal {
attribute MealType type;
attribute float size; // in grams
void initialize(MealType type, float size);
};
An ECMAScript implementation would restrict the strings that can be assigned to the type property or passed to the initializeMeal function to those identified in the enumeration.
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.
A callback function is a definition (matching "callback" CallbackRest) used to declare a function type.
callback identifier = return-type (arguments…);
See also the similarly named callback interfaces.
The identifier on the left of the equals sign gives the name of the callback function and the return type and argument list (matching ReturnType and ArgumentList) on the right side of the equals sign gives the signature of the callback function type.
Callback functions MUST NOT be used as the type of a constant.
The following extended attribute is applicable to callback functions: [TreatNonCallableAsNull].
[3] | CallbackOrInterface | → | "callback" CallbackRestOrInterface | Interface |
[4] | CallbackRestOrInterface | → | CallbackRest | Interface |
[23] | CallbackRest | → | identifier = ReturnType "(" ArgumentList ")" ";" |
The following IDL fragment defines a callback function used for an API that invokes a user-defined function when an operation is complete.
callback AsyncOperationCallback = void (DOMString status);
interface AsyncOperations {
void performOperation(AsyncOperationCallback whenFinished);
};
In the ECMAScript language binding, a 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 + ".");
});
A typedef is a definition (matching Typedef) used to declare a new name for a type. This new name is not exposed by language bindings; it is purely used as a shorthand for referencing the type in the IDL.
typedef type identifier;
The type being given a new name is specified after the typedef
keyword (matching Type), and the
identifier token following the
type gives the name.
The Type MUST NOT identify the same or another typedef.
Extended attributes can be
given directly after the typedef
keyword, and any such
extended attributes will be taken to apply to constructs that
use the typedef.
typedef [extended-attributes] type identifier;
A typedef MUST NOT
be used as the type of a construct if an extended attribute
that appears after the typedef
keyword would be disallowed from appearing
directly on that construct.
That means you can write:
typedef [Clamp] octet Value;
interface A {
void setColor(Value r, Value g, Value b);
};
as a shorthand for:
interface A {
void setColor([Clamp] octet r, [Clamp] octet g, [Clamp] octet b);
};
but it would be invalid to write either of the following two operations:
interface A {
Value getRedComponent();
void setRedComponent([EnforceRange] Value r);
};
since [Clamp] cannot be used on an operation return value and it also cannot be used in conjunction with [EnforceRange].
Any extended attributes that apply to a construct due to their appearing on a referenced typedef are considered to appear after those that are specified explicitly on the construct, although note that none of the extended attributes defined in this specification that can validly be used in a typedef are sensitive to order.
No extended attributes defined in this specification are applicable to typedefs themselves.
[24] | Typedef | → | "typedef" ExtendedAttributeList Type identifier ";" |
The following IDL fragment demonstrates the use of typedefs to allow the use of a short identifier instead of a long sequence type.
interface Point {
attribute float x;
attribute float y;
};
typedef sequence<Point> Points;
interface Widget {
boolean pointWithinBounds(Point p);
boolean allPointsWithinBounds(Points ps);
};
An implements statement is a definition (matching ImplementsStatement) used to declare that all objects implementing an interface A (identified by the first identifier) MUST additionally implement interface B (identified by the second identifier), including all other interfaces that B inherits from.
identifier-A implements identifier-B;
Transitively, if objects implementing B are declared with an implements statement to additionally implement interface C, then all objects implementing A do additionally implement interface C.
The two identifiers MUST identify two different interfaces.
The interface identified on the left-hand side of an implements statement MUST NOT inherit from the interface identifier on the right-hand side, and vice versa.
If each implements statement is considered to be an edge in a directed graph, from a node representing the interface on the left-hand side of the statement to a node representing the interface on the right-hand side, then this graph MUST NOT have any cycles.
Interfaces that a given object implements are partitioned into those that are considered supplemental interfaces and those that are not. An interface A is considered to be a supplemental interface of an object O if:
B implements A
; orSpecification authors are discouraged from writing implements statements where the interface on the left-hand side is a supplemental interface. For example, if author 1 writes:
interface Window { ... };
interface SomeFunctionality { ... };
Window implements SomeFunctionality;
and author 2 later writes:
interface Gizmo { ... };
interface MoreFunctionality { ... };
SomeFunctionality implements MoreFunctionality;
Gizmo implements SomeFunctionality;
then it might be the case that author 2 is unaware of exactly which
interfaces already are used on the left-hand side of an
implements SomeFunctionality
statement, and so has
required more object implement MoreFunctionality
than he or she expected.
Better in this case would be for author 2 to write:
interface Gizmo { ... };
interface MoreFunctionality { ... };
Gizmo implements SomeFunctionality;
Gizmo implements MoreFunctionality;
The consequential interfaces of an interface A are:
A implements B
;C implements D
,
where C is a consequential interface of A.For a given interface, there MUST NOT be any member defined on any of its consequential interfaces whose identifier is the same as any other member defined on any of those consequential interfaces or on the original interface itself.
For example, that precludes the following:
interface A { attribute long x; };
interface B { attribute long x; };
A implements B; // B::x would clash with A::x
interface C { attribute long y; };
interface D { attribute long y; };
interface E : D { };
C implements E; // D::y would clash with C::y
interface F { };
interface H { attribute long z; };
interface I { attribute long z; };
F implements H;
F implements I; // H::z and I::z would clash when mixed in to F
No extended attributes defined in this specification are applicable to implements statements.
[25] | ImplementsStatement | → | identifier "implements" identifier ";" |
The following IDL fragment defines two interfaces, stating that one interface is always implemented on objects implementing the other.
interface Entry {
readonly attribute unsigned short entryType;
// ...
};
interface Observable {
void addEventListener(DOMString type,
EventListener listener,
boolean useCapture);
// ...
};
Entry implements Observable;
An ECMAScript implementation would thus have an “addEventListener” property in the prototype chain of every Entry:
var e = getEntry(); // Obtain an instance of Entry.
typeof e.addEventListener; // Evaluates to "function".
Note that it is not the case that all Observable objects implement Entry.
In a given implementation of a set of IDL fragments, an object can be described as being a platform object, a user object, or neither. There are three kinds of object that are considered to be platform objects:
In a browser, for example, the browser-implemented DOM objects (implementing interfaces such as Node and Document) that provide access to a web page’s contents to ECMAScript running in the page would be platform objects. These objects might be host objects, implemented in a language like C++, or they might be native ECMAScript objects. Regardless, an implementation of a given set of IDL fragments needs to be able to recognize all platform objects that are created by the implementation. This might be done by having some internal state that records whether a given object is indeed a platform object for that implementation, or perhaps by observing that the object is implemented by a given internal C++ class. How exactly platform objects are recognised by a given implementation of a set of IDL fragments is implementation specific.
All other objects in the system would not be treated as platform objects. For example, assume that a web page opened in a browser loads an ECMAScript library that implements DOM Core. This library would be considered to be a different implementation from the browser provided implementation. The objects created by the ECMAScript library that implement the Node interface will not be treated as platform objects that implement Node by the browser implementation.
User objects are those that authors would create, implementing callback interfaces that the Web APIs use to be able to invoke author-defined operations or to send and receive values to the author’s program through manipulating the object’s attributes. In a web page, an ECMAScript object that implements the EventListener interface, which is used to register a callback that the DOM Events implementation invokes, would be considered to be a user object.
Note that user objects can only implement callback interfaces and platform objects can only implement non-callback interfaces.
This section lists the types supported by Web IDL, the set of values corresponding to each type, and how constants of that type are represented.
The following types are known as integer types: byte, octet, short, unsigned short, long, unsigned long, long long and unsigned long long.
The following types are known as primitive types: boolean, the integer types, float, unresticted float, double and unrestricted double.
The object type and all interface types are known as object types.
Every type has a type name, which is a string, not necessarily unique, that identifies the type. Each sub-section below defines what the type name is for each type.
When conversions are made from language binding specific types to IDL types in order to invoke an operation or assign a value to an attribute, all conversions necessary will be performed before the specified functionality of the operation or attribute assignment is carried out. If the conversion cannot be performed, then the operation will not run or the attribute will not be updated. In some language bindings, type conversions could result in an exception being thrown. In such cases, these exceptions will be propagated to the code that made the attempt to invoke the operation or assign to the attribute.
[57] | Type | → | SingleType | UnionType TypeSuffix |
[58] | SingleType | → | NonAnyType | "any" TypeSuffixStartingWithArray |
[59] | UnionType | → | "(" UnionMemberType "or" UnionMemberType UnionMemberTypes ")" |
[60] | UnionMemberType | → | NonAnyType | UnionType TypeSuffix | "any" "[" "]" TypeSuffix |
[61] | UnionMemberTypes | → | "or" UnionMemberType UnionMemberTypes | ε |
[62] | NonAnyType | → | PrimitiveType TypeSuffix | "DOMString" TypeSuffix | identifier TypeSuffix | "sequence" "<" Type ">" Null | "object" TypeSuffix | "Date" TypeSuffix |
[63] | ConstType | → | PrimitiveType Null | identifier Null |
[64] | PrimitiveType | → | UnsignedIntegerType | UnrestrictedFloatType | "boolean" | "byte" | "octet" |
[65] | UnrestrictedFloatType | → | "unrestricted" FloatType | FloatType |
[66] | FloatType | → | "float" | "double" |
[67] | UnsignedIntegerType | → | "unsigned" IntegerType | IntegerType |
[68] | IntegerType | → | "short" | "long" OptionalLong |
[69] | OptionalLong | → | "long" | ε |
[70] | TypeSuffix | → | "[" "]" TypeSuffix | "?" TypeSuffixStartingWithArray | ε |
[71] | TypeSuffixStartingWithArray | → | "[" "]" TypeSuffix | ε |
[72] | Null | → | "?" | ε |
The any type is the union of all other possible non-union types. Its type name is “Any”.
The any type is like a discriminated union type, in that each of its values has a specific non-any type associated with it. For example, one value of the any type is the unsigned long 150, while another is the long 150. These are distinct values.
The particular type of an any value is known as its specific type. (Values of union types also have specific types.)
The boolean type has two values: true and false.
boolean constant values in IDL are
represented with the true
and
false
tokens.
The byte type is a signed integer type that has values in the range [−128, 127].
byte constant values in IDL are represented with integer tokens.
The octet type is an unsigned integer type that has values in the range [0, 255].
octet constant values in IDL are represented with integer tokens.
The short type is a signed integer type that has values in the range [−32768, 32767].
short constant values in IDL are represented with integer tokens.
The unsigned short type is an unsigned integer type that has values in the range [0, 65535].
unsigned short constant values in IDL are represented with integer tokens.
The type name of the unsigned short type is “UnsignedShort”.
The long type is a signed integer type that has values in the range [−2147483648, 2147483647].
long constant values in IDL are represented with integer tokens.
The unsigned long type is an unsigned integer type that has values in the range [0, 4294967295].
unsigned long constant values in IDL are represented with integer tokens.
The type name of the unsigned long type is “UnsignedLong”.
The long long type is a signed integer type that has values in the range [−9223372036854775808, 9223372036854775807].
long long constant values in IDL are represented with integer tokens.
The unsigned long long type is an unsigned integer type that has values in the range [0, 18446744073709551615].
unsigned long long constant values in IDL are represented with integer tokens.
The type name of the unsigned long long type is “UnsignedLongLong”.
The float type is a floating point numeric type that corresponds to the set of finite single-precision 32 bit IEEE 754 floating point numbers. [IEEE-754]
float constant values in IDL are represented with float tokens.
The unrestricted float type is a floating point numeric type that corresponds to the set of all possible single-precision 32 bit IEEE 754 floating point numbers, finite and non-finite. [IEEE-754]
unrestricted float constant values in IDL are represented with float tokens.
The type name of the unrestricted float type is “UnrestrictedFloat”.
The double type is a floating point numeric type that corresponds to the set of finite double-precision 64 bit IEEE 754 floating point numbers. [IEEE-754]
double constant values in IDL are represented with float tokens.
The unrestricted double type is a floating point numeric type that corresponds to the set of all possible double-precision 32 bit IEEE 754 floating point numbers, finite and non-finite. [IEEE-754]
unrestricted double constant values in IDL are represented with float tokens.
The type name of the unrestricted double type is “UnrestrictedDouble”.
The DOMString type corresponds to the set of all possible sequences of code units. Such sequences are commonly interpreted as UTF-16 encoded strings [RFC2781] although this is not required. While DOMString is defined to be an OMG IDL boxed sequence<unsigned short> valuetype in DOM Level 3 Core ([DOM3CORE], section 1.2.1), this document defines DOMString to be an intrinsic type so as to avoid special casing that sequence type in various situations where a string is required.
Note also that null
is not a value of type DOMString.
To allow null, a
nullable DOMString,
written as DOMString?
in IDL, needs to be used.
Nothing in this specification requires a DOMString value to be a valid UTF-16 string. For example, a DOMString value might include unmatched surrogate pair characters. However, authors of specifications using Web IDL might want to obtain a sequence of Unicode characters given a particular sequence of code units. The following algorithm defines a way to convert a DOMString to a sequence of Unicode characters:
There is no way to represent a constant DOMString value in IDL, although DOMString dictionary member and operation optional argument default values an be specified using a string literal.
The object type corresponds to the set of all possible non-null object references.
There is no way to represent a constant object value in IDL.
To denote a type that includes all possible object references plus the null value, use the nullable type object?.
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.
There is no way to represent a constant object reference value for a particular interface type in IDL.
To denote a type that includes all possible references to objects implementing the given interface plus the null value, use a nullable type.
The type name of an interface type is the identifier of the interface.
An identifier that identifies a dictionary is used to refer to a type that corresponds to the set of all dictionaries that adhere to the dictionary definition.
There is no way to represent a constant dictionary value in IDL.
The type name of a dictionary type is the identifier of the dictionary.
An identifier that identifies an enumeration is used to refer to a type whose values are the set of strings (sequences of code units, as with DOMString) that are the enumeration’s values.
Like DOMString, there is no way to represent a constant enumeration value in IDL, although enumeration-typed dictionary member default values can be specified using a string literal.
The type name of an enumeration type is the identifier of the enumeration.
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.
There is no way to represent a constant callback function value in IDL.
The type name of a callback function type is the identifier of the callback function.
A nullable type is an IDL type constructed from an existing type (called the inner type), which just allows the additional value null to be a member of its set of values. Nullable types are represented in IDL by placing a U+003F QUESTION MARK ("?") character after an existing type. The inner type MUST NOT be any or another nullable type or a union type that itself has a nullable type as a member type, as they already allow the null value.
Nullable type constant values in IDL are represented in the same way that
constant values of their inner type
would be represented, or with the null
token.
The type name of a nullable type is the concatenation of the type name of the inner type T and the string “OrNull”.
For example, a type that allows the values true, false and null is written as boolean?:
interface MyConstants {
const boolean? ARE_WE_THERE_YET = false;
};
The following interface has two attributes: one whose value can be a DOMString or the null value, and another whose value can be a reference to a Node object or the null value:
interface Node {
readonly attribute DOMString? namespaceURI;
readonly attribute Node? parentNode;
// ...
};
The sequence<T> type is a parameterized type whose values are (possibly zero-length) sequences of values of type T. Sequences are always passed by value. In language bindings where a sequence is represented by an object of some kind, passing a sequence to a user agent implemented object will not result in a reference to the sequence being kept by that object. Similarly, any sequence returned from a user agent implemented object will be a copy and modifications made to it will not be visible to the object.
There is no way to represent a constant sequence value in IDL.
Sequences MUST NOT be used as the type of an attribute, constant or exception field.
This restriction exists so that it is clear to specification writers and API users that sequences are copied rather than having references to them passed around. Instead of a writable attribute of a sequence type, it is suggested that a pair of operations to get and set the sequence is used. Another option is to use an array type, which can be used as the type of an attribute.
The type name of a sequence type is the concatenation of the type name for T and the string “Sequence”.
The T[] type is a parameterized type. The values of this type are non-null references to arrays of values of type T. Unlike sequences, arrays are passed by reference. Passing an array to a platform object could result in that array being modified by the object. An array returned from a platform object might also be modified by the object, and any modifications to the array performed by user code might be acted upon by the platform object.
The element type of an array MUST NOT be a sequence or dictionary type.
Arrays can either be fixed length or variable length. Fixed length arrays cannot have their length changed by user code after they have been created, while variable length arrays can. Unless otherwise specified, arrays are fixed length.
Arrays can also be designated as being read only. User code cannot modify the values of read only array elements. If an array is read only, then it is also implicitly fixed length.
There is no way to represent a constant array value in IDL.
The type name of an array type is the concatenation of the type name for T and the string “Array”.
See section 4.2.24 for an example using array 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 (float or float[])
. When applying a
a []
or ?
suffix to a
union type
as a whole, it is placed after the closing parenthesis,
as in (Node or DOMString)?
.
Note that the member types
of a union type do not descend into nested union types. So for
(float or (Date or Event) or (Node or DOMString)?)
the member types
are float
, (Date or Event)
and
(Node or DOMString)?
.
Like the any type, values of union types have a specific type, which is the particular member type that matches the value.
The flattened member types of a union type is a set of types determined as follows:
For example, the flattened member types
of the union type
(Node or (Date or Event) or (XMLHttpRequest or DOMString)? or (float[] or NodeList)[])
are the six types Node
, Date
, Event
,
XMLHttpRequest
, DOMString
and
(float[] or NodeList)[]
.
The number of nullable member types of a union type is an integer determined as follows:
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. A union type includes a nullable type if its number of nullable member types is 1.
Each pair of flattened member types in a union type, T and U, MUST be distinguishable.
Union type constant values in IDL are represented in the same way that constant values of their member types would be represented.
The type name of a union type is formed by taking the type names of each member type, in order, and joining them with the string “Or”.
[59] | UnionType | → | "(" UnionMemberType "or" UnionMemberType UnionMemberTypes ")" |
[60] | UnionMemberType | → | NonAnyType | UnionType TypeSuffix | "any" "[" "]" TypeSuffix |
[61] | UnionMemberTypes | → | "or" UnionMemberType UnionMemberTypes | ε |
[62] | NonAnyType | → | PrimitiveType TypeSuffix | "DOMString" TypeSuffix | identifier TypeSuffix | "sequence" "<" Type ">" Null | "object" TypeSuffix | "Date" TypeSuffix |
The Date type is a type that represents an instant in time with millisecond accuracy. The instants in time that this type can represent are the same that can be represented with ECMAScript Date objects ([ECMA-262], section 15.9.1.1) – namely, every millisecond in the 200,000,000 days centered around midnight of 1 January, 1970 UTC, except for any millisecond that is part of an inserted leap second, because they cannot be represented by this type.
An additional value that this type can represent is one that indicates an indeterminate or undefined time, which we write as undefined.
There is no way to represent a constant Date value in IDL.
An extended attribute is an annotation that can appear on definitions, interface members, exception members, dictionary members, and operation arguments, and is used to control how language bindings will handle those constructs. Extended attributes are specified with an ExtendedAttributeList, which is a square bracket enclosed, comma separated list of ExtendedAttributes.
The ExtendedAttribute grammar symbol matches nearly any sequence of tokens, however the extended attributes defined in this document only accept a more restricted syntax. Any extended attribute encountered in an IDL fragment is matched against the following four grammar symbols to determine which form (or forms) it is in:
Grammar symbol | Form | Example |
---|---|---|
ExtendedAttributeNoArgs | takes no arguments |
[Replaceable]
|
ExtendedAttributeArgList | takes an argument list |
[Constructor(float x, float y)]
|
ExtendedAttributeNamedArgList | takes a named argument list |
[NamedConstructor=Image(DOMString src)]
|
ExtendedAttributeIdent | takes an identifier |
[PutForwards=name]
|
This specification defines a number of extended attributes that are applicable to the ECMAScript language binding, which are described in section 4.3. Each extended attribute definition will state which of the above five forms are allowed.
This section describes how definitions written with the IDL defined in section 3 correspond to particular constructs in ECMAScript, as defined by the ECMAScript Language Specification Edition 5.1 [ECMA-262].
Objects defined in this section have internal properties as described in ECMA-262 sections 8.12 and 13.2 unless otherwise specified, in which case one or more of the following are redefined in accordance with the rules for host objects: [[Call]], [[DefineOwnProperty]], [[GetOwnProperty]] and [[Delete]].
No ECMAScript objects described in this section are required to have a non-standard [[Class]] internal property value. However, to influence the result of calling Object.prototype.toString on an object, a class string is defined for some objects.
Section 4.1 below describes how Object.prototype.toString takes an object’s class string into account.
Unless otherwise specified, the [[Extensible]] internal property of objects defined in this section has the value true.
Unless otherwise specified, the [[Prototype]] internal property of objects defined in this section is the Object prototype object.
If an object is defined to be a function object, then it has characteristics as follows:
Algorithms in this section use the conventions described in ECMA-262 section 5.2, such as the use of steps and substeps, the use of mathematical operations, and so on. The ToBoolean, ToNumber, ToUint16, ToInt32, ToUint32, ToString, ToObject, IsAccessorDescriptor and IsDataDescriptor abstract operations and the Type(x) notation referenced in this section are defined in ECMA-262 sections 8 and 9.
When an algorithm says to “throw a SomethingError” then this means to construct a new ECMAScript SomethingError object and to throw it, just as the algorithms in ECMA-262 do.
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:
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.
In an ECMAScript implementation of a given set of IDL fragments, there will exist a number of ECMAScript objects that correspond to definitions in those IDL fragments. These objects are termed the initial objects, and comprise the following:
Each ECMAScript global environment ([ECMA-262], section 10.2.3) MUST have its own unique set of each of the initial objects, created before control enters any ECMAScript execution context associated with the environment, but after the global object for that environment is created. The [[Prototype]]s of all initial objects in a given global environment MUST come from that same global environment.
In an HTML user agent, multiple global environments can exist when multiple frames or windows are created. Each frame or window will have its own set of initial objects, which the following HTML document demonstrates:
<!DOCTYPE html>
<title>Different global environments</title>
<iframe id=a></iframe>
<script>
var iframe = document.getElementById("a");
var w = iframe.contentWindow; // The global object in the frame
Object == w.Object; // Evaluates to false, per ECMA-262
Node == w.Node; // Evaluates to false
iframe instanceof w.Node; // Evaluates to false
iframe instanceof w.Object; // Evaluates to false
iframe.appendChild instanceof Function; // Evaluates to true
iframe.appendChild instanceof w.Function; // Evaluates to false
</script>
Unless otherwise specified, each ECMAScript global environment exposes all interfaces and exceptions that the implementation supports. If a given ECMAScript global environment does not expose an interface or exception, then the requirements given in section 4.4 and section 4.9 are not followed for that interface or exception.
This allows, for example, ECMAScript global environments for Web Workers to expose different sets of supported interfaces from those exposed in environments for Web pages.
As soon as any ECMAScript global environment is created, the following steps MUST be performed:
"[object Undefined]"
."[object Null]"
."[object "
, class, and "]"
.Requiring particular behavior from Object.prototype.toString rather than requiring non-standard [[Class]] internal property values is done to avoid making it impossible to implement APIs described with Web IDL natively in ECMAScript with Proxies.
There is one built-in ECMAScript function that behaves differently for platform objects with this custom Object.prototype.toString behavior instead of custom [[Class]] values: Function.prototype.bind will return a new Function object with a length property with a non-zero value if the object has a legacy caller that takes at least one argument.
This section describes how types in the IDL map to types in ECMAScript.
Each sub-section below describes how values of a given IDL type are represented in ECMAScript. For each IDL type, it is described how ECMAScript values are converted to an IDL value when passed to a platform object expecting that type, and how IDL values of that type are converted to ECMAScript values when returned from a platform object.
Since the IDL any type is the union of all other IDL types, it can correspond to any ECMAScript value type.
How to convert an ECMAScript value to an IDL any value depends on the type of the ECMAScript value:
An IDL any value is converted to an ECMAScript value as follows. If the value is an object reference to a special object that represents an ECMAScript undefined value, then it is converted to the ECMAScript undefined value. Otherwise, the rules for converting the specific type of the IDL any value as described in the remainder of this section are performed.
The only place that the void type may appear in IDL is as the return type of an operation. Functions on platform objects that implement an operation whose IDL specifies a void return type MUST return the undefined value.
ECMAScript functions that implement an operation whose IDL specifies a void return type MAY return any value, which will be discarded.
An ECMAScript value V is converted to an IDL boolean value by running the following algorithm:
The IDL boolean value true is converted to the ECMAScript true value and the IDL boolean value false is converted to the ECMAScript false value.
An ECMAScript value V is converted to an IDL byte value by running the following algorithm:
The result of converting an IDL byte value to an ECMAScript value is a Number that represents the same numeric value as the IDL byte value. The Number value will be an integer in the range [−128, 127].
An ECMAScript value V is converted to an IDL octet value by running the following algorithm:
The result of converting an IDL octet value to an ECMAScript value is a Number that represents the same numeric value as the IDL octet value. The Number value will be an integer in the range [0, 255].
An ECMAScript value V is converted to an IDL short value by running the following algorithm:
The result of converting an IDL short value to an ECMAScript value is a Number that represents the same numeric value as the IDL short value. The Number value will be an integer in the range [−32768, 32767].
An ECMAScript value V is converted to an IDL unsigned short value by running the following algorithm:
The result of converting an IDL unsigned short value to an ECMAScript value is a Number that represents the same numeric value as the IDL unsigned short value. The Number value will be an integer in the range [0, 65535].
An ECMAScript value V is converted to an IDL long value by running the following algorithm:
The result of converting an IDL long value to an ECMAScript value is a Number that represents the same numeric value as the IDL long value. The Number value will be an integer in the range [−2147483648, 2147483647].
An ECMAScript value V is converted to an IDL unsigned long value by running the following algorithm:
The result of converting an IDL unsigned long value to an ECMAScript value is a Number that represents the same numeric value as the IDL unsigned long value. The Number value will be an integer in the range [0, 4294967295].
An ECMAScript value V is converted to an IDL long long value by running the following algorithm:
The result of converting an IDL long long value to an ECMAScript value is a Number value that represents the closest numeric value to the long long, choosing the numeric value with an even significand if there are two equally close values ([ECMA-262], section 8.5). If the long long is in the range (−(253 − 1), 253 − 1), then the Number will be able to represent exactly the same value as the long long.
An ECMAScript value V is converted to an IDL unsigned long long value by running the following algorithm:
The result of converting an IDL unsigned long long value to an ECMAScript value is a Number value that represents the closest numeric value to the unsigned long long, choosing the numeric value with an even significand if there are two equally close values ([ECMA-262], section 8.5). If the unsigned long long is less than or equal to 253 − 1, then the Number will be able to represent exactly the same value as the unsigned long long.
An ECMAScript value V is converted to an IDL float value by running the following algorithm:
The result of converting an IDL float value to an ECMAScript value is the Number value that represents the same numeric value as the IDL float value.
An ECMAScript value V is converted to an IDL unrestricted float value by running the following algorithm:
Since there is only a single ECMAScript NaN value, it must be canonicalized to a particular single precision IEEE 754 NaN value. The NaN value mentioned above is chosen simply because it is the quiet NaN with the lowest value when its bit pattern is interpreted as an unsigned 32 bit integer.
The result of converting an IDL unrestricted float value to an ECMAScript value is a Number:
An ECMAScript value V is converted to an IDL double value by running the following algorithm:
The result of converting an IDL double value to an ECMAScript value is the Number value that represents the same numeric value as the IDL double value.
An ECMAScript value V is converted to an IDL unrestricted double value by running the following algorithm:
Since there is only a single ECMAScript NaN value, it must be canonicalized to a particular double precision IEEE 754 NaN value. The NaN value mentioned above is chosen simply because it is the quiet NaN with the lowest value when its bit pattern is interpreted as an unsigned 64 bit integer.
The result of converting an IDL unrestricted double value to an ECMAScript value is a Number:
An ECMAScript value V is converted to an IDL DOMString value by running the following algorithm:
The result of converting an IDL DOMString value to an ECMAScript value is the String value that represents the same sequence of code units that the IDL DOMString represents.
IDL object values are represented by ECMAScript Object values.
An ECMAScript value V is converted to an IDL object value by running the following algorithm:
The result of converting an IDL object value to an ECMAScript value is the Object value that represents a reference to the same object that the IDL object represents.
IDL interface type values are represented by ECMAScript Object or Function values.
An ECMAScript value V is converted to an IDL interface type value by running the following algorithm (where I is the interface):
The result of converting an IDL interface type value to an ECMAScript value is the Object value that represents a reference to the same object that the IDL interface type value represents.
IDL dictionary type values are represented by ECMAScript Object values. Properties on the object (or its prototype chain) correspond to dictionary members.
An ECMAScript value V is converted to an IDL dictionary type value by running the following algorithm (where D is the dictionary):
The order that dictionary members are looked up on the ECMAScript object are not necessarily the same as the object’s property enumeration order.
An IDL dictionary value V is converted to an ECMAScript Object value by running the following algorithm (where D is the dictionary):
({})
.IDL enumeration types are represented by ECMAScript String values.
An ECMAScript value V is converted to an IDL enumeration type value as follows (where E is the enumeration):
The result of converting an IDL enumeration type value to an ECMAScript value is the String value that represents the same sequence of code units as the enumeration value.
IDL callback function types are represented by ECMAScript Function objects.
An ECMAScript value V is converted to an IDL callback function type value by running the following algorithm:
The result of converting an IDL callback function type value to an ECMAScript value is a reference to the same object that the IDL callback function type value represents.
IDL nullable type values are represented by values of either the ECMAScript type corresponding to the inner IDL type, or the ECMAScript null value.
An ECMAScript value V is converted to an IDL nullable type T? value (where T is the inner type) as follows:
EmptyString
or Null
, then:
EmptyString
, then return the DOMString?
value that represents the empty string.
Null
. Return the null
DOMString? value.
The result of converting an IDL nullable type value to an ECMAScript value is:
IDL sequence<T> values are represented by ECMAScript Array values.
An ECMAScript value V is converted to an IDL sequence<T> value as follows:
An IDL sequence value S0..n−1 of type sequence<T> is converted to an ECMAScript Array object as follows:
[]
.The following interface defines an attribute of a sequence type as well as an operation with an argument of a sequence type.
interface Canvas {
sequence<DOMString> getSupportedImageCodecs();
void drawPolygon(sequence<float> coordinates);
sequence<float> getLastDrawnPolygon();
// ...
};
In an ECMAScript implementation of this interface, an Array
object with elements of type String is used to
represent a sequence<DOMString>, while an
Array with elements of type Number
represents a sequence<float>. The
Array objects are effectively passed by
value; every time the getSupportedImageCodecs()
function is called a new Array is
returned, and whenever an Array is
passed to drawPolygon
no reference
will be kept after the call completes.
// Obtain an instance of Canvas. Assume that getSupportedImageCodecs()
// returns a sequence with two DOMString values: "image/png" and "image/svg+xml".
var canvas = getCanvas();
// An Array object of length 2.
var supportedImageCodecs = canvas.getSupportedImageCodecs();
// Evaluates to "image/png".
supportedImageCodecs[0];
// Each time canvas.getSupportedImageCodecs() is called, it returns a
// new Array object. Thus modifying the returned Array will not
// affect the value returned from a subsequent call to the function.
supportedImageCodecs[0] = "image/jpeg";
// Evaluates to "image/png".
canvas.getSupportedImageCodecs()[0];
// This evaluates to false, since a new Array object is returned each call.
canvas.getSupportedImageCodecs() == canvas.getSupportedImageCodecs();
// An Array of Numbers...
var a = [0, 0, 100, 0, 50, 62.5];
// ...can be passed to a platform object expecting a sequence<float>.
canvas.drawPolygon(a);
// Each element will be converted to a float by first calling ToNumber().
// So the following call is equivalent to the previous one, except that
// "hi" will be alerted before drawPolygon() returns.
a = [false, '',
{ valueOf: function() { alert('hi'); return 100; } }, 0,
'50', new Number(62.5)];
canvas.drawPolygon(s);
// Modifying an Array that was passed to drawPolygon() is guaranteed not to
// have an effect on the Canvas, since the Array is effectively passed by value.
a[4] = 20;
var b = canvas.getLastDrawnPolygon();
alert(b[4]); // This would alert "50".
IDL array values are represented by references to objects known as platform array objects, with particular characteristics that allow them to behave similarly to native Array objects. All platform array objects are platform objects, and thus each is associated with a particular global environment.
Platform array objects differ from Array objects in the following ways:
The value of the internal [[Prototype]] property of a platform array object MUST be the Array prototype object ([ECMA-262], section 15.4.4) from its associated global environment.
Note that some of the functions from the Array prototype object will not behave on a fixed length platform array object as they do on an Array object, since attempting to assign to the “length” property will fail. Similarly, some of the functions from the Array prototype object will not perform any useful operation on read only arrays.
The class string of a platform array object MUST be the type name of the array type.
Platform array objects appear to have a “length” property and a property for each element of the array. The values and behaviors of these properties are implemented by the internal [[GetOwnProperty]], [[DefineOwnProperty]] and [[Delete]] methods, which are also defined below.
Platform array objects cannot be fixed; if Object.freeze
, Object.seal
or Object.preventExtensions
is called on one, the function
MUST throw a TypeError.
An ECMAScript value V is converted to an IDL array value of type T[] as follows:
An IDL array value V of type T[] is converted to an ECMAScript value as follows:
The following IDL defines an interface that has an unsigned short[] attribute.
[Constructor]
interface LotteryResults {
readonly attribute unsigned short[] numbers;
};
Assuming that the array has a fixed length of 6, the following ECMAScript code illustrates how the array attribute in the above interface would behave:
var results = new LotteryResults(); // results is a new platform object
// implementing the LotteryResults interface.
var a = [4, 8, 15, 16, 23, 42]; // Numbers will be assigned into the array.
for (var i = 0; i < 6; i++) {
results.numbers[i] = a[i];
}
results.numbers = a; // This has no effect, since numbers is
// read only.
a[0] = 5; // Change the array.
results.numbers[0]; // Evaluates to 4, since results.numbers is
// not a reference to 'a'.
results.numbers[0] = 5; // Modifies the array stored in the platform
// object.
results.numbers[0]; // Now evaluates to 5.
results.numbers[0] = 6.25; // Assigns 6 to the first element of the array
// since that is how 6.5 is converted to an
// unsigned short.
results.numbers.length = 7; // Has no effect, since numbers is
// fixed length.
results.numbers[6]; // Evaluates to undefined.
results.numbers.slice(0, 2); // Evaluates to an Array [6, 8].
results.numbers.push(108); // Has no effect, since the definition of
// push() relies on calling [[Put]] on a
// non-existent array index property
// and on "length", both of which will
// be silently ignored.
delete results.numbers[3]; // Has no effect and evaluates to false,
// since the array index properties are
// non-configurable.
If passing an Array object to a platform object expecting an IDL array value, a new platform array object will be created to represent an IDL array value determined from that Array. If the LotteryResults interface is instead defined as:
[Constructor]
interface LotteryResults {
attribute unsigned short[] numbers;
};
then an Array object can be assigned to the “numbers” property. Unless the prose accompanying the interface said otherwise, this would result in a fixed length array of whatever length the Array has being assigned to the IDL attribute.
var results = new LotteryResults();
results.numbers.length; // Evaluates to 6.
var a = [1, 3, 5];
results.numbers = a; // Assigns a fixed length IDL array of length 3 to
// the numbers attribute.
results.numbers; // This now evaluates to a platform array object
// that represents the fixed length IDL array,
// not the Array object assigned in the previous
// statement.
results.numbers == a; // Evaluates to false.
results.numbers.length; // Evaluates to 3.
results.numbers.push(7); // Silently ignored in non-strict mode.
results.numbers.length; // So this still evaluates to 3.
The internal [[GetOwnProperty]] method of every platform array object A with element type T MUST behave as follows when called with property name P:
The internal [[DefineOwnProperty]] method of every platform array object A with element type T MUST behave as follows when passed property name P, property descriptor Desc and boolean flag Throw. The term “Reject” is used in the same sense as that defined in ECMA-262, namely, to mean “If Throw is true, then throw a TypeError exception, otherwise return false”.
The internal [[Delete]] method of every platform array object A with element type T MUST behave as follows when passed property name P and boolean flag Throw. The term “Reject” is used as defined in section 4.2.24.2 above.
IDL union type values are represented by ECMAScript values that correspond to the union’s member types.
To convert an ECMAScript value V to an IDL union type value is done as follows:
An IDL union type value is converted to an ECMAScript value as follows. If the value is an object reference to a special object that represents an ECMAScript undefined value, then it is converted to the ECMAScript undefined value. Otherwise, the rules for converting the specific type of the IDL union type value as described in this section (4.2).
IDL Date values are represented by ECMAScript Date objects.
An ECMAScript value V is converted to an IDL Date value by running the following algorithm:
An IDL Date value V is converted to an ECMAScript value by running the following the algorithm:
Platform objects returning an ECMAScript Date object from attributes, operations or exception field do not hold on to a reference to the Date object. A script that modifies a Date object so retrieved cannot affect the platform object it was retrieved from.
This section defines a number of extended attributes whose presence affects only the ECMAScript binding.
If the [ArrayClass] extended attribute appears on an interface that is not defined to inherit from another, it indicates that the internal [[Prototype]] property of its interface prototype object will be the Array prototype object rather than the Object prototype object. This allows Array methods to be used more easily with objects implementing the interface.
The [ArrayClass] extended attribute MUST take no arguments. It MUST NOT be used on an interface that has any inherited interfaces.
Interfaces using [ArrayClass] will need to define a “length” attribute of type unsigned long that exposes the length of the array-like object, in order for the inherited Array methods to operate correctly. Such interfaces would typically also support indexed properties, which would provide access to the array elements.
See section 4.4.3 for the specific requirements that the use of [ArrayClass] entails.
The following IDL fragment defines two interfaces that use [ArrayClass].
[ArrayClass]
interface ItemList {
attribute unsigned long length;
getter object getItem(unsigned long index);
creator setter object setItem(unsigned long index, object item);
deleter void removeItem(unsigned long index);
};
[ArrayClass]
interface ImmutableItemList {
readonly attribute unsigned long length;
getter object getItem(unsigned long index);
};
In an ECMAScript implementation of the above two interfaces, with appropriate definitions for getItem, setItem and removeItem, Array methods to inspect and modify the array-like object can be used.
var list = getItemList(); // Obtain an instance of ItemList.
list.concat(); // Clone the ItemList into an Array.
list.pop(); // Remove an item from the ItemList.
list.unshift({ }); // Insert an item at index 0.
ImmutableItemList has a read only length attribute and no indexed property setter, creator or deleter. The mutating Array methods will generally not succeed on objects implementing ImmutableItemList. The exact behavior depends on the definition of the Array methods themselves ([ECMA-262], section 15.4.4).
If the [Clamp] extended attribute appears on an operation argument, writable attribute or dictionary member whose type is one of the integer types, it indicates that when an ECMAScript Number is converted to the IDL type, out of range values will be clamped to the range of valid values, rather than using the operators that use a modulo operation (ToInt32, ToUint32, etc.).
The [Clamp] extended attribute MUST take no arguments.
The [Clamp] extended attribute MUST NOT appear on a read only attribute, or an attribute, operation argument or dictionary member that is not of an integer type. It also MUST NOT be used in conjunction with the [EnforceRange] extended attribute.
See the rules for converting ECMAScript values to the various IDL integer types in section 4.2 for the specific requirements that the use of [Clamp] entails.
In the following IDL fragment, two operations are declared that take three octet arguments; one uses the [Clamp] extended attribute on all three arguments, while the other does not:
interface GraphicsContext {
void setColor(octet red, octet green, octet blue);
void setColorClamped([Clamp] octet red, [Clamp] octet green, [Clamp] octet blue);
};
In an ECMAScript implementation of the IDL, a call to setColorClamped with Number values that are out of range for an octet are clamped to the range [0, 255].
// 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);
If the [Constructor] extended attribute appears on an interface, it indicates that the interface object for this interface will have an [[Construct]] internal method, allowing objects implementing the interface to be constructed. Multiple [Constructor] extended attributes may appear on a given interface.
The [Constructor]
extended attribute MUST either
take no arguments or
take an argument list.
The bare form, [Constructor]
, has the same meaning as
using an empty argument list, [Constructor()]
. For each
[Constructor] extended attribute
on the interface, there will be a way to construct an object that implements
the interface by passing the specified arguments.
If the [Constructor] extended attribute is specified on an interface, then the [NoInterfaceObject] extended attribute MUST NOT also be specified on that interface.
The [Constructor] extended attribute MUST NOT be used on a callback interface.
See section 4.4.1.1 below for details on how a constructor is to be implemented.
The following IDL defines two interfaces. The second has the [Constructor] extended attribute, while the first does not.
interface NodeList {
Node item(unsigned long index);
readonly attribute unsigned long length;
};
[Constructor,
Constructor(float radius)]
interface Circle {
attribute float r;
attribute float cx;
attribute float cy;
readonly attribute float circumference;
};
An ECMAScript implementation supporting these interfaces would have a [[Construct]] property on the Circle interface object which would return a new object that implements the interface. It would take either zero or one argument. The NodeList interface object would not have a [[Construct]] property.
var x = new Circle(); // The uses the zero-argument constructor to create a
// reference to a platform object that implements the
// Circle interface.
var y = new Circle(1.25); // This also creates a Circle object, this time using
// the one-argument constructor.
var z = new NodeList(); // This would throw a TypeError, since no
// [Constructor] is declared.
If the [EnforceRange] extended attribute appears on an operation argument, writable attribute or dictionary member whose type is one of the integer types, it indicates that when an ECMAScript Number is converted to the IDL type, out of range values will cause an exception to be thrown, rather than converted to being a valid value using the operators that use a modulo operation (ToInt32, ToUint32, etc.). The Number will be rounded towards zero before being checked against its range.
The [EnforceRange] extended attribute MUST take no arguments.
The [EnforceRange] extended attribute MUST NOT appear on a read only attribute, or an attribute, operation argument or dictionary member that is not of an integer type. It also MUST NOT be used in conjunction with the [Clamp] extended attribute.
See the rules for converting ECMAScript values to the various IDL integer types in section 4.2 for the specific requirements that the use of [EnforceRange] entails.
In the following IDL fragment, two operations are declared that take three octet arguments; one uses the [EnforceRange] extended attribute on all three arguments, while the other does not:
interface GraphicsContext {
void setColor(octet red, octet green, octet blue);
void setColorEnforcedRange([EnforceRange] octet red, [EnforceRange] octet green, [EnforceRange] octet blue);
};
In an ECMAScript implementation of the IDL, a call to setColorEnforcedRange with 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);
If the [ImplicitThis] extended attribute appears on an interface, it indicates that when a Function corresponding to one of the interface’s operations is invoked with the null or undefined value as the this value, that the ECMAScript global object will be used as the this value instead. This is regardless of whether the calling code is in strict mode.
The [ImplicitThis] extended attribute MUST take no arguments.
See section 4.4.7 for the specific requirements that the use of [ImplicitThis] entails.
The [ImplicitThis] extended attribute is intended for use on the Window interface as defined in HTML5 ([HTML5], section 5.2).
In the following example, the Window interface is defined with the [ImplicitThis] extended attribute.
[ImplicitThis]
interface Window {
...
attribute DOMString name;
void alert(DOMString message);
};
Since the Window object is used as the ECMAScript global object, calls to its functions can be made without an explicit object, even in strict mode:
"use strict";
window.alert("hello"); // Calling alert with an explicit window object works.
alert("hello"); // This also works, even though we are in strict mode.
alert.call(null, "hello"); // As does passing null explicitly as the this value.
// This does not apply to getters for attributes on the interface, though.
// The following will throw a TypeError.
Object.getOwnPropertyDescriptor(Window.prototype, "name").get.call(null);
If the [LenientThis] extended attribute appears on an attribute, it indicates that invocations of the attribute’s getter or setter with a this value that is not an object that implements the interface on which the attribute appears will be ignored.
The [LenientThis] extended attribute MUST take no arguments.
Specifications SHOULD NOT use [LenientThis] unless required for compatibility reasons. Specification authors who wish to use this feature are strongly advised to discuss this on the public-script-coord@w3.org mailing list before proceeding.
See the Attributes section below for how [LenientThis] is to be implemented.
The following IDL fragment defines an interface that uses the [LenientThis] extended attribute.
interface Example {
[LenientThis] attribute DOMString x;
attribute DOMString y;
};
An ECMAScript implementation that supports this interface will allow the getter and setter of the accessor property that corresponds to x to be invoked with something other than an Example object.
var example = getExample(); // Get an instance of Example.
var obj = { };
// Fine.
example.x;
// Ignored, since the this value is not an Example object and [LenientThis] is used.
Object.getOwnPropertyDescriptor(Example.prototype, "x").get.call(obj);
// Also ignored, since Example.prototype is not an Example object and [LenientThis] is used.
Example.prototype.x;
// Throws a TypeError, since Example.prototype is not an Example object.
Example.prototype.y;
If the [NamedConstructor] extended attribute appears on an interface, it indicates that the ECMAScript global object will have a property with the specified name whose value is a constructor function that can create objects that implement the interface. Multiple [NamedConstructor] extended attributes may appear on a given interface.
The [NamedConstructor]
extended attribute MUST either
take an identifier or
take a named argument list.
The first form, [NamedConstructor=identifier]
, has the same meaning as
using an empty argument list, [NamedConstructor=identifier()]
. For each
[NamedConstructor] extended attribute
on the interface, there will be a way to construct an object that implements
the interface by passing the specified arguments to the constructor function
that is the value of the aforementioned property.
The identifier used for the named constructor MUST NOT be the same as that used by an [NamedConstructor] extended attribute on another interface, MUST NOT be the same as an identifier of an interface (or exception) that has an interface object (or exception interface object), and MUST NOT be one of the reserved identifiers.
The [Constructor] extended attribute MUST NOT be used on a callback interface.
See section 4.4.2 below for details on how named constructors are to be implemented.
The following IDL defines an interface that uses the [NamedConstructor] extended attribute.
[NamedConstructor=Audio,
NamedConstructor=Audio(DOMString src)]
interface HTMLAudioElement : HTMLMediaElement {
// ...
};
An ECMAScript implementation that supports this interface will allow the construction of HTMLAudioElement objects using the Audio constructor.
typeof Audio; // Evaluates to 'function'.
var a1 = new Audio(); // Creates a new object that implements
// HTMLAudioElement, using the zero-argument
// constructor.
var a2 = new Audio('a.flac'); // Creates an HTMLAudioElement using the
// one-argument constructor.
If the [NoInterfaceObject] extended attribute appears on an interface, it indicates that an interface object will not exist for the interface in the ECMAScript binding. Similarly, if it appears on an exception it indicates that an exception interface object will not exist for the exception in the ECMAScript binding.
The [NoInterfaceObject] extended attribute SHOULD NOT be used on interfaces that are not solely used as supplemental interfaces, unless there are clear Web compatibility reasons for doing so. Specification authors who wish to use this feature are strongly advised to discuss this on the public-script-coord@w3.org mailing list before proceeding.
The [NoInterfaceObject] extended attribute MUST take no arguments.
If the [NoInterfaceObject] extended attribute is specified on an interface, then the [Constructor] extended attribute MUST NOT also be specified on that interface. A [NamedConstructor] extended attribute is fine, however.
The [NoInterfaceObject] extended attribute MUST NOT be specified on an interface that has any static operations defined on it.
The [NoInterfaceObject] extended attribute MUST NOT be specified on a callback interface, as interface objects never exist for callback interfaces.
See section 4.2.18 and section 4.9 for the specific requirements that the use of [NoInterfaceObject] entails.
The following IDL fragment defines two interfaces, one whose interface object is exposed on the ECMAScript global object, and one whose isn’t:
interface Storage {
void addEntry(unsigned long key, any value);
};
[NoInterfaceObject]
interface Query {
any lookupEntry(unsigned long key);
};
An ECMAScript implementation of the above IDL would allow manipulation of Storage’s prototype, but not Query’s.
typeof Storage; // evaluates to "object"
// Add some tracing alert() call to Storage.addEntry.
var fn = Storage.prototype.addEntry;
Storage.prototype.addEntry = function(key, value) {
alert('Calling addEntry()');
return fn.call(this, key, value);
};
typeof Query; // evaluates to "undefined"
var fn = Query.prototype.lookupEntry; // exception, Query isn’t defined
If the [OverrideBuiltins] extended attribute appears on an interface, it indicates that for a platform object implementing the interface, properties corresponding to all of the object’s supported property names will appear to be on the object, regardless of what other properties exist on the object or its prototype chain. This means that named properties will always shadow any properties that would otherwise appear on the object. This is in contrast to the usual behavior, which is for named properties to be exposed only if there is no property with the same name on the object itself or somewhere on its prototype chain.
The [OverrideBuiltins] extended attribute MUST take no arguments and MUST NOT appear on an interface that does not define a named property getter or that also is declared with the [NamedPropertiesObject] extended attribute. If the extended attribute is specified on a partial interface definition, then that partial interface definition MUST be the part of the interface definition that defines the named property getter.
See section 4.6.1 and section 4.6.3 for the specific requirements that the use of [OverrideBuiltins] entails.
The following IDL fragment defines two interfaces, one that has a named property getter and one that does not.
interface StringMap {
readonly attribute unsigned long length;
getter DOMString lookup(DOMString key);
};
[OverrideBuiltins]
interface StringMap2 {
readonly attribute unsigned long length;
getter DOMString lookup(DOMString key);
};
In an ECMAScript implementation of these two interfaces, getting certain properties on objects implementing the interfaces will result in different values:
// Obtain an instance of StringMap. Assume that it has "abc", "length" and
// "toString" as supported property names.
var map1 = getStringMap();
// This invokes the named property getter.
map1.abc;
// This fetches the "length" property on the object that corresponds to the
// length attribute.
map1.length;
// This fetches the "toString" property from the object's prototype chain.
map1.toString;
// Obtain an instance of StringMap2. Assume that it also has "abc", "length"
// and "toString" as supported property names.
var map2 = getStringMap2();
// This invokes the named property getter.
map2.abc;
// This also invokes the named property getter, despite the fact that the "length"
// property on the object corresponds to the length attribute.
map2.length;
// This too invokes the named property getter, despite the fact that "toString" is
// a property in map2's prototype chain.
map2.toString;
If the [PutForwards] extended attribute appears on a read only attribute declaration whose type is an interface type, it indicates that assigning to the attribute will have specific behavior. Namely, the assignment is “forwarded” to the attribute (specified by the extended attribute argument) on the object that is currently referenced by the attribute being assigned to.
The [PutForwards] extended attribute MUST take an identifier. Assuming that:
then there MUST be another attribute B declared on J whose identifier is N. Assignment of a value to the attribute A on an object implementing I will result in that value being assigned to attribute B of the object that A references, instead.
Note that [PutForwards]-annotated attributes can be chained. That is, an attribute with the [PutForwards] extended attribute can refer to an attribute that itself has that extended attribute. There MUST NOT exist a cycle in a chain of forwarded assignments. A cycle exists if, when following the chain of forwarded assignments, a particular attribute on an interface is encountered more than once.
An attribute with the [PutForwards] extended attribute MUST NOT also be declared with the [Replaceable] extended attribute.
The [PutForwards] extended attribute MUST NOT be used on an attribute declared on a callback interface.
See the Attributes section below for how [PutForwards] is to be implemented.
The following IDL fragment defines interfaces for names and people. The [PutForwards] extended attribute is used on the name attribute of the Person interface to indicate that assignments to that attribute result in assignments to the full attribute of the Person object:
interface Name {
attribute DOMString full;
attribute DOMString family;
attribute DOMString given;
};
interface Person {
[PutForwards=full] readonly attribute Name name;
attribute unsigned short age;
};
In the ECMAScript binding, this would allow assignments to the “name” property:
var p = getPerson(); // Obtain an instance of Person.
p.name = 'John Citizen'; // This statement...
p.name.full = 'John Citizen'; // ...has the same behavior as this one.
If the [Replaceable] extended attribute appears on a read only attribute, it indicates that setting the corresponding property on the platform object will result in an own property with the same name being created on the object which has the value being assigned. This property will shadow the accessor property corresponding to the attribute, which exists on the interface prototype object.
The [Replaceable] extended attribute MUST take no arguments.
An attribute with the [Replaceable] extended attribute MUST NOT also be declared with the [PutForwards] extended attribute.
The [Replaceable] extended attribute MUST NOT be used on an attribute declared on a callback interface.
See section 4.4.6 for the specific requirements that the use of [Replaceable] entails.
The following IDL fragment defines an interface with an operation that increments a counter, and an attribute that exposes the counter’s value, which is initially 0:
interface Counter {
[Replaceable] readonly attribute unsigned long value;
void increment();
};
Assigning to the “value” property on a platform object implementing Counter will shadow the property that corresponds to the attribute:
var counter = getCounter(); // Obtain an instance of Counter.
counter.value; // Evaluates to 0.
counter.hasOwnProperty("value"); // Evaluates to false.
Object.getPrototypeOf(counter).hasOwnProperty("value"); // Evaluates to true.
counter.increment();
counter.increment();
counter.value; // Evaluates to 2.
counter.value = 'a'; // Shadows the property with one that is unrelated
// to Counter::value.
counter.hasOwnProperty("value"); // Evaluates to true.
counter.increment();
counter.value; // Evaluates to 'a'.
delete counter.value; // Reveals the original property.
counter.value; // Evaluates to 3.
If the [NamedPropertiesObject] extended attribute appears on an interface, then for objects that support named properties these properties will be exposed on an object in the prototype chain rather than on the object itself, which is the normal behavior. The result of this is that the named properties will appear to be replaceable.
Specifications SHOULD NOT use [NamedPropertiesObject] unless required for compatibility reasons. Specification authors who wish to use this feature are strongly advised to discuss this on the public-script-coord@w3.org mailing list before proceeding.
The [NamedPropertiesObject] extended attribute MUST take no arguments.
If the [NamedPropertiesObject] extended attribute is used on an interface, then:
If [NamedPropertiesObject] 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 [NamedPropertiesObject] extended attribute MUST NOT be used on an interface that can have more than one object implementing it in the same ECMAScript global environment.
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.
See section 4.4.4, section 4.6.2 and section 4.6.3 for the specific requirements that the use of [NamedPropertiesObject] entails.
This extended attribute is intended to be used by the Window interface as defined in HTML5 ([HTML5], section 5.2). The interface exposes frames as properties on the Window object. Since the Window object also serves as the ECMAScript global object, variable declarations or assignments to the named properties will result in them being replaced by the new value.
[NamedPropertiesObject]
interface Window {
getter any (DOMString name);
// ...
};
The following HTML document illustrates how the named properties on the Window object can be shadowed:
<!DOCTYPE html>
<title>Shadowing named properties on Window</title>
<iframe name=abc></iframe>
<script>
window.abc; // Evaluates to the iframe's Window object.
abc = 1; // Shadows the named property.
window.abc; // Evaluates to 1.
</script>
If the [TreatNonCallableAsNull] extended attribute appears on a callback function, then it indicates that any value assigned to an attribute whose type is a nullable callback function that is not a callable object will be converted to the null value.
Specifications SHOULD NOT use [TreatNonCallableAsNull]
unless required to specify the behavior of legacy APIs or for consistency with these
APIs. Specification authors who
wish to use this feature are strongly advised to discuss this on the
public-script-coord@w3.org
mailing list before proceeding. At the time of writing, the only known
valid use of [TreatNonCallableAsNull]
is for the callback functions used as the type
of event handler IDL attributes
([HTML5], section 6.1.6.1)
such as onclick
and onerror
.
See section 4.2.22 for the specific requirements that the use of [TreatNonCallableAsNull] entails.
The following IDL fragment defines an interface that has one attribute whose type is a [TreatNonCallableAsNull]-annotated callback function and another whose type is a callback function without the extended attribute:
[TreatNonCallableAsNull]
callback OccurrenceHandler = void (DOMString details);
callback ErrorHandler = void (DOMString details);
interface Manager {
attribute OccurrenceHandler? handler1;
attribute ErrorHandler? handler2;
};
In an ECMAScript implementation, assigning a value that is not callable (such as a Number value) 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) {
}
manager.handler2 = function() { };
manager.handler2; // Evaluates to the function.
manager.handler2 = 123;
manager.handler2; // Evaluates to null.
If the [TreatNullAs] extended attribute appears on an attribute or operation argument whose type is DOMString, it indicates that a null value assigned to the attribute or passed as the operation argument will be handled differently from its default handling. Instead of being stringified to “null”, which is the default, it will be converted to the empty string “”.
If [TreatNullAs] is specified on an operation itself, and that operation is on a callback interface, then it indicates that a user object implementing the interface will have the return value of the function that implements the operation handled in the same way as for operation arguments and attributes, as above.
The [TreatNullAs]
extended attribute MUST take the identifier
EmptyString
.
The [TreatNullAs] extended attribute MUST NOT be specified on an operation argument, attribute or operation return value whose type is not DOMString.
This means that even an attribute of type DOMString? must not use [TreatNullAs], since null is a valid value of that type.
The [TreatNullAs] extended attribute also MUST NOT be specified on an operation on a non-callback interface.
See section 4.2.16 for the specific requirements that the use of [TreatNullAs] entails.
The following IDL fragment defines an interface that has one attribute with the [TreatNullAs] extended attribute, and one operation with an argument that has the extended attribute:
interface Dog {
attribute DOMString name;
[TreatNullAs=EmptyString] attribute DOMString owner;
boolean isMemberOfBreed([TreatNullAs=EmptyString] DOMString breedName);
};
An ECMAScript implementation implementing the Dog
interface would convert a null value
assigned to the “name” property or passed as the
argument to the isMemberOfBreed
function
to the empty string rather than "null"
:
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.
The [TreatUndefinedAs] extended attribute has two uses.
The first use is to control how the undefined
value is converted into a DOMString.
If the extended attribute
appears on an attribute
or operation argument whose type is
DOMString or DOMString?,
and it is specified as [TreatUndefinedAs=EmptyString]
or
[TreatUndefinedAs=Null]
,
it indicates that an undefined value
assigned to the corresponding property or passed as an argument to
the corresponding function will be handled differently from its
default handling, which is to stringify to
“undefined”:
EmptyString
, then the value assigned to the
attribute or passed as the operation argument will be the empty string,
“”.
Null
, then the value assigned to the
attribute or passed as the operation argument will be the
null value.
If [TreatUndefinedAs] is specified on an operation itself, then it indicates that a user object implementing the interface will have the return value of the function that implements the operation handled in the same way as for operation arguments and attributes, as above.
The second use for [TreatUndefinedAs]
is to control how undefined values passed
to a function corresponding to an operation
are treated. If it is specified as [TreatUndefinedAs=Missing]
on
an optional operation argument, then an explicit undefined value
will cause the function call to be treated as if the argument had been omitted.
The [TreatUndefinedAs]
extended attribute MUST take an identifier:
EmptyString
, Null
or Missing
.
[TreatUndefinedAs=Null]
MUST NOT be specified on operation argument,
attribute or operation return value whose type is not DOMString?,
and [TreatUndefinedAs=EmptyString]
MUST NOT be specified on operation argument,
attribute or operation return value whose type is neither
DOMString nor DOMString?.
The [TreatUndefinedAs]
extended attribute
also MUST NOT be specified on an operation on
a non-callback interface.
[TreatUndefinedAs=Missing]
MUST NOT
be specified on an operation itself and MUST NOT be
specified on a non-optional operation argument. When specified on an operation argument,
then any following arguments MUST also be annotated with
[TreatUndefinedAs=Missing]
.
Specifications SHOULD NOT use [TreatUndefinedAs=Missing]
unless required for compatibility reasons. Specification authors who
wish to use this feature are strongly advised to discuss this on the
public-script-coord@w3.org
mailing list before proceeding.
See section 4.2.16
and section 4.2.22
for the specific requirements that the use of
[TreatUndefinedAs=Null]
and [TreatUndefinedAs=EmptyString]
entails. See the overload resolution algorithm
for how [TreatUndefinedAs=Missing]
is handled.
The following IDL fragment defines an interface that has one attribute with the [TreatUndefinedAs] extended attribute, and one operation with an argument that has the extended attribute:
interface Cat {
attribute DOMString name;
[TreatUndefinedAs=Null] attribute DOMString? owner;
boolean isMemberOfBreed([TreatUndefinedAs=EmptyString] DOMString breedName);
};
An ECMAScript implementation implementing the Cat
interface would convert an undefined value
assigned to the “name” and “owner”
properties and passed as the argument to the isMemberOfBreed
function
all differently; the value would be converted to the string
“undefined”, the null
value, and the empty string “”, respectively:
var c = getCat(); // Obtain an instance of Cat.
c.name = undefined; // This assigns the string "undefined" to the
// .name property.
c.owner = undefined; // This assigns the null value to the
// .owner property.
c.isMemberOfBreed(undefined); // This passes the string "" to the
// isMemberOfBreed function.
The following IDL fragment defines an interface with
an operation that uses [TreatUndefinedAs=Missing]
.
interface A {
void f(float x, [TreatUndefinedAs=Missing] optional float y);
};
If f is called as f(1, undefined)
then it will have the same behavior
as if it were called as f(1)
.
If the [Unforgeable] extended attribute appears on a read only attribute, it indicates that the attribute will be reflected as an ECMAScript property in a way that means its behavior cannot be modified and that performing a property lookup on the object will always result in the attribute’s property value being returned. In particular, the property will be non-configurable and will exist as an own property on the object itself rather than on its prototype.
The [Unforgeable] extended attribute MUST take no arguments.
The [Unforgeable] extended attribute MUST NOT appear on anything other than a read only attribute. It also MUST NOT appear on an attribute on interface A if there exists another interface B that has A as an inherited interface.
For example, the following IDL would be invalid:
interface A {
[Unforgeable] readonly attribute DOMString key;
};
interface B : A { };
See section 4.4.6, section 4.6.1 and section 4.6.3 for the specific requirements that the use of [Unforgeable] entails.
The following IDL fragment defines an interface that has two attributes, one of which is designated as [Unforgeable]:
interface System {
[Unforgeable] readonly attribute DOMString username;
readonly attribute Date loginTime;
};
In an ECMAScript implementation of the interface, the username attribute will be exposed as a non-configurable property on the object itself:
var system = getSystem(); // Get an instance of System.
system.hasOwnProperty("username"); // Evaluates to true.
system.hasOwnProperty("loginTime"); // Evaluates to false.
System.prototype.hasOwnProperty("username"); // Evaluates to false.
System.prototype.hasOwnProperty("loginTime"); // Evaluates to true.
try {
// This call would fail, since the property is non-configurable.
Object.defineProperty(system, "username", { value: "administrator" });
} catch (e) { }
// This defineProperty call would succeed, because System.prototype.loginTime
// is configurable.
var forgedLoginTime = new Date(new Date() - 3600000);
Object.defineProperty(System.prototype, "loginTime", { value: forgedLoginTime });
system.loginTime; // So this now evaluates to forgedLoginTime.
For every interface that:
a corresponding property MUST exist on the ECMAScript global object. The name of the property is the identifier of the interface, and its value is an object called the interface object.
The property has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }. The characteristics of an interface object are described in section 4.4.1 below.
In addition, for every [NamedConstructor] extended attribute on an interface, a corresponding property MUST exist on the ECMAScript global object. The name of the property is the identifier that occurs directly after the “=”, and its value is an object called a named constructor, which allows construction of objects that implement the interface. The property has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }. The characteristics of a named constructor are described in section 4.4.2 below.
The interface object for a given non-callback interface is a function object. It has properties that correspond to the constants and static operations defined on that interface, as described in sections 4.4.5 and 4.4.7 below.
The value of the “prototype” property of an interface object for a non-callback interface MUST be an object called the interface prototype object. This object has properties that correspond to the attributes and operations defined on the interface, and is described in more detail in section 4.4.3 below.
Since an interface object for a non-callback interface is a function object, it will have a “prototype” property with attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.
The interface object for a callback interface MUST NOT be a function object and MUST NOT have a “prototype” property. The internal [[Prototype]] property of an interface object for a callback interface MUST be the Object.prototype object.
If the interface is declared with a [Constructor] extended attribute, then the interface object can be called as a function to create an object that implements that interface. Interfaces that do not have a constructor will throw an exception when called as a function.
In order to define how overloaded constructor invocations are resolved, the overload resolution algorithm is defined. Its input is an effective overload set, S, and a list of ECMAScript values, arg0..n−1. Its output is a pair consisting of the operation or extended attribute of one of S’s entries and a list of IDL values. The algorithm behaves as follows:
[TreatUndefinedAs=Missing]
extended attribute
on its arguments at indices j and above, then set argcount to j.All entries in S at this point have the same type at index i.
This is the argument that will be used to resolve which overload is selected.
The overload resolution algorithm performs both the identification of which overloaded operation, constructor, etc. is being called, and the conversion of the ECMAScript argument values to their corresponding IDL values. Informally, it operates as follows.
First, the selection of valid overloads is done by considering the number of ECMAScript arguments that were passed in to the function:
[TreatUndefinedAs=Missing]
on the corresponding argument.Once we have a set of possible overloads with the right number of arguments, the ECMAScript values are converted from left to right. The nature of the restrictions on overloading means that if we have multiple possible overloads at this point, then there will be one position in the argument list that will be used to distinguish which overload we will finally select; this is the distinguishing argument index. All arguments to the left of this one, in all the overloads we are still considering at this point, will have the same type at a given argument index.
So we convert all of the arguments from index 0 up to the distinguishing argument index. Once we come to the distinguishing argument index, we inspect the type of the ECMAScript value that is passed in to determine which IDL type it may correspond to. This allows us to select the final overload that will be invoked. If there is no valid overload for the type of value passed in here, then we throw a TypeError. The inspection of the value does not have any side effects; the only side effects that come from running the overload resolution algorithm are those that come from converting the ECMAScript values to IDL values. After this, we convert the remaining argument values, still from left to right.
If at the end of this process, we have selected an overload that has optional argument default values for arguments that follow the explicit arguments that we have just converted, then we include those default values in the list of argument values we return from the algorithm.
In general, an explicit undefined passed to an operation
is not treated the same as a missing optional argument (unless [TreatUndefinedAs=Missing]
is specified in the IDL). This is inline with the current
proposed behaviour for parameter default values in ECMAScript 6th edition. However,
there is a possibility that ES6 will change, in which case the treatment of undefined
might be revisited.
The internal [[Call]] method of the interface object behaves as follows, assuming arg0..n−1 is the list of argument values passed to the constructor, and I is the interface:
If the internal [[Call]] method of the interface object returns normally, then it MUST return an object that implements interface I. This object also MUST be associated with the ECMAScript global environment associated with the interface object.
Interface objects for interfaces declared with a [Constructor] extended attribute MUST have a property named “length” with attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false } whose value is a Number determined as follows:
A named constructor that exists due to one or more [NamedConstructor] extended attributes with a given identifier is a function object. It MUST have a [[Call]] internal property, which allows construction of objects that implement the interface on which the [NamedConstructor] extended attributes appear. It behaves as follows, assuming arg0..n−1 is the list of argument values passed to the constructor, id is the identifier of the constructor specified in the extended attribute named argument list, and I is the interface on which the [NamedConstructor] extended attribute appears:
If the internal [[Call]] method of the named constructor returns normally, then it MUST return an object that implements interface I. This object also MUST be associated with the ECMAScript global environment associated with the named constructor.
A named constructor MUST have a property named “length” with attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false } whose value is a Number determined as follows:
A named constructor MUST also have a property named “prototype” with attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false } whose value is the interface prototype object for the interface on which the [NamedConstructor] extended attribute appears.
There MUST exist an interface prototype object for every non-callback interface defined, regardless of whether the interface was declared with the [NoInterfaceObject] extended attribute. The interface prototype object for a particular interface has properties that correspond to the attributes and operations defined on that interface. These properties are described in more detail in sections 4.4.6 and 4.4.7 below.
As with the interface object, the interface prototype object also has properties that correspond to the constants defined on that interface, described in section 4.4.5 below.
If the [NoInterfaceObject] extended attribute was not specified on the interface, then the interface prototype object MUST also have a property named “constructor” with attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } whose value is a reference to the interface object for the interface.
The interface prototype object for a given interface A MUST have an internal [[Prototype]] property whose value is as follows:
The interface prototype object of an interface that is defined with the [NoInterfaceObject] extended attribute will be accessible if the interface is used as a non-supplemental interface. For example, with the following IDL:
[NoInterfaceObject]
interface Foo {
};
partial interface Window {
attribute Foo foo;
};
it is not possible to access the interface prototype object through
the interface object
(since it does not exist as window.Foo
). However, an instance
of Foo can expose the interface prototype
object by gettings its internal [[Prototype]]
property value – Object.getPrototypeOf(window.foo)
in
this example.
If the interface is used solely as a supplemental interface, then there will be no way to access its interface prototype object, since no object will have the interface prototype object as its internal [[Prototype]] property value. In such cases, it is an acceptable optimization for this object not to exist.
The class string of an interface prototype object is the concatenation of the interface’s identifier and the string “Prototype”.
For every interface declared with the [NamedPropertiesObject] extended attribute, there MUST exists an object known as the named properties object for that interface.
A named properties object MUST be a function object.
The named properties object for a given interface A MUST have an internal [[Prototype]] property whose value is as follows:
The class string of a named properties object is the concatenation of the interface’s identifier and the string “Properties”.
The internal [[GetOwnProperty]] method of every named properties object MUST behave as follows when called with object O and property name P:
For each constant defined on an interface A, there MUST be a corresponding property on the interface object, if it exists. The property has the following characteristics:
In addition, a property with the same characteristics MUST exist on the interface prototype object.
For each attribute defined on the interface, there MUST exist a corresponding property. If the attribute was declared with the [Unforgeable] extended attribute, then the property exists on every object that implements the interface. Otherwise, it exists on the interface’s interface prototype object.
The characteristics of these properties are as follows:
readonly
and has neither a
[PutForwards] nor a [Replaceable]
extended attribute declared on it.
Otherwise, it is a Function object whose behavior when invoked is as follows:
Note that attempting to assign to a property corresponding to a read only attribute results in different behavior depending on whether the script doing so is in strict mode. When in strict mode, such an assignment will result in a TypeError being thrown. When not in strict mode, the assignment attempt will be ignored.
For each unique identifier of an operation defined on the interface, there MUST be a corresponding property on the interface prototype object (if it is a regular operation) or the interface object (if it is a static operation), unless the effective overload set for that identifier and operation and with an argument count of 0 has no entries.
The characteristics of such a corresponding property are as follows:
In addition, if the interface
has a stringifier, then
a property MUST exist on
the interface prototype object
whose name is “toString”,
with attributes { [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }
and whose value is a
Function object. If stringifier
was specified on an attribute A, then the
function, when invoked,
MUST behave as follows:
If stringifier
was specified on an operation
with an identifier P, then
the function, when invoked,
MUST behave as follows:
If stringifier
was specified on an operation
with no identifier,
then the behavior of the function
is the stringification behavior
of the interface, as described in the prose for the interface.
The interface prototype object of an interface A MUST have a copy of each property that corresponds to one of the constants, attributes or operations that exist on all of the interface prototype objects of A’s consequential interfaces.
Every platform object is associated with a global environment, just as the initial objects are. It is the responsibility of specifications using Web IDL to state which global environment (or, by proxy, which global object) each platform object is associated with.
The primary interface of a platform object that implements one or more interfaces is the most-derived non-supplemental interface that it implements. The value of the internal [[Prototype]] property of the platform object is the interface prototype object of the primary interface from the platform object’s associated global environment.
The class string of a platform object that implements one or more interfaces MUST be the identifier of the primary interface of the platform object.
If a platform object implements an interface that supports indexed or named properties, the object will appear to have additional properties that correspond to the object’s indexed and named properties. These properties are not “real” own properties on the object, but are made to look like they are by being exposed by the [[GetOwnProperty]] internal method.
However, when the [NamedPropertiesObject] extended attribute has been used, named properties are not exposed on the object but on the interface prototype object itself.
It is permissible for an object to implement multiple interfaces that support indexed properties. However, if so, and there are conflicting definitions as to the object’s supported property indices, or if one of the interfaces is a supplemental interface for the platform object, then it is undefined what additional properties the object will appear to have, or what its exact behavior will be with regard to its indexed properties. The same applies for named properties.
The indexed property getter that is defined on the derived-most interface that the platform object implements is the one that defines the behavior when indexing the object with an array index. Similarly for indexed property setters, deleters and creators. This way, the definitions of these special operations from ancestor interfaces can be overridden.
Platform objects implementing an interface that supports indexed or named properties cannot be fixed; if Object.freeze
, Object.seal
or Object.preventExtensions
is called on one of these objects, these the function
MUST throw a TypeError.
Similarly, an interface prototype object
that exposes named properties due to the use of [NamedPropertiesObject]
also MUST throw a TypeError
if one of the three functions above is called on it.
The name of each property that appears to exist due to an object supporting indexed properties is an array index property name, which is a property name P for which the following algorithm returns true:
The named property visibility algorithm is used to determine if a given named property is exposed on an object. Some named properties are not exposed on an object depending on whether the [OverrideBuiltins] extended attribute was used. The algorithm operates as follows, with property name P and object O:
This should ensure that for objects with named properties, property resolution is done in the following order:
Support for getters is handled by the platform object [[GetOwnProperty]] method defined in section 4.6.2, for creators and setters by the platform object [[DefineOwnProperty]] method defined in section 4.6.3, and for deleters by the platform object [[Delete]] method defined in section 4.6.4.
The internal [[GetOwnProperty]] method of every platform object O that implements an interface which supports indexed or named properties MUST behave as follows when called with property name P:
The internal [[DefineOwnProperty]] method of every platform object O that implements an interface which supports indexed or named properties MUST behave as follows when called with property name P, property descriptor Desc and boolean flag Throw. The term “Reject” is used as defined in section 4.2.24.2 above.
The internal [[Delete]] method of every platform object O that implements an interface which supports indexed or named properties MUST behave as follows when called with property name P and boolean flag Throw. The term “Reject” is used as defined in section 4.2.24.2 above.
The internal [[Call]] method of every platform object O that implements an interface I with at least one legacy caller MUST behave as follows, assuming arg0..n−1 is the list of argument values passed to [[Call]]:
This document does not define a complete property enumeration order for all platform objects implementing interfaces (or for platform objects representing exceptions). However, if a platform object implements an interface that supports indexed or named properties, then properties on the object MUST be enumerated in the following order:
Future versions of the ECMAScript specification may define a total order for property enumeration.
As described in section 3.9 above, callback interfaces can be implemented in script by an ECMAScript object. The following cases determine whether and how a given object is considered to be a user object implementing a callback interface:
A single operation interface is one that:
A user object’s operation is called with a list of IDL argument values idlarg0..n−1 by following the algorithm below. The callback this value is the value to use as the this value when calling the object’s operation implementation internal [[Call]] method. By default, the object itself is used as the callback this value, however this MAY be overridden by other specifications.
Note that ECMAScript objects need not have properties corresponding to constants on them to be considered as user objects implementing interfaces that happen to have constants declared on them.
The value of a user object’s attribute is retrieved using the following algorithm:
The value of a user object’s attribute is set using the following algorithm:
An ECMAScript Function object that is being used as a callback function value is called in a manner similar to how operations on user objects are called (as described in the previous section). The Function object is called with a list of IDL argument values idlarg0..n−1 by following the algorithm below. By default, the callback this value when invoking a callback function is null, unless overridden by other specifications.
For every exception that is not declared with the [NoInterfaceObject] extended attribute, a corresponding property MUST exist on the ECMAScript global object. The name of the property is the identifier of the exception, and its value is an object called the exception interface object, which provides access to any constants that have been associated with the exception. The property has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
The exception interface object for a given exception MUST be a function object.
If any constants have been declared on the exception, then the exception interface object will have properties corresponding to these constants as described in section 4.9.3 below.
The exception interface object MUST also have a property named “prototype” with attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false } whose value is an object called the exception interface prototype object. This object also provides access to the constants that are declared on the exception.
The internal [[Call]] method of an exception interface object MUST behave as follows, assuming arg0..n−1 is the list of argument values passed to the function, and E is the exception corresponding to the exception interface object:
This shadows the “message” property from Error.prototype, whose initial value is the empty string.
There MUST exist an exception interface prototype object for every exception defined, regardless of whether the exception was declared with the [NoInterfaceObject] extended attribute. The exception interface prototype object for a particular exception has properties that correspond to the constants and exception fields defined on the exception. These properties are described in more detail in sections 4.9.3 and 4.9.4, below.
The exception interface prototype object for a given exception MUST have an internal [[Prototype]] property whose value is as follows:
As with interface prototype objects, exception interface prototype objects can be accessible even if declared with [NoInterfaceObject] since it is possible to get the internal [[Prototype]] property of an exception object.
The class string of an exception interface prototype object is the concatenation of the exception’s identifier and the string “Prototype”.
There MUST be a property named “name” on the exception interface prototype object with attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } and whose value is the identifier of the exception.
If an exception is thrown with a specific type, then the rules in section 4.11 below will create a shadowing “name” property on the exception object itself.
If the [NoInterfaceObject] extended attribute was not specified on the exception, then there MUST also be a property named “constructor” on the exception interface prototype object with attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true } and whose value is a reference to the exception interface object for the exception.
For each constant defined on the exception, there MUST be a corresponding property on the exception interface prototype object. The property has the following characteristics:
If there exists an exception interface object for the exception, then it MUST also have a property with the same characteristics.
For each exception field, there MUST be a corresponding property on the exception interface prototype object, whose characteristics are as follows:
Objects representing particular IDL exceptions are platform objects. Such objects can only represent a single exception, and also cannot simultaneously represent an exception and implement an interface.
Every platform object representing an exception in ECMAScript is associated with a global environment, just
as the initial objects are.
When an exception object is created by calling an exception interface object,
either normally or as part of a new
expression, then the global environment
of the newly created object is associated with MUST be the same as for the
interface object itself.
The value of the internal [[Prototype]] property of the exception object MUST be the exception interface prototype object from the global environment the exception object is associated with.
The class string of the exception object MUST be the identifier of the exception.
Objects representing predefined exceptions are simply native ECMAScript objects of the corresponding type.
First, we define the current global environment as the result of running the following algorithm:
When an IDL exception or predefined exception E is to be thrown, with optional type T and optional message M, the following steps MUST be followed:
The above algorithm does not restrict platform objects representing exceptions propagating out of a Function to be ones that are associated with the global environment where that Function object originated. For example, consider the IDL:
exception NumberError { };
interface A {
/**
* Calls computeSquareRoot on m, passing x as its argument.
*/
float doComputation(MathUtils m, float x);
};
interface MathUtils {
/**
* If x is negative, throws a NumberError exception. Otherwise, returns
* the square root of x.
*/
float computeSquareRoot(float x);
};
If we pass a MathUtils object from a different global environment to doComputation, then the exception thrown will be from that global environment:
var a = getA(); // An A object from this global environment.
var m = otherWindow.getMathUtils(); // A MathUtils object from a different global environment.
a instanceof Object; // Evaluates to true.
m instanceof Object; // Evaluates to false.
m instanceof otherWindow.Object; // Evaluates to true.
try {
a.doComputation(m, -1);
} catch (e) {
e instanceof NumberError; // Evaluates to false.
e instanceof otherWindow.NumberError; // Evaluates to true.
}
Any requirements in this document to throw an instance of an ECMAScript built-in Error MUST use the built-in from the current global environment.
None of the algorithms or processing requirements in the ECMAScript language binding catch ECMAScript exceptions. Whenever an ECMAScript Function is invoked due to requirements in this section and that Function ends due to an exception being thrown, that exception MUST propagate to the caller, and if not caught there, to its caller, and so on.
The following IDL fragment
defines two interfaces
and an exception.
The valueOf
attribute on ExceptionThrower
is defined to throw an exception whenever an attempt is made
to get its value.
interface Dahut {
attribute DOMString type;
};
exception SomeException {
};
interface ExceptionThrower {
// This attribute always throws a SomeException and never returns a value.
attribute long valueOf;
};
Assuming an ECMAScript implementation supporting this interface, the following code demonstrates how exceptions are handled:
var d = getDahut(); // Obtain an instance of Dahut.
var et = getExceptionThrower(); // Obtain an instance of ExceptionThrower.
try {
d.type = { toString: function() { throw "abc"; } };
} catch (e) {
// The string "abc" is caught here, since as part of the conversion
// from the native object to a string, the anonymous function
// was invoked, and none of the [[DefaultValue]], ToPrimitive or
// ToString algorithms are defined to catch the exception.
}
try {
d.type = { toString: { } };
} catch (e) {
// An exception is caught here, since an attempt is made to invoke
// [[Call]] on the native object that is the value of toString
// property.
}
d.type = et;
// An uncaught SomeException exception is thrown here, since the
// [[DefaultValue]] algorithm attempts to get the value of the
// "valueOf" property on the ExceptionThrower object. The exception
// propagates out of this block of code.
This section specifies some common definitions that all conforming implementations MUST support.
typedef unsigned long long DOMTimeStamp;
The DOMTimeStamp type is used for representing a number of milliseconds, either as an absolute time (relative to some epoch) or as a relative amount of time. Specifications that use this type will need to define how the number of milliseconds is to be interpreted.
callback Function = any (any... arguments);
The Function callback function type is used for representing function values with no restriction on what arguments are passed to it or what kind of value is returned from it.
callback VoidFunction = void ();
The VoidFunction callback function type is used for representing function values that take no arguments and do not return any value.
This section is informative.
Extensions to language binding requirements can be specified using extended attributes that do not conflict with those defined in this document. Extensions for private, project-specific use should not be included in IDL fragments appearing in other specifications. It is recommended that extensions that are required for use in other specifications be coordinated with the group responsible for work on Web IDL, which at the time of writing is the W3C Web Applications Working Group, for possible inclusion in a future version of this document.
Extensions to any other aspect of the IDL language are strongly discouraged.
This section is informative.
It is expected that other specifications that define Web platform interfaces using a conforming IDL fragment will reference this specification. It is suggested that those specifications include a sentence such as the following, to indicate that the IDL is to be interpreted as described in this specification:
The IDL fragment in Appendix A of this specification must be interpreted as required for conforming IDL fragments, as described in the “Web IDL” specification. [WEBIDL]
In addition, it is suggested that the conformance class for user agents in referencing specifications be linked to the conforming implementation class from this specification:
A conforming FooML user agent must also be a conforming implementation of the IDL fragment in Appendix A of this specification, as described in the “Web IDL” specification. [WEBIDL]
This section is informative.
The editor would like to thank the following people for contributing to this specification: Glenn Adams, David Andersson, L. David Baron, Art Barstow, Robin Berjon, Marcos Cáceres, Giovanni Campagna, Brendan Eich, Gorm Haug Eriksen, David Flanagan, Aryeh Gregor, Marcin Hanclik, Jed Hartman, Dominique Hazaël-Massieux, Ian Hickson, Björn Höhrmann, Kyle Huey, Dimitry Golubovsky, Kartikaya Gupta, James Graham, Aryeh Gregor, Magnus Kristiansen, Mark Miller, Lachlan Hunt, Oliver Hunt, Jim Jewett, Anne van Kesteren, Jim Ley, Travis Leithead, Kevin Lindsey, 呂康豪 (Kang-Hao Lu), Ms2ger, Andrew Oakley, 岡坂 史紀 (Shiki Okasaka), Olli Pettay, Simon Pieters, Andrei Popescu, Tim Renouf, Alex Russell, Doug Schepers, Jonas Sicking, Garrett Smith, Sam Sneddon, Josh Soref, Maciej Stachowiak, Anton Tayanovskyy, Jeff Walden, Allen Wirfs-Brock, Collin Xu and Boris Zbarsky.
Special thanks also go to Sam Weinig for maintaining this document while the editor was unavailable to do so.
This section defines an LL(1) grammar whose start symbol, Definitions, matches an entire IDL fragment.
Each production in the grammar has on its right hand side either a non-zero sequence of terminal and non-terminal symbols, or an epsilon (ε) which indicates no symbols. Symbols that begin with an uppercase letter are non-terminal symbols. Symbols within quotes are terminal symbols that are matched with the exact text between the quotes. Symbols that begin with a lowercase letter are terminal symbols that are matched by the regular expressions (using Perl 5 regular expression syntax [PERLRE]) as follows:
integer | = | -?(0([0-7]*|[Xx][0-9A-Fa-f]+)|[1-9][0-9]*) |
float | = | -?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+) |
identifier | = | [A-Z_a-z][0-9A-Z_a-z]* |
string | = | "[^"]*" |
whitespace | = | [\t\n\r ]+|[\t\n\r ]*((//.*|/\*.*?\*/)[\t\n\r ]*)+ |
other | = | [^\t\n\r 0-9A-Z_a-z] |
The tokenizer operates on a sequence of Unicode characters [UNICODE]. When tokenizing, the longest possible match MUST be used. For example, if the input text is “a1”, it is tokenized as a single identifier, and not as a separate identifier and integer. If the longest possible match could match both an identifier and one of the quoted terminal symbols from the grammar, it MUST be tokenized as the quoted terminal symbol. Thus, the input text “long” is tokenized as the quoted terminal symbol "long" rather than an identifier called “long”.
The IDL syntax is case sensitive, both for the quoted terminal symbols used in the grammar and the values used for identifier terminals. Thus, for example, the input text “Const” is tokenized as an identifier rather than the quoted terminal symbol "const", an interface with identifier “A” is distinct from one named “a”, and an extended attribute [constructor] will not be recognized as the [Constructor] extended attribute.
Implicitly, the whitespace terminal is allowed between every terminal in the input text being parsed. Such whitespace terminals, which actually encompass both whitespace and comments, are ignored while parsing.
The following LL(1) grammar, starting with Definitions, matches an IDL fragment:
The Other non-terminal matches any single terminal symbol except for "(", ")", "[", "]", "{", "}" and ",".
While the ExtendedAttribute non-terminal matches any non-empty sequence of terminal symbols (as long as any parentheses, square brackets or braces are balanced, and the "," token appears only within those balanced brackets), only a subset of those possible sequences are used by the extended attributes defined in this specification — see section 3.11 for the syntaxes that are used by these extended attributes.
This section is informative.
In order for this document to progress along the W3C Recommendation track to the next stage, Proposed Recommendation, a minimum of three months must have elapsed since the publication of the Candidate Recommendation, and there must be at least two independent, interoperable implementations of each feature. Each feature may be implemented by a different set of products; there is no requirement that all features be implemented by a single product. We define independent, interopable and implementation, similarly to the CSS Working Group’s definitions, as follows:
The official Web IDL test suite will be based on IDL fragments from existing Web specifications. The Working Group will select this set of IDL fragments as follows:
The term feature is used loosely to enable the Working Group to judge how detailed the test suite ought to be.
The following features of Web IDL are considered at risk and may be dropped if they are not in use by any Web specification by the time the test suite is otherwise complete:
This section is informative.
The following is a list of substantial changes to the document on each publication.
Required objects returned from a constructor be associated with the same ECMAScript global environment that the interface object is.
Disallowed both DOMString and primitive types from being in a union type.
Defined sequence and array types to be distinguishable from interface types that support indexed properties, and made the overload resolution algorithm prefer interface types to sequences and arrays.
Allowed dictionaries to be split into partial definitions, and changed the order of dictionary members to be lexicographical instead of appearance order in order to have a defined ordering when partial dictionaries are used.
Renamed “callbacks” to “callback functions” to reduce confusion with “callback interfaces”.
Modified the overload resolution algorithm (and combined it with the argument resolution algorithm) such that it always evaluates arguments from left to right, rather than evaluating first the argument that would definitively resolve the overloading.
Added Function
and VoidFunction
callback common
definitions.
Allowed Infinity
, -Infinity
and NaN
to be specified as values for constants, dictionary members and optional
argument default values.
Changed [TreatNonCallableAsNull] so that it is specified on the callback rather than the attribute, and such that it affects only type conversions done for attributes and not for operation arguments, etc.
Allowed operation arguments to be specified using particular keywords without requiring them to be escaped.
Split the float and double into types that do and do not include non-finite values.
Removed the check on ECMAScript Number to IDL (unsigned) long long values that the value is within the range of continguously representable integers, since that behavior can be had by using [EnforceRange].
Added direct links to an unofficial HTML version of the ECMAScript spec, and updated the reference to ECMAScript 5.1.
Forbade static operations from being declared on callback interfaces.
Removed extraneous Optional production from the grammar.
Allow default values to be specified for optional operation arguments.
Rename [ReplaceableNamedProperties] to [NamedPropertiesObject] and make it so that the named properties for an interface annotated with this extended attribute are exposed a separate object in the prototype chain just above the interface’s prototype object.
Fix the ECMAScript operation invocation algorithm so that it works for static operations.
Try to clarify platform versus user objects.
Tighten up the conversion rules from ECMAScript values to IDL values, so that they are more in line with the values accepted by the overload resolution algorithm.
Changed the handling of undefined in ECMAScript
operation calls so that they are not unconditionally treated as missing
optional arguments. Now, [TreatUndefinedAs=Missing]
must be
placed on those arguments to allow this behavior.
Disallowed static operations from having the same identifier as a regular operation on the same interface.
Dropped the [Callback] extended attribute and made callback interfaces and callbacks (for single functions) base IDL language level features. User objects now may only implement callback interfaces, and platform objects may only implement non-callback interfaces.
Redesigned overloading to avoid having to pay attention to the order that overloads appear in the IDL. DOMString and primitive types are no longer distinguishable, but non-callback interfaces, dictionaries, sequence types, array types and Date are now distinguishable. Dropped [AllowAny], which is no longer needed since DOMString will be selected automatically when there is not an exact match when invoking an overloaded operation.
Added union types.
Added string enumerations.
Specified class strings for interface prototype objects and exception interface prototype objects and removed them from interface objects and exception interface objects.
Removed requirements for particular [[Class]] internal property values and instead required custom behavior from Object.prototype.toString.
Allowed [OverrideBuiltins] and [ReplaceableNamedProperties] to be placed on partial interface definitions.
Split out the Java language binding into its own document.
Removed string constants, since they are unneeded currently.
Allowed specifications to state that certain interfaces or exceptions are not to be exposed by particular ECMAScript global environments.
Changed the [Prefix] extended attribute to [JavaPrefix] and moved it to be in the Java language binding. It now takes a dotted name instead of a scoped name.
Removed modules and [NamespaceObject].
Allowed extended attributes to be specified as part of a typedef, so that those extended attributes will apply to any construct that uses the typedef.
Added predefined exception types corresponding to the ECMAScript error types.
An exception is now thrown if an ECMAScript Number is passed to a platform object expecting a long long or unsigned long long and the Number is outside the range of contiguous exactly-representable integers.
Added [LenientThis].
Disallowed overloading that distinguishes between two interface types where one is an inherited interface of the other.
Disallowed overloading across separate interface and partial interface definitions.
Removed the ability for specifications to disambiguate overloaded operation calls for cases that are still technically distinguishable, such as distinguishing based on interface type. Also defined that otherwise ambiguous calls involving interface types are resolved by selecting the overload that appears earliest on the interface.
Changed exceptions to have an intrinsic type, and added recommendations to specification authors on how to name exception types.
Changed inherits getter
to inherit
.
Renamed “callers” to “legacy callers” to discourage their use.
Added [EnforceRange] which will cause an exception to be thrown if an ECMAScript Number is out of range (after rounding).
Tweaked [Clamp] so that it rounds to nearest rather than floors.
Recommend against using [NoInterfaceObject] for non-supplemental interfaces.
Added [ArrayClass].
Made trailing ECMAScript undefined values in function calls be equivalent to missing optional parameters.
Removed [CopyInheritedPrototype].
Made the length property on platform array objects non-configurable.
Removed omittable
, since nobody is using it (and probably won’t,
unless considering non-ECMAScript language bindings). Instead, identifierless
special operations will map to methods with special names in the Java
language binding, rather than being left out altogether.
Disallows [NoInterfaceObject] on interfaces that have static operations.
Removed named properties “resolved before prototype properties”.
Made ECMAScript namespace object properties enumerable.
Removed raises, setraises and getraises clauses since they do not add any value.
Added the [TreatNonCallableAsNull] extended attribute.
Made type conversion from an ECMAScript non-object value to an IDL dictionary value throw an exception.
Specified that the “prototype” property of a named constructor has the same value as the one on the interface object.
Specify [[Call]] for operations and add an [ImplicitThis] extended attribute for use on Window.
Tweaked the names of Java getter and setter methods to avoid conflicts with other interface members.
Disallowed definitions with special ECMAScript property names and if they begin with a leading underscore.
Modified the overload resolution algorithm so that it works with sequence types.
Disallows consequential interfaces from defining interface members whose identifiers are the same as any of those on the original interface.
Renamed “name getter”, “index getter” and friends to “named property getter”, “indexed property getter” and so on, since that’s a more accurate description of what they are.
Removed the optional in
keyword from arguments, since it serves no
useful purpose.
Added some green boxes illustrating the syntax of the different IDL constructs.
Added IDL syntax to declare that a writable attribute inherits its getter behavior from a read only attribute of the same name in on an ancestor interface.
Made all interface objects be Function objects, regardless of whether they have a constructor.
Added the notion of named properties being “resolved before prototype properties” to handle the Window object’s odd treatment of named properties.
Specified attributes of ECMAScript properties corresponding to stringifiers, making them non-enumerable.
Introduced the terms “platform object” and “user object” to distinguish between objects provided by the implementation and those created and supplied by the user of an API. Most of mentions of ECMAScript native objects were replaced with “user object” and host objects with “platform object”. Specific requirements on what ECMAScript objects can be passed to platform objects expecting non-[Callback] interface types are now given.
Added an [Unforgeable] extended attribute to require properties corresponding to IDL attributes be non-configurable and to appear as own properties on the object rather than on the prototype.
Allowed [Callback] interfaces to inherit from other [Callback] interfaces.
Removed array host object prototype objects, since they didn’t have any useful properties on them. Instead, the [[Prototype]] of array host objects are now required to be the Array prototype object.
Added a [CopyInheritedPrototype] extended attribute.
Added support for partial interface definitions.
Removed mixin prototype objects from the ECMAScript binding. At the IDL level, objects may now only implement a single inheritance hierarchy of interfaces, plus any supplemental interfaces that are required due to “implements” statements. Interface prototype objects for interfaces on the left-hand side of an “implements” statement now also get properties for members of the interface on the right-hand side of the statement.
Tweaked the ECMAScript overload resolution algorithm so that passing too few arguments will result in an exception being thrown and passing more arguments than the longest overload will mean those extra arguments will be ignored. Distinguishing which overload is called when the overloads have the same argument list length is now performed only on arguments where across all of the overloads, not all of the types at that position are the same.
Added a [ReplaceableNamedProperties] extended attribute to control whether named properties on an object can be replaced by assigning to them.
Required that ECMAScript host objects that support indexed and named properties and for array host objects refuse to be fixed.
Removed the “toString” property from array host objects, so that the one inherited from the Array prototype object is used instead.
Changed the implementation requirements for ECMAScript host objects that support indexed and named properties, and for array host objects, to use specific [[GetOwnProperty]] and [[DefineOwnProperty]] behavior, instead of in terms of setting and removing own properties on the object.
Disallowed sequence and dictionary types from being used as an array element type.
Added a [Clamp] extended attribute to control how ECMAScript Number values are converted to IDL integer values.
Added the dictionary type and allowed null to be specified as the value of a constant or the default value of a dictionary member.
Added a Date IDL type.
Point out that special operations for indexed and named properties can be overridden.
Added requirements on the property enumeration order for indexed and named properties.
Required that multiple ECMAScript global environments have independent copies of interface objects, interface prototype objects, etc., and defined which global environment’s objects are used when an exception is thrown.
Disallowed sequence types from being used as attribute types.
Removed null from the set of values for interface types, object and array types, allowed those types to be nullable, and updated the overload resolution algorithm to account for these changes.
Made calling an ECMAScript Function that corresponds to an IDL operation throw a TypeError if the this value isn’t an object that implements the right interface.
Add constructors to Java classes corresponding to IDL exceptions.
Define what it means to throw an IDL exception with a given message.
Added “constructor” properties back to interface prototype objects.
Allowed exceptions to inherit from other exceptions, so that they can be more consistent with native ECMAScript errors and so that we can move away from defining and using integer exception codes.
Required that when calling an ECMAScript Function that corresponds to an IDL interface, the argument values are converted to IDL values in order from left to right.
Made properties corresponding to operations enumerable.
Changed the interface object and exception interface object properties on the global object to be configurable.
Added a signed 8 bit integer types named byte.
Expanded the allowable types for constants to include DOMString and nullable primitives.
Added support for static operations.
Fixed errors in the float and integer grammar terminals.
Added productions for array types to the grammar, which were missing.
Added a section for common IDL definitions that all conforming implementations must support, the first entry in which is a definition for the DOMTimeStamp type.
Made constructors due to [Constructor] and
[NamedConstructor] callable. Their behavior
when called is the same as when used in a new
expression.
Updated the ECMAScript language binding to target ECMAScript 5th edition, the biggest part of which is that now interface attributes are implemented as accessor properties.
Ensure that corresponding properties do not exist for constants, attributes and operations named “constructor” or “toString” if they would conflict with other requirements to have properties with those names.
Moved properties corresponding to attributes from host object instances to their interface prototype objects. Similarly, moved properties corresponding to exception fields from host exception objects to their exception interface prototype objects.
Disallow both [PutForwards] and [Replaceable] appearing on the same attribute.
Required that callable objects corresponding to operations be Function objects.
Changed the “constructor” property on interface prototype objects to be writable.
Changed the “prototype” property on interface and exception objects be non-enumerable.
Allowed callers to be overloaded.
Defined the “length” property on Function objects that correspond to operations and constructors.
Changed sequences to be passed by value, and added an array type for ordered lists of values that are passed by reference.
Removed interface forward declarations and the requirement that interfaces be declared before use.
Made the in
keyword in argument lists optional.
Changed the Object
,
TRUE
and FALSE
keywords to be all lowercase.
Dropped [Optional] and [Variadic]
in favor of optional
and ...
syntax.
Dropped [ImplementedOn] in favor of an
implements
statement.
Dropped [ExceptionConsts] in favor of allowing constants to be defined directly on exceptions. Defining constants on modules is now disallowed.
Changed [Constructor] and [PutForwards] to be an ECMAScript-specific extended attribute.
Turned [Callable],
[IndexGetter],
[IndexSetter],
[IndexCreator],
[IndexDeleter],
[NameGetter],
[NameSetter],
[NameCreator],
[NameDeleter] and
[Stringifies] into real Web IDL syntax
using caller
, getter
, setter
,
creator
, deleter
and stringifier
.
Dropped [NoIndexingOperations] in favor of
an omittable
keyword that can be used on the above
six special operations.
Removed boxed valuetypes and replaced them with the concept of nullable types.
Added [NamespaceObject] to allow reflecting module hierarchies in ECMAScript.
Disallowed specifying [Callback] on
interfaces that do not match the criteria for interfaces that
can be implemented by native objects, and disallowed the use
of the FunctionOnly
and
PropertyOnly
identifiers unless
the interface has only a single operation (or multiple operations,
as long as they all have the same identifier).
Made corresponding indexed properties and ECMAScript properties for operations enumerable.
Outlawed having both [NoInterfaceObject] and [Constructor] on an interface.
Required that identical mixin prototype objects are in fact the same object.
Renamed [Null] and [Undefined] to [TreatNullAs] and [TreatUndefinedAs]. They are now honored when values are returned from native object implemented operations and attributes.
Added algorithms for getting and setting values of attributes on native object implementations of interfaces.
Added [OverrideBuiltins], which makes name getters prefer named properties instead of properties on the object itself.
Fixed bugs in the host object [[Put]] algorithm (now [[DefineOwnProperty]]) so that name and index creators are actually invoked, and restructured it as well as the host object [[Delete]] algorithm so that they are easier to read.
Provided language binding independent advice on handling user implemented interfaces that throw exceptions or return values of inappropriate types.
Renamed the awkwardly worded “object implementing an interface” type to “interface type”.
Added an [AllowAny] ECMAScript-specific extended attribute on operation arguments, which indicates that any type of ECMAScript value is allowed to be passed to that argument.
Changed the definition of the effective overload set to take into account the number of arguments passed, so that it can be used to resolve overloaded calls properly in the presence of variadic operations.
Removed DOMString from the list of primitive types, removed null from its set of values, and allowed it to be distinguished from primitive types in the overload resolution algorithm. The [Callback] extended attribute is now also taken into account when a native object is passed as an argument.
Defined exception handling for algorithms that call in to user ECMAScript code.
Added an algorithm for converting a sequence of 16 bit unsigned integer code units into a sequence of Unicode characters.
Added a double type for double precision floating point numbers.
Define [[Class]] for host objects that implement a single interface, regardless of whether it is annotated with [PrototypeRoot].
Added a [NoIndexingOperations] extended attribute to indicate that operations annotated with named property or indexed property extended attributes won’t result in functions, if the language binding supports object indexing.
Changed the way extended attributes are parsed in the grammar and filled out the Extensibility section to mention how extended attributes not defined in this document can be used.
Fixed some bugs in the rules for converting float and unsigned long long to ECMAScript Number values, and vice versa.
Added [Prefix] to change the default mapping of modules to language binding namespacing constructs.
Allowed interfaces with constants to be implemented by ECMAScript native objects. This specifically allows implementation of a DOM Level 2 Traversal NodeFilter object in script.
Added a [Callable] extended attribute, which can be used to indicate the behavior of calling an object as a function.
Removed a bogus requirement that [PutForwards] identify an attribute whose type is the same as the attribute that has the [PutForwards], and disallowed cycles of forwarding assignments.
Added a [Replaceable] extended attribute that can be placed on an attribute to indicate that the corresponding ECMAScript property can be replaced.
Added a requirement that [Stringifies]
not be specified on an interface that also declares an
interface member named toString
.
Changed the DOMString type to be a sequence of 16 bit code units, rather than a sequence of Unicode characters.
Reworded the ECMAScript type mapping section so that it can be more easily referenced from other sections of the document.
Renamed [NativeObject] to
[Callback], and gave it an
additional PropertyOnly
argument.
Added an [Optional] extended attribute to make certain kinds of operation overloading able to be specified more succinctly.
Reworked operation overloading in IDL so that it is much more restrictive. Updated the overloaded operation and constructor resolution in ECMAScript accordingly.
Specified the behavior of index and name getters in ECMAScript as being in terms of additional properties that are placed on the host object. Added [IndexCreator], [IndexDeleter], [NameCreator] and [NameDeleter] to handle more aspects of these properties. The definition of [[Get]] for host objects is removed, but [[Put]] is expanded to handle index and name creators/setters, and [[Delete]] is now specified to handle index and name deleters.
Specified the value of [[Class]] for host objects.
Removed the suggestion to perform tricksy multiple inheritance simulation in ECMAScript with a mandated way to map multiple inheritance into a single inheritance prototype chain. Added [ImplementedOn] and [PrototypeRoot] to help with this.
Made an explicit mention of the Web Interface Definition Language (WIDL) W3C Member submission in the Status of this Document section.
Added an [NamedConstructor] extended attribute
to handle peculiarities like HTML5’s Image
constructor.
[Constructor] extended attributes may now take an argument list, and more than one can be used on an interface.
Added a [NativeObject] extended attribute that restricts which interfaces may be implemented by ECMAScript native objects, and updated the “Native objects implementing interfaces” section to be more restricted and precise.
Moved [NoInterfaceObject] into the ECMAScript-specific extended attributes section.
Fixed errors in a couple of algorithms that were introduced by steps being renumbered.
Properties corresponding to IDL constants are now ReadOnly.
Removed [NoNull], and added [Null] and [Undefined] in its place.
Made DOMString an intrinsic type, but still allow it to be defined as a boxed sequence of unsigned shorts for compatibility with already published IDL fragments.
ECMAScript host object constructors (specified with [Constructor]) now must return an object that implements the interface.
Tweaked the abstract and introduction so that it is clear that Web IDL can be used for specifications that define not only a DOM, but any interface.
Clarified the behavior of passing a non-null, non-Object value to a host object that expects a boxed valuetype.
Renamed document to Web IDL.
Restricted boxed valuetypes to boxing only types that cannot already have null.
Reworked how operation overloading is specified (the [Overloads] extended attribute is no longer needed), and how ECMAScript disambiguates calls to overloaded operations.
Filled in the “Host exception objects” section.
Added an exception interface prototype object for constants to live in. Added constants to interface objects, interface prototype objects, exception interface objects and exception interface prototype objects.
Tweaked the behavior of sequences in ECMAScript.
Added an editorial note about the possibility of somehow
specifying HTML5’s Image
constructor.
Added a [NoInterfaceObject] extended attribute, which prevents an ECMAScript interface object being created for the interface on which it appears.
Added a [Stringifies] extended attribute.
Fixed small bugs in [[HasProperty]], [[Get]] and [[Put]] algorithms for ECMAScript host objects.
Added an editorial note about the possibility of an extended attribute that specifies what properties get enumerated in a for..in loop in ECMAScript.
Initial publication.