Web IDL

Living Standard — Last Updated

Participate:
GitHub whatwg/webidl (new issue, open issues)
Chat on Matrix
Commits:
GitHub whatwg/webidl/commits
Snapshot as of this commit
@webidl
Tests:
web-platform-tests webidl/ (ongoing work)
Translations (non-normative):
日本語
简体中文
한국어

Abstract

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.

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 Definitions grammar symbol. The set of IDL fragments that an implementation supports is not ordered. See IDL grammar 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, 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 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 § 2.14 Extended attributes, while those specific to the JavaScript language binding are discussed in § 3.3 Extended attributes.

[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 identifier token somewhere in the declaration:

Note: Operations can have no identifier when they are being used to declare a special kind of operation, such as a getter or setter.

For all of these constructs, the identifier is the value of the identifier token with any leading U+005F (_) removed.

Note: A leading U+005F (_) is used to escape an identifier from looking like a reserved word so that, for example, an interface named "interface" can be defined. The leading U+005F (_) is dropped to unescape the identifier.

Operation arguments can take a slightly wider set of identifiers. In an operation declaration, the identifier of an argument is specified immediately after its type and is given by either an identifier token or by one of the keywords that match the ArgumentNameKeyword symbol. If one of these keywords is used, it need not be escaped with a leading underscore.

interface interface_identifier {
  return_type operation_identifier(argument_type argument_identifier /* , ... */);
};
ArgumentNameKeyword ::
    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 identifier token is used, then the identifier of the operation argument is the value of that token with any leading U+005F (_) removed. If instead one of 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 (except operation arguments) must not be "constructor", "toString", or begin with a U+005F (_). These are known as reserved identifiers.

Although the "toJSON" identifier is not a reserved identifier, it must only be used for regular operations that convert objects to JSON types, as described in § 2.5.3.1 toJSON.

Note: Further restrictions on identifier names for particular constructs can be made in later sections.

Within the set of IDL fragments that a given implementation supports, the identifier of every interface, namespace, dictionary, enumeration, callback function, callback interface and typedef must not be the same as the identifier of any other interface, namespace, dictionary, enumeration, callback function, callback interface or typedef.

Within an IDL fragment, a reference to a definition need not appear after the declaration of the referenced definition. References can also be made across IDL fragments.

Therefore, the following IDL fragment is valid:

[Exposed=Window]
interface B : A {
  undefined f(SequenceOfLongs x);
};

[Exposed=Window]
interface A {
};

typedef sequence<long> SequenceOfLongs;

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

// Typedef identifier: "number"
typedef double number;

// Interface identifier: "System"
[Exposed=Window]
interface System {

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

  // Operation argument identifier: "interface"
  sequence<object> getObjects(DOMString interface);

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

// Interface identifier: "TextField"
[Exposed=Window]
interface TextField {

  // Attribute identifier: "const"
  attribute boolean _const;

  // Attribute identifier: "value"
  attribute DOMString? _value;
};

Note that while the second attribute on the TextField interface need not have been escaped with an underscore (because "value" is not a keyword in the IDL grammar), it is still unescaped to obtain the attribute’s identifier.

2.2. Interfaces

IDL fragments are used to describe object oriented systems. In such systems, objects are entities that have identity and which are encapsulations of state and behavior. An interface is a definition (matching interface InterfaceRest) that declares some state and behavior that an object implementing that interface will expose.

[extended_attributes]
interface identifier {
  /* interface_members... */
};

An interface is a specification of a set of interface members (matching InterfaceMembers). These are the members that appear between the braces in the interface declaration.

Interfaces in Web IDL describe how objects that implement the interface behave. In bindings for object oriented languages, it is expected that an object that implements a particular IDL interface provides ways to inspect and modify the object’s state and to invoke the behavior described by the interface.

An interface can be defined to inherit from another interface. If the identifier of the interface is followed by a U+003A (:) and an identifier, then that identifier identifies the inherited interface. An object that implements an interface that inherits from another also implements that inherited interface. The object therefore will also have members that correspond to the interface members from the inherited interface.

interface identifier : identifier_of_inherited_interface {
  /* interface_members... */
};

The order that members appear in has significance for property enumeration in the JavaScript binding.

Interfaces may specify an interface member that has the same name as one from an inherited interface. Objects that implement the derived interface will expose the member on the derived interface. It is language binding specific whether the overridden member can be accessed on the object.

Consider the following two interfaces.

[Exposed=Window]
interface A {
  undefined f();
  undefined g();
};

[Exposed=Window]
interface B : A {
  undefined f();
  undefined g(DOMString x);
};

In the JavaScript language binding, an instance of B will have a prototype chain that looks like the following:

[Object.prototype: the Object prototype object]
     ↑
[A.prototype: interface prototype object for A]
     ↑
[B.prototype: interface prototype object for B]
     ↑
[instanceOfB]

Calling instanceOfB.f() in JavaScript will invoke the f defined 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.

The list of inclusive inherited interfaces of an interface I is defined as follows:
  1. Let result be « ».

  2. Let interface be I.

  3. While interface is not null:

    1. Append interface to result.

    2. Set interface to the interface that I inherits from, if any, and null otherwise.

  4. Return result.

Note that general multiple inheritance of interfaces is not supported, and objects also cannot implement arbitrary sets of interfaces. Objects can be defined to implement a single given interface A, which means that it also implements all of A’s inherited interfaces. In addition, an includes statement can be used to define that objects implementing an interface A will always also include the members of the