W3C

Language Bindings for DOM Specifications

W3C Working Draft 17 October 2007

This Version:
http://www.w3.org/TR/2007/WD-DOM-Bindings-20071017/
Latest Version:
http://www.w3.org/TR/DOM-Bindings/
Editor:
Cameron McCormack, Invited Expert <cam@mcc.id.au>

Abstract

This specification defines an Interface Definition Language (IDL) to be used by specifications that define a Document Object Model (DOM). How interfaces described with this IDL correspond to constructs within ECMAScript and Java execution environments is also detailed.

Status of this Document

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 17 October 2007 First Public Working Draft of the “Language Bindings for DOM Specifications” specification. Please send comments about this document to public-webapi@w3.org (archived) with “[Bindings]” at the start of the subject line.

“Language Bindings for DOM Specifications” is intended to specify in detail the IDL language used by W3C specifications to define DOM interfaces, and to provide precise conformance requirements for ECMAScript and Java bindings of such interfaces. It is expected that this document acts as a guide to implementors of already-published DOM specifications, and that newly published DOM specifications reference this document to ensure conforming implementations of DOM interfaces are interoperable.

This document is produced by the Web API 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.

Publication as a Working Draft 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.

Table of Contents

1. Introduction

This section is informative.

Specifications published by the W3C that include Document Object Model (DOM) interfaces are typically 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 specifications 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 a subset of OMG IDL version 3.0 for use by DOM specifications. 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 3rd Edition and Java are given.

2. Conformance

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”, “recommended”, “may” and “optional” in this document are to be interpreted as described in [RFC2119].

The following conformance classes are defined by this specification:

conforming IDL fragment

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.

conforming implementation

A user agent is considered to be a conforming implementation with respect 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.

conforming ECMAScript implementation

A user agent is considered to be a conforming ECMAScript implementation with respect 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.

conforming Java implementation

A user agent is considered to be a conforming Java implementation with respect 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 Java language binding.

3. Interface definition language

This section describes a language with which interfaces can be defined in a language independent manner. This language is based on the Object Management Group’s Interface Definition Language [OMGIDL], and is syntactically a subset thereof.

An IDL fragment is a sequence of definitions that matches the Definitions non-terminal in the grammar. See Appendix A for the complete grammar and an explanation of the notation used.

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 are discussed in section 3.8 below.

A definition is said to be declared at the outermost scope if there is no Module ancestor of the non-terminal representing the definition in the parse tree for the IDL fragment. Conforming IDL fragments should not have any non-module definitions declared at the outermost scope.

A definition has been declared previously, relative to a given scoped name that resolved to the definition, if:

[1]DefinitionsExtendedAttributeList Definition Definitions
 | ε
[2]DefinitionModule
 | Interface
 | Exception
 | Typedef
 | Valuetype
 | Const
Editorial note

Each of the sections below needs examples.

3.1. Names

The first identifier terminal in a derivation of a Definition, InterfaceMember or ExceptionMember determines the identifier of that definition, interface member or exception member (respectively) as follows:

  • If the value of the identifier terminal begins with a U+005F LOW LINE ("_") character, then the identifier of the definition, interface member or exception member is the value of the identifier terminal without that leading U+005F LOW LINE ("_") character.
  • Otherwise, the value of the identifier terminal does not begin with a U+005F LOW LINE ("_") character. The identifier of the definition, interface member or exception member is the value of the identifier terminal.

The identifier of a definition must be locally unique to the module in which the definition occurred.

Every definition also has a qualified name, which must be globally unique to the IDL fragment in which it is defined. The qualified name of a definition is defined as follows:

A scoped name is a string formed from the concatenation of the terminal values (removing any leading U+005F LOW LINE ("_") characters from the value of identifier terminals, as in the rules for identifiers) in the derivation of a ScopedName non-terminal. The scoped name can be either an absolute scoped name if it begins with two consecutive U+003A COLON (":") characters, or a relative scoped name if it does not.

A scoped name can be resolved, with respect to a given module, to a definition as follows:

  • If the scoped name is a relative scoped name, then:
    • If there exists a definition whose qualified name is equal to the concatenation of the qualified name of the module, two U+003A COLON (":") characters and the scoped name, then the scoped name resolves to that definition.
    • Otherwise, if there exists a definition whose qualified name is equal to the concatenation of two U+003A COLON (":") characters and the scoped name, then the scoped name resolves to that definition.
    • Otherwise, the scoped name does not resolve to a definition.
  • Otherwise, the scoped name is an absolute scoped name:
    • If there exists a definition whose qualified name is equal to the scoped name, then the scoped name resolves to that definition.
    • Otherwise, the scoped name does not resolve to a definition.
[40]ScopedName"::" identifier ScopedNameParts
 | identifier ScopedNameParts
[41]ScopedNameParts"::" identifier ScopedNameParts
 | ε

3.2. Modules

A module is a definition that matches the Module non-terminal, and which serves as a container for other definitions.

The enclosing module of a definition is defined as follows:

The relevant language binding determines how modules affect the naming of constructs that correspond to definitions in the language. If the language supports some form of namespacing mechanism, then a module will correspond to a namespace.

The following extended attributes are applicable to modules: [ExceptionConsts].

[3]Module"module" identifier "{" Definitions "}" ";"

3.3. Interfaces

An interface is a definition that matches the Interface non-terminal whose InterfaceBody is not empty (i.e., it is not the case that InterfaceBody ⇒ ε). An interface is a specification of a set of interface members, which are the constants, attributes and operations given by the InterfaceMembers part of the InterfaceBody. Objects implementing the interface need to have members that correspond to each of the interface’s members.

The identifier of an interface member is given by the first identifier terminal in a derivation of the non-terminal that represents the interface member. The identifier of an interface member must be unique within the interface on which it is defined.

An interface inherits from another if there is a scoped name in the ScopedNameList that, with respect to the enclosing module of the interface, resolves to that inherited interface. Every scoped name in the ScopedNameList must resolve to an interface whose definition occurs before the definition of the inheriting interface. An object that implements an interface that inherits from another also implements that inherited interface. The object therefore needs also to have members that correspond to the interface members from the inherited 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.

The relevant language binding determines how interfaces correspond to constructs in the language. Many object-oriented languages support interfaces, in which case the mapping of IDL interfaces to language interfaces is simple.

An interface forward declaration is a definition that matches the Interface non-terminal whose InterfaceBody is empty (i.e., InterfaceBody ⇒ ε). A forward declaration is used to introduce an interface name to allow for the definition of mutually recursive interfaces, since scoped names need to resolve to types that have been declared previously.

The following extended attributes are applicable to interfaces: [Constructor].

[4]Interface"interface" identifier InterfaceBody ";"
[5]InterfaceInheritance":" ScopedNameList
 | ε
[6]InterfaceBodyInterfaceInheritance "{" InterfaceMembers "}"
 | ε
[7]InterfaceMembersExtendedAttributeList InterfaceMember InterfaceMembers
 | ε
[8]InterfaceMemberConst
 | Attribute
 | Operation
[38]ScopedNameListScopedName ScopedNames
[39]ScopedNames"," ScopedName ScopedNames
 | ε

3.3.1. Constants

A constant is a definition that matches the Const non-terminal, and is used to bind a constant value to a name. Constants can appear on interfaces and also at the module or outermost scope.

The ConstExpr part of a constant definition gives the value of the constant, which can be one of the two boolean literal terminals ("TRUE" and "FALSE"), an integer terminal or a float terminal.

The value of the boolean literal terminals are as follows:

  • The value of the "TRUE" terminal is a value of type boolean: true.
  • The value of the "FALSE" terminal is a value of type boolean: false.

The value of an integer terminal is determined as follows:

  1. Let S be the string value of the integer terminal.
  2. Let n be the length of S.
  3. Initialize mag to 0.
  4. Initialize sign to 1.
  5. Initialize base to 10.
  6. Initialize i to 0.
  7. If the first character of S is not U+002D HYPHEN-MINUS ("-"), then go to step 10.
  8. Set sign to −1.
  9. Set i to 1.
  10. If the ith zero-based character of S is not U+0030 DIGIT ZERO ("0"), then go to step 16.
  11. Set base to 8.
  12. Set i to i + 1.
  13. If the ith zero-based character of S is not U+0058 LATIN CAPITAL LETTER X ("X") or U+0078 LATIN SMALL LETTER X ("x"), then go to step 16.
  14. Set base to 16.
  15. Set i to i + 1.
  16. Let digit be the value obtained by looking up the ith zero-based character of S in the table below:
    CharacterValue of digit
    U+0030 DIGIT ZERO ("0")0
    U+0031 DIGIT ONE ("1")1
    U+0032 DIGIT TWO ("2")2
    U+0033 DIGIT THREE ("3")3
    U+0034 DIGIT FOUR ("4")4
    U+0035 DIGIT FIVE ("5")5
    U+0036 DIGIT SIX ("6")6
    U+0037 DIGIT SEVEN ("7")7
    U+0038 DIGIT EIGHT ("8")8
    U+0039 DIGIT NINE ("9")9
    U+0041 LATIN CAPITAL LETTER A ("A")10
    U+0041 LATIN CAPITAL LETTER B ("B")11
    U+0041 LATIN CAPITAL LETTER C ("C")12
    U+0041 LATIN CAPITAL LETTER D ("D")13
    U+0041 LATIN CAPITAL LETTER E ("E")14
    U+0041 LATIN CAPITAL LETTER F ("F")15
    U+0061 LATIN SMALL LETTER A ("a")10
    U+0061 LATIN SMALL LETTER B ("b")11
    U+0061 LATIN SMALL LETTER C ("c")12
    U+0061 LATIN SMALL LETTER D ("d")13
    U+0061 LATIN SMALL LETTER E ("e")14
    U+0061 LATIN SMALL LETTER F ("f")15
  17. Set mag to mag * base + digit.
  18. Set i to i + 1.
  19. If i < n, go to step 16.
  20. The value of the integer terminal is sign * mag.

The type of an integer terminal is the same as the type of the constant it is being used as the value of. The value of the integer terminal must not lie outside the valid range of values for its type, as given in section 3.7 below.

The type of a float terminal is float, and its value is determined as follows:

  1. Let S be the string value of the float terminal.
  2. Let n be the length of S.
  3. Initialize mant to 0.
  4. Initialize sign to 1.
  5. Initialize exp1 to 0.
  6. Initialize exp2 to 0.
  7. Initialize expSign to 1.
  8. Iniitalize afterDot to false.
  9. Initialize i to 0.
  10. If the first character of S is not U+002D HYPHEN-MINUS ("-"), then go to step 13.
  11. Set sign to −1.
  12. Set i to 1.
  13. If the ith zero-based character of S is U+0045 LATIN CAPITAL LETTER E ("E") or U+0045 LATIN SMALL LETTER E ("e"), then go to step 23.
  14. If the ith zero-based character of S is not U+002E FULL STOP ("."), then go to step 17.
  15. Set afterDot to true.
  16. Go to step 20.
  17. Let digit be the Unicode codepoint of the ith zero-based character of S minus 48.
  18. Set mant to mant * 10 + digit.
  19. If afterDot is true, set exp1 to exp1 − 1.
  20. Set i to i + 1.
  21. If i < n, go to step 13.
  22. Go to step 33.
  23. Set i to i + 1.
  24. If the ith zero-based character of S is not U+002D HYPHEN-MINUS ("-"), then go to step 27.
  25. Set expSign to −1.
  26. Set i to i + 1.
  27. If the ith zero-based character of S is not U+002B PLUS SIGN ("+"), then set i to i + 1.
  28. Let digit be the Unicode codepoint of the ith zero-based character of S minus 48.
  29. Set exp2 to exp2 * 10 + digit.
  30. Set i to i + 1.
  31. If i < n, go to step 33.
  32. Go to step 28.
  33. The value of the float terminal is the IEEE 754 floating point number closest to sign * mant * 10expSign * exp2 + exp1. [IEEE-754]

A constant must be assigned a value of the same type that the constant is declared to be.

No extended attributes are applicable to constants.

[13]Const"const" DeclarationType identifier "=" ConstExpr ";"
[14]ConstExprBooleanLiteral
 | integer
 | float
[15]BooleanLiteral"TRUE"
 | "FALSE"

3.3.2. Attributes

An attribute is an interface member that matches the Attribute non-terminal, and is used to declare that objects implementing the interface will have an attribute with the given identifier that can be assigned and retrieved.

The type of the attribute is given by the DeclarationType non-terminal. If the DeclarationType is a scoped name, then it must resolve, with respect to the enclosing module of the interface on which the attribute is defined, to an interface, typedef or boxed valuetype that has been declared previously.

The attribute is read only if the "readonly" terminal is used in the definition. 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.

The GetRaises and SetRaises clauses are used to declare the possible exceptions that can be thrown when retrieving the value of and assigning a value to the attribute, respectively. Each scoped name in the GetRaises and SetRaises clauses must resolve, with respect to the enclosing module of the interface on which the attribute is defined, to an exception that has been declared previously.

Editorial note

Should conforming implementations have a requirement that they must not raise an exception (that was defined in the IDL) that is not in the getraises/setraises list?

The following extended attributes are applicable to attributes: [NoNull], [PutForwards].

[16]AttributeReadOnly "attribute" DeclarationType identifier GetRaises SetRaises ";"
[17]ReadOnly"readonly"
 | ε
[18]GetRaises"getraises" ExceptionList
 | ε
[19]SetRaises"setraises" ExceptionList
 | ε
[22]ExceptionList"(" ScopedNameList ")"

3.3.3. Operations

An operation is an interface member that matches the Operation non-terminal, and is used to declare that objects implementing the interface will have a method with the given identifier.

The return type of the operation is given by the ReturnType non-terminal. A return type of "void" indicates that the operation returns no value. If the DeclarationType is a scoped name, then it must resolve, with respect to the enclosing module of the interface on which the operation is defined, to an interface, typedef or boxed valuetype that has been declared previously.

The ArgumentList non-terminal gives the list of arguments for the operation. The identifier of an argument is given by the identifier terminal in the Argument, and the type of the argument is given by the DeclarationType. If the DeclarationType is a scoped name, then it must resolve, with respect to the enclosing module of the interface on which the operation is defined, to an interface, typedef or boxed valuetype that has been declared previously.

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

The Raises clause is used to declare the possible exceptions that can be thrown when invoking the operation. Each scoped name in the Raises clause must resolve, with respect to the enclosing module of the interface on which the operation is defined, to an exception that has been declared previously.

The following extended attributes are applicable to operations: [IndexGetter], [IndexSetter], [NameGetter], [NameSetter], [NoNull], [Overloads].

The following extended attributes are applicable to operation arguments: [NoNull], [Variadic].

[20]OperationReturnType identifier "(" ArgumentList ")" Raises ";"
[21]Raises"raises" ExceptionList
 | ε
[23]ArgumentListArgument Arguments
 | ε
[24]Arguments"," Argument Arguments
 | ε
[25]ArgumentExtendedAttributeList "in" DeclarationType identifier
[37]ReturnTypeDeclarationType
 | "void"

3.4. Exceptions

An exception is a definition that matches the Exception non-terminal, and is used to declare a type of exception that can be thrown by implementations. The identifier of the exception is given by the identifier terminal.

Exceptions are different from interfaces in that they can have only exception members (matching ExceptionMember) declared on them, rather than the three types of interface members. An exception member’s type is given by the DeclarationType non-terminal of the ExceptionMember. If the DeclarationType is a scoped name, then it must resolve, with respect to the enclosing module of the exception on which the exception member is declared, to an interface, typedef or boxed valuetype that has been declared previously.

The identifier of an exception member is given by the first identifier terminal in a derivation of ExceptionMember. The identifier of an interface member must be unique within the exception on which it is defined.

Exception members 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.

No extended attributes are applicable to exceptions or exception members.

[9]Exception"exception" identifier "{" ExceptionMembers "}" ";"
[10]ExceptionMembersExtendedAttributeList ExceptionMember ExceptionMembers
 | ε
[26]ExceptionMemberDeclarationType identifier ";"

3.5. Typedefs

A typedef is a definition that matches the Typedef non-terminal, and is used to declare a new name for a type.

The type is given by the Type non-terminal, and the new name for the type is the identifier of the typedef, as given by the identifier terminal.

Using a typedef is the only way to utilize the sequence<T> type, since interface members, exception members and operation return types and argument types must be specified with a DeclarationType, which does not allow a sequence<T>.

[11]Typedef"typedef" Type identifier ";"

3.6. Valuetypes

Valuetypes in OMG IDL are used to define types similar to structs in C. That is, they define composite types that can have zero or more member variables that are passed by value. OMG IDL valuetypes have the additional feature of allowing null to be passed in place of an object with those member variables. An OMG IDL boxed valuetype is a special case, where the valuetype has a single member.

The IDL defined in this specification supports only boxed valuetypes, which are definitions that match the Valuetype non-terminal. The identifier of the valuetype is given by the identifier terminal, and the type being boxed is given by the DeclarationType non-terminal.

Boxed valuetypes are essentially used just for allowing a null value to be used where normally a non-object value could only be used.

[12]Valuetype"valuetype" identifier DeclarationType ";"

3.7. Types

This section lists the types supported by the IDL.

[32]DeclarationTypeUnsignedIntegerType
 | ScopedName
 | "any"
 | "boolean"
 | "octet"
 | "float"
 | "Object"
[33]TypeDeclarationType
 | "sequence" "<" Type ">"
[34]UnsignedIntegerType"unsigned" IntegerType
 | IntegerType
[35]IntegerType"short"
 | "long" OptionalLong
[36]OptionalLong"long"
 | ε

3.7.1. any

The any type is the union of all other possible types.

3.7.2. boolean

The boolean type has two values: true and false.

boolean constant values in IDL are represented with the "TRUE" and "FALSE" terminals.

3.7.3. octet

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 terminals.

3.7.4. short

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 terminals.

3.7.5. unsigned short

The unsigned short type is an unsigned integer type that has values in the range [0, 65535].

unsigned short constant values in IDL are represented with integer terminals.

3.7.6. long

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 terminals.

3.7.7. unsigned long

The unsigned long type is an unsigned integer type that has values in the range [0, 4294967295].

unsigned long constant values in IDL are represented with integer terminals.

3.7.8. long long

The long long type is a signed integer type that has values in the range [−9223372036854775808, 9223372036854775807].

long long constant values in IDL are represented with integer terminals.

3.7.9. unsigned long long

The unsigned long long type is an unsigned integer type that has values in the range [0, 18446744073709551615].

unsigned long long constant values in IDL are represented with integer terminals.

3.7.10. float

The float type is a floating point numeric type that corresponds to the set of possible single-precision 32 bit IEEE 754 floating point numbers. [IEEE-754]

float constant values in IDL are represented with float terminals.

Editorial note

Do we need to mention anything about different NaNs, zeroes, infinities or denormalised numbers?

3.7.11. sequence<T>

The sequence<T> type is a parameterized type whose values are (possibly zero-length) sequences of values of type T. Sequences can have an arbitrary length that is immutable. However, sequence element values are mutable.

There is no way to represent a sequence constant value in IDL.

3.7.12. Object

The Object type corresponds to the set of all possible object references, plus the special value null, which indicates no object reference.

There is no way to represent an Object constant value in IDL.

3.7.13. Object implementing an interface

A scoped name that resolves to an interface is used to refer to a type that corresponds to the set of all possible references to objects that implement that interface, plus the special value null, which indicates no object reference.

There is no way to represent an Object constant value in IDL.

3.7.14. Boxed valuetype

A scoped name that resolves to a boxed valuetype is used to refer to a type that corresponds to the set of values for the type being boxed, plus the special value null, which indicates no value.

There is no way to represent a boxed valuetype constant value in IDL.

3.8. Extended attributes

An extended attribute is an annotation that can appear on definitions, interface members, exception members and operation arguments, and are 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.

An extended attribute is specified as an identifier. Some extended attributes are defined to take an argument. The argument is given by following the identifier with a "=" terminal and the identifier argument.

This specification defines a number of extended attributes, which are listed in the sub-sections below.

Editorial note

Have an extended attribute that specifies what properties get enumerated in a for..in loop?

[27]ExtendedAttributeList"[" ExtendedAttribute ExtendedAttributes "]"
[28]ExtendedAttributes"," ExtendedAttribute ExtendedAttributes
 | ε
[29]ExtendedAttributeidentifier ExtendedAttributeAssignment
[30]ExtendedAttributeAssignment"=" ExtendedAttributeArgument
 | ε
[31]ExtendedAttributeArgumentidentifier

3.8.1. [Constructor]

If the [Constructor] extended attribute appears on an interface, it indicates that there must be a way to construct objects that implement this interface. How such objects can be constructed is specific to the language binding.

The [Constructor] extended attribute must take no argument.

Example

The following IDL defines two interfaces. The second has the [Constructor] extended attribute, while the first does not.

IDL
interface NodeList {
  Node item(in unsigned long index);
  readonly attribute unsigned long length;
};

[Constructor]
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. The NodeList interface object would not have a [[Construct]] property.

ECMAScript
var x = new Circle();    // x is now a reference to a host object that implements the Circle interface.
var y = new NodeList();  // This would throw a TypeError.
Editorial note

This doesn’t allow for constructors which take arguments, and that’s probably something that will be wanted. Maybe the extended attribute should be on operations instead, e.g.:

IDL
interface Circle {
  attribute float r;
  attribute float cx;
  attribute float cy;
  readonly attribute float circumference;

  [Constructor] Circle createCircle(in float r, in float cx, in float cy);
};

For ES, such operations map to a [[Construct]] property with a function that takes the given arguments. For other languages, this could perhaps map to a static method somewhere.

3.8.2. [ExceptionConsts]

If the [ExceptionConsts] extended attribute appears on a module, it indicates that any constants declared on that module are intended to exist on the language construct that corresponds to the exception given by the extended attribute’s argument (for languages that support constants on exceptions). Exactly how these constants are exposed is language binding specific.

The [ExceptionConsts] must take a single argument, an identifier, which must be the identifier of an exception, defined in that module, on which the constants declared at the module scope should live.

Example

The following IDL fragment declares an exception and a number of constants at the module scope:

IDL
[ExceptionConsts=FileIOException]
module fileio {

  exception FileIOException {
    unsigned short code;
  };

  const unsigned short FILE_NOT_FOUND = 1;
  const unsigned short READ_ERROR = 2;
  const unsigned short WRITE_ERROR = 3;
};

In the ECMAScript binding, this will result in properties on the exception interface object for each of the constants:

ECMAScript
typeof FileIOException;          // evaluates to "object"
FileIOException.FILE_NOT_FOUND;  // evaluates to 1

3.8.3. [IndexGetter]

If the [IndexGetter] extended attribute appears on an operation with a single unsigned long argument, it indicates that an object that implements the interface can be indexed with an unsigned long, resulting in the same effect as calling the operation with the given index (for languages that support such object indexing). If an object implements interfaces such that it has more than one operation annotated with [IndexGetter], then which operation is invoked when an object is indexed with an unsigned long value is undefined.

The [IndexGetter] extended attribute must take no argument.

Example

The following IDL fragment defines an interface OrderedMap which allows retrieving and setting values by name or by index number:

IDL
valuetype DOMString sequence<unsigned short>;

interface OrderedMap {
  readonly attribute unsigned long size;

  [IndexGetter] any getByIndex(in unsigned long index);
  [IndexSetter] void setByIndex(in unsigned long index, in any value);

  [NameGetter] any get(in DOMString name);
  [NameSetter] void set(in DOMString name, in any value);
};

An ECMAScript implementation would have an internal [[Get]] method that allows values to be retrieved from the map as properties, and a corresponding [[Put]] method for setting values in the map:

ECMAScript
var map = getOrderedMap();  // Assume map is a host object implementing the OrderedMap interface.
var x, y;

x = map[0];                 // Same as: x = map.getByIndex(0)
map[1] = false;             // Same as: map.setByIndex(1, false)

y = map.apple;              // Same as: y = map.get('apple')
map.banana = 123;           // Same as: map.set('banana', 123)

3.8.4. [IndexSetter]

If the [IndexSetter] extended attribute appears on an operation with two arguments, the first of which is unsigned long, it indicates that an object that implements the interface can be indexed with an unsigned long for assignment, resulting in the same effect as calling the operation with the given index and value to assign (for languages that support such object indexing). If an object implements interfaces such that it has more than one operation annotated with [IndexSetter], then which operation is invoked when an object is indexed with an unsigned long value for assignment is undefined.

The [IndexSetter] extended attribute must take no argument.

Example

See section 3.8.3 for an example of the use of [IndexSetter].

3.8.5. [NameGetter]

If the [NameGetter] extended attribute appears on an operation with a single sequence<unsigned short> valuetype argument, it indicates that an object that implements the interface can be indexed with a string, resulting in the same effect as calling the operation with the given index name (for languages that support such object indexing). If an object has both a [NameGetter]- and [IndexGetter]-annotated operation, then which operation is invoked when an object is indexed is language binding specific.

The [NameGetter] extended attribute must take no argument.

Example

See section 3.8.3 for an example of the use of [NameGetter].

Editorial note

I’m slightly uncomfortable giving sequence<unsigned short> such special status here.

3.8.6. [NameSetter]

If the [NameSetter] extended attribute appears on an operation with a two arguments, the first of which is a sequence<unsigned short> boxed valuetype, it indicates that an object that implements the interface can be indexed with a string for assignment, resulting in the same effect as calling the operation with the given index and value to assign (for languages that support such object indexing). If an object implements interfaces such that it has more than one operation annotated with [NameSetter], then which operation is invoked when an object is indexed with a boxed sequence<unsigned short> value for assignment is undefined.

The [NameSetter] extended attribute must take no argument.

Example

See section 3.8.3 for an example of the use of [NameSetter].

3.8.7. [NoNull]

If the [NoNull] extended attribute appears on an attribute, an operation or an operation argument, whose type is a boxed valuetype, it indicates that a null value is not expected and will never be returned. How implementations treat the assignment of a null value to an attribute with the [NoNull] extended attribute, or passing a null value as a [NoNull] operation argument, is specific to the language binding.

The [NoNull] extended attribute must take no argument.

Example

The following IDL fragment defines an interface that has one attribute with the [NoNull] extended attribute, and one operation with an argument that has the extended attribute:

IDL
valuetype DOMString sequence<unsigned short>;

interface Dog {
  [NoNull] attribute DOMString name;
  attribute DOMString shortName;

  boolean isMemberOfBreed([NoNull] in DOMString breedName);
};

An ECMAScript implementation implementing the Dog interface would not allow the null value to be assigned to the name property or passed as the argument to the isMemberOfBreed function:

ECMAScript
var d = getDog();         // Assume d is a host object implementing the Dog interface.

d.name = null;            // This assigns the string "null" to the .name property.
d.isMemberOfBreed(null);  // This passes the string "null" to the isMemberOfBreed function.
Editorial note

Perhaps instead of having a [NoNull] extended attribute on DOMString arguments/attributes, different types could be used, e.g.:

IDL
typedef sequence<unsigned short> DOMString;
valuetype DOMStringOrNull DOMString;

3.8.8. [Overloads]

If the [Overloads] extended attribute appears on an operation, it indicates that the operation is to be considered to overload the operation with the identifier given as the extended attribute argument. The extent to which a language supports method overloading determines whether an object implementing an interface with overloaded operations must implement the operation using the overloaded name or the original name, and is specific to the language binding.

The [Overloads] extended attribute must take a single argument, an identifier, which must be the identifier of another operation defined on the interface, which this operation overloads. The identifier must not identify an operation that itself is declared with an [Overloads] extended attribute.

Example

The following IDL fragment defines an interface with overloaded operations:

IDL
interface Person;

interface PersonFactory {
  Person createPerson();
  [Overloads=createPerson] Person createPersonWithAge(in short age);
};

Since the ECMAScript binding allows overloading, a host object implementing the PersonFactory interface will have a single property createPerson:

ECMAScript
var f = getFactory();          // Assume f is a host object implementing the PersonFactory interface.

typeof f.createPerson;         // Evaluates to "function".
typeof f.createPersonWithAge;  // Evaluates to "undefined".

var p1 = f.createPerson();     // Corresponds to the createPerson operation.
var p2 = f.createPerson(26);   // Corresponds to the createPersonWithAge operation.

However, a hypothetical C language binding would not, since C does not support overloading. Separate functions would likely be used for the two operations:

C
PersonFactory* f = getFactory();

Person* p1 = PersonFactory_createPerson(f);             // Corresponds to the createPerson operation.
Person* p2 = PersonFactory_createPersonWithAge(f, 26);  // Corresponds to the createPersonWithAge operation.

3.8.9. [PutForwards]

If the [PutForwards] extended attribute appears on a read only attribute declaration whose type is an object implementing an interface, 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 the value of the attribute being assigned to.

It is binding language specific what behavior occurs when assigning to such an attribute when its value is null.

The [PutForwards] extended attribute must take a single argument, an identifier, which must be the identifier of an attribute that exists on the interface that is the type of this attribute, which is the attribute that assignments will be forward to.

Example

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:

IDL
valuetype DOMString sequence<unsigned short>;

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:

ECMAScript
var p = getPerson();           // Assume p is a host object implementing the Person interface.

p.name = 'John Citizen';       // This statement...
p.name.full = 'John Citizen';  // ...has the same behavior as this one.

3.8.10. [Variadic]

If the [Variadic] extended attribute appears on the final argument of an operation, it indicates that the operation is variadic, and can be passed zero or more arguments after the regular arguments. Each of these extra arguments will have to be of the type specified by that final argument. How such arguments are passed is specific to the language binding.

The [Variadic] extended attribute must take no argument.

Example

The following IDL fragment defines an interface that has a variadic operation:

IDL
interface IntegerSet {
  readonly unsigned long cardinality;

  void union([Variadic] in long integers);
  void intersection([Variadic] in long integers);
};

In the ECMAScript binding, variadic operations are implemented by functions that can accept the subsequent arguments:

ECMAScript
var s = getIntegerSet();  // Assume s is a host object implementing the IntegerSet interface.

s.union();                // Passing no arguments corresponding to 'integers'.
s.union(1, 4, 7);         // Passing three arguments corresponding to 'integers'.

A binding for a language that does not support variadic functions may specify that an explicit array or list of integers be passed to such an operation.

Editorial note

HTML 5 may want to use [Variadic] in the middle of the argument list, something like this:

IDL
any executeSql(DOMString q, [Variadic] DOMString p, Callback c);
any executeSql(Array a, Callback f);

Having [Variadic] in the middle isn’t so common in languages, as it tends to cause ambiguities.

4. ECMAScript binding

This section describes how definitions written with the IDL in section 3 correspond to particular ECMAScript constructs.

Unless otherwise specified, every object described in this section has internal properties [[Get]], [[Put]], [[CanPut]], [[HasProperty]], [[Delete]] and [[DefaultValue]] with the same behavior as specified for native objects, as described in section 8.6.2 of [ECMA-262].

If a value for the internal property [[Class]] is not given for a particular object, its value is implementation specific.

4.1. ECMAScript type mapping

This sub-section describes how types in the IDL map to types in ECMAScript. The phrase “to pass a value to a host object expecting type T” is used in this sub-section to describe passing an ECMAScript value as an argument to a function whose corresponding operation in the IDL specifies that the argument is of type T, or assigning to a property whose corresponding attribute in the IDL is of type T. Conversely, the phrase “to return a value of type T from a host object” is used to describe obtaining the ECMAScript return value from a function whose corresponding operation in the IDL specifies a return type T, or retrieving a property whose corresponding attribute in the IDL is of type T.

Editorial note

The above should become two <dfn>s that are linked to from the sub-sections below.

4.1.1. any

The any IDL type can correspond to any ECMAScript type.

4.1.2. void

The only place that the void type may appear in IDL is as the return type of an operation. Functions on host 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.

4.1.3. boolean

Values passed to a host object that expects a boolean must first be converted to an ECMAScript Boolean value by the ToBoolean operator defined in section 9.2 of [ECMA-262].

boolean values returned from a host object must be ECMAScript Boolean values.

4.1.4. octet

Values passed to a host object that expects an octet must first be converted to an ECMAScript Number value by the ToUint8 operator, which functions, analagously to the ToUint32 operator defined in section 9.6 of [ECMA-262], as follows:

  1. Call ToNumber on the input argument.
  2. If Result(1) is NaN, +0, −0, +∞, or −∞, return +0.
  3. Compute sign(Result(1)) * floor(abs(Result(1))).
  4. Compute Result(3) modulo 28.
  5. Return Result(4).

octet values returned from a host object must be ECMAScript Number values.

4.1.5. short

Values passed to a host object that expects a short must first be converted to an ECMAScript Number value by the ToInt16 operator, which functions, analagously to the ToInt32 operator defined in section 9.5 of [ECMA-262], as follows:

  1. Call ToNumber on the input argument.
  2. If Result(1) is NaN, +0, −0, +∞, or −∞, return +0.
  3. Compute sign(Result(1)) * floor(abs(Result(1))).
  4. Compute Result(3) modulo 216.
  5. If Result(4) is greater than or equal to 215, return Result(4) − 216. Otherwise, return Result(4).

short values returned from a host object must be ECMAScript Number values.

4.1.6. unsigned short

Values passed to a host object that expects an unsigned short must first be converted to an ECMAScript Number value by the ToUint16 operator defined in section 9.7 of [ECMA-262].

unsigned short values returned from a host object must be ECMAScript Number values.

4.1.7. long

Values passed to a host object that expects an long must first be converted to an ECMAScript Number value by the ToInt32 operator defined in section 9.5 of [ECMA-262].

long values returned from a host object must be ECMAScript Number values.

4.1.8. unsigned long

Values passed to a host object that expects an unsigned long must first be converted to an ECMAScript Number value by the ToUint32 operator defined in section 9.5 of [ECMA-262].

unsigned long values returned from a host object must be ECMAScript Number values.

4.1.9. long long

Values passed to a host object that expects a long long must first be converted to an ECMAScript Number value by the ToInt64 operator, which functions, analagously to the ToInt32 operator defined in section 9.5 of [ECMA-262], as follows:

  1. Call ToNumber on the input argument.
  2. If Result(1) is NaN, +0, −0, +∞, or −∞, return +0.
  3. Compute sign(Result(1)) * floor(abs(Result(1))).
  4. Compute Result(3) modulo 264.
  5. If Result(4) is greater than or equal to 263, return Result(4) − 264. Otherwise, return Result(4).

long long values returned from a host object must be ECMAScript Number values. If the long long value cannot be represented exactly by a Number value (i.e., it is less than or equal to −253 or greater than or equal to 253), the Number value returned must be the number representable by a Number closest to the given long long.

Editorial note

Should check that range of signed integers representable in a double.

4.1.10. unsigned long long

Values passed to a host object that expects an unsigned long long must first be converted to an ECMAScript Number value by the ToUint64 operator, which functions, analagously to the ToUint32 operator defined in section 9.6 of [ECMA-262], as follows:

  1. Call ToNumber on the input argument.
  2. If Result(1) is NaN, +0, −0, +∞, or −∞, return +0.
  3. Compute sign(Result(1)) * floor(abs(Result(1))).
  4. Compute Result(3) modulo 264.
  5. Return Result(4).

unsigned long long values returned from a host object must be ECMAScript Number values. If the unsigned long long value cannot be represented exactly by a Number value (i.e., it is greater than or equal to 253), the Number value returned must be the number representable by a Number closest to the given unsigned long long.

Editorial note

Should we do something other than choosing the closest double value to represent the long long?

4.1.11. float

Values passed to a host object that expects a float must first be converted to an ECMAScript Number value by the ToNumber operator defined in section 9.3 of [ECMA-262].

float values returned from a host object must be ECMAScript Number values.

4.1.12. sequence<T>

Values passed to a host object that expects a sequence<T> must be objects with a length property whose value is a non-negative integer Number that specifies the number of elements in the sequence. Such objects must return the element in the sequence at position n when their [[Get]] internal method is invoked with n as its argument. (An ECMAScript Array is an object that matches this description.) When the host object gets an element of the sequence using the [[Get]] method, the returned value must first be handled according to the rules in this section for the type T.

Editorial note

The above paragraph needs to have tighter language for the behaviour of [[Get]], like the definition for [[Get]] in section 4.3.1.

If a host object expecting a sequence<T> is passed a value which is not an object with a non-negative integer Number length property, a TypeError exception must be thrown.

Sequences are passed by reference. If a reference to a sequence passed to a host object is kept (whether internally or as the value of an attribute), and the passed sequence is not an ECMAScript Array object, the kept reference must be a newly created ECMAScript Array object whose contents is the elements of the sequence.