Skip to content

Commit d4d8773

Browse files
Merge pull request #927 from lightpanda-io/window-frames
Partial window.frames implementation
2 parents d9ed4cf + b199925 commit d4d8773

File tree

4 files changed

+101
-9
lines changed

4 files changed

+101
-9
lines changed

src/browser/dom/nodelist.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ pub const NodeList = struct {
110110
try self.nodes.append(alloc, node);
111111
}
112112

113-
pub fn get_length(self: *NodeList) u32 {
113+
pub fn get_length(self: *const NodeList) u32 {
114114
return @intCast(self.nodes.items.len);
115115
}
116116

src/browser/html/elements.zig

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ pub const Interfaces = .{
6161
HTMLHeadElement,
6262
HTMLHeadingElement,
6363
HTMLHtmlElement,
64-
HTMLIFrameElement,
6564
HTMLImageElement,
6665
HTMLImageElement.Factory,
6766
HTMLInputElement,
@@ -102,6 +101,7 @@ pub const Interfaces = .{
102101
HTMLVideoElement,
103102

104103
@import("form.zig").HTMLFormElement,
104+
@import("iframe.zig").HTMLIFrameElement,
105105
@import("select.zig").Interfaces,
106106
};
107107

@@ -584,12 +584,6 @@ pub const HTMLHtmlElement = struct {
584584
pub const subtype = .node;
585585
};
586586

587-
pub const HTMLIFrameElement = struct {
588-
pub const Self = parser.IFrame;
589-
pub const prototype = *HTMLElement;
590-
pub const subtype = .node;
591-
};
592-
593587
pub const HTMLImageElement = struct {
594588
pub const Self = parser.Image;
595589
pub const prototype = *HTMLElement;

src/browser/html/iframe.zig

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright (C) 2023-2025 Lightpanda (Selecy SAS)
2+
//
3+
// Francis Bouvier <[email protected]>
4+
// Pierre Tachoire <[email protected]>
5+
//
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU Affero General Public License as
8+
// published by the Free Software Foundation, either version 3 of the
9+
// License, or (at your option) any later version.
10+
//
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU Affero General Public License for more details.
15+
//
16+
// You should have received a copy of the GNU Affero General Public License
17+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
const std = @import("std");
19+
const Allocator = std.mem.Allocator;
20+
21+
const parser = @import("../netsurf.zig");
22+
const Page = @import("../page.zig").Page;
23+
const HTMLElement = @import("elements.zig").HTMLElement;
24+
25+
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#htmliframeelement
26+
pub const HTMLIFrameElement = struct {
27+
pub const Self = parser.IFrame;
28+
pub const prototype = *HTMLElement;
29+
pub const subtype = .node;
30+
};

src/browser/html/window.zig

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const MediaQueryList = @import("media_query_list.zig").MediaQueryList;
3333
const Performance = @import("../dom/performance.zig").Performance;
3434
const CSSStyleDeclaration = @import("../cssom/CSSStyleDeclaration.zig");
3535
const Screen = @import("screen.zig").Screen;
36+
const domcss = @import("../dom/css.zig");
3637
const Css = @import("../css/css.zig").Css;
3738

3839
const Function = Env.Function;
@@ -126,7 +127,43 @@ pub const Window = struct {
126127
return self;
127128
}
128129

129-
// TODO: frames
130+
// frames return the window itself, but accessing it via a pseudo
131+
// array returns the Window object corresponding to the given frame or
132+
// iframe.
133+
// https://developer.mozilla.org/en-US/docs/Web/API/Window/frames
134+
pub fn get_frames(self: *Window) *Window {
135+
return self;
136+
}
137+
138+
pub fn indexed_get(self: *Window, index: u32, has_value: *bool, page: *Page) !*Window {
139+
const frames = try domcss.querySelectorAll(
140+
page.call_arena,
141+
parser.documentHTMLToNode(self.document),
142+
"iframe",
143+
);
144+
145+
if (index >= frames.nodes.items.len) {
146+
has_value.* = false;
147+
return undefined;
148+
}
149+
150+
has_value.* = true;
151+
// TODO return the correct frame's window
152+
// frames.nodes.items[indexed]
153+
return error.TODO;
154+
}
155+
156+
// Retrieve the numbre of frames/iframes from the DOM dynamically.
157+
pub fn get_length(self: *const Window, page: *Page) !u32 {
158+
const frames = try domcss.querySelectorAll(
159+
page.call_arena,
160+
parser.documentHTMLToNode(self.document),
161+
"iframe",
162+
);
163+
164+
return frames.get_length();
165+
}
166+
130167
pub fn get_top(self: *Window) *Window {
131168
return self;
132169
}
@@ -493,6 +530,14 @@ test "Browser.HTML.Window" {
493530
.{ "scrollend", "true" },
494531
}, .{});
495532

533+
try runner.testCases(&.{
534+
.{ "window == window.self", "true" },
535+
.{ "window == window.parent", "true" },
536+
.{ "window == window.top", "true" },
537+
.{ "window == window.frames", "true" },
538+
.{ "window.frames.length", "0" },
539+
}, .{});
540+
496541
try runner.testCases(&.{
497542
.{ "var qm = false; window.queueMicrotask(() => {qm = true });", null },
498543
.{ "qm", "true" },
@@ -515,3 +560,26 @@ test "Browser.HTML.Window" {
515560
}, .{});
516561
}
517562
}
563+
564+
test "Browser.HTML.Window.frames" {
565+
var runner = try testing.jsRunner(testing.tracking_allocator, .{ .html =
566+
\\<body>
567+
\\ <iframe
568+
\\ src="https://httpbin.io/html"
569+
\\ title="iframea">
570+
\\ </iframe>
571+
\\ <iframe
572+
\\ src="https://httpbin.io/html"
573+
\\ title="iframeb">
574+
\\ </iframe>
575+
\\</body>
576+
});
577+
578+
defer runner.deinit();
579+
580+
try runner.testCases(&.{
581+
.{ "frames.length", "2" },
582+
.{ "try { frames[1] } catch (e) { e }", "Error: TODO" }, // TODO fixme
583+
.{ "frames[3]", "undefined" },
584+
}, .{});
585+
}

0 commit comments

Comments
 (0)