From 39afb6593dacc7d6f7232ed10511f63ccae22df5 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Tue, 12 Dec 2023 17:26:51 +0100 Subject: [PATCH 1/3] dom: hmtl collection: wip postAttach --- src/dom/html_collection.zig | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/dom/html_collection.zig b/src/dom/html_collection.zig index 1bd28034..e6f917d9 100644 --- a/src/dom/html_collection.zig +++ b/src/dom/html_collection.zig @@ -465,6 +465,35 @@ pub const HTMLCollection = struct { return null; } + fn item_name(n: Union) !?[]const u8 { + const elem = @as(*parser.Element, @ptrCast(n)); + if (try parser.elementGetAttribute(elem, "id")) |v| { + return v; + } + if (try parser.elementGetAttribute(elem, "name")) |v| { + return v; + } + + return null; + } + + pub fn postAttach(self: *HTMLCollection, alloc: std.mem.Allocator, js_obj: jsruntime.JSObject) !void { + const ln = try self.get_length(); + var i: u32 = 0; + while (i < ln) { + defer i += 1; + + const v = try self._item(i); + // TODO k must be deinit + const k = try std.fmt.allocPrint(alloc, "{d}", .{i}); + try js_obj.set(k, v); + + if (try item_name(v)) |name| { + try js_obj.set(name, v); + } + } + } + pub fn deinit(self: *HTMLCollection, alloc: std.mem.Allocator) void { self.matcher.deinit(alloc); } @@ -495,6 +524,9 @@ pub fn testExecFn( .{ .src = "getElementsByTagNameAll.item(7).localName", .ex = "p" }, .{ .src = "getElementsByTagNameAll.namedItem('para-empty-child').localName", .ex = "span" }, + // array like + .{ .src = "getElementsByTagNameAll[0].localName", .ex = "html" }, + .{ .src = "document.getElementById('content').getElementsByTagName('*').length", .ex = "4" }, .{ .src = "document.getElementById('content').getElementsByTagName('p').length", .ex = "2" }, .{ .src = "document.getElementById('content').getElementsByTagName('div').length", .ex = "0" }, From f59f36422c21e1e42675a720567aa30a13ac824b Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 11 Jan 2024 10:49:17 +0100 Subject: [PATCH 2/3] html_collection: free generated array like keys --- src/dom/html_collection.zig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/dom/html_collection.zig b/src/dom/html_collection.zig index e6f917d9..3a91f1f7 100644 --- a/src/dom/html_collection.zig +++ b/src/dom/html_collection.zig @@ -359,6 +359,10 @@ pub const HTMLCollection = struct { cur_idx: ?u32 = undefined, cur_node: ?*parser.Node = undefined, + // array_like_keys is used to keep reference to array like interface implementation. + // the collection generates keys string which must be free on deinit. + array_like_keys: std.ArrayListUnmanaged([]u8) = .{}, + // start returns the first node to walk on. fn start(self: HTMLCollection) !?*parser.Node { if (self.root == null) return null; @@ -488,6 +492,8 @@ pub const HTMLCollection = struct { const k = try std.fmt.allocPrint(alloc, "{d}", .{i}); try js_obj.set(k, v); + self.array_like_keys.append(alloc, k); + if (try item_name(v)) |name| { try js_obj.set(name, v); } @@ -495,6 +501,8 @@ pub const HTMLCollection = struct { } pub fn deinit(self: *HTMLCollection, alloc: std.mem.Allocator) void { + for (self.array_like_keys_) |k| alloc.free(k); + self.array_like_keys.deinit(alloc); self.matcher.deinit(alloc); } }; From 93db41ff10d2144297a3640be4e75f7a2581bdf0 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Mon, 15 Jan 2024 12:03:59 +0100 Subject: [PATCH 3/3] html_collection: update iterator values --- src/dom/html_collection.zig | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/dom/html_collection.zig b/src/dom/html_collection.zig index 3a91f1f7..c2c8b723 100644 --- a/src/dom/html_collection.zig +++ b/src/dom/html_collection.zig @@ -469,12 +469,11 @@ pub const HTMLCollection = struct { return null; } - fn item_name(n: Union) !?[]const u8 { - const elem = @as(*parser.Element, @ptrCast(n)); - if (try parser.elementGetAttribute(elem, "id")) |v| { + fn item_name(elt: *parser.Element) !?[]const u8 { + if (try parser.elementGetAttribute(elt, "id")) |v| { return v; } - if (try parser.elementGetAttribute(elem, "name")) |v| { + if (try parser.elementGetAttribute(elt, "name")) |v| { return v; } @@ -486,16 +485,15 @@ pub const HTMLCollection = struct { var i: u32 = 0; while (i < ln) { defer i += 1; - - const v = try self._item(i); - // TODO k must be deinit const k = try std.fmt.allocPrint(alloc, "{d}", .{i}); - try js_obj.set(k, v); + try self.array_like_keys.append(alloc, k); - self.array_like_keys.append(alloc, k); + const node = try self.item(i) orelse unreachable; + const e = @as(*parser.Element, @ptrCast(node)); + try js_obj.set(k, e); - if (try item_name(v)) |name| { - try js_obj.set(name, v); + if (try item_name(e)) |name| { + try js_obj.set(name, e); } } } @@ -534,6 +532,10 @@ pub fn testExecFn( // array like .{ .src = "getElementsByTagNameAll[0].localName", .ex = "html" }, + .{ .src = "getElementsByTagNameAll[7].localName", .ex = "p" }, + .{ .src = "getElementsByTagNameAll[8]", .ex = "undefined" }, + .{ .src = "getElementsByTagNameAll['para-empty-child'].localName", .ex = "span" }, + .{ .src = "getElementsByTagNameAll['foo']", .ex = "undefined" }, .{ .src = "document.getElementById('content').getElementsByTagName('*').length", .ex = "4" }, .{ .src = "document.getElementById('content').getElementsByTagName('p').length", .ex = "2" },