@@ -290,6 +290,22 @@ pub const Element = struct {
290
290
return true ;
291
291
}
292
292
293
+ pub fn _getAttributeNames (self : * parser.Element , page : * Page ) ! []const []const u8 {
294
+ const attributes = try parser .nodeGetAttributes (@ptrCast (self )) orelse return &.{};
295
+ const ln = try parser .namedNodeMapGetLength (attributes );
296
+
297
+ const names = try page .call_arena .alloc ([]const u8 , ln );
298
+ var at : usize = 0 ;
299
+
300
+ for (0.. ln ) | i | {
301
+ const attribute = try parser .namedNodeMapItem (attributes , @intCast (i )) orelse break ;
302
+ names [at ] = try parser .attributeGetName (attribute );
303
+ at += 1 ;
304
+ }
305
+
306
+ return names [0.. at ];
307
+ }
308
+
293
309
pub fn _getAttributeNode (self : * parser.Element , name : []const u8 ) ! ? * parser.Attribute {
294
310
return try parser .elementGetAttributeNode (self , name );
295
311
}
@@ -597,6 +613,7 @@ test "Browser.DOM.Element" {
597
613
.{ "let a = document.getElementById('content')" , "undefined" },
598
614
.{ "a.hasAttributes()" , "true" },
599
615
.{ "a.attributes.length" , "1" },
616
+ .{ "a.getAttributeNames()" , "id" },
600
617
.{ "a.getAttribute('id')" , "content" },
601
618
.{ "a.attributes['id'].value" , "content" },
602
619
.{
@@ -615,6 +632,7 @@ test "Browser.DOM.Element" {
615
632
.{ "a.setAttribute('foo', 'bar')" , "undefined" },
616
633
.{ "a.hasAttribute('foo')" , "true" },
617
634
.{ "a.getAttribute('foo')" , "bar" },
635
+ .{ "a.getAttributeNames()" , "id,foo" },
618
636
619
637
.{ "a.setAttribute('foo', 'baz')" , "undefined" },
620
638
.{ "a.hasAttribute('foo')" , "true" },
@@ -807,6 +825,7 @@ test "Browser.DOM.Element" {
807
825
808
826
try runner .testCases (&.{
809
827
.{ "const rm = document.createElement('div')" , null },
828
+ .{ "rm.getAttributeNames()" , "" },
810
829
.{ "rm.id = 'to-remove'" , null },
811
830
.{ "document.getElementsByTagName('body')[0].appendChild(rm)" , null },
812
831
.{ "document.getElementById('to-remove') != null" , "true" },
0 commit comments