From 894b6182cf64e03321f23fb19e860ec953c121b5 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 7 Dec 2023 16:16:39 +0100 Subject: [PATCH 01/13] dom: implement document.createTextNode --- src/dom/document.zig | 9 +++++++++ src/netsurf.zig | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/src/dom/document.zig b/src/dom/document.zig index adf34d35..ea29dad8 100644 --- a/src/dom/document.zig +++ b/src/dom/document.zig @@ -129,6 +129,10 @@ pub const Document = struct { return try parser.documentCreateDocumentFragment(self); } + pub fn _createTextNode(self: *parser.Document, data: []const u8) !*parser.Text { + return try parser.documentCreateTextNode(self, data); + } + pub fn deinit(_: *parser.Document, _: std.mem.Allocator) void {} }; @@ -226,6 +230,11 @@ pub fn testExecFn( }; try checkCases(js_env, &createDocumentFragment); + var createTextNode = [_]Case{ + .{ .src = "document.createTextNode('foo')", .ex = "[object Text]" }, + }; + try checkCases(js_env, &createTextNode); + const tags = comptime parser.Tag.all(); comptime var createElements: [(tags.len) * 2]Case = undefined; inline for (tags, 0..) |tag, i| { diff --git a/src/netsurf.zig b/src/netsurf.zig index 0919e56a..b764c9dd 100644 --- a/src/netsurf.zig +++ b/src/netsurf.zig @@ -1137,6 +1137,13 @@ pub inline fn documentCreateDocumentFragment(doc: *Document) !*DocumentFragment return df.?; } +pub inline fn documentCreateTextNode(doc: *Document, s: []const u8) !*Text { + var txt: ?*Text = undefined; + const err = documentVtable(doc).dom_document_create_text_node.?(doc, try strFromData(s), &txt); + try DOMErr(err); + return txt.?; +} + // DocumentHTML pub const DocumentHTML = c.dom_html_document; From 94876d01f187eda1c04d033b4cc1deb371b375e2 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 7 Dec 2023 16:27:26 +0100 Subject: [PATCH 02/13] dom: add document.createCDATASection --- src/dom/cdata_section.zig | 12 ++++++++++++ src/dom/character_data.zig | 2 ++ src/dom/document.zig | 9 +++++++++ src/dom/node.zig | 1 + src/netsurf.zig | 10 ++++++++++ 5 files changed, 34 insertions(+) create mode 100644 src/dom/cdata_section.zig diff --git a/src/dom/cdata_section.zig b/src/dom/cdata_section.zig new file mode 100644 index 00000000..8f02ceb1 --- /dev/null +++ b/src/dom/cdata_section.zig @@ -0,0 +1,12 @@ +const std = @import("std"); + +const parser = @import("../netsurf.zig"); + +const Text = @import("text.zig").Text; + +// https://dom.spec.whatwg.org/#cdatasection +pub const CDATASection = struct { + pub const Self = parser.CDATASection; + pub const prototype = *Text; + pub const mem_guarantied = true; +}; diff --git a/src/dom/character_data.zig b/src/dom/character_data.zig index 8f139691..b515b719 100644 --- a/src/dom/character_data.zig +++ b/src/dom/character_data.zig @@ -10,12 +10,14 @@ const parser = @import("../netsurf.zig"); const Node = @import("node.zig").Node; const Comment = @import("comment.zig").Comment; const Text = @import("text.zig").Text; +const CDATASection = @import("cdata_section.zig").CDATASection; const HTMLElem = @import("../html/elements.zig"); // CharacterData interfaces pub const Interfaces = generate.Tuple(.{ Comment, Text, + CDATASection, }); // CharacterData implementation diff --git a/src/dom/document.zig b/src/dom/document.zig index ea29dad8..aa4a5c6a 100644 --- a/src/dom/document.zig +++ b/src/dom/document.zig @@ -133,6 +133,10 @@ pub const Document = struct { return try parser.documentCreateTextNode(self, data); } + pub fn _createCDATASection(self: *parser.Document, data: []const u8) !*parser.CDATASection { + return try parser.documentCreateCDATASection(self, data); + } + pub fn deinit(_: *parser.Document, _: std.mem.Allocator) void {} }; @@ -235,6 +239,11 @@ pub fn testExecFn( }; try checkCases(js_env, &createTextNode); + var createCDATASection = [_]Case{ + .{ .src = "document.createCDATASection('foo')", .ex = "[object CDATASection]" }, + }; + try checkCases(js_env, &createCDATASection); + const tags = comptime parser.Tag.all(); comptime var createElements: [(tags.len) * 2]Case = undefined; inline for (tags, 0..) |tag, i| { diff --git a/src/dom/node.zig b/src/dom/node.zig index 022aa9c7..b700b73f 100644 --- a/src/dom/node.zig +++ b/src/dom/node.zig @@ -54,6 +54,7 @@ pub const Node = struct { ), .comment => .{ .Comment = @as(*parser.Comment, @ptrCast(node)) }, .text => .{ .Text = @as(*parser.Text, @ptrCast(node)) }, + .cdata_section => .{ .CDATASection = @as(*parser.CDATASection, @ptrCast(node)) }, .document => .{ .HTMLDocument = @as(*parser.DocumentHTML, @ptrCast(node)) }, .document_type => .{ .DocumentType = @as(*parser.DocumentType, @ptrCast(node)) }, .attribute => .{ .Attr = @as(*parser.Attribute, @ptrCast(node)) }, diff --git a/src/netsurf.zig b/src/netsurf.zig index b764c9dd..3042da20 100644 --- a/src/netsurf.zig +++ b/src/netsurf.zig @@ -791,6 +791,9 @@ pub fn characterDataSubstringData(cdata: *CharacterData, offset: u32, count: u32 return strToData(s.?); } +// CDATASection +pub const CDATASection = c.dom_cdata_section; + // Text pub const Text = c.dom_text; @@ -1144,6 +1147,13 @@ pub inline fn documentCreateTextNode(doc: *Document, s: []const u8) !*Text { return txt.?; } +pub inline fn documentCreateCDATASection(doc: *Document, s: []const u8) !*CDATASection { + var cdata: ?*CDATASection = undefined; + const err = documentVtable(doc).dom_document_create_cdata_section.?(doc, try strFromData(s), &cdata); + try DOMErr(err); + return cdata.?; +} + // DocumentHTML pub const DocumentHTML = c.dom_html_document; From 24ec5f554d320ce43bade61a371378967c5f49bb Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 7 Dec 2023 16:30:33 +0100 Subject: [PATCH 03/13] dom: implement document.createComment --- src/dom/document.zig | 9 +++++++++ src/netsurf.zig | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/src/dom/document.zig b/src/dom/document.zig index aa4a5c6a..734bc178 100644 --- a/src/dom/document.zig +++ b/src/dom/document.zig @@ -137,6 +137,10 @@ pub const Document = struct { return try parser.documentCreateCDATASection(self, data); } + pub fn _createComment(self: *parser.Document, data: []const u8) !*parser.Comment { + return try parser.documentCreateComment(self, data); + } + pub fn deinit(_: *parser.Document, _: std.mem.Allocator) void {} }; @@ -244,6 +248,11 @@ pub fn testExecFn( }; try checkCases(js_env, &createCDATASection); + var createComment = [_]Case{ + .{ .src = "document.createComment('foo')", .ex = "[object Comment]" }, + }; + try checkCases(js_env, &createComment); + const tags = comptime parser.Tag.all(); comptime var createElements: [(tags.len) * 2]Case = undefined; inline for (tags, 0..) |tag, i| { diff --git a/src/netsurf.zig b/src/netsurf.zig index 3042da20..fe46b57f 100644 --- a/src/netsurf.zig +++ b/src/netsurf.zig @@ -1154,6 +1154,13 @@ pub inline fn documentCreateCDATASection(doc: *Document, s: []const u8) !*CDATAS return cdata.?; } +pub inline fn documentCreateComment(doc: *Document, s: []const u8) !*Comment { + var com: ?*Comment = undefined; + const err = documentVtable(doc).dom_document_create_comment.?(doc, try strFromData(s), &com); + try DOMErr(err); + return com.?; +} + // DocumentHTML pub const DocumentHTML = c.dom_html_document; From d13da6ffab745f813e5acc7c577e58f0462cdf93 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 7 Dec 2023 16:48:02 +0100 Subject: [PATCH 04/13] dom: implement document.createProcessingInstruction --- src/dom/character_data.zig | 2 ++ src/dom/document.zig | 9 +++++++++ src/dom/node.zig | 1 + src/dom/processing_instruction.zig | 14 ++++++++++++++ src/netsurf.zig | 15 +++++++++++++++ 5 files changed, 41 insertions(+) create mode 100644 src/dom/processing_instruction.zig diff --git a/src/dom/character_data.zig b/src/dom/character_data.zig index b515b719..447edf53 100644 --- a/src/dom/character_data.zig +++ b/src/dom/character_data.zig @@ -11,6 +11,7 @@ const Node = @import("node.zig").Node; const Comment = @import("comment.zig").Comment; const Text = @import("text.zig").Text; const CDATASection = @import("cdata_section.zig").CDATASection; +const ProcessingInstruction = @import("processing_instruction.zig").ProcessingInstruction; const HTMLElem = @import("../html/elements.zig"); // CharacterData interfaces @@ -18,6 +19,7 @@ pub const Interfaces = generate.Tuple(.{ Comment, Text, CDATASection, + ProcessingInstruction, }); // CharacterData implementation diff --git a/src/dom/document.zig b/src/dom/document.zig index 734bc178..e9a6903f 100644 --- a/src/dom/document.zig +++ b/src/dom/document.zig @@ -141,6 +141,10 @@ pub const Document = struct { return try parser.documentCreateComment(self, data); } + pub fn _createProcessingInstruction(self: *parser.Document, target: []const u8, data: []const u8) !*parser.ProcessingInstruction { + return try parser.documentCreateProcessingInstruction(self, target, data); + } + pub fn deinit(_: *parser.Document, _: std.mem.Allocator) void {} }; @@ -253,6 +257,11 @@ pub fn testExecFn( }; try checkCases(js_env, &createComment); + var createProcessingInstruction = [_]Case{ + .{ .src = "document.createProcessingInstruction('foo', 'bar')", .ex = "[object ProcessingInstruction]" }, + }; + try checkCases(js_env, &createProcessingInstruction); + const tags = comptime parser.Tag.all(); comptime var createElements: [(tags.len) * 2]Case = undefined; inline for (tags, 0..) |tag, i| { diff --git a/src/dom/node.zig b/src/dom/node.zig index b700b73f..86b3dae5 100644 --- a/src/dom/node.zig +++ b/src/dom/node.zig @@ -55,6 +55,7 @@ pub const Node = struct { .comment => .{ .Comment = @as(*parser.Comment, @ptrCast(node)) }, .text => .{ .Text = @as(*parser.Text, @ptrCast(node)) }, .cdata_section => .{ .CDATASection = @as(*parser.CDATASection, @ptrCast(node)) }, + .processing_instruction => .{ .ProcessingInstruction = @as(*parser.ProcessingInstruction, @ptrCast(node)) }, .document => .{ .HTMLDocument = @as(*parser.DocumentHTML, @ptrCast(node)) }, .document_type => .{ .DocumentType = @as(*parser.DocumentType, @ptrCast(node)) }, .attribute => .{ .Attr = @as(*parser.Attribute, @ptrCast(node)) }, diff --git a/src/dom/processing_instruction.zig b/src/dom/processing_instruction.zig new file mode 100644 index 00000000..2b2f8f2d --- /dev/null +++ b/src/dom/processing_instruction.zig @@ -0,0 +1,14 @@ +const std = @import("std"); + +const parser = @import("../netsurf.zig"); + +const CharacterData = @import("character_data.zig").CharacterData; + +// https://dom.spec.whatwg.org/#processinginstruction +pub const ProcessingInstruction = struct { + pub const Self = parser.ProcessingInstruction; + pub const prototype = *CharacterData; + pub const mem_guarantied = true; + + // TODO implement get_target +}; diff --git a/src/netsurf.zig b/src/netsurf.zig index fe46b57f..96639ea2 100644 --- a/src/netsurf.zig +++ b/src/netsurf.zig @@ -818,6 +818,9 @@ pub fn textSplitText(text: *Text, offset: u32) !*Text { // Comment pub const Comment = c.dom_comment; +// ProcessingInstruction +pub const ProcessingInstruction = c.dom_processing_instruction; + // Attribute pub const Attribute = c.dom_attr; @@ -1161,6 +1164,18 @@ pub inline fn documentCreateComment(doc: *Document, s: []const u8) !*Comment { return com.?; } +pub inline fn documentCreateProcessingInstruction(doc: *Document, target: []const u8, data: []const u8) !*ProcessingInstruction { + var pi: ?*ProcessingInstruction = undefined; + const err = documentVtable(doc).dom_document_create_processing_instruction.?( + doc, + try strFromData(target), + try strFromData(data), + &pi, + ); + try DOMErr(err); + return pi.?; +} + // DocumentHTML pub const DocumentHTML = c.dom_html_document; From 9b9d927f385b90329d8524e2487c1dd653a6704a Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 7 Dec 2023 17:02:14 +0100 Subject: [PATCH 05/13] dom: implement ProcessingIntruction.target --- src/dom/document.zig | 3 ++- src/dom/processing_instruction.zig | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/dom/document.zig b/src/dom/document.zig index e9a6903f..6a34c01b 100644 --- a/src/dom/document.zig +++ b/src/dom/document.zig @@ -258,7 +258,8 @@ pub fn testExecFn( try checkCases(js_env, &createComment); var createProcessingInstruction = [_]Case{ - .{ .src = "document.createProcessingInstruction('foo', 'bar')", .ex = "[object ProcessingInstruction]" }, + .{ .src = "let pi = document.createProcessingInstruction('foo', 'bar')", .ex = "undefined" }, + .{ .src = "pi.target", .ex = "foo" }, }; try checkCases(js_env, &createProcessingInstruction); diff --git a/src/dom/processing_instruction.zig b/src/dom/processing_instruction.zig index 2b2f8f2d..cb5cf29d 100644 --- a/src/dom/processing_instruction.zig +++ b/src/dom/processing_instruction.zig @@ -10,5 +10,8 @@ pub const ProcessingInstruction = struct { pub const prototype = *CharacterData; pub const mem_guarantied = true; - // TODO implement get_target + pub fn get_target(self: *parser.ProcessingInstruction) ![]const u8 { + // libdom stores the ProcessingInstruction target in the node's name. + return try parser.nodeName(@as(*parser.Node, @ptrCast(self))); + } }; From 3ec5cee98cf8a4a3163f33d981721b24da238323 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 7 Dec 2023 17:26:08 +0100 Subject: [PATCH 06/13] dom: implement document.importNode --- src/dom/document.zig | 10 ++++++++++ src/netsurf.zig | 8 ++++++++ 2 files changed, 18 insertions(+) diff --git a/src/dom/document.zig b/src/dom/document.zig index 6a34c01b..48f827f7 100644 --- a/src/dom/document.zig +++ b/src/dom/document.zig @@ -145,6 +145,10 @@ pub const Document = struct { return try parser.documentCreateProcessingInstruction(self, target, data); } + pub fn _importNode(self: *parser.Document, node: *parser.Node, deep: ?bool) !*parser.Node { + return try parser.documentImportNode(self, node, deep orelse false); + } + pub fn deinit(_: *parser.Document, _: std.mem.Allocator) void {} }; @@ -263,6 +267,12 @@ pub fn testExecFn( }; try checkCases(js_env, &createProcessingInstruction); + var importNode = [_]Case{ + .{ .src = "let nimp = document.getElementById('content')", .ex = "undefined" }, + .{ .src = "document.importNode(nimp)", .ex = "[object Node]" }, + }; + try checkCases(js_env, &importNode); + const tags = comptime parser.Tag.all(); comptime var createElements: [(tags.len) * 2]Case = undefined; inline for (tags, 0..) |tag, i| { diff --git a/src/netsurf.zig b/src/netsurf.zig index 96639ea2..439c0478 100644 --- a/src/netsurf.zig +++ b/src/netsurf.zig @@ -1176,6 +1176,14 @@ pub inline fn documentCreateProcessingInstruction(doc: *Document, target: []cons return pi.?; } +pub inline fn documentImportNode(doc: *Document, node: *Node, deep: bool) !*Node { + var res: NodeExternal = undefined; + const nodeext = toNodeExternal(Node, node); + const err = documentVtable(doc).dom_document_import_node.?(doc, nodeext, deep, &res); + try DOMErr(err); + return @as(*Node, @ptrCast(res)); +} + // DocumentHTML pub const DocumentHTML = c.dom_html_document; From 82148da5f6d6b7754dcdc6fd0bceb39a4da3b678 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 7 Dec 2023 17:31:04 +0100 Subject: [PATCH 07/13] dom: implement document.adoptNode --- src/dom/document.zig | 10 ++++++++++ src/netsurf.zig | 8 ++++++++ 2 files changed, 18 insertions(+) diff --git a/src/dom/document.zig b/src/dom/document.zig index 48f827f7..8d9da356 100644 --- a/src/dom/document.zig +++ b/src/dom/document.zig @@ -149,6 +149,10 @@ pub const Document = struct { return try parser.documentImportNode(self, node, deep orelse false); } + pub fn _adoptNode(self: *parser.Document, node: *parser.Node) !*parser.Node { + return try parser.documentAdoptNode(self, node); + } + pub fn deinit(_: *parser.Document, _: std.mem.Allocator) void {} }; @@ -273,6 +277,12 @@ pub fn testExecFn( }; try checkCases(js_env, &importNode); + var adoptNode = [_]Case{ + .{ .src = "let nadop = document.getElementById('content')", .ex = "undefined" }, + .{ .src = "document.adoptNode(nadop)", .ex = "[object Node]" }, + }; + try checkCases(js_env, &adoptNode); + const tags = comptime parser.Tag.all(); comptime var createElements: [(tags.len) * 2]Case = undefined; inline for (tags, 0..) |tag, i| { diff --git a/src/netsurf.zig b/src/netsurf.zig index 439c0478..d79c2d51 100644 --- a/src/netsurf.zig +++ b/src/netsurf.zig @@ -1184,6 +1184,14 @@ pub inline fn documentImportNode(doc: *Document, node: *Node, deep: bool) !*Node return @as(*Node, @ptrCast(res)); } +pub inline fn documentAdoptNode(doc: *Document, node: *Node) !*Node { + var res: NodeExternal = undefined; + const nodeext = toNodeExternal(Node, node); + const err = documentVtable(doc).dom_document_adopt_node.?(doc, nodeext, &res); + try DOMErr(err); + return @as(*Node, @ptrCast(res)); +} + // DocumentHTML pub const DocumentHTML = c.dom_html_document; From f0149b03e51dbf0ec6a0c2fcf74c76f09d338216 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 7 Dec 2023 17:36:34 +0100 Subject: [PATCH 08/13] dom: implement document.createAttribute --- src/dom/document.zig | 9 +++++++++ src/netsurf.zig | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/src/dom/document.zig b/src/dom/document.zig index 8d9da356..3411b52a 100644 --- a/src/dom/document.zig +++ b/src/dom/document.zig @@ -153,6 +153,10 @@ pub const Document = struct { return try parser.documentAdoptNode(self, node); } + pub fn _createAttribute(self: *parser.Document, name: []const u8) !*parser.Attribute { + return try parser.documentCreateAttribute(self, name); + } + pub fn deinit(_: *parser.Document, _: std.mem.Allocator) void {} }; @@ -283,6 +287,11 @@ pub fn testExecFn( }; try checkCases(js_env, &adoptNode); + var createAttr = [_]Case{ + .{ .src = "document.createAttribute('foo')", .ex = "[object Attr]" }, + }; + try checkCases(js_env, &createAttr); + const tags = comptime parser.Tag.all(); comptime var createElements: [(tags.len) * 2]Case = undefined; inline for (tags, 0..) |tag, i| { diff --git a/src/netsurf.zig b/src/netsurf.zig index d79c2d51..ea33315d 100644 --- a/src/netsurf.zig +++ b/src/netsurf.zig @@ -1192,6 +1192,13 @@ pub inline fn documentAdoptNode(doc: *Document, node: *Node) !*Node { return @as(*Node, @ptrCast(res)); } +pub inline fn documentCreateAttribute(doc: *Document, name: []const u8) !*Attribute { + var attr: ?*Attribute = undefined; + const err = documentVtable(doc).dom_document_create_attribute.?(doc, try strFromData(name), &attr); + try DOMErr(err); + return attr.?; +} + // DocumentHTML pub const DocumentHTML = c.dom_html_document; From b0c69488486ab58fd5e9a3e2d9fc2e90ad922fb9 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 7 Dec 2023 17:42:15 +0100 Subject: [PATCH 09/13] dom: implement document.createAttributeNS --- src/dom/document.zig | 4 ++++ src/netsurf.zig | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/dom/document.zig b/src/dom/document.zig index 3411b52a..faa6dc54 100644 --- a/src/dom/document.zig +++ b/src/dom/document.zig @@ -157,6 +157,10 @@ pub const Document = struct { return try parser.documentCreateAttribute(self, name); } + pub fn _createAttributeNS(self: *parser.Document, ns: []const u8, qname: []const u8) !*parser.Attribute { + return try parser.documentCreateAttributeNS(self, ns, qname); + } + pub fn deinit(_: *parser.Document, _: std.mem.Allocator) void {} }; diff --git a/src/netsurf.zig b/src/netsurf.zig index ea33315d..d32b2cee 100644 --- a/src/netsurf.zig +++ b/src/netsurf.zig @@ -1199,6 +1199,18 @@ pub inline fn documentCreateAttribute(doc: *Document, name: []const u8) !*Attrib return attr.?; } +pub inline fn documentCreateAttributeNS(doc: *Document, ns: []const u8, qname: []const u8) !*Attribute { + var attr: ?*Attribute = undefined; + const err = documentVtable(doc).dom_document_create_attribute_ns.?( + doc, + try strFromData(ns), + try strFromData(qname), + &attr, + ); + try DOMErr(err); + return attr.?; +} + // DocumentHTML pub const DocumentHTML = c.dom_html_document; From 807b3275a431a28738b66aaafd3d1c906d5e3556 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 7 Dec 2023 17:44:43 +0100 Subject: [PATCH 10/13] dom: add more WPT tests for document --- tests/wpt/dom/nodes/Document-adoptNode.html | 50 ++++++++++++++ .../dom/nodes/Document-createAttribute.html | 55 +++++++++++++++ .../Document-createCDATASection-xhtml.xhtml | 22 ++++++ .../nodes/Document-createCDATASection.html | 16 +++++ .../Document-createComment-createTextNode.js | 22 ++++++ .../wpt/dom/nodes/Document-createComment.html | 21 ++++++ ...nt-createProcessingInstruction-xhtml.xhtml | 15 +++++ .../Document-createProcessingInstruction.html | 11 +++ .../Document-createProcessingInstruction.js | 39 +++++++++++ .../dom/nodes/Document-createTextNode.html | 21 ++++++ tests/wpt/dom/nodes/Document-importNode.html | 67 +++++++++++++++++++ 11 files changed, 339 insertions(+) create mode 100644 tests/wpt/dom/nodes/Document-adoptNode.html create mode 100644 tests/wpt/dom/nodes/Document-createAttribute.html create mode 100644 tests/wpt/dom/nodes/Document-createCDATASection-xhtml.xhtml create mode 100644 tests/wpt/dom/nodes/Document-createCDATASection.html create mode 100644 tests/wpt/dom/nodes/Document-createComment-createTextNode.js create mode 100644 tests/wpt/dom/nodes/Document-createComment.html create mode 100644 tests/wpt/dom/nodes/Document-createProcessingInstruction-xhtml.xhtml create mode 100644 tests/wpt/dom/nodes/Document-createProcessingInstruction.html create mode 100644 tests/wpt/dom/nodes/Document-createProcessingInstruction.js create mode 100644 tests/wpt/dom/nodes/Document-createTextNode.html create mode 100644 tests/wpt/dom/nodes/Document-importNode.html diff --git a/tests/wpt/dom/nodes/Document-adoptNode.html b/tests/wpt/dom/nodes/Document-adoptNode.html new file mode 100644 index 00000000..60a4e677 --- /dev/null +++ b/tests/wpt/dom/nodes/Document-adoptNode.html @@ -0,0 +1,50 @@ + + +Document.adoptNode + + + +
+x + diff --git a/tests/wpt/dom/nodes/Document-createAttribute.html b/tests/wpt/dom/nodes/Document-createAttribute.html new file mode 100644 index 00000000..b3dc8b60 --- /dev/null +++ b/tests/wpt/dom/nodes/Document-createAttribute.html @@ -0,0 +1,55 @@ + + +Document.createAttribute + + + + +
+ diff --git a/tests/wpt/dom/nodes/Document-createCDATASection-xhtml.xhtml b/tests/wpt/dom/nodes/Document-createCDATASection-xhtml.xhtml new file mode 100644 index 00000000..b0a5a7f2 --- /dev/null +++ b/tests/wpt/dom/nodes/Document-createCDATASection-xhtml.xhtml @@ -0,0 +1,22 @@ + + + + + document.createCDATASection + + + + + + + + + + diff --git a/tests/wpt/dom/nodes/Document-createCDATASection.html b/tests/wpt/dom/nodes/Document-createCDATASection.html new file mode 100644 index 00000000..72b3684c --- /dev/null +++ b/tests/wpt/dom/nodes/Document-createCDATASection.html @@ -0,0 +1,16 @@ + + +document.createCDATASection must throw in HTML documents + + + + + diff --git a/tests/wpt/dom/nodes/Document-createComment-createTextNode.js b/tests/wpt/dom/nodes/Document-createComment-createTextNode.js new file mode 100644 index 00000000..62a38d38 --- /dev/null +++ b/tests/wpt/dom/nodes/Document-createComment-createTextNode.js @@ -0,0 +1,22 @@ +function test_create(method, iface, nodeType, nodeName) { + ["\u000b", "a -- b", "a-", "-b", null, undefined].forEach(function(value) { + test(function() { + var c = document[method](value); + var expected = String(value); + assert_true(c instanceof iface); + assert_true(c instanceof CharacterData); + assert_true(c instanceof Node); + assert_equals(c.ownerDocument, document); + assert_equals(c.data, expected, "data"); + assert_equals(c.nodeValue, expected, "nodeValue"); + assert_equals(c.textContent, expected, "textContent"); + assert_equals(c.length, expected.length); + assert_equals(c.nodeType, nodeType); + assert_equals(c.nodeName, nodeName); + assert_equals(c.hasChildNodes(), false); + assert_equals(c.childNodes.length, 0); + assert_equals(c.firstChild, null); + assert_equals(c.lastChild, null); + }, method + "(" + format_value(value) + ")"); + }); +} diff --git a/tests/wpt/dom/nodes/Document-createComment.html b/tests/wpt/dom/nodes/Document-createComment.html new file mode 100644 index 00000000..a175c3a2 --- /dev/null +++ b/tests/wpt/dom/nodes/Document-createComment.html @@ -0,0 +1,21 @@ + + +Document.createComment + + + + + + + + + + + + + + +
+ diff --git a/tests/wpt/dom/nodes/Document-createProcessingInstruction-xhtml.xhtml b/tests/wpt/dom/nodes/Document-createProcessingInstruction-xhtml.xhtml new file mode 100644 index 00000000..d06f70fd --- /dev/null +++ b/tests/wpt/dom/nodes/Document-createProcessingInstruction-xhtml.xhtml @@ -0,0 +1,15 @@ + + +Document.createProcessingInstruction in XML documents + + + + + + + + +
+ + +
+ diff --git a/tests/wpt/dom/nodes/Document-createProcessingInstruction.js b/tests/wpt/dom/nodes/Document-createProcessingInstruction.js new file mode 100644 index 00000000..d6cc3725 --- /dev/null +++ b/tests/wpt/dom/nodes/Document-createProcessingInstruction.js @@ -0,0 +1,39 @@ +test(function() { + var invalid = [ + ["A", "?>"], + ["\u00B7A", "x"], + ["\u00D7A", "x"], + ["A\u00D7", "x"], + ["\\A", "x"], + ["\f", "x"], + [0, "x"], + ["0", "x"] + ], + valid = [ + ["xml:fail", "x"], + ["A\u00B7A", "x"], + ["a0", "x"] + ] + + for (var i = 0, il = invalid.length; i < il; i++) { + test(function() { + assert_throws_dom("INVALID_CHARACTER_ERR", function() { + document.createProcessingInstruction(invalid[i][0], invalid[i][1]) + }) + }, "Should throw an INVALID_CHARACTER_ERR for target " + + format_value(invalid[i][0]) + " and data " + + format_value(invalid[i][1]) + ".") + } + for (var i = 0, il = valid.length; i < il; ++i) { + test(function() { + var pi = document.createProcessingInstruction(valid[i][0], valid[i][1]); + assert_equals(pi.target, valid[i][0]); + assert_equals(pi.data, valid[i][1]); + assert_equals(pi.ownerDocument, document); + assert_true(pi instanceof ProcessingInstruction); + assert_true(pi instanceof Node); + }, "Should get a ProcessingInstruction for target " + + format_value(valid[i][0]) + " and data " + + format_value(valid[i][1]) + ".") + } +}) diff --git a/tests/wpt/dom/nodes/Document-createTextNode.html b/tests/wpt/dom/nodes/Document-createTextNode.html new file mode 100644 index 00000000..ccc1b1b7 --- /dev/null +++ b/tests/wpt/dom/nodes/Document-createTextNode.html @@ -0,0 +1,21 @@ + + +Document.createTextNode + + + + + + + + + + + + + + +
+ diff --git a/tests/wpt/dom/nodes/Document-importNode.html b/tests/wpt/dom/nodes/Document-importNode.html new file mode 100644 index 00000000..d27cce6c --- /dev/null +++ b/tests/wpt/dom/nodes/Document-importNode.html @@ -0,0 +1,67 @@ + + +Document.importNode + + + +
+ From 67b354abed7325657445454a0e949a059c483691 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 7 Dec 2023 17:48:50 +0100 Subject: [PATCH 11/13] dom: fix adoptNode and importNode return --- src/dom/document.zig | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/dom/document.zig b/src/dom/document.zig index faa6dc54..e527d304 100644 --- a/src/dom/document.zig +++ b/src/dom/document.zig @@ -7,6 +7,7 @@ const Case = jsruntime.test_utils.Case; const checkCases = jsruntime.test_utils.checkCases; const Node = @import("node.zig").Node; +const NodeUnion = @import("node.zig").Union; const collection = @import("html_collection.zig"); @@ -145,12 +146,14 @@ pub const Document = struct { return try parser.documentCreateProcessingInstruction(self, target, data); } - pub fn _importNode(self: *parser.Document, node: *parser.Node, deep: ?bool) !*parser.Node { - return try parser.documentImportNode(self, node, deep orelse false); + pub fn _importNode(self: *parser.Document, node: *parser.Node, deep: ?bool) !NodeUnion { + const n = try parser.documentImportNode(self, node, deep orelse false); + return try Node.toInterface(n); } - pub fn _adoptNode(self: *parser.Document, node: *parser.Node) !*parser.Node { - return try parser.documentAdoptNode(self, node); + pub fn _adoptNode(self: *parser.Document, node: *parser.Node) !NodeUnion { + const n = try parser.documentAdoptNode(self, node); + return try Node.toInterface(n); } pub fn _createAttribute(self: *parser.Document, name: []const u8) !*parser.Attribute { @@ -281,13 +284,13 @@ pub fn testExecFn( var importNode = [_]Case{ .{ .src = "let nimp = document.getElementById('content')", .ex = "undefined" }, - .{ .src = "document.importNode(nimp)", .ex = "[object Node]" }, + .{ .src = "document.importNode(nimp)", .ex = "[object HTMLDivElement]" }, }; try checkCases(js_env, &importNode); var adoptNode = [_]Case{ .{ .src = "let nadop = document.getElementById('content')", .ex = "undefined" }, - .{ .src = "document.adoptNode(nadop)", .ex = "[object Node]" }, + .{ .src = "document.adoptNode(nadop)", .ex = "[object HTMLDivElement]" }, }; try checkCases(js_env, &adoptNode); From 9ef61b424e75792fb6282618cb353dfcda818d87 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Fri, 8 Dec 2023 14:59:13 +0100 Subject: [PATCH 12/13] dom: create a Text.Interface union --- src/dom/character_data.zig | 7 +++---- src/dom/text.zig | 7 +++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/dom/character_data.zig b/src/dom/character_data.zig index 447edf53..54c4b603 100644 --- a/src/dom/character_data.zig +++ b/src/dom/character_data.zig @@ -9,16 +9,15 @@ const parser = @import("../netsurf.zig"); const Node = @import("node.zig").Node; const Comment = @import("comment.zig").Comment; -const Text = @import("text.zig").Text; -const CDATASection = @import("cdata_section.zig").CDATASection; +const Text = @import("text.zig"); const ProcessingInstruction = @import("processing_instruction.zig").ProcessingInstruction; const HTMLElem = @import("../html/elements.zig"); // CharacterData interfaces pub const Interfaces = generate.Tuple(.{ Comment, - Text, - CDATASection, + Text.Text, + Text.Interfaces, ProcessingInstruction, }); diff --git a/src/dom/text.zig b/src/dom/text.zig index ec098d00..30abec22 100644 --- a/src/dom/text.zig +++ b/src/dom/text.zig @@ -3,10 +3,17 @@ const std = @import("std"); const jsruntime = @import("jsruntime"); const Case = jsruntime.test_utils.Case; const checkCases = jsruntime.test_utils.checkCases; +const generate = @import("../generate.zig"); const parser = @import("../netsurf.zig"); const CharacterData = @import("character_data.zig").CharacterData; +const CDATASection = @import("cdata_section.zig").CDATASection; + +// Text interfaces +pub const Interfaces = generate.Tuple(.{ + CDATASection, +}); pub const Text = struct { pub const Self = parser.Text; From 9c7194e98dfe79e1b08b266270942408983eea82 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Fri, 8 Dec 2023 15:06:47 +0100 Subject: [PATCH 13/13] dom: use nodeName instead of string representation for document unit test --- src/dom/document.zig | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/dom/document.zig b/src/dom/document.zig index e527d304..8bb4577d 100644 --- a/src/dom/document.zig +++ b/src/dom/document.zig @@ -257,22 +257,26 @@ pub fn testExecFn( try checkCases(js_env, &new); var createDocumentFragment = [_]Case{ - .{ .src = "document.createDocumentFragment()", .ex = "[object DocumentFragment]" }, + .{ .src = "var v = document.createDocumentFragment()", .ex = "undefined" }, + .{ .src = "v.nodeName", .ex = "#document-fragment" }, }; try checkCases(js_env, &createDocumentFragment); var createTextNode = [_]Case{ - .{ .src = "document.createTextNode('foo')", .ex = "[object Text]" }, + .{ .src = "var v = document.createTextNode('foo')", .ex = "undefined" }, + .{ .src = "v.nodeName", .ex = "#text" }, }; try checkCases(js_env, &createTextNode); var createCDATASection = [_]Case{ - .{ .src = "document.createCDATASection('foo')", .ex = "[object CDATASection]" }, + .{ .src = "var v = document.createCDATASection('foo')", .ex = "undefined" }, + .{ .src = "v.nodeName", .ex = "#cdata-section" }, }; try checkCases(js_env, &createCDATASection); var createComment = [_]Case{ - .{ .src = "document.createComment('foo')", .ex = "[object Comment]" }, + .{ .src = "var v = document.createComment('foo')", .ex = "undefined" }, + .{ .src = "v.nodeName", .ex = "#comment" }, }; try checkCases(js_env, &createComment); @@ -284,18 +288,21 @@ pub fn testExecFn( var importNode = [_]Case{ .{ .src = "let nimp = document.getElementById('content')", .ex = "undefined" }, - .{ .src = "document.importNode(nimp)", .ex = "[object HTMLDivElement]" }, + .{ .src = "var v = document.importNode(nimp)", .ex = "undefined" }, + .{ .src = "v.nodeName", .ex = "DIV" }, }; try checkCases(js_env, &importNode); var adoptNode = [_]Case{ .{ .src = "let nadop = document.getElementById('content')", .ex = "undefined" }, - .{ .src = "document.adoptNode(nadop)", .ex = "[object HTMLDivElement]" }, + .{ .src = "var v = document.adoptNode(nadop)", .ex = "undefined" }, + .{ .src = "v.nodeName", .ex = "DIV" }, }; try checkCases(js_env, &adoptNode); var createAttr = [_]Case{ - .{ .src = "document.createAttribute('foo')", .ex = "[object Attr]" }, + .{ .src = "var v = document.createAttribute('foo')", .ex = "undefined" }, + .{ .src = "v.nodeName", .ex = "foo" }, }; try checkCases(js_env, &createAttr);