From d84a028763cbdc8e89f0ec2c99cf1cf76d752236 Mon Sep 17 00:00:00 2001
From: Volker Schukai <volker.schukai@schukai.com>
Date: Sun, 15 Sep 2024 18:16:33 +0200
Subject: [PATCH] fix: Replace `sleep` with `requestAnimationFrame` for
 smoother UI #234

---
 source/components/tree-menu/tree-menu.mjs |  20 +-
 source/data/buildtree.mjs                 | 126 ++---
 source/data/pathfinder.mjs                | 610 +++++++++++-----------
 source/dom/updater.mjs                    |  17 +-
 4 files changed, 389 insertions(+), 384 deletions(-)

diff --git a/source/components/tree-menu/tree-menu.mjs b/source/components/tree-menu/tree-menu.mjs
index ea022d007..b5dda631c 100644
--- a/source/components/tree-menu/tree-menu.mjs
+++ b/source/components/tree-menu/tree-menu.mjs
@@ -217,7 +217,6 @@ class TreeMenu extends CustomElement {
 	 * @param value
 	 */
 	selectEntry(value) {
-
 		this.shadowRoot
 			.querySelectorAll("[data-monster-role=entry]")
 			.forEach((entry) => {
@@ -242,7 +241,7 @@ class TreeMenu extends CustomElement {
 		let intend = parseInt(currentNode.getAttribute(ATTRIBUTE_INTEND));
 
 		if (intend > 0) {
-			const refSet = new Set()
+			const refSet = new Set();
 			let ref = currentNode.previousElementSibling;
 			while (ref && ref.hasAttribute(ATTRIBUTE_INTEND)) {
 				const i = parseInt(ref.getAttribute(ATTRIBUTE_INTEND));
@@ -254,9 +253,9 @@ class TreeMenu extends CustomElement {
 				if (i < intend) {
 					if (ref.getAttribute("data-monster-state") !== "open") {
 						ref.click();
-						
+
 						//console.log(ref.getAttribute("data-monster-state") )
-						
+
 						//refSet.add(ref)
 						//console.log(ref)
 					}
@@ -326,9 +325,8 @@ function initEventHandler() {
 					}
 					this[preventChangeSymbol] = true;
 					setTimeout(() => {
-						importEntries.call(this);	
-					},10)
-					
+						importEntries.call(this);
+					}, 10);
 				}),
 			);
 		});
@@ -448,7 +446,7 @@ function initEventHandler() {
 	}
 
 	return this;
-} 
+}
 
 /**
  * @private
@@ -518,9 +516,9 @@ function importEntries() {
 	}
 
 	setTimeout(() => {
-		this.setOption("entries", options);	
-	},5)
-	
+		this.setOption("entries", options);
+	}, 5);
+
 	return this;
 }
 
diff --git a/source/data/buildtree.mjs b/source/data/buildtree.mjs
index c88d2d590..0e3b36b9b 100644
--- a/source/data/buildtree.mjs
+++ b/source/data/buildtree.mjs
@@ -12,14 +12,14 @@
  * SPDX-License-Identifier: AGPL-3.0
  */
 
-import {isArray, isObject} from "../types/is.mjs";
-import {Node} from "../types/node.mjs";
-import {NodeList} from "../types/nodelist.mjs";
-import {clone} from "../util/clone.mjs";
-import {assembleParts} from "./buildmap.mjs";
-import {extend} from "./extend.mjs";
+import { isArray, isObject } from "../types/is.mjs";
+import { Node } from "../types/node.mjs";
+import { NodeList } from "../types/nodelist.mjs";
+import { clone } from "../util/clone.mjs";
+import { assembleParts } from "./buildmap.mjs";
+import { extend } from "./extend.mjs";
 
-export {buildTree};
+export { buildTree };
 
 /**
  * @private
@@ -140,69 +140,69 @@ const rootSymbol = Symbol("root");
  * @since 1.26.0
  */
 function buildTree(subject, selector, idKey, parentIDKey, options) {
-    const nodes = new Map();
-
-    const maxDepth = 100;
-
-    if (!isObject(options)) {
-        options = {};
-    }
-
-    options = extend(
-        {},
-        {
-            rootReferences: [null, undefined],
-            filter: undefined,
-        },
-        options,
-    );
-
-    const filter = options?.filter;
-    let rootReferences = options.rootReferences;
-    if (!isArray(rootReferences)) {
-        rootReferences = [rootReferences];
-    }
-
-    const childMap = assembleParts(subject, selector, filter, function (o, k, m) {
-        const key = o?.[idKey];
-        let ref = o?.[parentIDKey];
-        if (rootReferences.indexOf(ref) !== -1) ref = rootSymbol;
-
-        if (key === undefined) {
-            throw new Error("the object has no value for the specified id");
-        }
-
-        o[parentSymbol] = ref;
-
-        const node = new Node(o);
-        this.has(ref)
-            ? this.get(ref).add(node)
-            : this.set(ref, new NodeList().add(node));
-        nodes.set(key, node);
-    });
-
-    nodes.forEach((node) => {
+	const nodes = new Map();
+
+	const maxDepth = 100;
+
+	if (!isObject(options)) {
+		options = {};
+	}
+
+	options = extend(
+		{},
+		{
+			rootReferences: [null, undefined],
+			filter: undefined,
+		},
+		options,
+	);
+
+	const filter = options?.filter;
+	let rootReferences = options.rootReferences;
+	if (!isArray(rootReferences)) {
+		rootReferences = [rootReferences];
+	}
+
+	const childMap = assembleParts(subject, selector, filter, function (o, k, m) {
+		const key = o?.[idKey];
+		let ref = o?.[parentIDKey];
+		if (rootReferences.indexOf(ref) !== -1) ref = rootSymbol;
+
+		if (key === undefined) {
+			throw new Error("the object has no value for the specified id");
+		}
+
+		o[parentSymbol] = ref;
+
+		const node = new Node(o);
+		this.has(ref)
+			? this.get(ref).add(node)
+			: this.set(ref, new NodeList().add(node));
+		nodes.set(key, node);
+	});
+
+	nodes.forEach((node) => {
 		const id = node?.["value"]?.[idKey];
 
-        if (id === undefined) {
-            throw new Error("the object has no value for the specified id");
-        }
+		if (id === undefined) {
+			throw new Error("the object has no value for the specified id");
+		}
 
 		if (childMap.has(id)) {
-            node.childNodes = childMap.get(id);
-            childMap.delete(id);
+			node.childNodes = childMap.get(id);
+			childMap.delete(id);
 		}
 	});
 
-    const list = new NodeList();
+	const list = new NodeList();
 
-    childMap.forEach((s) => {
-        if (s instanceof Set) {
-            s.forEach((n) => {
-                list.add(n);
-            });
-        }
-    });
+	childMap.forEach((s) => {
+		if (s instanceof Set) {
+			s.forEach((n) => {
+				list.add(n);
+			});
+		}
+	});
 
-    return list;
+	return list;
 }
diff --git a/source/data/pathfinder.mjs b/source/data/pathfinder.mjs
index 98bf04194..c0fd5f10d 100644
--- a/source/data/pathfinder.mjs
+++ b/source/data/pathfinder.mjs
@@ -12,22 +12,22 @@
  * SPDX-License-Identifier: AGPL-3.0
  */
 
-import {Base} from "../types/base.mjs";
+import { Base } from "../types/base.mjs";
 import {
-    isArray,
-    isInteger,
-    isObject,
-    isPrimitive,
-    isString,
+	isArray,
+	isInteger,
+	isObject,
+	isPrimitive,
+	isString,
 } from "../types/is.mjs";
-import {Stack} from "../types/stack.mjs";
+import { Stack } from "../types/stack.mjs";
 import {
-    validateInteger,
-    validateBoolean,
-    validateString,
+	validateInteger,
+	validateBoolean,
+	validateString,
 } from "../types/validate.mjs";
 
-export {Pathfinder, DELIMITER, WILDCARD};
+export { Pathfinder, DELIMITER, WILDCARD };
 
 /**
  * path separator
@@ -89,102 +89,101 @@ const WILDCARD = "*";
  * @memberOf Monster.Data
  */
 class Pathfinder extends Base {
-    /**
-     * Creates a new instance of the constructor.
-     *
-     * @param {object} object - The object parameter for the constructor.
-     *
-     * @throws {Error} Throws an error if the provided object parameter is a simple type.
-     */
-    constructor(object) {
-        super();
-
-        if (isPrimitive(object)) {
-            throw new Error("the parameter must not be a simple type");
-        }
-
-        this.object = object;
-        this.wildCard = WILDCARD;
-    }
-
-    /**
-     * set wildcard
-     *
-     * @param {string} wildcard
-     * @return {Pathfinder}
-     * @since 1.7.0
-     */
-    setWildCard(wildcard) {
-        validateString(wildcard);
-        this.wildCard = wildcard;
-        return this;
-    }
-
-    /**
-     *
-     * @param {string|array} path
-     * @since 1.4.0
-     * @returns {*}
-     * @throws {TypeError} unsupported type
-     * @throws {Error} the journey is not at its end
-     * @throws {TypeError} value is not a string
-     * @throws {TypeError} value is not an integer
-     * @throws {Error} unsupported action for this data type
-     */
-    getVia(path) {
-        return getValueViaPath.call(this, this.object, path);
-    }
-
-    /**
-     *
-     * @param {string|array} path
-     * @param {*} value
-     * @returns {Pathfinder}
-     * @since 1.4.0
-     * @throws {TypeError} unsupported type
-     * @throws {TypeError} value is not a string
-     * @throws {TypeError} value is not an integer
-     * @throws {Error} unsupported action for this data type
-     */
-    setVia(path, value) {
-        setValueViaPath.call(this, this.object, path, value);
-        return this;
-    }
-
-    /**
-     * Delete Via Path
-     *
-     * @param {string|array} path
-     * @returns {Pathfinder}
-     * @since 1.6.0
-     * @throws {TypeError} unsupported type
-     * @throws {TypeError} value is not a string
-     * @throws {TypeError} value is not an integer
-     * @throws {Error} unsupported action for this data type
-     */
-    deleteVia(path) {
-        deleteValueViaPath.call(this, this.object, path);
-        return this;
-    }
-
-    /**
-     *
-     * @param {string|array} path
-     * @return {bool}
-     * @throws {TypeError} unsupported type
-     * @throws {TypeError} value is not a string
-     * @throws {TypeError} value is not an integer
-     * @since 1.4.0
-     */
-    exists(path) {
-        try {
-            getValueViaPath.call(this, this.object, path, true);
-            return true;
-        } catch (e) {
-        }
-
-        return false;
-    }
+	/**
+	 * Creates a new instance of the constructor.
+	 *
+	 * @param {object} object - The object parameter for the constructor.
+	 *
+	 * @throws {Error} Throws an error if the provided object parameter is a simple type.
+	 */
+	constructor(object) {
+		super();
+
+		if (isPrimitive(object)) {
+			throw new Error("the parameter must not be a simple type");
+		}
+
+		this.object = object;
+		this.wildCard = WILDCARD;
+	}
+
+	/**
+	 * set wildcard
+	 *
+	 * @param {string} wildcard
+	 * @return {Pathfinder}
+	 * @since 1.7.0
+	 */
+	setWildCard(wildcard) {
+		validateString(wildcard);
+		this.wildCard = wildcard;
+		return this;
+	}
+
+	/**
+	 *
+	 * @param {string|array} path
+	 * @since 1.4.0
+	 * @returns {*}
+	 * @throws {TypeError} unsupported type
+	 * @throws {Error} the journey is not at its end
+	 * @throws {TypeError} value is not a string
+	 * @throws {TypeError} value is not an integer
+	 * @throws {Error} unsupported action for this data type
+	 */
+	getVia(path) {
+		return getValueViaPath.call(this, this.object, path);
+	}
+
+	/**
+	 *
+	 * @param {string|array} path
+	 * @param {*} value
+	 * @returns {Pathfinder}
+	 * @since 1.4.0
+	 * @throws {TypeError} unsupported type
+	 * @throws {TypeError} value is not a string
+	 * @throws {TypeError} value is not an integer
+	 * @throws {Error} unsupported action for this data type
+	 */
+	setVia(path, value) {
+		setValueViaPath.call(this, this.object, path, value);
+		return this;
+	}
+
+	/**
+	 * Delete Via Path
+	 *
+	 * @param {string|array} path
+	 * @returns {Pathfinder}
+	 * @since 1.6.0
+	 * @throws {TypeError} unsupported type
+	 * @throws {TypeError} value is not a string
+	 * @throws {TypeError} value is not an integer
+	 * @throws {Error} unsupported action for this data type
+	 */
+	deleteVia(path) {
+		deleteValueViaPath.call(this, this.object, path);
+		return this;
+	}
+
+	/**
+	 *
+	 * @param {string|array} path
+	 * @return {bool}
+	 * @throws {TypeError} unsupported type
+	 * @throws {TypeError} value is not a string
+	 * @throws {TypeError} value is not an integer
+	 * @since 1.4.0
+	 */
+	exists(path) {
+		try {
+			getValueViaPath.call(this, this.object, path, true);
+			return true;
+		} catch (e) {}
+
+		return false;
+	}
 }
 
 /**
@@ -199,27 +198,27 @@ class Pathfinder extends Base {
  * @private
  */
 function iterate(subject, path, check) {
-    if (check === undefined) {
-        check = false;
-    }
-    validateBoolean(check);
-
-    const result = new Map();
-
-    if (isArray(path)) {
-        path = path.join(DELIMITER);
-    }
-
-    if (isObject(subject) || isArray(subject)) {
-        for (const [key, value] of Object.entries(subject)) {
-            result.set(key, getValueViaPath.call(this, value, path, check));
-        }
-    } else {
-        const key = path.split(DELIMITER).shift();
-        result.set(key, getValueViaPath.call(this, subject, path, check));
-    }
-
-    return result;
+	if (check === undefined) {
+		check = false;
+	}
+	validateBoolean(check);
+
+	const result = new Map();
+
+	if (isArray(path)) {
+		path = path.join(DELIMITER);
+	}
+
+	if (isObject(subject) || isArray(subject)) {
+		for (const [key, value] of Object.entries(subject)) {
+			result.set(key, getValueViaPath.call(this, value, path, check));
+		}
+	} else {
+		const key = path.split(DELIMITER).shift();
+		result.set(key, getValueViaPath.call(this, subject, path, check));
+	}
+
+	return result;
 }
 
 /**
@@ -233,71 +232,73 @@ function iterate(subject, path, check) {
  * @throws {Error} unsupported action for this data type
  */
 function getValueViaPath(subject, path, check) {
-    if (check === undefined) {
-        check = false;
-    }
-    validateBoolean(check);
-
-    if (!(isArray(path) || isString(path))) {
-        throw new Error("type error: a path must be a string or an array in getValueViaPath");
-    }
-
-    let parts;
-    if (isString(path)) {
-        if (path === "") {
-            return subject;
-        }
-
-        parts = path.split(DELIMITER);
-    }
-
-    let current = parts.shift();
-
-    if (current === this.wildCard) {
-        return iterate.call(this, subject, parts.join(DELIMITER), check);
-    }
-
-    if (isObject(subject) || isArray(subject)) {
-        let anchor;
-        if (subject instanceof Map || subject instanceof WeakMap) {
-            anchor = subject.get(current);
-        } else if (subject instanceof Set || subject instanceof WeakSet) {
-            current = parseInt(current);
-            validateInteger(current);
-            anchor = [...subject]?.[current];
-        } else if (typeof WeakRef === "function" && subject instanceof WeakRef) {
-            throw Error("unsupported action for this data type (WeakRef)");
-        } else if (isArray(subject)) {
-            current = parseInt(current);
-            validateInteger(current);
-            anchor = subject?.[current];
-        } else {
-            anchor = subject?.[current];
-        }
-
-        if (isObject(anchor) || isArray(anchor)) {
-            return getValueViaPath.call(this, anchor, parts.join(DELIMITER), check);
-        }
-
-        if (parts.length > 0) {
-            throw Error(`the journey is not at its end (${parts.join(DELIMITER)})`);
-        }
-
-        if (check === true) {
-            const descriptor = Object.getOwnPropertyDescriptor(
-                Object.getPrototypeOf(subject),
-                current,
-            );
-
-            if (!subject.hasOwnProperty(current) && descriptor === undefined) {
-                throw Error("unknown value " + current);
-            }
-        }
-
-        return anchor;
-    }
-
-    throw TypeError(`unsupported type ${typeof subject} for path ${path}`);
+	if (check === undefined) {
+		check = false;
+	}
+	validateBoolean(check);
+
+	if (!(isArray(path) || isString(path))) {
+		throw new Error(
+			"type error: a path must be a string or an array in getValueViaPath",
+		);
+	}
+
+	let parts;
+	if (isString(path)) {
+		if (path === "") {
+			return subject;
+		}
+
+		parts = path.split(DELIMITER);
+	}
+
+	let current = parts.shift();
+
+	if (current === this.wildCard) {
+		return iterate.call(this, subject, parts.join(DELIMITER), check);
+	}
+
+	if (isObject(subject) || isArray(subject)) {
+		let anchor;
+		if (subject instanceof Map || subject instanceof WeakMap) {
+			anchor = subject.get(current);
+		} else if (subject instanceof Set || subject instanceof WeakSet) {
+			current = parseInt(current);
+			validateInteger(current);
+			anchor = [...subject]?.[current];
+		} else if (typeof WeakRef === "function" && subject instanceof WeakRef) {
+			throw Error("unsupported action for this data type (WeakRef)");
+		} else if (isArray(subject)) {
+			current = parseInt(current);
+			validateInteger(current);
+			anchor = subject?.[current];
+		} else {
+			anchor = subject?.[current];
+		}
+
+		if (isObject(anchor) || isArray(anchor)) {
+			return getValueViaPath.call(this, anchor, parts.join(DELIMITER), check);
+		}
+
+		if (parts.length > 0) {
+			throw Error(`the journey is not at its end (${parts.join(DELIMITER)})`);
+		}
+
+		if (check === true) {
+			const descriptor = Object.getOwnPropertyDescriptor(
+				Object.getPrototypeOf(subject),
+				current,
+			);
+
+			if (!subject.hasOwnProperty(current) && descriptor === undefined) {
+				throw Error("unknown value " + current);
+			}
+		}
+
+		return anchor;
+	}
+
+	throw TypeError(`unsupported type ${typeof subject} for path ${path}`);
 }
 
 /**
@@ -313,73 +314,72 @@ function getValueViaPath(subject, path, check) {
  * @private
  */
 function setValueViaPath(subject, path, value) {
-    if (!(isArray(path) || isString(path))) {
-        throw new Error("type error: a path must be a string or an array");
-    }
-
-    let parts;
-    if (isArray(path)) {
-        if (path.length === 0) {
-            return;
-        }
-
-        parts = path;
-    } else {
-        parts = path.split(DELIMITER);
-    }
-
-    let last = parts.pop();
-    const subpath = parts.join(DELIMITER);
-
-    const stack = new Stack();
-    let current = subpath;
-    while (true) {
-        try {
-            getValueViaPath.call(this, subject, current, true);
-            break;
-        } catch (e) {
-        }
-
-        stack.push(current);
-        parts.pop();
-        current = parts.join(DELIMITER);
-
-        if (current === "") break;
-    }
-
-    while (!stack.isEmpty()) {
-        current = stack.pop();
-        let obj = {};
-
-        if (!stack.isEmpty()) {
-            const n = stack.peek().split(DELIMITER).pop();
-            if (isInteger(parseInt(n))) {
-                obj = [];
-            }
-        }
-
-        setValueViaPath.call(this, subject, current, obj);
-    }
-
-    const anchor = getValueViaPath.call(this, subject, subpath);
-
-    if (!(isObject(subject) || isArray(subject))) {
-        throw TypeError(`unsupported type: ${typeof subject} in setValueViaPath`);
-    }
-
-    if (anchor instanceof Map || anchor instanceof WeakMap) {
-        anchor.set(last, value);
-    } else if (anchor instanceof Set || anchor instanceof WeakSet) {
-        anchor.append(value);
-    } else if (typeof WeakRef === "function" && anchor instanceof WeakRef) {
-        throw Error("unsupported action for this data type in setValueViaPath");
-    } else if (isArray(anchor)) {
-        last = parseInt(last);
-        validateInteger(last);
-        assignProperty(anchor, "" + last, value);
-    } else {
-        assignProperty(anchor, last, value);
-    }
+	if (!(isArray(path) || isString(path))) {
+		throw new Error("type error: a path must be a string or an array");
+	}
+
+	let parts;
+	if (isArray(path)) {
+		if (path.length === 0) {
+			return;
+		}
+
+		parts = path;
+	} else {
+		parts = path.split(DELIMITER);
+	}
+
+	let last = parts.pop();
+	const subpath = parts.join(DELIMITER);
+
+	const stack = new Stack();
+	let current = subpath;
+	while (true) {
+		try {
+			getValueViaPath.call(this, subject, current, true);
+			break;
+		} catch (e) {}
+
+		stack.push(current);
+		parts.pop();
+		current = parts.join(DELIMITER);
+
+		if (current === "") break;
+	}
+
+	while (!stack.isEmpty()) {
+		current = stack.pop();
+		let obj = {};
+
+		if (!stack.isEmpty()) {
+			const n = stack.peek().split(DELIMITER).pop();
+			if (isInteger(parseInt(n))) {
+				obj = [];
+			}
+		}
+
+		setValueViaPath.call(this, subject, current, obj);
+	}
+
+	const anchor = getValueViaPath.call(this, subject, subpath);
+
+	if (!(isObject(subject) || isArray(subject))) {
+		throw TypeError(`unsupported type: ${typeof subject} in setValueViaPath`);
+	}
+
+	if (anchor instanceof Map || anchor instanceof WeakMap) {
+		anchor.set(last, value);
+	} else if (anchor instanceof Set || anchor instanceof WeakSet) {
+		anchor.append(value);
+	} else if (typeof WeakRef === "function" && anchor instanceof WeakRef) {
+		throw Error("unsupported action for this data type in setValueViaPath");
+	} else if (isArray(anchor)) {
+		last = parseInt(last);
+		validateInteger(last);
+		assignProperty(anchor, "" + last, value);
+	} else {
+		assignProperty(anchor, last, value);
+	}
 }
 
 /**
@@ -389,16 +389,16 @@ function setValueViaPath(subject, path, value) {
  * @param {*} value
  */
 function assignProperty(object, key, value) {
-    if (!object.hasOwnProperty(key)) {
-        object[key] = value;
-        return;
-    }
+	if (!object.hasOwnProperty(key)) {
+		object[key] = value;
+		return;
+	}
 
-    if (value === undefined) {
-        delete object[key];
-    }
+	if (value === undefined) {
+		delete object[key];
+	}
 
-    object[key] = value;
+	object[key] = value;
 }
 
 /**
@@ -415,40 +415,42 @@ function assignProperty(object, key, value) {
  * @private
  */
 function deleteValueViaPath(subject, path) {
-    if (!(isArray(path) || isString(path))) {
-        throw new Error("type error: a path must be a string or an array in deleteValueViaPath");
-    }
-
-    let parts;
-    if (isArray(path)) {
-        if (path.length === 0) {
-            return;
-        }
-
-        parts = path;
-    } else {
-        parts = path.split(DELIMITER);
-    }
-
-    let last = parts.pop();
-    const subPath = parts.join(DELIMITER);
-
-    const anchor = getValueViaPath.call(this, subject, subPath);
-
-    if (anchor instanceof Map) {
-        anchor.delete(last);
-    } else if (
-        anchor instanceof Set ||
-        anchor instanceof WeakMap ||
-        anchor instanceof WeakSet ||
-        (typeof WeakRef === "function" && anchor instanceof WeakRef)
-    ) {
-        throw Error("unsupported action for this data type in deleteValueViaPath");
-    } else if (isArray(anchor)) {
-        last = parseInt(last);
-        validateInteger(last);
-        delete anchor[last];
-    } else {
-        delete anchor[last];
-    }
+	if (!(isArray(path) || isString(path))) {
+		throw new Error(
+			"type error: a path must be a string or an array in deleteValueViaPath",
+		);
+	}
+
+	let parts;
+	if (isArray(path)) {
+		if (path.length === 0) {
+			return;
+		}
+
+		parts = path;
+	} else {
+		parts = path.split(DELIMITER);
+	}
+
+	let last = parts.pop();
+	const subPath = parts.join(DELIMITER);
+
+	const anchor = getValueViaPath.call(this, subject, subPath);
+
+	if (anchor instanceof Map) {
+		anchor.delete(last);
+	} else if (
+		anchor instanceof Set ||
+		anchor instanceof WeakMap ||
+		anchor instanceof WeakSet ||
+		(typeof WeakRef === "function" && anchor instanceof WeakRef)
+	) {
+		throw Error("unsupported action for this data type in deleteValueViaPath");
+	} else if (isArray(anchor)) {
+		last = parseInt(last);
+		validateInteger(last);
+		delete anchor[last];
+	} else {
+		delete anchor[last];
+	}
 }
diff --git a/source/dom/updater.mjs b/source/dom/updater.mjs
index 790ce09a9..cc7aab6d0 100644
--- a/source/dom/updater.mjs
+++ b/source/dom/updater.mjs
@@ -40,6 +40,7 @@ import { addAttributeToken, addToObjectLink } from "./attributes.mjs";
 import { updaterTransformerMethodsSymbol } from "./customelement.mjs";
 import { findTargetElementFromEvent } from "./events.mjs";
 import { findDocumentTemplate } from "./template.mjs";
+import { getWindow } from "./util.mjs";
 
 export { Updater, addObjectWithUpdaterToElement };
 
@@ -111,11 +112,15 @@ class Updater extends Base {
 
 				for (const [, change] of Object.entries(diffResult)) {
 					promises.push(
-						Sleep(1).then(() => {
-							removeElement.call(this, change);
-							insertElement.call(this, change);
-							updateContent.call(this, change);
-							updateAttributes.call(this, change);
+						new Promise((resolve) => {
+							getWindow().requestAnimationFrame(() => {
+								removeElement.call(this, change);
+								insertElement.call(this, change);
+								updateContent.call(this, change);
+								updateAttributes.call(this, change);
+
+								resolve();
+							});
 						}),
 					);
 				}
@@ -534,7 +539,7 @@ function insertElement(change) {
 
 				const available = new Set();
 
-				for (const [i, ] of Object.entries(value)) {
+				for (const [i] of Object.entries(value)) {
 					const ref = refPrefix + i;
 					const currentPath = `${dataPath}.${i}`;
 
-- 
GitLab