1. Introduction
This section is informative.
This standard defines an interface definition language, Web IDL, that can be used to describe interfaces that are intended to be implemented in web browsers. Web IDL is an IDL variant with a number of features that allow the behavior of common script objects in the web platform to be specified more readily. How interfaces described with Web IDL correspond to constructs within JavaScript execution environments is also detailed here.
Concretely, Web IDL provides a syntax for specifying the surface APIs of web platform objects, as well as JavaScript bindings that detail how those APIs manifest as JavaScript constructs. This ensures common tasks, such as installing global properties, processing numeric inputs, or exposing iteration behavior, remain uniform across web platform specifications: such specifications describe their interfaces using Web IDL, and then use prose to specify API-specific details.
The term "JavaScript" is used to refer to ECMA-262, rather than the official term ECMAScript, since the term JavaScript is more widely known.
2. Interface definition language
This section describes a language, Web IDL, which can be used to define
interfaces for APIs in the Web platform. A specification that defines Web APIs
can include one or more IDL fragments that
describe the interfaces (the state and behavior that objects can exhibit)
for the APIs defined by that specification.
An IDL fragment is
a sequence of definitions that matches the
The different kinds of definitions that can appear in an IDL fragment are: interfaces, partial interface definitions, interface mixins, partial mixin definitions, callback functions, callback interfaces, namespaces, partial namespace definitions, dictionaries, partial dictionary definitions, typedefs and includes statements. These are all defined in the following sections.
Each definition
(matching
[extended_attributes ]interface identifier { /* interface_members... */ };
Definitions ::ExtendedAttributeList Definition Definitions ε
Definition ::CallbackOrInterfaceOrMixin Namespace Partial Dictionary Enum Typedef IncludesStatement
The following is an example of an IDL fragment.
[Exposed =Window ]interface Paint { }; [Exposed =Window ]interface SolidColor :Paint {attribute double red ;attribute double green ;attribute double blue ; }; [Exposed =Window ]interface Pattern :Paint {attribute DOMString imageURL ; }; [Exposed =Window ]interface GraphicalWindow {constructor ();readonly attribute unsigned long width ;readonly attribute unsigned long height ;attribute Paint currentPaint ;undefined drawRectangle (double x ,double y ,double width ,double height );undefined drawText (double x ,double y ,DOMString text ); };
Here, four interfaces
are being defined.
The GraphicalWindow
interface has two
read only attributes,
one writable attribute, and two operations
defined on it. Objects that implement the GraphicalWindow
interface
will expose these attributes and operations in a manner appropriate to the
particular language being used.
In JavaScript, the attributes on the IDL interfaces will be exposed as accessor
properties and the operations as data properties whose value is a built-in function object on a
prototype object for all GraphicalWindow
objects; each JavaScript object that implements GraphicalWindow
will have that prototype object in its prototype chain.
The constructor operation that appears on GraphicalWindow
causes a constructor to exist in JavaScript implementations,
so that calling new GraphicalWindow()
would return a new object
that implemented the interface.
All interfaces have the [Exposed
] extended attribute, which ensures the interfaces
are only available in realms whose global object is a Window
object.
2.1. Names
Every interface,
partial interface definition,
namespace,
partial namespace definition,
dictionary,
partial dictionary definition,
enumeration,
callback function,
callback interface and
typedef (together called named definitions)
and every constant,
attribute,
and dictionary member has an
identifier, as do some
operations.
The identifier is determined by an
-
For named definitions, the
identifier token that appears directly after theinterface ,namespace ,dictionary ,enum orcallback keyword determines the identifier of that definition.interface interface_identifier { /* interface_members... */ };partial interface interface_identifier { /* interface_members... */ };namespace namespace_identifier { /* namespace_members... */ };partial namespace namespace_identifier { /* namespace_members... */ };dictionary dictionary_identifier { /* dictionary_members... */ };partial dictionary dictionary_identifier { /* dictionary_members... */ };enum enumeration_identifier {"enum" ,"values" /* , ... */ };callback callback_identifier =return_type (/* arguments... */);callback interface callback_interface_identifier { /* interface_members... */ }; -
For attributes, typedefs and dictionary members, the final
identifier token before the semicolon at the end of the declaration determines the identifier.[
extended_attributes ]interface identifier {attribute type attribute_identifier ; };typedef type typedef_identifier ;dictionary identifier {type dictionary_member_identifier ; }; -
For constants, the
identifier token before the equals sign determines the identifier.const type constant_identifier = 42; -
For operations, the
identifier token that appears after the return type but before the opening parenthesis (that is, one that is matched as part of theOptionalOperationName grammar symbol in anOperationRest ) determines the identifier of the operation. If there is no suchidentifier token, then the operation does not have an identifier.interface interface_identifier {return_type operation_identifier (/* arguments... */); };
Note: Operations can have no identifier when they are being used to declare a special kind of operation, such as a getter or setter.
For all of these constructs, the identifier
is the value of the
Note: A leading U+005F (_) is used to escape an identifier from looking
like a reserved word so that, for example, an interface named "interface
" can be
defined. The leading U+005F (_) is dropped to unescape the
identifier.
Operation arguments can take a slightly wider set of identifiers. In an operation
declaration, the identifier of an argument is specified immediately after its
type and is given by either an
interface interface_identifier {return_type operation_identifier (argument_type argument_identifier /* , ... */); };
ArgumentNameKeyword ::attribute callback const constructor deleter dictionary enum getter includes inherit interface iterable maplike mixin namespace partial readonly required setlike setter static stringifier typedef unrestricted
If an
The identifier of any of the abovementioned
IDL constructs (except operation arguments) must not be "constructor
",
"toString
",
or begin with a U+005F (_). These
are known as reserved identifiers.
Although the "toJSON
" identifier is not a reserved identifier,
it must only be used for regular operations
that convert objects to JSON types,
as described in § 2.5.3.1 toJSON.
Note: Further restrictions on identifier names for particular constructs can be made in later sections.
Within the set of IDL fragments that a given implementation supports, the identifier of every interface, namespace, dictionary, enumeration, callback function, callback interface and typedef must not be the same as the identifier of any other interface, namespace, dictionary, enumeration, callback function, callback interface or typedef.
Within an IDL fragment, a reference to a definition need not appear after the declaration of the referenced definition. References can also be made across IDL fragments.
Therefore, the following IDL fragment is valid:
[Exposed =Window ]interface B :A {undefined f (SequenceOfLongs x ); }; [Exposed =Window ]interface A { };typedef sequence <long >SequenceOfLongs ;
The following IDL fragment demonstrates how identifiers are given to definitions and interface members.
// Typedef identifier: "number"typedef double number ; // Interface identifier: "System" [Exposed =Window ]interface System { // Operation identifier: "createObject" // Operation argument identifier: "interface"object createObject (DOMString _interface ); // Operation argument identifier: "interface"sequence <object >getObjects (DOMString interface ); // Operation has no identifier; it declares a getter.getter DOMString (DOMString keyName ); }; // Interface identifier: "TextField" [Exposed =Window ]interface TextField { // Attribute identifier: "const"attribute boolean _const ; // Attribute identifier: "value"attribute DOMString ?_value ; };
Note that while the second attribute
on the TextField
interface
need not have been escaped with an underscore (because "value
" is
not a keyword in the IDL grammar), it is still unescaped
to obtain the attribute’s identifier.
2.2. Interfaces
IDL fragments are used to
describe object oriented systems. In such systems, objects are entities
that have identity and which are encapsulations of state and behavior.
An interface is a definition (matching
[extended_attributes ]interface identifier { /* interface_members... */ };
An interface is a specification of a set of
interface members
(matching
Interfaces in Web IDL describe how objects that implement the interface behave. In bindings for object oriented languages, it is expected that an object that implements a particular IDL interface provides ways to inspect and modify the object’s state and to invoke the behavior described by the interface.
An interface can be defined to inherit from another interface. If the identifier of the interface is followed by a U+003A (:) and an identifier, then that identifier identifies the inherited interface. An object that implements an interface that inherits from another also implements that inherited interface. The object therefore will also have members that correspond to the interface members from the inherited interface.
interface identifier :identifier_of_inherited_interface { /* interface_members... */ };
The order that members appear in has significance for property enumeration in the JavaScript binding.
Interfaces may specify an interface member that has the same name as one from an inherited interface. Objects that implement the derived interface will expose the member on the derived interface. It is language binding specific whether the overridden member can be accessed on the object.
Consider the following two interfaces.
[Exposed =Window ]interface A {undefined f ();undefined g (); }; [Exposed =Window ]interface B :A {undefined f ();undefined g (DOMString x ); };
In the JavaScript language binding, an instance of B
will have a prototype chain that looks like the following:
[Object.prototype: the Object prototype object] ↑ [A.prototype: interface prototype object for A] ↑ [B.prototype: interface prototype object for B] ↑ [instanceOfB]
Calling instanceOfB.f()
in JavaScript will invoke the f defined
on B
. However, the f from A
can still be invoked on an object that implements B
by
calling A.prototype.f.call(instanceOfB)
.
The inherited interfaces of a given interface A is the set of all interfaces that A inherits from, directly or indirectly. If A does not 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 includes statement can be used to define that objects implementing an interface A will always also include the members of the interface mixins A includes.
Each interface member can be preceded by a list of extended attributes (matching
[extended_attributes ]interface identifier { [extended_attributes ]const type constant_identifier = 42; [extended_attributes ]attribute type identifier ; [extended_attributes ]return_type identifier (/* arguments... */); };
The IDL for interfaces can be split into multiple parts by using
partial interface definitions
(matching
interface SomeInterface { /* interface_members... */ };partial interface SomeInterface { /* interface_members... */ };
Note: Partial interface definitions are intended for use as a specification editorial aide, allowing the definition of an interface to be separated over more than one section of the document, and sometimes multiple documents.
The order of appearance of an interface definition and any of its partial interface definitions does not matter.
Note: A partial interface definition cannot specify that the interface inherits from another interface. Inheritance is to be specified on the original interface definition.
The relevant language binding determines how interfaces correspond to constructs in the language.
The following extended attributes are applicable to interfaces:
[CrossOriginIsolated
],
[Exposed
],
[Global
],
[LegacyFactoryFunction
],
[LegacyNoInterfaceObject
],
[LegacyOverrideBuiltIns
],
[LegacyWindowAlias
], and
[SecureContext
].
The following extended attributes are applicable to partial interfaces:
[CrossOriginIsolated
],
[Exposed
],
[LegacyOverrideBuiltIns
], and
[SecureContext
].
Interfaces must be annotated with an [Exposed
] extended attribute.
The qualified name of an interface interface is defined as follows:
-
Let identifier be the identifier of interface.
-
If interface has a [
LegacyNamespace
] extended attribute, then:-
Let namespace be the identifier argument of the [
LegacyNamespace
] extended attribute. -
Return the concatenation of « namespace, identifier » with separator U+002E (.).
-
-
Return identifier.
CallbackOrInterfaceOrMixin ::callback CallbackRestOrInterface interface InterfaceOrMixin
InterfaceOrMixin ::InterfaceRest MixinRest
InterfaceRest ::identifier Inheritance { InterfaceMembers } ;
Partial ::partial PartialDefinition
PartialDefinition ::interface PartialInterfaceOrPartialMixin PartialDictionary Namespace
PartialInterfaceOrPartialMixin ::PartialInterfaceRest MixinRest
PartialInterfaceRest ::identifier { PartialInterfaceMembers } ;
InterfaceMembers ::ExtendedAttributeList InterfaceMember InterfaceMembers ε
InterfaceMember ::PartialInterfaceMember Constructor
PartialInterfaceMembers ::ExtendedAttributeList PartialInterfaceMember PartialInterfaceMembers ε
PartialInterfaceMember ::Const Operation Stringifier StaticMember Iterable AsyncIterable ReadOnlyMember ReadWriteAttribute ReadWriteMaplike ReadWriteSetlike InheritAttribute
Inheritance ::: identifier ε
The following IDL fragment
demonstrates the definition of two mutually referential interfaces.
Both Human
and Dog
inherit from Animal
. Objects that implement
either of those two interfaces will thus have a name
attribute.
[Exposed =Window ]interface Animal {attribute DOMString name ; }; [Exposed =Window ]interface Human :Animal {attribute Dog ?pet ; }; [Exposed =Window ]interface Dog :Animal {attribute Human ?owner ; };
The following IDL fragment defines simplified versions of a DOM interfaces and a callback interface.
[Exposed =Window ]interface Node {readonly attribute DOMString nodeName ;readonly attribute Node ?parentNode ;Node appendChild (Node newChild );undefined addEventListener (DOMString type ,EventListener listener ); };callback interface EventListener {undefined handleEvent (Event event ); };
Plain objects can implement a callback interface like
EventListener
:
var node= getNode(); // Obtain an instance of Node. var listener= { handleEvent: function ( event) { // ... } }; node. addEventListener( "click" , listener); // This works. node. addEventListener( "click" , function () { ... }); // As does this.
It is not possible for such an object to implement an interface like
Node
, however:
var node= getNode(); // Obtain an instance of Node. var newNode= { nodeName: "span" , parentNode: null , appendChild: function ( newchild) { // ... }, addEventListener: function ( type, listener) { // ... } }; node. appendChild( newNode); // This will throw a TypeError exception.
2.3. Interface mixins
An interface mixin is a definition (matching
interface mixin identifier { /* mixin_members... */ };
Note: Interface mixins, much like partial interfaces, are intended for use as a specification editorial aide, allowing a coherent set of functionalities to be grouped together, and included in multiple interfaces, possibly across documents. They are not meant to be exposed through language bindings. Guidance on when to choose partial interfaces, interface mixins, or partial interface mixins can be found in § 2.3.1 Using mixins and partials.
An interface mixin is a specification of a set of interface mixin members
(matching
These constants, regular operations, regular attributes, and stringifiers describe the behaviors that can be implemented by an object, as if they were specified on the interface that includes them.
Static attributes, static operations, special operations, and iterable, asynchronously iterable, maplike, and setlike declarations cannot appear in interface mixin declarations.
As with interfaces, the IDL for interface mixins can be split into multiple parts by using
partial interface mixin definitions
(matching
interface mixin SomeMixin { /* mixin_members... */ };partial interface mixin SomeMixin { /* mixin_members... */ };
The order that members appear in has significance for property enumeration in the JavaScript binding.
Note that unlike interfaces or dictionaries, interface mixins do not create types.
Of the extended attributes defined in this specification,
only the [CrossOriginIsolated
], [Exposed
], and [SecureContext
] extended attributes
are applicable to interface mixins.
An includes statement is a definition
(matching
interface_identifier includes mixin_identifier ;
The first identifier must reference a interface I. The second identifier must reference an interface mixin M.
Each member of M is considered to be a member of each interface I, J, K, … that