@@ -54,7 +54,7 @@ pub const IntersectionObserver = struct {
5454 var options = IntersectionObserverOptions {
5555 .root = parser .documentToNode (parser .documentHTMLToDocument (state .document .? )),
5656 .rootMargin = "0px 0px 0px 0px" ,
57- .threshold = & default_threshold ,
57+ .threshold = &.{ 0.0 } ,
5858 };
5959 if (options_ ) | * o | {
6060 if (o .root ) | root | {
@@ -74,10 +74,16 @@ pub const IntersectionObserver = struct {
7474 self .observed_entries = .{}; // We don't free as it is on an arena
7575 }
7676
77- pub fn _observe (self : * IntersectionObserver , targetElement : * parser.Element ) ! void {
77+ pub fn _observe (self : * IntersectionObserver , target_element : * parser.Element ) ! void {
78+ for (self .observed_entries .items ) | * observer | {
79+ if (observer .target == target_element ) {
80+ return ; // Already observed
81+ }
82+ }
83+
7884 try self .observed_entries .append (self .state .arena , .{
7985 .state = self .state ,
80- .target = targetElement ,
86+ .target = target_element ,
8187 .options = & self .options ,
8288 });
8389
@@ -107,7 +113,6 @@ const IntersectionObserverOptions = struct {
107113 rootMargin : ? []const u8 ,
108114 threshold : ? []const f32 ,
109115};
110- const default_threshold = [_ ]f32 {0.0 };
111116
112117// https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry
113118// https://w3c.github.io/IntersectionObserver/#intersection-observer-entry
@@ -118,7 +123,7 @@ pub const IntersectionObserverEntry = struct {
118123
119124 // Returns the bounds rectangle of the target element as a DOMRectReadOnly. The bounds are computed as described in the documentation for Element.getBoundingClientRect().
120125 pub fn get_boundingClientRect (self : * const IntersectionObserverEntry ) ! Element.DOMRect {
121- return self .state .renderer .getRect (self .target ); // Does this ever change?
126+ return self .state .renderer .getRect (self .target );
122127 }
123128
124129 // Returns the ratio of the intersectionRect to the boundingClientRect.
@@ -139,6 +144,10 @@ pub const IntersectionObserverEntry = struct {
139144 // Returns a DOMRectReadOnly for the intersection observer's root.
140145 pub fn get_rootBounds (self : * const IntersectionObserverEntry ) ! Element.DOMRect {
141146 const root = self .options .root .? ;
147+ if (@intFromPtr (root ) == @intFromPtr (self .state .document .? )) {
148+ return self .state .renderer .boundingRect ();
149+ }
150+
142151 const root_type = try parser .nodeType (root );
143152
144153 var element : * parser.Element = undefined ;
@@ -179,7 +188,7 @@ test "Browser.DOM.IntersectionObserver" {
179188 }, .{});
180189
181190 // This test is documenting current behavior, not correct behavior.
182- // Currently every time observe is called, the callback is called with all entries. 1 + 2 = 3
191+ // Currently every time observe is called, the callback is called with all entries.
183192 try runner .testCases (&.{
184193 .{ "let count_b = 0;" , "undefined" },
185194 .{ "let observer_b = new IntersectionObserver(entries => {count_b = entries.length;});" , "undefined" },
@@ -191,6 +200,17 @@ test "Browser.DOM.IntersectionObserver" {
191200 .{ "count_b;" , "2" },
192201 }, .{});
193202
203+ // Re-observing is a no-op
204+ try runner .testCases (&.{
205+ .{ "let count_bb = 0;" , "undefined" },
206+ .{ "let observer_bb = new IntersectionObserver(entries => {count_bb = entries.length;});" , "undefined" },
207+ .{ "const bb1 = document.createElement('div');" , "undefined" },
208+ .{ "observer_bb.observe(bb1);" , "undefined" },
209+ .{ "count_bb;" , "1" },
210+ .{ "observer_bb.observe(bb1);" , "undefined" },
211+ .{ "count_bb;" , "1" }, // Still 1, not 2
212+ }, .{});
213+
194214 // Unobserve
195215 try runner .testCases (&.{
196216 .{ "let count_c = 0;" , "undefined" },
@@ -234,8 +254,9 @@ test "Browser.DOM.IntersectionObserver" {
234254 .{ "entry.intersectionRect.width;" , "1" },
235255 .{ "entry.intersectionRect.height;" , "1" },
236256 .{ "entry.isIntersecting;" , "true" },
237- .{ "entry.rootBounds.x;" , "2" }, // This is not the prefered behaviour, the Window rect should wrap all elements so x -> 0
238- .{ "entry.rootBounds.width;" , "1" }, // width -> clientWidth
257+ .{ "entry.rootBounds.x;" , "0" },
258+ .{ "entry.rootBounds.y;" , "0" },
259+ .{ "entry.rootBounds.width;" , "2" },
239260 .{ "entry.rootBounds.height;" , "1" },
240261 .{ "entry.target;" , "[object HTMLDivElement]" },
241262 }, .{});
@@ -252,6 +273,6 @@ test "Browser.DOM.IntersectionObserver" {
252273 "undefined" ,
253274 },
254275 .{ "new_observer.observe(document.createElement('div'));" , "undefined" },
255- .{ "new_entry.rootBounds.x;" , "3 " },
276+ .{ "new_entry.rootBounds.x;" , "2 " },
256277 }, .{});
257278}
0 commit comments