HS: intersection observer mock + on intersection (+3 tests)
Applied from worktree-agent-ad6e17cbc4ea0c94b (commit 0a0fe314)
with manual re-apply onto post-cluster-26 HEAD:
- Parser: parse-on-feat collects `having margin X threshold Y`
clauses between `from X` and the body; packs them into a
`:having {"margin" M "threshold" T}` dict on the parts list.
- Compiler: scan-on threads a new `having-info` parameter through
all recursions; when event-name is "intersection", wraps the
hs-on call with `(do on-call (hs-on-intersection-attach! target
margin threshold))`.
- Runtime: hs-on-intersection-attach! constructs an
IntersectionObserver with {rootMargin, threshold} options and a
callback that dispatches an "intersection" DOM event carrying
{intersecting, entry} detail.
- Runner: HsIntersectionObserver mock fires the callback
synchronously on observe() with isIntersecting=true so handlers
run during activation; ignores margin/threshold (tests assert
only that the handler fires).
Suite hs-upstream-on: 33/70 -> 36/70 (on intersection: 0/3 -> 3/3).
Smoke 0-195 unchanged at 165/195.
This commit is contained in:
@@ -354,7 +354,26 @@ class HsResizeObserver {
|
||||
}
|
||||
}
|
||||
globalThis.ResizeObserver=HsResizeObserver; globalThis.ResizeObserverEntry=class{};
|
||||
globalThis.IntersectionObserver=class{observe(){}disconnect(){}};
|
||||
// HsIntersectionObserver — cluster-27 intersection mock. Fires the callback
|
||||
// synchronously on observe() with isIntersecting=true so `on intersection`
|
||||
// handlers run during activation. `margin`/`threshold` options are parsed
|
||||
// but ignored (tests only assert the handler fires).
|
||||
class HsIntersectionObserver {
|
||||
constructor(cb, opts) { this._cb = cb; this._opts = opts || {}; this._els = new Set(); }
|
||||
observe(el) {
|
||||
if (!el) return;
|
||||
this._els.add(el);
|
||||
const entry = { target: el, isIntersecting: true, intersectionRatio: 1,
|
||||
boundingClientRect: (el.getBoundingClientRect && el.getBoundingClientRect()) || {},
|
||||
intersectionRect: {}, rootBounds: null, time: 0 };
|
||||
try { this._cb([entry], this); } catch (e) {}
|
||||
}
|
||||
unobserve(el) { if (el) this._els.delete(el); }
|
||||
disconnect() { this._els.clear(); }
|
||||
takeRecords() { return []; }
|
||||
}
|
||||
globalThis.IntersectionObserver = HsIntersectionObserver;
|
||||
globalThis.IntersectionObserverEntry = class {};
|
||||
globalThis.navigator={userAgent:'node'}; globalThis.location={href:'http://localhost/',pathname:'/',search:'',hash:''};
|
||||
globalThis.history={pushState(){},replaceState(){},back(){},forward(){}};
|
||||
globalThis.getSelection=()=>({toString:()=>(globalThis.__test_selection||'')});
|
||||
|
||||
Reference in New Issue
Block a user