DOM

Living Standard — Last Updated

Participate:
GitHub whatwg/dom (new issue, open issues, legacy open bugs)
IRC: #whatwg on Freenode
Commits:
GitHub whatwg/dom/commits
@thedomstandard
Translation (non-normative):
日本語

Abstract

DOM defines a platform-neutral model for events and node trees.

Goals

This specification standardizes the DOM. It does so as follows:

  1. By consolidating DOM Level 3 Core [DOM-Level-3-Core], Element Traversal [ELEMENTTRAVERSAL], Selectors API Level 2 [SELECTORS-API2], the "DOM Event Architecture" and "Basic Event Interfaces" chapters of DOM Level 3 Events [uievents-20031107] (specific types of events do not belong in the DOM Standard), and DOM Level 2 Traversal and Range [DOM-Level-2-Traversal-Range], and:

    • Aligning them with the JavaScript ecosystem where possible.
    • Aligning them with existing implementations.
    • Simplifying them as much as possible.
  2. By moving features from the HTML Standard [HTML] that make more sense to be specified as part of the DOM Standard.

  3. By defining a replacement for the "Mutation Events" and "Mutation Name Event Types" chapters of DOM Level 3 Events [uievents-20031107] as the old model was problematic.

    The old model is expected to be removed from implementations in due course.

  4. By defining new features that simplify common DOM operations.

1. Conformance

All diagrams, examples, and notes in this specification are non-normative, as are all sections explicitly marked non-normative. Everything else in this specification is normative.

The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119. For readability, these words do not appear in all uppercase letters in this specification. [RFC2119]

Requirements phrased in the imperative as part of algorithms (such as "strip any leading space characters" or "return false and terminate these steps") are to be interpreted with the meaning of the keyword ("must", "should", "may", etc.) used in introducing the algorithm.

Conformance requirements phrased as algorithms or specific steps may be implemented in any manner, so long as the end result is equivalent. (In particular, the algorithms defined in this specification are intended to be easy to follow, and not intended to be performant.)

User agents may impose implementation-specific limits on otherwise unconstrained inputs, e.g. to prevent denial of service attacks, to guard against running out of memory, or to work around platform-specific limitations.

When a method or an attribute is said to call another method or attribute, the user agent must invoke its internal API for that attribute or method so that e.g. the author can’t change the behavior by overriding attributes or methods with custom properties or functions in JavaScript.

Unless otherwise stated, string comparisons are done in a case-sensitive manner.

1.1. Dependencies

The IDL fragments in this specification must be interpreted as required for conforming IDL fragments, as described in the Web IDL specification. [WEBIDL]

Some of the terms used in this specification are defined in Encoding, Selectors, Web IDL, XML, and Namespaces in XML. [ENCODING] [SELECTORS4] [WEBIDL] [XML] [XML-NAMES]

1.2. Extensibility

Vendor-specific proprietary extensions to this specification are strongly discouraged. Authors must not use such extensions, as doing so reduces interoperability and fragments the user base, allowing only users of specific user agents to access the content in question.

When extensions are needed, the DOM Standard can be updated accordingly, or a new standard can be written that hooks into the provided extensibility hooks for applicable specifications.

2. Terminology

The term context object means the object on which the algorithm, attribute getter, attribute setter, or method being discussed was called. When the context object is unambiguous, the term can be omitted.

2.1. Trees

A tree is a finite hierarchical tree structure. In tree order is preorder, depth-first traversal of a tree.

An object that participates in a tree has a parent, which is either another object or null, and an ordered list of zero or more child objects. An object A whose parent is object B is a child of B.

The root of an object is itself, if its parent is null, or else it is the root of its parent. The root of a tree is any object participating in that tree whose parent is null.

An object A is called a descendant of an object B, if either A is a child of B or A is a child of an object C that is a descendant of B.

An inclusive descendant is an object or one of its descendants.

An object A is called an ancestor of an object B if and only if B is a descendant of A.

An inclusive ancestor is an object or one of its ancestors.

An object A is called a sibling of an object B, if and only if B and A share the same non-null parent.

An inclusive sibling is an object or one of its siblings.

An object A is preceding an object B if A and B are in the same tree and A comes before B in tree order.

An object A is following an object B if A and B are in the same tree and A comes after B in tree order.

The first child of an object is its first child or null if it has no children.

The last child of an object is its last child or null if it has no children.

The previous sibling of an object is its first preceding sibling or null if it has no preceding sibling.

The next sibling of an object is its first following sibling or null if it has no following sibling.

The index of an object is its number of preceding siblings.

2.2. Strings

Comparing two strings in a case-sensitive manner means comparing them exactly, code point for code point.

Comparing two strings in a ASCII case-insensitive manner means comparing them exactly, code point for code point, except that the characters in the range U+0041 to U+005A (i.e. LATIN CAPITAL LETTER A to LATIN CAPITAL LETTER Z), inclusive, and the corresponding characters in the range U+0061 to U+007A (i.e. LATIN SMALL LETTER A to LATIN SMALL LETTER Z), inclusive, are considered to also match.

Converting a string to ASCII uppercase means replacing all characters in the range U+0061 to U+007A, inclusive, with the corresponding characters in the range U+0041 to U+005A, inclusive.

Converting a string to ASCII lowercase means replacing all characters in the range U+0041 to U+005A, inclusive, with the corresponding characters in the range U+0061 to U+007A, inclusive.

A string pattern is a prefix match for a string s when pattern is not longer than s and truncating s to pattern’s length leaves the two strings as matches of each other.

2.3. Ordered sets

The ordered set parser takes a string input and then runs these steps:

  1. Let position be a pointer into input, initially pointing at the start of the string.
  2. Let tokens be an ordered set of tokens, initially empty.
  3. Skip ASCII whitespace.
  4. While position is not past the end of input:
    1. Collect a code point sequence of code points that are not ASCII whitespace.
    2. If the collected string is not in tokens, append the collected string to tokens.
    3. Skip ASCII whitespace.
  5. Return tokens.

To collect a code point sequence of code points, run these steps:

  1. Let input and position be the same variables as those of the same name in the algorithm that invoked these steps.
  2. Let result be the empty string.
  3. While position does not point past the end of input and the code point at position is one of code points, append that code point to the end of result and advance position to the next code point in input.
  4. Return result.

To skip ASCII whitespace means to collect a code point sequence of ASCII whitespace and discard the return value.

The ordered set serializer takes a set and returns the concatenation of the strings in set, separated from each other by U+0020, if set is non-empty, and the empty string otherwise.

2.4. Selectors

To match a relative selectors string relativeSelectors against a set, run these steps:

  1. Let s be the result of parse a relative selector from relativeSelectors against set. [SELECTORS4]
  2. If s is failure, throw a SyntaxError.
  3. Return the result of evaluate a selector s using :scope elements set. [SELECTORS4]

To scope-match a selectors string selectors against a node, run these steps:

  1. Let s be the result of parse a selector selectors. [SELECTORS4]
  2. If s is failure, throw a SyntaxError.
  3. Return the result of evaluate a selector s against node’s root using scoping root node and scoping method scope-filtered. [SELECTORS4].

Support for namespaces within selectors is not planned and will not be added.

2.5. Namespaces

The HTML namespace is http://www.w3.org/1999/xhtml.

The SVG namespace is http://www.w3.org/2000/svg.

The XML namespace is http://www.w3.org/XML/1998/namespace.

The XMLNS namespace is http://www.w3.org/2000/xmlns/.

To validate a qualifiedName, run these steps:

  1. If qualifiedName does not match the Name production, then throw an InvalidCharacterError.

  2. If qualifiedName does not match the QName production, then throw a NamespaceError.

To validate and extract a namespace and qualifiedName, run these steps:

  1. If namespace is the empty string, set it to null.
  2. Validate qualifiedName. Rethrow any exceptions.
  3. Let prefix be null.
  4. Let localName be qualifiedName.
  5. If qualifiedName contains a ":" (U+003E), then split the string on it and set prefix to the part before and localName to the part after.
  6. If prefix is non-null and namespace is null, then throw a NamespaceError.
  7. If prefix is "xml" and namespace is not the XML namespace, then throw a NamespaceError.
  8. If either qualifiedName or prefix is "xmlns" and namespace is not the XMLNS namespace, then throw a NamespaceError.
  9. If namespace is the XMLNS namespace and neither qualifiedName nor prefix is "xmlns", then throw a NamespaceError.
  10. Return namespace, prefix, and localName.

3. Events

3.1. Introduction to "DOM Events"

Throughout the web platform events are dispatched to objects to signal an occurrence, such as network activity or user interaction. These objects implement the EventTarget interface and can therefore add event listeners to observe events by calling addEventListener():

obj.addEventListener("load", imgFetched)

function imgFetched(ev) {
  // great success
  
}

Event listeners can be removed by utilizing the removeEventListener() method, passing the same arguments.

Events are objects too and implement the Event interface (or a derived interface). In the example above ev is the event. It is passed as argument to event listener’s callback (typically a JavaScript Function as shown above). Event listeners key off the event’s type attribute value ("load" in the above example). The event’s target attribute value returns the object to which the event was dispatched (obj above).

Now while typically events are dispatched by the user agent as the result of user interaction or the completion of some task, applications can dispatch events themselves, commonly known as synthetic events:

// add an appropriate event listener
obj.addEventListener("cat", function(e) { process(e.detail) })

// create and dispatch the event
var event = new CustomEvent("cat", {"detail":{"hazcheeseburger":true}})
obj.dispatchEvent(event)

Apart from signaling, events are sometimes also used to let an application control what happens next in an operation. For instance as part of form submission an event whose type attribute value is "submit" is dispatched. If this event’s preventDefault() method is invoked, form submission will be terminated. Applications who wish to make use of this functionality through events dispatched by the application (synthetic events) can make use of the return value of the dispatchEvent() method:

if(obj.dispatchEvent(event)) {
  // event was not canceled, time for some magic
  
}

When an event is dispatched to an object that participates in a tree (e.g. an element), it can reach event listeners on that object’s ancestors too. First all object’s ancestor event listeners whose capture variable is set to true are invoked, in tree order. Second, object’s own event listeners are invoked. And finally, and only if event’s bubbles attribute value is true, object’s ancestor event listeners are invoked again, but now in reverse tree order.

Lets look at an example of how events work in a tree:

<!doctype html>
<html>
 <head>
  <title>Boring example</title>
 </head>
 <body>
  <p>Hello <span id=x>world</span>!</p>
  <script>
   function test(e) {
     debug(e.target, e.currentTarget, e.eventPhase)
   }
   document.addEventListener("hey", test, {capture: true})
   document.body.addEventListener("hey", test)
   var ev = new Event("hey", {bubbles:true})
   document.getElementById("x").dispatchEvent(ev)
  </script>
 </body>
</html>

The debug function will be invoked twice. Each time the event’s target attribute value will be the span element. The first time currentTarget attribute’s value will be the document, the second time the body element. eventPhase attribute’s value switches from CAPTURING_PHASE to BUBBLING_PHASE. If an event listener was registered for the span element, eventPhase attribute’s value would have been AT_TARGET.

3.2. Interface Event

[Constructor(DOMString type, optional EventInit eventInitDict),
 Exposed=(Window,Worker)]
interface Event {
  readonly attribute DOMString type;
  readonly attribute EventTarget? target;
  readonly attribute EventTarget? currentTarget;
  sequence<EventTarget> composedPath();

  const unsigned short NONE = 0;
  const unsigned short CAPTURING_PHASE = 1;
  const unsigned short AT_TARGET = 2;
  const unsigned short BUBBLING_PHASE = 3;
  readonly attribute unsigned short eventPhase;

  void stopPropagation();
  void stopImmediatePropagation();

  readonly attribute boolean bubbles;
  readonly attribute boolean cancelable;
  void preventDefault();
  readonly attribute boolean defaultPrevented;
  readonly attribute boolean composed;

  [Unforgeable] readonly attribute boolean isTrusted;
  readonly attribute DOMTimeStamp timeStamp;

  void initEvent(DOMString type, boolean bubbles, boolean cancelable); // historical
};

dictionary EventInit {
  boolean bubbles = false;
  boolean cancelable = false;
  boolean composed = false;
};

An Event object is simply named an event. It allows for signaling that something has occurred, e.g., that an image has completed downloading.

An event has an associated path. A path is a list of tuples, each of which consists of an item (an EventTarget object) and a target (null or an EventTarget object). A tuple is formatted as (item, target). A path is initially the empty list.

event = new Event(type [, eventInitDict])
Returns a new event whose type attribute value is set to type. The optional eventInitDict argument allows for setting the bubbles and cancelable attributes via object members of the same name.
event . type
Returns the type of event, e.g. "click", "hashchange", or "submit".
event . target
Returns the object to which event is dispatched.
event . currentTarget
Returns the object whose event listener’s callback is currently being invoked.
event . composedPath()
Returns the item objects of event’s path (objects on which listeners will be invoked), except for any nodes in shadow trees of which the shadow root’s mode is "closed" that are not reachable from event’s currentTarget.
event . eventPhase
Returns the event’s phase, which is one of NONE, CAPTURING_PHASE, AT_TARGET, and BUBBLING_PHASE.
event . stopPropagation()
When dispatched in a tree, invoking this method prevents event from reaching any objects other than the current object.
event . stopImmediatePropagation()
Invoking this method prevents event from reaching any registered event listeners after the current one finishes running and, when dispatched in a tree, also prevents event from reaching any other objects.
event . bubbles
Returns true or false depending on how event was initialized. True if event goes through its target attribute value’s ancestors in reverse tree order, and false otherwise.
event . cancelable
Returns true or false depending on how event was initialized. Its return value does not always carry meaning, but true can indicate that part of the operation during which event was dispatched, can be canceled by invoking the preventDefault() method.
event . preventDefault()
If invoked when the cancelable attribute value is true, and while executing a listener for the event with passive set to false, signals to the operation that caused event to be dispatched that it needs to be canceled.
event . defaultPrevented
Returns true if preventDefault() was invoked successfully to indicate cancellation, and false otherwise.
event . composed
Returns true or false depending on how event was initialized. True if event invokes listeners past a ShadowRoot node that is the root of its target attribute value, and false otherwise.
event . isTrusted
Returns true if event was dispatched by the user agent, and false otherwise.
event . timeStamp
Returns the creation time of event as the number of milliseconds that passed since 00:00:00 UTC on 1 January 1970.

The type attribute must return the value it was initialized to. When an event is created the attribute must be initialized to the empty string.

The target and currentTarget attributes must return the values they were initialized to. When an event is created the attributes must be initialized to null.

The composedPath() method, when invoked, must run these steps:

  1. Let composedPath be a new empty list.

  2. Let currentTarget be context object’s currentTarget attribute value.

  3. For each tuple in context object’s path:

    1. If currentTarget is a node and tuple’s item is an unclosed node of currentTarget, or currentTarget is not a node, then append tuple’s item to composedPath.

  4. Return composedPath.

This algorithm assumes that when the target argument to the dispatch algorithm is not a node, none of the tuples in event argument’s eventual path will contain a node either.

The eventPhase attribute must return the value it was initialized to, which must be one of the following:

NONE (numeric value 0)
Events not currently dispatched are in this phase.
CAPTURING_PHASE (numeric value 1)
When an event is dispatched to an object that participates in a tree it will be in this phase before it reaches its target attribute value.
AT_TARGET (numeric value 2)
When an event is dispatched it will be in this phase on its target attribute value.
BUBBLING_PHASE (numeric value 3)
When an event is dispatched to an object that participates in a tree it will be in this phase after it reaches its target attribute value.
Initially the attribute must be initialized to NONE.

Each event has the following associated flags that are all initially unset:

The stopPropagation() method, when invoked, must set the context object’s stop propagation flag.

The stopImmediatePropagation() method, when invoked, must set context object’s stop propagation flag and context object’s stop immediate propagation flag.

The bubbles and cancelable attributes must return the values they were initialized to.

The preventDefault() method, when invoked, must set the canceled flag if the cancelable attribute value is true and the in passive listener flag is unset.

This means there are scenarios where invoking preventDefault() has no effect. User agents are encouraged to log the precise cause in a developer console, to aid debugging.

The defaultPrevented attribute’s getter must return true if context object’s canceled flag is set, and false otherwise.

The composed attribute’s getter must return true if context object’s composed flag is set, and false otherwise.


The isTrusted attribute must return the value it was initialized to. When an event is created the attribute must be initialized to false.

The timeStamp attribute must return the value it was initialized to. When an event is created the attribute must be initialized to the number of milliseconds that have passed since 00:00:00 UTC on 1 January 1970, ignoring leap seconds.

This is highly likely to change and already does not reflect implementations well. Please see dom #23 for more details.


To initialize an event, with type, bubbles, and cancelable, run these steps:

  1. Set the initialized flag.
  2. Unset the stop propagation flag, stop immediate propagation flag, and canceled flag.
  3. Set the isTrusted attribute to false.
  4. Set the target attribute to null.
  5. Set the type attribute to type.
  6. Set the bubbles attribute to bubbles.
  7. Set the cancelable attribute to cancelable.

The initEvent(type, bubbles, cancelable) method, when invoked, must run these steps:

  1. If context object’s dispatch flag is set, then return.

  2. Initialize context object with type, bubbles, and cancelable.

As events have constructors initEvent() is redundant and incapable of setting composed. It has to be supported for legacy content.

3.3. Interface CustomEvent

[Constructor(DOMString type, optional CustomEventInit eventInitDict),
 Exposed=(Window,Worker)]
interface CustomEvent : Event {
  readonly attribute any detail;

  void initCustomEvent(DOMString type, boolean bubbles, boolean cancelable, any detail);
};

dictionary CustomEventInit : EventInit {
  any detail = null;
};

Events using the CustomEvent interface can be used to carry custom data.

event = new CustomEvent(type [, eventInitDict])
Works analogously to the constructor for Event except that the optional eventInitDict argument now allows for setting the detail attribute too.
event . detail
Returns any custom data event was created with. Typically used for synthetic events.

The detail attribute must return the value it was initialized to.

The initCustomEvent(type, bubbles, cancelable, detail) method must, when invoked, run these steps:

  1. If context object’s dispatch flag is set, terminate these steps.
  2. Initialize the context object with type, bubbles, and cancelable.
  3. Set context object’s detail attribute to detail.

3.4. Constructing events

When a constructor of the Event interface, or of an interface that inherits from the Event interface, is invoked, these steps must be run:

  1. Create an event that uses the interface the constructor was invoked upon.

  2. Set its initialized flag.

  3. Initialize the type attribute to the type argument.

  4. If there is an eventInitDict argument, then for each dictionary member present, find the attribute on event whose identifier matches the key of the dictionary member and then set the attribute to the value of that dictionary member.

  5. Return the event.

3.5. Defining event interfaces

In general, when defining a new interface that inherits from Event please always ask feedback from the WHATWG or the W3C WebApps WG community.

The CustomEvent interface can be used as starting point. However, do not introduce any init*Event() methods as they are redundant with constructors. Interfaces that inherit from the Event interface that have such a method only have it for historical reasons.

3.6. Interface EventTarget

[Exposed=(Window,Worker)]
interface EventTarget {
  void addEventListener(DOMString type, EventListener? callback, optional (AddEventListenerOptions or boolean) options);
  void removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options);
  boolean dispatchEvent(Event event);
};

callback interface EventListener {
  void handleEvent(Event event);
};

dictionary EventListenerOptions {
  boolean capture = false;
};

dictionary AddEventListenerOptions : EventListenerOptions {
  boolean passive = false;
  boolean once = false;
};

The EventTarget object represents the target to which an event is dispatched when something has occurred.

Each EventTarget object has an associated list of event listeners.

An event listener can be used to observe a specific event.

An event listener consists of these fields:

Although callback is an EventListener, as can be seen from the fields above, an event listener is a broader concept.

Each EventTarget object also has an associated get the parent algorithm, which takes an event event, and returns an EventTarget object. Unless specified otherwise it returns null.

Nodes, shadow roots, and documents override the get the parent algorithm.

target . addEventListener(type, callback [, options])
Appends an event listener for events whose type attribute value is type. The callback argument sets the callback that will be invoked when the event is dispatched.

The options argument sets listener-specific options. For compatibility this can be just a boolean, in which case the method behaves exactly as if the value was specified as optionscapture member.

When set to true, optionscapture member prevents callback from being invoked when the event’s eventPhase attribute value is BUBBLING_PHASE. When false (or not present), callback will not be invoked when event’s eventPhase attribute value is CAPTURING_PHASE. Either way, callback will be invoked if event’s eventPhase attribute value is AT_TARGET.

When set to true, optionspassive member indicates that the callback will not cancel the event by invoking preventDefault(). This is used to enable performance optimizations described in §3.7 Observing event listeners.

When set to true, options’s once member indicates that the callback will only be invoked once after which the event listener will be removed.

The event listener is appended to target’s list of event listeners and is not appended if it is a duplicate, i.e., having the same type, callback, and capture values.

target . removeEventListener(type, callback [, options])
Remove the event listener in target’s list of event listeners with the same type, callback, and options.
target . dispatchEvent(event)
Dispatches a synthetic event event to target and returns true if either event’s cancelable attribute value is false or its preventDefault() method was not invoked, and false otherwise.

To flatten options, run these steps:

  1. Let capture be false.

  2. If options is a boolean, set capture to options.

  3. If options is a dictionary, then set capture to options’s capture.

  4. Return capture.

To flatten more options, run these steps:

  1. Let capture be the result of flattening options.

  2. Let once and passive be false.

  3. If options is a dictionary, then set passive to options’s passive and once to options’s once.

  4. Return capture, passive, and once.

The addEventListener(type, callback, options) method, when invoked, must run these steps:

  1. If the context object’s global object is a ServiceWorkerGlobalScope object and its associated service worker’s script resource’s has ever been evaluated flag is set, throw a TypeError. [SERVICE-WORKERS]

    To optimize storing the event types allowed for the service worker and to avoid non-deterministic changes to the event listeners, invocation of the method is allowed only during the very first evaluation of the service worker script.

  2. If callback is null, terminate these steps.

  3. Let capture, passive, and once be the result of flattening more options.

  4. If context object’s associated list of event listener does not contain an event listener whose type is type, callback is callback, and capture is capture, then append a new event listener to it, whose type is type, callback is callback, capture is capture, passive is passive, and once is once.

The removeEventListener(type, callback, options) method, when invoked, must, run these steps

  1. If the context object’s global object is a ServiceWorkerGlobalScope object and its associated service worker’s script resource’s has ever been evaluated flag is set, throw a TypeError. [SERVICE-WORKERS]

  2. Let capture be the result of flattening options.

  3. If there is an event listener in the associated list of event listeners whose type is type, callback is callback, and capture is capture, then set that event listener’s removed to true and remove it from the associated list of event listeners.

The dispatchEvent(event) method, when invoked, must run these steps:

  1. If event’s dispatch flag is set, or if its initialized flag is not set, then throw an InvalidStateError.

  2. Initialize event’s isTrusted attribute to false.

  3. Return the result of dispatching event to context object.

3.7. Observing event listeners

In general, developers do not expect the presence of an event listener to be observable. The impact of an event listener is determined by its callback. That is, a developer adding a no-op event listener would not expect it to have any side effects.

Unfortunately, some event APIs have been designed such that implementing them efficiently requires observing event listeners. This can make the presence of listeners observable in that even empty listeners can have a dramatic performance impact on the behavior of the application. For example, touch and wheel events which can be used to block asynchronous scrolling. In some cases this problem can be mitigated by specifying the event to be cancelable only when there is at least one non-passive listener. For example, non-passive TouchEvent listeners must block scrolling, but if all listeners are passive then scrolling can be allowed to start in parallel by making the TouchEvent uncancelable (so that calls to preventDefault() are ignored). So code dispatching an event is able to observe the absence of non-passive listeners, and use that to clear the cancelable property of the event being dispatched.

Ideally, any new event APIs are defined such that they do not need this property (use public-scrip-coord@w3.org for discussion).

3.8. Dispatching events

To dispatch an event to a target, with an optional targetOverride, run these steps:

  1. Set event’s dispatch flag.

  2. If targetOverride is not given, let targetOverride be target.

    The targetOverride argument is only used by HTML and only under very specific circumstances.

  3. Append (target, targetOverride) to event’s path.

  4. Let parent be the result of invoking target’s get the parent with event.

  5. While parent is non-null:

    1. If target’s root is a shadow-including inclusive ancestor of parent, then append (parent, null) to event’s path.

    2. Otherwise, set target to parent and append (parent, target) to event’s path.

    3. Set parent to the result of invoking parent’s get the parent with event.

  6. Set event’s eventPhase attribute to CAPTURING_PHASE.

  7. For each tuple in event’s path, in reverse order:

    1. Set event’s target attribute to the target of the last tuple in event’s path, that is either tuple or preceding tuple, whose target is non-null.

    2. If tuple’s target is null, then invoke tuple’s item with event.

  8. For each tuple in event’s path, in order:

    1. Set event’s target attribute to the target of the last tuple in event’s path, that is either tuple or preceding tuple, whose target is non-null.

    2. If tuple’s target is non-null, then set event’s eventPhase attribute to AT_TARGET.

    3. Otherwise, set event’s eventPhase attribute to BUBBLING_PHASE.

    4. If either event’s eventPhase attribute is BUBBLING_PHASE and event’s bubbles attribute is true or event’s eventPhase attribute is AT_TARGET, then invoke tuple’s item with event.

  9. Unset event’s dispatch flag.

  10. Set event’s eventPhase attribute to NONE.

  11. Set event’s currentTarget attribute to null.

  12. Set event’s path to the empty list.

  13. Return false if event’s canceled flag is set, and true otherwise.

To invoke an object with event, run these steps:

  1. If event’s stop propagation flag is set, then terminate these steps.

  2. Let listeners be the empty list.

  3. For each event listener associated with object, append a pointer to the event listener to listeners.

    This avoids event listeners added after this point from being run. Note that removal still has an effect due to the removed field.

  4. Initialize event’s currentTarget attribute to object.

  5. Let found be the result of running inner invoke object with event.

  6. If found is false, run these substeps:

    1. Let originalEventType be event’s type attribute value.

    2. If event’s type attribute value is a match for any of the strings in the first column in the following table, set event’s type attribute value to the string in the second column on the same row as the matching string, and terminate these substeps otherwise.

      Event type Legacy event type
      "animationend" "webkitAnimationEnd"
      "animationiteration" "webkitAnimationIteration"
      "animationstart" "webkitAnimationStart"
      "transitionend" "webkitTransitionEnd"
    3. Inner invoke object with event.

    4. Set event’s type attribute value to originalEventType.

To inner invoke an object with event, run these steps:

  1. Let found be false.

  2. For each listener in listeners, whose removed is false, run these substeps:

    1. If event’s type attribute value is not listener’s type, terminate these substeps (and run them for the next event listener).

    2. Set found to true.

    3. If event’s eventPhase attribute value is CAPTURING_PHASE and listener’s capture is false, terminate these substeps (and run them for the next event listener).

    4. If event’s eventPhase attribute value is BUBBLING_PHASE and listener’s capture is true, terminate these substeps (and run them for the next event listener).

    5. If listener’s passive is true, set event’s in passive listener flag.

    6. Call listener’s callback’s handleEvent(), with event as argument and event’s currentTarget attribute value as callback this value. If this throws an exception, report the exception.

    7. Unset event’s in passive listener flag.

    8. If listener’s once is true, then set listener’s removed to true and remove it from object’s associated list of event listeners.

    9. If event’s stop immediate propagation flag is set, return found.

  3. Return found.

3.9. Firing events

To fire an event named e means that a new event using the Event interface, with its type attribute initialized to e, and its isTrusted attribute initialized to true, is to be dispatched to the given object.

Fire in the context of DOM is short for creating, initializing, and dispatching an event. Fire an event makes that process easier to write down. If the event needs its bubbles or cancelable attribute initialized, one could write "fire an event named submit with its cancelable attribute initialized to true".

3.10. Action versus occurrence

An event signifies an occurrence, not an action. Phrased differently, it represents a notification from an algorithm and can be used to influence the future course of that algorithm (e.g., through invoking preventDefault()). Events must not be used as actions or initiators that cause some algorithm to start running. That is not what they are for.

This is called out here specifically because previous iterations of the DOM had a concept of "default actions" associated with events that gave folks all the wrong ideas. Events do not represent or cause actions, they can only be used to influence an ongoing one.

4. Nodes

4.1. Introduction to "The DOM"

In its original sense, "The DOM" is an API for accessing and manipulating documents (in particular, HTML and XML documents). In this specification, the term "document" is used for any markup-based resource, ranging from short static documents to long essays or reports with rich multimedia, as well as to fully-fledged interactive applications.

Each such document is represented as a node tree. Some of the nodes in a tree can have children, while others are always leaves.

To illustrate, consider this HTML document:

<!DOCTYPE html>
<html class=e>
 <head><title>Aliens?</title></head>
 <body>Why yes.</body>
</html>

It is represented as follows:

Note that, due to the magic that is HTML parsing, not all ASCII whitespace were turned into Text nodes, but the general concept is clear. Markup goes in, a tree of nodes comes out.

The most excellent Live DOM Viewer can be used to explore this matter in more detail.

4.2. Node tree

Document, DocumentType, DocumentFragment, ShadowRoot, Element, Text, ProcessingInstruction, and Comment objects (simply called nodes) participate in a tree, simply named the node tree.

A node tree is constrained as follows, expressed as a relationship between the type of node and its allowed children:

Document

In tree order:

  1. Zero or more nodes each of which is ProcessingInstruction or Comment.

  2. Optionally one DocumentType node.

  3. Zero or more nodes each of which is ProcessingInstruction or Comment.

  4. Optionally one Element node.

  5. Zero or more nodes each of which is ProcessingInstruction or Comment.

DocumentFragment
ShadowRoot
Element

Zero or more nodes each of which is Element, Text, ProcessingInstruction, or Comment.

DocumentType
Text
ProcessingInstruction
Comment

None.

The length of a node node depends on node:

DocumentType
Zero.
Text
ProcessingInstruction
Comment
Its length attribute value.
Any other node
Its number of children.

A node is considered empty if its length is zero.

4.2.1. Document tree

A document tree is a node tree whose root is a document.

The document element of a document is the element whose parent is that document, if it exists, and null otherwise.

Per the node tree constraints, there can be only one such element.

An element is in a document if its root is a document.

4.2.2. Shadow tree

A shadow tree is a node tree whose root is a shadow root.

A shadow root is always connected to another node tree through its host. A shadow tree is therefore never alone. The node tree of a shadow root’s host is sometimes referred to as the light tree.

A shadow tree’s corresponding light tree can be a shadow tree itself.

An element is in a shadow-including document if its shadow-including root is a document.

4.2.2.1. Slots

A shadow tree contains zero or more elements that are slots.

A slot can only be created through HTML’s slot element.

A slot has an associated name (a string). Unless stated otherwise it is the empty string.

Use these attribute change steps to update a slot’s name:

  1. If element is a slot, localName is name, and namespace is null, then:

    1. If value is oldValue, then return.

    2. If value is null and oldValue is the empty string, then return.

    3. If value is the empty string and oldValue is null, then return.

    4. If value is null or the empty string, then set element’s name to the empty string.

    5. Otherwise, set element’s name to value.

    6. Run assign slotables for a tree with element’s tree.

The first slot in a shadow tree, in tree order, whose name is the empty string, is sometimes known as the "default slot".

A slot has an associated assigned nodes (a list of slotables). Unless stated otherwise it is empty.

4.2.2.2. Slotables

Element and Text nodes are slotables.

A slot can be a slotable.

A slotable has an associated name (a string). Unless stated otherwise it is the empty string.

Use these attribute change steps to update a slotable’s name:

  1. If localName is slot and namespace is null, then:

    1. If value is oldValue, then return.

    2. If value is null and oldValue is the empty string, then return.

    3. If value is the empty string and oldValue is null, then return.

    4. If value is null or the empty string, then set element’s name to the empty string.

    5. Otherwise, set element’s name to value.

    6. If element is assigned, then run assign slotables for element’s assigned slot.

    7. Run assign a slot for element.

A slotable has an associated assigned slot (null or a slot). Unless stated otherwise it is null. A slotable is assigned if its assigned slot is non-null.

4.2.2.3. Finding slots and slotables

To find a slot for a given slotable slotable and an optional open flag (unset unless stated otherwise), run these steps:

  1. If slotable’s parent is null, then return null.

  2. Let shadow be slotable’s parent’s shadow root.

  3. If shadow is null, then return null.

  4. If the open flag is set and shadow’s mode is not "open", then return null.

  5. Return the first slot in shadow’s tree whose name is slotable’s name, if any, and null otherwise.

To find slotables for a given slot slot, run these steps:

  1. Let result be an empty list.

  2. If slot’s root is not a shadow root, then return result.

  3. Let host be slot’s root’s host.

  4. For each slotable child of host, slotable, in tree order, run these substeps:

    1. Let foundSlot be the result of finding a slot given slotable.

    2. If foundSlot is slot, then append slotable to result.

  5. Return result.

To find flattened slotables for a given slot slot, run these steps:

  1. Let result be an empty list.

  2. Let slotables be the result of finding slotables given slot.

  3. If slotables is the empty list, then append each slotable child of slot, in tree order, to slotables.

  4. For each node in slotables, run these substeps:

    1. If node is a slot, run these subsubsteps:

      1. Let temporaryResult be the result of finding flattened slotables given node.

      2. Append each slotable in temporaryResult, in order, to result.

    2. Otherwise, append node to result.

  5. Return result.

4.2.2.4. Assigning slotables and slots

To assign slotables, for a slot slot with an optional suppress signaling flag (unset unless stated otherwise), run these steps:

  1. Let slotables be the result of finding slotables for slot.

  2. If suppress signaling flag is unset, and slotables and slot’s assigned nodes are not identical, then run signal a slot change for slot.

  3. Set slot’s assigned nodes to slotables.

  4. For each slotable in slotables, set slotable’s assigned slot to slot.

To assign slotables for a tree, given a tree tree and an optional set of slots noSignalSlots (empty unless stated otherwise), run these steps for each slot slot in tree, in tree order:

  1. Let suppress signaling flag be set, if slot is in noSignalSlots, and unset otherwise.

  2. Run assign slotables for slot with suppress signaling flag.

To assign a slot, given a slotable slotable, run these steps:

  1. Let slot be the result of finding a slot with slotable.

  2. If slot is non-null, then run assign slotables for slot.

4.2.2.5. Signaling slot change

Each unit of related similar-origin browsing contexts has a signal slot list (a list of slots). Unless stated otherwise it is empty. [HTML]

To signal a slot change, for a slot slot, run these steps:

  1. If slot is not in unit of related similar-origin browsing contexts' signal slot list, append slot to unit of related similar-origin browsing contexts' signal slot list.

  2. If slot is assigned, then run signal a slot change for slot’s assigned slot.

  3. Otherwise, if slot’s parent is a slot and slot’s parent’s assigned nodes is the empty list, then run signal a slot change for slot’s parent.

  4. Queue a mutation observer compound microtask.

4.2.3. Mutation algorithms

To ensure pre-insertion validity of a node into a parent before a child, run these steps:

  1. If parent is not a Document, DocumentFragment, or Element node, throw a HierarchyRequestError.
  2. If node is a host-including inclusive ancestor of parent, throw a HierarchyRequestError.
  3. If child is not null and its parent is not parent, then throw a NotFoundError.
  4. If node is not a DocumentFragment, DocumentType, Element, Text, ProcessingInstruction, or Comment node, throw a HierarchyRequestError.
  5. If either node is a Text node and parent is a document, or node is a doctype and parent is not a document, throw a HierarchyRequestError.
  6. If parent is a document, and any of the statements below, switched on node, are true, throw a HierarchyRequestError.
    DocumentFragment node
    If node has more than one element child or has a Text node child.

    Otherwise, if node has one element child and either parent has an element child, child is a doctype, or child is not null and a doctype is following child.

    element
    parent has an element child, child is a doctype, or child is not null and a doctype is following child.
    doctype
    parent has a doctype child, child is non-null and an element is preceding child, or child is null and parent has an element child.

To pre-insert a node into a parent before a child, run these steps:

  1. Ensure pre-insertion validity of node into parent before child.
  2. Let reference child be child.
  3. If reference child is node, set it to node’s next sibling.
  4. Adopt node into parent’s node document.
  5. Insert node into parent before reference child.
  6. Return node.

Specifications may define insertion steps for all or some nodes. The algorithm is passed insertedNode, as indicated in the insert algorithm below.

To insert a node into a parent before a child, with an optional suppress observers flag, run these steps:

  1. Let count be the number of children of node if it is a DocumentFragment node, and one otherwise.
  2. If child is non-null, run these substeps:
    1. For each range whose start node is parent and start offset is greater than child’s index, increase its start offset by count.
    2. For each range whose end node is parent and end offset is greater than child’s index, increase its end offset by count.
  3. Let nodes be node’s children if node is a DocumentFragment node, and a list containing solely node otherwise.
  4. If node is a DocumentFragment node, remove its children with the suppress observers flag set.
  5. If node is a DocumentFragment node, queue a mutation record of "childList" for node with removedNodes nodes.

    This step intentionally does not pay attention to the suppress observers flag.

  6. For each node in nodes, in tree order, run these substeps:

    1. Insert node into parent before child or at the end of parent if child is null.

    2. If parent is a shadow host and node is a slotable, then assign a slot for node.

    3. If parent is a slot whose assigned nodes is the empty list, then run signal a slot change for parent.

    4. Run assign slotables for a tree with node’s tree and a set containing each inclusive descendant of node that is a slot.

    5. For each shadow-including inclusive descendant inclusiveDescendant of node, in shadow-including tree order, run these subsubsteps:

      1. Run the insertion steps with inclusiveDescendant.

      2. If inclusiveDescendant is in a shadow-including document, then:

        1. If inclusiveDescendant is custom, then enqueue a custom element callback reaction with inclusiveDescendant, callback name "connectedCallback", and an empty argument list.

        2. Otherwise, try to upgrade inclusiveDescendant.

          If this successfully upgrades inclusiveDescendant, its connectedCallback will be enqueued automatically during the upgrade an element algorithm.

  7. If suppress observers flag is unset, queue a mutation record of "childList" for parent with addedNodes nodes, nextSibling child, and previousSibling child’s previous sibling or parent’s last child if child is null.

To append a node to a parent, pre-insert node into parent before null.

To replace a child with node within a parent, run these steps:

  1. If parent is not a Document, DocumentFragment, or Element node, throw a HierarchyRequestError.
  2. If node is a host-including inclusive ancestor of parent, throw a HierarchyRequestError.
  3. If child’s parent is not parent, then throw a NotFoundError.
  4. If node is not a DocumentFragment, DocumentType, Element, Text, ProcessingInstruction, or Comment node, throw a HierarchyRequestError.
  5. If either node is a Text node and parent is a document, or node is a doctype and parent is not a document, throw a HierarchyRequestError.
  6. If parent is a document, and any of the statements below, switched on node, are true, throw a HierarchyRequestError.
    DocumentFragment node
    If node has more than one element child or has a Text node child.

    Otherwise, if node has one element child and either parent has an element child that is not child or a doctype is following child.

    element
    parent has an element child that is not child or a doctype is following child.
    doctype
    parent has a doctype child that is not child, or an element is preceding child.

    The above statements differ from the pre-insert algorithm.

  7. Let reference child be child’s next sibling.
  8. If reference child is node, set it to node’s next sibling.
  9. Let previousSibling be child’s previous sibling.

  10. Adopt node into parent’s node document.
  11. Let removedNodes be the empty list.
  12. If child’s parent is not null, run these substeps:

    1. Set removedNodes to a list solely containing child.

    2. Remove child from its parent with the suppress observers flag set.

    The above can only be false if child is node.

  13. Let nodes be node’s children if node is a DocumentFragment node, and a list containing solely node otherwise.
  14. Insert node into parent before reference child with the suppress observers flag set.
  15. Queue a mutation record of "childList" for target parent with addedNodes nodes, removedNodes removedNodes, nextSibling reference child, and previousSibling previousSibling.
  16. Return child.

To replace all with a node within a parent, run these steps:

  1. If node is not null, adopt node into parent’s node document.
  2. Let removedNodes be parent’s children.
  3. Let addedNodes be the empty list if node is null, node’s children if node is a DocumentFragment node, and a list containing node otherwise.
  4. Remove all parent’s children, in tree order, with the suppress observers flag set.
  5. If node is not null, insert node into parent before null with the suppress observers flag set.
  6. Queue a mutation record of "childList" for parent with addedNodes addedNodes and removedNodes removedNodes.

This algorithm does not make any checks with regards to the node tree constraints. Specification authors need to use it wisely.

To pre-remove a child from a parent, run these steps:

  1. If child’s parent is not parent, then throw a NotFoundError.
  2. Remove child from parent.
  3. Return child.

Specifications may define removing steps for all or some nodes. The algorithm is passed removedNode, and optionally oldParent, as indicated in the remove algorithm below.

To remove a node from a parent, with an optional suppress observers flag, run these steps:

  1. Let index be node’s index.
  2. For each range whose start node is an inclusive descendant of node, set its start to (parent, index).
  3. For each range whose end node is an inclusive descendant of node, set its end to (parent, index).
  4. For each range whose start node is parent and start offset is greater than index, decrease its start offset by one.
  5. For each range whose end node is parent and end offset is greater than index, decrease its end offset by one.
  6. For each NodeIterator object iterator whose root’s node document is node’s node document, run the NodeIterator pre-removing steps given node and iterator.

  7. Let oldPreviousSibling be node’s previous sibling.
  8. Let oldNextSibling be node’s next sibling.
  9. Remove node from its parent.
  10. If node is assigned, then run assign slotables for node’s assigned slot.

  11. If parent is a slot whose assigned nodes is the empty list, then run signal a slot change for parent.

  12. If node has an inclusive descendant that is a slot, then:

    1. Run assign slotables for a tree with parent’s tree.

    2. Run assign slotables for a tree with node’s tree and a set containing each inclusive descendant of node that is a slot.

  13. Run the removing steps with node and parent.

  14. If node is custom, then enqueue a custom element callback reaction with node, callback name "disconnectedCallback", and an empty argument list.

    It is intentional for now that custom elements do not get parent passed. This might change in the future if there is a need.

  15. For each shadow-including descendant descendant of node, in shadow-including tree order, run these substeps:

    1. Run the removing steps with descendant.

    2. If descendant is custom, then enqueue a custom element callback reaction with descendant, callback name "disconnectedCallback", and an empty argument list.

  16. For each inclusive ancestor inclusiveAncestor of parent, if inclusiveAncestor has any registered observers whose options' subtree is true, then for each such registered observer registered, append a transient registered observer whose observer and options are identical to those of registered and source which is registered to node’s list of registered observers.
  17. If suppress observers flag is unset, queue a mutation record of "childList" for parent with removedNodes a list solely containing node, nextSibling oldNextSibling, and previousSibling oldPreviousSibling.

4.2.4. Mixin NonElementParentNode

Web compatibility prevents the getElementById() method from being exposed on elements (and therefore on ParentNode).

[NoInterfaceObject,
 Exposed=Window]
interface NonElementParentNode {
  Element? getElementById(DOMString elementId);
};
Document implements NonElementParentNode;
DocumentFragment implements NonElementParentNode;
node . getElementById(elementId)

Returns the first element within node’s descendants whose ID is elementId.

The getElementById(elementId) method, when invoked, must return the first element, in tree order, within context object’s descendants, whose ID is elementId, and null if there is no such element otherwise.

4.2.5. Mixin DocumentOrShadowRoot

[NoInterfaceObject,
 Exposed=Window]
interface DocumentOrShadowRoot {
};
Document implements DocumentOrShadowRoot;
ShadowRoot implements DocumentOrShadowRoot;

The DocumentOrShadowRoot mixin is expected to be used by other standards that want to define APIs shared between documents and shadow roots.

4.2.6. Mixin ParentNode

To convert nodes into a node, given nodes and document, run these steps:

  1. Let node be null.

  2. Replace each string in nodes with a new Text node whose data is the string and node document is document.

  3. If nodes contains one node, set node to that node.

  4. Otherwise, set node to a new DocumentFragment whose node document is document, and then append each node in nodes, if any, to it. Rethrow any exceptions.

  5. Return node.

[NoInterfaceObject,
 Exposed=Window]
interface ParentNode {
  [SameObject] readonly attribute HTMLCollection children;
  readonly attribute Element? firstElementChild;
  readonly attribute Element? lastElementChild;
  readonly attribute unsigned long childElementCount;

  [CEReactions, Unscopable] void prepend((Node or DOMString)... nodes);
  [CEReactions, Unscopable] void append((Node or DOMString)... nodes);

  Element? querySelector(DOMString selectors);
  [NewObject] NodeList querySelectorAll(DOMString selectors);
};
Document implements ParentNode;
DocumentFragment implements ParentNode;
Element implements ParentNode;
collection = node . children
Returns the child elements.
element = node . firstElementChild
Returns the first child that is an element, and null otherwise.
element = node . lastElementChild
Returns the last child that is an element, and null otherwise.
node . prepend(nodes)
Inserts nodes before the first child of node, while replacing strings in nodes with equivalent Text nodes.

Throws a HierarchyRequestError if the constraints of the node tree are violated.

node . append(nodes)
Inserts nodes after the last child of node, while replacing strings in nodes with equivalent Text nodes.

Throws a HierarchyRequestError if the constraints of the node tree are violated.

node . querySelector(selectors)
Returns the first element that is a descendant of node that matches selectors.
node . querySelectorAll(selectors)
Returns all element descendants of node that match selectors.

The children attribute must return an HTMLCollection collection rooted at the context object matching only element children.

The firstElementChild attribute must return the first child that is an element, and null otherwise.

The lastElementChild attribute must return the last child that is an element, and null otherwise.

The childElementCount attribute must return the number of children of the context object that are elements.

The prepend(nodes) method must run these steps:

  1. Let node be the result of converting nodes into a node given nodes and context object’s node document. Rethrow any exceptions.

  2. Pre-insert node into context object before the context object’s first child. Rethrow any exceptions.

The append(nodes) method must run these steps:

  1. Let node be the result of converting nodes into a node given nodes and context object’s node document. Rethrow any exceptions.

  2. Append node to context object. Rethrow any exceptions.

The querySelector(selectors) method, when invoked, must return the first result of running scope-match a selectors string selectors against the context object, and null if the result is an empty list otherwise.

The querySelectorAll(selectors) method, when invoked, must return the static result of running scope-match a selectors string selectors against the context object.

4.2.7. Mixin NonDocumentTypeChildNode

Web compatibility prevents the previousElementSibling and nextElementSibling attributes from being exposed on doctypes (and therefore on ChildNode).

[NoInterfaceObject,
 Exposed=Window]
interface NonDocumentTypeChildNode {
  readonly attribute Element? previousElementSibling;
  readonly attribute Element? nextElementSibling;
};
Element implements NonDocumentTypeChildNode;
CharacterData implements NonDocumentTypeChildNode;
element = node . previousElementSibling
Returns the first preceding sibling that is an element, and null otherwise.
element = node . nextElementSibling
Returns the first following sibling that is an element, and null otherwise.

The previousElementSibling attribute must return the first preceding sibling that is an element, and null otherwise.

The nextElementSibling attribute must return the first following sibling that is an element, and null otherwise.

4.2.8. Mixin ChildNode

[NoInterfaceObject,
 Exposed=Window]
interface ChildNode {
  [CEReactions, Unscopable] void before((Node or DOMString)... nodes);
  [CEReactions, Unscopable] void after((Node or DOMString)... nodes);
  [CEReactions, Unscopable] void replaceWith((Node or DOMString)... nodes);
  [CEReactions, Unscopable] void remove();
};
DocumentType implements ChildNode;
Element implements ChildNode;
CharacterData implements ChildNode;
node . before(nodes)
Inserts nodes just before node, while replacing strings in nodes with equivalent Text nodes.

Throws a HierarchyRequestError if the constraints of the node tree are violated.

node . after(nodes)
Inserts nodes just after node, while replacing strings in nodes with equivalent Text nodes.

Throws a HierarchyRequestError if the constraints of the node tree are violated.

node . replaceWith(nodes)
Replaces node with nodes, while replacing strings in nodes with equivalent Text nodes.

Throws a HierarchyRequestError if the constraints of the node tree are violated.

node . remove()
Removes node.

The before(nodes) method, when invoked, must run these steps:

  1. Let parent be context object’s parent.

  2. If parent is null, terminate these steps.

  3. Let viablePreviousSibling be context object’s first preceding sibling not in nodes, and null otherwise.

  4. Let node be the result of converting nodes into a node, given nodes and context object’s node document. Rethrow any exceptions.

  5. If viablePreviousSibling is null, set it to parent’s first child, and to viablePreviousSibling’s next sibling otherwise.

  6. Pre-insert node into parent before viablePreviousSibling. Rethrow any exceptions.

The after(nodes) method, when invoked, must run these steps:

  1. Let parent be context object’s parent.

  2. If parent is null, terminate these steps.

  3. Let viableNextSibling be context object’s first following sibling not in nodes, and null otherwise.

  4. Let node be the result of converting nodes into a node, given nodes and context object’s node document. Rethrow any exceptions.

  5. Pre-insert node into parent before viableNextSibling. Rethrow any exceptions.

The replaceWith(nodes) method, when invoked, must run these steps:

  1. Let parent be context object’s parent.

  2. If parent is null, terminate these steps.

  3. Let viableNextSibling be context object’s first following sibling not in nodes, and null otherwise.

  4. Let node be the result of converting nodes into a node, given nodes and context object’s node document. Rethrow any exceptions.

  5. If context object’s parent is parent, replace the context object with node within parent. Rethrow any exceptions.

    Context object could have been inserted into node.

  6. Otherwise, pre-insert node into parent before viableNextSibling. Rethrow any exceptions.

The remove() method, when invoked, must run these steps:

  1. If context object’s parent is null, terminate these steps.

  2. Remove the context object from context object’s parent.

4.2.9. Mixin: Slotable

[NoInterfaceObject,
 Exposed=Window]
interface Slotable {
  readonly attribute HTMLSlotElement? assignedSlot;
};
Element implements Slotable;
Text implements Slotable;

The assignedSlot attribute’s getter must return the result of find a slot given context object and with the open flag set.

4.2.10. Old-style collections: NodeList and HTMLCollection

A collection is an object that represents a lists of DOM nodes. A collection can be either live or static. Unless otherwise stated, a collection must be live.

If a collection is live, then the attributes and methods on that object must operate on the actual underlying data, not a snapshot of the data.

When a collection is created, a filter and a root are associated with it.

The collection then represents a view of the subtree rooted at the collection’s root, containing only nodes that match the given filter. The view is linear. In the absence of specific requirements to the contrary, the nodes within the collection must be sorted in tree order.

4.2.10.1. Interface NodeList

A NodeList object is a collection of nodes.

[Exposed=Window]
interface NodeList {
  getter Node? item(unsigned long index);
  readonly attribute unsigned long length;
  iterable<Node>;
};
collection . length
Returns the number of nodes in the collection.
element = collection . item(index)
element = collection[index]
Returns the node with index index from the collection. The nodes are sorted in tree order.

The object’s supported property indices are the numbers in the range zero to one less than the number of nodes represented by the collection. If there are no such elements, then there are no supported property indices.

The length attribute must return the number of nodes represented by the collection.

The item(index) method must return the indexth node in the collection. If there is no indexth node in the collection, then the method must return null.

4.2.10.2. Interface HTMLCollection
[Exposed=Window, LegacyUnenumerableNamedProperties]
interface HTMLCollection {
  readonly attribute unsigned long length;
  getter Element? item(unsigned long index);
  getter Element? namedItem(DOMString name);
};

An HTMLCollection object is a collection of elements.

HTMLCollection is an historical artifact we cannot rid the web of. While developers are of course welcome to keep using it, new API standard designers ought not to use it (use sequence<T> in IDL instead).

collection . length
Returns the number of elements in the collection.
element = collection . item(index)
element = collection[index]
Returns the element with index index from the collection. The elements are sorted in tree order.
element = collection . namedItem(name)
element = collection[name]
Returns the first element with ID or name name from the collection.

The object’s supported property indices are the numbers in the range zero to one less than the number of elements represented by the collection. If there are no such elements, then there are no supported property indices.

The length attribute’s getter must return the number of nodes represented by the collection.

The item(index) method, when invoked, must return the indexth element in the collection. If there is no indexth element in the collection, then the method must return null.

The supported property names are the values from the list returned by these steps:

  1. Let result be an empty list.

  2. For each element represented by the collection, in tree order, run these substeps:

    1. If element has an ID which is not in result, append element’s ID to result.

    2. If element is in the HTML namespace and has a name attribute whose value is neither the empty string nor is in result, append element’s name attribute value to result.

  3. Return result.

The namedItem(key) method, when invoked, must run these steps:

  1. If key is the empty string, return null.

  2. Return the first element in the collection for which at least one of the following is true:

    or null if there is no such element.

4.3. Mutation observers

Each unit of related similar-origin browsing contexts has a mutation observer compound microtask queued flag, which is initially unset, and an associated list of MutationObserver objects, which is initially empty. [HTML]

To queue a mutation observer compound microtask, run these steps:

  1. If mutation observer compound microtask queued flag is set, terminate these steps.
  2. Set mutation observer compound microtask queued flag.
  3. Queue a compound microtask to notify mutation observers.

To notify mutation observers, run these steps:

  1. Unset mutation observer compound microtask queued flag.
  2. Let notify list be a copy of unit of related similar-origin browsing contexts' list of MutationObserver objects.
  3. For each MutationObserver object mo in notify list, execute a compound microtask subtask to run these steps: [HTML]
    1. Let queue be a copy of mo’s record queue.
    2. Empty mo’s record queue.
    3. Remove all transient registered observers whose observer is mo.
    4. If queue is non-empty, call mo’s callback with queue as first argument, and mo (itself) as second argument and callback this value. If this throws an exception, report the exception.
  4. Let signalList be a copy of unit of related similar-origin browsing contexts' signal slot list.

  5. Empty unit of related similar-origin browsing contexts' signal slot list.

  6. For each slot slot in signalList, in order, fire an event named slotchange, with its bubbles attribute set to true, at slot.


Each node has an associated list of registered observers.

A registered observer consists of an observer (a MutationObserver object) and options (a MutationObserverInit dictionary). A transient registered observer is a specific type of registered observer that has a source which is a registered observer.

Transient registered observers are used to track mutations within a given node’s descendants after node has been removed so they do not get lost when subtree is set to true on node’s parent.

4.3.1. Interface MutationObserver

[Constructor(MutationCallback callback)]
interface MutationObserver {
  void observe(Node target, MutationObserverInit options);
  void disconnect();
  sequence<MutationRecord> takeRecords();
};

callback MutationCallback = void (sequence<MutationRecord> mutations, MutationObserver observer);

dictionary MutationObserverInit {
  boolean childList = false;
  boolean attributes;
  boolean characterData;
  boolean subtree = false;
  boolean attributeOldValue;
  boolean characterDataOldValue;
  sequence<DOMString> attributeFilter;
};

A MutationObserver object can be used to observe mutations to the tree of nodes.

Each MutationObserver object has these associated concepts:

observer = new MutationObserver(callback)
Constructs a MutationObserver object and sets its callback to callback. The callback is invoked with a list of MutationRecord objects as first argument and the constructed MutationObserver object as second argument. It is invoked after nodes registered with the observe() method, are mutated.
observer . observe(target, options)
Instructs the user agent to observe a given target (a node) and report any mutations based on the criteria given by options (an object).

The options argument allows for setting mutation observation options via object members. These are the object members that can be used:

childList
Set to true if mutations to target’s children are to be observed.
attributes
Set to true if mutations to target’s attributes are to be observed. Can be omitted if attributeOldValue and/or attributeFilter is specified.
characterData
Set to true if mutations to target’s data are to be observed. Can be omitted if characterDataOldValue is specified.
subtree
Set to true if mutations to not just target, but also target’s descendants are to be observed.
attributeOldValue
Set to true if attributes is true or omitted and target’s attribute value before the mutation needs to be recorded.
characterDataOldValue
Set to true if characterData is set to true or omitted and target’s data before the mutation needs to be recorded.
attributeFilter
Set to a list of attribute local names (without namespace) if not all attribute mutations need to be observed and attributes is true or omitted.
observer . disconnect()
Stops observer from observing any mutations. Until the observe() method is used again, observer’s callback will not be invoked.
observer . takeRecords()
Empties the record queue and returns what was in there.

The MutationObserver(callback) constructor must create a new MutationObserver object with callback set to callback, append it to the unit of related similar-origin browsing contexts' list of MutationObserver objects, and then return it.

The observe(target, options) method, when invoked, must run these steps:

  1. If either optionsattributeOldValue or attributeFilter is present and optionsattributes is omitted, set optionsattributes to true.
  2. If optionscharacterDataOldValue is present and optionscharacterData is omitted, set optionscharacterData to true.
  3. If none of optionschildList attributes, and characterData is true, throw a TypeError.
  4. If optionsattributeOldValue is true and optionsattributes is false, throw a TypeError.
  5. If optionsattributeFilter is present and optionsattributes is false, throw a TypeError.
  6. If optionscharacterDataOldValue is true and optionscharacterData is false, throw a TypeError.
  7. For each registered observer registered in target’s list of registered observers whose observer is the context object:
    1. Remove all transient registered observers whose source is registered.
    2. Replace registered’s options with options.
  8. Otherwise, add a new registered observer to target’s list of registered observers with the context object as the observer and options as the options, and add target to context object’s list of nodes on which it is registered.

The disconnect() method must, for each node node in the context object’s list of nodes, remove any registered observer on node for which the context object is the observer, and also empty context object’s record queue.

The takeRecords() method must return a copy of the record queue and then empty the record queue.

4.3.2. Queuing a mutation record

To queue a mutation record of type for target with one or more of (depends on type) name name, namespace namespace, oldValue oldValue, addedNodes addedNodes, removedNodes removedNodes, previousSibling previousSibling, and nextSibling nextSibling, run these steps:

  1. Let interested observers be an initially empty set of MutationObserver objects optionally paired with a string.
  2. Let nodes be the inclusive ancestors of target.
  3. Then, for each node in nodes, and then for each registered observer (with registered observer’s options as options) in node’s list of registered observers, run these substeps:

    1. If none of the following are true

      • node is not target and optionssubtree is false
      • type is "attributes" and optionsattributes is not true
      • type is "attributes", optionsattributeFilter is present, and optionsattributeFilter does not contain name or namespace is non-null
      • type is "characterData" and optionscharacterData is not true
      • type is "childList" and optionschildList is false

      then run these subsubsteps:

      1. If registered observer’s observer is not in interested observers, append registered observer’s observer to interested observers.

      2. If either type is "attributes" and optionsattributeOldValue is true, or type is "characterData" and optionscharacterDataOldValue is true, set the paired string of registered observer’s observer in interested observers to oldValue.

  4. Then, for each observer in interested observers, run these substeps:

    1. Let record be a new MutationRecord object with its type set to type and target set to target.
    2. If name and namespace are given, set record’s attributeName to name, and record’s attributeNamespace to namespace.
    3. If addedNodes is given, set record’s addedNodes to addedNodes.
    4. If removedNodes is given, set record’s removedNodes to removedNodes,
    5. If previousSibling is given, set record’s previousSibling to previousSibling.
    6. If nextSibling is given, set record’s nextSibling to nextSibling.
    7. If observer has a paired string, set record’s oldValue to observer’s paired string.
    8. Append record to observer’s record queue.
  5. Queue a mutation observer compound microtask.

4.3.3. Interface MutationRecord

[Exposed=Window]
interface MutationRecord {
  readonly attribute DOMString type;
  [SameObject] readonly attribute Node target;
  [SameObject] readonly attribute NodeList addedNodes;
  [SameObject] readonly attribute NodeList removedNodes;
  readonly attribute Node? previousSibling;
  readonly attribute Node? nextSibling;
  readonly attribute DOMString? attributeName;
  readonly attribute DOMString? attributeNamespace;
  readonly attribute DOMString? oldValue;
};
record . type
Returns "attributes" if it was an attribute mutation. "characterData" if it was a mutation to a CharacterData node. And "childList" if it was a mutation to the tree of nodes.
record . target
Returns the node the mutation affected, depending on the type. For "attributes", it is the element whose attribute changed. For "characterData", it is the CharacterData node. For "childList", it is the node whose children changed.
record . addedNodes
record . removedNodes
Return the nodes added and removed respectively.
record . previousSibling
record . nextSibling
Return the previous and next sibling respectively of the added or removed nodes, and null otherwise.
record . attributeName
Returns the local name of the changed attribute, and null otherwise.
record . attributeNamespace
Returns the namespace of the changed attribute, and null otherwise.
record . oldValue
The return value depends on type. For "attributes", it is the value of the changed attribute before the change. For "characterData", it is the data of the changed node before the change. For "childList", it is null.

The type and target attributes must return the values they were initialized to.

The addedNodes and removedNodes attributes must return the values they were initialized to. Unless stated otherwise, when a MutationRecord object is created, they must both be initialized to an empty NodeList.

The previousSibling, nextSibling, attributeName, attributeNamespace, and oldValue attributes must return the values they were initialized to. Unless stated otherwise, when a MutationRecord object is created, they must be initialized to null.

4.3.4. Garbage collection

Nodes have a strong reference to registered observers in their list of registered observers.

Registered observers in a node’s list of registered observers have a weak reference to the node.

4.4. Interface Node

[Exposed=Window]
interface Node : EventTarget {
  const unsigned short ELEMENT_NODE = 1;
  const unsigned short ATTRIBUTE_NODE = 2; // historical
  const unsigned short TEXT_NODE = 3;
  const unsigned short CDATA_SECTION_NODE = 4; // historical
  const unsigned short ENTITY_REFERENCE_NODE = 5; // historical
  const unsigned short ENTITY_NODE = 6; // historical
  const unsigned short PROCESSING_INSTRUCTION_NODE = 7;
  const unsigned short COMMENT_NODE = 8;
  const unsigned short DOCUMENT_NODE = 9;
  const unsigned short DOCUMENT_TYPE_NODE = 10;
  const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
  const unsigned short NOTATION_NODE = 12; // historical
  readonly attribute unsigned short nodeType;
  readonly attribute DOMString nodeName;

  readonly attribute USVString baseURI;

  readonly attribute boolean isConnected;
  readonly attribute Document? ownerDocument;
  readonly attribute Node rootNode;
  readonly attribute Node? parentNode;
  readonly attribute Element? parentElement;
  boolean hasChildNodes();
  [SameObject] readonly attribute NodeList childNodes;
  readonly attribute Node? firstChild;
  readonly attribute Node? lastChild;
  readonly attribute Node? previousSibling;
  readonly attribute Node? nextSibling;

  [CEReactions] attribute DOMString? nodeValue;
  [CEReactions] attribute DOMString? textContent;
  [CEReactions] void normalize();

  [CEReactions, NewObject] Node cloneNode(optional boolean deep = false);
  boolean isEqualNode(Node? otherNode);
  boolean isSameNode(Node? otherNode); // historical alias of ===

  const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01;
  const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02;
  const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x04;
  const unsigned short DOCUMENT_POSITION_CONTAINS = 0x08;
  const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10;
  const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
  unsigned short compareDocumentPosition(Node other);
  boolean contains(Node? other);

  DOMString? lookupPrefix(DOMString? namespace);
  DOMString? lookupNamespaceURI(DOMString? prefix);
  boolean isDefaultNamespace(DOMString? namespace);

  [CEReactions] Node insertBefore(Node node, Node? child);
  [CEReactions] Node appendChild(Node node);
  [CEReactions] Node replaceChild(Node node, Node child);
  [CEReactions] Node removeChild(Node child);
};

Node is an abstract interface and does not exist as node. It is used by all nodes (Document, DocumentType, DocumentFragment, ShadowRoot, Element, Text, ProcessingInstruction, and Comment).

Each node has an associated node document, set upon creation, that is a document.

A node’s node document can be changed by the adopt algorithm.

A node’s get the parent algorithm, given an event, returns the node’s assigned slot, if node is assigned, and node’s parent otherwise.


node . nodeType
Returns the type of node, represented by a number from the following list:
Node . ELEMENT_NODE (1)
node is an element.
Node . TEXT_NODE (3)
node is a Text node.
Node . PROCESSING_INSTRUCTION_NODE (7)
node is a ProcessingInstruction node.
Node . COMMENT_NODE (8)
node is a Comment node.
Node . DOCUMENT_NODE (9)
node is a document.
Node . DOCUMENT_TYPE_NODE (10)
node is a doctype.
Node . DOCUMENT_FRAGMENT_NODE (11)
node is a DocumentFragment or ShadowRoot node.
node . nodeName
Returns a string appropriate for the type of node, as follows:
Element
Its tagName attribute value.
Text
"#text".
ProcessingInstruction
Its target.
Comment
"#comment".
Document
"#document".
DocumentType
Its name.
DocumentFragment
ShadowRoot
"#document-fragment".

The nodeType attribute’s getter, when invoked, must return the first matching statement, switching on the context object:

Element
ELEMENT_NODE (1)
Text
TEXT_NODE (3);
ProcessingInstruction
PROCESSING_INSTRUCTION_NODE (7);
Comment
COMMENT_NODE (8);
Document
DOCUMENT_NODE (9);
DocumentType
DOCUMENT_TYPE_NODE (10);
DocumentFragment
ShadowRoot
DOCUMENT_FRAGMENT_NODE (11).

The nodeName attribute’s getter, when invoked, must return the first matching statement, switching on the context object:

Element
Its tagName attribute value.
Text
"#text".
ProcessingInstruction
Its target.
Comment
"#comment".
Document
"#document".
DocumentType
Its name.
DocumentFragment
ShadowRoot
"#document-fragment".

node . baseURI
Returns node’s node document’s base URL.

The baseURI attribute’s getter must return node document’s base URL, serialized.


node . isConnected

Returns true if node is in a shadow-including document and false otherwise.

node . ownerDocument
Returns the node document. Returns null for documents.
node . rootNode
Returns the root.
node . parentNode
Returns the parent.
node . parentElement
Returns the parent element.
node . hasChildNodes()
Returns whether node has children.
node . childNodes
Returns the children.
node . firstChild
Returns the first child.
node . lastChild
Returns the last child.
node . previousSibling
Returns the previous sibling.
node . nextSibling
Returns the next sibling.

The isConnected attribute’s getter must return true, if context object is in a shadow-including document, and false otherwise.

The ownerDocument attribute’s getter must return null, if the context object is a document, and the context object’s node document otherwise.

The node document of a document is that document itself. All nodes have a node document at all times.

The rootNode attribute’s getter must return context object’s root.

The parentNode attribute’s getter must return the context object’s parent.

The parentElement attribute’s getter must return the context object’s parent element.

The hasChildNodes() method, when invoked, must return true if the context object has children, and false otherwise.

The childNodes attribute’s getter must return a NodeList rooted at the context object matching only children.

The firstChild attribute’s getter must return the context object’s first child.

The lastChild attribute’s getter must return the context object’s last child.

The previousSibling attribute’s getter must return the context object’s previous sibling.

The nextSibling attribute’s getter must return the context object’s next sibling.


The nodeValue attribute must return the following, depending on the context object:

Text
ProcessingInstruction
Comment
The context object’s data.
Any other node
Null.

The nodeValue attribute must, on setting, if the new value is null, act as if it was the empty string instead, and then do as described below, depending on the context object:

Text
ProcessingInstruction
Comment
Replace data with node context object, offset 0, count length attribute value, and data new value.
Any other node
Do nothing.

The textContent attribute’s getter must return the following, switching on context object:

DocumentFragment
ShadowRoot
Element
The concatenation of data of all the Text node descendants of the context object, in tree order.
Text
ProcessingInstruction
Comment
The context object’s data.
Any other node
Null.

The textContent attribute’s setter must, if the given value is null, act as if it was the empty string instead, and then do as described below, switching on context object:

DocumentFragment
ShadowRoot
Element
  1. Let node be null.

  2. If the given value is not the empty string, set node to a new Text node whose data is the given value and node document is context object’s node document.

  3. Replace all with node within the context object.

Text
ProcessingInstruction
Comment

Replace data with node context object, offset 0, count length attribute value, and data the given value.

Any other node

Do nothing.


node . normalize()
Removes empty Text nodes and concatenates the data of remaining contiguous Text nodes into the first of their nodes.

The normalize() method must run these steps:

For each Text node descendant of the context object:

  1. Let node be the Text node descendant.
  2. Let length be node’s length attribute value.
  3. If length is zero, remove node and continue with the next Text node, if any.
  4. Let data be the concatenation of the data of node’s contiguous Text nodes (excluding itself), in tree order.
  5. Replace data with node node, offset length, count 0, and data data.
  6. Let current node be node’s next sibling.
  7. While current node is a Text node:
    1. For each range whose start node is current node, add length to its start offset and set its start node to node.
    2. For each range whose end node is current node, add length to its end offset and set its end node to node.
    3. For each range whose start node is current node’s parent and start offset is current node’s index, set its start node to node and its start offset to length.
    4. For each range whose end node is current node’s parent and end offset is current node’s index, set its end node to node and its end offset to length.
    5. Add current node’s length attribute value to length.
    6. Set current node to its next sibling.
  8. Remove node’s contiguous Text nodes (excluding itself), in tree order.

node . cloneNode([deep = false])
Returns a copy of node. If deep is true, the copy also includes the node’s descendants.
node . isEqualNode(otherNode)
Returns whether node and otherNode have the same properties.

Specifications may define cloning steps for all or some nodes. The algorithm is passed copy, node, document, and an optional clone children flag, as indicated in the clone algorithm.

HTML defines cloning steps for script and input elements. SVG ought to do the same for its script elements, but does not call this out at the moment.

To clone a node, with an optional document and clone children flag, run these steps:

  1. If document is not given, let document be node’s node document.

  2. If node is an element, then:

    1. Let copy be the result of creating an element, given document, node’s local name, node’s namespace, node’s namespace prefix, and the value of node’s is attribute if present (or null if not). The synchronous custom elements flag should be unset.

    2. For each attribute in node’s attribute list, in order, run these substeps:

      1. Let copyAttribute be a new attribute.

      2. Set copyAttribute’s namespace, namespace prefix, local name, and value, to those of attribute.

      3. Append copyAttribute to copy.

  3. Otherwise, let copy be a node that implements the same interfaces as node, and fulfills these additional requirements, switching on node:

    Document

    Set copy’s encoding, content type, URL, type, and mode, to those of node.

    DocumentType

    Set copy’s name, public ID, and system ID, to those of node.

    Text
    Comment
    Set copy’s data, to that of node.
    ProcessingInstruction
    Set copy’s target and data to those of node.
    Any other node
  4. Set copy’s node document and document to copy, if copy is a document, and set copy’s node document to document otherwise.

  5. Run any cloning steps defined for node in other applicable specifications and pass copy, node, document and the clone children flag if set, as parameters.
  6. If the clone children flag is set, clone all the children of node and append them to copy, with document as specified and the clone children flag being set.
  7. Return copy.

The cloneNode(deep) method, when invoked, must run these steps:

  1. If context object is a shadow root, then throw a NotSupportedError.

  2. Return a clone of the context object, with the clone children flag set if deep is true.

A node A equals a node B if all of the following conditions are true:

The isEqualNode(otherNode) method, when invoked, must return true if otherNode is non-null and context object equals otherNode, and false otherwise.

The isSameNode(otherNode) method, when invoked, must return true if otherNode is context object, and false otherwise.


node . compareDocumentPosition(other)
Returns a bitmask indicating the position of other relative to node. These are the bits that can be set:
Node . DOCUMENT_POSITION_DISCONNECTED (1)
Set when node and other are not in the same tree.
Node . DOCUMENT_POSITION_PRECEDING (2)
Set when other is preceding node.
Node . DOCUMENT_POSITION_FOLLOWING (4)
Set when other is following node.
Node . DOCUMENT_POSITION_CONTAINS (8)
Set when other is an ancestor of node.
Node . DOCUMENT_POSITION_CONTAINED_BY (16, 10 in hexadecimal)
Set when other is a descendant of node.
node . contains(other)
Returns true if other is an inclusive descendant of node, and false otherwise.

These are the constants compareDocumentPosition() returns as mask:

The compareDocumentPosition(other) method must run these steps:

  1. Let reference be the context object.
  2. If other and reference are the same object, return zero.
  3. If other and reference are not in the same tree, return the result of adding DOCUMENT_POSITION_DISCONNECTED, DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC, and either DOCUMENT_POSITION_PRECEDING or DOCUMENT_POSITION_FOLLOWING, with the constraint that this is to be consistent, together.

    Whether to return DOCUMENT_POSITION_PRECEDING or DOCUMENT_POSITION_FOLLOWING is typically implemented via pointer comparison. In JavaScript implementations Math.random() can be used.

  4. If other is an ancestor of reference, return the result of adding DOCUMENT_POSITION_CONTAINS to DOCUMENT_POSITION_PRECEDING.
  5. If other is a descendant of reference, return the result of adding DOCUMENT_POSITION_CONTAINED_BY to DOCUMENT_POSITION_FOLLOWING.
  6. If other is preceding reference return DOCUMENT_POSITION_PRECEDING.
  7. Return DOCUMENT_POSITION_FOLLOWING.

The contains(other) method must return true if other is an inclusive descendant of the context object, and false otherwise (including when other is null).


To locate a namespace prefix for an element using namespace run these steps:

  1. If element’s namespace is namespace and its namespace prefix is not null, return its namespace prefix.
  2. If element has an attribute whose namespace prefix is "xmlns" and value is namespace, then return element’s first such attribute’s local name.
  3. If element’s parent element is not null, return the result of running locate a namespace prefix on that element using namespace. Otherwise, return null.

To locate a namespace for a node using prefix depends on node:

Element
  1. If its namespace is not null and its namespace prefix is prefix, return namespace.
  2. If it has an attribute whose namespace is the XMLNS namespace, namespace prefix is "xmlns" and local name is prefix, or if prefix is null and it has an attribute whose namespace is the XMLNS namespace, namespace prefix is null and local name is "xmlns":
    1. Let value be its value if it is not the empty string, and null otherwise.
    2. Return value.
  3. If its parent element is null, return null.
  4. Return the result of running locate a namespace on its parent element using prefix.
Document
  1. If its document element is null, return null.
  2. Return the result of running locate a namespace on its document element using prefix.
DocumentType
DocumentFragment
ShadowRoot
Return null.
Any other node
  1. If its parent element is null, return null.
  2. Return the result of running locate a namespace on its parent element using prefix.

The lookupPrefix(namespace) method must run these steps:

  1. If namespace is null or the empty string, return null.
  2. Otherwise it depends on the context object:
    Element
    Return the result of locating a namespace prefix for the node using namespace.
    Document
    Return the result of locating a namespace prefix for its document element, if that is not null, and null otherwise.
    DocumentType
    DocumentFragment
    ShadowRoot
    Return null.
    Any other node
    Return the result of locating a namespace prefix for its parent element, or if that is null, null.

The lookupNamespaceURI(prefix) method must run these steps:

  1. If prefix is the empty string, set it to null.
  2. Return the result of running locate a namespace for the context object using prefix.

The isDefaultNamespace(namespace) method must run these steps:

  1. If namespace is the empty string, set it to null.
  2. Let defaultNamespace be the result of running locate a namespace for the context object using null.
  3. Return true if defaultNamespace is the same as namespace, and false otherwise.

The insertBefore(node, child) method must return the result of pre-inserting node into the context object before child.

The appendChild(node) method must return the result of appending node to the context object.

The replaceChild(node, child) method must return the result of replacing child with node within the context object.

The removeChild(child) method must return the result of pre-removing child from the context object.


The list of elements with qualified name qualifiedName for a node root is the HTMLCollection returned by the following algorithm:

  1. If qualifiedName is "*" (U+002A), return a HTMLCollection rooted at root, whose filter matches only descendant elements.

  2. Otherwise, if root’s node document is an HTML document, return a HTMLCollection rooted at root, whose filter matches the following descendant elements:

  3. Otherwise, return a HTMLCollection rooted at root, whose filter matches descendant elements whose qualified name is qualifiedName.

When invoked with the same argument, and as long as root’s node document’s type has not changed, the same HTMLCollection object may be returned as returned by an earlier call.

The list of elements with namespace namespace and local name localName for a node root is the HTMLCollection returned by the following algorithm:

  1. If namespace is the empty string, set it to null.
  2. If both namespace and localName are "*" (U+002A), return a HTMLCollection rooted at root, whose filter matches descendant elements.
  3. Otherwise, if namespace is "*" (U+002A), return a HTMLCollection rooted at root, whose filter matches descendant elements whose local name is localName.
  4. Otherwise, if localName is "*" (U+002A), return a HTMLCollection rooted at root, whose filter matches descendant elements whose namespace is namespace.
  5. Otherwise, return a HTMLCollection rooted at root, whose filter matches descendant elements whose namespace is namespace and local name is localName.

When invoked with the same arguments, the same HTMLCollection object may be returned as returned by an earlier call.

The list of elements with class names classNames for a node root is the HTMLCollection returned by the following algorithm:

  1. Let classes be the result of running the ordered set parser on classNames.
  2. If classes is the empty set, return an empty HTMLCollection.
  3. Return a HTMLCollection rooted at root, whose filter matches descendant elements that have all their classes in classes.

    The comparisons for the classes must be done in an ASCII case-insensitive manner if root’s node document’s mode is "quirks", and in a case-sensitive manner otherwise.

When invoked with the same argument, the same HTMLCollection object may be returned as returned by an earlier call.

4.5. Interface Document

[Constructor,
 Exposed=Window]
interface Document : Node {
  [SameObject] readonly attribute DOMImplementation implementation;
  readonly attribute USVString URL;
  readonly attribute USVString documentURI;
  readonly attribute USVString origin;
  readonly attribute DOMString compatMode;
  readonly attribute DOMString characterSet;
  readonly attribute DOMString charset; // historical alias of .characterSet
  readonly attribute DOMString inputEncoding; // historical alias of .characterSet
  readonly attribute DOMString contentType;

  readonly attribute DocumentType? doctype;
  readonly attribute Element? documentElement;
  HTMLCollection getElementsByTagName(DOMString qualifiedName);
  HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
  HTMLCollection getElementsByClassName(DOMString classNames);

  [NewObject] Element createElement(DOMString localName, optional ElementCreationOptions options);
  [NewObject] Element createElementNS(DOMString? namespace, DOMString qualifiedName, optional ElementCreationOptions options);
  [NewObject] DocumentFragment createDocumentFragment();
  [NewObject] Text createTextNode(DOMString data);
  [NewObject] Comment createComment(DOMString data);
  [NewObject] ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data);

  [CEReactions, NewObject] Node importNode(Node node, optional boolean deep = false);
  [CEReactions] Node adoptNode(Node node);

  [NewObject] Attr createAttribute(DOMString localName);
  [NewObject] Attr createAttributeNS(DOMString? namespace, DOMString qualifiedName);

  [NewObject] Event createEvent(DOMString interface);

  [NewObject] Range createRange();

  // NodeFilter.SHOW_ALL = 0xFFFFFFFF
  [NewObject] NodeIterator createNodeIterator(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
  [NewObject] TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
};

[Exposed=Window]
interface XMLDocument : Document {};

dictionary ElementCreationOptions {
  DOMString is;
};

Document nodes are simply known as documents.

Each document has an associated base URL (a URL), encoding (an encoding), content type (a string), URL (a URL), type ("xml" or "html"), and mode ("no-quirks", "quirks", or "limited-quirks"). [ENCODING] [URL]

Unless stated otherwise, a document’s base URL is "about:blank", encoding is the utf-8 encoding, content type is "application/xml", URL is "about:blank", type is "xml", and its mode is "no-quirks".

Unless stated otherwise, a document’s origin is a new opaque origin. [HTML]

A document is said to be an XML document if its type is "xml", and an HTML document otherwise. Whether a document is an HTML document or an XML document affects the behavior of certain APIs.

A document is said to be in no-quirks mode if its mode is "no-quirks", quirks mode if its mode is "quirks", and limited-quirks mode if its mode is "limited-quirks".

The mode is only ever changed from the default if the document is created by the HTML parser, based on the presence, absence, or value of the DOCTYPE string. [HTML]

No-quirks mode was originally known as "standards mode" and limited-quirks mode was once known as "almost standards mode". They have been renamed because their details are now defined by standards. (And because Ian Hickson vetoed their original names on the basis that they are nonsensical.)

A document’s get the parent algorithm, given an event, returns null if event’s type attribute value is "load" or document does not have a browsing context, and the document’s associated Window object otherwise.


document = new Document()
Returns a new document.
document . implementation
Returns document’s DOMImplementation object.
document . URL
document . documentURI
Returns document’s URL.
document . origin
Returns document’s origin.
document . compatMode
Returns the string "BackCompat" if document’s mode is "quirks", and "CSS1Compat" otherwise.
document . characterSet
Returns document’s encoding.
document . contentType
Returns document’s content type.

The Document() constructor, when invoked, must return a new document whose origin is the origin of the global object’s associated document. [HTML]

Unlike createDocument() this constructor does not return an XMLDocument object, but a document (Document object).

The implementation attribute’s getter must return the DOMImplementation object that is associated with the document.

The URL attribute’s getter and documentURI attribute’s getter must return the URL, serialized.

The origin attribute’s getter must return the Unicode serialization of context object’s origin.

The compatMode attribute’s getter must return "BackCompat" if context object’s mode is "quirks", and "CSS1Compat" otherwise.

The characterSet attribute’s getter, charset attribute’s getter, and inputEncoding attribute’s getter, must return context object’s encoding’s name.

The contentType attribute’s getter must return the content type.


document . doctype
Returns the doctype or null if there is none.
document . documentElement
Returns the document element.
collection = document . getElementsByTagName(qualifiedName)

If qualifiedName is "*" returns a HTMLCollection of all descendant elements.

Otherwise, returns a HTMLCollection of all descendant elements whose qualified name is qualifiedName. (Matches case-insensitively against elements in the HTML namespace within an HTML document.)

collection = document . getElementsByTagNameNS(namespace, localName)
If namespace and localName are "*" returns a HTMLCollection of all descendant elements.

If only namespace is "*" returns a HTMLCollection of all descendant elements whose local name is localName.

If only localName is "*" returns a HTMLCollection of all descendant elements whose namespace is namespace.

Otherwise, returns a HTMLCollection of all descendant elements whose namespace is namespace and local name is localName.

collection = document . getElementsByClassName(classNames)
collection = element . getElementsByClassName(classNames)
Returns a HTMLCollection of the elements in the object on which the method was invoked (a document or an element) that have all the classes given by classNames. The classNames argument is interpreted as a space-separated list of classes.

The doctype attribute’s getter must return the child of the document that is a doctype, and null otherwise.

The documentElement attribute’s getter must return the document element.

The getElementsByTagName(qualifiedName) method, when invoked, must return the list of elements with qualified name qualifiedName for the context object.

Thus, in an HTML document, document.getElementsByTagName("FOO") will match <FOO> elements that are not in the HTML namespace, and <foo> elements that are in the HTML namespace, but not <FOO> elements that are in the HTML namespace.

The getElementsByTagNameNS(namespace, localName) method, when invoked, must return the list of elements with namespace namespace and local name localName for the context object.

The getElementsByClassName(classNames) method, when invoked, must return the list of elements with class names classNames for the context object.

Given the following XHTML fragment:
<div id="example">
  <p id="p1" class="aaa bbb"/>
  <p id="p2" class="aaa ccc"/>
  <p id="p3" class="bbb ccc"/>
</div>

A call to document.getElementById("example").getElementsByClassName("aaa") would return a HTMLCollection with the two paragraphs p1 and p2 in it.

A call to getElementsByClassName("ccc bbb") would only return one node, however, namely p3. A call to document.getElementById("example").getElementsByClassName("bbb  ccc ") would return the same thing.

A call to getElementsByClassName("aaa,bbb") would return no nodes; none of the elements above are in the aaa,bbb class.


element = document . createElement(localName [, options])
Returns an element in the HTML namespace with localName as local name. (In an HTML document localName is lowercased.)

If localName does not match the Name production an InvalidCharacterError will be thrown.

When supplied, optionsis member can be used to create a customized built-in element.

element = document . createElementNS(namespace, qualifiedName [, options])
Returns an element with namespace namespace. Its namespace prefix will be everything before ":" (U+003E) in qualifiedName or null. Its local name will be everything after ":" (U+003E) in qualifiedName or qualifiedName.

If localName does not match the Name production an InvalidCharacterError will be thrown.

If one of the following conditions is true a NamespaceError will be thrown:

When supplied, optionsis member can be used to create a customized built-in element.

documentFragment = document . createDocumentFragment()
Returns a DocumentFragment node.
text = document . createTextNode(data)
Returns a Text node whose data is data.
comment = document . createComment(data)
Returns a Comment node whose data is data.
processingInstruction = document . createProcessingInstruction(target, data)
Returns a ProcessingInstruction node whose target is target and data is data. If target does not match the Name production an InvalidCharacterError will be thrown. If data contains "?>" an InvalidCharacterError will be thrown.

The element interface for any name and namespace is Element, unless stated otherwise.

The HTML Standard will e.g. define that for html and the HTML namespace, the HTMLHtmlElement interface is used. [HTML]

The createElement(localName, options) method, when invoked, must run these steps:

  1. If localName does not match the Name production, then throw an InvalidCharacterError.

  2. If the context object is an HTML document, let localName be converted to ASCII lowercase.
  3. Let is be the value of is member of options, or null if no such member exists.
  4. Let definition be the result of looking up a custom element definition, given the context object, the HTML namespace, localName, and is.
  5. If is is non-null and definition is null, then throw a NotFoundError.
  6. Let namespace be the HTML namespace, if the context object’s content type is "text/html" or "application/xhtml+xml", and null otherwise.
  7. Let element be the result of creating an element given the context object, localName, namespace, null, is, and with the synchronous custom elements flag set. Rethrow any exceptions.
  8. If is is non-null, then set an attribute value for element using "is" and is.
  9. Return element.

The internal createElementNS steps, given document, namespace, qualifiedName, and options, are as follows:

  1. Let namespace, prefix, and localName be the result of passing namespace and qualifiedName to validate and extract. Rethrow any exceptions.
  2. Let is be the value of is member of options, or null if no such member exists.
  3. Let definition be the result of looking up a custom element definition, given the context object, namespace, localName, and is.
  4. If is is non-null and definition is null, then throw a NotFoundError.
  5. Let element be the result of creating an element given document, localName, namespace, prefix, is, and with the synchronous custom elements flag set. Rethrow any exceptions.

  6. If is is non-null, then set an attribute value for element using "is" and is.
  7. Return element.

The createElementNS(namespace, qualifiedName, options) method, when invoked, must return the result of running the internal createElementNS steps, given context object, namespace, qualifiedName, and options.

The createDocumentFragment() method, when invoked, must return a new DocumentFragment node with its node document set to the context object.

The createTextNode(data) method, when invoked, must return a new Text node with its data set to data and node document set to the context object.

No check is performed that data consists of characters that match the Char production.

The createComment(data) method, when invoked, must return a new Comment node with its data set to data and node document set to the context object.

No check is performed that data consists of characters that match the Char production or that it contains two adjacent hyphens or ends with a hyphen.

The createProcessingInstruction(target, data) method, when invoked, must run these steps:

  1. If target does not match the Name production, then throw an InvalidCharacterError.
  2. If data contains the string "?>", then throw an InvalidCharacterError.
  3. Return a new ProcessingInstruction node, with target set to target, data set to data, and node document set to the context object.

No check is performed that target contains "xml" or ":", or that data contains characters that match the Char production.


clone = document . importNode(node [, deep = false])
Returns a copy of node. If deep is true, the copy also includes the node’s descendants.

If node is a document or a shadow root, throws a NotSupportedError.

node = document . adoptNode(node)
Moves node from another document and returns it.

If node is a document, throws a NotSupportedError or, if node is a shadow root, throws a HierarchyRequestError.

The importNode(node, deep) method, when invoked, must run these steps:

  1. If node is a document or shadow root, then throw a NotSupportedError.

  2. Return a clone of node, with context object and the clone children flag set if deep is true.

Specifications may define adopting steps for all or some nodes. The algorithm is passed node and oldDocument, as indicated in the adopt algorithm.

To adopt a node into a document, run these steps:

  1. Let oldDocument be node’s node document.

  2. If node’s parent is not null, remove node from its parent.

  3. If document is not the same as oldDocument, run these substeps:

    1. For each inclusiveDescendant in node’s shadow-including inclusive descendants, in shadow-including tree order, set inclusiveDescendant’s node document to document.

    2. For each inclusiveDescendant in node’s shadow-including inclusive descendants, in shadow-including tree order, run the adopting steps with inclusiveDescendant and oldDocument.

The adoptNode(node) method, when invoked, must run these steps:

  1. If node is a document, then throw a NotSupportedError.
  2. If node is a shadow root, then throw a HierarchyRequestError.
  3. Adopt node into the context object.
  4. Return node.

The createAttribute(localName) method, when invoked, must run these steps:

  1. If localName does not match the Name production in XML, then throw an InvalidCharacterError.

  2. If the context object is an HTML document, let localName be converted to ASCII lowercase.
  3. Return a new attribute whose local name is localName.

The createAttributeNS(namespace, qualifiedName) method, when invoked, must run these steps:

  1. Let namespace, prefix, and localName be the result of passing namespace and qualifiedName to validate and extract. Rethrow any exceptions.

  2. Return a new attribute whose namespace is namespace, namespace prefix is prefix, and local name is localName.


The createEvent(interface) method, when invoked, must run these steps:

  1. Let constructor be null.

  2. If interface is an ASCII case-insensitive match for any of the strings in the first column in the following table, then set constructor to the interface in the second column on the same row as the matching string:

    String Interface Notes
    "animationevent" AnimationEvent [CSS3-ANIMATIONS]
    "beforeunloadevent" BeforeUnloadEvent [HTML]
    "closeevent" CloseEvent
    "compositionevent" CompositionEvent [UIEVENTS]
    "customevent" CustomEvent
    "devicemotionevent" DeviceMotionEvent [DEVICE-ORIENTATION]
    "deviceorientationevent" DeviceOrientationEvent
    "dragevent" DragEvent [HTML]
    "errorevent" ErrorEvent
    "event" Event
    "events"
    "focusevent" FocusEvent [UIEVENTS]
    "hashchangeevent" HashChangeEvent [HTML]
    "htmlevents" Event
    "idbversionchangeevent" IDBVersionChangeEvent [INDEXEDDB]
    "keyboardevent" KeyboardEvent [UIEVENTS]
    "messageevent" MessageEvent [HTML]
    "mouseevent" MouseEvent [UIEVENTS]
    "mouseevents"
    "pagetransitionevent" PageTransitionEvent [HTML]
    "popstateevent" PopStateEvent
    "progressevent" ProgressEvent [XHR]
    "storageevent" StorageEvent [HTML]
    "svgevents" Event
    "svgzoomevent" SVGZoomEvent [SVG]
    "svgzoomevents"
    "textevent" CompositionEvent [UIEVENTS]
    "touchevent" TouchEvent [TOUCH-EVENTS]
    "trackevent" TrackEvent [HTML]
    "transitionevent" TransitionEvent [CSS3-TRANSITIONS]
    "uievent" UIEvent [UIEVENTS]
    "uievents"
    "webglcontextevent" WebGLContextEvent [WEBGL]
    "wheelevent" WheelEvent [UIEVENTS]
  3. If constructor is null, then throw a NotSupportedError.

  4. If the initial value of constructor is undefined, then throw a NotSupportedError.

    Typically user agents disable support for touch events in some configurations, in which case the initial value of TouchEvent is undefined.

  5. Let event be the result of invoking the initial value of constructor with the empty string as argument.

  6. Unset event’s initialized flag.

  7. Return event.

Event constructors ought to be used instead.


The createRange() method, when invoked, must return a new range with (context object, 0) as its start and end.

The Range() constructor ought to be used instead.


The createNodeIterator(root, whatToShow, filter) method, when invoked, must run these steps:

  1. Create a NodeIterator object.
  2. Set root to root and initialize the referenceNode attribute to root.
  3. Initialize the pointerBeforeReferenceNode attribute to true.
  4. Set whatToShow to whatToShow.
  5. Set filter to filter.
  6. Return the newly created NodeIterator object.

The createTreeWalker(root, whatToShow, filter) method, when invoked, must run these steps:

  1. Create a TreeWalker object.
  2. Set root to root and initialize the currentNode attribute to root.
  3. Set whatToShow to whatToShow.
  4. Set filter to filter.
  5. Return the newly created TreeWalker object.

4.5.1. Interface DOMImplementation

User agents must create a DOMImplementation object whenever a document is created and associate it with that document.

[Exposed=Window]
interface DOMImplementation {
  [NewObject] DocumentType createDocumentType(DOMString qualifiedName, DOMString publicId, DOMString systemId);
  [NewObject] XMLDocument createDocument(DOMString? namespace, [TreatNullAs=EmptyString] DOMString qualifiedName, optional DocumentType? doctype = null);
  [NewObject] Document createHTMLDocument(optional DOMString title);

  boolean hasFeature(); // useless; always returns true
};
doctype = document . implementation . createDocumentType(qualifiedName, publicId, systemId)
Returns a doctype, with the given qualifiedName, publicId, and systemId. If qualifiedName does not match the Name production, an InvalidCharacterError is thrown, and if it does not match the QName production, a NamespaceError is thrown.
doc = document . implementation . createDocument(namespace, qualifiedName [, doctype = null])
Returns an XMLDocument, with a document element whose local name is qualifiedName and whose namespace is namespace (unless qualifiedName is the empty string), and with doctype, if it is given, as its doctype.

This method throws the same exceptions as the createElementNS() method, when invoked with namespace and qualifiedName.

doc = document . implementation . createHTMLDocument([title])
Returns a document, with a basic tree already constructed including a title element, unless the title argument is omitted.

The createDocumentType(qualifiedName, publicId, systemId) method, when invoked, must run these steps:

  1. Validate qualifiedName. Rethrow any exceptions.

  2. Return a new doctype, with qualifiedName as its name, publicId as its public ID, and systemId as its system ID, and with its node document set to the associated document of the context object.

No check is performed that publicId code points match the PubidChar production or that systemId does not contain both a '"' and a "'".

The createDocument(namespace, qualifiedName, doctype) method, when invoked, must run these steps:

  1. Let document be a new XMLDocument.

    This method creates an XMLDocument rather than a normal document. They are identical except for the addition of the load() method deployed content relies upon. [HTML]

  2. Let element be null.

  3. If qualifiedName is not the empty string, then set element to the result of running the internal createElementNS steps, given document, namespace, qualifiedName, and an empty dictionary. Rethrow any exceptions.

  4. If doctype is non-null, append doctype to document.

  5. If element is non-null, append element to document.

  6. document’s origin is the origin of the context object’s associated document. [HTML]

  7. document’s content type is determined by namespace:

    HTML namespace
    application/xhtml+xml
    SVG namespace
    image/svg+xml
    Any other namespace
    application/xml
  8. Return document.

The createHTMLDocument(title) method, when invoked, must run these steps:

  1. Let doc be a new document that is an HTML document.

  2. Set doc’s content type to "text/html".

  3. Append a new doctype, with "html" as its name and with its node document set to doc, to doc.

  4. Append the result of creating an element given doc, html, and the HTML namespace, to doc.

  5. Append the result of creating an element given doc, head, and the HTML namespace, to the html element created earlier.

  6. If title is given:

    1. Append the result of creating an element given doc, title, and the HTML namespace, to the head element created earlier.

    2. Append a new Text node, with its data set to title (which could be the empty string) and its node document set to doc, to the title element created earlier.

  7. Append the result of creating an element given doc, body, and the HTML namespace, to the html element created earlier.

  8. doc’s origin is the origin of the context object’s associated document. [HTML]

  9. Return doc.

The hasFeature() method, when invoked, must return true.

hasFeature() originally would report whether the user agent claimed to support a given DOM feature, but experience proved it was not nearly as reliable or granular as simply checking whether the desired objects, attributes, or methods existed. As such, it is no longer to be used, but continues to exist (and simply returns true) so that old pages don’t stop working.

4.6. Interface DocumentType

[Exposed=Window]
interface DocumentType : Node {
  readonly attribute DOMString name;
  readonly attribute DOMString publicId;
  readonly attribute DOMString systemId;
};

DocumentType nodes are simply known as doctypes.

Doctypes have an associated name, public ID, and system ID.

When a doctype is created, its name is always given. Unless explicitly given when a doctype is created, its public ID and system ID are the empty string.

The name attribute’s getter must return the context object’s name.

The publicId attribute’s getter must return the context object’s public ID.

The systemId attribute’s getter must return the context object’s system ID.

4.7. Interface DocumentFragment

[Constructor,
 Exposed=Window]
interface DocumentFragment : Node {
};

A DocumentFragment node has an associated host (null or an element in a different node tree). It is null unless otherwise stated.

An object A is a host-including inclusive ancestor of an object B, if either A is an inclusive ancestor of B, or if B’s root has a non-null host and A is a host-including inclusive ancestor of B’s root’s host.

The DocumentFragment node’s host concept is useful for HTML’s template element and for shadow roots, and impacts the pre-insert and replace algorithms.

tree = new DocumentFragment()
Returns a new DocumentFragment node.

The DocumentFragment() constructor, when invoked, must return a new DocumentFragment node whose node document is the global object’s associated document.

4.8. Interface ShadowRoot

[Exposed=Window]
interface ShadowRoot : DocumentFragment {
  readonly attribute ShadowRootMode mode;
  readonly attribute Element host;
};

enum ShadowRootMode { "open", "closed" };

ShadowRoot nodes are simply known as shadow roots.

Shadow roots have an associated mode ("open" or "closed").

Shadow roots’s associated host is never null.

A shadow root’s get the parent algorithm, given an event, returns null if event’s composed flag is unset and shadow root is the root of event’s path’s first tuple’s item, and shadow root’s host otherwise.

The mode attribute’s getter must return the context object’s mode.

The host attribute’s getter must return the context object’s host.


In shadow-including tree order, is shadow-including preorder, depth-first traversal of a node tree. shadow-including preorder, depth-first traversal of a node tree tree is preorder, depth-first traversal of tree, with for each shadow host encountered in tree, shadow-including preorder, depth-first traversal of that element’s shadow root’s node tree just after it is encountered.

The shadow-including root of an object is its root’s host’s shadow-including root, if the object’s root is a shadow root, and its root otherwise.

An object A is a shadow-including descendant of an object B, if A is a descendant of B, or A’s root is a shadow root and A’s root’s host is a shadow-including inclusive descendant of B.

A shadow-including inclusive descendant is an object or one of its shadow-including descendants.

An object A is a shadow-including ancestor of an object B, if and only if B is a shadow-including descendant of A.

A shadow-including inclusive ancestor is an object or one of its shadow-including ancestors.

A node A is an unclosed node of a node B, if A’s root is a shadow-including inclusive ancestor of B, or A’s root is a shadow root whose mode is "open" and host is an unclosed node of B.


For now you can find more information about this object in Shadow DOM. The DOM Standard will be updated over time to cover more details.

4.9. Interface Element

[Exposed=Window]
interface Element : Node {
  readonly attribute DOMString? namespaceURI;
  readonly attribute DOMString? prefix;
  readonly attribute DOMString localName;
  readonly attribute DOMString tagName;

  [CEReactions] attribute DOMString id;
  [CEReactions] attribute DOMString className;
  [CEReactions, SameObject, PutForwards=value] readonly attribute DOMTokenList classList;
  [CEReactions] attribute DOMString slot;

  boolean hasAttributes();
  [SameObject] readonly attribute NamedNodeMap attributes;
  sequence<DOMString> getAttributeNames();
  DOMString? getAttribute(DOMString qualifiedName);
  DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
  [CEReactions] void setAttribute(DOMString qualifiedName, DOMString value);
  [CEReactions] void setAttributeNS(DOMString? namespace, DOMString qualifiedName, DOMString value);
  [CEReactions] void removeAttribute(DOMString qualifiedName);
  [CEReactions] void removeAttributeNS(DOMString? namespace, DOMString localName);
  boolean hasAttribute(DOMString qualifiedName);
  boolean hasAttributeNS(DOMString? namespace, DOMString localName);

  Attr? getAttributeNode(DOMString qualifiedName);
  Attr? getAttributeNodeNS(DOMString? namespace, DOMString localName);
  [CEReactions] Attr? setAttributeNode(Attr attr);
  [CEReactions] Attr? setAttributeNodeNS(Attr attr);
  [CEReactions] Attr removeAttributeNode(Attr attr);

  ShadowRoot attachShadow(ShadowRootInit init);
  readonly attribute ShadowRoot? shadowRoot;

  Element? closest(DOMString selectors);
  boolean matches(DOMString selectors);
  boolean webkitMatchesSelector(DOMString selectors); // historical alias of .matches

  HTMLCollection getElementsByTagName(DOMString qualifiedName);
  HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
  HTMLCollection getElementsByClassName(DOMString classNames);

  [CEReactions] Element? insertAdjacentElement(DOMString where, Element element); // historical
  [CEReactions] void insertAdjacentText(DOMString where, DOMString data); // historical
};

dictionary ShadowRootInit {
  required ShadowRootMode mode;
};

Element nodes are simply known as elements.

Elements have an associated namespace, namespace prefix, local name, and custom element state. When an element is created, all of these values are initialized.

An element’s custom element state is one of "undefined", "uncustomized", or "custom". An element whose custom element state is "uncustomized" or "custom" is said to be defined. An element whose custom element state is "custom", is said to be custom.

Whether or not an element is defined is used to determine the behavior of the :defined pseudo-class. Whether or not an element is custom is used to determine the behavior of the mutation algorithms.

The following code illustrates elements in each of these three states:

<!DOCTYPE html>
<script>
  window.customElements.define("sw-rey", class extends HTMLElement {})
  window.customElements.define("sw-finn", class extends HTMLElement {}, { extends: "p" })
  window.customElements.define("sw-kylo", class extends HTMLElement {
    constructor() {
      super()
      throw new Error("The droid... stole a freighter?")
    }
  })
</script>

<!-- "undefined" (not defined, not custom) -->
<sw-han></sw-han>
<sw-kylo></sw-kylo>
<p is="sw-luke"></p>
<p is="asdf"></p>

<!-- "uncustomized" (defined, not custom) -->
<p></p>
<asdf></asdf>

<!-- "custom" (defined, custom) -->
<sw-rey></sw-rey>
<p is="sw-finn"></p>

Elements also have an associated shadow root (null or a shadow root). It is null unless otherwise stated. An element is a shadow host if its shadow root is non-null.

An element’s qualified name is its local name if its namespace prefix is null, and its namespace prefix, followed by ":", followed by its local name, otherwise.

User agents could have this as an internal slot as an optimization, but are not required to do so. The standard has this concept for readability.

To create an element, given a document, localName, namespace, and optional prefix, is, and synchronous custom elements flag, run these steps:

  1. If prefix was not given, let prefix be null.

  2. If is was not given, let is be null.

  3. Let result be null.

  4. Let definition be the result of looking up a custom element definition given document, namespace, localName, and is.

  5. If definition is non-null, and definition’s name is not equal to its local name (i.e., definition represents a customized built-in element), then:

    1. Let interface be the element interface for localName and the HTML namespace.

    2. Set result to a new element that implements interface, with no attributes, namespace set to the HTML namespace, namespace prefix set to prefix, local name set to localName, custom element state set to "undefined", and node document set to document.

    3. If the synchronous custom elements flag is set, upgrade element using definition.

    4. Otherwise, enqueue a custom element upgrade reaction given result and definition.

  6. Otherwise, if definition is non-null, then:

    1. If the synchronous custom elements flag is set:

      1. Let C be definition’s constructor.

      2. Set result to Construct(C). Rethrow any exceptions.

      3. If result does not implement the HTMLElement interface, throw a TypeError.

        This is meant to be a brand check to ensure that the object was allocated by the HTMLElement constructor. See webidl #97 about making this more precise.

      4. If result’s attribute list is not empty, then throw a NotSupportedError.

      5. If result has children, then throw a NotSupportedError.

      6. If result’s parent is not null, then throw a NotSupportedError.

      7. If result’s node document is not document, then throw a NotSupportedError.

      8. If result’s namespace is not the HTML namespace, then throw a NotSupportedError.

      9. If result’s local name is not equal to localName, then throw a NotSupportedError.

      10. Set result’s namespace prefix to prefix.

      11. Set result’s custom element state to "custom".

    2. Otherwise:

      1. Set result to a new element that implements the HTMLElement interface, with no attributes, namespace set to the HTML namespace, namespace prefix set to prefix, local name set to localName, custom element state set to "undefined", and node document set to document.

      2. Enqueue a custom element upgrade reaction given result and definition.

  7. Otherwise:

    1. Let interface be the element interface for localName and namespace.

    2. Set result to a new element that implements interface, with no attributes, namespace set to namespace, namespace prefix set to prefix, local name set to localName, custom element state set to "uncustomized", and node document set to document.

    3. If document has a browsing context, and namespace is the HTML namespace, and either localName is a valid custom element name or is is is non-null, set result’s custom element state to "undefined".

  8. Return result.

Elements also have an ordered attribute list exposed through a NamedNodeMap. Unless explicitly given when an element is created, its attribute list is empty. An element has an attribute A if A is in its attribute list.

This and other specifications may define attribute change steps for elements. The algorithm is passed element, localName, oldValue, value, and namespace.

To change an attribute attribute from an element element to value, run these steps:

  1. Queue a mutation record of "attributes" for element with name attribute’s local name, namespace attribute’s namespace, and oldValue attribute’s value.
  2. If element is custom, then enqueue a custom element callback reaction with element, callback name "attributeChangedCallback", and an argument list containing attribute’s local name, attribute’s value, value, and attribute’s namespace.
  3. Run the attribute change steps with element, attribute’s local name, attribute’s value, value, and attribute’s namespace.

  4. Set attribute’s value to value.

To append an attribute attribute to an element element, run these steps:

  1. Queue a mutation record of "attributes" for element with name attribute’s local name, namespace attribute’s namespace, and oldValue null.
  2. If element is custom, then enqueue a custom element callback reaction with element, callback name "attributeChangedCallback", and an argument list containing attribute’s local name, null, attribute’s value, and attribute’s namespace.
  3. Run the attribute change steps with element, attribute’s local name, null, attribute’s value, and attribute’s namespace.

  4. Append the attribute to the element’s attribute list.
  5. Set attribute’s element to element.

To remove an attribute attribute from an element element, run these steps:

  1. Queue a mutation record of "attributes" for element with name attribute’s local name, namespace attribute’s namespace, and oldValue attribute’s value.
  2. If element is custom, then enqueue a custom element callback reaction with element, callback name "attributeChangedCallback", and an argument list containing attribute’s local name, attribute’s value, null, and attribute’s namespace.
  3. Run the attribute change steps with element, attribute’s local name, attribute’s value, null, and attribute’s namespace.

  4. Remove attribute from the element’s attribute list.
  5. Set attribute’s element to null.

To replace an attribute oldAttr by an attribute newAttr in an element element, run these steps:

  1. Queue a mutation record of "attributes" for element with name oldAttr’s local name, namespace oldAttr’s namespace, and oldValue oldAttr’s value.

  2. If element is custom, then enqueue a custom element callback reaction with element, callback name "attributeChangedCallback", and an argument list containing oldAttr’s local name, oldAttr’s value, newAttr’s value, and oldAttr’s namespace.
  3. Run the attribute change steps with element, oldAttr’s local name, oldAttr’s value, newAttr’s value, and oldAttr’s namespace.

  4. Replace oldAttr by newAttr in the element’s attribute list.

  5. Set oldAttr’s element to null.

  6. Set newAttr’s element to element.


To get an attribute by name given a qualifiedName and element element, run these steps:

  1. If element is in the HTML namespace and its node document is an HTML document, let qualifiedName be converted to ASCII lowercase.

  2. Return the first attribute in element’s attribute list whose qualified name is qualifiedName, and null otherwise.

To get an attribute by namespace and local name given a namespace, localName, and element element, run these steps:

  1. If namespace is the empty string, set it to null.
  2. Return the attribute in element’s attribute list whose namespace is namespace and local name is localName, if any, and null otherwise.

To get an attribute value given an element element, localName, and optionally a namespace (null unless stated otherwise), run these steps:

  1. Let attr be the result of getting an attribute given namespace, localName, and element.

  2. If attr is null, then return the empty string.

  3. Return attr’s value.

To set an attribute given an attr and element, run these steps:

  1. If attr’s element is neither null nor element, throw an InUseAttributeError.

  2. Let oldAttr be the result of getting an attribute given attr’s namespace, attr’s local name, and element.

  3. If oldAttr is attr, return attr.

  4. If oldAttr is non-null, replace it by attr in element.

  5. Otherwise, append attr to element.

  6. Return oldAttr.

To set an attribute value for an element element using a localName and value, and an optional prefix, and namespace, run these steps:

  1. If prefix is not given, set it to null.
  2. If namespace is not given, set it to null.
  3. Let attribute be the result of getting an attribute given namespace, localName, and element.
  4. If attribute is null, create an attribute whose namespace is namespace, namespace prefix is prefix, local name is localName, and value is value, and then append this attribute to element and terminate these steps.
  5. Change attribute from element to value.

To remove an attribute by name given a qualifiedName and element element, run these steps:

  1. Let attr be the result of getting an attribute given qualifiedName and element.

  2. If attr is non-null, remove it from element.

  3. Return attr.

To remove an attribute by namespace and local name given a namespace, localName, and element element, run these steps:

  1. Let attr be the result of getting an attribute given namespace, localName, and element.
  2. If attr is non-null, remove it from element.
  3. Return attr.

An element can have an associated unique identifier (ID)

Historically elements could have multiple identifiers e.g., by using the HTML id attribute and a DTD. This specification makes ID a concept of the DOM and allows for only one per element, given by an id attribute.

Use these attribute change steps to update an element’s ID:

  1. If localName is id, namespace is null, and value is null or the empty string, then unset element’s ID.

  2. Otherwise, if localName is id, namespace is null, then set element’s ID to value.

While this specification defines requirements for class, id, and slot attributes on any element, it makes no claims as to whether using them is conforming or not.


A node’s parent of type Element is known as a parent element. If the node has a parent of a different type, its parent element is null.


namespace = element . namespaceURI
Returns the namespace.
prefix = element . prefix
Returns the namespace prefix.
localName = element . localName
Returns the local name.
qualifiedName = element . tagName
Returns the qualified name. (The return value is uppercased in an HTML document.)

The namespaceURI attribute’s getter must return the context object’s namespace.

The prefix attribute’s getter must return the context object’s namespace prefix.

The localName attribute’s getter must return the context object’s local name.

The tagName attribute’s getter must run these steps:

  1. Let qualifiedName be context object’s qualified name.

  2. If the context object is in the HTML namespace and its node document is an HTML document, let qualifiedName be converted to ASCII uppercase.

  3. Return qualifiedName.

IDL attributes that are defined to reflect a content attribute of a given name, must have a getter and setter that follow these steps:

getter

Return the result of running get an attribute value given context object and name.

setter

Set an attribute value for the context object using name and the given value.

The id attribute must reflect the "id" content attribute.

The className attribute must reflect the "class" content attribute.

The classList attribute’s getter must return a DOMTokenList object whose associated element is the context object and whose associated attribute’s local name is class. The tokens of this particular DOMTokenList object are also known as the element’s classes.

The slot attribute must reflect the "slot" content attribute.

id, class, and slot are effectively superglobal attributes as they can appear on any element, regardless of that element’s namespace.


The hasAttributes() method, when invoked, must return false if context object’s attribute list is empty, and true otherwise.

The attributes attribute must return the associated NamedNodeMap.

The getAttributeNames() method, when invoked, must return the qualified names of the attributes in the context object’s attribute list, in order, and the empty sequence otherwise.

These are not guaranteed to be unique.

The getAttribute(qualifiedName) method, when invoked, must run these steps:

  1. Let attr be the result of getting an attribute given qualifiedName and the context object.

  2. If attr is null, return null.

  3. Return attr’s value.

The getAttributeNS(namespace, localName) method, when invoked, must these steps:

  1. Let attr be the result of getting an attribute given namespace, localName, and the context object.

  2. If attr is null, return null.

  3. Return attr’s value.

The setAttribute(qualifiedName, value) method, when invoked, must run these steps:

  1. If qualifiedName does not match the Name production in XML, then throw an InvalidCharacterError.

  2. If the context object is in the HTML namespace and its node document is an HTML document, let qualifiedName be converted to ASCII lowercase.

  3. Let attribute be the first attribute in context object’s attribute list whose qualified name is qualifiedName, and null otherwise.

  4. If attribute is null, create an attribute whose local name is qualifiedName and value is value, append this attribute to the context object’s attribute list, and then terminate these steps.

  5. Change attribute from context object to value.

The setAttributeNS(namespace, qualifiedName, value) method, when invoked, must run these steps:

  1. Let namespace, prefix, and localName be the result of passing namespace and qualifiedName to validate and extract. Rethrow any exceptions.

  2. Set an attribute value for the context object using localName, value, and also prefix and namespace.

The removeAttribute(qualifiedName) method, when invoked, must remove an attribute given qualifiedName and the context object, and then return undefined.

The removeAttributeNS(namespace, localName) method must remove an attribute given namespace, localName, and the context object, and then return undefined.

The hasAttribute(qualifiedName) method, when invoked, must run these steps:

  1. If the context object is in the HTML namespace and its node document is an HTML document, let qualifiedName be converted to ASCII lowercase.

  2. Return true if the context object has an attribute whose qualified name is qualifiedName, and false otherwise.

The hasAttributeNS(namespace, localName) method, when invoked, must run these steps:

  1. If namespace is the empty string, set it to null.
  2. Return true if the context object has an attribute whose namespace is namespace and local name is localName, and false otherwise.

The getAttributeNode(qualifiedName) method, when invoked, must return the result of getting an attribute given qualifiedName and the context object.

The getAttributeNodeNS(namespace, localName) method, when invoked, must return the result of getting an attribute given namespace, localName, and the context object.

The setAttributeNode(attr) and setAttributeNodeNS(attr) methods, when invoked, must return the result of setting an attribute given attr and the context object. Rethrow any exceptions.

The removeAttributeNode(attr) method, when invoked, must run these steps:

  1. If attr is not in context object’s attribute list, then throw a NotFoundError.

  2. Remove attr from context object.

  3. Return attr.


var shadow = element . attachShadow(init)

Creates a shadow root for element and returns it.

var shadow = element . shadowRoot

Returns element’s shadow root, if any, and if shadow root’s mode is "open", and null otherwise.

The attachShadow(init) method, when invoked, must run these steps:

  1. If context object’s namespace is not the HTML namespace, then throw a NotSupportedError.

  2. If context object’s local name is not a valid custom element name, "article", "aside", "blockquote", "body", "div", "footer", "h1", "h2", "h3", "h4", "h5", "h6", "header", "nav", "p", "section", or "span", then throw a NotSupportedError.

  3. If context object is a shadow host, then throw an InvalidStateError.

  4. Let shadow be a new shadow root whose node document is context object’s node document, host is context object, and mode is init’s mode.

  5. Set context object’s shadow root to shadow.

  6. Return shadow.

The shadowRoot attribute’s getter must run these steps:

  1. Let shadow be context object’s shadow root.

  2. If shadow is null or its mode is "closed", then return null.

  3. Return shadow.


element . closest(selectors)
Returns the first (starting at element) inclusive ancestor that matches selectors, and null otherwise.
element . matches(selectors)
Returns true if matching selectors against element’s root yields element, and false otherwise.

The closest(selectors) method, when invoked, must run these steps:

  1. Let s be the result of parse a selector from selectors. [SELECTORS4]
  2. If s is failure, throw a SyntaxError.
  3. Let elements be context object’s inclusive ancestors that are elements, in reverse tree order.
  4. For each element in elements, if match a selector against an element, using s, element, and :scope element context object, returns success, return element. [SELECTORS4]
  5. Return null.

The matches(selectors) and webkitMatchesSelector(selectors) methods, when invoked, must run these steps:

  1. Let s be the result of parse a selector from selectors. [SELECTORS4]
  2. If s is failure, throw a SyntaxError.
  3. Return true if the result of match a selector against an element, using s, element, and :scope element context object, returns success, and false otherwise. [SELECTORS4]

The getElementsByTagName(qualifiedName) method, when invoked, must return the list of elements with qualified name qualifiedName for the context object.

The getElementsByTagNameNS(namespace, localName) method must return the list of elements with namespace namespace and local name localName for the context object.

The getElementsByClassName(classNames) method must return the list of elements with class names classNames for the context object.


To insert adjacent, given an element element, string where, and a node node, run the steps associated with the first ASCII case-insensitive match for where:

"beforebegin"

If element’s parent is null, return null.

Return the result of pre-inserting node into element’s parent before element. Rethrow any exceptions.

"afterbegin"

Return the result of pre-inserting node into element before element’s first child. Rethrow any exceptions.

"beforeend"

Return the result of pre-inserting node into element before null. Rethrow any exceptions.

"afterend"

If element’s parent is null, return null.

Return the result of pre-inserting node into element’s parent before element’s next sibling. Rethrow any exceptions.

Otherwise

Throw a SyntaxError.

The insertAdjacentElement(where, element) method, when invoked, must return the result of running insert adjacent, given context object, where, and element. Rethrow any exceptions.

The insertAdjacentText(where, data) method, when invoked, must run these steps:

  1. Let text be a new Text node whose data is data and node document is context object’s node document.

  2. Run insert adjacent, given context object, where, and text. Rethrow any exceptions.

This method returns nothing because it existed before we had a chance to design it.

4.9.1. Interface NamedNodeMap

[Exposed=Window, LegacyUnenumerableNamedProperties]
interface NamedNodeMap {
  readonly attribute unsigned long length;
  getter Attr? item(unsigned long index);
  getter Attr? getNamedItem(DOMString qualifiedName);
  Attr? getNamedItemNS(DOMString? namespace, DOMString localName);
  [CEReactions] Attr? setNamedItem(Attr attr);
  [CEReactions] Attr? setNamedItemNS(Attr attr);
  [CEReactions] Attr removeNamedItem(DOMString qualifiedName);
  [CEReactions] Attr removeNamedItemNS(DOMString? namespace, DOMString localName);
};

A NamedNodeMap has an associated element (an element).

A NamedNodeMap object’s attribute list is its element’s attribute list.


A NamedNodeMap object’s supported property indices are the numbers in the range zero to the number of attributes in its attribute list map minus one, unless the attribute list is empty, in which case there are no supported property indices.

The length attribute’s getter must return the number of attributes in the attribute list.

The item(index) method, when invoked, must run these steps:

  1. If index is equal to or greater than the number of attributes in the attribute list, return null.

  2. Otherwise, return the indexth attribute in the attribute list.

A NamedNodeMap object’s supported property names are the return value of running these steps:

  1. Let names be the qualified names of the attributes in this NamedNodeMap object’s attribute list, with duplicates omitted, in order.

  2. If this NamedNodeMap object’s element is in the HTML namespace and its node document is an HTML document, then for each name in names, run these substeps:

    1. Let lowercaseName be name, converted to ASCII lowercase.

    2. If lowercaseName is not equal to name, remove name from names.

  3. Return names.

The getNamedItem(qualifiedName) method, when invoked, must return the result of getting an attribute given qualifiedName and element.

The getNamedItemNS(namespace, localName) method, when invoked, must return the result of getting an attribute given namespace, localName, and element.

The setNamedItem(attr) and setNamedItemNS(attr) methods, when invoked, must return the result of setting an attribute given attr and element. Rethrow any exceptions.

The removeNamedItem(qualifiedName) method, when invoked, must run these steps:

  1. Let attr be the result of removing an attribute given qualifiedName and element.

  2. If attr is null, then throw a NotFoundError.

  3. Return attr.

The removeNamedItemNS(namespace, localName) method, when invoked, must run these steps:

  1. Let attr be the result of removing an attribute given namespace, localName, and element.

  2. If attr is null, then throw a NotFoundError.

  3. Return attr.

4.9.2. Interface Attr

[Exposed=Window]
interface Attr {
  readonly attribute DOMString? namespaceURI;
  readonly attribute DOMString? prefix;
  readonly attribute DOMString localName;
  readonly attribute DOMString name;
  readonly attribute DOMString nodeName; // historical alias of .name
  [CEReactions] attribute DOMString value;
  [CEReactions, TreatNullAs=EmptyString] attribute DOMString nodeValue; // historical alias of .value
  [CEReactions, TreatNullAs=EmptyString] attribute DOMString textContent; // historical alias of .value

  readonly attribute Element? ownerElement;

  readonly attribute boolean specified; // useless; always returns true
};

Attr objects are simply known as attributes. They are sometimes referred to as content attributes to avoid confusion with IDL attributes.

Attributes have a namespace (null or a non-empty string), namespace prefix (null or a non-empty string), local name (a non-empty string), value (a string), and element (null or an element).

If designed today they would just have a name and value. ☹

An attribute’s qualified name is its local name if its namespace prefix is null, and its namespace prefix, followed by ":", followed by its local name, otherwise.

User agents could have this as an internal slot as an optimization, but are not required to do so. The standard has this concept for readability.

When an attribute is created, its local name is given. Unless explicitly given when an attribute is created, its namespace, namespace prefix, and element are set to null, and its value is set to the empty string.

An A attribute is an attribute whose local name is A and whose namespace and namespace prefix are null.


The namespaceURI attribute’s getter must return the namespace.

The prefix attribute’s getter must return the namespace prefix.

The localName attribute’s getter must return the local name.

The name attribute’s getter, and nodeName attribute’s getter, must return the qualified name.

The value attribute’s getter, nodeValue attribute’s getter, and textContent attribute’s getter, must return the value.

The value attribute’s setter, nodeValue attribute’s setter, and textContent attribute’s setter, must run these steps:

  1. If context object’s element is null, set context object’s value to the given value.
  2. Otherwise, change the context object from context object’s element to the given value.

Unlike node’s textContent, no special null handling is required.


The ownerElement attribute’s getter must return context object’s element.


The specified attribute’s getter must return true.

4.10. Interface CharacterData

[Exposed=Window]
interface CharacterData : Node {
  [TreatNullAs=EmptyString] attribute DOMString data;
  readonly attribute unsigned long length;
  DOMString substringData(unsigned long offset, unsigned long count);
  void appendData(DOMString data);
  void insertData(unsigned long offset, DOMString data);
  void deleteData(unsigned long offset, unsigned long count);
  void replaceData(unsigned long offset, unsigned long count, DOMString data);
};

CharacterData is an abstract interface and does not exist as node. It is used by Text, ProcessingInstruction, and Comment nodes.

Each node inheriting from the CharacterData interface has an associated mutable string called data.

To replace data of node node with offset offset, count count, and data data, run these steps:

  1. Let length be node’s length attribute value.
  2. If offset is greater than length, then throw an IndexSizeError.
  3. If offset plus count is greater than length let count be length minus offset.
  4. Queue a mutation record of "characterData" for node with oldValue node’s data.
  5. Insert data into node’s data after offset code units.
  6. Let delete offset be offset plus the number of code units in data.
  7. Starting from delete offset code units, remove count code units from node’s data.
  8. For each range whose start node is node and start offset is greater than offset but less than or equal to offset plus count, set its start offset to offset.
  9. For each range whose end node is node and end offset is greater than offset but less than or equal to offset plus count, set its end offset to offset.
  10. For each range whose start node is node and start offset is greater than offset plus count, increase its start offset by the number of code units in data, then decrease it by count.
  11. For each range whose end node is node and end offset is greater than offset plus count, increase its end offset by the number of code units in data, then decrease it by count.

To substring data with node node, offset offset, and count count, run these steps:

  1. Let length be node’s length attribute value.
  2. If offset is greater than length, then throw an IndexSizeError.
  3. If offset plus count is greater than length, return a string whose value is the code units from the offsetth code unit to the end of node’s data, and then terminate these steps.
  4. Return a string whose value is the code units from the offsetth code unit to the offset+countth code unit in node’s data.

The data attribute’s getter must return context object’s data. Its setter must replace data with node context object offset 0, count length attribute value, and data new value.

The length attribute’s getter must return the number of code units in context object’s data.

The substringData(offset, count) method, when invoked, must return the result of running substring data with node context object, offset offset, and count count.

The appendData(data) method, when invoked, must replace data with node context object, offset length attribute value, count 0, and data data.

The insertData(offset, data) method, when invoked, must replace data with node context object, offset offset, count 0, and data data.

The deleteData(offset, count) method, when invoked, must replace data with node context object, offset offset, count count, and data the empty string.

The replaceData(offset, count, data) method, when invoked, must replace data with node context object, offset offset, count count, and data data.

4.11. Interface Text

[Constructor(optional DOMString data = ""),
 Exposed=Window]
interface Text : CharacterData {
  [NewObject] Text splitText(unsigned long offset);
  readonly attribute DOMString wholeText;
};
text = new Text([data = ""])
Returns a new Text node whose data is data.
text . splitText(offset)
Splits data at the given offset and returns the remainder as Text node.
text . wholeText
Returns the combined data of all direct Text node siblings.

The Text(data) constructor must return a new Text node whose data is data and node document is the global object’s associated document.

To split a Text node node with offset offset, run these steps:

  1. Let length be node’s length attribute value.
  2. If offset is greater than length, then throw an IndexSizeError.
  3. Let count be length minus offset.
  4. Let new data be the result of substringing data with node node, offset offset, and count count.
  5. Let new node be a new Text node, with the same node document as node. Set new node’s data to new data.
  6. Let parent be node’s parent.
  7. If parent is not null, run these substeps:
    1. Insert new node into parent before node’s next sibling.
    2. For each range whose start node is node and start offset is greater than offset, set its start node to new node and decrease its start offset by offset.
    3. For each range whose end node is node and end offset is greater than offset, set its end node to new node and decrease its end offset by offset.
    4. For each range whose start node is parent and start offset is equal to the index of node + 1, increase its start offset by one.
    5. For each range whose end node is parent and end offset is equal to the index of node + 1, increase its end offset by one.
  8. Replace data with node node, offset offset, count count, and data the empty string.
  9. If parent is null, run these substeps:
    1. For each range whose start node is node and start offset is greater than offset, set its start offset to offset.
    2. For each range whose end node is node and end offset is greater than offset, set its end offset to offset.
  10. Return new node.

The splitText(offset) method must split the context object with offset offset.

The contiguous Text nodes of a node are the node itself, the previous sibling Text node (if any) and its contiguous Text nodes, and the next sibling Text node (if any) and its contiguous Text nodes, avoiding any duplicates.

The wholeText attribute must return a concatenation of the data of the contiguous Text nodes of the context object, in tree order.

4.12. Interface ProcessingInstruction

[Exposed=Window]
interface ProcessingInstruction : CharacterData {
  readonly attribute DOMString target;
};

ProcessingInstruction nodes have an associated target.

The target attribute must return the target.

4.13. Interface Comment

[Constructor(optional DOMString data = ""),
 Exposed=Window]
interface Comment : CharacterData {
};
comment = new Comment([data = ""])
Returns a new Comment node whose data is data.

The Comment(data) constructor must return a new Comment node whose data is data and node document is the global object’s associated document.

5. Ranges

5.1. Introduction to "DOM Ranges"

A Range object (range) represents a sequence of content within a node tree. Each range has a start and an end which are boundary points. A boundary point is a tuple consisting of a node and a non-negative numeric offset. So in other words, a range represents a piece of content within a node tree between two boundary points.

Ranges are frequently used in editing for selecting and copying content.

In the node tree above, a range can be used to represent the sequence “syndata is awes”. Assuming p is assigned to the p element, and em to the em element, this would be done as follows:

var range = new Range(),
    firstText = p.childNodes[1],
    secondText = em.firstChild
range.setStart(firstText, 9) // do not forget the leading space
range.setEnd(secondText, 4)
// range now stringifies to the aforementioned quote

Attributes such as src and alt in the node tree above cannot be represented by a range. The ranges concept is only useful for nodes.

Ranges are affected by mutations to the node tree. Such mutations will not invalidate a range and will try to ensure that the range still represents the same piece of content. Necessarily, a range might itself be modified as part of the mutation to the node tree when e.g. part of the content it represents is mutated.

See the insert and remove algorithms, the normalize() method, and the replace data and split algorithms for the hairy details.

5.2. Interface Range

[Constructor,
 Exposed=Window]
interface Range {
  readonly attribute Node startContainer;
  readonly attribute unsigned long startOffset;
  readonly attribute Node endContainer;
  readonly attribute unsigned long endOffset;
  readonly attribute boolean collapsed;
  readonly attribute Node commonAncestorContainer;

  void setStart(Node node, unsigned long offset);
  void setEnd(Node node, unsigned long offset);
  void setStartBefore(Node node);
  void setStartAfter(Node node);
  void setEndBefore(Node node);
  void setEndAfter(Node node);
  void collapse(optional boolean toStart = false);
  void selectNode(Node node);
  void selectNodeContents(Node node);

  const unsigned short START_TO_START = 0;
  const unsigned short START_TO_END = 1;
  const unsigned short END_TO_END = 2;
  const unsigned short END_TO_START = 3;
  short compareBoundaryPoints(unsigned short how, Range sourceRange);

  [CEReactions] void deleteContents();
  [CEReactions, NewObject] DocumentFragment extractContents();
  [CEReactions, NewObject] DocumentFragment cloneContents();
  [CEReactions] void insertNode(Node node);
  [CEReactions] void surroundContents(Node newParent);

  [NewObject] Range cloneRange();
  void detach();

  boolean isPointInRange(Node node, unsigned long offset);
  short comparePoint(Node node, unsigned long offset);

  boolean intersectsNode(Node node);

  stringifier;
};

Range objects are simply known as ranges.

A boundary point is a (node, offset) tuple, where offset is a non-negative integer.

Generally speaking, a boundary point’s offset will be between zero and the boundary point’s node length, inclusive. Algorithms that modify a tree (in particular the insert, remove, replace data, and split algorithms) also modify ranges associated with that tree.

If the two nodes of boundary points (node A, offset A) and (node B, offset B) have the same root, the position of the first relative to the second is either before, equal, or after, as returned by the following algorithm:

  1. If node A is the same as node B, return equal if offset A is the same as offset B, before if offset A is less than offset B, and after if offset A is greater than offset B.
  2. If node A is following node B, compute the position of (node B, offset B) relative to (node A, offset A). If it is before, return after. If it is after, return before.
  3. If node A is an ancestor of node B:
    1. Let child equal node B.
    2. While child is not a child of node A, set child to its parent.
    3. If the index of child is less than offset A, return after.
  4. Return before.

Each range has two associated boundary points — a start and end.

For convenience, start node is start’s node, start offset is start’s offset, end node is end’s node, and end offset is end’s offset.

The root of a range is the root of its start node.

A node node is contained in a range range if node’s root is the same as range’s root, and (node, 0) is after range’s start, and (node, length of node) is before range’s end.

A node is partially contained in a range if it is an inclusive ancestor of the range’s start node but not its end node, or vice versa.

Some facts to better understand these definitions:

range = new Range()
Returns a new range.

The Range() constructor must return a new range with (global object’s associated document, 0) as its start and end.


node = range . startContainer
Returns range’s start node.
offset = range . startOffset
Returns range’s start offset.
node = range . endContainer
Returns range’s end node.
offset = range . endOffset
Returns range’s end offset.
collapsed = range . collapsed
Returns true if range’s start and end are the same, and false otherwise.
container = range . commonAncestorContainer
Returns the node, furthest away from the document, that is an ancestor of both range’s start node and end node.

The startContainer attribute must return the start node.

The startOffset attribute must return the start offset.

The endContainer attribute must return the end node.

The endOffset attribute must return the end offset.

The collapsed attribute must return true if start is the same as end, and false otherwise.

The commonAncestorContainer attribute must run these steps:

  1. Let container be start node.
  2. While container is not an inclusive ancestor of end node, let container be container’s parent.
  3. Return container.

To set the start or end of a range to a boundary point (node, offset), run these steps:

  1. If node is a doctype, then throw an InvalidNodeTypeError.
  2. If offset is greater than node’s length, then throw an IndexSizeError.
  3. Let bp be the boundary point (node, offset).
  4. If these steps were invoked as "set the start"
    1. If bp is after the range’s end, or if range’s root is not equal to node’s root, set range’s end to bp.
    2. Set range’s start to bp.
    If these steps were invoked as "set the end"
    1. If bp is before the range’s start, or if range’s root is not equal to node’s root, set range’s start to bp.
    2. Set range’s end to bp.

The setStart(node, offset) method must set the start of the context object to boundary point (node, offset).

The setEnd(node, offset) method must set the end of the context object to boundary point (node, offset).

The setStartBefore(node) method must run these steps:

  1. Let parent be node’s parent.
  2. If parent is null, then throw an InvalidNodeTypeError.
  3. Set the start of the context object to boundary point (parent, node’s index).

The setStartAfter(node) method must run these steps:

  1. Let parent be node’s parent.
  2. If parent is null, then throw an InvalidNodeTypeError.
  3. Set the start of the context object to boundary point (parent, node’s index plus one).

The setEndBefore(node) method must run these steps:

  1. Let parent be node’s parent.
  2. If parent is null, then throw an InvalidNodeTypeError.
  3. Set the end of the context object to boundary point (parent, node’s index).

The setEndAfter(node) method must run these steps:

  1. Let parent be node’s parent.
  2. If parent is null, then throw an InvalidNodeTypeError.
  3. Set the end of the context object to boundary point (parent, node’s index plus one).

The collapse(toStart) method, when invoked, must if toStart is true, set end to start, and set start to end otherwise.

To select a node node within a range range, run these steps:

  1. Let parent be node’s parent.
  2. If parent is null, throw an InvalidNodeTypeError.
  3. Let index be node’s index.
  4. Set range’s start to boundary point (parent, index).
  5. Set range’s end to boundary point (parent, index plus one).

The selectNode(node) method must select node within context object.

The selectNodeContents(node) method must run these steps:

  1. If node is a doctype, throw an InvalidNodeTypeError.
  2. Let length be the length of node.
  3. Set start to the boundary point (node, 0).
  4. Set end to the boundary point (node, length).

The compareBoundaryPoints(how, sourceRange) method must run these steps:

  1. If how is not one of

    then throw a NotSupportedError.

  2. If context object’s root is not the same as sourceRange’s root, then throw a WrongDocumentError.
  3. If how is:
    START_TO_START:
    Let this point be the context object’s start. Let other point be sourceRange’s start.
    START_TO_END:
    Let this point be the context object’s end. Let other point be sourceRange’s start.
    END_TO_END:
    Let this point be the context object’s end. Let other point be sourceRange’s end.
    END_TO_START:
    Let this point be the context object’s start. Let other point be sourceRange’s end.
  4. If the position of this point relative to other point is
    before
    Return −1.
    equal
    Return 0.
    after
    Return 1.

The deleteContents() method, when invoked, must run these steps:

  1. If start is end, terminate these steps.
  2. Let original start node, original start offset, original end node, and original end offset be the context object’s start node, start offset, end node, and end offset, respectively.
  3. If original start node and original end node are the same, and they are a Text, ProcessingInstruction, or Comment node, replace data with node original start node, offset original start offset, count original end offset minus original start offset, and data the empty string, and then terminate these steps.
  4. Let nodes to remove be a list of all the nodes that are contained in the context object, in tree order, omitting any node whose parent is also contained in the context object.
  5. If original start node is an inclusive ancestor of original end node, set new node to original start node and new offset to original start offset.
  6. Otherwise:
    1. Let reference node equal original start node.
    2. While reference node’s parent is not null and is not an inclusive ancestor of original end node, set reference node to its parent.
    3. Set new node to the parent of reference node, and new offset to one plus the index of reference node.

      If reference node’s parent were null, it would be the root of the context object, so would be an inclusive ancestor of original end node, and we could not reach this point.

  7. If original start node is a Text, ProcessingInstruction, or Comment node, replace data with node original start node, offset original start offset, count original start node’s length minus original start offset, data the empty string.
  8. For each node in nodes to remove, in tree order, remove node from its parent.
  9. If original end node is a Text, ProcessingInstruction, or Comment node, replace data with node original end node, offset 0, count original end offset and data the empty string.
  10. Set start and end to (new node, new offset).

To extract a range range, run these steps:

  1. Let fragment be a new DocumentFragment node whose node document is range’s start node’s node document.
  2. If range’s start is its end, return fragment.
  3. Let original start node, original start offset, original end node, and original end offset be range’s start node, start offset, end node, and end offset, respectively.
  4. If original start node is original end node, and they are a Text, ProcessingInstruction, or Comment node:
    1. Let clone be a clone of original start node.
    2. Set the data of clone to the result of substringing data with node original start node, offset original start offset, and count original end offset minus original start offset.
    3. Append clone to fragment.
    4. Replace data with node original start node, offset original start offset, count original end offset minus original start offset, and data the empty string.
    5. Return fragment.
  5. Let common ancestor be original start node.
  6. While common ancestor is not an inclusive ancestor of original end node, set common ancestor to its own parent.
  7. Let first partially contained child be null.
  8. If original start node is not an inclusive ancestor of original end node, set first partially contained child to the first child of common ancestor that is partially contained in range.
  9. Let last partially contained child be null.
  10. If original end node is not an inclusive ancestor of original start node, set last partially contained child to the last child of common ancestor that is partially contained in range.

    These variable assignments do actually always make sense. For instance, if original start node is not an inclusive ancestor of original end node, original start node is itself partially contained in range, and so are all its ancestors up until a child of common ancestor. common ancestor cannot be original start node, because it has to be an inclusive ancestor of original end node. The other case is similar. Also, notice that the two children will never be equal if both are defined.

  11. Let contained children be a list of all children of common ancestor that are contained in range, in tree order.
  12. If any member of contained children is a doctype, then throw a HierarchyRequestError.

    We do not have to worry about the first or last partially contained node, because a doctype can never be partially contained. It cannot be a boundary point of a range, and it cannot be the ancestor of anything.

  13. If original start node is an inclusive ancestor of original end node, set new node to original start node and new offset to original start offset.
  14. Otherwise:
    1. Let reference node equal original start node.
    2. While reference node’s parent is not null and is not an inclusive ancestor of original end node, set reference node to its parent.
    3. Set new node to the parent of reference node, and new offset to one plus reference node’s index.

      If reference node’s parent is null, it would be the root of range, so would be an inclusive ancestor of original end node, and we could not reach this point.

  15. If first partially contained child is a Text, ProcessingInstruction, or Comment node:

    In this case, first partially contained child is original start node.

    1. Let clone be a clone of original start node.
    2. Set the data of clone to the result of substringing data with node original start node, offset original start offset, and count original start node’s length minus original start offset.
    3. Append clone to fragment.
    4. Replace data with node original start node, offset original start offset, count original start node’s length minus original start offset, and data the empty string.
  16. Otherwise, if first partially contained child is not null:
    1. Let clone be a clone of first partially contained child.
    2. Append clone to fragment.
    3. Let subrange be a new range whose start is (original start node, original start offset) and whose end is (first partially contained child, first partially contained child’s length).
    4. Let subfragment be the result of extracting subrange.
    5. Append subfragment to clone.
  17. For each contained child in contained children, append contained child to fragment.
  18. If last partially contained child is a Text, ProcessingInstruction, or Comment node:

    In this case, last partially contained child is original end node.

    1. Let clone be a clone of original end node.
    2. Set the data of clone to the result of substringing data with node original end node, offset 0, and count original end offset.
    3. Append clone to fragment.
    4. Replace data with node original end node, offset 0, count original end offset, and data the empty string.
  19. Otherwise, if last partially contained child is not null:
    1. Let clone be a clone of last partially contained child.
    2. Append clone to fragment.
    3. Let subrange be a new range whose start is (last partially contained child, 0) and whose end is (original end node, original end offset).
    4. Let subfragment be the result of extracting subrange.
    5. Append subfragment to clone.
  20. Set range’s start and end to (new node, new offset).
  21. Return fragment.

The extractContents() method must return the result of extracting context object.

To clone the contents of a range range, run these steps:

  1. Let fragment be a new DocumentFragment node whose node document is range’s start node’s node document.
  2. If range’s start is its end, return fragment.
  3. Let original start node, original start offset, original end node, and original end offset be range’s start node, start offset, end node, and end offset, respectively.
  4. If original start node is original end node, and they are a Text, ProcessingInstruction, or Comment node:
    1. Let clone be a clone of original start node.
    2. Set the data of clone to the result of substringing data with node original start node, offset original start offset, and count original end offset minus original start offset.
    3. Append clone to fragment.
    4. Return fragment.
  5. Let common ancestor be original start node.
  6. While common ancestor is not an inclusive ancestor of original end node, set common ancestor to its own parent.
  7. Let first partially contained child be null.
  8. If original start node is not an inclusive ancestor of original end node, set first partially contained child to the first child of common ancestor that is partially contained in range.
  9. Let last partially contained child be null.
  10. If original end node is not an inclusive ancestor of original start node, set last partially contained child to the last child of common ancestor that is partially contained in range.

    These variable assignments do actually always make sense. For instance, if original start node is not an inclusive ancestor of original end node, original start node is itself partially contained in range, and so are all its ancestors up until a child of common ancestor. common ancestor cannot be original start node, because it has to be an inclusive ancestor of original end node. The other case is similar. Also, notice that the two children will never be equal if both are defined.

  11. Let contained children be a list of all children of common ancestor that are contained in range, in tree order.
  12. If any member of contained children is a doctype, then throw a HierarchyRequestError.

    We do not have to worry about the first or last partially contained node, because a doctype can never be partially contained. It cannot be a boundary point of a range, and it cannot be the ancestor of anything.

  13. If first partially contained child is a Text, ProcessingInstruction, or Comment node:

    In this case, first partially contained child is original start node.

    1. Let clone be a clone of original start node.
    2. Set the data of clone to the result of substringing data with node original start node, offset original start offset, and count original start node’s length minus original start offset.
    3. Append clone to fragment.
  14. Otherwise, if first partially contained child is not null:
    1. Let clone be a clone of first partially contained child.
    2. Append clone to fragment.
    3. Let subrange be a new range whose start is (original start node, original start offset) and whose end is (first partially contained child, first partially contained child’s length).
    4. Let subfragment be the result of cloning the contents of subrange.
    5. Append subfragment to clone.
  15. For each contained child in contained children:
    1. Let clone be a clone of contained child with the clone children flag set.
    2. Append clone to fragment.
  16. If last partially contained child is a Text, ProcessingInstruction, or Comment node:

    In this case, last partially contained child is original end node.

    1. Let clone be a clone of original end node.
    2. Set the data of clone to the result of substringing data with node original end node, offset 0, and count original end offset.
    3. Append clone to fragment.
  17. Otherwise, if last partially contained child is not null:
    1. Let clone be a clone of last partially contained child.
    2. Append clone to fragment.
    3. Let subrange be a new range whose start is (last partially contained child, 0) and whose end is (original end node, original end offset).
    4. Let subfragment be the result of cloning the contents of subrange.
    5. Append subfragment to clone.
  18. Return fragment.

The cloneContents() method must return the result of cloning the contents of context object.

To insert a node node into a range range, run these steps:

  1. If range’s start node is a ProcessingInstruction or Comment node, is a Text node whose parent is null, or is node, then throw a HierarchyRequestError.
  2. Let referenceNode be null.
  3. If range’s start node is a Text node, set referenceNode to that Text node.
  4. Otherwise, set referenceNode to the child of start node whose index is start offset, and null if there is no such child.
  5. Let parent be range’s start node if referenceNode is null, and referenceNode’s parent otherwise.
  6. Ensure pre-insertion validity of node into parent before referenceNode.
  7. If range’s start node is a Text node, set referenceNode to the result of splitting it with offset range’s start offset.
  8. If node is referenceNode, set referenceNode to its next sibling.
  9. If node’s parent is not null, remove node from its parent.
  10. Let newOffset be parent’s length if referenceNode is null, and referenceNode’s index otherwise.
  11. Increase newOffset by node’s length if node is a DocumentFragment node, and one otherwise.
  12. Pre-insert node into parent before referenceNode.
  13. If range’s start and end are the same, set range’s end to (parent, newOffset).

The insertNode(node) method must insert node into context object.

The surroundContents(newParent) method must run these steps:

  1. If a non-Text node is partially contained in the context object, then throw an InvalidStateError.
  2. If newParent is a Document, DocumentType, or DocumentFragment node, then throw an InvalidNodeTypeError.
  3. Let fragment be the result of extracting context object.
  4. If newParent has children, replace all with null within newParent.
  5. Insert newParent into context object.
  6. Append fragment to newParent.
  7. Select newParent within context object.

The cloneRange() method must return a new range with the same start and end as the context object.

The detach() method must do nothing. Its functionality (disabling a Range object) was removed, but the method itself is preserved for compatibility.


position = range . comparePoint(node, offset)
Returns −1 if the point is before the range, 0 if the point is in the range, and 1 if the point is after the range.
intersects = range . intersectsNode(node)
Returns whether range intersects node.

The isPointInRange(node, offset) must run these steps:

  1. If node’s root is different from the context object’s root, return false.
  2. If node is a doctype, then throw an InvalidNodeTypeError.
  3. If offset is greater than node’s length, then throw an IndexSizeError.
  4. If (node, offset) is before start or after end, return false.
  5. Return true.

The comparePoint(node, offset) method must run these steps:

  1. If node’s root is different from the context object’s root, then throw a WrongDocumentError.
  2. If node is a doctype, then throw an InvalidNodeTypeError.
  3. If offset is greater than node’s length, then throw an IndexSizeError.
  4. If (node, offset) is before start, return −1.
  5. If (node, offset) is after end, return 1.
  6. Return 0.

The intersectsNode(node) method must run these steps:

  1. If node’s root is different from the context object’s root, return false.
  2. Let parent be node’s parent.
  3. If parent is null, return true.
  4. Let offset be node’s index.
  5. If (parent, offset) is before end and (parent, offset + 1) is after start, return true.
  6. Return false.

The stringification behavior must run these steps:

  1. Let s be the empty string.
  2. If start node is end node, and it is a Text node, return the substring of that Text node’s data beginning at start offset and ending at end offset.
  3. If start node is a Text node, append to s the substring of that node’s data from the start offset until the end.
  4. Append to s the concatenation, in tree order, of the data of all Text nodes that are contained in the context object.
  5. If end node is a Text node, append to s the substring of that node’s data from its start until the end offset.
  6. Return s.

The createContextualFragment(), getClientRects(), and getBoundingClientRect() methods are defined in other specifications. [DOM-Parsing] [CSSOM-VIEW]

6. Traversal

NodeIterator and TreeWalker objects can be used to filter and traverse node trees.

Each NodeIterator and TreeWalker object also has an associated root node, whatToShow bitmask, and filter callback.

To filter node run these steps:

  1. Let n be node’s nodeType attribute value minus 1.
  2. If the nth bit (where 0 is the least significant bit) of whatToShow is not set, return FILTER_SKIP.
  3. If filter is null, return FILTER_ACCEPT.
  4. Let result be the return value of calling filter’s acceptNode() with node as argument. Rethrow any exceptions.
  5. Return result.

6.1. Interface NodeIterator

[Exposed=Window]
interface NodeIterator {
  [SameObject] readonly attribute Node root;
  readonly attribute Node referenceNode;
  readonly attribute boolean pointerBeforeReferenceNode;
  readonly attribute unsigned long whatToShow;
  readonly attribute NodeFilter? filter;

  Node? nextNode();
  Node? previousNode();

  void detach();
};

NodeIterator objects can be created using the createNodeIterator() method.

Each NodeIterator object has an associated iterator collection, which is a collection rooted at root, whose filter matches any node.

As mentioned earlier, NodeIterator objects have an associated root node, whatToShow bitmask, and filter callback as well.

The NodeIterator pre-removing steps given a nodeIterator and toBeRemovedNode, are as follows:

  1. If toBeRemovedNode is not an inclusive ancestor of the referenceNode attribute value, terminate these steps.

  2. If the pointerBeforeReferenceNode attribute value is true, run these substeps:

    1. Let next be toBeRemovedNode’s first following node that is an inclusive descendant of nodeIterator’s root and is not an inclusive descendant of toBeRemovedNode, and null if there is no such node.

    2. If next is non-null, set nodeIterator’s referenceNode attribute to next and terminate these steps.

    3. Otherwise, set nodeIterator’s pointerBeforeReferenceNode attribute to false.

      Steps are not terminated here.

  3. Set nodeIterator’s referenceNode attribute to toBeRemovedNode’s parent, if toBeRemovedNode’s previous sibling is null, and to the inclusive descendant of toBeRemovedNode’s previous sibling that appears last in tree order otherwise.


The root attribute must return root.

The referenceNode and pointerBeforeReferenceNode attributes must return what they were initialized to.

The whatToShow attribute must return whatToShow.

The filter attribute must return filter.

To traverse in direction direction run these steps:

  1. Let node be the value of the referenceNode attribute.
  2. Let before node be the value of the pointerBeforeReferenceNode attribute.
  3. Run these substeps:
    1. If direction is next
      If before node is false, let node be the first node following node in the iterator collection. If there is no such node return null. If before node is true, set it to false.
      If direction is previous
      If before node is true, let node be the first node preceding node in the iterator collection. If there is no such node return null. If before node is false, set it to true.
    2. Filter node and let result be the return value.
    3. If result is FILTER_ACCEPT, go to the next step in the overall set of steps. Otherwise, run these substeps again.
  4. Set the referenceNode attribute to node, set the pointerBeforeReferenceNode attribute to before node, and return node.

The nextNode() method must traverse in direction next.

The previousNode() method must traverse in direction previous.

The detach() method must do nothing. Its functionality (disabling a NodeIterator object) was removed, but the method itself is preserved for compatibility.

6.2. Interface TreeWalker

[Exposed=Window]
interface TreeWalker {
  [SameObject] readonly attribute Node root;
  readonly attribute unsigned long whatToShow;
  readonly attribute NodeFilter? filter;
           attribute Node currentNode;

  Node? parentNode();
  Node? firstChild();
  Node? lastChild();
  Node? previousSibling();
  Node? nextSibling();
  Node? previousNode();
  Node? nextNode();
};

TreeWalker objects can be created using the createTreeWalker() method.

As mentioned earlier TreeWalker objects have an associated root node, whatToShow bitmask, and filter callback.

The root attribute must return root.

The whatToShow attribute must return whatToShow.

The filter attribute must return filter.

The currentNode attribute must return what it was initialized to.

Setting the currentNode attribute must set it to the new value.

The parentNode() method must run these steps:

  1. Let node be the value of the currentNode attribute.
  2. While node is not null and is not root, run these substeps:
    1. Let node be node’s parent.
    2. If node is not null and filtering node returns FILTER_ACCEPT, then set the currentNode attribute to node, return node.
  3. Return null.

To traverse children of type type, run these steps:

  1. Let node be the value of the currentNode attribute.
  2. Set node to node’s first child if type is first, and node’s last child if type is last.
  3. If node is null, return null.
  4. Main: Repeat these substeps:
    1. Filter node and let result be the return value.
    2. If result is FILTER_ACCEPT, then set the currentNode attribute to node and return node.
    3. If result is FILTER_SKIP, run these subsubsteps:
      1. Let child be node’s first child if type is first, and node’s last child if type is last.
      2. If child is not null, set node to child and goto Main.
    4. Repeat these subsubsteps:
      1. Let sibling be node’s next sibling if type is first, and node’s previous sibling if type is last.
      2. If sibling is not null, set node to sibling and goto Main.
      3. Let parent be node’s parent.
      4. If parent is null, parent is root, or parent is currentNode attribute’s value, return null.
      5. Otherwise, set node to parent.

The firstChild() method must traverse children of type first.

The lastChild() method must traverse children of type last.

To traverse siblings of type type run these steps:

  1. Let node be the value of the currentNode attribute.
  2. If node is root, return null.
  3. Run these substeps:
    1. Let sibling be node’s next sibling if type is next, and node’s previous sibling if type is previous.
    2. While sibling is not null, run these subsubsteps:
      1. Set node to sibling.
      2. Filter node and let result be the return value.
      3. If result is FILTER_ACCEPT, then set the currentNode attribute to node and return node.
      4. Set sibling to node’s first child if type is next, and node’s last child if type is previous.
      5. If result is FILTER_REJECT or sibling is null, then set sibling to node’s next sibling if type is next, and node’s previous sibling if type is previous.
    3. Set node to its parent.
    4. If node is null or is root, return null.
    5. Filter node and if the return value is FILTER_ACCEPT, then return null.
    6. Run these substeps again.

The nextSibling() method must traverse siblings of type next.

The previousSibling() method must traverse siblings of type previous.

The previousNode() method must run these steps:

  1. Let node be the value of the currentNode attribute.
  2. While node is not root, run these substeps:
    1. Let sibling be the previous sibling of node.
    2. While sibling is not null, run these subsubsteps:
      1. Set node to sibling.
      2. Filter node and let result be the return value.
      3. While result is not FILTER_REJECT and node has a child, set node to its last child and then filter node and set result to the return value.
      4. If result is FILTER_ACCEPT, then set the currentNode attribute to node and return node.
      5. Set sibling to the previous sibling of node.
    3. If node is root or node’s parent is null, return null.
    4. Set node to its parent.
    5. Filter node and if the return value is FILTER_ACCEPT, then set the currentNode attribute to node and return node.
  3. Return null.

The nextNode() method must run these steps:

  1. Let node be the value of the currentNode attribute.
  2. Let result be FILTER_ACCEPT.
  3. Run these substeps:
    1. While result is not FILTER_REJECT and node has a child, run these subsubsteps:
      1. Set node to its first child.
      2. Filter node and set result to the return value.
      3. If result is FILTER_ACCEPT, then set the currentNode attribute to node and return node.
    2. If a node is following node and is not following root, set node to the first such node. Otherwise, return null.
    3. Filter node and set result to the return value.
    4. If result is FILTER_ACCEPT, then set the currentNode attribute to node and return node.
    5. Run these substeps again.

6.3. Interface NodeFilter

[Exposed=Window]
callback interface NodeFilter {
  // Constants for acceptNode()
  const unsigned short FILTER_ACCEPT = 1;
  const unsigned short FILTER_REJECT = 2;
  const unsigned short FILTER_SKIP = 3;

  // Constants for whatToShow
  const unsigned long SHOW_ALL = 0xFFFFFFFF;
  const unsigned long SHOW_ELEMENT = 0x1;
  const unsigned long SHOW_ATTRIBUTE = 0x2; // historical
  const unsigned long SHOW_TEXT = 0x4;
  const unsigned long SHOW_CDATA_SECTION = 0x8; // historical
  const unsigned long SHOW_ENTITY_REFERENCE = 0x10; // historical
  const unsigned long SHOW_ENTITY = 0x20; // historical
  const unsigned long SHOW_PROCESSING_INSTRUCTION = 0x40;
  const unsigned long SHOW_COMMENT = 0x80;
  const unsigned long SHOW_DOCUMENT = 0x100;
  const unsigned long SHOW_DOCUMENT_TYPE = 0x200;
  const unsigned long SHOW_DOCUMENT_FRAGMENT = 0x400;
  const unsigned long SHOW_NOTATION = 0x800; // historical

  unsigned short acceptNode(Node node);
};

NodeFilter objects can be used as filter callback and provide constants for the whatToShow bitmask.

It is typically implemented as a JavaScript function.

These constants can be used as callback return value:

These constants can be used for the whatToShow bitmask:

7. Sets

Yes, the name DOMTokenList is an unfortunate legacy mishap.

7.1. Interface DOMTokenList

interface DOMTokenList {
  readonly attribute unsigned long length;
  getter DOMString? item(unsigned long index);
  boolean contains(DOMString token);
  [CEReactions] void add(DOMString... tokens);
  [CEReactions] void remove(DOMString... tokens);
  [CEReactions] boolean toggle(DOMString token, optional boolean force);
  [CEReactions] void replace(DOMString token, DOMString newToken);
  boolean supports(DOMString token);
  [CEReactions] attribute DOMString value;
  stringifier;
  iterable<DOMString>;
};

A DOMTokenList object has an associated ordered set of tokens, which is initially empty.

A DOMTokenList object also has an associated element and an attribute’s local name.

Specifications may define supported tokens for a DOMTokenList's associated attribute’s local name.

A DOMTokenList object’s validation steps for a given token are:

  1. If the associated attribute’s local name does not define supported tokens, throw a TypeError.

  2. Let lowercase token be a copy of token, converted to ASCII lowercase.

  3. If lowercase token is present in supported tokens, return true.

  4. Return false.

A DOMTokenList object’s update steps are to set an attribute value for the associated element using associated attribute’s local name and the result of running the ordered set serializer for tokens.

A DOMTokenList object’s serialize steps are to return the result of running get an attribute value given the associated element and the associated attribute’s local name.


A DOMTokenList object has these attribute change steps for its associated element:

  1. If localName is associated attribute’s local name, namespace is null, and value is null, then set tokens to the empty set.

  2. Otherwise, localName is associated attribute’s local name, namespace is null, then set tokens to value, parsed.

When a DOMTokenList object is created, run these substeps:

  1. Let element be associated element.

  2. Let localName be associated attribute’s local name.

  3. Let value be the result of getting an attribute given null, localName, and element.

  4. Run the attribute change steps for element, localName, value, value, and null.

tokenlist . length

Returns the number of tokens.

tokenlist . item(index)
tokenlist[index]

Returns the token with index index.

tokenlist . contains(token)

Returns true if token is present, and false otherwise.

tokenlist . add(tokens…)

Adds all arguments passed, except those already present.

Throws a SyntaxError if one of the arguments is the empty string.

Throws an InvalidCharacterError if one of the arguments contains any ASCII whitespace.

tokenlist . remove(tokens…)

Removes arguments passed, if they are present.

Throws a SyntaxError if one of the arguments is the empty string.

Throws an InvalidCharacterError if one of the arguments contains any ASCII whitespace.

tokenlist . toggle(token [, force])

If force is not given, "toggles" token, removing it if it’s present and adding it if it’s not present. If force is true, adds token (same as add()). If force is false, removes token (same as remove()).

Returns true if token is now present, and false otherwise.

Throws a SyntaxError if token is empty.

Throws an InvalidCharacterError if token contains any spaces.

tokenlist . replace(token, newToken)

Replaces token with newToken.

Throws a SyntaxError if one of the arguments is the empty string.

Throws an InvalidCharacterError if one of the arguments contains any ASCII whitespace.

tokenlist . supports(token)

Returns true if token is in the associated attribute’s supported tokens. Returns false otherwise.

Throws a TypeError if the associated attribute has no supported tokens defined.

tokenlist . value

Returns the associated set as string.

Can be set, to change the associated attribute.

The length attribute' getter must return the number of tokens in the tokens.

The object’s supported property indices are the numbers in the range zero to the number of tokens in tokens minus one, unless tokens is empty, in which case there are no supported property indices.

The item(index) method, when invoked, must run these steps:

  1. If index is equal to or greater than the number of tokens in tokens, return null.

  2. Return the indexth token in tokens.

The contains(token) method, when invoked, must return true if token is in tokens, and false otherwise.

The add(tokens…) method, when invoked, must run these steps:

  1. For each token in tokens, run these substeps:

    1. If token is the empty string, then throw a SyntaxError.

    2. If token contains any ASCII whitespace, then throw an InvalidCharacterError.

  2. For each token in tokens, in given order, that is not in tokens, append token to tokens.

  3. Run the update steps.

The remove(tokens…) method, when invoked, must run these steps:

  1. For each token in tokens, run these substeps:

    1. If token is the empty string, then throw a SyntaxError.

    2. If token contains any ASCII whitespace, then throw an InvalidCharacterError.

  2. For each token in tokens, remove token from tokens.

  3. Run the update steps.

The toggle(token, force) method, when invoked, must run these steps:

  1. If token is the empty string, then throw a SyntaxError.

  2. If token contains any ASCII whitespace, then throw an InvalidCharacterError.

  3. If token is in tokens, run these substeps:

    1. If force is either not passed or is false, then remove token from tokens, run the update steps, and return false.

    2. Otherwise, return true.

  4. Otherwise, run these substeps:

    1. If force is passed and is false, return false.

    2. Otherwise, append token to tokens, run the update steps, and return true.

The replace(token, newToken) method, when invoked, must run these steps:

  1. If either token or newToken is the empty string, then throw a SyntaxError.

  2. If either token or newToken contains any ASCII whitespace, then throw an InvalidCharacterError.

  3. If token is not in tokens, terminate these steps.

  4. Replace token in tokens with newToken.

  5. Run the update steps.

The supports(token) method, when invoked, must run these steps:

  1. Let result be the return value of validation steps called with token. Rethrow any exceptions.

  2. Return result.

The value attribute must return the result of running context object’s serialize steps.

Setting the value attribute must set an attribute value for the associated element using associated attribute’s local name and the given value.

The stringification behavior must return the result of running context object’s serialize steps.

8. Historical

As explained in goals this specification is a significant revision of various DOM specifications. This section attempts to enumerate the changes.

8.1. DOM Events

These are the changes made to the features described in the "DOM Event Architecture", "Basic Event Interfaces", "Mutation Events", and "Mutation Name Event Types" chapters of DOM Level 3 Events. The other chapters are defined by the UI Events specification. [UIEVENTS]

8.2. DOM Core

These are the changes made to the features described in DOM Level 3 Core.

DOMString, DOMException, and DOMTimeStamp are now defined in Web IDL.

Node now inherits from EventTarget.

Nodes are implicitly adopted across document boundaries.

Doctypes now always have a node document and can be moved across document boundaries.

ProcessingInstruction now inherits from CharacterData.

hasAttributes() and attributes moved from Node to Element.

namespaceURI, prefix, and localName moved from Node to Element and Attr.

The remainder of interfaces and interface members listed in this section were removed to simplify the DOM platform. Implementations conforming to this specification will not support them.

It is not yet clear if it would be web-compatible to remove all the following features. The editors welcome any data showing that some of these features should be reintroduced.

Interfaces:

Interface members:

Node
  • isSupported
  • getFeature()
  • getUserData()
  • setUserData()
Document
  • createCDATASection()
  • createEntityReference()
  • xmlEncoding
  • xmlStandalone
  • xmlVersion
  • strictErrorChecking
  • domConfig
  • normalizeDocument()
  • renameNode()
DOMImplementation
  • getFeature()
Attr
No longer inherits from Node and therefore completely changed.
Element
  • schemaTypeInfo
  • setIdAttribute()
  • setIdAttributeNS()
  • setIdAttributeNode()
DocumentType
  • entities
  • notations
  • internalSubset
Text
  • isElementContentWhitespace
  • replaceWholeText()

8.3. DOM Ranges

These are the changes made to the features described in the "Document Object Model Range" chapter of DOM Level 2 Traversal and Range.

8.4. DOM Traversal

These are the changes made to the features described in the "Document Object Model Traversal" chapter of DOM Level 2 Traversal and Range.

Acknowledgments

There have been a lot of people that have helped make DOM more interoperable over the years and thereby furthered the goals of this standard. Likewise many people have helped making this standard what it is today.

With that, many thanks to Adam Klein, Adrian Bateman, Aleksey Shvayka, Alex Komoroske, Alex Russell, Anthony Ramine, Arkadiusz Michalski, Arnaud Le Hors, Arun Ranganathan, Björn Höhrmann, Boris Zbarsky, Brandon Payton, Brandon Slade, Brandon Wallace, Brian Kardell, Cameron McCormack, Chris Dumez, Chris Paris, Chris Rebert, Daniel Glazman, Darin Fisher, David Bruant, David Flanagan, David Håsäther, David Hyatt, Deepak Sherveghar, Dethe Elza, Dimitri Glazkov, Domenic Denicola, Dominic Cooney, Dominique Hazaël-Massieux, Don Jordan, Doug Schepers, Edward O’Connor, Elisée Maurer Elliott Sprehn, Eric Bidelman, Erik Arvidsson, Gavin Nicol, Geoffrey Sneddon, Giorgio Liscio, Glen Huang, Glenn Adams, Glenn Maynard, Hajime Morrita, Harald Alvestrand, Hayato Ito, Henri Sivonen, Hunan Rostomyan, Ian Hickson, Igor Bukanov, Jacob Rossi, Jake Archibald, Jake Verbaten, James Graham, James Greene, James Robinson, Jeffrey Yasskin, Jens Lindström, Jesse McCarthy, João Eiras, Joe Kesselman, John Atkins, Jonas Sicking, Jonathan Robie, Joris van der Wel, Joshua Bell, Jungkee Song, Justin Summerlin, 呂康豪 (Kang-Hao Lu), Kevin Sweeney, Koji Ishii, Lachlan Hunt, Lauren Wood, Malte Ubl, Manish Goregaokar, Manish Tripathi, Marcos Caceres, Mark Miller, Mats Palmgren, Mounir Lamouri, Michael™ Smith, Mike Champion, Mike Taylor, Ojan Vafai, Oliver Nightingale, Olli Pettay, Ondřej Žára, Peter Sharpe, Philip Jägenstedt, Philippe Le Hégaret, Rafael Weinstein, Richard Bradshaw, Rick Byers, Rick Waldron, Robbert Broersma, Robin Berjon, Roland Steiner, Rune F. Halvorsen, Ruud Steltenpool, Ryosuke Niwa, Sam Dutton, Samuel Giles, Sebastian Mayr, Seo Sanghyeon, Sergey G. Grekhov, Shiki Okasaka, Shinya Kawanaka, Simon Pieters, Steve Byrne, Stig Halvorsen, Tab Atkins, Takashi Sakamoto, Takayoshi Kochi, timeless, Timo Tijhof, Tobie Langel, Tom Pixley, Travis Leithead, triple-underscore, Veli Şenol, Vidur Apparao, Warren He, Yehuda Katz, Yoav Weiss, Yoichi Osato, Yoshinori Sano, and Zack Weinberg for being awesome!

This standard is written by Anne van Kesteren (Mozilla, annevk@annevk.nl) with substantial contributions from Aryeh Gregor (Mozilla, ayg@aryeh.name) and Ms2ger (Mozilla, ms2ger@gmail.com).

Part of the revision history of the integration points related to custom elements can be found in the w3c/webcomponents repository, which is available under the W3C Permissive Document License.

Per CC0, to the extent possible under law, the editors have waived all copyright and related or neighboring rights to this work.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[CSS-ANIMATIONS-1]
CSS Animations Module Level 1 URL: https://drafts.csswg.org/css-animations-1/
[CSS-TRANSITIONS-1]
CSS Transitions Module Level 1 URL: https://drafts.csswg.org/css-transitions-1/
[CSS3-ANIMATIONS]
Dean Jackson; et al. CSS Animations. 19 February 2013. WD. URL: http://www.w3.org/TR/css3-animations/
[CSS3-TRANSITIONS]
Dean Jackson; et al. CSS Transitions. 19 November 2013. WD. URL: http://dev.w3.org/csswg/css-transitions/
[DEVICE-ORIENTATION]
Stephen Block; Andrei Popescu. DeviceOrientation Event Specification. 1 December 2011. LCWD. URL: http://www.w3.org/TR/orientation-event/
[ECMASCRIPT]
ECMAScript Language Specification. URL: https://tc39.github.io/ecma262/
[ENCODING]
Anne van Kesteren. Encoding Standard. Living Standard. URL: https://encoding.spec.whatwg.org/
[HTML]
Ian Hickson. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119
[SELECTORS-4]
Selectors Level 4 URL: https://drafts.csswg.org/selectors-4/
[SELECTORS4]
Elika Etemad; Tab Atkins Jr.. Selectors Level 4. 2 May 2013. WD. URL: http://www.w3.org/TR/selectors4/
[SERVICE-WORKERS]
Alex Russell; Jungkee Song; Jake Archibald. Service Workers. 25 June 2015. WD. URL: https://slightlyoff.github.io/ServiceWorker/spec/service_worker/
[SVG]
Jon Ferraiolo. Scalable Vector Graphics (SVG) 1.0 Specification. 4 September 2001. REC. URL: http://www.w3.org/TR/SVG/
[TOUCH-EVENTS]
Doug Schepers; et al. Touch Events. 10 October 2013. REC. URL: http://dvcs.w3.org/hg/webevents/raw-file/v1/touchevents.html
[UIEVENTS]
Gary Kacmarcik; Travis Leithead. UI Events Specification. 15 December 2015. WD. URL: https://w3c.github.io/uievents/
[URL]
Anne van Kesteren; Sam Ruby. URL Standard. Living Standard. URL: https://url.spec.whatwg.org/
[WEBGL]
Chris Marrin (Apple Inc.). WebGL Specification, Version 1.0. 10 February 2011. URL: https://www.khronos.org/registry/webgl/specs/1.0/
[WEBIDL]
Cameron McCormack; Boris Zbarsky. WebIDL Level 1. 8 March 2016. CR. URL: https://heycam.github.io/webidl/
[XHR]
Anne van Kesteren. XMLHttpRequest Standard. Living Standard. URL: https://xhr.spec.whatwg.org/
[XML]
Tim Bray; et al. Extensible Markup Language (XML) 1.0 (Fifth Edition). 26 November 2008. REC. URL: http://www.w3.org/TR/xml
[XML-NAMES]
Tim Bray; et al. Namespaces in XML 1.0 (Third Edition). 8 December 2009. REC. URL: http://www.w3.org/TR/xml-names

Informative References

[CSSOM-VIEW]
Simon Pieters. CSSOM View Module. 17 March 2016. WD. URL: https://drafts.csswg.org/cssom-view/
[DOM-Level-2-Traversal-Range]
Joseph Kesselman; et al. Document Object Model (DOM) Level 2 Traversal and Range Specification. 13 November 2000. REC. URL: http://www.w3.org/TR/DOM-Level-2-Traversal-Range/
[DOM-Level-3-Core]
Arnaud Le Hors; et al. Document Object Model (DOM) Level 3 Core Specification. 7 April 2004. REC. URL: http://www.w3.org/TR/DOM-Level-3-Core/
[DOM-Parsing]
Travis Leithead. DOM Parsing and Serialization. 17 May 2016. WD. URL: https://w3c.github.io/DOM-Parsing/
[ELEMENTTRAVERSAL]
Doug Schepers; Robin Berjon. Element Traversal Specification. 22 December 2008. REC. URL: http://www.w3.org/TR/ElementTraversal/
[INDEXEDDB]
Nikunj Mehta; et al. Indexed Database API. 8 January 2015. REC. URL: http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html
[SELECTORS-API2]
Lachlan Hunt. Selectors API Level 2. 17 October 2013. NOTE. URL: http://dev.w3.org/2006/webapi/selectors-api2/
[UIEVENTS-20031107]
Philippe Le Hégaret; Tim Pixley. Document Object Model (DOM) Level 3 Events Specification. 7 November 2003. NOTE. URL: http://www.w3.org/TR/2003/NOTE-DOM-Level-3-Events-20031107

IDL Index

[Constructor(DOMString type, optional EventInit eventInitDict),
 Exposed=(Window,Worker)]
interface Event {
  readonly attribute DOMString type;
  readonly attribute EventTarget? target;
  readonly attribute EventTarget? currentTarget;
  sequence<EventTarget> composedPath();

  const unsigned short NONE = 0;
  const unsigned short CAPTURING_PHASE = 1;
  const unsigned short AT_TARGET = 2;
  const unsigned short BUBBLING_PHASE = 3;
  readonly attribute unsigned short eventPhase;

  void stopPropagation();
  void stopImmediatePropagation();

  readonly attribute boolean bubbles;
  readonly attribute boolean cancelable;
  void preventDefault();
  readonly attribute boolean defaultPrevented;
  readonly attribute boolean composed;

  [Unforgeable] readonly attribute boolean isTrusted;
  readonly attribute DOMTimeStamp timeStamp;

  void initEvent(DOMString type, boolean bubbles, boolean cancelable); // historical
};

dictionary EventInit {
  boolean bubbles = false;
  boolean cancelable = false;
  boolean composed = false;
};

[Constructor(DOMString type, optional CustomEventInit eventInitDict),
 Exposed=(Window,Worker)]
interface CustomEvent : Event {
  readonly attribute any detail;

  void initCustomEvent(DOMString type, boolean bubbles, boolean cancelable, any detail);
};

dictionary CustomEventInit : EventInit {
  any detail = null;
};

[Exposed=(Window,Worker)]
interface EventTarget {
  void addEventListener(DOMString type, EventListener? callback, optional (AddEventListenerOptions or boolean) options);
  void removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options);
  boolean dispatchEvent(Event event);
};

callback interface EventListener {
  void handleEvent(Event event);
};

dictionary EventListenerOptions {
  boolean capture = false;
};

dictionary AddEventListenerOptions : EventListenerOptions {
  boolean passive = false;
  boolean once = false;
};

[NoInterfaceObject,
 Exposed=Window]
interface NonElementParentNode {
  Element? getElementById(DOMString elementId);
};
Document implements NonElementParentNode;
DocumentFragment implements NonElementParentNode;

[NoInterfaceObject,
 Exposed=Window]
interface DocumentOrShadowRoot {
};
Document implements DocumentOrShadowRoot;
ShadowRoot implements DocumentOrShadowRoot;

[NoInterfaceObject,
 Exposed=Window]
interface ParentNode {
  [SameObject] readonly attribute HTMLCollection children;
  readonly attribute Element? firstElementChild;
  readonly attribute Element? lastElementChild;
  readonly attribute unsigned long childElementCount;

  [CEReactions, Unscopable] void prepend((Node or DOMString)... nodes);
  [CEReactions, Unscopable] void append((Node or DOMString)... nodes);

  Element? querySelector(DOMString selectors);
  [NewObject] NodeList querySelectorAll(DOMString selectors);
};
Document implements ParentNode;
DocumentFragment implements ParentNode;
Element implements ParentNode;

[NoInterfaceObject,
 Exposed=Window]
interface NonDocumentTypeChildNode {
  readonly attribute Element? previousElementSibling;
  readonly attribute Element? nextElementSibling;
};
Element implements NonDocumentTypeChildNode;
CharacterData implements NonDocumentTypeChildNode;

[NoInterfaceObject,
 Exposed=Window]
interface ChildNode {
  [CEReactions, Unscopable] void before((Node or DOMString)... nodes);
  [CEReactions, Unscopable] void after((Node or DOMString)... nodes);
  [CEReactions, Unscopable] void replaceWith((Node or DOMString)... nodes);
  [CEReactions, Unscopable] void remove();
};
DocumentType implements ChildNode;
Element implements ChildNode;
CharacterData implements ChildNode;

[NoInterfaceObject,
 Exposed=Window]
interface Slotable {
  readonly attribute HTMLSlotElement? assignedSlot;
};
Element implements Slotable;
Text implements Slotable;

[Exposed=Window]
interface NodeList {
  getter Node? item(unsigned long index);
  readonly attribute unsigned long length;
  iterable<Node>;
};

[Exposed=Window, LegacyUnenumerableNamedProperties]
interface HTMLCollection {
  readonly attribute unsigned long length;
  getter Element? item(unsigned long index);
  getter Element? namedItem(DOMString name);
};

[Constructor(MutationCallback callback)]
interface MutationObserver {
  void observe(Node target, MutationObserverInit options);
  void disconnect();
  sequence<MutationRecord> takeRecords();
};

callback MutationCallback = void (sequence<MutationRecord> mutations, MutationObserver observer);

dictionary MutationObserverInit {
  boolean childList = false;
  boolean attributes;
  boolean characterData;
  boolean subtree = false;
  boolean attributeOldValue;
  boolean characterDataOldValue;
  sequence<DOMString> attributeFilter;
};

[Exposed=Window]
interface MutationRecord {
  readonly attribute DOMString type;
  [SameObject] readonly attribute Node target;
  [SameObject] readonly attribute NodeList addedNodes;
  [SameObject] readonly attribute NodeList removedNodes;
  readonly attribute Node? previousSibling;
  readonly attribute Node? nextSibling;
  readonly attribute DOMString? attributeName;
  readonly attribute DOMString? attributeNamespace;
  readonly attribute DOMString? oldValue;
};

[Exposed=Window]
interface Node : EventTarget {
  const unsigned short ELEMENT_NODE = 1;
  const unsigned short ATTRIBUTE_NODE = 2; // historical
  const unsigned short TEXT_NODE = 3;
  const unsigned short CDATA_SECTION_NODE = 4; // historical
  const unsigned short ENTITY_REFERENCE_NODE = 5; // historical
  const unsigned short ENTITY_NODE = 6; // historical
  const unsigned short PROCESSING_INSTRUCTION_NODE = 7;
  const unsigned short COMMENT_NODE = 8;
  const unsigned short DOCUMENT_NODE = 9;
  const unsigned short DOCUMENT_TYPE_NODE = 10;
  const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
  const unsigned short NOTATION_NODE = 12; // historical
  readonly attribute unsigned short nodeType;
  readonly attribute DOMString nodeName;

  readonly attribute USVString baseURI;

  readonly attribute boolean isConnected;
  readonly attribute Document? ownerDocument;
  readonly attribute Node rootNode;
  readonly attribute Node? parentNode;
  readonly attribute Element? parentElement;
  boolean hasChildNodes();
  [SameObject] readonly attribute NodeList childNodes;
  readonly attribute Node? firstChild;
  readonly attribute Node? lastChild;
  readonly attribute Node? previousSibling;
  readonly attribute Node? nextSibling;

  [CEReactions] attribute DOMString? nodeValue;
  [CEReactions] attribute DOMString? textContent;
  [CEReactions] void normalize();

  [CEReactions, NewObject] Node cloneNode(optional boolean deep = false);
  boolean isEqualNode(Node? otherNode);
  boolean isSameNode(Node? otherNode); // historical alias of ===

  const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01;
  const unsigned short DOCUMENT_POSITION_PRECEDING = 0x02;
  const unsigned short DOCUMENT_POSITION_FOLLOWING = 0x04;
  const unsigned short DOCUMENT_POSITION_CONTAINS = 0x08;
  const unsigned short DOCUMENT_POSITION_CONTAINED_BY = 0x10;
  const unsigned short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
  unsigned short compareDocumentPosition(Node other);
  boolean contains(Node? other);

  DOMString? lookupPrefix(DOMString? namespace);
  DOMString? lookupNamespaceURI(DOMString? prefix);
  boolean isDefaultNamespace(DOMString? namespace);

  [CEReactions] Node insertBefore(Node node, Node? child);
  [CEReactions] Node appendChild(Node node);
  [CEReactions] Node replaceChild(Node node, Node child);
  [CEReactions] Node removeChild(Node child);
};

[Constructor,
 Exposed=Window]
interface Document : Node {
  [SameObject] readonly attribute DOMImplementation implementation;
  readonly attribute USVString URL;
  readonly attribute USVString documentURI;
  readonly attribute USVString origin;
  readonly attribute DOMString compatMode;
  readonly attribute DOMString characterSet;
  readonly attribute DOMString charset; // historical alias of .characterSet
  readonly attribute DOMString inputEncoding; // historical alias of .characterSet
  readonly attribute DOMString contentType;

  readonly attribute DocumentType? doctype;
  readonly attribute Element? documentElement;
  HTMLCollection getElementsByTagName(DOMString qualifiedName);
  HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
  HTMLCollection getElementsByClassName(DOMString classNames);

  [NewObject] Element createElement(DOMString localName, optional ElementCreationOptions options);
  [NewObject] Element createElementNS(DOMString? namespace, DOMString qualifiedName, optional ElementCreationOptions options);
  [NewObject] DocumentFragment createDocumentFragment();
  [NewObject] Text createTextNode(DOMString data);
  [NewObject] Comment createComment(DOMString data);
  [NewObject] ProcessingInstruction createProcessingInstruction(DOMString target, DOMString data);

  [CEReactions, NewObject] Node importNode(Node node, optional boolean deep = false);
  [CEReactions] Node adoptNode(Node node);

  [NewObject] Attr createAttribute(DOMString localName);
  [NewObject] Attr createAttributeNS(DOMString? namespace, DOMString qualifiedName);

  [NewObject] Event createEvent(DOMString interface);

  [NewObject] Range createRange();

  // NodeFilter.SHOW_ALL = 0xFFFFFFFF
  [NewObject] NodeIterator createNodeIterator(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
  [NewObject] TreeWalker createTreeWalker(Node root, optional unsigned long whatToShow = 0xFFFFFFFF, optional NodeFilter? filter = null);
};

[Exposed=Window]
interface XMLDocument : Document {};

dictionary ElementCreationOptions {
  DOMString is;
};

[Exposed=Window]
interface DOMImplementation {
  [NewObject] DocumentType createDocumentType(DOMString qualifiedName, DOMString publicId, DOMString systemId);
  [NewObject] XMLDocument createDocument(DOMString? namespace, [TreatNullAs=EmptyString] DOMString qualifiedName, optional DocumentType? doctype = null);
  [NewObject] Document createHTMLDocument(optional DOMString title);

  boolean hasFeature(); // useless; always returns true
};

[Exposed=Window]
interface DocumentType : Node {
  readonly attribute DOMString name;
  readonly attribute DOMString publicId;
  readonly attribute DOMString systemId;
};

[Constructor,
 Exposed=Window]
interface DocumentFragment : Node {
};

[Exposed=Window]
interface ShadowRoot : DocumentFragment {
  readonly attribute ShadowRootMode mode;
  readonly attribute Element host;
};

enum ShadowRootMode { "open", "closed" };

[Exposed=Window]
interface Element : Node {
  readonly attribute DOMString? namespaceURI;
  readonly attribute DOMString? prefix;
  readonly attribute DOMString localName;
  readonly attribute DOMString tagName;

  [CEReactions] attribute DOMString id;
  [CEReactions] attribute DOMString className;
  [CEReactions, SameObject, PutForwards=value] readonly attribute DOMTokenList classList;
  [CEReactions] attribute DOMString slot;

  boolean hasAttributes();
  [SameObject] readonly attribute NamedNodeMap attributes;
  sequence<DOMString> getAttributeNames();
  DOMString? getAttribute(DOMString qualifiedName);
  DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
  [CEReactions] void setAttribute(DOMString qualifiedName, DOMString value);
  [CEReactions] void setAttributeNS(DOMString? namespace, DOMString qualifiedName, DOMString value);
  [CEReactions] void removeAttribute(DOMString qualifiedName);
  [CEReactions] void removeAttributeNS(DOMString? namespace, DOMString localName);
  boolean hasAttribute(DOMString qualifiedName);
  boolean hasAttributeNS(DOMString? namespace, DOMString localName);

  Attr? getAttributeNode(DOMString qualifiedName);
  Attr? getAttributeNodeNS(DOMString? namespace, DOMString localName);
  [CEReactions] Attr? setAttributeNode(Attr attr);
  [CEReactions] Attr? setAttributeNodeNS(Attr attr);
  [CEReactions] Attr removeAttributeNode(Attr attr);

  ShadowRoot attachShadow(ShadowRootInit init);
  readonly attribute ShadowRoot? shadowRoot;

  Element? closest(DOMString selectors);
  boolean matches(DOMString selectors);
  boolean webkitMatchesSelector(DOMString selectors); // historical alias of .matches

  HTMLCollection getElementsByTagName(DOMString qualifiedName);
  HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName);
  HTMLCollection getElementsByClassName(DOMString classNames);

  [CEReactions] Element? insertAdjacentElement(DOMString where, Element element); // historical
  [CEReactions] void insertAdjacentText(DOMString where, DOMString data); // historical
};

dictionary ShadowRootInit {
  required ShadowRootMode mode;
};

[Exposed=Window, LegacyUnenumerableNamedProperties]
interface NamedNodeMap {
  readonly attribute unsigned long length;
  getter Attr? item(unsigned long index);
  getter Attr? getNamedItem(DOMString qualifiedName);
  Attr? getNamedItemNS(DOMString? namespace, DOMString localName);
  [CEReactions] Attr? setNamedItem(Attr attr);
  [CEReactions] Attr? setNamedItemNS(Attr attr);
  [CEReactions] Attr removeNamedItem(DOMString qualifiedName);
  [CEReactions] Attr removeNamedItemNS(DOMString? namespace, DOMString localName);
};

[Exposed=Window]
interface Attr {
  readonly attribute DOMString? namespaceURI;
  readonly attribute DOMString? prefix;
  readonly attribute DOMString localName;
  readonly attribute DOMString name;
  readonly attribute DOMString nodeName; // historical alias of .name
  [CEReactions] attribute DOMString value;
  [CEReactions, TreatNullAs=EmptyString] attribute DOMString nodeValue; // historical alias of .value
  [CEReactions, TreatNullAs=EmptyString] attribute DOMString textContent; // historical alias of .value

  readonly attribute Element? ownerElement;

  readonly attribute boolean specified; // useless; always returns true
};
[Exposed=Window]
interface CharacterData : Node {
  [TreatNullAs=EmptyString] attribute DOMString data;
  readonly attribute unsigned long length;
  DOMString substringData(unsigned long offset, unsigned long count);
  void appendData(DOMString data);
  void insertData(unsigned long offset, DOMString data);
  void deleteData(unsigned long offset, unsigned long count);
  void replaceData(unsigned long offset, unsigned long count, DOMString data);
};

[Constructor(optional DOMString data = ""),
 Exposed=Window]
interface Text : CharacterData {
  [NewObject] Text splitText(unsigned long offset);
  readonly attribute DOMString wholeText;
};
[Exposed=Window]
interface ProcessingInstruction : CharacterData {
  readonly attribute DOMString target;
};
[Constructor(optional DOMString data = ""),
 Exposed=Window]
interface Comment : CharacterData {
};

[Constructor,
 Exposed=Window]
interface Range {
  readonly attribute Node startContainer;
  readonly attribute unsigned long startOffset;
  readonly attribute Node endContainer;
  readonly attribute unsigned long endOffset;
  readonly attribute boolean collapsed;
  readonly attribute Node commonAncestorContainer;

  void setStart(Node node, unsigned long offset);
  void setEnd(Node node, unsigned long offset);
  void setStartBefore(Node node);
  void setStartAfter(Node node);
  void setEndBefore(Node node);
  void setEndAfter(Node node);
  void collapse(optional boolean toStart = false);
  void selectNode(Node node);
  void selectNodeContents(Node node);

  const unsigned short START_TO_START = 0;
  const unsigned short START_TO_END = 1;
  const unsigned short END_TO_END = 2;
  const unsigned short END_TO_START = 3;
  short compareBoundaryPoints(unsigned short how, Range sourceRange);

  [CEReactions] void deleteContents();
  [CEReactions, NewObject] DocumentFragment extractContents();
  [CEReactions, NewObject] DocumentFragment cloneContents();
  [CEReactions] void insertNode(Node node);
  [CEReactions] void surroundContents(Node newParent);

  [NewObject] Range cloneRange();
  void detach();

  boolean isPointInRange(Node node, unsigned long offset);
  short comparePoint(Node node, unsigned long offset);

  boolean intersectsNode(Node node);

  stringifier;
};

[Exposed=Window]
interface NodeIterator {
  [SameObject] readonly attribute Node root;
  readonly attribute Node referenceNode;
  readonly attribute boolean pointerBeforeReferenceNode;
  readonly attribute unsigned long whatToShow;
  readonly attribute NodeFilter? filter;

  Node? nextNode();
  Node? previousNode();

  void detach();
};

[Exposed=Window]
interface TreeWalker {
  [SameObject] readonly attribute Node root;
  readonly attribute unsigned long whatToShow;
  readonly attribute NodeFilter? filter;
           attribute Node currentNode;

  Node? parentNode();
  Node? firstChild();
  Node? lastChild();
  Node? previousSibling();
  Node? nextSibling();
  Node? previousNode();
  Node? nextNode();
};
[Exposed=Window]
callback interface NodeFilter {
  // Constants for acceptNode()
  const unsigned short FILTER_ACCEPT = 1;
  const unsigned short FILTER_REJECT = 2;
  const unsigned short FILTER_SKIP = 3;

  // Constants for whatToShow
  const unsigned long SHOW_ALL = 0xFFFFFFFF;
  const unsigned long SHOW_ELEMENT = 0x1;
  const unsigned long SHOW_ATTRIBUTE = 0x2; // historical
  const unsigned long SHOW_TEXT = 0x4;
  const unsigned long SHOW_CDATA_SECTION = 0x8; // historical
  const unsigned long SHOW_ENTITY_REFERENCE = 0x10; // historical
  const unsigned long SHOW_ENTITY = 0x20; // historical
  const unsigned long SHOW_PROCESSING_INSTRUCTION = 0x40;
  const unsigned long SHOW_COMMENT = 0x80;
  const unsigned long SHOW_DOCUMENT = 0x100;
  const unsigned long SHOW_DOCUMENT_TYPE = 0x200;
  const unsigned long SHOW_DOCUMENT_FRAGMENT = 0x400;
  const unsigned long SHOW_NOTATION = 0x800; // historical

  unsigned short acceptNode(Node node);
};

interface DOMTokenList {
  readonly attribute unsigned long length;
  getter DOMString? item(unsigned long index);
  boolean contains(DOMString token);
  [CEReactions] void add(DOMString... tokens);
  [CEReactions] void remove(DOMString... tokens);
  [CEReactions] boolean toggle(DOMString token, optional boolean force);
  [CEReactions] void replace(DOMString token, DOMString newToken);
  boolean supports(DOMString token);
  [CEReactions] attribute DOMString value;
  stringifier;
  iterable<DOMString>;
};