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 interface mixins A includes.

Each interface member can be preceded by a list of extended attributes (matching ExtendedAttributeList), which can control how the interface member will be handled in language bindings.

[extended_attributes]
interface identifier {

  [extended_attributes]
  const type constant_identifier = 42;

  [extended_attributes]
  attribute type identifier;

  [extended_attributes]
  return_type identifier(/* arguments... */);
};

The IDL for interfaces can be split into multiple parts by using partial interface definitions (matching partial interface PartialInterfaceRest). The identifier of a partial interface definition must be the same as the identifier of an interface definition. All of the members that appear on each of the partial interfaces are considered to be members of the interface itself.

interface SomeInterface {
  /* interface_members... */
};

partial interface SomeInterface {
  /* interface_members... */
};

Note: Partial interface definitions are intended for use as a specification editorial aide, allowing the definition of an interface to be separated over more than one section of the document, and sometimes multiple documents.

The order of appearance of an interface definition and any of its partial interface definitions does not matter.

Note: A partial interface definition cannot specify that the interface inherits from another interface. Inheritance is to be specified on the original interface definition.

The relevant language binding determines how interfaces correspond to constructs in the language.

The following extended attributes are applicable to interfaces: [CrossOriginIsolated], [Exposed], [Global], [LegacyFactoryFunction], [LegacyNoInterfaceObject], [LegacyOverrideBuiltIns], [LegacyWindowAlias], and [SecureContext].

The following extended attributes are applicable to partial interfaces: [CrossOriginIsolated], [Exposed], [LegacyOverrideBuiltIns], and [SecureContext].

Interfaces must be annotated with an [Exposed] extended attribute.

The qualified name of an interface interface is defined as follows:

  1. Let identifier be the identifier of interface.

  2. If interface has a [LegacyNamespace] extended attribute, then:

    1. Let namespace be the identifier argument of the [LegacyNamespace] extended attribute.

    2. Return the concatenation of « namespace, identifier » with separator U+002E (.).

  3. 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 MixinRest) that declares state and behavior that can be included by one or more interfaces, and that are exposed by objects that implement an interface that includes the interface mixin.

interface mixin identifier {
  /* mixin_members... */
};

Note: Interface mixins, much like partial interfaces, are intended for use as a specification editorial aide, allowing a coherent set of functionalities to be grouped together, and included in multiple interfaces, possibly across documents. They are not meant to be exposed through language bindings. Guidance on when to choose partial interfaces, interface mixins, or partial interface mixins can be found in § 2.3.1 Using mixins and partials.

An interface mixin is a specification of a set of interface mixin members (matching MixinMembers), which are the constants, regular operations, regular attributes, and stringifiers that appear between the braces in the interface mixin declaration.

These constants, regular operations, regular attributes, and stringifiers describe the behaviors that can be implemented by an object, as if they were specified on the interface that includes them.

Static attributes, static operations, special operations, and iterable, asynchronously iterable, maplike, and setlike declarations cannot appear in interface mixin declarations.

As with interfaces, the IDL for interface mixins can be split into multiple parts by using partial interface mixin definitions (matching partial interface MixinRest). The identifier of a partial interface mixin definition must be the same as the identifier of an interface mixin definition. All of the members that appear on each of the partial interface mixin definitions are considered to be members of the interface mixin itself, and—by extension—of the interfaces that include the interface mixin.

interface mixin SomeMixin {
  /* mixin_members... */
};

partial interface mixin SomeMixin {
  /* mixin_members... */
};

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

Note that unlike interfaces or dictionaries, interface mixins do not create types.

Of the extended attributes defined in this specification, only the [CrossOriginIsolated], [Exposed], and [SecureContext] extended attributes are applicable to interface mixins.

An includes statement is a definition (matching IncludesStatement) used to declare that all objects implementing an interface I (identified by the first identifier) must additionally include the members of interface mixin M (identified by the second identifier). Interface I is said to include interface mixin M.

interface_identifier includes mixin_identifier;

The first identifier must reference a interface I. The second identifier must reference an interface mixin M.

Each member of M is considered to be a member of each interface I, J, K, … that includes M, as if a copy of each member had been made. So for a given member m of M, interface I is considered to have a member mI, interface J is considered to have a member mJ, interface K is considered to have a member mK, and so on. The host interfaces of mI, mJ, and mK, are I, J, and K respectively.

Note: In JavaScript, this implies that each regular operation declared as a member of interface mixin M, and exposed as a data property with a built-in function object value, is a distinct built-in function object in each interface prototype object whose associated interface includes M. Similarly, for attributes, each copy of the accessor property has distinct built-in function objects for its getters and setters.

The order of appearance of includes statements affects the order in which interface mixin are included by their host interface.

Member order isn’t clearly specified, in particular when interface mixins are defined in separate documents. It is discussed in issue #432.

No extended attributes defined in this specification are applicable to includes statements.

The following IDL fragment defines an interface, Entry, and an interface mixin, Observable. The includes statement specifies that Observable’s members are always included on objects implementing Entry.

interface Entry {
  readonly attribute unsigned short entryType;
  // ...
};

interface mixin Observable {
  undefined addEventListener(DOMString type,
                        EventListener listener,
                        boolean useCapture);
  // ...
};

Entry includes Observable;

A JavaScript implementation would thus have an addEventListener property in the prototype chain of every Entry:

var e = getEntry();          // Obtain an instance of Entry.
typeof e.addEventListener;   // Evaluates to "function".
CallbackOrInterfaceOrMixin ::
    callback CallbackRestOrInterface
    interface InterfaceOrMixin
InterfaceOrMixin ::
    InterfaceRest
    MixinRest
Partial ::
    partial PartialDefinition
PartialDefinition ::
    interface PartialInterfaceOrPartialMixin
    PartialDictionary
    Namespace
MixinRest ::
    mixin identifier { MixinMembers } ;
MixinMembers ::
    ExtendedAttributeList MixinMember MixinMembers
    ε
MixinMember ::
    Const
    RegularOperation
    Stringifier
    OptionalReadOnly AttributeRest
IncludesStatement ::
    identifier includes identifier ;

2.3.1. Using mixins and partials

This section is informative.

Interface mixins allow the sharing of attributes, constants, and operations across multiple interfaces. If you’re only planning to extend a single interface, you might consider using a partial interface instead.

For example, instead of:

interface mixin WindowSessionStorage {
  readonly attribute Storage sessionStorage;
};
Window includes WindowSessionStorage;

do:

partial interface Window {
  readonly attribute Storage sessionStorage;
};

Additionally, you can rely on extending interface mixins exposed by other specifications to target common use cases, such as exposing a set of attributes, constants, or operations across both window and worker contexts.

For example, instead of the common but verbose:

interface mixin GlobalCrypto {
  readonly attribute Crypto crypto;
};

Window includes GlobalCrypto;
WorkerGlobalScope includes GlobalCrypto;

you can extend the WindowOrWorkerGlobalScope interface mixin using a partial interface mixin:

partial interface mixin WindowOrWorkerGlobalScope {
  readonly attribute Crypto crypto;
};

2.4. Callback interfaces

A callback interface is a definition matching callback interface identifier { CallbackInterfaceMembers } ;. It can be implemented by any object, as described in § 2.12 Objects implementing interfaces.

Note: A callback interface is not an interface. The name and syntax are left over from earlier versions of this standard, where these concepts had more in common.

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

callback interface identifier {
  /* interface_members... */
};

Note: See also the similarly named callback function definition.

Callback interfaces must define exactly one regular operation.

Specification authors should not define callback interfaces unless required to describe the requirements of existing APIs. Instead, a callback function should be used.

The definition of EventListener as a callback interface is an example of an existing API that needs to allow objects with a given property (in this 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 JavaScript language binding).

Callback interfaces which declare constants must be annotated with an [Exposed] extended attribute.

CallbackRestOrInterface ::
    CallbackRest
    interface identifier { CallbackInterfaceMembers } ;
CallbackInterfaceMembers ::
    ExtendedAttributeList CallbackInterfaceMember CallbackInterfaceMembers
    ε
CallbackInterfaceMember ::
    Const
    RegularOperation

2.5. Members

Interfaces, interface mixins, and namespaces are specifications of a set of members (respectively matching InterfaceMembers, MixinMembers, and NamespaceMembers), which are the constants, attributes, operations, and other declarations that appear between the braces of their declarations. Attributes describe the state that an object implementing the interface, interface mixin, or namespace will expose, and operations describe the behaviors that can be invoked on the object. Constants declare named constant values that are exposed as a convenience to users of objects in the system.

When an interface includes an interface mixin, each member of the interface mixin is also considered a member of the interface. In contrast, inherited interface members are not considered members of the interface.

The constructor steps, getter steps, setter steps, and method steps for the various members defined on an interface or interface mixin have access to a this value, which is an IDL value of the interface type that the member is declared on or that includes the interface mixin the member is declared on.

Setter steps also have access to the given value, which is an IDL value of the type the attribute is declared as.

Interfaces, interface mixins, callback interfaces and namespaces each support a different set of members, which are specified in § 2.2 Interfaces, § 2.3 Interface mixins, § 2.4 Callback interfaces, and § 2.6 Namespaces, and summarized in the following informative table:

Interfaces Callback interfaces Interface mixins Namespaces
Constants
Regular attributes Only read only attributes
Static attributes
Regular Operations
Stringifiers
Special Operations
Static Operations
Iterable declarations
Asynchronously iterable declarations
Maplike declarations
Setlike declarations

2.5.1. Constants

A constant is a declaration (matching Const) used to bind a constant value to a name. Constants can appear on interfaces and callback interfaces.

Constants have in the past primarily been used to define named integer codes in the style of an enumeration. The Web platform is moving away from this design pattern in favor of the use of strings. Editors who wish to use this feature are strongly advised to discuss this by filing an issue before proceeding.

const type constant_identifier = 42;

The identifier of a constant must not be the same as the identifier of another interface member or callback interface member defined on the same interface or callback interface. The identifier also must not be "length", "name" or "prototype".

Note: These three names are the names of properties that are defined on the interface object in the JavaScript language binding.

The type of a constant (matching ConstType) must not be any type other than a primitive type. If an identifier is used, it must reference a typedef whose type is a primitive type.

The ConstValue part of a constant declaration gives the value of the constant, which can be one of the two boolean literal tokens (true and false), an integer token, a decimal token, or one of the three special floating point constant values (-Infinity, Infinity and NaN).

Note: These values – in addition to strings and the empty sequence – can also be used to specify the default value of a dictionary member or of an optional argument. Note that strings, the empty sequence [], and the default dictionary {} cannot be used as the value of a constant.

The value of the boolean literal tokens true 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:

  1. Let S be the sequence of scalar values matched by the integer token.

  2. Let sign be −1 if S begins with U+002D (-), and 1 otherwise.

  3. Let base be the base of the number based on the scalar values that follow the optional leading U+002D (-):

    U+0030 (0), U+0058 (X)
    U+0030 (0), U+0078 (x)

    The base is 16.

    U+0030 (0)

    The base is 8.

    Otherwise

    The base is 10.

  4. Let number be the result of interpreting all remaining scalar values following the optional leading U+002D (-) character and any scalar values indicating the base as an integer specified in base base.

  5. Return sign × number.

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 § 2.13 Types.

The value of a decimal token is either an IEEE 754 single-precision floating point number or an IEEE 754 double-precision floating point number, depending on the type of the constant, dictionary member or optional argument it is being used as the value for, determined as follows:
  1. Let S be the sequence of scalar values matched by the decimal token.

  2. Let result be the Mathematical Value that would be obtained if S were parsed as a JavaScript NumericLiteral.

  3. If the decimal token is being used as the value for a float or unrestricted float, then the value of the decimal token is the IEEE 754 single-precision floating point number closest to result.

  4. Otherwise, the decimal token is being used as the value for a double or unrestricted double, and the value of the decimal token is the IEEE 754 double-precision floating point number closest to result. [IEEE-754]

The value of a constant value specified as Infinity, -Infinity, 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 it is being used as the value for:

Type unrestricted float, constant value Infinity

The value is the IEEE 754 single-precision positive infinity value.

Type unrestricted double, constant value Infinity

The value is the IEEE 754 double-precision positive infinity value.

Type unrestricted float, constant value -Infinity

The value is the IEEE 754 single-precision negative infinity value.

Type unrestricted double, constant value -Infinity

The value is the IEEE 754 double-precision negative infinity value.

Type unrestricted float, constant value NaN

The value is the IEEE 754 single-precision NaN value with the bit pattern 0x7fc00000.

Type unrestricted double, constant value NaN

The value is the IEEE 754 double-precision NaN value with the bit pattern 0x7ff8000000000000.

The type of a decimal token is the same as the type of the constant, dictionary member or optional argument it is being used as the value of. The value of the decimal token must not lie outside the valid range of values for its type, as given in § 2.13 Types. 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 or callback interface on which they appear. It is language binding specific whether constants are exposed on instances.

The JavaScript language binding does however allow constants to be accessed through objects implementing the IDL interfaces on which the constants are declared. For example, with the following IDL:

[Exposed=Window]
interface A {
  const short rambaldi = 47;
};

the constant value can be accessed in JavaScript either as A.rambaldi or instanceOfA.rambaldi.

The following extended attributes are applicable to constants: [CrossOriginIsolated], [Exposed], and [SecureContext].

Const ::
    const ConstType identifier = ConstValue ;
ConstValue ::
    BooleanLiteral
    FloatLiteral
    integer
BooleanLiteral ::
    true
    false
FloatLiteral ::
    decimal
    -Infinity
    Infinity
    NaN
ConstType ::
    PrimitiveType
    identifier

The following IDL fragment demonstrates how constants of the above types can be defined.

[Exposed=Window]
interface Util {
  const boolean DEBUG = false;
  const octet LF = 10;
  const unsigned long BIT_MASK = 0x0000fc00;
  const double AVOGADRO = 6.022e23;
};

2.5.2. Attributes

An attribute is an interface member or namespace member (matching inherit AttributeRest, static OptionalReadOnly AttributeRest, stringifier OptionalReadOnly AttributeRest, OptionalReadOnly AttributeRest, or AttributeRest) that is used to declare data fields with a given type and identifier whose value can be retrieved and (in some cases) changed. There are two kinds of attributes:

  1. regular attributes, which are those used to declare that objects implementing the interface will have a data field member with the given identifier

    interface interface_identifier {
      attribute type identifier;
    };
    
  2. static attributes, which are used to declare attributes that are not associated with a particular object implementing the interface

    interface interface_identifier {
      static attribute type identifier;
    };
    

If an attribute has no static keyword, then it declares a regular attribute. Otherwise, it declares a static attribute. Note that in addition to being interface members, read only regular attributes can be namespace members as well.

The getter steps of an attribute attr should be introduced using text of the form “The attr getter steps are:” followed by a list, or “The attr getter steps are to” followed by an inline description.

The setter steps of an attribute attr should be introduced using text of the form “The attr setter steps are:” followed by a list, or “The attr setter steps are to” followed by an inline description.

Note: When defining getter steps, you implicitly have access to this. When defining setter steps, you implicitly have access to this and the given value.

The identifier of an attribute must not be the same as the identifier of another interface member defined on the same interface. The identifier of a static attribute must not be "prototype".

The type of the attribute is given by the type (matching Type) that appears after the attribute keyword. If the Type is an identifier or an identifier followed by ?, then the identifier must identify an interface, enumeration, callback function, callback interface or typedef.

The type of the attribute, after resolving typedefs, must not be a nullable or non-nullable version of any of the following types:

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.

interface interface_identifier {
  readonly attribute type identifier;
};

Attributes whose type is a promise type must be read only. Additionally, they cannot have any of the extended attributes [LegacyLenientSetter], [PutForwards], [Replaceable], or [SameObject].

A regular attribute that is not read only can be declared to inherit its getter from an ancestor interface. This can be used to make a read only attribute in an ancestor interface be writable on a derived interface. An attribute inherits its getter if its declaration includes inherit in the declaration. The read only attribute from which the attribute inherits its getter is the attribute with the same identifier on the closest ancestor interface of the one on which the inheriting attribute is defined. The attribute whose getter is being inherited must be of the same type as the inheriting attribute.

Note: The grammar ensures that inherit does not appear on a read only attribute or a static attribute.

[Exposed=Window]
interface Ancestor {
  readonly attribute TheType theIdentifier;
};

[Exposed=Window]
interface Derived : Ancestor {
  inherit attribute TheType theIdentifier;
};

When the stringifier keyword is used in a regular attribute declaration, it indicates that objects implementing the interface will be stringified to the value of the attribute. See § 2.5.5 Stringifiers for details.

interface interface_identifier {
  stringifier attribute DOMString identifier;
};

The following extended attributes are applicable to regular and static attributes: [CrossOriginIsolated], [Exposed], [SameObject], and [SecureContext].

The following extended attributes are applicable only to regular attributes: [LegacyLenientSetter], [LegacyLenientThis], [PutForwards], [Replaceable], [LegacyUnforgeable].

ReadOnlyMember ::
    readonly ReadOnlyMemberRest
ReadOnlyMemberRest ::
    AttributeRest
    MaplikeRest
    SetlikeRest
ReadWriteAttribute ::
    AttributeRest
InheritAttribute ::
    inherit AttributeRest
AttributeRest ::
    attribute TypeWithExtendedAttributes AttributeName ;
AttributeName ::
    AttributeNameKeyword
    identifier
AttributeNameKeyword ::
    required
OptionalReadOnly ::
    readonly
    ε

The following IDL fragment demonstrates how attributes can be declared on an interface:

[Exposed=Window]
interface Animal {

  // A simple attribute that can be set to any string value.
  readonly attribute DOMString name;

  // An attribute whose value can be assigned to.
  attribute unsigned short age;
};

[Exposed=Window]
interface Person : Animal {

  // An attribute whose getter behavior is inherited from Animal, and need not be
  // specified in the description of Person.
  inherit attribute DOMString name;
};

2.5.3. Operations

An operation is an