From dca99c338eae9fd37b4a0ec9f948c2632afc9f0b Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Thu, 25 Dec 2025 17:00:27 +0800 Subject: [PATCH] more Animation accessors --- src/browser/js/js.zig | 6 +-- src/browser/tests/animation/animation.html | 15 ++++++ src/browser/webapi/Element.zig | 4 +- src/browser/webapi/animation/Animation.zig | 63 ++++++++++++++++++++-- 4 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 src/browser/tests/animation/animation.html diff --git a/src/browser/js/js.zig b/src/browser/js/js.zig index 882d00d7..c56e41d8 100644 --- a/src/browser/js/js.zig +++ b/src/browser/js/js.zig @@ -85,12 +85,12 @@ pub const PromiseResolver = struct { } fn _resolve(self: PromiseResolver, value: anytype) !void { const context = self.context; - const js_value = try context.zigValueToJs(value); + const js_value = try context.zigValueToJs(value, .{}); if (self.resolver.resolve(context.v8_context, js_value) == null) { return error.FailedToResolvePromise; } - self.runMicrotasks(); + self.context.runMicrotasks(); } pub fn reject(self: PromiseResolver, comptime source: []const u8, value: anytype) void { @@ -105,7 +105,7 @@ pub const PromiseResolver = struct { if (self.resolver.reject(context.v8_context, js_value) == null) { return error.FailedToRejectPromise; } - self.runMicrotasks(); + self.context.runMicrotasks(); } }; diff --git a/src/browser/tests/animation/animation.html b/src/browser/tests/animation/animation.html new file mode 100644 index 00000000..27e562a0 --- /dev/null +++ b/src/browser/tests/animation/animation.html @@ -0,0 +1,15 @@ + + + + diff --git a/src/browser/webapi/Element.zig b/src/browser/webapi/Element.zig index d2a1b508..0fbf547f 100644 --- a/src/browser/webapi/Element.zig +++ b/src/browser/webapi/Element.zig @@ -724,8 +724,8 @@ pub fn getAnimations(_: *const Element) []*Animation { return &.{}; } -pub fn animate(_: *Element, _: js.Object, _: js.Object) !Animation { - return Animation.init(); +pub fn animate(_: *Element, _: js.Object, _: js.Object, page: *Page) !*Animation { + return Animation.init(page); } pub fn closest(self: *Element, selector: []const u8, page: *Page) !?*Element { diff --git a/src/browser/webapi/animation/Animation.zig b/src/browser/webapi/animation/Animation.zig index 2fecfa95..b8f83143 100644 --- a/src/browser/webapi/animation/Animation.zig +++ b/src/browser/webapi/animation/Animation.zig @@ -21,8 +21,13 @@ const Page = @import("../../Page.zig"); const Animation = @This(); -pub fn init() !Animation { - return .{}; +_effect: ?js.Object = null, +_timeline: ?js.Object = null, +_ready_resolver: ?js.PromiseResolver = null, +_finished_resolver: ?js.PromiseResolver = null, + +pub fn init(page: *Page) !*Animation { + return page._factory.create(Animation{}); } pub fn play(_: *Animation) void {} @@ -31,6 +36,48 @@ pub fn cancel(_: *Animation) void {} pub fn finish(_: *Animation) void {} pub fn reverse(_: *Animation) void {} +pub fn getPlayState(_: *const Animation) []const u8 { + return "finished"; +} + +pub fn getPending(_: *const Animation) bool { + return false; +} + +pub fn getFinished(self: *Animation, page: *Page) !js.Promise { + if (self._finished_resolver == null) { + const resolver = page.js.createPromiseResolver(.none); + resolver.resolve("Animation.getFinished", self); + self._finished_resolver = resolver; + } + return self._finished_resolver.?.promise(); +} + +pub fn getReady(self: *Animation, page: *Page) !js.Promise { + // never resolved, because we're always "finished" + if (self._ready_resolver == null) { + const resolver = page.js.createPromiseResolver(.none); + self._ready_resolver = resolver; + } + return self._ready_resolver.?.promise(); +} + +pub fn getEffect(self: *const Animation) ?js.Object { + return self._effect; +} + +pub fn setEffect(self: *Animation, effect: js.Object) !void { + self._effect = try effect.persist(); +} + +pub fn getTimeline(self: *const Animation) ?js.Object { + return self._timeline; +} + +pub fn setTimeline(self: *Animation, timeline: js.Object) !void { + self._timeline = try timeline.persist(); +} + pub const JsApi = struct { pub const bridge = js.Bridge(Animation); @@ -38,7 +85,6 @@ pub const JsApi = struct { pub const name = "Animation"; pub const prototype_chain = bridge.prototypeChain(); pub var class_id: bridge.ClassId = undefined; - pub const empty_with_no_proto = true; }; pub const play = bridge.function(Animation.play, .{}); @@ -46,4 +92,15 @@ pub const JsApi = struct { pub const cancel = bridge.function(Animation.cancel, .{}); pub const finish = bridge.function(Animation.finish, .{}); pub const reverse = bridge.function(Animation.reverse, .{}); + pub const playState = bridge.accessor(Animation.getPlayState, null, .{}); + pub const pending = bridge.accessor(Animation.getPending, null, .{}); + pub const finished = bridge.accessor(Animation.getFinished, null, .{}); + pub const ready = bridge.accessor(Animation.getReady, null, .{}); + pub const effect = bridge.accessor(Animation.getEffect, Animation.setEffect, .{}); + pub const timeline = bridge.accessor(Animation.getTimeline, Animation.getTimeline, .{}); }; + +const testing = @import("../../../testing.zig"); +test "WebApi: Animation" { + try testing.htmlRunner("animation/animation.html", .{}); +}