diff --git a/src/browser/webapi/navigation/Navigation.zig b/src/browser/webapi/navigation/Navigation.zig index 20fbe9328..508a3c2b7 100644 --- a/src/browser/webapi/navigation/Navigation.zig +++ b/src/browser/webapi/navigation/Navigation.zig @@ -26,6 +26,7 @@ const Factory = @import("../../Factory.zig"); const Event = @import("../Event.zig"); const EventTarget = @import("../EventTarget.zig"); +const ErrorEvent = @import("../event/ErrorEvent.zig"); const log = lp.log; @@ -44,6 +45,8 @@ const NavigationCurrentEntryChangeEvent = @import("../event/NavigationCurrentEnt _proto: *EventTarget, _on_currententrychange: ?js.Function.Global = null, +_on_navigatesuccess: ?js.Function.Global = null, +_on_navigateerror: ?js.Function.Global = null, _current_navigation_kind: ?NavigationKind = null, @@ -66,6 +69,12 @@ pub fn onRemoveFrame(self: *Navigation) void { if (self._on_currententrychange) |cb| cb.release(); self._on_currententrychange = null; + if (self._on_navigatesuccess) |cb| cb.release(); + self._on_navigatesuccess = null; + + if (self._on_navigateerror) |cb| cb.release(); + self._on_navigateerror = null; + for (self._entries.items) |entry| { if (entry._on_dispose) |cb| cb.release(); entry._on_dispose = null; @@ -303,6 +312,29 @@ pub fn replaceEntry( return entry; } +fn fireNavigateSuccess(self: *Navigation, frame: *Frame) void { + if (!frame.hasDirectListeners( + self.asEventTarget(), + "navigatesuccess", + self._on_navigatesuccess, + )) { + return; + } + + const event = Event.initTrusted( + .wrap("navigatesuccess"), + null, + frame.page, + ) catch |err| { + log.warn(.event, "Navigation.fireNavigateSuccess", .{ .err = err }); + return; + }; + + self.dispatch(self._on_navigatesuccess, event, frame) catch |err| { + log.warn(.event, "Navigation.fireNavigateSuccess dispatch", .{ .err = err }); + }; +} + fn fireCurrentEntryChangeEvent( self: *Navigation, previous: *NavigationHistoryEntry, @@ -335,6 +367,16 @@ fn fireCurrentEntryChangeEvent( }; } +fn resolveFinished( + self: *Navigation, + resolver: js.PromiseResolver, + comptime source: []const u8, + frame: *Frame, +) void { + resolver.resolve(source, {}); + self.fireNavigateSuccess(frame); +} + const NavigateOptions = struct { history: ?[]const u8 = null, info: ?js.Value = null, @@ -381,9 +423,8 @@ pub fn navigateInner( committed.resolve("navigation push", {}); // todo: Fire navigate event - finished.resolve("navigation push", {}); - _ = try self.pushEntry(url, .{ .source = .navigation, .value = state }, frame, true); + self.resolveFinished(finished, "navigation push", frame); } else { try frame.scheduleNavigation(url, .{ .reason = .navigation, .kind = kind }, .{ .script = frame }); } @@ -394,9 +435,8 @@ pub fn navigateInner( committed.resolve("navigation replace", {}); // todo: Fire navigate event - finished.resolve("navigation replace", {}); - _ = try self.replaceEntry(url, .{ .source = .navigation, .value = state }, frame, true); + self.resolveFinished(finished, "navigation replace", frame); } else { try frame.scheduleNavigation(url, .{ .reason = .navigation, .kind = kind }, .{ .script = frame }); } @@ -409,7 +449,8 @@ pub fn navigateInner( committed.resolve("navigation traverse", {}); // todo: Fire navigate event - finished.resolve("navigation traverse", {}); + self.fireCurrentEntryChangeEvent(previous, kind, frame); + self.resolveFinished(finished, "navigation traverse", frame); } else { try frame.scheduleNavigation(url, .{ .reason = .navigation, .kind = kind }, .{ .script = frame }); } @@ -423,8 +464,6 @@ pub fn navigateInner( try frame.queueHashChange(old_url, new_url); } - self.fireCurrentEntryChangeEvent(previous, kind, frame); - _ = try committed.persist(); _ = try finished.persist(); return .{ @@ -524,6 +563,24 @@ fn setOnCurrentEntryChange(self: *Navigation, listener: ?js.Function) !void { } } +fn getOnNavigateSuccess(self: *Navigation) ?js.Function.Global { + return self._on_navigatesuccess; +} + +fn setOnNavigateSuccess(self: *Navigation, listener: ?js.Function) !void { + if (self._on_navigatesuccess) |old| old.release(); + self._on_navigatesuccess = if (listener) |l| try l.persistWithThis(self) else null; +} + +fn getOnNavigateError(self: *Navigation) ?js.Function.Global { + return self._on_navigateerror; +} + +fn setOnNavigateError(self: *Navigation, listener: ?js.Function) !void { + if (self._on_navigateerror) |old| old.release(); + self._on_navigateerror = if (listener) |l| try l.persistWithThis(self) else null; +} + pub const JsApi = struct { pub const bridge = js.Bridge(Navigation); @@ -551,6 +608,16 @@ pub const JsApi = struct { Navigation.setOnCurrentEntryChange, .{}, ); + pub const onnavigatesuccess = bridge.accessor( + Navigation.getOnNavigateSuccess, + Navigation.setOnNavigateSuccess, + .{}, + ); + pub const onnavigateerror = bridge.accessor( + Navigation.getOnNavigateError, + Navigation.setOnNavigateError, + .{}, + ); }; const testing = @import("../../../testing.zig");