mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 15:13:28 +00:00
dom: refacto HTMLCollection to extract matching
This commit is contained in:
@@ -7,7 +7,8 @@ const Case = jsruntime.test_utils.Case;
|
||||
const checkCases = jsruntime.test_utils.checkCases;
|
||||
|
||||
const Node = @import("node.zig").Node;
|
||||
const HTMLCollection = @import("html_collection.zig").HTMLCollection;
|
||||
|
||||
const collection = @import("html_collection.zig");
|
||||
|
||||
const Element = @import("element.zig").Element;
|
||||
const ElementUnion = @import("element.zig").Union;
|
||||
@@ -49,12 +50,9 @@ pub const Document = struct {
|
||||
// the spec changed to return an HTMLCollection instead.
|
||||
// That's why we reimplemented getElementsByTagName by using an
|
||||
// HTMLCollection in zig here.
|
||||
pub fn _getElementsByTagName(self: *parser.Document, tag_name: []const u8) HTMLCollection {
|
||||
pub fn _getElementsByTagName(self: *parser.Document, allocator: std.mem.Allocator, tag_name: []const u8) !collection.HTMLCollection {
|
||||
const root = parser.documentGetDocumentElement(self);
|
||||
return HTMLCollection{
|
||||
.root = parser.elementToNode(root),
|
||||
.match = tag_name,
|
||||
};
|
||||
return collection.HTMLCollectionByTagName(allocator, parser.elementToNode(root), tag_name);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -5,11 +5,59 @@ const parser = @import("../netsurf.zig");
|
||||
const jsruntime = @import("jsruntime");
|
||||
const Case = jsruntime.test_utils.Case;
|
||||
const checkCases = jsruntime.test_utils.checkCases;
|
||||
const generate = @import("../generate.zig");
|
||||
|
||||
const utils = @import("utils.z");
|
||||
const Element = @import("element.zig").Element;
|
||||
const Union = @import("element.zig").Union;
|
||||
|
||||
const Match = union(enum) {
|
||||
matchByTagName: MatchByTagName,
|
||||
|
||||
pub fn match(self: Match, node: *parser.Node) bool {
|
||||
switch (self) {
|
||||
inline else => |case| return case.match(node),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deinit(self: Match, allocator: std.mem.Allocator) void {
|
||||
switch (self) {
|
||||
inline else => |case| case.deinit(allocator),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub const MatchByTagName = struct {
|
||||
// tag is used to select node against their name.
|
||||
// tag comparison is case insensitive.
|
||||
tag: []const u8,
|
||||
is_wildcard: bool,
|
||||
|
||||
fn init(allocator: std.mem.Allocator, tag_name: []const u8) !MatchByTagName {
|
||||
return MatchByTagName{
|
||||
.tag = try std.ascii.allocUpperString(allocator, tag_name),
|
||||
.is_wildcard = std.mem.eql(u8, tag_name, "*"),
|
||||
};
|
||||
}
|
||||
|
||||
fn deinit(self: *MatchByTagName, allocator: std.mem.Allocator) void {
|
||||
allocator.free(self.tag);
|
||||
}
|
||||
|
||||
pub fn match(self: MatchByTagName, node: *parser.Node) bool {
|
||||
return self.is_wildcard or std.mem.eql(u8, self.tag, parser.nodeName(node));
|
||||
}
|
||||
};
|
||||
|
||||
pub fn HTMLCollectionByTagName(allocator: std.mem.Allocator, root: *parser.Node, tag_name: []const u8) !HTMLCollection {
|
||||
return HTMLCollection{
|
||||
.root = root,
|
||||
.match = Match{
|
||||
.matchByTagName = try MatchByTagName.init(allocator, tag_name),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// WEB IDL https://dom.spec.whatwg.org/#htmlcollection
|
||||
// HTMLCollection is re implemented in zig here because libdom
|
||||
// dom_html_collection expects a comparison function callback as arguement.
|
||||
@@ -17,10 +65,9 @@ const Union = @import("element.zig").Union;
|
||||
pub const HTMLCollection = struct {
|
||||
pub const mem_guarantied = true;
|
||||
|
||||
match: Match,
|
||||
|
||||
root: *parser.Node,
|
||||
// match is used to select node against their name.
|
||||
// match comparison is case insensitive.
|
||||
match: []const u8,
|
||||
|
||||
// save a state for the collection to improve the _item speed.
|
||||
cur_idx: ?u32 = undefined,
|
||||
@@ -76,20 +123,15 @@ pub const HTMLCollection = struct {
|
||||
/// get_length computes the collection's length dynamically according to
|
||||
/// the current root structure.
|
||||
// TODO: nodes retrieved must be de-referenced.
|
||||
pub fn get_length(self: *HTMLCollection, allocator: std.mem.Allocator) !u32 {
|
||||
pub fn get_length(self: *HTMLCollection) u32 {
|
||||
var len: u32 = 0;
|
||||
var node: *parser.Node = self.root;
|
||||
var ntype: parser.NodeType = undefined;
|
||||
|
||||
const imatch = try std.ascii.allocUpperString(allocator, self.match);
|
||||
defer allocator.free(imatch);
|
||||
|
||||
const is_wildcard = std.mem.eql(u8, self.match, "*");
|
||||
|
||||
while (true) {
|
||||
ntype = parser.nodeType(node);
|
||||
if (ntype == .element) {
|
||||
if (is_wildcard or std.mem.eql(u8, imatch, parser.nodeName(node))) {
|
||||
if (self.match.match(node)) {
|
||||
len += 1;
|
||||
}
|
||||
}
|
||||
@@ -100,26 +142,21 @@ pub const HTMLCollection = struct {
|
||||
return len;
|
||||
}
|
||||
|
||||
pub fn _item(self: *HTMLCollection, allocator: std.mem.Allocator, index: u32) !?Union {
|
||||
pub fn _item(self: *HTMLCollection, index: u32) ?Union {
|
||||
var i: u32 = 0;
|
||||
var node: *parser.Node = self.root;
|
||||
var ntype: parser.NodeType = undefined;
|
||||
|
||||
const is_wildcard = std.mem.eql(u8, self.match, "*");
|
||||
|
||||
// Use the current state to improve speed if possible.
|
||||
if (self.cur_idx != null and index >= self.cur_idx.?) {
|
||||
i = self.cur_idx.?;
|
||||
node = self.cur_node.?;
|
||||
}
|
||||
|
||||
const imatch = try std.ascii.allocUpperString(allocator, self.match);
|
||||
defer allocator.free(imatch);
|
||||
|
||||
while (true) {
|
||||
ntype = parser.nodeType(node);
|
||||
if (ntype == .element) {
|
||||
if (is_wildcard or std.mem.eql(u8, imatch, parser.nodeName(node))) {
|
||||
if (self.match.match(node)) {
|
||||
// check if we found the searched element.
|
||||
if (i == index) {
|
||||
// save the current state
|
||||
@@ -140,7 +177,7 @@ pub const HTMLCollection = struct {
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn _namedItem(self: *HTMLCollection, allocator: std.mem.Allocator, name: []const u8) !?Union {
|
||||
pub fn _namedItem(self: *HTMLCollection, name: []const u8) ?Union {
|
||||
if (name.len == 0) {
|
||||
return null;
|
||||
}
|
||||
@@ -148,15 +185,10 @@ pub const HTMLCollection = struct {
|
||||
var node: *parser.Node = self.root;
|
||||
var ntype: parser.NodeType = undefined;
|
||||
|
||||
const is_wildcard = std.mem.eql(u8, self.match, "*");
|
||||
|
||||
const imatch = try std.ascii.allocUpperString(allocator, self.match);
|
||||
defer allocator.free(imatch);
|
||||
|
||||
while (true) {
|
||||
ntype = parser.nodeType(node);
|
||||
if (ntype == .element) {
|
||||
if (is_wildcard or std.mem.eql(u8, imatch, parser.nodeName(node))) {
|
||||
if (self.match.match(node)) {
|
||||
const elem = @as(*parser.Element, @ptrCast(node));
|
||||
|
||||
var attr = parser.elementGetAttribute(elem, "id");
|
||||
|
||||
Reference in New Issue
Block a user