Repository: unoplatform/uno
File: src/Uno.UI.Runtime.Skia.WebAssembly.Browser/ts/Runtime/BrowserPointerInputSource.ts (TypeScript)

Code before:
		}


		// Fast ancestry check. True if the event originated inside the native host subtree.
		// Walks parents; hops out of shadow roots via getRootNode().host when present.
		// Uses identity comparisons only; no selector matching or allocations.
		private isEventFromNativeElementHost(eventTarget: EventTarget | null): boolean {
			const host: HTMLElement | null = this.getNativeElementHostCached();
			if (host === null) {
				return false; // No host to exclude.
			}

			let currentNode = eventTarget as Node | null;

			while (currentNode !== null) {
				// Identity compare for cheapest match.
				if (currentNode === host) {
					return true;
				}

				// Shadow DOM hop if applicable; otherwise climb light DOM.
				const rootNode: any = typeof (currentNode as any).getRootNode === "function"
					? (currentNode as any).getRootNode()
					: null;

				if (rootNode !== null && rootNode.host instanceof Node) {
					currentNode = rootNode.host as Node;
				} else {
					currentNode = currentNode.parentNode;
				}
			}

			return false;
		}

		private onPointerEventReceived(evt: PointerEvent): void {
			let id = (evt.target as HTMLElement)?.id;
			if (id === "uno-enable-accessibility") {
				// We have a div to enable accessibility (see enableA11y in WebAssemblyWindowWrapper).
				// Pressing space on keyboard to click it will trigger pointer event which we want to ignore.
				return;
			}

			if (this.isEventFromNativeElementHost(evt.target)) {
				// Events from the native host are handled by the native control directly.
				// We don't want to interfere with them.
				return;
			}

			const event = BrowserPointerInputSource.toHtmlPointerEvent(evt.type);


Review comment (suggestion):
This is probably why it's working actually, the `host` property doesn't seem to exist on a [`Node`](https://developer.mozilla.org/en-US/docs/Web/API/Node) so the `rootNode.host instanceof Node` is always `false` so we always use the `currentNode.parentNode`.

Unless I misunderstood something, I think could just remove all the `getRootNode()` and just iterate the `currentNode.parentNode`

Code after:
			return this._nativeElementHost;
		}


		// Returns true if the event originated from within the native host subtree.
		// Traverses regular DOM first, then crosses Shadow DOM boundaries when required.
		// Uses identity comparisons only; avoids selector matching, allocations, and redundant lookups.
		private isEventFromNativeElementHost(eventTarget: EventTarget | null) {
			const hostElement = this.getNativeElementHostCached();
			if (hostElement === null) {
				return false; // No host exists; nothing to filter.
			}

			let currentNode = eventTarget as Node | null;

			while (currentNode !== null) {
				// Fast identity comparison.
				if (currentNode === hostElement) {
					return true;
				}

				// Normal DOM climb first (fastest path)
				const parent = (currentNode as any).parentNode as Node | null;
				if (parent) {
					currentNode = parent;
					continue;
				}

				// Only if parentNode is null, check for a shadow boundary.
				const rootNode = currentNode.getRootNode();

				// If we're inside a shadow root, jump to its host to continue traversal
				if (rootNode instanceof ShadowRoot && rootNode.host) {
					currentNode = rootNode.host as Node; // cross shadow boundary
					continue;
				}

				// Reached the top (Document or no further nodes)
				break;
			}

			return false;
		}

		private onPointerEventReceived(evt: PointerEvent): void {
			let id = (evt.target as HTMLElement)?.id;
			if (id === "uno-enable-accessibility") {
				// We have a div to enable accessibility (see enableA11y in WebAssemblyWindowWrapper).
				// Pressing space on keyboard to click it will trigger pointer event which we want to ignore.
				return;
			}