Skip to content

Commit d397d75

Browse files
committed
DOMImplementation and DocumentType skeletons
1 parent 618b28a commit d397d75

File tree

8 files changed

+209
-3
lines changed

8 files changed

+209
-3
lines changed

src/browser/dump.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub fn deep(node: *Node, opts: Opts, writer: *std.Io.Writer) error{WriteFailed}!
2626
}
2727
},
2828
.document => try children(node, opts, writer),
29+
.document_type => {},
2930
.document_fragment => try children(node, opts, writer),
3031
.attribute => unreachable,
3132
}
@@ -49,6 +50,9 @@ pub fn toJSON(node: *Node, writer: *std.json.Stringify) !void {
4950
.document => {
5051
try writer.write("document");
5152
},
53+
.document_type => {
54+
try writer.write("document_type");
55+
},
5256
.element => |*el| {
5357
try writer.write("element");
5458
try writer.objectField("tag");

src/browser/js/bridge.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,9 @@ pub const JsApis = flattenTypes(&.{
446446
@import("../webapi/HTMLDocument.zig"),
447447
@import("../webapi/KeyValueList.zig"),
448448
@import("../webapi/DocumentFragment.zig"),
449+
@import("../webapi/DocumentType.zig"),
449450
@import("../webapi/DOMException.zig"),
451+
@import("../webapi/DOMImplementation.zig"),
450452
@import("../webapi/DOMTreeWalker.zig"),
451453
@import("../webapi/DOMNodeIterator.zig"),
452454
@import("../webapi/NodeFilter.zig"),
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<!DOCTYPE html>
2+
<head>
3+
<title>DOMImplementation Test</title>
4+
<script src="testing.js"></script>
5+
</head>
6+
7+
<body>
8+
</body>
9+
10+
<script id=implementation>
11+
{
12+
const impl = document.implementation;
13+
testing.expectEqual('[object DOMImplementation]', impl.toString());
14+
}
15+
</script>
16+
17+
<script id=hasFeature>
18+
{
19+
const impl = document.implementation;
20+
testing.expectEqual(true, impl.hasFeature('XML', '1.0'));
21+
testing.expectEqual(true, impl.hasFeature('HTML', '2.0'));
22+
testing.expectEqual(true, impl.hasFeature('', null));
23+
}
24+
</script>
25+
26+
<script id=createDocumentType>
27+
{
28+
const impl = document.implementation;
29+
const doctype = impl.createDocumentType('html', '', '');
30+
testing.expectEqual(10, doctype.nodeType);
31+
testing.expectEqual('html', doctype.nodeName);
32+
testing.expectEqual('html', doctype.name);
33+
testing.expectEqual('', doctype.publicId);
34+
testing.expectEqual('', doctype.systemId);
35+
testing.expectEqual('[object DocumentType]', doctype.toString());
36+
}
37+
</script>
38+
39+
<script id=createDocumentTypeWithIds>
40+
{
41+
const impl = document.implementation;
42+
const doctype = impl.createDocumentType(
43+
'svg',
44+
'-//W3C//DTD SVG 1.1//EN',
45+
'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'
46+
);
47+
testing.expectEqual('svg', doctype.name);
48+
testing.expectEqual('-//W3C//DTD SVG 1.1//EN', doctype.publicId);
49+
testing.expectEqual('http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd', doctype.systemId);
50+
}
51+
</script>
52+
53+
<script id=createDocumentTypeNullIds>
54+
{
55+
const impl = document.implementation;
56+
const doctype = impl.createDocumentType('html', null, null);
57+
testing.expectEqual('html', doctype.name);
58+
testing.expectEqual('', doctype.publicId);
59+
testing.expectEqual('', doctype.systemId);
60+
}
61+
</script>
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
const std = @import("std");
2+
3+
const js = @import("../js/js.zig");
4+
const Page = @import("../Page.zig");
5+
const Node = @import("Node.zig");
6+
const DocumentType = @import("DocumentType.zig");
7+
8+
const DOMImplementation = @This();
9+
10+
pub fn createDocumentType(_: *const DOMImplementation, qualified_name: []const u8, public_id: ?[]const u8, system_id: ?[]const u8, page: *Page) !*DocumentType {
11+
const name = try page.dupeString(qualified_name);
12+
const pub_id = try page.dupeString(public_id orelse "");
13+
const sys_id = try page.dupeString(system_id orelse "");
14+
15+
const doctype = try page._factory.node(DocumentType{
16+
._proto = undefined,
17+
._name = name,
18+
._public_id = pub_id,
19+
._system_id = sys_id,
20+
});
21+
22+
return doctype;
23+
}
24+
25+
pub fn hasFeature(_: *const DOMImplementation, _: []const u8, _: ?[]const u8) bool {
26+
// Modern DOM spec says this should always return true
27+
// This method is deprecated and kept for compatibility only
28+
return true;
29+
}
30+
31+
pub fn className(_: *const DOMImplementation) []const u8 {
32+
return "[object DOMImplementation]";
33+
}
34+
35+
pub const JsApi = struct {
36+
pub const bridge = js.Bridge(DOMImplementation);
37+
38+
pub const Meta = struct {
39+
pub const name = "DOMImplementation";
40+
pub const prototype_chain = bridge.prototypeChain();
41+
pub var class_index: u16 = 0;
42+
pub const empty_with_no_proto = true;
43+
};
44+
45+
pub const createDocumentType = bridge.function(DOMImplementation.createDocumentType, .{ .dom_exception = true });
46+
pub const hasFeature = bridge.function(DOMImplementation.hasFeature, .{});
47+
48+
pub const toString = bridge.function(_toString, .{});
49+
fn _toString(_: *const DOMImplementation) []const u8 {
50+
return "[object DOMImplementation]";
51+
}
52+
};
53+
54+
const testing = @import("../../testing.zig");
55+
test "WebApi: DOMImplementation" {
56+
try testing.htmlRunner("domimplementation.html", .{});
57+
}

src/browser/webapi/Document.zig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const Selector = @import("selector/Selector.zig");
1212
const NodeFilter = @import("NodeFilter.zig");
1313
const DOMTreeWalker = @import("DOMTreeWalker.zig");
1414
const DOMNodeIterator = @import("DOMNodeIterator.zig");
15+
const DOMImplementation = @import("DOMImplementation.zig");
1516

1617
pub const HTMLDocument = @import("HTMLDocument.zig");
1718

@@ -124,6 +125,10 @@ pub fn className(_: *const Document) []const u8 {
124125
return "[object Document]";
125126
}
126127

128+
pub fn getImplementation(_: *const Document) DOMImplementation {
129+
return .{};
130+
}
131+
127132
pub fn createDocumentFragment(_: *const Document, page: *Page) !*@import("DocumentFragment.zig") {
128133
return @import("DocumentFragment.zig").init(page);
129134
}
@@ -176,6 +181,7 @@ pub const JsApi = struct {
176181
pub const URL = bridge.accessor(Document.getURL, null, .{});
177182
pub const documentElement = bridge.accessor(Document.getDocumentElement, null, .{});
178183
pub const readyState = bridge.accessor(Document.getReadyState, null, .{});
184+
pub const implementation = bridge.accessor(Document.getImplementation, null, .{});
179185

180186
pub const createElement = bridge.function(Document.createElement, .{});
181187
pub const createElementNS = bridge.function(Document.createElementNS, .{});
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
const std = @import("std");
2+
3+
const js = @import("../js/js.zig");
4+
const Page = @import("../Page.zig");
5+
const Node = @import("Node.zig");
6+
7+
const DocumentType = @This();
8+
9+
_proto: *Node,
10+
_name: []const u8,
11+
_public_id: []const u8,
12+
_system_id: []const u8,
13+
14+
pub fn asNode(self: *DocumentType) *Node {
15+
return self._proto;
16+
}
17+
18+
pub fn asEventTarget(self: *DocumentType) *@import("EventTarget.zig") {
19+
return self._proto.asEventTarget();
20+
}
21+
22+
pub fn getName(self: *const DocumentType) []const u8 {
23+
return self._name;
24+
}
25+
26+
pub fn getPublicId(self: *const DocumentType) []const u8 {
27+
return self._public_id;
28+
}
29+
30+
pub fn getSystemId(self: *const DocumentType) []const u8 {
31+
return self._system_id;
32+
}
33+
34+
pub fn className(_: *const DocumentType) []const u8 {
35+
return "[object DocumentType]";
36+
}
37+
38+
pub const JsApi = struct {
39+
pub const bridge = js.Bridge(DocumentType);
40+
41+
pub const Meta = struct {
42+
pub const name = "DocumentType";
43+
pub const prototype_chain = bridge.prototypeChain();
44+
pub var class_index: u16 = 0;
45+
};
46+
47+
pub const name = bridge.accessor(DocumentType.getName, null, .{});
48+
pub const publicId = bridge.accessor(DocumentType.getPublicId, null, .{});
49+
pub const systemId = bridge.accessor(DocumentType.getSystemId, null, .{});
50+
51+
pub const toString = bridge.function(_toString, .{});
52+
fn _toString(self: *const DocumentType) []const u8 {
53+
return self.className();
54+
}
55+
};
56+
57+
const testing = @import("../../testing.zig");
58+
test "WebApi: DOMImplementation" {
59+
try testing.htmlRunner("domimplementation.html", .{});
60+
}

src/browser/webapi/Node.zig

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ const collections = @import("collections.zig");
1111
pub const CData = @import("CData.zig");
1212
pub const Element = @import("Element.zig");
1313
pub const Document = @import("Document.zig");
14+
pub const HTMLDocument = @import("HTMLDocument.zig");
1415
pub const Children = @import("children.zig").Children;
1516
pub const DocumentFragment = @import("DocumentFragment.zig");
17+
pub const DocumentType = @import("DocumentType.zig");
1618

1719
const Allocator = std.mem.Allocator;
1820
const LinkedList = std.DoublyLinkedList;
@@ -29,6 +31,7 @@ pub const Type = union(enum) {
2931
cdata: *CData,
3032
element: *Element,
3133
document: *Document,
34+
document_type: *DocumentType,
3235
attribute: *Element.Attribute,
3336
document_fragment: *DocumentFragment,
3437
};
@@ -76,6 +79,11 @@ pub fn is(self: *Node, comptime T: type) ?*T {
7679
return doc.is(T);
7780
}
7881
},
82+
.document_type => |dt| {
83+
if (T == DocumentType) {
84+
return dt;
85+
}
86+
},
7987
.document_fragment => |doc| {
8088
if (T == DocumentFragment) {
8189
return doc;
@@ -145,6 +153,7 @@ pub fn getTextContent(self: *Node, writer: *std.Io.Writer) error{WriteFailed}!vo
145153
.element => |el| return el.getInnerText(writer),
146154
.cdata => |c| try writer.writeAll(c.getData()),
147155
.document => {},
156+
.document_type => {},
148157
.document_fragment => {},
149158
.attribute => |attr| try writer.writeAll(attr._value),
150159
}
@@ -163,6 +172,7 @@ pub fn setTextContent(self: *Node, data: []const u8, page: *Page) !void {
163172
.element => |el| return el.replaceChildren(&.{.{ .text = data }}, page),
164173
.cdata => |c| c._data = try page.arena.dupe(u8, data),
165174
.document => {},
175+
.document_type => {},
166176
.document_fragment => {},
167177
.attribute => |attr| return attr.setValue(data, page),
168178
}
@@ -176,6 +186,7 @@ pub fn getNodeName(self: *const Node, page: *Page) ![]const u8 {
176186
.comment => "#comment",
177187
},
178188
.document => "#document",
189+
.document_type => |dt| dt.getName(),
179190
.document_fragment => "#document-fragment",
180191
.attribute => |attr| attr._name,
181192
};
@@ -190,6 +201,7 @@ pub fn nodeType(self: *const Node) u8 {
190201
.comment => 8,
191202
},
192203
.document => 9,
204+
.document_type => 10,
193205
.document_fragment => 11,
194206
};
195207
}
@@ -333,6 +345,7 @@ pub fn getNodeValue(self: *const Node) ?[]const u8 {
333345
.attribute => |attr| attr._value,
334346
.element => null,
335347
.document => null,
348+
.document_type => null,
336349
.document_fragment => null,
337350
};
338351
}
@@ -343,18 +356,19 @@ pub fn setNodeValue(self: *const Node, value: ?[]const u8, page: *Page) !void {
343356
.attribute => |attr| try attr.setValue(value, page),
344357
.element => {},
345358
.document => {},
359+
.document_type => {},
346360
.document_fragment => {},
347361
}
348362
}
349363

350364
pub fn format(self: *Node, writer: *std.Io.Writer) !void {
351365
// // If you need extra debugging:
352366
// return @import("../dump.zig").deep(self, .{}, writer);
353-
354367
return switch (self._type) {
355368
.cdata => |cd| cd.format(writer),
356369
.element => |el| writer.print("{f}", .{el}),
357370
.document => writer.writeAll("<document>"),
371+
.document_type => writer.writeAll("<doctype>"),
358372
.document_fragment => writer.writeAll("<document_fragment>"),
359373
.attribute => |attr| writer.print("{f}", .{attr}),
360374
};
@@ -380,8 +394,7 @@ pub fn className(self: *const Node) []const u8 {
380394

381395
pub fn normalize(self: *Node, page: *Page) !void {
382396
var buffer: std.ArrayListUnmanaged(u8) = .empty;
383-
const arena = page.call_arena;
384-
return self._normalize(arena, &buffer, page);
397+
return self._normalize(page.call_arena, &buffer, page);
385398
}
386399

387400
pub fn cloneNode(self: *Node, deep_: ?bool, page: *Page) error{ OutOfMemory, StringTooLarge, NotSupported, NotImplemented }!*Node {
@@ -396,6 +409,7 @@ pub fn cloneNode(self: *Node, deep_: ?bool, page: *Page) error{ OutOfMemory, Str
396409
},
397410
.element => |el| return el.cloneElement(deep, page),
398411
.document => return error.NotSupported,
412+
.document_type => return error.NotSupported,
399413
.document_fragment => return error.NotImplemented,
400414
.attribute => return error.NotSupported,
401415
}
@@ -612,6 +626,7 @@ pub const JsApi = struct {
612626
.cdata => |cdata| return cdata.getData(),
613627
.attribute => |attr| return attr._value,
614628
.document => return null,
629+
.document_type => return null,
615630
.document_fragment => return null,
616631
}
617632
}

src/browser/webapi/Window.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ pub const JsApi = struct {
249249

250250
pub const self = bridge.accessor(Window.getWindow, null, .{ .cache = "self" });
251251
pub const window = bridge.accessor(Window.getWindow, null, .{ .cache = "window" });
252+
pub const parent = bridge.accessor(Window.getWindow, null, .{ .cache = "parent" });
252253
pub const console = bridge.accessor(Window.getConsole, null, .{ .cache = "console" });
253254
pub const navigator = bridge.accessor(Window.getNavigator, null, .{ .cache = "navigator" });
254255
pub const localStorage = bridge.accessor(Window.getLocalStorage, null, .{ .cache = "localStorage" });

0 commit comments

Comments
 (0)