From 907298c6b1933a1e5a52fc35749957b6e4cc9cb6 Mon Sep 17 00:00:00 2001 From: Muki Kiboigo Date: Mon, 8 Dec 2025 05:16:47 -0800 Subject: [PATCH] backport pageshow event --- src/browser/Page.zig | 9 +++ src/browser/js/bridge.zig | 1 + src/browser/webapi/Event.zig | 1 + src/browser/webapi/Window.zig | 14 +++++ .../webapi/event/PageTransitionEvent.zig | 63 +++++++++++++++++++ src/browser/webapi/navigation/Navigation.zig | 2 +- 6 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 src/browser/webapi/event/PageTransitionEvent.zig diff --git a/src/browser/Page.zig b/src/browser/Page.zig index 2cdf6351..9da5f5d1 100644 --- a/src/browser/Page.zig +++ b/src/browser/Page.zig @@ -58,6 +58,7 @@ const MutationObserver = @import("webapi/MutationObserver.zig"); const IntersectionObserver = @import("webapi/IntersectionObserver.zig"); const CustomElementDefinition = @import("webapi/CustomElementDefinition.zig"); const storage = @import("webapi/storage/storage.zig"); +const PageTransitionEvent = @import("webapi/event/PageTransitionEvent.zig"); const timestamp = @import("../datetime.zig").timestamp; const milliTimestamp = @import("../datetime.zig").milliTimestamp; @@ -436,6 +437,14 @@ fn _documentIsComplete(self: *Page) !void { self.window._on_load, .{ .inject_target = false, .context = "page load" }, ); + + const pageshow_event = try PageTransitionEvent.init("pageshow", .{}, self); + try self._event_manager.dispatchWithFunction( + self.window.asEventTarget(), + pageshow_event.asEvent(), + self.window._on_pageshow, + .{ .context = "page show" }, + ); } fn pageHeaderDoneCallback(transfer: *Http.Transfer) !void { diff --git a/src/browser/js/bridge.zig b/src/browser/js/bridge.zig index 5a07e5a2..5fccd42c 100644 --- a/src/browser/js/bridge.zig +++ b/src/browser/js/bridge.zig @@ -568,6 +568,7 @@ pub const JsApis = flattenTypes(&.{ @import("../webapi/event/MessageEvent.zig"), @import("../webapi/event/ProgressEvent.zig"), @import("../webapi/event/NavigationCurrentEntryChangeEvent.zig"), + @import("../webapi/event/PageTransitionEvent.zig"), @import("../webapi/MessageChannel.zig"), @import("../webapi/MessagePort.zig"), @import("../webapi/media/MediaError.zig"), diff --git a/src/browser/webapi/Event.zig b/src/browser/webapi/Event.zig index 5db5de85..11da60fd 100644 --- a/src/browser/webapi/Event.zig +++ b/src/browser/webapi/Event.zig @@ -57,6 +57,7 @@ pub const Type = union(enum) { progress_event: *@import("event/ProgressEvent.zig"), composition_event: *@import("event/CompositionEvent.zig"), navigation_current_entry_change_event: *@import("event/NavigationCurrentEntryChangeEvent.zig"), + page_transition_event: *@import("event/PageTransitionEvent.zig"), }; const Options = struct { diff --git a/src/browser/webapi/Window.zig b/src/browser/webapi/Window.zig index ea7467c1..d6b83bb4 100644 --- a/src/browser/webapi/Window.zig +++ b/src/browser/webapi/Window.zig @@ -55,6 +55,7 @@ _performance: Performance, _history: History, _storage_bucket: *storage.Bucket, _on_load: ?js.Function = null, +_on_pageshow: ?js.Function = null, _on_error: ?js.Function = null, // TODO: invoke on error? _on_unhandled_rejection: ?js.Function = null, // TODO: invoke on error _location: *Location, @@ -138,6 +139,18 @@ pub fn setOnLoad(self: *Window, cb_: ?js.Function) !void { } } +pub fn getOnPageShow(self: *const Window) ?js.Function { + return self._on_pageshow; +} + +pub fn setOnPageShow(self: *Window, cb_: ?js.Function) !void { + if (cb_) |cb| { + self._on_pageshow = cb; + } else { + self._on_pageshow = null; + } +} + pub fn getOnError(self: *const Window) ?js.Function { return self._on_error; } @@ -497,6 +510,7 @@ pub const JsApi = struct { pub const CSS = bridge.accessor(Window.getCSS, null, .{ .cache = "CSS" }); pub const customElements = bridge.accessor(Window.getCustomElements, null, .{ .cache = "customElements" }); pub const onload = bridge.accessor(Window.getOnLoad, Window.setOnLoad, .{}); + pub const onpageshow = bridge.accessor(Window.getOnPageShow, Window.setOnPageShow, .{}); pub const onerror = bridge.accessor(Window.getOnError, Window.getOnError, .{}); pub const onunhandledrejection = bridge.accessor(Window.getOnUnhandledRejection, Window.setOnUnhandledRejection, .{}); pub const fetch = bridge.function(Window.fetch, .{}); diff --git a/src/browser/webapi/event/PageTransitionEvent.zig b/src/browser/webapi/event/PageTransitionEvent.zig new file mode 100644 index 00000000..f4cebf54 --- /dev/null +++ b/src/browser/webapi/event/PageTransitionEvent.zig @@ -0,0 +1,63 @@ +// Copyright (C) 2023-2024 Lightpanda (Selecy SAS) +// +// Francis Bouvier +// Pierre Tachoire +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +const log = @import("../../../log.zig"); +// const Window = @import("../html/window.zig").Window; +const Event = @import("../Event.zig"); +const js = @import("../../js/js.zig"); +const Page = @import("../../Page.zig"); + +// https://developer.mozilla.org/en-US/docs/Web/API/PageTransitionEvent +const PageTransitionEvent = @This(); + +const EventInit = struct { + persisted: ?bool = null, +}; + +_proto: *Event, +_persisted: bool, + +pub fn init(typ: []const u8, init_obj: EventInit, page: *Page) !*PageTransitionEvent { + return page._factory.event(typ, PageTransitionEvent{ + ._proto = undefined, + ._persisted = init_obj.persisted orelse false, + }); +} + +pub fn asEvent(self: *PageTransitionEvent) *Event { + return self._proto; +} + +pub fn getPersisted(self: *PageTransitionEvent) bool { + return self._persisted; +} + +const PageTransitionKind = enum { show, hide }; + +pub const JsApi = struct { + pub const bridge = js.Bridge(PageTransitionEvent); + + pub const Meta = struct { + pub const name = "PageTransitionEvent"; + pub const prototype_chain = bridge.prototypeChain(); + pub var class_id: bridge.ClassId = undefined; + }; + + pub const constructor = bridge.constructor(PageTransitionEvent.init, .{}); + pub const persisted = bridge.accessor(PageTransitionEvent.getPersisted, null, .{}); +}; diff --git a/src/browser/webapi/navigation/Navigation.zig b/src/browser/webapi/navigation/Navigation.zig index f6c26d80..e19e8b03 100644 --- a/src/browser/webapi/navigation/Navigation.zig +++ b/src/browser/webapi/navigation/Navigation.zig @@ -329,7 +329,7 @@ pub fn reload(self: *Navigation, _opts: ?ReloadOptions, page: *Page) !Navigation const entry = self.getCurrentEntry(); if (opts.state) |state| { const previous = entry; - entry.state = .{ .source = .navigation, .value = state.toJson(arena) catch return error.DataClone }; + entry._state = .{ .source = .navigation, .value = state.toJson(arena) catch return error.DataClone }; const event = try NavigationCurrentEntryChangeEvent.init( "currententrychange",