From 631ec70058152f0804854fc294e4c1c3a2aee0e6 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Fri, 27 Feb 2026 16:19:27 +0100 Subject: [PATCH] add window.scrollBy --- src/browser/tests/window_scroll.html | 36 ++++++++++++++++++++++++++++ src/browser/webapi/Window.zig | 23 ++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 src/browser/tests/window_scroll.html diff --git a/src/browser/tests/window_scroll.html b/src/browser/tests/window_scroll.html new file mode 100644 index 00000000..d5a5c010 --- /dev/null +++ b/src/browser/tests/window_scroll.html @@ -0,0 +1,36 @@ + + + + + + + + + + + + diff --git a/src/browser/webapi/Window.zig b/src/browser/webapi/Window.zig index 194ce397..079760f3 100644 --- a/src/browser/webapi/Window.zig +++ b/src/browser/webapi/Window.zig @@ -515,6 +515,24 @@ pub fn scrollTo(self: *Window, opts: ScrollToOpts, y: ?i32, page: *Page) !void { ); } +pub fn scrollBy(self: *Window, opts: ScrollToOpts, y: ?i32, page: *Page) !void { + // The scroll is relative to the current position. So compute to new + // absolute position. + var absx: i32 = undefined; + var absy: i32 = undefined; + switch (opts) { + .x => |x| { + absx = @as(i32, @intCast(self._scroll_pos.x)) + x; + absy = @as(i32, @intCast(self._scroll_pos.y)) + (y orelse 0); + }, + .opts => |o| { + absx = @as(i32, @intCast(self._scroll_pos.x)) + o.left; + absy = @as(i32, @intCast(self._scroll_pos.y)) + o.top; + }, + } + return self.scrollTo(.{ .x = absx }, absy, page); +} + pub fn unhandledPromiseRejection(self: *Window, rejection: js.PromiseRejection, page: *Page) !void { if (comptime IS_DEBUG) { log.debug(.js, "unhandled rejection", .{ @@ -784,6 +802,7 @@ pub const JsApi = struct { pub const pageYOffset = bridge.accessor(Window.getScrollY, null, .{}); pub const scrollTo = bridge.function(Window.scrollTo, .{}); pub const scroll = bridge.function(Window.scrollTo, .{}); + pub const scrollBy = bridge.function(Window.scrollBy, .{}); // Return false since we don't have secure-context-only APIs implemented // (webcam, geolocation, clipboard, etc.) @@ -818,3 +837,7 @@ const testing = @import("../../testing.zig"); test "WebApi: Window" { try testing.htmlRunner("window", .{}); } + +test "WebApi: Window scroll" { + try testing.htmlRunner("window_scroll.html", .{}); +}