Files
obscura/crates
SGavrl 5e23903063 fix: DocumentFragment flattening in appendChild / insertBefore / replaceChild (closes #217) (#221)
Heavy-JS sites build subtrees off-DOM in a DocumentFragment then
appendChild the fragment to a real parent. The DOM spec says: move
the fragment's children up and leave the fragment empty. Our shim
was passing the fragment's _nid straight to the Rust op, so the
fragment node itself got grafted instead of its children, and
framework code that read the inserted nodes' properties hit
"Cannot read properties of undefined (reading 'length')" the moment
it expected a real Element but found our fragment wrapper.

That is what was killing Google Shopping and Bing Shopping for
@Tarun-004 — Bing's anti-malware shim, Google's result-row renderer,
and a sticky-container helper (n.Setup / n.InitializeStickyContainer
in the stack) all use the off-DOM-fragment pattern.

Same defect existed in insertBefore and replaceChild — all three
now flatten DocumentFragment per spec.

While there, three smaller defenses that the same kind of page
exposes:

- _nid validation. Passing a non-Node truthy value (e.g. undefined,
  a plain object) used to silently call op_dom("append_child",
  parent, undefined), which the Rust side parses with unwrap_or(0)
  and grafts as a child of the document root.
- Self-append guard mirrors the insert_before self-cycle fix:
  appendChild(self) is a no-op rather than corrupting the
  sibling-pointer linked list.
- Tree::append_child gains a parent_id == child_id early return as
  defense in depth, parallel to the insert_before guard.

Sanity test in eval mode: DocumentFragment with two children appended
to a host now produces "<span>A</span><span>B</span>" and the
fragment is empty; insertBefore with a fragment containing C produces
"<span>C</span><span>A</span><span>B</span>"; self-append and
appendChild(null) no longer throw.

Verified against the actual reproducer: `obscura fetch --dump text
https://www.bing.com/shop?q=test` no longer produces the
TypeError / "Inline script error" / "Timer error" pattern from
the issue.
2026-06-02 09:38:02 +02:00
..