y
"); + expect(end).toBe("my-widget"); + expect(out).toBe("y
"); + }); + + it("stray end tags with a deep open-element stack", () => { + // Each used to trigger a full reverse scan of the open-element + // stack in lol-html's selectors_vm, so N unclosed plus N stray + // was O(N^2). At this N the old behaviour pins a core for >10s; after + // the fix the miss is O(1) and this completes in a few hundred ms. + const N = 80_000; + const doc = Buffer.alloc(7 * N, "").toString(); + const out = new HTMLRewriter().on("nomatch", { element() {} }).transform(doc); + expect(out.length).toBe(doc.length); + expect(out).toBe(doc); + }); + + it("descendant combinator over deeply nested matching elements", () => { + // Matching "div div" used to re-execute the same hereditary jump once + // per ancestor for every start tag, giving O(depth^2). With the + // deduplicated active-jump set it is O(depth). + const N = 25_000; + const open = Buffer.alloc(5 * N, "