Commit a547729a authored by Jens Oliver Meiert's avatar Jens Oliver Meiert Committed by David Sveningsson
Browse files

perf: optimize performance with caching and loop refinements

parent d9f22aaa
Loading
Loading
Loading
Loading
+13 −8
Original line number Diff line number Diff line
@@ -37,15 +37,20 @@ export class Context {
	}

	public consume(n: number, state: State): void {
		/* poor mans line counter :( */
		let consumed = this.string.slice(0, n);
		let offset;
		while ((offset = consumed.indexOf("\n")) >= 0) {
			this.line++;
			this.column = 1;
			consumed = consumed.slice(offset + 1);
		let lastNewline = -1;
		let newlines = 0;
		for (let i = 0; i < n; i++) {
			if (this.string[i] === "\n") {
				newlines++;
				lastNewline = i;
			}
		}
		if (newlines > 0) {
			this.line += newlines;
			this.column = n - lastNewline;
		} else {
			this.column += n;
		}
		this.column += consumed.length;
		this.offset += n;

		/* remove N chars */
+13 −4
Original line number Diff line number Diff line
@@ -640,10 +640,19 @@ export class HtmlElement extends DOMNode {
	}

	public getElementsByTagName(tagName: string): HtmlElement[] {
		return this.childElements.reduce<HtmlElement[]>((matches, node) => {
		const matches: HtmlElement[] = [];
		/* eslint-disable-next-line unicorn/prefer-query-selector -- querySelectorAll() is less optimized here */
			return matches.concat(node.is(tagName) ? [node] : [], node.getElementsByTagName(tagName));
		}, []);
		this.collectByTagName(tagName, matches);
		return matches;
	}

	private collectByTagName(tagName: string, matches: HtmlElement[]): void {
		for (const node of this.childElements) {
			if (node.is(tagName)) {
				matches.push(node);
			}
			node.collectByTagName(tagName, matches);
		}
	}

	public querySelector(selector: string): HtmlElement | null {
+9 −1
Original line number Diff line number Diff line
@@ -2,12 +2,20 @@ import { ComplexSelector } from "./complex-selector";
import { getCompounds } from "./get-compounds";
import { type Selector } from "./selector";

const cache = new Map<string, Selector>();

/**
 * Parse given selector.
 *
 * @internal
 */
export function parseSelector(selector: string): Selector {
	const cached = cache.get(selector);
	if (cached) {
		return cached;
	}
	const compounds = getCompounds(selector);
	return ComplexSelector.fromCompounds(compounds);
	const result = ComplexSelector.fromCompounds(compounds);
	cache.set(selector, result);
	return result;
}