projen
Version:
CDK for software projects
1,145 lines • 51.1 kB
JavaScript
"use strict";
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spread = (this && this.__spread) || function () {
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
return ar;
};
Object.defineProperty(exports, "__esModule", { value: true });
var DOMImpl_1 = require("../dom/DOMImpl");
var DOMException_1 = require("../dom/DOMException");
var interfaces_1 = require("../dom/interfaces");
var util_1 = require("../util");
var util_2 = require("@oozcitak/util");
var infra_1 = require("@oozcitak/infra");
var CustomElementAlgorithm_1 = require("./CustomElementAlgorithm");
var TreeAlgorithm_1 = require("./TreeAlgorithm");
var NodeIteratorAlgorithm_1 = require("./NodeIteratorAlgorithm");
var ShadowTreeAlgorithm_1 = require("./ShadowTreeAlgorithm");
var MutationObserverAlgorithm_1 = require("./MutationObserverAlgorithm");
var DOMAlgorithm_1 = require("./DOMAlgorithm");
var DocumentAlgorithm_1 = require("./DocumentAlgorithm");
/**
* Ensures pre-insertion validity of a node into a parent before a
* child.
*
* @param node - node to insert
* @param parent - parent node to receive node
* @param child - child node to insert node before
*/
function mutation_ensurePreInsertionValidity(node, parent, child) {
var e_1, _a, e_2, _b, e_3, _c, e_4, _d;
var parentNodeType = parent._nodeType;
var nodeNodeType = node._nodeType;
var childNodeType = child ? child._nodeType : null;
/**
* 1. If parent is not a Document, DocumentFragment, or Element node,
* throw a "HierarchyRequestError" DOMException.
*/
if (parentNodeType !== interfaces_1.NodeType.Document &&
parentNodeType !== interfaces_1.NodeType.DocumentFragment &&
parentNodeType !== interfaces_1.NodeType.Element)
throw new DOMException_1.HierarchyRequestError("Only document, document fragment and element nodes can contain child nodes. Parent node is " + parent.nodeName + ".");
/**
* 2. If node is a host-including inclusive ancestor of parent, throw a
* "HierarchyRequestError" DOMException.
*/
if (TreeAlgorithm_1.tree_isHostIncludingAncestorOf(parent, node, true))
throw new DOMException_1.HierarchyRequestError("The node to be inserted cannot be an inclusive ancestor of parent node. Node is " + node.nodeName + ", parent node is " + parent.nodeName + ".");
/**
* 3. If child is not null and its parent is not parent, then throw a
* "NotFoundError" DOMException.
*/
if (child !== null && child._parent !== parent)
throw new DOMException_1.NotFoundError("The reference child node cannot be found under parent node. Child node is " + child.nodeName + ", parent node is " + parent.nodeName + ".");
/**
* 4. If node is not a DocumentFragment, DocumentType, Element, Text,
* ProcessingInstruction, or Comment node, throw a "HierarchyRequestError"
* DOMException.
*/
if (nodeNodeType !== interfaces_1.NodeType.DocumentFragment &&
nodeNodeType !== interfaces_1.NodeType.DocumentType &&
nodeNodeType !== interfaces_1.NodeType.Element &&
nodeNodeType !== interfaces_1.NodeType.Text &&
nodeNodeType !== interfaces_1.NodeType.ProcessingInstruction &&
nodeNodeType !== interfaces_1.NodeType.CData &&
nodeNodeType !== interfaces_1.NodeType.Comment)
throw new DOMException_1.HierarchyRequestError("Only document fragment, document type, element, text, processing instruction, cdata section or comment nodes can be inserted. Node is " + node.nodeName + ".");
/**
* 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"
* DOMException.
*/
if (nodeNodeType === interfaces_1.NodeType.Text &&
parentNodeType === interfaces_1.NodeType.Document)
throw new DOMException_1.HierarchyRequestError("Cannot insert a text node as a child of a document node. Node is " + node.nodeName + ".");
if (nodeNodeType === interfaces_1.NodeType.DocumentType &&
parentNodeType !== interfaces_1.NodeType.Document)
throw new DOMException_1.HierarchyRequestError("A document type node can only be inserted under a document node. Parent node is " + parent.nodeName + ".");
/**
* 6. If parent is a document, and any of the statements below, switched on
* node, are true, throw a "HierarchyRequestError" DOMException.
* - 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.
*/
if (parentNodeType === interfaces_1.NodeType.Document) {
if (nodeNodeType === interfaces_1.NodeType.DocumentFragment) {
var eleCount = 0;
try {
for (var _e = __values(node._children), _f = _e.next(); !_f.done; _f = _e.next()) {
var childNode = _f.value;
if (childNode._nodeType === interfaces_1.NodeType.Element)
eleCount++;
else if (childNode._nodeType === interfaces_1.NodeType.Text)
throw new DOMException_1.HierarchyRequestError("Cannot insert text a node as a child of a document node. Node is " + childNode.nodeName + ".");
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_f && !_f.done && (_a = _e.return)) _a.call(_e);
}
finally { if (e_1) throw e_1.error; }
}
if (eleCount > 1) {
throw new DOMException_1.HierarchyRequestError("A document node can only have one document element node. Document fragment to be inserted has " + eleCount + " element nodes.");
}
else if (eleCount === 1) {
try {
for (var _g = __values(parent._children), _h = _g.next(); !_h.done; _h = _g.next()) {
var ele = _h.value;
if (ele._nodeType === interfaces_1.NodeType.Element)
throw new DOMException_1.HierarchyRequestError("The document node already has a document element node.");
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
}
finally { if (e_2) throw e_2.error; }
}
if (child) {
if (childNodeType === interfaces_1.NodeType.DocumentType)
throw new DOMException_1.HierarchyRequestError("Cannot insert an element node before a document type node.");
var doctypeChild = child._nextSibling;
while (doctypeChild) {
if (doctypeChild._nodeType === interfaces_1.NodeType.DocumentType)
throw new DOMException_1.HierarchyRequestError("Cannot insert an element node before a document type node.");
doctypeChild = doctypeChild._nextSibling;
}
}
}
}
else if (nodeNodeType === interfaces_1.NodeType.Element) {
try {
for (var _j = __values(parent._children), _k = _j.next(); !_k.done; _k = _j.next()) {
var ele = _k.value;
if (ele._nodeType === interfaces_1.NodeType.Element)
throw new DOMException_1.HierarchyRequestError("Document already has a document element node. Node is " + node.nodeName + ".");
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (_k && !_k.done && (_c = _j.return)) _c.call(_j);
}
finally { if (e_3) throw e_3.error; }
}
if (child) {
if (childNodeType === interfaces_1.NodeType.DocumentType)
throw new DOMException_1.HierarchyRequestError("Cannot insert an element node before a document type node. Node is " + node.nodeName + ".");
var doctypeChild = child._nextSibling;
while (doctypeChild) {
if (doctypeChild._nodeType === interfaces_1.NodeType.DocumentType)
throw new DOMException_1.HierarchyRequestError("Cannot insert an element node before a document type node. Node is " + node.nodeName + ".");
doctypeChild = doctypeChild._nextSibling;
}
}
}
else if (nodeNodeType === interfaces_1.NodeType.DocumentType) {
try {
for (var _l = __values(parent._children), _m = _l.next(); !_m.done; _m = _l.next()) {
var ele = _m.value;
if (ele._nodeType === interfaces_1.NodeType.DocumentType)
throw new DOMException_1.HierarchyRequestError("Document already has a document type node. Node is " + node.nodeName + ".");
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (_m && !_m.done && (_d = _l.return)) _d.call(_l);
}
finally { if (e_4) throw e_4.error; }
}
if (child) {
var elementChild = child._previousSibling;
while (elementChild) {
if (elementChild._nodeType === interfaces_1.NodeType.Element)
throw new DOMException_1.HierarchyRequestError("Cannot insert a document type node before an element node. Node is " + node.nodeName + ".");
elementChild = elementChild._previousSibling;
}
}
else {
var elementChild = parent._firstChild;
while (elementChild) {
if (elementChild._nodeType === interfaces_1.NodeType.Element)
throw new DOMException_1.HierarchyRequestError("Cannot insert a document type node before an element node. Node is " + node.nodeName + ".");
elementChild = elementChild._nextSibling;
}
}
}
}
}
exports.mutation_ensurePreInsertionValidity = mutation_ensurePreInsertionValidity;
/**
* Ensures pre-insertion validity of a node into a parent before a
* child, then adopts the node to the tree and inserts it.
*
* @param node - node to insert
* @param parent - parent node to receive node
* @param child - child node to insert node before
*/
function mutation_preInsert(node, parent, child) {
/**
* 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.
*/
mutation_ensurePreInsertionValidity(node, parent, child);
var referenceChild = child;
if (referenceChild === node)
referenceChild = node._nextSibling;
DocumentAlgorithm_1.document_adopt(node, parent._nodeDocument);
mutation_insert(node, parent, referenceChild);
return node;
}
exports.mutation_preInsert = mutation_preInsert;
/**
* Inserts a node into a parent node before the given child node.
*
* @param node - node to insert
* @param parent - parent node to receive node
* @param child - child node to insert node before
* @param suppressObservers - whether to notify observers
*/
function mutation_insert(node, parent, child, suppressObservers) {
var e_5, _a;
// Optimized common case
if (child === null && node._nodeType !== interfaces_1.NodeType.DocumentFragment) {
mutation_insert_single(node, parent, suppressObservers);
return;
}
/**
* 1. Let count be the number of children of node if it is a
* DocumentFragment node, and one otherwise.
*/
var count = (node._nodeType === interfaces_1.NodeType.DocumentFragment ?
node._children.size : 1);
/**
* 2. If child is non-null, then:
*/
if (child !== null) {
/**
* 2.1. For each live range whose start node is parent and start
* offset is greater than child's index, increase its start
* offset by count.
* 2.2. For each live range whose end node is parent and end
* offset is greater than child's index, increase its end
* offset by count.
*/
if (DOMImpl_1.dom.rangeList.size !== 0) {
var index_1 = TreeAlgorithm_1.tree_index(child);
try {
for (var _b = __values(DOMImpl_1.dom.rangeList), _c = _b.next(); !_c.done; _c = _b.next()) {
var range = _c.value;
if (range._start[0] === parent && range._start[1] > index_1) {
range._start[1] += count;
}
if (range._end[0] === parent && range._end[1] > index_1) {
range._end[1] += count;
}
}
}
catch (e_5_1) { e_5 = { error: e_5_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
}
finally { if (e_5) throw e_5.error; }
}
}
}
/**
* 3. Let nodes be node’s children, if node is a DocumentFragment node;
* otherwise « node ».
*/
var nodes = node._nodeType === interfaces_1.NodeType.DocumentFragment ? new (Array.bind.apply(Array, __spread([void 0], node._children)))() : [node];
/**
* 4. If node is a DocumentFragment node, remove its children with the
* suppress observers flag set.
*/
if (node._nodeType === interfaces_1.NodeType.DocumentFragment) {
while (node._firstChild) {
mutation_remove(node._firstChild, node, true);
}
}
/**
* 5. If node is a DocumentFragment node, then queue a tree mutation record
* for node with « », nodes, null, and null.
*/
if (DOMImpl_1.dom.features.mutationObservers) {
if (node._nodeType === interfaces_1.NodeType.DocumentFragment) {
MutationObserverAlgorithm_1.observer_queueTreeMutationRecord(node, [], nodes, null, null);
}
}
/**
* 6. Let previousSibling be child’s previous sibling or parent’s last
* child if child is null.
*/
var previousSibling = (child ? child._previousSibling : parent._lastChild);
var index = child === null ? -1 : TreeAlgorithm_1.tree_index(child);
/**
* 7. For each node in nodes, in tree order:
*/
for (var i = 0; i < nodes.length; i++) {
var node_1 = nodes[i];
if (util_1.Guard.isElementNode(node_1)) {
// set document element node
if (util_1.Guard.isDocumentNode(parent)) {
parent._documentElement = node_1;
}
// mark that the document has namespaces
if (!node_1._nodeDocument._hasNamespaces && (node_1._namespace !== null ||
node_1._namespacePrefix !== null)) {
node_1._nodeDocument._hasNamespaces = true;
}
}
/**
* 7.1. If child is null, then append node to parent’s children.
* 7.2. Otherwise, insert node into parent’s children before child’s
* index.
*/
node_1._parent = parent;
if (child === null) {
infra_1.set.append(parent._children, node_1);
}
else {
infra_1.set.insert(parent._children, node_1, index);
index++;
}
// assign siblings and children for quick lookups
if (parent._firstChild === null) {
node_1._previousSibling = null;
node_1._nextSibling = null;
parent._firstChild = node_1;
parent._lastChild = node_1;
}
else {
var prev = (child ? child._previousSibling : parent._lastChild);
var next = (child ? child : null);
node_1._previousSibling = prev;
node_1._nextSibling = next;
if (prev)
prev._nextSibling = node_1;
if (next)
next._previousSibling = node_1;
if (!prev)
parent._firstChild = node_1;
if (!next)
parent._lastChild = node_1;
}
/**
* 7.3. If parent is a shadow host and node is a slotable, then
* assign a slot for node.
*/
if (DOMImpl_1.dom.features.slots) {
if (parent._shadowRoot !== null && util_1.Guard.isSlotable(node_1)) {
ShadowTreeAlgorithm_1.shadowTree_assignASlot(node_1);
}
}
/**
* 7.4. If node is a Text node, run the child text content change
* steps for parent.
*/
if (DOMImpl_1.dom.features.steps) {
if (util_1.Guard.isTextNode(node_1)) {
DOMAlgorithm_1.dom_runChildTextContentChangeSteps(parent);
}
}
/**
* 7.5. If parent's root is a shadow root, and parent is a slot
* whose assigned nodes is the empty list, then run signal
* a slot change for parent.
*/
if (DOMImpl_1.dom.features.slots) {
if (util_1.Guard.isShadowRoot(TreeAlgorithm_1.tree_rootNode(parent)) &&
util_1.Guard.isSlot(parent) && util_2.isEmpty(parent._assignedNodes)) {
ShadowTreeAlgorithm_1.shadowTree_signalASlotChange(parent);
}
}
/**
* 7.6. Run assign slotables for a tree with node's root.
*/
if (DOMImpl_1.dom.features.slots) {
ShadowTreeAlgorithm_1.shadowTree_assignSlotablesForATree(TreeAlgorithm_1.tree_rootNode(node_1));
}
/**
* 7.7. For each shadow-including inclusive descendant
* inclusiveDescendant of node, in shadow-including tree
* order:
*/
var inclusiveDescendant = TreeAlgorithm_1.tree_getFirstDescendantNode(node_1, true, true);
while (inclusiveDescendant !== null) {
/**
* 7.7.1. Run the insertion steps with inclusiveDescendant.
*/
if (DOMImpl_1.dom.features.steps) {
DOMAlgorithm_1.dom_runInsertionSteps(inclusiveDescendant);
}
if (DOMImpl_1.dom.features.customElements) {
/**
* 7.7.2. If inclusiveDescendant is connected, then:
*/
if (util_1.Guard.isElementNode(inclusiveDescendant) &&
ShadowTreeAlgorithm_1.shadowTree_isConnected(inclusiveDescendant)) {
if (util_1.Guard.isCustomElementNode(inclusiveDescendant)) {
/**
* 7.7.2.1. If inclusiveDescendant is custom, then enqueue a custom
* element callback reaction with inclusiveDescendant, callback name
* "connectedCallback", and an empty argument list.
*/
CustomElementAlgorithm_1.customElement_enqueueACustomElementCallbackReaction(inclusiveDescendant, "connectedCallback", []);
}
else {
/**
* 7.7.2.2. Otherwise, try to upgrade inclusiveDescendant.
*/
CustomElementAlgorithm_1.customElement_tryToUpgrade(inclusiveDescendant);
}
}
}
inclusiveDescendant = TreeAlgorithm_1.tree_getNextDescendantNode(node_1, inclusiveDescendant, true, true);
}
}
/**
* 8. If suppress observers flag is unset, then queue a tree mutation record
* for parent with nodes, « », previousSibling, and child.
*/
if (DOMImpl_1.dom.features.mutationObservers) {
if (!suppressObservers) {
MutationObserverAlgorithm_1.observer_queueTreeMutationRecord(parent, nodes, [], previousSibling, child);
}
}
}
exports.mutation_insert = mutation_insert;
/**
* Inserts a node into a parent node. Optimized routine for the common case where
* node is not a document fragment node and it has no child nodes.
*
* @param node - node to insert
* @param parent - parent node to receive node
* @param suppressObservers - whether to notify observers
*/
function mutation_insert_single(node, parent, suppressObservers) {
/**
* 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, then:
* 2.1. For each live range whose start node is parent and start
* offset is greater than child's index, increase its start
* offset by count.
* 2.2. For each live 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;
* otherwise « node ».
* 4. If node is a DocumentFragment node, remove its children with the
* suppress observers flag set.
* 5. If node is a DocumentFragment node, then queue a tree mutation record
* for node with « », nodes, null, and null.
*/
/**
* 6. Let previousSibling be child’s previous sibling or parent’s last
* child if child is null.
*/
var previousSibling = parent._lastChild;
// set document element node
if (util_1.Guard.isElementNode(node)) {
// set document element node
if (util_1.Guard.isDocumentNode(parent)) {
parent._documentElement = node;
}
// mark that the document has namespaces
if (!node._nodeDocument._hasNamespaces && (node._namespace !== null ||
node._namespacePrefix !== null)) {
node._nodeDocument._hasNamespaces = true;
}
}
/**
* 7. For each node in nodes, in tree order:
* 7.1. If child is null, then append node to parent’s children.
* 7.2. Otherwise, insert node into parent’s children before child’s
* index.
*/
node._parent = parent;
parent._children.add(node);
// assign siblings and children for quick lookups
if (parent._firstChild === null) {
node._previousSibling = null;
node._nextSibling = null;
parent._firstChild = node;
parent._lastChild = node;
}
else {
var prev = parent._lastChild;
node._previousSibling = prev;
node._nextSibling = null;
if (prev)
prev._nextSibling = node;
if (!prev)
parent._firstChild = node;
parent._lastChild = node;
}
/**
* 7.3. If parent is a shadow host and node is a slotable, then
* assign a slot for node.
*/
if (DOMImpl_1.dom.features.slots) {
if (parent._shadowRoot !== null && util_1.Guard.isSlotable(node)) {
ShadowTreeAlgorithm_1.shadowTree_assignASlot(node);
}
}
/**
* 7.4. If node is a Text node, run the child text content change
* steps for parent.
*/
if (DOMImpl_1.dom.features.steps) {
if (util_1.Guard.isTextNode(node)) {
DOMAlgorithm_1.dom_runChildTextContentChangeSteps(parent);
}
}
/**
* 7.5. If parent's root is a shadow root, and parent is a slot
* whose assigned nodes is the empty list, then run signal
* a slot change for parent.
*/
if (DOMImpl_1.dom.features.slots) {
if (util_1.Guard.isShadowRoot(TreeAlgorithm_1.tree_rootNode(parent)) &&
util_1.Guard.isSlot(parent) && util_2.isEmpty(parent._assignedNodes)) {
ShadowTreeAlgorithm_1.shadowTree_signalASlotChange(parent);
}
}
/**
* 7.6. Run assign slotables for a tree with node's root.
*/
if (DOMImpl_1.dom.features.slots) {
ShadowTreeAlgorithm_1.shadowTree_assignSlotablesForATree(TreeAlgorithm_1.tree_rootNode(node));
}
/**
* 7.7. For each shadow-including inclusive descendant
* inclusiveDescendant of node, in shadow-including tree
* order:
* 7.7.1. Run the insertion steps with inclusiveDescendant.
*/
if (DOMImpl_1.dom.features.steps) {
DOMAlgorithm_1.dom_runInsertionSteps(node);
}
if (DOMImpl_1.dom.features.customElements) {
/**
* 7.7.2. If inclusiveDescendant is connected, then:
*/
if (util_1.Guard.isElementNode(node) &&
ShadowTreeAlgorithm_1.shadowTree_isConnected(node)) {
if (util_1.Guard.isCustomElementNode(node)) {
/**
* 7.7.2.1. If inclusiveDescendant is custom, then enqueue a custom
* element callback reaction with inclusiveDescendant, callback name
* "connectedCallback", and an empty argument list.
*/
CustomElementAlgorithm_1.customElement_enqueueACustomElementCallbackReaction(node, "connectedCallback", []);
}
else {
/**
* 7.7.2.2. Otherwise, try to upgrade inclusiveDescendant.
*/
CustomElementAlgorithm_1.customElement_tryToUpgrade(node);
}
}
}
/**
* 8. If suppress observers flag is unset, then queue a tree mutation record
* for parent with nodes, « », previousSibling, and child.
*/
if (DOMImpl_1.dom.features.mutationObservers) {
if (!suppressObservers) {
MutationObserverAlgorithm_1.observer_queueTreeMutationRecord(parent, [node], [], previousSibling, null);
}
}
}
/**
* Appends a node to the children of a parent node.
*
* @param node - a node
* @param parent - the parent to receive node
*/
function mutation_append(node, parent) {
/**
* To append a node to a parent, pre-insert node into parent before null.
*/
return mutation_preInsert(node, parent, null);
}
exports.mutation_append = mutation_append;
/**
* Replaces a node with another node.
*
* @param child - child node to remove
* @param node - node to insert
* @param parent - parent node to receive node
*/
function mutation_replace(child, node, parent) {
var e_6, _a, e_7, _b, e_8, _c, e_9, _d;
/**
* 1. If parent is not a Document, DocumentFragment, or Element node,
* throw a "HierarchyRequestError" DOMException.
*/
if (parent._nodeType !== interfaces_1.NodeType.Document &&
parent._nodeType !== interfaces_1.NodeType.DocumentFragment &&
parent._nodeType !== interfaces_1.NodeType.Element)
throw new DOMException_1.HierarchyRequestError("Only document, document fragment and element nodes can contain child nodes. Parent node is " + parent.nodeName + ".");
/**
* 2. If node is a host-including inclusive ancestor of parent, throw a
* "HierarchyRequestError" DOMException.
*/
if (TreeAlgorithm_1.tree_isHostIncludingAncestorOf(parent, node, true))
throw new DOMException_1.HierarchyRequestError("The node to be inserted cannot be an ancestor of parent node. Node is " + node.nodeName + ", parent node is " + parent.nodeName + ".");
/**
* 3. If child’s parent is not parent, then throw a "NotFoundError"
* DOMException.
*/
if (child._parent !== parent)
throw new DOMException_1.NotFoundError("The reference child node cannot be found under parent node. Child node is " + child.nodeName + ", parent node is " + parent.nodeName + ".");
/**
* 4. If node is not a DocumentFragment, DocumentType, Element, Text,
* ProcessingInstruction, or Comment node, throw a "HierarchyRequestError"
* DOMException.
*/
if (node._nodeType !== interfaces_1.NodeType.DocumentFragment &&
node._nodeType !== interfaces_1.NodeType.DocumentType &&
node._nodeType !== interfaces_1.NodeType.Element &&
node._nodeType !== interfaces_1.NodeType.Text &&
node._nodeType !== interfaces_1.NodeType.ProcessingInstruction &&
node._nodeType !== interfaces_1.NodeType.CData &&
node._nodeType !== interfaces_1.NodeType.Comment)
throw new DOMException_1.HierarchyRequestError("Only document fragment, document type, element, text, processing instruction, cdata section or comment nodes can be inserted. Node is " + node.nodeName + ".");
/**
* 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"
* DOMException.
*/
if (node._nodeType === interfaces_1.NodeType.Text &&
parent._nodeType === interfaces_1.NodeType.Document)
throw new DOMException_1.HierarchyRequestError("Cannot insert a text node as a child of a document node. Node is " + node.nodeName + ".");
if (node._nodeType === interfaces_1.NodeType.DocumentType &&
parent._nodeType !== interfaces_1.NodeType.Document)
throw new DOMException_1.HierarchyRequestError("A document type node can only be inserted under a document node. Parent node is " + parent.nodeName + ".");
/**
* 6. If parent is a document, and any of the statements below, switched on
* node, are true, throw a "HierarchyRequestError" DOMException.
* - 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.
*/
if (parent._nodeType === interfaces_1.NodeType.Document) {
if (node._nodeType === interfaces_1.NodeType.DocumentFragment) {
var eleCount = 0;
try {
for (var _e = __values(node._children), _f = _e.next(); !_f.done; _f = _e.next()) {
var childNode = _f.value;
if (childNode._nodeType === interfaces_1.NodeType.Element)
eleCount++;
else if (childNode._nodeType === interfaces_1.NodeType.Text)
throw new DOMException_1.HierarchyRequestError("Cannot insert text a node as a child of a document node. Node is " + childNode.nodeName + ".");
}
}
catch (e_6_1) { e_6 = { error: e_6_1 }; }
finally {
try {
if (_f && !_f.done && (_a = _e.return)) _a.call(_e);
}
finally { if (e_6) throw e_6.error; }
}
if (eleCount > 1) {
throw new DOMException_1.HierarchyRequestError("A document node can only have one document element node. Document fragment to be inserted has " + eleCount + " element nodes.");
}
else if (eleCount === 1) {
try {
for (var _g = __values(parent._children), _h = _g.next(); !_h.done; _h = _g.next()) {
var ele = _h.value;
if (ele._nodeType === interfaces_1.NodeType.Element && ele !== child)
throw new DOMException_1.HierarchyRequestError("The document node already has a document element node.");
}
}
catch (e_7_1) { e_7 = { error: e_7_1 }; }
finally {
try {
if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
}
finally { if (e_7) throw e_7.error; }
}
var doctypeChild = child._nextSibling;
while (doctypeChild) {
if (doctypeChild._nodeType === interfaces_1.NodeType.DocumentType)
throw new DOMException_1.HierarchyRequestError("Cannot insert an element node before a document type node.");
doctypeChild = doctypeChild._nextSibling;
}
}
}
else if (node._nodeType === interfaces_1.NodeType.Element) {
try {
for (var _j = __values(parent._children), _k = _j.next(); !_k.done; _k = _j.next()) {
var ele = _k.value;
if (ele._nodeType === interfaces_1.NodeType.Element && ele !== child)
throw new DOMException_1.HierarchyRequestError("Document already has a document element node. Node is " + node.nodeName + ".");
}
}
catch (e_8_1) { e_8 = { error: e_8_1 }; }
finally {
try {
if (_k && !_k.done && (_c = _j.return)) _c.call(_j);
}
finally { if (e_8) throw e_8.error; }
}
var doctypeChild = child._nextSibling;
while (doctypeChild) {
if (doctypeChild._nodeType === interfaces_1.NodeType.DocumentType)
throw new DOMException_1.HierarchyRequestError("Cannot insert an element node before a document type node. Node is " + node.nodeName + ".");
doctypeChild = doctypeChild._nextSibling;
}
}
else if (node._nodeType === interfaces_1.NodeType.DocumentType) {
try {
for (var _l = __values(parent._children), _m = _l.next(); !_m.done; _m = _l.next()) {
var ele = _m.value;
if (ele._nodeType === interfaces_1.NodeType.DocumentType && ele !== child)
throw new DOMException_1.HierarchyRequestError("Document already has a document type node. Node is " + node.nodeName + ".");
}
}
catch (e_9_1) { e_9 = { error: e_9_1 }; }
finally {
try {
if (_m && !_m.done && (_d = _l.return)) _d.call(_l);
}
finally { if (e_9) throw e_9.error; }
}
var elementChild = child._previousSibling;
while (elementChild) {
if (elementChild._nodeType === interfaces_1.NodeType.Element)
throw new DOMException_1.HierarchyRequestError("Cannot insert a document type node before an element node. Node is " + node.nodeName + ".");
elementChild = elementChild._previousSibling;
}
}
}
/**
* 7. Let reference child be child’s next sibling.
* 8. If reference child is node, set it to node’s next sibling.
* 8. Let previousSibling be child’s previous sibling.
*/
var referenceChild = child._nextSibling;
if (referenceChild === node)
referenceChild = node._nextSibling;
var previousSibling = child._previousSibling;
/**
* 10. Adopt node into parent’s node document.
* 11. Let removedNodes be the empty list.
*/
DocumentAlgorithm_1.document_adopt(node, parent._nodeDocument);
var removedNodes = [];
/**
* 12. If child’s parent is not null, then:
*/
if (child._parent !== null) {
/**
* 12.1. Set removedNodes to [child].
* 12.2. Remove child from its parent with the suppress observers flag
* set.
*/
removedNodes.push(child);
mutation_remove(child, child._parent, true);
}
/**
* 13. Let nodes be node’s children if node is a DocumentFragment node;
* otherwise [node].
*/
var nodes = [];
if (node._nodeType === interfaces_1.NodeType.DocumentFragment) {
nodes = Array.from(node._children);
}
else {
nodes.push(node);
}
/**
* 14. Insert node into parent before reference child with the suppress
* observers flag set.
*/
mutation_insert(node, parent, referenceChild, true);
/**
* 15. Queue a tree mutation record for parent with nodes, removedNodes,
* previousSibling, and reference child.
*/
if (DOMImpl_1.dom.features.mutationObservers) {
MutationObserverAlgorithm_1.observer_queueTreeMutationRecord(parent, nodes, removedNodes, previousSibling, referenceChild);
}
/**
* 16. Return child.
*/
return child;
}
exports.mutation_replace = mutation_replace;
/**
* Replaces all nodes of a parent with the given node.
*
* @param node - node to insert
* @param parent - parent node to receive node
*/
function mutation_replaceAll(node, parent) {
var e_10, _a;
/**
* 1. If node is not null, adopt node into parent’s node document.
*/
if (node !== null) {
DocumentAlgorithm_1.document_adopt(node, parent._nodeDocument);
}
/**
* 2. Let removedNodes be parent’s children.
*/
var removedNodes = Array.from(parent._children);
/**
* 3. Let addedNodes be the empty list.
* 4. If node is DocumentFragment node, then set addedNodes to node’s
* children.
* 5. Otherwise, if node is non-null, set addedNodes to [node].
*/
var addedNodes = [];
if (node && node._nodeType === interfaces_1.NodeType.DocumentFragment) {
addedNodes = Array.from(node._children);
}
else if (node !== null) {
addedNodes.push(node);
}
try {
/**
* 6. Remove all parent’s children, in tree order, with the suppress
* observers flag set.
*/
for (var removedNodes_1 = __values(removedNodes), removedNodes_1_1 = removedNodes_1.next(); !removedNodes_1_1.done; removedNodes_1_1 = removedNodes_1.next()) {
var childNode = removedNodes_1_1.value;
mutation_remove(childNode, parent, true);
}
}
catch (e_10_1) { e_10 = { error: e_10_1 }; }
finally {
try {
if (removedNodes_1_1 && !removedNodes_1_1.done && (_a = removedNodes_1.return)) _a.call(removedNodes_1);
}
finally { if (e_10) throw e_10.error; }
}
/**
* 7. If node is not null, then insert node into parent before null with the
* suppress observers flag set.
*/
if (node !== null) {
mutation_insert(node, parent, null, true);
}
/**
* 8. Queue a tree mutation record for parent with addedNodes, removedNodes,
* null, and null.
*/
if (DOMImpl_1.dom.features.mutationObservers) {
MutationObserverAlgorithm_1.observer_queueTreeMutationRecord(parent, addedNodes, removedNodes, null, null);
}
}
exports.mutation_replaceAll = mutation_replaceAll;
/**
* Ensures pre-removal validity of a child node from a parent, then
* removes it.
*
* @param child - child node to remove
* @param parent - parent node
*/
function mutation_preRemove(child, parent) {
/**
* 1. If child’s parent is not parent, then throw a "NotFoundError"
* DOMException.
* 2. Remove child from parent.
* 3. Return child.
*/
if (child._parent !== parent)
throw new DOMException_1.NotFoundError("The child node cannot be found under parent node. Child node is " + child.nodeName + ", parent node is " + parent.nodeName + ".");
mutation_remove(child, parent);
return child;
}
exports.mutation_preRemove = mutation_preRemove;
/**
* Removes a child node from its parent.
*
* @param node - node to remove
* @param parent - parent node
* @param suppressObservers - whether to notify observers
*/
function mutation_remove(node, parent, suppressObservers) {
var e_11, _a, e_12, _b, e_13, _c, e_14, _d;
if (DOMImpl_1.dom.rangeList.size !== 0) {
/**
* 1. Let index be node’s index.
*/
var index = TreeAlgorithm_1.tree_index(node);
try {
/**
* 2. For each live range whose start node is an inclusive descendant of
* node, set its start to (parent, index).
* 3. For each live range whose end node is an inclusive descendant of
* node, set its end to (parent, index).
*/
for (var _e = __values(DOMImpl_1.dom.rangeList), _f = _e.next(); !_f.done; _f = _e.next()) {
var range = _f.value;
if (TreeAlgorithm_1.tree_isDescendantOf(node, range._start[0], true)) {
range._start = [parent, index];
}
if (TreeAlgorithm_1.tree_isDescendantOf(node, range._end[0], true)) {
range._end = [parent, index];
}
if (range._start[0] === parent && range._start[1] > index) {
range._start[1]--;
}
if (range._end[0] === parent && range._end[1] > index) {
range._end[1]--;
}
}
}
catch (e_11_1) { e_11 = { error: e_11_1 }; }
finally {
try {
if (_f && !_f.done && (_a = _e.return)) _a.call(_e);
}
finally { if (e_11) throw e_11.error; }
}
try {
/**
* 4. For each live range whose start node is parent and start offset is
* greater than index, decrease its start offset by 1.
* 5. For each live range whose end node is parent and end offset is greater
* than index, decrease its end offset by 1.
*/
for (var _g = __values(DOMImpl_1.dom.rangeList), _h = _g.next(); !_h.done; _h = _g.next()) {
var range = _h.value;
if (range._start[0] === parent && range._start[1] > index) {
range._start[1] -= 1;
}
if (range._end[0] === parent && range._end[1] > index) {
range._end[1] -= 1;
}
}
}
catch (e_12_1) { e_12 = { error: e_12_1 }; }
finally {
try {
if (_h && !_h.done && (_b = _g.return)) _b.call(_g);
}
finally { if (e_12) throw e_12.error; }
}
}
/**
* 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.
*/
if (DOMImpl_1.dom.features.steps) {
try {
for (var _j = __values(NodeIteratorAlgorithm_1.nodeIterator_iteratorList()), _k = _j.next(); !_k.done; _k = _j.next()) {
var iterator = _k.value;
if (iterator._root._nodeDocument === node._nodeDocument) {
DOMAlgorithm_1.dom_runNodeIteratorPreRemovingSteps(iterator, node);
}
}
}
catch (e_13_1) { e_13 = { error: e_13_1 }; }
finally {
try {
if (_k && !_k.done && (_c = _j.return)) _c.call(_j);
}
finally { if (e_13) throw e_13.error; }
}
}
/**
* 7. Let oldPreviousSibling be node’s previous sibling.
* 8. Let oldNextSibling be node’s next sibling.
*/
var oldPreviousSibling = node._previousSibling;
var oldNextSibling = node._nextSibling;
// set document element node
if (util_1.Guard.isDocumentNode(parent) && util_1.Guard.isElementNode(node)) {
parent._documentElement = null;
}
/**
* 9. Remove node from its parent’s children.
*/
node._parent = null;
parent._children.delete(node);
// assign siblings and children for quick lookups
var prev = node._previousSibling;
var next = node._nextSibling;
node._previousSibling = null;
node._nextSibling = null;
if (prev)
prev._nextSibling = next;
if (next)
next._previousSibling = prev;
if (!prev)
parent._firstChild = next;
if (!next)
parent._lastChild = prev;
/**
* 10. If node is assigned, then run assign slotables for node’s assigned
* slot.
*/
if (DOMImpl_1.dom.features.slots) {
if (util_1.Guard.isSlotable(node) && node._assignedSlot !== null && ShadowTreeAlgorithm_1.shadowTree_isAssigned(node)) {
ShadowTreeAlgorithm_1.shadowTree_assignSlotables(node._assignedSlot);
}
}
/**
* 11. If parent’s root is a shadow root, and parent is a slot whose
* assigned nodes is the empty list, then run signal a slot change for
* parent.
*/
if (DOMImpl_1.dom.features.slots) {
if (util_1.Guard.isShadowRoot(TreeAlgorithm_1.tree_rootNode(parent)) &&
util_1.Guard.isSlot(parent) && util_2.isEmpty(parent._assignedNodes)) {
ShadowTreeAlgorithm_1.shadowTree_signalASlotChange(parent);
}
}
/**
* 12. If node has an inclusive descendant that is a slot, then:
* 12.1. Run assign slotables for a tree with parent's root.
* 12.2. Run assign slotables for a tree with node.
*/
if (DOMImpl_1.dom.features.slots) {
var descendant_1 = TreeAlgorithm_1.tree_getFirstDescendantNode(node, true, false, function (e) { return util_1.Guard.isSlot(e); });
if (descendant_1 !== null) {
ShadowTreeAlgorithm_1.shadowTree_assignSlotablesForATree(TreeAlgorithm_1.tree_rootNode(parent));
ShadowTreeAlgorithm_1.shadowTree_assignSlotablesForATree(node);
}
}
/**
* 13. Run the removing steps with node and parent.
*/
if (DOMImpl_1.dom.features.steps) {
DOMAlgorithm_1.dom_runRemovingSteps(node, parent);
}
/**
* 14. If node is custom, then enqueue a custom element callback
* reaction with node, callback name "disconnectedCallback",
* and an empty argument list.
*/
if (DOMImpl_1.dom.features.customElements) {
if (util_1.Guard.isCustomElementNode(node)) {
CustomElementAlgorithm_1.customElement_enqueueACustomElementCallbackReaction(node, "disconnectedCallback", []);
}
}
/**
* 15. For each shadow-including descendant descendant of node,
* in shadow-including tree order, then:
*/
var descendant = TreeAlgorithm_1.tree_getFirstDescendantNode(node, false, true);
while (descendant !== null) {
/**
* 15.1. Run the removing steps with descendant.
*/
if (DOMImpl_1.dom.features.steps) {
DOMAlgorithm_1.dom_runRemovingSteps(descendant, node);
}
/**
* 15.2. If descendant is custom, then enqueue a custom element
* callback reaction with descendant, callback name
* "disconnectedCallback", and an empty argument list.
*/
if (DOMImpl_1.dom.features.customElements) {
if (util_1.Guard.isCustomElementNode(descendant)) {
CustomElementAlgorithm_1.customElement_enqueueACustomElementCallbackReaction(descendant, "disconnectedCallback", []);
}
}
descendant = TreeAlgorithm_1.tree_getNextDescendantNode(node, descendant, false, true);
}
/**
* 16. For each inclusive ancestor inclusiveAncestor of parent, and
* then for each registered of inclusiveAncestor's registered
* observer list, if registered's options's subtree is true,
* then append a new transient registered observer whose
* observer is registered's observer, options is registered's
* options, and source is registered to node's registered
* observer list.
*/
if (DOMImpl_1.dom.features.mutationObservers) {
var inclusiveAncestor = TreeAlgorithm_1.tree_getFirstAncestorNode(parent, true);
while (inclusiveAncestor !== null) {
try {
for (var _l = (e_14 = void 0, __values(inclusiveAncestor._registeredObserverList)), _m = _l.next(); !_m.done; _m = _l.next()) {
var registered = _m.value;
if (registered.options.subtree) {
node._registeredObserverList.push({
observer: registered.observer,
options: registered.options,
source: registered
});
}
}
}
catch (e_14_1) { e_14 = { error: e_14_1 }; }
finally {
try {
if (_m && !_m.done && (_d = _l.return)) _d.c