MediaQueryLis dummy

This commit is contained in:
Karl Seguin
2025-11-01 20:35:06 +08:00
parent 8b3f36c1f8
commit 9138a3c881
10 changed files with 97 additions and 42 deletions

View File

@@ -108,8 +108,3 @@ pub fn runMessageLoop(self: *const Browser) void {
}
self.env.runIdleTasks();
}
const testing = @import("../testing.zig");
test "Browser" {
try testing.htmlRunner("browser.html", .{});
}

View File

@@ -92,7 +92,7 @@ pub fn dispatch(self: *EventManager, target: *EventTarget, event: *Event) !void
event._target = target;
switch (target._type) {
.node => |node| try self.dispatchNode(node, event),
.xhr, .window, .abort_signal => {
.xhr, .window, .abort_signal, .media_query_list => {
const list = self.lookup.getPtr(@intFromPtr(target)) orelse return;
try self.dispatchAll(list, target, event);
},

View File

@@ -442,6 +442,7 @@ pub const JsApis = flattenTypes(&.{
@import("../webapi/Crypto.zig"),
@import("../webapi/css/CSSStyleDeclaration.zig"),
@import("../webapi/css/CSSStyleProperties.zig"),
@import("../webapi/css/MediaQueryList.zig"),
@import("../webapi/Document.zig"),
@import("../webapi/HTMLDocument.zig"),
@import("../webapi/KeyValueList.zig"),

View File

@@ -0,0 +1,37 @@
<!DOCTYPE html>
<head>
<script src="../testing.js"></script>
</head>
<body>
</body>
<script id=matchMedia_basic>
{
const mql = window.matchMedia('(min-width: 600px)');
testing.expectEqual('object', typeof mql);
testing.expectEqual('(min-width: 600px)', mql.media);
testing.expectEqual(false, mql.matches);
}
</script>
<script id=matchMedia_different_queries>
{
const mql1 = window.matchMedia('(max-width: 1024px)');
testing.expectEqual('(max-width: 1024px)', mql1.media);
testing.expectEqual(false, mql1.matches);
const mql2 = window.matchMedia('(prefers-color-scheme: dark)');
testing.expectEqual('(prefers-color-scheme: dark)', mql2.media);
testing.expectEqual(false, mql2.matches);
}
</script>
<script id=matchMedia_event_target>
{
const mql = window.matchMedia('(orientation: portrait)');
testing.expectEqual('function', typeof mql.addEventListener);
testing.expectEqual('function', typeof mql.removeEventListener);
testing.expectEqual('function', typeof mql.dispatchEvent);
}
</script>

View File

@@ -37,4 +37,6 @@
testing.expectEqual('string', typeof plainDoc.URL);
testing.expectEqual('string', typeof document.readyState);
testing.expectEqual('string', typeof plainDoc.readyState);
testing.expectEqual("[object Intl.DateTimeFormat]", new Intl.DateTimeFormat().toString());
</script>

View File

@@ -15,6 +15,7 @@ pub const Type = union(enum) {
window: *@import("Window.zig"),
xhr: *@import("net/XMLHttpRequestEventTarget.zig"),
abort_signal: *@import("AbortSignal.zig"),
media_query_list: *@import("css/MediaQueryList.zig"),
};
pub fn dispatchEvent(self: *EventTarget, event: *Event, page: *Page) !bool {
@@ -62,6 +63,7 @@ pub fn format(self: *EventTarget, writer: *std.Io.Writer) !void {
.window => writer.writeAll("<window>"),
.xhr => writer.writeAll("<XMLHttpRequestEventTarget>"),
.abort_signal => writer.writeAll("<abort_signal>"),
.media_query_list => writer.writeAll("<MediaQueryList>"),
};
}

View File

@@ -65,7 +65,7 @@ pub const JsApi = struct {
pub const hash = bridge.accessor(Location.getHash, null, .{});
pub const pathname = bridge.accessor(Location.getPathname, null, .{});
pub const hostname = bridge.accessor(Location.getHostname, null, .{});
pub const host = bridge.accessor(URL.getHost, null, .{});
pub const host = bridge.accessor(Location.getHost, null, .{});
pub const port = bridge.accessor(Location.getPort, null, .{});
pub const origin = bridge.accessor(Location.getOrigin, null, .{});
pub const protocol = bridge.accessor(Location.getProtocol, null, .{});

View File

@@ -130,41 +130,6 @@ pub fn toString(self: *const URL, page: *const Page) ![:0]const u8 {
return buf.written()[0 .. buf.written().len - 1 :0];
}
fn getUserInfo(self: *const URL) ?[]const u8 {
const raw = self._raw;
const scheme_end = std.mem.indexOf(u8, raw, "://") orelse return null;
const authority_start = scheme_end + 3;
const pos = std.mem.indexOfScalar(u8, raw[authority_start..], '@') orelse return null;
const path_start = std.mem.indexOfScalarPos(u8, raw, authority_start, '/') orelse raw.len;
const full_pos = authority_start + pos;
if (full_pos < path_start) {
return raw[authority_start..full_pos];
}
return null;
}
fn getHost(self: *const URL) []const u8 {
const raw = self._raw;
const scheme_end = std.mem.indexOf(u8, raw, "://") orelse return "";
var authority_start = scheme_end + 3;
if (std.mem.indexOf(u8, raw[authority_start..], "@")) |pos| {
authority_start += pos + 1;
}
const authority = raw[authority_start..];
const path_start = std.mem.indexOfAny(u8, authority, "/?#") orelse return authority;
return authority[0..path_start];
}
const KnownProtocol = enum {
@"http:",
@"https:",
};
pub const JsApi = struct {
pub const bridge = js.Bridge(URL);

View File

@@ -11,6 +11,7 @@ const Location = @import("Location.zig");
const Fetch = @import("net/Fetch.zig");
const EventTarget = @import("EventTarget.zig");
const ErrorEvent = @import("event/ErrorEvent.zig");
const MediaQueryList = @import("css/MediaQueryList.zig");
const storage = @import("storage/storage.zig");
const Window = @This();
@@ -135,6 +136,13 @@ pub fn cancelAnimationFrame(self: *Window, id: u32) void {
sc.removed = true;
}
pub fn matchMedia(_: *const Window, query: []const u8, page: *Page) !*MediaQueryList {
return page._factory.eventTarget(MediaQueryList{
._proto = undefined,
._media = try page.dupeString(query),
});
}
pub fn btoa(_: *const Window, input: []const u8, page: *Page) ![]const u8 {
const encoded_len = std.base64.standard.Encoder.calcSize(input.len);
const encoded = try page.call_arena.alloc(u8, encoded_len);
@@ -266,6 +274,7 @@ pub const JsApi = struct {
pub const clearImmediate = bridge.function(Window.clearImmediate, .{});
pub const requestAnimationFrame = bridge.function(Window.requestAnimationFrame, .{});
pub const cancelAnimationFrame = bridge.function(Window.cancelAnimationFrame, .{});
pub const matchMedia = bridge.function(Window.matchMedia, .{});
pub const btoa = bridge.function(Window.btoa, .{});
pub const atob = bridge.function(Window.atob, .{});
};

View File

@@ -0,0 +1,44 @@
// zlint-disable unused-decls
const std = @import("std");
const js = @import("../../js/js.zig");
const EventTarget = @import("../EventTarget.zig");
const MediaQueryList = @This();
_proto: *EventTarget,
_media: []const u8,
pub fn deinit(self: *MediaQueryList) void {
_ = self;
}
pub fn asEventTarget(self: *MediaQueryList) *EventTarget {
return self._proto;
}
pub fn getMedia(self: *const MediaQueryList) []const u8 {
return self._media;
}
/// Always returns false for dummy implementation
pub fn getMatches(_: *const MediaQueryList) bool {
return false;
}
pub const JsApi = struct {
pub const bridge = js.Bridge(MediaQueryList);
pub const Meta = struct {
pub const name = "MediaQueryList";
pub const prototype_chain = bridge.prototypeChain();
pub var class_index: u16 = 0;
};
pub const media = bridge.accessor(MediaQueryList.getMedia, null, .{});
pub const matches = bridge.accessor(MediaQueryList.getMatches, null, .{});
};
const testing = @import("../../../testing.zig");
test "WebApi: MediaQueryList" {
try testing.htmlRunner("css/media_query_list.html", .{});
}