perf(finder,orphan): 第一層掃描提速——category 記憶化(S3)+orphan 葉塊預計算(S2),保行為

下游效能訴求一(掃描疑 O(n²))之第一層:無狀態、保行為、無公開 API 變更之確定收益。

S3 category 記憶化:finder.category 以 categoryCache(WeakMap<Element, InlineCategory>)記憶化,砍
除 collectRuns/jiyaAdjacency/jinze/split 跨 pass 對同一元素之重複 el.matches()(pill/isolate/
avoid 選擇器)。安全:單次 render 內一元素之分類恆定(class/skip 屬性/nodeName 不因 render 變更;
jz-* 包裹按 nodeName 分類亦恆定),且 Finder 隨 makeCtx 每次 render 重建 → 快取僅存活單次 render、
無跨 render 失效(持久化屬 C1,另議)。亲驗(正確補 Element.prototype.matches):pill/isolate 密集
頁面 el.matches() 8204→5842(約降三成);暫禁快取則 computeCategory 2322 vs 1041(命中率 55%)。

S2 orphan 葉塊預計算:以一趟上攀預計算「非葉塊」Set 取代逐塊 block.querySelector(sel) 掃整棵子樹之
O(Σ塊子樹)(深塊嵌套下 O(n²));某塊為另一塊之最近塊祖先 ⟺ 含塊級後代,scope 無涉、與原
querySelector 同口徑,行為等價。sel 亦外提出迴圈。

測試 129→130(+1 鎖定 S2 非葉塊等價:含巢狀塊之容器跳過、僅內層葉塊綁定);全綠、輸出不變。
文檔:ARCHITECTURE §4.1(category 記憶化)+§6.5.1(orphan 葉塊預計算)。

新發現(待議、非本層):剩餘 el.matches() 之最大來源為 insidePill 之「逐文本節點沿祖先鏈 pillMatches」
(eachTextNode 每文本節點一趟、未記憶化)——可作下一項提速機會。
This commit is contained in:
2026-07-11 19:56:53 +08:00
parent 3fbb2904ef
commit 168e9e73f0
7 changed files with 138 additions and 6 deletions
+17
View File
@@ -1077,6 +1077,23 @@ test("垂懸字 攀升守衛 revert:綁整 span 之退化路徑 render→rever
assert.equal(p.textContent, "開頭較長的一段文字內容之後接續結尾文字", "textContent 還原");
});
// S2 非葉塊預計算(取代逐塊 querySelector)等價性:含巢狀塊之容器(div>p)——容器為非葉、
// 直文字不綁(實義字屬內層段落),僅內層葉塊 <p> 綁定。鎖定「非葉塊跳過」路徑之行為不變。
test("垂懸字 S2 非葉塊:含巢狀塊之容器跳過、僅內層葉塊綁定", () =>
{
const { document } = setupDom(
'<div lang="zh-Hant">容器直接文字結尾甲乙<p>內層段落的實義字丙丁。</p></div>',
);
createJuzhen().render(document.body);
const div = document.querySelector("div");
const p = document.querySelector("p");
const pOrphan = p.querySelector("jz-orphan");
assert.ok(pOrphan, "內層葉塊 <p> 應產生 jz-orphan");
assert.equal(pOrphan.textContent, "丙丁。", "綁定 <p> 末 2 實義字+句號");
const directOrphan = Array.from(div.children).some((c) => c.nodeName === "JZ-ORPHAN");
assert.equal(directOrphan, false, "非葉容器 <div> 之直文字不應被綁入 jz-orphan");
});
// ----- 標點懸掛已移除(§6.5.6):hanging 選項保留為 no-op,永不產生 jz-hang-* -----
// 純負 margin 機制為機制級死路(寬度守恆矛盾,CSS 接觸不到斷行器);原生
// hanging-punctuation 為唯一正解但僅 Safari 支援、且與 inline-block 原子互斥。