W3C

Language Bindings for DOM Specifications

W3C Working Draft 10 April 2008

This Version:
http://www.w3.org/TR/2008/WD-DOM-Bindings-20080410/
Latest Version:
http://www.w3.org/TR/DOM-Bindings/
Previous Version:
http://www.w3.org/TR/2007/WD-DOM-Bindings-20071017/
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 10 April 2008 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:

  • If the definition is declared at the outermost scope, then the qualified name of the definition is two consecutive U+003A COLON (":") characters followed by the identifier of the definition.
  • Otherwise, the definition is not declared at the outermost scope. The qualified name of the definition is the qualified name of the definition’s enclosing module followed by two consecutive U+003A COLON (":") characters followed by the identifier of the definition.

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 is 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.
[41]ScopedName"::" identifier ScopedNameParts
 | identifier ScopedNameParts
[42]ScopedNameParts"::" identifier ScopedNameParts
 | ε

3.2. Modules

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

The enclosing module of a definition is defined as follows:

  • If the definition is declared at the outermost scope, then the definition has no enclosing module.
  • Otherwise, the definition is not declared at the outermost scope. The enclosing module of the definition is the closest Module ancestor of the non-terminal representing the definition in the IDL fragment’s parse tree.

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 (that is, 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 will 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 (except for operations, which can be overloaded) 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 will also 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 (that is, 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], [NoInterfaceObject], [Stringifies].

Editorial note

Should there be a way to define constructors on the interface with particular names, to support HTML 5’s Audio, Image and Option constructors?

[4]Interface"interface" identifier InterfaceBody ";"
[5]InterfaceInheritance":" ScopedNameList
 | ε
[6]InterfaceBodyInterfaceInheritance "{" InterfaceMembers "}"
 | ε
[7]InterfaceMembersExtendedAttributeList InterfaceMember InterfaceMembers
 | ε
[8]InterfaceMemberConst
 | Attribute
 | Operation
[39]ScopedNameListScopedName ScopedNames
[40]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+0042 LATIN CAPITAL LETTER B ("B")11
    U+0043 LATIN CAPITAL LETTER C ("C")12
    U+0044 LATIN CAPITAL LETTER D ("D")13
    U+0045 LATIN CAPITAL LETTER E ("E")14
    U+0046 LATIN CAPITAL LETTER F ("F")15
    U+0061 LATIN SMALL LETTER A ("a")10
    U+0062 LATIN SMALL LETTER B ("b")11
    U+0063 LATIN SMALL LETTER C ("c")12
    U+0064 LATIN SMALL LETTER D ("d")13
    U+0065 LATIN SMALL LETTER E ("e")14
    U+0066 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 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].

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
[38]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 exception 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.

The following extended attributes are applicable to exceptions: [NoInterfaceObject].

No extended attributes are applicable to 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 BoxedType non-terminal. If the BoxedType is a ScopedName, then it must refer to a type that does not allow null as a value (i.e., boolean, octet, short, unsigned short, unsigned long, long long, unsigned long long, float or sequence<T>.

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 BoxedType ";"

3.7. Types

This section lists the types supported by the IDL.

[32]DeclarationTypeUnsignedIntegerType
 | ScopedName
 | "any"
 | "boolean"
 | "octet"
 | "float"
 | "Object"
[33]BoxedTypeUnsignedIntegerType
 | ScopedName
 | "boolean"
 | "octet"
 | "float"
 | "sequence" "<" Type ">"
[34]TypeDeclarationType
 | "sequence" "<" Type ">"
[35]UnsignedIntegerType"unsigned" IntegerType
 | IntegerType
[36]IntegerType"short"
 | "long" OptionalLong
[37]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.

Editorial note

Should sequences really be immutable? Is there any advantage to disallowing resizing sequences here, rather than selectively by the interface designer? The sequence section in the ECMAScript bindings below assume it is 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. [NoInterfaceObject]

If the [NoInterfaceObject] extended attribute appears on an interface, it indicates that an interface object will not exist for the interface in the ECMAScript binding. Similarly, if it appears on an exception it indicates that an exception interface object will not exist for the exception in the ECMAScript binding.

The [NoInterfaceObject] must take no argument.

Editorial note

Should this be [InterfaceObject] instead, and default to not having one?

Example

The following IDL fragment defines two interfaces, one whose interface object is exposed on the ECMAScript global object, and one whose isn’t:

IDL
interface Storage {
  void addEntry(in unsigned long key, in any value);
};

[NoInterfaceObject]
interface Query {
  any lookupEntry(in unsigned long key);
};

An ECMAScript implementation of the above IDL would allow manipulation of Storage’s prototype, but not Query’s.

ECMAScript

typeof Storage;                        // evaluates to "object"

// Add some tracing alert() call to Storage.addEntry.
var fn = Storage.prototype.addEntry;
Storage.prototype.addEntry = function(key, value) {
  alert('Calling addEntry()');
  return fn.call(this, key, value);
};

typeof Query;                          // evaluates to "undefined"
var fn = Query.prototype.lookupEntry;  // exception, Query isn’t defined

3.8.6. [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 somewhat uncomfortable giving sequence<unsigned short> such special status here.

Perhaps the language should special case DOMString to make it always refer to a string, but still allow it to be typedefed to sequence<unsigned short> for compatibility?

3.8.7. [NameSetter]

If the [NameSetter] extended attribute appears on an operation with 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.8. [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.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 language binding 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. [Stringifies]

If the [Stringifies] extended attribute appears on an interface, it indicates that, for language bindings that support object stringification, an object that implements the interface will stringify in a non-default manner.

The [Stringifies] extended attribute may take a single argument, an identifier, which identifies an attribute on the interface whose value will be used as the result of the stringification. If the argument is not supplied, the stringification behavior must be described in prose.

Example

The following IDL fragment defines an interface that will stringify to the value of its name attribute:

IDL
[Constructor, Stringifies=name]
interface Student {
  unsigned long id;
  DOMString name;
};

In the ECMAScript binding, using a Student object in a context where a string is expected will result in the value of the object’s name property being used:

ECMAScript
var s = new Student();
s.id = 12345678;
s.name = '周杰倫';

var greeting = 'Hello, ' + s + '!';  // Now greeting == 'Hello, 周杰倫!'.

The following IDL fragment defines an interface that has custom stringification behavior that is not specified in the IDL itself.

IDL
[Constructor, Stringifies]
interface Student {
  unsigned long id;
  DOMString familyName;
  [NoNull] DOMString givenName;
};

Thus, prose is required to explain the stringification behavior, such as the following paragraph:

Objects that implement the Student interface must stringify as follows. If the value of the familyName attribute is null, the stringification of the object is the value of the givenName attribute. Otherwise, if the value of the familyName attribute is not null, the stringification of the object is the concatenation of the the value of the givenName attribute, the string " " and the value of the familyName attribute.

An ECMAScript implementation of the IDL would behave as follows:

ECMAScript
var s = new Student();
s.id = 12345679;
s.familyName = 'Smithee';
s.givenName = 'Alan';

var greeting = 'Hi ' + s;  // Now greeting == 'Hi Alan Smithee'.

3.8.11. [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.

4. ECMAScript binding

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

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 section describes how types in the IDL map to types in ECMAScript.

Passing 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 or exception member in the IDL is of type T. Conversely, returning 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 or exception member in the IDL is of type T.

Each sub-section below describes how a values of a given IDL type are represented in ECMAScript. For each IDL type, it is described how ECMAScript values are converted to an IDL value when passed to a host object expecting that type, and how IDL values of that type are converted to ECMAScript values when returned from a host object.

4.1.1. any

The IDL any type can correspond to any ECMAScript type.

Since there is no ECMAScript value that does correspond to an IDL value, no conversion is performed when passing an ECMAScript value to a host object expecting any, or when a host object returns a value of type any.

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

IDL boolean values are represented by ECMAScript Boolean values.

Values passed to a host object expecting 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

IDL octet values are represented by integer ECMAScript Number values in the range [0, 255].

Values passed to a host object expecting an octet must first be converted to an ECMAScript Number value by the ToUint8 operator, which functions (analogously 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 integer ECMAScript Number values in the range [0, 255].

4.1.5. short

IDL short values are represented by integer ECMAScript Number values in the range [−32768, 32767].

Values passed to a host object expecting a short must first be converted to an ECMAScript Number value by the ToInt16 operator, which functions (analogously 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 integer ECMAScript Number values in the range [−32768, 32767].

4.1.6. unsigned short

IDL unsigned short values are represented by integer ECMAScript Number values in the range [0, 65535].

Values passed to a host object expecting 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 integer ECMAScript Number values in the range [0, 65535].

4.1.7. long

IDL long values are represented by integer ECMAScript Number values in the range [−2147483648, 2147483647].

Values passed to a host object expecting 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 integer ECMAScript Number values in the range [−2147483648, 2147483647].

4.1.8. unsigned long

IDL unsigned long values are represented by integer ECMAScript Number values in the range [0, 4294967295].

Values passed to a host object expecting 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 integer ECMAScript Number values in the range [0, 4294967295].

4.1.9. long long

IDL long long values are represented by ECMAScript Number values.

Values passed to a host object expecting a long long must first be converted to an ECMAScript Number value by the ToInt64 operator, which functions (analogously 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

IDL unsigned long long values are represented by ECMAScript Number values.

Values passed to a host object expecting an unsigned long long must first be converted to an ECMAScript Number value by the ToUint64 operator, which functions (analogously 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

IDL float values are represented by ECMAScript Number values.

Values passed to a host object expecting 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>

IDL sequence<T> values are represented by ECMAScript Object values with special properties.

Values passed to a host object expecting a sequence<T> must be objects with a length property whose value, after being converted to a Number by the ToUint32 operator, is a non-negative integer that specifies the number of elements in the sequence. This number must also be equal to the result of passing the original length property value to the ToNumber algorithm. Assigning to the length property a non-negative integer Number must change the length of the sequence to be the given number. If the sequence is lengthened, new elements must be given the value that the undefined value is converted to when handling it according to the rules in this section for the type T. If the sequence is shortened, the values beyond the new length of the sequence are lost. The object representing the sequence must return the element in the sequence at position n when its [[Get]] internal method is invoked with n as its argument.

Note that an ECMAScript Array is an object that matches this description. Implementations are free, however, to use a host object to implement the sequence in the interests of efficiency.

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.

If a host object expecting a sequence<T> is passed a value which is not an object that conforms to the above rules (for example, it does not have a length property), then a TypeError exception must be thrown.

While sequences are passed by reference (being objects), it is of course up to the interface designer whether, for example, after assigning a sequence to a property on a host object that same seqence object is returned when getting the property. The behavior of storing sequences in the host object in this manner should be made clear in prose describing the interface.

Editorial note

Should there be a way to declare a sequence whose length cannot be changed from script?

Example

The following IDL defines an interface that has a sequence<unsigned short> attribute.

IDL
typedef sequence<unsigned short> Integers;

[Constructor]
interface LotteryResults {
  attribute Integers numbers;
};

The following paragraph is used to clarify the behavior of assigning a value to the numbers property:

In the ECMAScript language binding, assigning an array-like object to the numbers property results in a copy of those values being stored in the LotteryResults object. The array-like object returned when the numbers property is retrieved, however, will not change over the lifetime of the LotteryResults object.

The following ECMAScript code illustrates how the sequence attribute in the above interface would behave:

ECMAScript
var results = new LotteryResults();  // results is a new host object implementing the LotteryResults interface.
var a = [4, 8, 15, 16, 23, 42];      // An object that can serve as a sequence<unsigned short>.

results.numbers = a;                 // Assign the sequence, resulting in the values being copied into the host object.
a[0] = 5;                            // Change the array.
results.numbers[0];                  // Evaluates to 4, since results.numbers is not a reference to 'a'.

results.numbers[0] = 5;              // Modifies the sequence stored in the host object.
results.numbers[0];                  // Now evaluates to 5.

results.length = 7;                  // Increase the length of the sequence.
results.numbers[6];                  // Evaluates to 0, since that is how 'undefined' is converted to an 'unsigned short'.

4.1.13. sequence<unsigned short>

As a special case, IDL sequence<unsigned short> values are represented by ECMAScript String values.

Values passed to a host object expecting a sequence<unsigned short> value must first be converted to an ECMAScript String value by the ToString operator defined in section 9.8 of [ECMA-262].

sequence<unsigned short> values returned from a host object must be ECMAScript String values.

4.1.14. Object

IDL Object values are represented by ECMAScript Object values.

If a host object expecting an Object is passed the null value, then that value must passed without modification. Otherwise, the value being passed must first be converted to an ECMAScript Object value by the ToObject operator defined in section 9.9 of [ECMA-262].

If a host object returns an Object that is null, then the ECMAScript null value must be returned. Otherwise, an ECMAScript Object value must be returned.

4.1.15. Object implementing an interface

IDL object implementing an interface values are represented by ECMAScript Object values.

If a host object expecting an object that implements an interface I is passed the null value, then that value must passed without modification. Otherwise, the value being passed must first be converted to an ECMAScript Object value by the ToObject operator defined in section 9.9 of [ECMA-262]. If after that conversion the object is not one that implements I (either intrinsically for a host object, or as described in section 4.4 below for a native object), then a TypeError must be thrown.

If a host object returns an object that implements an interface I that is null, then the ECMAScript null value must be returned. Otherwise, an ECMAScript Object value that implements I must be returned.

4.1.16. Boxed valuetype

IDL boxed valuetype values are represented by values of either the ECMAScript type corresponding to the IDL type being boxed, or the ECMAScript null value.

If a host object expecting a boxed valuetype that is not annotated with the [NoNull] extended attribute is passed the null value, then that value must be passed without modification. However, if the [NoNull] extended attribute does apply and the null value is passed to the host object, the behavior depends on the type being boxed. If the type being boxed is sequence<unsigned short>, then the ECMAScript String "null" must be passed to the host object. If the type being boxed is anything else, the behavior is implementation specific.

If a host object expecting a boxed valuetype is passed an ECMAScript Object value, the value must first be handled according to the rules in this section corresponding to the IDL type being boxed.

If a host object returns a boxed valuetype that is null, then the ECMAScript null value must be returned. If the operation, attribute is annotated with the [NoNull] extended attribute, the host object must not return null. If the value returned is not null, it must be handled according to the rules in this section corresponding to the IDL type being boxed.

Editorial note

Perhaps there should be an example here for the real-world case that boxed valuetypes are actually used for (DOMString).

4.2. Interfaces

For every interface that is not declared with the [NoInterfaceObject] extended attribute, a corresponding property must exist on the ECMAScript global object whose name is the identifier of the interface. The value of this property is an object called the interface object, which provides access to the constants and operations defined on the interface. The property has the attributes { DontDelete, DontEnum }.

4.2.1. Interface object

The interface object for a particular interface must have an internal [[Prototype]] property whose value is the Object prototype object.

The interface object also has properties that correspond to the constants defined on that interface, as described in section 4.2.3 below.

If the interface is declared with the [Constructor] extended attribute, then the interface object must also have a [[Construct]] internal property, which allows construction of objects that implement the given interface. The behavior of this [[Construct]] method is not necessarily the same as that described for Function objects in section 13.2.2 of [ECMA-262].

The interface object must also have a property named prototype with attributes { DontDelete, ReadOnly } whose value is an object called the interface prototype object. This object provides access to the functions that correspond to the operations defined on the interface, and is described in more detail in section 4.2.2 below.

4.2.1.1. Interface object [[HasInstance]] method

The internal [[HasInstance]] method of every interface object I must behave as follows, assuming V is the object argument passed to [[HasInstance]]:

  1. If V is not an object, return false.
  2. Call the [[Get]] method of I with property name "prototype".
  3. Let O be Result(2).
  4. If O is not an object, throw a TypeError exception.
  5. If V is a host object that implements the interface for which O is the interface prototype object, return true.
  6. Let V be the value of the [[Prototype]] property of V.
  7. If V is null, return false.
  8. If O and V refer to the same object or if they refer to objects joined to each other (see section 13.1.2 of [ECMA-262]), return true.
  9. Go to step 6.

4.2.2. Interface prototype object

There must exist an interface prototype object for every interface defined, regardless of whether the interface was declared with the [NoInterfaceObject] extended attribute. The interface prototype object for a particular interface has properties that correspond to the operations defined on that interface. These properties are described in more detail in section 4.2.4 below.

As with the interface object, the interface prototype object also has properties that correspond to the constants defined on that interface, described in section 4.2.3 below.

If the interface is declared with the [Constructor] extended attribute, the interface prototype object must also have a property named constructor with attributes { DontEnum } whose value is a reference to the interface object for the interface.

Editorial note

Haven’t checked what attributes browsers use on the constructor property.

Also, should the constructor property exist even for non-constructable objects?

No particular value must be used for the internal [[Prototype]] property of the interface prototype object. However, it must be an object that provides access to the properties corresponding to the operations and constants defined on the interfaces from which this interface inherits. Changes made to the interface prototype objects of superinterfaces must be reflected through this object, as with normal prototype-based single inheritance in ECMAScript. If more than one superinterface has a given property, it is implementation specific which one is accessed.

Example

Assume the following IDL:

IDL
interface A {
  void f();
};

interface B {
  void g();
};

interface C : A, B {
  void f();
};

interface D : C {
  void h();
};

The following is one way for an implementation to set up the prototype chain for the interface objects:

  • The [[Prototype]] internal property of the interface prototype objects for A and B is the Object prototype object, since neither of these interfaces has a superinterface.
  • The [[Get]], [[CanPut]] and [[HasProperty]] internal methods of the interface prototype object for A are the standard ones defined in section 8.6.2 of [ECMA-262].
  • The [[Prototype]] internal prototype of the interface prototype object for C is null.
  • The [[Get]] internal method of the interface prototype object for C behaves as follows (where O is the object and P is the property name):
    1. If O doesn’t have a property with name P, go to step 4.
    2. Get the value of the property.
    3. Return Result(2).
    4. Call the [[HasProperty]] method of the interface prototype object for A with property name P.
    5. If Result(4) is false, go to step 8.
    6. Call the [[Get]] method of the interface prototype object for A with property name P.
    7. Return Result(6).
    8. Call the [[HasProperty]] method of the interface prototype object for B with property name P.
    9. If Result(8) is false, go to step 12.
    10. Call the [[Get]] method of the interface prototype object for B with property name P.
    11. Return Result(10).
    12. Return undefined.
  • The [[CanPut]] internal method of the interface prototype object for C behaves as follows (where O is the object and P is the property name):
    1. If O doesn’t have a property with name P, go to step 4.
    2. If the property has the ReadOnly attribute, return false.
    3. Return true.
    4. Call the [[CanPut]] method of the interface prototype object for A with property name P.
    5. If Result(4) is false, return false.
    6. Call the [[CanPut]] method of the interface prototype object for B with property name P.
    7. If Result(6) is false, return false.
    8. Return true.
  • The [[HasProperty]] internal method of the interface prototype object for C behaves as follows (where O is the object and P is the property name):
    1. If O has a property with name P, return true.
    2. Call the [[HasProperty]] method of the interface prototype object for A with property name P.
    3. If Result(3) is true, return true.
    4. Call the [[HasProperty]] method of the interface prototype object for B with property name P.
    5. If Result(5) is true, return true.
    6. Return false.
  • The [[Prototype]] internal property of the interface prototype object for D is the interface prototype object for C, since D has only a single superinterface.
  • The [[Get]], [[CanPut]] and [[HasProperty]] internal methods of the interface prototype object for D are the standard ones defined in section 8.6.2 of [ECMA-262].
Editorial note

Should the prototype chain and internal methods given in the example above be mandated, or just left as an example of how to do it?

4.2.3. Constants

For each constant defined on the interface, there must be a corresponding property on the interface object (if it exists) and the interface prototype object:

  • The name of the property is the identifier of the constant.
  • The value of the property is the ECMAScript value that is equivalent to the constant’s IDL value, according to the rules in section 4.1 above.
  • The property has attributes { DontDelete }.

4.2.4. Operations

For each unique identifier of an operation defined on the interface, there must be a corresponding property on the interface prototype object:

  • The name of the property is the identifier.
  • The property has attributes { DontEnum }.
  • The value of the property is a Function object that behaves as follows, assuming I is the identifier:
    1. Initialize O to null.
    2. Initialize arity to 0.
    3. Let n be the number of arguments passed to the function.
    4. Let arg0‥n−1 be the arguments passed to the function.
    5. If I identifies a single operation:
      1. Set O to the operation that I identifies.
      2. Set arity to the number of arguments that O is declared with.
      3. If the final argument of O has the [Variadic] extended attribute, set arity to arity − 1.
    6. Otherwise, if I identifies more than one operation:
      1. Let m be the number of operations I identifies.
      2. Let P1‥m be the operations that I identifies.
      3. Let score1‥m be a score calculated for each operation in P1‥m, as follows:
        1. Let Q be the operation for which a score is being calculated.
        2. Set arity to the number of arguments that Q is declared with.
        3. If the final argument of Q has the [Variadic] extended attribute, set arity to arity − 1.
        4. Initialize s to 0.
        5. If n < arity, set s to ∞.
        6. Otherwise, if n ≥ arity:
          1. Initialize i to 0.
          2. While i < arity:
            1. Let dt be the IDL type of argument i that Q is declared with.
            2. Let at be the ECMAScript type of argi.
            3. Let x be the value determined by looking up the score table below.
            4. If x ≠ 0, set s to s + (arity + 2)x.
            5. Set i to i + 1.
          3. If the final argument of Q has the [Variadic] extended attribute:
            1. Let dt be the IDL type of the final argument that Q is declared with.
            2. While i < n:
              1. Let at be the ECMAScript type of argi.
              2. Let x be the value determined by looking up the score table below.
              3. If x = ∞, set s to ∞.
              4. Set i to i + 1.
        7. The calculated score is s.
      4. If the minimum score in score1‥m is ∞, then there is no appropriate overloaded operation to invoke. Throw a TypeError and end the function.
      5. Set O to the operation in P1‥m whose corresponding score in score1‥m is the minimum. If multiple operations have the minimum score, it is undefined which is chosen. (Interface designers may specify in prose how operations are disambiguated at this point.)
    7. Perform the actions listed in the description of O with arg0‥n−1 as the argument values.
    Score table
    atdtx
    Undefined(any type)0
    Booleanboolean*1
    any1
    sequence<T> *
    Object implementing an interface
    (any other type)2
    Numberfloat *1
    octet *1
    short *1
    unsigned short *1
    long *1
    unsigned long *1
    long long *1
    unsigned long long *1
    any1
    sequence<T> *
    Object implementing an interface
    (any other type)2
    Stringsequence<unsigned short> *1
    any1
    sequence<T> (where T ≠ unsigned short) *
    Object implementing an interface
    (any other type)2
    NullObject1
    Object implementing an interface1
    Boxed valuetype of any type1
    any1
    sequence<T> *
    (any other type)2
    ObjectObject1
    Object implementing interface A (if the object implements A)1
    sequence<T> *1
    any1
    Object implementing interface A (if the object does not implement A)
    (any other type)2
    * The specified type or a boxed valuetype of the specified type.
    Editorial note

    Should there be a way for script to explicitly disambiguate function calls? For example, something like the “Explicit Method Specification” LiveConnect 3. That could allow:

    IDL
    [Constructor]
    interface Ambiguity {
    
      void f(in octet x);
      void f(in long x);
    
      void g(in Node n);
      void g(in Document n);
    };
    ECMAScript
    var a = new Ambiguity();
    
    a.f(5);              // undefined which f() is called
    a['f(octet)'](5);    // explicitly call the first f()
    a['f(long)'](5);     // explicitly call the second f()
    
    a.g(document);                                // undefined which g() is called, since 'document' implements Node and Document
    a['g(::org::w3c::dom::Node)'](document);      // explicitly call the first g()
    a['g(::org::w3c::dom::Document)'](document);  // explicitly call the second g()
    

In addition, if the interface is declared with the [Stringifies] extended attribute, a property must exist on the interface prototype object whose name is toString and whose value is a Function object. If the [Stringifies] extended attribute on the interface has an identifier argument P, assuming O is the object on which the function was invoked, the behavior of the toString function is as follows:

  1. Invoke the [[Get]] method of object O with P as the argument.
  2. Compute ToString(Result(1)).
  3. Return Result(2).

If the [Stringifies] extended attribute on the interface was not given an argument, then the behavior of the toString function is the stringification behavior of the interface, as described in the prose for the interface.

Editorial note

Should say what happens if [Stringifies] is used on an interface that also has a toString operation.

4.3. Host objects implementing interfaces

If a host object implements an interface, then for each attribute defined on the interface, there must be a corresponding property on the host object:

  • The name of the property is the identifier of the attribute.
  • If the attribute is declared readonly, the property has attributes { DontDelete, ReadOnly }. Otherwise, the property has attributes { DontDelete }.

If a host object implements more than one interface with an attribute of a given name, it is implementation specific which attribute the property corresponds to.

No particular value must be used for the internal [[Prototype]] property of the host object. However, it must be an object that provides access to the properties corresponding to the operations and constants defined on all interfaces the host object implements. Changes made to the interface prototype objects of interfaces implemented by the host object must be reflected through this object. If more than one interface prototype object has a given property, it is implementation specific which one is accessed.

Example

Assume the IDL and interface prototype objects given in the section 4.2.2 example.

Now assume that ab is a host object that implements A and B and d is a host object that implements D. The following is one way for an implementation to connect the host objects to the interface prototype objects:

  • The [[Prototype]] internal property of the host object ab is an object that provides access to the properties from the interface prototype objects for both A and B:
    • The [[Prototype]] internal property of the [[Prototype]] object for ab is null.
    • The [[Get]] internal method of the [[Prototype]] object for ab behaves as follows (where O is the object and P is the property name):
      1. If O doesn’t have a property with name P, go to step 4.
      2. Get the value of the property P on object O.
      3. Return Result(2).
      4. Call the [[HasProperty]] method of the interface prototype object for A with property name P.
      5. If Result(4) is false, go to step 8.
      6. Call the [[Get]] method of the interface prototype object for A with property name P.
      7. Return Result(6).
      8. Call the [[HasProperty]] method of the interface prototype object for B with property name P.
      9. If Result(8) is false, go to step 12.
      10. Call the [[Get]] method of the interface prototype object for B with property name P.
      11. Return Result(10).
      12. Return undefined.
    • The [[CanPut]] internal method of the [[Prototype]] object for ab behaves as follows (where O is the object and P is the property name):
      1. If O doesn’t have a property with name P, go to step 4.
      2. If the property has the ReadOnly attribute, return false.
      3. Return true.
      4. Call the [[CanPut]] method of the interface prototype object for A with property name P.
      5. If Result(4) is false, return false.
      6. Call the [[CanPut]] method of the interface prototype object for B with property name P.
      7. If Result(6) is false, return false.
      8. Return true.

      Note that this method shouldn’t strictly be required, since there would be no way for script to get access to the [[Prototype]] object for ab.

    • The [[HasProperty]] internal method of the [[Prototype]] object for ab behaves as follows (where O is the object and P is the property name):
      1. If O has a property with name P, return true.
      2. Call the [[HasProperty]] method of the interface prototype object for A with property name P.
      3. If Result(2) is true, return true.
      4. Call the [[HasProperty]] method of the interface prototype object for B with property name P.
      5. If Result(5) is true, return true.
      6. Return false.
  • The [[Prototype]] internal property of the host object d is the interface prototype object for D, since D is the only interface the object directly implements.

4.3.1. Host object [[Get]] method

The internal [[Get]] method of every host object O that implements at least one IDL interface must behave as follows, assuming P is the property name passed to [[Get]]:

  1. Determine the name of an [IndexGetter]-annotated operation on the interfaces that O implements. If there is no such operation, go to step 8.
  2. Compute ToUint32(P).
  3. Compute ToString(Result(2)).
  4. If Result(3) is equal to P and Result(2) is not equal to 232 − 1, go to step 8.
  5. Invoke the [[Get]] method of object O with Result(1) as the argument.
  6. Invoke the [[Call]] method of Result(5), providing O as the this value and Result(2) as the single argument value.
  7. Return Result(5).
  8. Determine the name of a [NameGetter]-annotated operation on the interfaces that O implements. If there is no such operation, go to step 14.
  9. Invoke the [[HasProperty]] method of object O with P as the argument.
  10. If Result(9) is true, go to step 14.
  11. Invoke the [[Get]] method of object O with Result(7) as the argument.
  12. Invoke the [[Call]] method of Result(10), providing O as the this value and P as the single argument value.
  13. Return Result(11).
  14. If O doesn’t have a property with name P, go to step 17.
  15. Get the value of the property.
  16. Return Result(15).
  17. If the [[Prototype]] of O is null, return undefined.
  18. Call the [[Get]] method of [[Prototype]] with property name P.
  19. Return Result(18).

4.3.2. Host object [[Put]] method

The internal [[Put]] method of every host object O that implements at least one IDL interface must behave as follows, assuming P is the property name and V is the property value passed to [[Put]]:

  1. Determine the name of a [IndexSetter]-annotated operation on the interfaces that O implements. If there is no such operation, go to step 8.
  2. Compute ToUint32(P).
  3. Compute ToString(Result(2)).
  4. If Result(3) is equal to P and Result(2) is not equal to 232 − 1, go to step 8.
  5. Invoke the [[Get]] method of object O with Result(1) as the argument.
  6. Invoke the [[Call]] method of Result(5), providing O as the this value and Result(2) and V as the two argument values.
  7. Return Result(5).
  8. Determine the name of a [NameSetter]-annotated operation on the interfaces that O implements. If there is no such operation, go to step 14.
  9. Invoke the [[HasProperty]] method of object O with P as the argument.
  10. If Result(9) is true, go to step 14.
  11. Invoke the [[Get]] method of object O with Result(7) as the argument.
  12. Invoke the [[Call]] method of Result(10), providing O as the this value and P and V as the two argument values.
  13. Return Result(11).
  14. If O has a property with name P and that property does not correspond to an IDL operation declared readonly, then go to step 19.
  15. If the property on O with name P does not correspond to an IDL operation declared with a [PutForwards] extended attribute, then an implementation specific exception is thrown and these steps are ended.
  16. Call the [[Get]] method of O with name P.
  17. Call the [[Put]] method of Result(16) with the property name being the argument to the [PutForwards] extended attribute, and value V.
  18. Return.
  19. Call the [[CanPut]] method of O with name P.
  20. If Result(19) is false, return.
  21. If O doesn’t have a property with name P, go to step 23.
  22. Set the value of the property to V. The attributes of the property are not changed.
  23. Return.
  24. Create a property with name P, set its value to V and give it empty attributes.
  25. Return.

4.4. Native objects implementing interfaces

A native ECMAScript object is considered to implement a particular interface if it has properties corresponding to all operations on that interface, whose values are Function objects. The rules for which operations correspond to properties in the presence of overloaded operations is the same as described for host objects in section 4.2.4 above.

Editorial note

How operations correspond to attributes on native objects could be fleshed out about, rather than just refering to the host object Operations section earlier.

Note that if the interface has attributes declared on it, corresponding properties are not required to exist on the native object. Since native objects cannot have properties with attributes (such as ReadOnly), a property that does exist on the object that corresponds to a readonly attribute declared on the interface does not have to be read-only.

Since native objects cannot have custom internal properties, such objects implementing the interface are not required to honor the [IndexGetter], [IndexSetter], [NameGetter], [NameSetter] or [PutForwards] extended attributes.

As a special case, a Function object F is considered to implement an interface if that interface is declared with exactly one operation. The function itself is the implementation of the operation. If the Function object also has a property P whose name is the name of the operation and whose value is a Function object, then that P is used as the implementation of the operation rather than F.

4.5. Exceptions

For every exception that is not declared with the [NoInterfaceObject] extended attribute, a corresponding property must exist on the ECMAScript global object whose name is the identifier of the exception. The value of this property is an object called the exception interface object, which provides access to any constants that have been associated with the exception. The property has the attributes { DontDelete, DontEnum }.

4.5.1. Exception interface object

The exception interface object for a particular exception must have an internal [[Prototype]] object whose value is the Object prototype object.

If any constants have been associated with the exception through the [ExceptionConsts] extended attribute, then the exception interface object will have properties corresponding to these constants as described in section 4.5.3 below.

The exception interface object must also have a property named prototype with attributes { DontDelete, ReadOnly } whose value is an object called the exception interface prototype object. This object also provides access to the constants that are associated with the exception through the [ExceptionConsts] extended attribute.

4.5.1.1. Exception interface object [[HasInstance]] method

The internal [[HasInstance]] method of every exception interface object E must behave as follows, assuming V is the object argument passed to [[HasInstance]]:

  1. If V is not an object, return false.
  2. If V is a host object that is an exception whose exception interface object is E, return true.
  3. Return false.

4.5.2. Exception interface prototype object

There must exist an exception interface prototype object for every exception defined, regardless of whether the exception was declared with the [NoInterfaceObject] extended attribute. The exception interface prototype object for a particular exception has properties that correspond to the constants associated with the exception with the [ExceptionConsts] extended attribute. These properties are described in more detail in section 4.5.3 below.

4.5.3. Constants

If the enclosing module of the exception has an [ExceptionConsts] extended attribute whose argument is the identifier of the exception, then there must be a property, corresponding to each constant defined on the enclosing module, on the exception interface object (if it exists) and the exception interface prototype object:

  • The name of the property is the identifier of the constant.
  • The value of the property is the ECMAScript value that is equivalent to the constant’s IDL value, according to the rules in section 4.1 above.
  • The property has attributes { DontDelete }.

4.6. Host exception objects

A host exception object is a host object that implements a given exception. The behavior of a host object that implements more than one exception, or an exception as well as an interface, is not defined.

A host exception object must have a property for each exception member declared on the exception:

  • The name of the property is the identifier of the exception member.
  • The property has attributes { DontDelete }.

The value of the internal [[Prototype]] property of the host exception object must be the exception interface prototype object.

5. Java binding

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

5.1. Names

Since Java has a number of reserved words in the language, identifiers of Java constructs corresponding to IDL definitions need to be escaped to avoid conflicts. A name is Java escaped as follows:

  • If the name is a Java reserved word, then the Java escaped name is the name prefixed with a U+005F LOW LINE ("_") character.
  • Otherwise, the name is not a Java reserved word. The Java escaped name is simply the name.
Note

At the time of publication, the list of Java reserved words is the following: abstract, assert, boolean, break, byte, case, catch, char, class, const, continue, default, do, double, else, enum, extends, final, finally, float, for, goto, if, implements, import, instanceof, int, interface, long, native, new, package, private, protected, public, return, short, static, strictfp, super, switch, synchronized, this, throw, throws, transient, try, void, volatile, while.

5.2. Java type mapping

This section describes how types in the IDL map to types in Java.

5.2.1. any

The any IDL type corresponds to a Java java.lang.Object value. Values of IDL types that correspond to Java primitive types must be represented with an object according to the following table:

IDL type Java class
boolean java.lang.Boolean
octet java.lang.Byte
short java.lang.Short
unsigned short java.lang.Short
long java.lang.Integer
unsigned long java.lang.Integer
long long java.lang.Long
unsigned long long java.lang.Long
float java.lang.Float

5.2.2. void

The only place that the void type may appear in IDL is as the return type of an operation. Methods on Java objects that implement an operation whose IDL specifies a void return type must be declared to have a return type of void.

5.2.3. boolean

The IDL boolean type maps exactly to the Java boolean type.

5.2.4. octet

The IDL octet type corresponds to the Java byte type. Note that while the IDL octet type is unsigned, with a range of [0, 255], the Java byte type is signed, with a range of [−128, 127].

To encode an octet value in a byte, the following steps must be followed:

  1. Let x be the octet value to encode.
  2. If x < 128, return a byte whose value is x.
  3. Otherwise x ≥ 128. Return a byte whose value is x − 256.

Note that in Java this is the same as having the octet value stored in an int and casting it to a byte.

To decode an octet value from a byte, the following steps must be followed:

  1. Let x be the byte value to decode.
  2. If x ≥ 0, return an octet whose value is x.
  3. Otherwise x < 0. Return an octet whose value is x + 256.

Note that in Java this is the same as performing a bit-wise AND of the byte value with the int constant 0xff.

5.2.5. short

The IDL short type maps exactly to the Java short type.

5.2.6. unsigned short

The IDL unsigned short type corresponds to the Java short type. Note that while the IDL unsigned short type is unsigned, with a range of [0, 65535], the Java short type is signed, with a range of [−32768, 32767].

To encode an IDL unsigned short value in a Java short, the following steps must be followed:

  1. Let x be the IDL unsigned short value to encode.
  2. If x < 32768, return a Java short whose value is x.
  3. Otherwise x ≥ 32768. Return a Java short whose value is x − 65536.

Note that in Java this is the same as having the unsigned short value stored in an int and casting it to a short.

To decode an IDL unsigned short value from a Java short, the following steps must be followed:

  1. Let x be the Java short value to decode.
  2. If x ≥ 0, return an IDL unsigned short whose value is x.
  3. Otherwise x < 0. Return an IDL unsigned short whose value is x + 65536.

Note that in Java this is the same as performing a bit-wise AND of the short value with the int constant 0xffff.

5.2.7. long

The IDL long type maps exactly to the Java int type.

5.2.8. unsigned long

The IDL unsigned long type corresponds to the Java int type. Note that while the IDL unsigned long type is unsigned, with a range of [0, 4294967295], the Java int type is signed, with a range of [−2147483648, 2147483647].

To encode an IDL unsigned long value in a Java int, the following steps must be followed:

  1. Let x be the IDL unsigned long value to encode.
  2. If x < 2147483648, return a Java int whose value is x.
  3. Otherwise x ≥ 2147483648. Return a Java int whose value is x − 4294967296.

Note that in Java this is the same as having the unsigned long value stored in a Java long and casting it to an int.

To decode an IDL unsigned long value from a Java int, the following steps must be followed:

  1. Let x be the Java int value to decode.
  2. If x ≥ 0, return an IDL unsigned long whose value is x.
  3. Otherwise x < 0. Return an IDL unsigned long whose value is x + 4294967296.

Note that in Java this is the same as performing a bit-wise AND of the int value with the long constant 0xffffffffL.

5.2.9. long long

The IDL long long type maps exactly to the Java long type.

5.2.10. unsigned long long

The IDL unsigned long long type corresponds to the Java long type. Note that while the IDL unsigned long long type is unsigned, with a range of [0, 18446744073709551615], the Java long type is signed, with a range of [−9223372036854775808, 9223372036854775807].

To encode an IDL unsigned long long value in a Java long, the following steps must be followed:

  1. Let x be the IDL unsigned long long value to encode.
  2. If x < 18446744073709551616, return a Java long whose value is x.
  3. Otherwise x ≥ 18446744073709551616. Return a Java long whose value is x − 18446744073709551615.

To decode an IDL unsigned long long value from a Java long, the following steps must be followed:

  1. Let x be the Java long value to decode.
  2. If x ≥ 0, return an IDL unsigned long long whose value is x.
  3. Otherwise x < 0. Return an IDL unsigned long long whose value is x + 18446744073709551615.

5.2.11. float

The IDL float type maps exactly to the Java float type.

5.2.12. sequence<T>

The IDL sequence<T> type corresponds to a Java array of type T.

A Java object implementing an interface with an operation declared to return a sequence<T> value must not return null from the corresponding method. Similarly, a getter method for an IDL attribute must not return null if the attribute is declared to be of type sequence<T>.

A Java object implementing an interface with an operation declared to take an argument of type sequence<T> must throw a NullPointerException exception if null is passed as the corresponding argument to the corresponding method. Similarly, a setter method for an IDL attribute must throw a NullPointerException exception if the attribute is declared to be of type sequence<T>.

Editorial note

Should mention what to do with null values in nested sequences (e.g. sequence<sequence<short>>).

5.2.13. sequence<unsigned short>

As a special case, a sequence<unsigned short> is represented by a Java String object.

A Java object implementing an interface with an operation declared to return a sequence<unsigned short> value must not return null from the corresponding method. Similarly, a getter method for an IDL attribute must not return null if the attribute is declared to be of type sequence<unsigned short>.

A Java object implementing an interface with an operation declared to take an argument of type sequence<unsigned short> must throw a NullPointerException exception if null is passed as the corresponding argument to the corresponding method. Similarly, a setter method for an IDL attribute must throw a NullPointerException exception if the attribute is declared to be of type sequence<unsigned short>.

5.2.14. Object

The IDL Object type maps exactly to the Java java.lang.Object type.

5.2.15. Object implementing an interface

The IDL interface type maps exactly to the corresponding Java interface type.

5.2.16. Boxed valuetype

A boxed valuetype is represented differently depending on the type being boxed. Let T be the type being boxed.

If T maps to a Java object value, which is the case for any, sequence<T>, sequence<unsigned short>, Object and interface types, then a boxed valuetype is represented by the Java null value (if the value of the boxed valuetype is null) or by a value as described in this section for the mapping for T (if the value of the boxed valuetype is not null). Thus, a Java object whose method implements an operation declared to take an argument of a sequence type must not throw an exception simply for being passed a null value.

Editorial note

What to do if [NoNull] is used? Throw, or something else?

If T does not map to a Java object value, then the boxed valuetype maps to a Java class as specified in the table below:

T Java class
boolean java.lang.Boolean
octet java.lang.Byte
short java.lang.Short
unsigned short java.lang.Short
long java.lang.Integer
unsigned long java.lang.Integer
long long java.lang.Long
unsigned long long java.lang.Long
float java.lang.Float

If the value of the boxed valuetype is not null, then the value stored inside the object of the given class must be as specified by the rules in this section for type T.

5.3. Modules

Every IDL module corresponds to a Java package, whose name is derived as follows:

  • If the module has been declared at the outermost scope, then the name of the corresponding Java package is the Java escaped identifier of the module.
  • Otherwise, the module has not been declared at the outermost scope. The name of the corresponding Java package is the name of the Java package corresponding to the enclosing module of this module, followed by a U+002E FULL STOP ("."), followed by the Java escaped identifier of the module.

Definitions inside an IDL module correspond to Java constructs declared to be in the package for that module.

Example

The following IDL will cause a Java interface named HTMLDocument in package org.w3c.dom.html to exist:

IDL
[Prefix="org::w3c::dom"]
module html {
  interface HTMLDocument {
    // …
  };
};
Java
package org.w3c.dom.html;

interface HTMLDocument {
  // …
}
Editorial note

The example uses [Prefix] and doesn’t match the prose above. Is [Prefix] a reasonable way to map modules to Java packages? It seems to me that just using the module structure to map to the package name is more natural:

IDL
module org {
  module w3c {
    module dom {
      module html {
        // …
      };
    };
  };
};

But that’s pretty verbose. In C++ you can skip steps in one go, so something similar in IDL would be:

IDL
module org::w3c::dom::html {
  // …
};

But that is not syntactically compatible with OMG IDL.

5.4. Interfaces

A conforming Java implementation must have a public Java interface corresponding to to every IDL interface that is supported, whose name is the Java escaped identifier of the IDL interface and which resides in the Java package corresponding to the interface’s enclosing module.

The Java interface must be declared to extend every Java interface that corresponds to an interface from which this IDL interface inherits.

5.4.1. Constants

For each constant defined on the IDL interface, there must be a corresponding constant declared on the Java interface with the following properties:

  • The constant has no modifiers.
  • The type of the constant is the Java type that corresponds to the type of the IDL constant, according to the rules in section 5.2 above.
  • The name of the constant is the Java escaped identifier of the constant.
  • The value of the constant is the Java value that is equivalent to the constant’s IDL value, according to the rules in section 5.2 above.

5.4.2. Operations

For each operation defined on the IDL interface, there must be a corresponding method declared on the Java interface with the following properties:

  • The method has no modifiers.
  • The return type of the method is the Java type that corresponds to the operation return type, according to the rules in section 5.2 above.
  • The tenative name of the method is the Java escaped identifier of the operation. The name of the method is the tenative name of the method prefixed with the smallest number of U+005F LOW LINE ("_") characters required to make the name not equal to the name of a constant declared on the Java interface or one of the methods on the java.lang.Object class.
  • The method has an argument for each argument on the operation. The type of the method argument is as follows. Let T be the Java type that corresponds to the operation argument type according to the rules in section 5.2 above. If the argument is the final argument on the operation, and it is declared with the [Variadic] extended attribute, then the type of the method argument will be an array of T (i.e., T[]). Otherwise, the type of the method argument will be T.
Editorial note

Recent versions of Java can actually do varargs.

Editorial note

Some overloaded operations in the IDL can correspond to a single method. This needs to be taken into account in this section. For example:

IDL
interface A {

  void f(in Object x);
  void f(in any x);
};

In addition, the method should have a throws clause specifying all of the Java exception classes that correspond to the IDL exceptions that are listed in the Raises clause of the operation, and no others.

5.4.3. Attributes

For each attribute defined on the IDL interface, there must be a corresponding getter method declared on the Java interface with the following properties:

  • The method has no modifiers.
  • The return type of the method is the Java type that corresponds to the attribute type, according to the rules in section 5.2 above.
  • The tentative name of the method is a U+0067 LATIN SMALL G ("g") character, followed by a U+0065 LATIN SMALL E ("e") character, followed by a U+0074 LATIN SMALL T ("t") character, followed by the first character of the identifier of the attribute uppercased (as if passed to the java.lang.Character.toUpperCase() method), followed by the remaining characters from the identifier of the attribute. The name of the method is the Java escaped tenative name of the method prefixed with the smallest number of U+005F LOW LINE ("_") characters required to make the name not equal to the name of a constant or method declared on the Java interface or one of the methods on the java.lang.Object class.
  • The method has no arguments.

In addition, the method should have a throws clause specifying all of the Java exception classes that correspond to the IDL exceptions that are listed in the GetRaises clause of the attribute, and no others.

For each attribute defined on the IDL interface that is not read only, there must be a corresponding setter method declared on the Java interface with the following properties:

  • The method has no modifiers.
  • The return type of the method is void.
  • The tentative name of the method is a U+0073 LATIN SMALL S ("s") character, followed by a U+0065 LATIN SMALL E ("e") character, followed by a U+0074 LATIN SMALL T ("t") character, followed by the first character of the identifier of the attribute uppercased (as if passed to the java.lang.Character.toUpperCase() method), followed by the remaining characters from the identifier of the attribute. The name of the method is the Java escaped tenative name of the method prefixed with the smallest number of U+005F LOW LINE ("_") characters required to make the name not equal to the name of a constant or method declared on the Java interface or one of the methods on the java.lang.Object class.
  • The method has a single argument whose type is the Java type that corresponds to the attribute type, according to the rules in section 5.2 above.

In addition, the method should have a throws clause specifying all of the Java exception classes that correspond to the IDL exceptions that are listed in the SetRaises clause of the attribute, and no others.

For each attribute defined on the IDL interface that is read only and is declared with the [PutForwards] extended attribute, there must be a corresponding setter method declared on the Java interface with the following properties:

  • The method has no modifiers.
  • The return type of the method is void.
  • The tentative name of the method is a U+0073 LATIN SMALL S ("s") character, followed by a U+0065 LATIN SMALL E ("e") character, followed by a U+0074 LATIN SMALL T ("t") character, followed by the first character of the identifier of the attribute uppercased (as if passed to the java.lang.Character.toUpperCase() method), followed by the remaining characters from the identifier of the attribute. The name of the method is the Java escaped tenative name of the method prefixed with the smallest number of U+005F LOW LINE ("_") characters required to make the name not equal to the name of a constant or method declared on the Java interface or one of the methods on the java.lang.Object class.
  • The method has a single argument whose type is the Java type that corresponds to the type of the attribute identified by the [PutForwards] extended attribute on the interface type that this attribute is declared to be of, according to the rules in section 5.2 above.

In addition, the method should have a throws clause specifying all of the Java exception classes that correspond to the IDL exceptions that are listed in the SetRaises clause of the attribute identified by the [PutForwards] extended attribute on the interface type that this attribute is declared to be of, and no others.

5.5. Objects implementing interfaces

A Java object that implements an IDL interface must be of a Java class that implements the Java interface that corresponds to the IDL interface.

If the IDL interface is declared with the [Stringifies] extended attribute, the String toString() method must be overridden to allow stringification of the object as required by the IDL interface. If the [Stringifies] extended attribute on the IDL interface has an identifier argument A, assuming O is the object on which the method was invoked, the behavior of the overridden toString method must be as follows:

  1. Invoke the getter method on O that corresponds to the IDL attribute A.
  2. Return Result(1).

If the [Stringifies] extended attribute on the IDL interface was not given an argument, then the behavior of the overridden toString() method is the stringification behavior of the IDL interface, as described in the prose for the IDL interface.

Editorial note

Should say what happens if [Stringifies] is used on an interface that also has a toString operation.

5.6. Exceptions

A conforming Java implementation must have a Java class corresponding to every IDL exception that is supported, whose name is the Java escaped identifier of the IDL exception and which resides in the Java package corresponding to the exception’s enclosing module.

The Java class must have only the public modifier, and be declared to extend java.lang.RuntimeException.

5.6.1. Constants

For each constant defined on the enclosing module of the IDL exception, where that module has been declared with the [ExceptionConsts] extended attribute, there must be a corresponding constant declared on the Java class with the following properties:

  • The constant has no modifiers.
  • The type of the constant is the Java type that corresponds to the type of the IDL constant, according to the rules in section 5.2 above.
  • The name of the constant is the Java escaped identifier of the constant.
  • The value of the constant is the Java value that is equivalent to the constant’s IDL value, according to the rules in section 5.2 above.

5.6.2. Exception members

For each exception member defined on the exception, there must be a corresponding instance variable declared on the Java class with the following properties:

  • The instance variable has only the modifier public.
  • The type of the instance variable is the Java type that corresponds to the type of the IDL exception member, according to the rules in section 5.2 above.
  • The name of the instance variable is the Java escaped identifier of the exception member.
  • The instance variable is not declared with an initializer.

6. Extensibility

This section is informative.

7. Referencing this specification

This section is informative.

It is expected that other specifications that define DOM interfaces using a conforming IDL fragment will reference this specification. It is suggested that those specifications include a sentence such as the following, to indicate that the IDL is to be interpreted as described in this specification:

The IDL fragment in Appendix A of this specification must be interpreted as required for conforming IDL fragments, as described in the “Language Bindings for DOM Specifications” specification. [DOMBIND]

In addition, it is suggested that the conformance class for user agents in referencing specifications be linked to the conforming implementation class from this specification:

A conforming FooML user agent must also be a conforming implementation of the IDL fragment in Appendix A of this specification, as described in the “Language Bindings for DOM Specifications” specification. [DOMBIND]

8. Acknowledgements

This section is informative.

The editor would like to thank the following people for contributing to this specification: David Andersson, Robin Berjon, Gorm Haug Eriksen, Ian Hickson, Björn Höhrmann, Anne van Kesteren, Jim Ley, Simon Pieters, Jonas Sicking, Maciej Stachowiak, Boris Zbarsky.

A. IDL grammar

This section defines an LL(1) grammar whose start symbol, Definitions, matches an entire IDL fragment.

Each production in the grammar has on its right hand side either a non-zero sequence of terminal and non-terminal symbols, or an epsilon (ε) which indicates no symbols. Symbols that begin with an uppercase letter are non-terminal symbols. Symbols within quotes are terminal symbols that are matched with the exact text between the quotes. Symbols that begin with a lowercase letter are terminal symbols that are matched by the regular expressions (using Perl 5 regular expression syntax [PERLRE]) as follows:

integer = -?0([0-7]*|[Xx][0-9A-Fa-f]+)|[1-9][0-9]*
float = -?([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+
identifier = [A-Z_a-z][0-9A-Z_a-z]*
whitespace = [\t\n\r ]+|[\t\n\r ]*((//.*|/\*.*?\*/)[\t\n\r ]*)+
Editorial note

Should we require quoting (with an underscore) of identifiers that would match keywords used in OMG IDL 3.0 but not in this IDL?

When tokenizing, the longest possible match must be used. For example, if the input text is “a1”, it should be tokenized as a single identifier, and not as a separate identifier and integer. If the longest possible match could match both an identifier and one of the quoted terminal symbols from the grammar, it must be tokenized as the quoted terminal symbol. Thus, the input text “in” is tokenized as the quoted terminal symbol "in" rather than an identifier called “in”.

Implicitly, the whitespace terminal is allowed between every terminal in the input text being parsed. Such whitespace terminals, which actually encompass both whitespace and comments, are ignored while parsing.

The following LL(1) grammar matches an IDL fragment:

[1]DefinitionsExtendedAttributeList Definition Definitions
 | ε
[2]DefinitionModule
 | Interface
 | Exception
 | Typedef
 | Valuetype
 | Const
[3]Module"module" identifier "{" Definitions "}" ";"
[4]Interface"interface" identifier InterfaceBody ";"
[5]InterfaceInheritance":" ScopedNameList
 | ε
[6]InterfaceBodyInterfaceInheritance "{" InterfaceMembers "}"
 | ε
[7]InterfaceMembersExtendedAttributeList InterfaceMember InterfaceMembers
 | ε
[8]InterfaceMemberConst
 | Attribute
 | Operation
[9]Exception"exception" identifier "{" ExceptionMembers "}" ";"
[10]ExceptionMembersExtendedAttributeList ExceptionMember ExceptionMembers
 | ε
[11]Typedef"typedef" Type identifier ";"
[12]Valuetype"valuetype" identifier BoxedType ";"
[13]Const"const" DeclarationType identifier "=" ConstExpr ";"
[14]ConstExprBooleanLiteral
 | integer
 | float
[15]BooleanLiteral"TRUE"
 | "FALSE"
[16]AttributeReadOnly "attribute" DeclarationType identifier GetRaises SetRaises ";"
[17]ReadOnly"readonly"
 | ε
[18]GetRaises"getraises" ExceptionList
 | ε
[19]SetRaises"setraises" ExceptionList
 | ε
[20]OperationReturnType identifier "(" ArgumentList ")" Raises ";"
[21]Raises"raises" ExceptionList
 | ε
[22]ExceptionList"(" ScopedNameList ")"
[23]ArgumentListArgument Arguments
 | ε
[24]Arguments"," Argument Arguments
 | ε
[25]ArgumentExtendedAttributeList "in" DeclarationType identifier
[26]ExceptionMemberDeclarationType identifier ";"
[27]ExtendedAttributeList"[" ExtendedAttribute ExtendedAttributes "]"
 | ε
[28]ExtendedAttributes"," ExtendedAttribute ExtendedAttributes
 | ε
[29]ExtendedAttributeidentifier ExtendedAttributeAssignment
[30]ExtendedAttributeAssignment"=" ExtendedAttributeArgument
 | ε
[31]ExtendedAttributeArgumentidentifier
[32]DeclarationTypeUnsignedIntegerType
 | ScopedName
 | "any"
 | "boolean"
 | "octet"
 | "float"
 | "Object"
[33]BoxedTypeUnsignedIntegerType
 | ScopedName
 | "boolean"
 | "octet"
 | "float"
 | "sequence" "<" Type ">"
[34]TypeDeclarationType
 | "sequence" "<" Type ">"
[35]UnsignedIntegerType"unsigned" IntegerType
 | IntegerType
[36]IntegerType"short"
 | "long" OptionalLong
[37]OptionalLong"long"
 | ε
[38]ReturnTypeDeclarationType
 | "void"
[39]ScopedNameListScopedName ScopedNames
[40]ScopedNames"," ScopedName ScopedNames
 | ε
[41]ScopedName"::" identifier ScopedNameParts
 | identifier ScopedNameParts
[42]ScopedNameParts"::" identifier ScopedNameParts
 | ε
Editorial note

Still not sure how we should handle extensibility of extended attributes.

B. References

[ECMA-262]
ECMAScript Language Specification, 3rd Edition, M. Cowlishaw, Editor. Ecma International, December 1999. Available at http://www.ecma-international.org/publications/standards/Ecma-262.htm.
[IEEE-754]
IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-1985). Institute of Electrical and Electronics Engineers, 1985.
[OMGIDL]
CORBA 3.0 – OMG IDL Syntax and Semantics chapter. Object Management Group, June 2002. Available at http://www.omg.org/cgi-bin/apps/doc?formal/02-06-39.pdf.
[PERLRE]
Perl regular expressions (Perl 5.8.8). The Perl Foundation, February 2006. Available at http://www.perl.com/doc/manual/html/pod/perlre.html.
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels, S. Bradner. IETF, March 1997. Available at http://www.ietf.org/rfc/rfc2119.

C. Changes

The following is a list of substantial changes to the document on each publication.

10 April 2008 – WD
  • Restricted boxed valuetypes to boxing only types that cannot already have null.

  • Reworked how operation overloading is specified (the [Overloads] extended attribute is no longer needed), and how ECMAScript disambiguates calls to overloaded operations.

  • Filled in the “Host exception objects” section.

  • Added an exception interface prototype object for constants to live in. Added constants to interface objects, interface prototype objects, exception interface objects and exception interface prototype objects.

  • Tweaked the behavior of sequences in ECMAScript.

  • Added an editorial note about the possibility of somehow specifying HTML 5’s Image constructor.

  • Added a [NoInterfaceObject] extended attribute, which prevents an ECMAScript interface object being created for the interface on which it appears.

  • Added a [Stringifies] extended attribute.

  • Fixed small bugs in [[HasProperty]], [[Get]] and [[Put]] algorithms for ECMAScript host objects.

  • Added an editorial note about the possibility of an extended attribute that specifies what properties get enumerated in a for..in loop in ECMAScript.

17 October 2007 – FPWD
  • Initial publication.