Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

Element#matches() compiles the selector on every call

Đang mở
#348 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 17 ngày

@jonasporto đang làm issue này rồi.

Từ ngày 16/10/2026.

  • #349 của @jonasporto — đang mở

Đánh giá

Độ khó
2/5
Thời gian dự kiến
1-3 giờ
Mức phù hợp với người mới
35/100
Loại issue
Tái cấu trúc
Độ rõ ràng
Đặc tả rõ ràng
Mức độ hoạt động
Đình trệ
Công nghệ
css, javascript
Lĩnh vực
backend, performance

Hướng nghiên cứu

The hot path is esm/shared/matches.js near line 109, where Element#matches() passes the selector string to CSSselect.is(), which recompiles it on every call; prepareMatch already compiles once per call for querySelector* and closest(), so look there for the pattern to reuse. Pull request #349 is already open against this, so check it before starting. Done means a compiled selector is cached per selector string and document kind in a small bounded Map, :scope selectors still compile per call, and the existing matches tests pass with coverage unchanged.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Element#matches(selectors) parses and compiles the selector again on every call. Code that tests many elements against the same few selectors (resolving a <style> sheet over an SVG chart, for example) spends most of its time in css-what's parser and css-select's compiler rather than in matching.

// npm i linkedom && node matches.mjs
import { parseHTML } from 'linkedom';

let svg = '<svg id="chart">';
for (let i = 0; i < 400; i++)
  svg += `<g class="node n${i % 7}"><rect class="box"></rect><g class="label"><text class="title"><tspan>${i}</tspan></text></g></g>`;
const { document } = parseHTML(`<!doctype html><html><body>${svg}</svg></body></html>`);

const selectors = [];
for (const a of ['#chart', '#chart .node', '#chart g.label', 'svg'])
  for (const b of ['rect', 'text', 'tspan', '.label', '.title', '.box', '.n3', 'g', '.cluster rect', '.edgeLabel', 'g.node', '.missing'])
    selectors.push(`${a} ${b}`);

const elements = [...document.querySelectorAll('svg, svg *')];
const t = performance.now();
for (const el of elements)
  for (const sel of selectors)
    el.matches(sel);
console.log(`${elements.length * selectors.length} calls: ${(performance.now() - t).toFixed(0)} ms`);

Node 22.17.0, macOS, median of runs:

96,048 matches() calls
linkedom 0.18.13 ~112 ms
linkedom main (3fcf145) ~108 ms
same, with the compiled selector kept per selector string ~20 ms

A larger run (2,001 elements × 50 selectors, 300k calls), in ms per 100k calls: linkedom 0.18.13 158, main 111, with the compiled selector kept 17; happy-dom 21.0.3 10, jsdom 30.1.3 209.

A CPU profile of main shows css-what parseSelector/unescapeCSS, css-select compileToken/escapeRegex and GC on top; the matching itself is a small share.

Where: esm/shared/matches.js#L109 passes the selector string to CSSselect.is(), which calls compile(query, options) each time (css-select 7.0.0, dist/index.js, is). querySelector* and closest() compile once per call through prepareMatch, so it is matches() that pays per element.

Possible fix: keep the compiled function per selector string and document kind (xmlMode), in a small bounded Map; selectors with :scope keep compiling per call since their context is the element. I have this with a test (coverage unchanged) and can open a PR.

Ngôn ngữ chính
HTML
Star
2.1k
Fork
112
Merge trung bình
11 ngày 1 giờ
Pull request đã merge (30 ngày)
1

Chuẩn bị môi trường

Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của WebReflection/linkedom

Tất cả issue của WebReflection/linkedom

Issue tương tự

Thêm issue về Backend & API Design

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.