diff --git a/source/components/form/select.mjs b/source/components/form/select.mjs
index d77ba607300295f87731facaf8a05aec0b19863d..631a3ff4e127923b72959aeb1d025981ad9a32d2 100644
--- a/source/components/form/select.mjs
+++ b/source/components/form/select.mjs
@@ -14,7 +14,7 @@
 
 import {instanceSymbol} from "../../constants.mjs";
 import {internalSymbol} from "../../constants.mjs";
-import {buildMap} from "../../data/buildmap.mjs";
+import {buildMap,build as buildValue} from "../../data/buildmap.mjs";
 import {DeadMansSwitch} from "../../util/deadmansswitch.mjs";
 import {positionPopper} from "./util/floating-ui.mjs";
 import {
@@ -697,11 +697,12 @@ class Select extends CustomControl {
      * @fires monster-options-set this event is fired when the options are set
      */
     importOptions(data) {
+        const self = this;
         const mappingOptions = this.getOption("mapping", {});
         const selector = mappingOptions?.["selector"];
         const labelTemplate = mappingOptions?.["labelTemplate"];
         const valueTemplate = mappingOptions?.["valueTemplate"];
-        const filter = mappingOptions?.["filter"];
+        let filter = mappingOptions?.["filter"];
 
         let flag = false;
         if (labelTemplate === "") {
@@ -717,6 +718,36 @@ class Select extends CustomControl {
         if (flag === true) {
             throw new Error("missing label configuration");
         }
+        if (isString(filter) ) {
+            if (0 === filter.indexOf('run:')) {
+                const code = filter.replace('run:', '');
+                filter = (m, v, k) => {
+                    const fkt = new Function('m', 'v', 'k', "control", code);
+                    return fkt(m, v, k, self);
+                }
+            } else if (0 === filter.indexOf('call:')) {
+
+                const parts = filter.split(':');
+                parts.shift(); // remove prefix
+                const fkt = parts.shift();
+
+                switch (fkt) {
+                    case "filterValueOfAttribute":
+
+                        const attribute = parts.shift();
+                        const attrValue = self.getAttribute(attribute);
+
+                        filter = (m, v, k) => {
+                            const mm = buildValue(m, valueTemplate);
+                            return mm != attrValue; // no type check, no !==
+                        }
+                        break;
+
+                    default:
+                        addErrorAttribute(this, new Error(`Unknown filter function ${fkt}`));
+                }
+            }
+        }
 
         const map = buildMap(data, selector, labelTemplate, valueTemplate, filter);
 
diff --git a/source/components/form/tree-select.mjs b/source/components/form/tree-select.mjs
index 75288f9169134eff0cb879db7e9b9663239ad939..837c41d9f6305d725a39171386020c6cd5e3ac40 100644
--- a/source/components/form/tree-select.mjs
+++ b/source/components/form/tree-select.mjs
@@ -12,37 +12,38 @@
  * SPDX-License-Identifier: AGPL-3.0
  */
 
-import { buildTree } from "../../data/buildtree.mjs";
+import {buildTree} from "../../data/buildtree.mjs";
 import {
-	addAttributeToken,
-	findClosestByAttribute,
+    addAttributeToken,
+    findClosestByAttribute,
 } from "../../dom/attributes.mjs";
 import {
-	ATTRIBUTE_ERRORMESSAGE,
-	ATTRIBUTE_ROLE,
-	ATTRIBUTE_UPDATER_INSERT_REFERENCE,
+    ATTRIBUTE_ERRORMESSAGE,
+    ATTRIBUTE_ROLE,
+    ATTRIBUTE_UPDATER_INSERT_REFERENCE,
 } from "../../dom/constants.mjs";
-import { instanceSymbol } from "../../constants.mjs";
+import {instanceSymbol} from "../../constants.mjs";
 import {
-	assembleMethodSymbol,
-	registerCustomElement,
+    assembleMethodSymbol,
+    registerCustomElement,
 } from "../../dom/customelement.mjs";
 import {
-	findTargetElementFromEvent,
-	fireCustomEvent,
-	fireEvent,
+    findTargetElementFromEvent,
+    fireCustomEvent,
+    fireEvent,
 } from "../../dom/events.mjs";
-import { Formatter } from "../../text/formatter.mjs";
-import { isString } from "../../types/is.mjs";
-import { Node } from "../../types/node.mjs";
-import { NodeRecursiveIterator } from "../../types/noderecursiveiterator.mjs";
-import { validateInstance } from "../../types/validate.mjs";
-import { ATTRIBUTE_FORM_URL, ATTRIBUTE_INTEND } from "./constants.mjs";
-import { Select } from "./select.mjs";
-import { SelectStyleSheet } from "./stylesheet/select.mjs";
-import { TreeSelectStyleSheet } from "./stylesheet/tree-select.mjs";
-
-export { TreeSelect, formatHierarchicalSelection };
+import {Formatter} from "../../text/formatter.mjs";
+import {isString} from "../../types/is.mjs";
+import {Node} from "../../types/node.mjs";
+import {NodeRecursiveIterator} from "../../types/noderecursiveiterator.mjs";
+import {validateInstance} from "../../types/validate.mjs";
+import {ATTRIBUTE_FORM_URL, ATTRIBUTE_INTEND} from "./constants.mjs";
+import {Select} from "./select.mjs";
+import {SelectStyleSheet} from "./stylesheet/select.mjs";
+import {TreeSelectStyleSheet} from "./stylesheet/tree-select.mjs";
+import {addErrorAttribute} from "../../dom/error.mjs";
+
+export {TreeSelect, formatHierarchicalSelection};
 
 /**
  * @private
@@ -72,161 +73,201 @@ const keyEventHandler = Symbol("keyEventHandler");
  * @fires monster-changed
  */
 class TreeSelect extends Select {
-	/**
-	 * This method is called by the `instanceof` operator.
-	 * @return {symbol}
-	 * @since 2.1.0
-	 */
-	static get [instanceSymbol]() {
-		return Symbol.for("@schukai/monster/components/form/tree-select@@instance");
-	}
-
-	/**
-	 * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
-	 * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
-	 *
-	 * The individual configuration values can be found in the table.
-	 *
-	 * @extends Select
-	 * @property {Array} mapping.rootReferences=['0', undefined, null]
-	 * @property {String} mapping.idTemplate=id
-	 * @property {String} mapping.parentTemplate=parent
-	 * @property {String} mapping.selection
-	 * @property {Object} formatter
-	 * @property {String} formatter.separator=" / "
-	 */
-	get defaults() {
-		return Object.assign(
-			{},
-			super.defaults,
-			{
-				mapping: {
-					rootReferences: ["0", undefined, null],
-					id: "id",
-					parent: "parent",
-
-					selector: "*",
-					labelTemplate: "",
-					valueTemplate: "",
-				},
-				formatter: {
-					selection: formatHierarchicalSelection,
-					separator: " / ",
-				},
-				templates: {
-					main: getTemplate(),
-				},
-			},
-			initOptionsFromArguments.call(this),
-		);
-	}
-
-	/**
-	 *
-	 * @return {string}
-	 */
-	static getTag() {
-		return "monster-tree-select";
-	}
-
-	/**
-	 *
-	 * @return {CSSStyleSheet[]}
-	 */
-	static getCSSStyleSheet() {
-		return [SelectStyleSheet, TreeSelectStyleSheet];
-	}
-
-	/**
-	 * Import Select Options from dataset
-	 * Not to be confused with the control defaults/options
-	 *
-	 * @param {array|object|Map|Set} data
-	 * @return {Select}
-	 * @throws {Error} map is not iterable
-	 */
-	importOptions(data) {
-		this[internalNodesSymbol] = new Map();
-
-		const mappingOptions = this.getOption("mapping", {});
-
-		const filter = mappingOptions?.["filter"];
-		const rootReferences = mappingOptions?.["rootReferences"];
-
-		const id = this.getOption("mapping.id", "id");
-		const parentID = this.getOption("mapping.parent", "parent");
-
-		const selector = mappingOptions?.["selector"];
-		const options = [];
-
-		try {
-			const nodes = buildTree(data, selector, id, parentID, {
-				filter,
-				rootReferences,
-			});
-
-			for (const node of nodes) {
-				const iterator = new NodeRecursiveIterator(node);
-				for (const n of iterator) {
-					const formattedValues = formatKeyLabel.call(this, n);
-
-					const label = formattedValues.label;
-					const value = formattedValues.value;
-					const intend = n.level;
-
-					const visibility = intend > 0 ? "hidden" : "visible";
-					const state = "close";
-
-					this[internalNodesSymbol].set(value, n);
-
-					options.push({
-						value,
-						label,
-						intend,
-						state,
-						visibility,
-						["has-children"]: n.hasChildNodes(),
-					});
-				}
-			}
-
-			this.setOption("options", options);
-
-			fireCustomEvent(this, "monster-options-set", {
-				options,
-			});
-		} catch (e) {
-			addAttributeToken(this, ATTRIBUTE_ERRORMESSAGE, e?.message || e);
-		}
-
-		return this;
-	}
-
-	/**
-	 *
-	 * @return {TreeSelect}
-	 */
-	[assembleMethodSymbol]() {
-		super[assembleMethodSymbol]();
-		initEventHandler.call(this);
-	}
+    /**
+     * This method is called by the `instanceof` operator.
+     * @return {symbol}
+     * @since 2.1.0
+     */
+    static get [instanceSymbol]() {
+        return Symbol.for("@schukai/monster/components/form/tree-select@@instance");
+    }
+
+    /**
+     * To set the options via the HTML tag, the attribute `data-monster-options` must be used.
+     * @see {@link https://monsterjs.org/en/doc/#configurate-a-monster-control}
+     *
+     * The individual configuration values can be found in the table.
+     *
+     * @extends Select
+     * @property {Array} mapping.rootReferences=['0', undefined, null]
+     * @property {String} mapping.idTemplate=id
+     * @property {String} mapping.parentTemplate=parent
+     * @property {String} mapping.selection
+     * @property {String} mapping.labelTemplate
+     * @property {String} mapping.valueTemplate
+     * @property {String} mapping.filter The filter function to apply to each node, you can use run: syntax to execute a function, or use call:filterValueOfAttribute:data-my-attribute.
+     * @property {Object} formatter
+     * @property {String} formatter.separator=" / "
+     */
+    get defaults() {
+        return Object.assign(
+            {},
+            super.defaults,
+            {
+                mapping: {
+                    rootReferences: ["0", undefined, null],
+                    id: "id",
+                    parent: "parent",
+
+                    selector: "*",
+                    labelTemplate: "",
+                    valueTemplate: "",
+
+                    filter: null,
+                },
+                formatter: {
+                    selection: formatHierarchicalSelection,
+                    separator: " / ",
+                },
+                templates: {
+                    main: getTemplate(),
+                },
+            },
+            initOptionsFromArguments.call(this),
+        );
+    }
+
+    /**
+     *
+     * @return {string}
+     */
+    static getTag() {
+        return "monster-tree-select";
+    }
+
+    /**
+     *
+     * @return {CSSStyleSheet[]}
+     */
+    static getCSSStyleSheet() {
+        return [SelectStyleSheet, TreeSelectStyleSheet];
+    }
+
+    /**
+     * Import Select Options from dataset
+     * Not to be confused with the control defaults/options
+     *
+     * @param {array|object|Map|Set} data
+     * @return {Select}
+     * @throws {Error} map is not iterable
+     */
+    importOptions(data) {
+        const self = this;
+
+        this[internalNodesSymbol] = new Map();
+
+        const id = this.getOption("mapping.id", "id");
+        const parentID = this.getOption("mapping.parent", "parent");
+
+        const mappingOptions = this.getOption("mapping", {});
+
+        let filter = mappingOptions?.["filter"];
+
+        if (isString(filter) ) {
+            if (0 === filter.indexOf('run:')) {
+                const code = filter.replace('run:', '');
+                filter = (m, v, k) => {
+                    const fkt = new Function('m', 'v', 'k', "control", code);
+                    return fkt(m, v, k, self);
+                }
+            } else if (0 === filter.indexOf('call:')) {
+
+                const parts = filter.split(':');
+                parts.shift(); // remove prefix
+                const fkt = parts.shift();
+
+                switch (fkt) {
+                    case "filterValueOfAttribute":
+
+                        const attribute = parts.shift();
+                        const attrValue = self.getAttribute(attribute);
+
+                        filter = (m, v, k) => {
+                            return m?.[id] != attrValue; // no type check, no !==
+                        }
+                        break;
+
+                    default:
+                        addErrorAttribute(this, new Error(`Unknown filter function ${fkt}`));
+                }
+            }
+
+        }
+
+        const rootReferences = mappingOptions?.["rootReferences"];
+
+        const selector = mappingOptions?.["selector"];
+        const options = [];
+
+        try {
+            const nodes = buildTree(data, selector, id, parentID, {
+                filter,
+                rootReferences,
+            });
+
+            for (const node of nodes) {
+                const iterator = new NodeRecursiveIterator(node);
+                for (const n of iterator) {
+                    const formattedValues = formatKeyLabel.call(this, n);
+
+                    const label = formattedValues.label;
+                    const value = formattedValues.value;
+                    const intend = n.level;
+
+                    const visibility = intend > 0 ? "hidden" : "visible";
+                    const state = "close";
+
+                    this[internalNodesSymbol].set(value, n);
+
+                    options.push({
+                        value,
+                        label,
+                        intend,
+                        state,
+                        visibility,
+                        ["has-children"]: n.hasChildNodes(),
+                    });
+                }
+            }
+
+            this.setOption("options", options);
+
+            fireCustomEvent(this, "monster-options-set", {
+                options,
+            });
+        } catch (e) {
+            addErrorAttribute(this, e);
+        }
+
+        return this;
+    }
+
+    /**
+     *
+     * @return {TreeSelect}
+     */
+    [assembleMethodSymbol]() {
+        super[assembleMethodSymbol]();
+        initEventHandler.call(this);
+    }
 }
 
+
 /**
  * @private
  * @param event
  */
 function handleOptionKeyboardEvents(event) {
-	switch (event?.["code"]) {
-		case "ArrowLeft":
-			closeOrOpenCurrentOption.call(this, event, "close");
-			event.preventDefault();
-			break;
-		case "ArrowRight":
-			closeOrOpenCurrentOption.call(this, event, "open");
-			event.preventDefault();
-			break;
-	}
+    switch (event?.["code"]) {
+        case "ArrowLeft":
+            closeOrOpenCurrentOption.call(this, event, "close");
+            event.preventDefault();
+            break;
+        case "ArrowRight":
+            closeOrOpenCurrentOption.call(this, event, "open");
+            event.preventDefault();
+            break;
+    }
 }
 
 /**
@@ -234,24 +275,24 @@ function handleOptionKeyboardEvents(event) {
  * @param {event} event
  */
 function closeOrOpenCurrentOption(event, mode) {
-	validateInstance(event, Event);
-
-	if (typeof event.composedPath !== "function") {
-		throw new Error("unsupported event");
-	}
-
-	const path = event.composedPath();
-	const optionNode = path.shift();
-
-	const state = optionNode.getAttribute("data-monster-state");
-	if (state !== mode) {
-		const handler = optionNode.querySelector(
-			"[data-monster-role=folder-handler]",
-		);
-		if (handler instanceof HTMLElement) {
-			fireEvent(handler, "click");
-		}
-	}
+    validateInstance(event, Event);
+
+    if (typeof event.composedPath !== "function") {
+        throw new Error("unsupported event");
+    }
+
+    const path = event.composedPath();
+    const optionNode = path.shift();
+
+    const state = optionNode.getAttribute("data-monster-state");
+    if (state !== mode) {
+        const handler = optionNode.querySelector(
+            "[data-monster-role=folder-handler]",
+        );
+        if (handler instanceof HTMLElement) {
+            fireEvent(handler, "click");
+        }
+    }
 }
 
 /**
@@ -261,25 +302,25 @@ function closeOrOpenCurrentOption(event, mode) {
  * @private
  */
 function formatKeyLabel(node) {
-	validateInstance(node, Node);
+    validateInstance(node, Node);
 
-	const v = node.value;
-	if (v === undefined) {
-		throw new Error("the object has no value for the specified id");
-	}
+    const v = node.value;
+    if (v === undefined) {
+        throw new Error("the object has no value for the specified id");
+    }
 
-	const label = new Formatter(v).format(
-		this.getOption("mapping.labelTemplate", ""),
-	);
+    const label = new Formatter(v).format(
+        this.getOption("mapping.labelTemplate", ""),
+    );
 
-	const value = new Formatter(v).format(
-		this.getOption("mapping.valueTemplate", ""),
-	);
+    const value = new Formatter(v).format(
+        this.getOption("mapping.valueTemplate", ""),
+    );
 
-	return {
-		value,
-		label,
-	};
+    return {
+        value,
+        label,
+    };
 }
 
 /**
@@ -288,27 +329,27 @@ function formatKeyLabel(node) {
  * @return {Array}
  */
 function buildTreeLabels(value) {
-	if (!this[internalNodesSymbol]) {
-		return [value];
-	}
-
-	let node = this[internalNodesSymbol].get(value);
-	if (node === undefined) {
-		node = this[internalNodesSymbol].get(parseInt(value));
-	}
-
-	const parts = [];
-
-	if (node instanceof Node) {
-		let ptr = node;
-		while (ptr) {
-			const formattedValues = formatKeyLabel.call(this, ptr);
-			parts.unshift(formattedValues.label);
-			ptr = ptr.parent;
-		}
-	}
-
-	return parts;
+    if (!this[internalNodesSymbol]) {
+        return [value];
+    }
+
+    let node = this[internalNodesSymbol].get(value);
+    if (node === undefined) {
+        node = this[internalNodesSymbol].get(parseInt(value));
+    }
+
+    const parts = [];
+
+    if (node instanceof Node) {
+        let ptr = node;
+        while (ptr) {
+            const formattedValues = formatKeyLabel.call(this, ptr);
+            parts.unshift(formattedValues.label);
+            ptr = ptr.parent;
+        }
+    }
+
+    return parts;
 }
 
 /**
@@ -326,9 +367,9 @@ function buildTreeLabels(value) {
  * @return {string}
  */
 function formatHierarchicalSelection(value) {
-	return buildTreeLabels
-		.call(this, value)
-		.join(this.getOption("formatter.separator", " / "));
+    return buildTreeLabels
+        .call(this, value)
+        .join(this.getOption("formatter.separator", " / "));
 }
 
 /**
@@ -342,99 +383,99 @@ const openOptionEventHandler = Symbol("openOptionEventHandler");
  * @throws {Error} no shadow-root is defined
  */
 function initEventHandler() {
-	if (!this.shadowRoot) {
-		throw new Error("no shadow-root is defined");
-	}
-
-	this[openOptionEventHandler] = (event) => {
-		const element = findTargetElementFromEvent(
-			event,
-			ATTRIBUTE_ROLE,
-			"folder-handler",
-		);
-		if (!(element instanceof HTMLElement)) {
-			return;
-		}
-
-		const container = findClosestByAttribute(element, ATTRIBUTE_ROLE, "option");
-		const index = container
-			.getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE)
-			.split("-")
-			.pop();
-
-		const currentState = this.getOption(`options.${index}.state`);
-
-		const newState = currentState === "close" ? "open" : "close";
-		this.setOption(`options.${index}.state`, newState);
-
-		const newVisibility = newState === "open" ? "visible" : "hidden";
-
-		if (container.hasAttribute(ATTRIBUTE_INTEND)) {
-			const intend = container.getAttribute(ATTRIBUTE_INTEND);
-
-			let ref = container.nextElementSibling;
-			const childIntend = parseInt(intend) + 1;
-
-			const cmp = (a, b) => {
-				if (newState === "open") {
-					return a === b;
-				}
-
-				return a >= b;
-			};
-
-			while (
-				ref?.hasAttribute(ATTRIBUTE_INTEND) &&
-				cmp(parseInt(ref.getAttribute(ATTRIBUTE_INTEND)), childIntend)
-			) {
-				const refIndex = ref
-					.getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE)
-					.split("-")
-					.pop();
-				this.setOption(`options.${refIndex}.visibility`, newVisibility);
-
-				if (newState === "close") {
-					this.setOption(`options.${refIndex}.state`, "close");
-				}
-
-				ref = ref.nextElementSibling;
-			}
-		}
-	};
-
-	this[keyEventHandler] = (event) => {
-		const path = event.composedPath();
-		const element = path?.[0];
-
-		let role;
-
-		if (element instanceof HTMLElement) {
-			if (element.hasAttribute(ATTRIBUTE_ROLE)) {
-				role = element.getAttribute(ATTRIBUTE_ROLE);
-			} else if (element === this) {
-				show.call(this);
-				focusFilter.call(this);
-			} else {
-				const e = element.closest(`[${ATTRIBUTE_ROLE}]`);
-				if (e instanceof HTMLElement && e.hasAttribute()) {
-					role = e.getAttribute(ATTRIBUTE_ROLE);
-				}
-			}
-		} else {
-			return;
-		}
-
-		switch (role) {
-			case "option-label":
-			case "option-control":
-			case "option":
-				handleOptionKeyboardEvents.call(this, event);
-				break;
-		}
-	};
-
-	this.shadowRoot.addEventListener("keydown", this[keyEventHandler]);
-	this.shadowRoot.addEventListener("click", this[openOptionEventHandler]);
+    if (!this.shadowRoot) {
+        throw new Error("no shadow-root is defined");
+    }
+
+    this[openOptionEventHandler] = (event) => {
+        const element = findTargetElementFromEvent(
+            event,
+            ATTRIBUTE_ROLE,
+            "folder-handler",
+        );
+        if (!(element instanceof HTMLElement)) {
+            return;
+        }
+
+        const container = findClosestByAttribute(element, ATTRIBUTE_ROLE, "option");
+        const index = container
+            .getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE)
+            .split("-")
+            .pop();
+
+        const currentState = this.getOption(`options.${index}.state`);
+
+        const newState = currentState === "close" ? "open" : "close";
+        this.setOption(`options.${index}.state`, newState);
+
+        const newVisibility = newState === "open" ? "visible" : "hidden";
+
+        if (container.hasAttribute(ATTRIBUTE_INTEND)) {
+            const intend = container.getAttribute(ATTRIBUTE_INTEND);
+
+            let ref = container.nextElementSibling;
+            const childIntend = parseInt(intend) + 1;
+
+            const cmp = (a, b) => {
+                if (newState === "open") {
+                    return a === b;
+                }
+
+                return a >= b;
+            };
+
+            while (
+                ref?.hasAttribute(ATTRIBUTE_INTEND) &&
+                cmp(parseInt(ref.getAttribute(ATTRIBUTE_INTEND)), childIntend)
+                ) {
+                const refIndex = ref
+                    .getAttribute(ATTRIBUTE_UPDATER_INSERT_REFERENCE)
+                    .split("-")
+                    .pop();
+                this.setOption(`options.${refIndex}.visibility`, newVisibility);
+
+                if (newState === "close") {
+                    this.setOption(`options.${refIndex}.state`, "close");
+                }
+
+                ref = ref.nextElementSibling;
+            }
+        }
+    };
+
+    this[keyEventHandler] = (event) => {
+        const path = event.composedPath();
+        const element = path?.[0];
+
+        let role;
+
+        if (element instanceof HTMLElement) {
+            if (element.hasAttribute(ATTRIBUTE_ROLE)) {
+                role = element.getAttribute(ATTRIBUTE_ROLE);
+            } else if (element === this) {
+                show.call(this);
+                focusFilter.call(this);
+            } else {
+                const e = element.closest(`[${ATTRIBUTE_ROLE}]`);
+                if (e instanceof HTMLElement && e.hasAttribute()) {
+                    role = e.getAttribute(ATTRIBUTE_ROLE);
+                }
+            }
+        } else {
+            return;
+        }
+
+        switch (role) {
+            case "option-label":
+            case "option-control":
+            case "option":
+                handleOptionKeyboardEvents.call(this, event);
+                break;
+        }
+    };
+
+    this.shadowRoot.addEventListener("keydown", this[keyEventHandler]);
+    this.shadowRoot.addEventListener("click", this[openOptionEventHandler]);
 }
 
 /**
@@ -448,14 +489,14 @@ function initEventHandler() {
  * @return {object}
  */
 function initOptionsFromArguments() {
-	const options = {};
+    const options = {};
 
-	const url = this.getAttribute(ATTRIBUTE_FORM_URL);
-	if (isString(url)) {
-		options["url"] = new URL(url).toString();
-	}
+    const url = this.getAttribute(ATTRIBUTE_FORM_URL);
+    if (isString(url)) {
+        options["url"] = new URL(url).toString();
+    }
 
-	return options;
+    return options;
 }
 
 /**
@@ -463,8 +504,8 @@ function initOptionsFromArguments() {
  * @return {string}
  */
 function getTemplate() {
-	// language=HTML
-	return `
+    // language=HTML
+    return `
         <template id="options">
             <div data-monster-role="option"
                  tabindex="-1"
diff --git a/source/data/buildmap.mjs b/source/data/buildmap.mjs
index 656abaf924401b348f7ddc3202043856319c1d27..3e20319e836c054327854035da70cc1c1145059e 100644
--- a/source/data/buildmap.mjs
+++ b/source/data/buildmap.mjs
@@ -17,7 +17,7 @@ import { validateString } from "../types/validate.mjs";
 import { clone } from "../util/clone.mjs";
 import { DELIMITER, Pathfinder, WILDCARD } from "./pathfinder.mjs";
 
-export { buildMap, PARENT, assembleParts };
+export { buildMap, PARENT, assembleParts};
 
 /**
  * @type {string}
@@ -361,7 +361,7 @@ function buildFlatMap(subject, selector, key, parentMap) {
  * @param {*} defaultValue
  * @return {*}
  */
-function build(subject, definition, defaultValue) {
+export function build(subject, definition, defaultValue) {
 	if (definition === undefined) return defaultValue ? defaultValue : subject;
 	validateString(definition);
 
diff --git a/source/dom/updater.mjs b/source/dom/updater.mjs
index 2c1ec37e60cb09d781a34e205598655aa255b9e6..303874215f536065782bd34b9af891bd5242051f 100644
--- a/source/dom/updater.mjs
+++ b/source/dom/updater.mjs
@@ -395,7 +395,7 @@ function retrieveAndSetValue(element) {
                 element.constructor.prototype,
                 "value",
             )?.["get"]) ||
-        element.hasOwnProperty("value")
+        "value" in element
     ) {
         value = element?.["value"];
     } else {