1. 8.4 Dynamic markup insertion
      1. 8.4.1 Opening the input stream
      2. 8.4.2 Closing the input stream
      3. 8.4.3 document.write()
      4. 8.4.4 document.writeln()
    2. 8.5 DOM parsing and serialization APIs
      1. 8.5.1 The DOMParser interface
      2. 8.5.2 Unsafe HTML parsing methods
      3. 8.5.3 HTML serialization methods
      4. 8.5.4 The innerHTML property
      5. 8.5.5 The outerHTML property
      6. 8.5.6 The insertAdjacentHTML() method
      7. 8.5.7 The createContextualFragment() method

8.4 Dynamic markup insertion

APIs for dynamically inserting markup into the document interact with the parser, and thus their behavior varies depending on whether they are used with HTML documents (and the HTML parser) or XML documents (and the XML parser).

Document objects have a throw-on-dynamic-markup-insertion counter, which is used in conjunction with the create an element for the token algorithm to prevent custom element constructors from being able to use document.open(), document.close(), and document.write() when they are invoked by the parser. Initially, the counter must be set to zero.

8.4.1 Opening the input stream

document = document.open()

Document/open

Support in all current engines.

Firefox1+Safari11+Chrome64+
Opera51+Edge79+
Edge (Legacy)12+Internet Explorer4+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android47+

Causes the Document to be replaced in-place, as if it was a new Document object, but reusing the previous object, which is then returned.

The resulting Document has an HTML parser associated with it, which can be given data to parse using document.write().

The method has no effect if the Document is still being parsed.

Throws an "InvalidStateError" DOMException if the Document is an XML document.

Throws an "InvalidStateError" DOMException if the parser is currently executing a custom element constructor.

window = document.open(url, name, features)

Works like the window.open() method.

Document objects have an active parser was aborted boolean, which is used to prevent scripts from invoking the document.open() and document.write() methods (directly or indirectly) after the document's active parser has been aborted. It is initially false.

The document open steps, given a document, are as follows:

  1. If document is an XML document, then throw an "InvalidStateError" DOMException exception.

  2. If document's throw-on-dynamic-markup-insertion counter is greater than 0, then throw an "InvalidStateError" DOMException.

  3. Let entryDocument be the entry global object's associated Document.

  4. If document's origin is not same origin to entryDocument's origin, then throw a "SecurityError" DOMException.

  5. If document has an active parser whose script nesting level is greater than 0, then return document.

    This basically causes document.open() to be ignored when it's called in an inline script found during parsing, while still letting it have an effect when called from a non-parser task such as a timer callback or event handler.

  6. Similarly, if document's unload counter is greater than 0, then return document.

    This basically causes document.open() to be ignored when it's called from a beforeunload, pagehide, or unload event handler while the Document is being unloaded.

  7. If document's active parser was aborted is true, then return document.

    This notably causes document.open() to be ignored if it is called after a navigation has started, but only during the initial parse. See issue #4723 for more background.

  8. If document's node navigable is non-null and document's node navigable's ongoing navigation is a navigation ID, then stop loading document's node navigable.

  9. For each shadow-including inclusive descendant node of document, erase all event listeners and handlers given node.

  10. If document is the associated Document of document's relevant global object, then erase all event listeners and handlers given document's relevant global object.

  11. Let oldFlag be the value of document's fire mutation events flag.
  12. Set document's fire mutation events flag to false.
  13. Replace all with null within document.

  14. Set document's fire mutation events flag to oldFlag.
  15. If document is fully active, then:

    1. Let newURL be a copy of entryDocument's URL.

    2. If entryDocument is not document, then set newURL's fragment to null.

    3. Run the URL and history update steps with document and newURL.

  16. Set document's is initial about:blank to false.

  17. If document's iframe load in progress flag is set, then set document's mute iframe load flag.

  18. Set document to no-quirks mode.

  19. Create a new HTML parser and associate it with document. This is a script-created parser (meaning that it can be closed by the document.open() and document.close() methods, and that the tokenizer will wait for an explicit call to document.close() before emitting an end-of-file token). The encoding confidence is irrelevant.

  20. Set the insertion point to point at just before the end of the input stream (which at this point will be empty).

  21. Update the current document readiness of document to "loading".

    This causes a readystatechange event to fire, but the event is actually unobservable to author code, because of the previous step which erased all event listeners and handlers that could observe it.

  22. Return document.

The document open steps do not affect whether a Document is ready for post-load tasks or completely loaded.

The open(unused1, unused2) method must return the result of running the document open steps with this.

The unused1 and unused2 arguments are ignored, but kept in the IDL to allow code that calls the function with one or two arguments to continue working. They are necessary due to Web IDL overload resolution algorithm rules, which would throw a TypeError exception for such calls had the arguments not been there. whatwg/webidl issue #581 investigates changing the algorithm to allow for their removal. [WEBIDL]

The open(url, name, features) method must run these steps:

  1. If this is not fully active, then throw an "InvalidAccessError" DOMException exception.

  2. Return the result of running the window open steps with url, name, and features.

8.4.2 Closing the input stream

document.close()

Document/close

Support in all current engines.

Firefox1+Safari11+Chrome64+
Opera51+Edge79+
Edge (Legacy)12+Internet Explorer4+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android47+

Closes the input stream that was opened by the document.open() method.

Throws an "InvalidStateError" DOMException if the Document is an XML document.

Throws an "InvalidStateError" DOMException if the parser is currently executing a custom element constructor.

The close() method must run the following steps:

  1. If this is an XML document, then throw an "InvalidStateError" DOMException.

  2. If this's throw-on-dynamic-markup-insertion counter is greater than zero, then throw an "InvalidStateError" DOMException.

  3. If there is no script-created parser associated with this, then return.

  4. Insert an explicit "EOF" character at the end of the parser's input stream.

  5. If this's pending parsing-blocking script is not null, then return.

  6. Run the tokenizer, processing resulting tokens as they are emitted, and stopping when the tokenizer reaches the explicit "EOF" character or spins the event loop.

8.4.3 document.write()

document.write(...text)

Document/write

Support in all current engines.

Firefox1+Safari1+Chrome1+
Opera3+Edge79+
Edge (Legacy)12+Internet Explorer4+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android10.1+

In general, adds the given string(s) to the Document's input stream.

This method has very idiosyncratic behavior. In some cases, this method can affect the state of the HTML parser while the parser is running, resulting in a DOM that does not correspond to the source of the document (e.g. if the string written is the string "<plaintext>" or "<!--"). In other cases, the call can clear the current page first, as if document.open() had been called. In yet more cases, the method is simply ignored, or throws an exception. Users agents are explicitly allowed to avoid executing script elements inserted via this method. And to make matters even worse, the exact behavior of this method can in some cases be dependent on network latency, which can lead to failures that are very hard to debug. For all these reasons, use of this method is strongly discouraged.

Throws an "InvalidStateError" DOMException when invoked on XML documents.

Throws an "InvalidStateError" DOMException if the parser is currently executing a custom element constructor.

This method performs no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes.

Document objects have an ignore-destructive-writes counter, which is used in conjunction with the processing of script elements to prevent external scripts from being able to use document.write() to blow away the document by implicitly calling document.open(). Initially, the counter must be set to zero.

The document write steps, given a Document object document and a string input, are as follows:

  1. If document is an XML document, then throw an "InvalidStateError" DOMException.

  2. If document's throw-on-dynamic-markup-insertion counter is greater than 0, then throw an "InvalidStateError" DOMException.

  3. If document's active parser was aborted is true, then return.

  4. If the insertion point is undefined, then:

    1. If document's unload counter is greater than 0 or document's ignore-destructive-writes counter is greater than 0, then return.

    2. Run the document open steps with document.

  5. Insert input into the input stream just before the insertion point.

  6. If document's pending parsing-blocking script is null, then have the HTML parser process input, one code point at a time, processing resulting tokens as they are emitted, and stopping when the tokenizer reaches the insertion point or when the processing of the tokenizer is aborted by the tree construction stage (this can happen if a script end tag token is emitted by the tokenizer).

    If the document.write() method was called from script executing inline (i.e. executing because the parser parsed a set of script tags), then this is a reentrant invocation of the parser. If the parser pause flag is set, the tokenizer will abort immediately and no HTML will be parsed, per the tokenizer's parser pause flag check.

The document.write(...) method steps are to run the document write steps with this and a string that is the concatenation of all arguments passed.

8.4.4 document.writeln()

document.writeln(...text)

Document/writeln

Support in all current engines.

Firefox1+Safari11+Chrome64+
Opera51+Edge79+
Edge (Legacy)12+Internet Explorer4+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android47+

Adds the given string(s) to the Document's input stream, followed by a newline character. If necessary, calls the open() method implicitly first.

Throws an "InvalidStateError" DOMException when invoked on XML documents.

Throws an "InvalidStateError" DOMException if the parser is currently executing a custom element constructor.

This method performs no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes.

The document.writeln(...) method steps are to run the document write steps with this and a string that is the concatenation of all arguments passed and U+000A LINE FEED.

8.5 DOM parsing and serialization APIs

DOMParser

Support in all current engines.

Firefox1+Safari1.3+Chrome1+
Opera8+Edge79+
Edge (Legacy)12+Internet Explorer9+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android10.1+
partial interface Element {
  [CEReactions] undefined setHTMLUnsafe(HTMLString html);
  DOMString getHTML(optional GetHTMLOptions options = {});

  [CEReactions] attribute [LegacyNullToEmptyString] HTMLString innerHTML;
  [CEReactions] attribute [LegacyNullToEmptyString] HTMLString outerHTML;
  [CEReactions] undefined insertAdjacentHTML(DOMString position, HTMLString string);
};

partial interface ShadowRoot {
  [CEReactions] undefined setHTMLUnsafe(HTMLString html);
  DOMString getHTML(optional GetHTMLOptions options = {});

  [CEReactions] attribute [LegacyNullToEmptyString] HTMLString innerHTML;
};

dictionary GetHTMLOptions {
  boolean serializableShadowRoots = false;
  sequence<ShadowRoot> shadowRoots = [];
};

8.5.1 The DOMParser interface

The DOMParser interface allows authors to create new Document objects by parsing strings, as either HTML or XML.

parser = new DOMParser()

DOMParser/DOMParser

Support in all current engines.

Firefox1+Safari1.3+Chrome1+
Opera8+Edge79+
Edge (Legacy)12+Internet Explorer9+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android10.1+

Constructs a new DOMParser object.

document = parser.parseFromString(string, type)

DOMParser/parseFromString

Support in all current engines.

Firefox1+Safari1.3+Chrome1+
Opera8+Edge79+
Edge (Legacy)12+Internet Explorer9+
Firefox Android?Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android10.1+

Parses string using either the HTML or XML parser, according to type, and returns the resulting Document. type can be "text/html" (which will invoke the HTML parser), or any of "text/xml", "application/xml", "application/xhtml+xml", or "image/svg+xml" (which will invoke the XML parser).

For the XML parser, if string cannot be parsed, then the returned Document will contain elements describing the resulting error.

Note that script elements are not evaluated during parsing, and the resulting document's encoding will always be UTF-8. The document's URL will be inherited from parser's relevant global object.

Values other than the above for type will cause a TypeError exception to be thrown.

The design of DOMParser, as a class that needs to be constructed and then have its parseFromString() method called, is an unfortunate historical artifact. If we were designing this functionality today it would be a standalone function. For parsing HTML, the modern alternative is Document.parseHTMLUnsafe().

This method performs no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes.

[Exposed=Window]
interface DOMParser {
  constructor();

  [NewObject] Document parseFromString(HTMLString string, DOMParserSupportedType type);
};

enum DOMParserSupportedType {
  "text/html",
  "text/xml",
  "application/xml",
  "application/xhtml+xml",
  "image/svg+xml"
};

The new DOMParser() constructor steps are to do nothing.

The parseFromString(string, type) method steps are:

  1. Let document be a new Document, whose content type is type and URL is this's relevant global object's associated Document's URL.

    The document's encoding will be left as its default, of UTF-8. In particular, any XML declarations or meta elements found while parsing string will have no effect.

  2. Switch on type:

    "text/html"
    1. Parse HTML from a string given document and string.

    Since document does not have a browsing context, scripting is disabled.

    Otherwise
    1. Create an XML parser parse, associated with document, and with XML scripting support disabled.

    2. Parse string using parser.

    3. If the previous step resulted in an XML well-formedness or XML namespace well-formedness error, then:

      1. Assert: document has no child nodes.

      2. Let root be the result of creating an element given document, "parsererror", and "http://www.mozilla.org/newlayout/xml/parsererror.xml".

      3. Optionally, add attributes or children to root to describe the nature of the parsing error.

      4. Append root to document.

  3. Return document.

To parse HTML from a string, given a document Document and a string html:

  1. Set document's type to "html".

  2. Create an HTML parser parser, associated with document.

  3. Place html into the input stream for parser. The encoding confidence is irrelevant.

  4. Start parser and let it run until it has consumed all the characters just inserted into the input stream.

    This might mutate the document's mode.

8.5.2 Unsafe HTML parsing methods

element.setHTMLUnsafe(html)

Parses html using the HTML parser, and replaces the children of element with the result. element provides context for the HTML parser.

shadowRoot.setHTMLUnsafe(html)

Parses html using the HTML parser, and replaces the children of shadowRoot with the result. shadowRoot's host provides context for the HTML parser.

doc = Document.parseHTMLUnsafe(html)

Parses html using the HTML parser, and returns the resulting Document.

Note that script elements are not evaluated during parsing, and the resulting document's encoding will always be UTF-8. The document's URL will be about:blank.

These methods perform no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes.

Element's setHTMLUnsafe(html) method steps are:

  1. Let target be this's template contents if this is a template element; otherwise this.

  2. Unsafely set HTML given target, this, and html.

ShadowRoot's setHTMLUnsafe(html) method steps are to unsafely set HTML given this, this's shadow host, and html.

To unsafely set HTML, given an Element or DocumentFragment target, an Element contextElement, and a string html:

  1. Let newChildren be the result of the HTML fragment parsing algorithm given contextElement, html, and true.

  2. Let fragment be a new DocumentFragment whose node document is contextElement's node document.

  3. For each node in newChildren, append node to fragment.

  4. Replace all with fragment within target.


The static parseHTMLUnsafe(html) method steps are:

  1. Let document be a new Document, whose content type is "text/html".

    Since document does not have a browsing context, scripting is disabled.

  2. Set document's allow declarative shadow roots to true.

  3. Parse HTML from a string given document and html.

  4. Return document.

8.5.3 HTML serialization methods

html = element.getHTML({ serializableShadowRoots, shadowRoots })

Returns the result of serializing element to HTML. Shadow roots within element are serialized according to the provided options:

If neither option is provided, then no shadow roots are serialized.

html = shadowRoot.getHTML({ serializableShadowRoots, shadowRoots })

Returns the result of serializing shadowRoot to HTML, using its shadow host as the context element. Shadow roots within shadowRoot are serialized according to the provided options, as above.

Element's getHTML(options) method steps are to return the result of HTML fragment serialization algorithm with this, options["serializableShadowRoots"], and options["shadowRoots"].

ShadowRoot's getHTML(options) method steps are to return the result of HTML fragment serialization algorithm with this, options["serializableShadowRoots"], and options["shadowRoots"].

8.5.4 The innerHTML property

The innerHTML property has a number of outstanding issues in the DOM Parsing and Serialization issue tracker, documenting various problems with its specification.

element.innerHTML

Returns a fragment of HTML or XML that represents the element's contents.

In the case of an XML document, throws a "InvalidStateError" DOMException if the element cannot be serialized to XML.

element.innerHTML = value

Replaces the contents of the element with nodes parsed from the given string.

In the case of an XML document, throws a "SyntaxError" DOMException if the given string is not well-formed.

shadowRoot.innerHTML

Returns a fragment of HTML that represents the shadow roots's contents.

shadowRoot.innerHTML = value

Replaces the contents of the shadow root with nodes parsed from the given string.

These properties' setters perform no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes.

The fragment serializing algorithm steps, given an Element or DocumentFragment node and a boolean require well-formed, are:

  1. Let context document be node's node document.

  2. If context document is an HTML document, return the result of HTML fragment serialization algorithm with node, false, and « ».

  3. Return the XML serialization of node given require well-formed.

The fragment parsing algorithm steps, given an Element or DocumentFragment context and a string markup, are:

  1. Let algorithm be the HTML fragment parsing algorithm.

  2. If context's node document is an XML document, then set algorithm to the XML fragment parsing algorithm.

  3. Let new children be the result of invoking algorithm given markup, with context set to context.

  4. Let fragment be a new DocumentFragment whose node document is context's node document.

  5. Append each Node in new children to fragment (in tree order).

    This ensures the node document for the new nodes is correct.

  6. Return fragment.

Element's innerHTML getter steps are to return the result of running fragment serializing algorithm steps with this and true.

ShadowRoot's innerHTML getter steps are to return the result of running fragment serializing algorithm steps with this and true.

Element's innerHTML setter steps are:

  1. Let context be this.

  2. Let fragment be the result of invoking the fragment parsing algorithm steps with context and the given value.

  3. If context is a template element, then set context to the template element's template contents (a DocumentFragment).

    Setting innerHTML on a template element will replace all the nodes in its template contents rather than its children.

  4. Replace all with fragment within context.

ShadowRoot's innerHTML setter steps are:

  1. Let context be this's host.

  2. Let fragment be the result of invoking the fragment parsing algorithm steps with context and the given value.

  3. Replace all with fragment within this.

8.5.5 The outerHTML property

The outerHTML property has a number of outstanding issues in the DOM Parsing and Serialization issue tracker, documenting various problems with its specification.

element.outerHTML

Returns a fragment of HTML or XML that represents the element and its contents.

In the case of an XML document, throws a "InvalidStateError" DOMException if the element cannot be serialized to XML.

element.outerHTML = value

Replaces the element with nodes parsed from the given string.

In the case of an XML document, throws a "SyntaxError" DOMException if the given string is not well-formed.

Throws a "NoModificationAllowedError" DOMException if the parent of the element is a Document.

This property's setter performs no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes.

Element's outerHTML getter steps are:

  1. Let element be a fictional node whose only child is this.

  2. Return the result of running fragment serializing algorithm steps with element and true.

Element's outerHTML setter steps are:

  1. Let parent be this's parent.

  2. If parent is null, return. There would be no way to obtain a reference to the nodes created even if the remaining steps were run.

  3. If parent is a Document, throw a "NoModificationAllowedError" DOMException.

  4. If parent is a DocumentFragment, set parent to the result of creating an element given this's node document, body, and the HTML namespace.

  5. Let fragment be the result of invoking the fragment parsing algorithm steps given parent and the given value.

  6. Replace this with fragment within this's parent.

8.5.6 The insertAdjacentHTML() method

The insertAdjacentHTML() method has a number of outstanding issues in the DOM Parsing and Serialization issue tracker, documenting various problems with its specification.

element.insertAdjacentHTML(position, string)

Parses string as HTML or XML and inserts the resulting nodes into the tree in the position given by the position argument, as follows:

"beforebegin"
Before the element itself (i.e., after element's previous sibling)
"afterbegin"
Just inside the element, before its first child.
"beforeend"
Just inside the element, after its last child.
"afterend"
After the element itself (i.e., before element's next sibling)

Throws a "SyntaxError" DOMException if the arguments have invalid values (e.g., in the case of an XML document, if the given string is not well-formed).

Throws a "NoModificationAllowedError" DOMException if the given position isn't possible (e.g. inserting elements after the root element of a Document).

This method performs no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes.

Element's insertAdjacentHTML(position, string) method steps are:

  1. Let context be null.

  2. Use the first matching item from this list:

    If position is an ASCII case-insensitive match for the string "beforebegin"
    If position is an ASCII case-insensitive match for the string "afterend"
    1. Set context to this's parent.

    2. If context is null or a Document, throw a "NoModificationAllowedError" DOMException.

    If position is an ASCII case-insensitive match for the string "afterbegin"
    If position is an ASCII case-insensitive match for the string "beforeend"
    Set context to this.
    Otherwise

    Throw a "SyntaxError" DOMException.

  3. If context is not an Element or all of the following are true:

    set context to the result of creating an element given this's node document, body, and the HTML namespace.

  4. Let fragment be the result of invoking the fragment parsing algorithm steps with context and string.

  5. Use the first matching item from this list:
    If position is an ASCII case-insensitive match for the string "beforebegin"

    Insert fragment into this's parent before this.

    If position is an ASCII case-insensitive match for the string "afterend"

    Insert fragment into this before its first child.

    If position is an ASCII case-insensitive match for the string "afterbegin"

    Append fragment to this.

    If position is an ASCII case-insensitive match for the string "beforeend"

    Insert fragment into this's parent before this's next sibling.

As with other direct Node-manipulation APIs (and unlike innerHTML), insertAdjacentHTML() does not include any special handling for template elements. In most cases you will want to use templateEl.content.insertAdjacentHTML() instead of directly manipulating the child nodes of a template element.

8.5.7 The createContextualFragment() method

The createContextualFragment() method has a number of outstanding issues in the DOM Parsing and Serialization issue tracker, documenting various problems with its specification.

docFragment = range.createContextualFragment(string)

Returns a DocumentFragment created from the markup string string using range's start node as the context in which fragment is parsed.

This method performs no sanitization to remove potentially-dangerous elements and attributes like script or event handler content attributes.

partial interface Range {
  [CEReactions, NewObject] DocumentFragment createContextualFragment(HTMLString string);
};

Range's createContextualFragment(string) method steps are:

  1. Let node be this's start node.

  2. Let element be null.

  3. If node implements Element, set element to node.

  4. Otherwise, if node implements Text or Comment, set element to node's parent element.

  5. If element is null or all of the following are true:

    then set element to the result of creating an element given this's node document, body, and the HTML namespace.

  6. Let fragment node be the result of invoking the fragment parsing algorithm steps with element and string.

  7. For each script of fragment node's script element descendants:

    1. Set script's already started to false.

    2. Set script's parser document to null.

  8. Return fragment node.