packages/moon/src/executor/executor.js
function executePatch(patches) {
	for (let i = 0; i < patches.length; i++) {
		const patch = patches[i];

		switch (patch.type) {
			case patchTypes.updateText: {
				// Update text of a node with new text.
				const nodeOld = patch.nodeOld;
				const nodeNew = patch.nodeNew;

				nodeOld.element.textContent = nodeNew.data[""];
				nodeOld.node = nodeNew;

				break;
			}

			case patchTypes.updateData: {
				// Set attributes and events of a node with new data.
				const nodeOld = patch.nodeOld;
				const nodeOldNodeData = nodeOld.node.data;
				const nodeOldElement = nodeOld.element;
				const nodeNew = patch.nodeNew;
				const nodeNewData = nodeNew.data;

				// Set attributes on the DOM element.
				for (let key in nodeNewData) {
					const value = nodeNewData[key];

					if (key[0] === "@") {
						// Update the event listener.
						nodeOldElement.MoonEvents[key] = value;
					} else if (key !== "children") {
						// Remove the attribute if the value is false, and update it
						// otherwise.
						if (value === false) {
							nodeOldElement.removeAttribute(key);
						} else {
							nodeOldElement.setAttribute(key, value);
						}
					}
				}

				// Remove old attributes.
				for (let key in nodeOldNodeData) {
					if (!(key in nodeNewData)) {
						nodeOldElement.removeAttribute(key);
					}
				}

				nodeOld.node = nodeNew;

				break;
			}

			case patchTypes.appendNode: {
				// Append a node to the parent.
				const nodeParent = patch.nodeParent;
				const nodeOldNew = executeCreate(patch.nodeNew);

				nodeParent.element.appendChild(nodeOldNew.element);
				nodeParent.children.push(nodeOldNew);

				break;
			}

			case patchTypes.removeNode: {
				// Remove a node from the parent.
				const nodeParent = patch.nodeParent;

				// Pops the last child because the patches still hold a reference
				// to them. The diff phase can only create this patch when there
				// are extra old children, and popping nodes off of the end is more
				// efficient than removing at a specific index, especially because
				// they are equivalent in this case.
				nodeParent.element.removeChild(nodeParent.children.pop().element);

				break;
			}

			case patchTypes.replaceNode: {
				// Replaces an old node with a new node.
				const nodeOld = patch.nodeOld;
				const nodeOldElement = nodeOld.element;
				const nodeNew = patch.nodeNew;
				const nodeOldNew = executeCreate(nodeNew);
				const nodeOldNewElement = nodeOldNew.element;

				nodeOldElement.parentNode.replaceChild(nodeOldNewElement, nodeOldElement);

				nodeOld.element = nodeOldNewElement;
				nodeOld.node = nodeOldNew.node;
				nodeOld.children = nodeOldNew.children;

				break;
			}
		}
	}

	// Remove the current execution from the queue.
	executeQueue.shift();

	// If there is new data in the execution queue, continue to it.
	if (executeQueue.length !== 0) {
		if (performance.now() - executeStart >= 16) {
			// If the current frame doesn't have sufficient time left to keep
			// running then start the next execution in the next frame.
			requestAnimationFrame(() => {
				executeStart = performance.now();

				executeNext();
			});
		} else {
			executeNext();
		}
	}
}
function executePatch(patches) {
	for (let i = 0; i < patches.length; i++) {
		const patch = patches[i];

		switch (patch.type) {
			case patchTypes.updateText: {
				// Update text of a node with new text.
				const nodeOld = patch.nodeOld;
				const nodeNew = patch.nodeNew;

				nodeOld.element.textContent = nodeNew.data[""];
				nodeOld.node = nodeNew;

				break;
			}

			case patchTypes.updateData: {
				// Set attributes and events of a node with new data.
				const nodeOld = patch.nodeOld;
				const nodeOldNodeData = nodeOld.node.data;
				const nodeOldElement = nodeOld.element;
				const nodeNew = patch.nodeNew;
				const nodeNewData = nodeNew.data;

				// Set attributes on the DOM element.
				for (let key in nodeNewData) {
					const value = nodeNewData[key];

					if (key[0] === "@") {
						// Update the event listener.
						nodeOldElement.MoonEvents[key] = value;
					} else if (key !== "children") {
						// Remove the attribute if the value is false, and update it
						// otherwise.
						if (value === false) {
							nodeOldElement.removeAttribute(key);
						} else {
							nodeOldElement.setAttribute(key, value);
						}
					}
				}

				// Remove old attributes.
				for (let key in nodeOldNodeData) {
					if (!(key in nodeNewData)) {
						nodeOldElement.removeAttribute(key);
					}
				}

				nodeOld.node = nodeNew;

				break;
			}

			case patchTypes.appendNode: {
				// Append a node to the parent.
				const nodeParent = patch.nodeParent;
				const nodeOldNew = executeCreate(patch.nodeNew);

				nodeParent.element.appendChild(nodeOldNew.element);
				nodeParent.children.push(nodeOldNew);

				break;
			}

			case patchTypes.removeNode: {
				// Remove a node from the parent.
				const nodeParent = patch.nodeParent;

				// Pops the last child because the patches still hold a reference
				// to them. The diff phase can only create this patch when there
				// are extra old children, and popping nodes off of the end is more
				// efficient than removing at a specific index, especially because
				// they are equivalent in this case.
				nodeParent.element.removeChild(nodeParent.children.pop().element);

				break;
			}

			case patchTypes.replaceNode: {
				// Replaces an old node with a new node.
				const nodeOld = patch.nodeOld;
				const nodeOldElement = nodeOld.element;
				const nodeNew = patch.nodeNew;
				const nodeOldNew = executeCreate(nodeNew);
				const nodeOldNewElement = nodeOldNew.element;

				nodeOldElement.parentNode.replaceChild(nodeOldNewElement, nodeOldElement);

				nodeOld.element = nodeOldNewElement;
				nodeOld.node = nodeOldNew.node;
				nodeOld.children = nodeOldNew.children;

				break;
			}
		}
	}

	// Remove the current execution from the queue.
	executeQueue.shift();

	// If there is new data in the execution queue, continue to it.
	if (executeQueue.length !== 0) {
		if (performance.now() - executeStart >= 16) {
			// If the current frame doesn't have sufficient time left to keep
			// running then start the next execution in the next frame.
			requestAnimationFrame(() => {
				executeStart = performance.now();

				executeNext();
			});
		} else {
			executeNext();
		}
	}
}
function executePatch ( patches ) { for ( let i = 0 ; i < patches . length ; i ++ ) { const patch = patches [ i ] ; switch ( patch . type ) { case patchTypes . updateText : { // Update text of a node with new text. const nodeOld = patch . nodeOld ; const nodeNew = patch . nodeNew ; nodeOld . element . textContent = nodeNew . data [ "" ] ; nodeOld . node = nodeNew ; break ; } case patchTypes . updateData : { // Set attributes and events of a node with new data. const nodeOld = patch . nodeOld ; const nodeOldNodeData = nodeOld . node . data ; const nodeOldElement = nodeOld . element ; const nodeNew = patch . nodeNew ; const nodeNewData = nodeNew . data ; // Set attributes on the DOM element. for ( let key in nodeNewData ) { const value = nodeNewData [ key ] ; if ( key [ 0 ] === "@" ) { // Update the event listener. nodeOldElement . MoonEvents [ key ] = value ; } else if ( key !== "children" ) { // Remove the attribute if the value is false, and update it // otherwise. if ( value === false ) { nodeOldElement . removeAttribute ( key ) ; } else { nodeOldElement . setAttribute ( key , value ) ; } } } // Remove old attributes. for ( let key in nodeOldNodeData ) { if ( ! ( key in nodeNewData ) ) { nodeOldElement . removeAttribute ( key ) ; } } nodeOld . node = nodeNew ; break ; } case patchTypes . appendNode : { // Append a node to the parent. const nodeParent = patch . nodeParent ; const nodeOldNew = executeCreate ( patch . nodeNew ) ; nodeParent . element . appendChild ( nodeOldNew . element ) ; nodeParent . children . push ( nodeOldNew ) ; break ; } case patchTypes . removeNode : { // Remove a node from the parent. const nodeParent = patch . nodeParent ; // Pops the last child because the patches still hold a reference // to them. The diff phase can only create this patch when there // are extra old children, and popping nodes off of the end is more // efficient than removing at a specific index, especially because // they are equivalent in this case. nodeParent . element . removeChild ( nodeParent . children . pop ( ) . element ) ; break ; } case patchTypes . replaceNode : { // Replaces an old node with a new node. const nodeOld = patch . nodeOld ; const nodeOldElement = nodeOld . element ; const nodeNew = patch . nodeNew ; const nodeOldNew = executeCreate ( nodeNew ) ; const nodeOldNewElement = nodeOldNew . element ; nodeOldElement . parentNode . replaceChild ( nodeOldNewElement , nodeOldElement ) ; nodeOld . element = nodeOldNewElement ; nodeOld . node = nodeOldNew . node ; nodeOld . children = nodeOldNew . children ; break ; } } } // Remove the current execution from the queue. executeQueue . shift ( ) ; // If there is new data in the execution queue, continue to it. if ( executeQueue . length !== 0 ) { if ( performance . now ( ) - executeStart >= 16 ) { // If the current frame doesn't have sufficient time left to keep // running then start the next execution in the next frame. requestAnimationFrame ( ( ) => { executeStart = performance . now ( ) ; executeNext ( ) ; } ) ; } else { executeNext ( ) ; } } }
Applies the list of patches as DOM updates.

@param {Array} patches
Applies the list of patches as DOM updates .