in packages/miniapp-runtime/src/dom/node.ts [148:212]
public insertBefore<T extends Node>(newChild: T, refChild?: Node | null, isReplace?: boolean): T {
if (newChild.nodeName === DOCUMENT_FRAGMENT) {
newChild.childNodes.reduceRight((previousValue, currentValue) => {
this.insertBefore(currentValue, previousValue);
return currentValue;
}, refChild);
return newChild;
}
// Parent release newChild
// - cleanRef: false (No need to clean eventSource, because newChild is about to be inserted)
// - update: true (Need to update parent.childNodes, because parent.childNodes is reordered)
newChild.remove({ cleanRef: false });
// Data structure
newChild.parentNode = this;
if (refChild) {
// insertBefore & replaceChild
const index = this.findIndex(refChild);
this.childNodes.splice(index, 0, newChild);
} else {
// appendChild
this.childNodes.push(newChild);
}
// Serialization
if (this._root) {
if (!refChild) {
// appendChild
const isOnlyChild = this.childNodes.length === 1;
if (isOnlyChild) {
this.updateChildNodes();
} else {
this.enqueueUpdate({
path: newChild._path,
value: this.hydrate(newChild),
});
}
} else if (isReplace) {
// replaceChild
this.enqueueUpdate({
path: newChild._path,
value: this.hydrate(newChild),
});
} else {
// insertBefore
this.updateChildNodes();
}
}
MutationObserver.record({
type: MutationRecordType.CHILD_LIST,
target: this,
addedNodes: [newChild],
removedNodes: isReplace
? [refChild as Node] /** replaceChild */
: [],
nextSibling: isReplace
? (refChild as Node).nextSibling /** replaceChild */
: (refChild || null), /** insertBefore & appendChild */
previousSibling: newChild.previousSibling,
});
return newChild;
}