Skip to content

Commit e32d35b

Browse files
committed
no reobserve rootbounds for Window
1 parent db28336 commit e32d35b

File tree

3 files changed

+41
-13
lines changed

3 files changed

+41
-13
lines changed

src/browser/browser.zig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,15 @@ const FlatRenderer = struct {
828828
};
829829
}
830830

831+
pub fn boundingRect(self: *const FlatRenderer) Element.DOMRect {
832+
return .{
833+
.x = 0.0,
834+
.y = 0.0,
835+
.width = @floatFromInt(self.width()),
836+
.height = @floatFromInt(self.height()),
837+
};
838+
}
839+
831840
pub fn width(self: *const FlatRenderer) u32 {
832841
return @intCast(self.elements.items.len + 1); // +1 since x starts at 1 (use len after append)
833842
}

src/browser/dom/element.zig

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -348,10 +348,8 @@ pub const Element = struct {
348348

349349
// returns a collection of DOMRect objects that indicate the bounding rectangles for each CSS border box in a client.
350350
// We do not render so just always return the element's rect.
351-
pub fn _getClientRects(self: *parser.Element, state: *SessionState) ![]DOMRect {
352-
var heap = try state.arena.create(DOMRect);
353-
heap.* = try state.renderer.getRect(self);
354-
return heap[0..1];
351+
pub fn _getClientRects(self: *parser.Element, state: *SessionState) ![1]DOMRect {
352+
return [_]DOMRect{try state.renderer.getRect(self)};
355353
}
356354

357355
pub fn get_clientWidth(_: *parser.Element, state: *SessionState) u32 {

src/browser/dom/intersection_observer.zig

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)