legacy tests

This commit is contained in:
Karl Seguin
2025-12-25 16:47:08 +08:00
parent c88cb35b84
commit cc3a498294
8 changed files with 109 additions and 120 deletions

View File

@@ -258,3 +258,27 @@
testing.expectEqual('text node', body.childNodes[0].textContent);
}
</script>
<script id=children>
testing.expectEqual(1, document.children.length);
testing.expectEqual('HTML', document.children.item(0).nodeName)
testing.expectEqual('HTML', document.firstElementChild.nodeName);
testing.expectEqual('HTML', document.lastElementChild.nodeName);
testing.expectEqual(1, document.childElementCount);
let nd = new Document();
testing.expectEqual(0, nd.children.length);
testing.expectEqual(null, nd.children.item(0));
testing.expectEqual(null, nd.firstElementChild);
testing.expectEqual(null, nd.lastElementChild);
testing.expectEqual(0, nd.childElementCount);
</script>
<script id=adoptedStyleSheets>
{
const acss = document.adoptedStyleSheets;
testing.expectEqual(0, acss.length);
acss.push(new CSSStyleSheet());
testing.expectEqual(1, acss.length);
}
</script>

View File

@@ -56,7 +56,14 @@
{
const event = document.createEvent('CustomEvent');
testing.expectEqual('', event.type);
testing.expectEqual(false, event.bubbles);
testing.expectEqual(false, event.cancelable);
testing.expectEqual(null, event.detail);
event.initCustomEvent('tea', true, true);
testing.expectEqual('tea', event.type);
testing.expectEqual(true, event.bubbles);
testing.expectEqual(true, event.cancelable);
}
</script>

View File

@@ -85,9 +85,6 @@
v = document.createTextNode('foo');
testing.expectEqual('#text', v.nodeName);
v = document.createCDATASection('foo');
testing.expectEqual('#cdata-section', v.nodeName);
v = document.createAttribute('foo');
testing.expectEqual('foo', v.nodeName);
@@ -108,7 +105,7 @@
<script id=children>
testing.expectEqual(1, document.children.length);
testing.expectEqual('HTML', document.children.item(0).nodeName);
testing.expectEqual('HTML', document.children.item(0).nodeName)
testing.expectEqual('HTML', document.firstElementChild.nodeName);
testing.expectEqual('HTML', document.lastElementChild.nodeName);
testing.expectEqual(1, document.childElementCount);
@@ -121,7 +118,7 @@
testing.expectEqual(0, nd.childElementCount);
</script>
<script id=createElement>
<!-- <script id=createElement>
let emptydoc = document.createElement('html');
emptydoc.prepend(document.createElement('html'));
@@ -132,10 +129,9 @@
// Maybe that something doesn't crash?
// Adding this so that the test runner doesn't complain;
testing.skip();
</script>
</script> -->
<script id=querySelector>
testing.expectEqual(null, document.querySelector(''));
testing.expectEqual('HTML', document.querySelector('*').nodeName);
testing.expectEqual('content', document.querySelector('#content').id);
testing.expectEqual('p1', document.querySelector('#p1').id);

View File

@@ -118,10 +118,10 @@
new IntersectionObserver(entries => { entry = entries[0]; }).observe(div1);
testing.eventually(() => {
testing.expectEqual(0, entry.boundingClientRect.x);
testing.expectEqual(125, entry.boundingClientRect.x);
testing.expectEqual(1, entry.intersectionRatio);
testing.expectEqual(0, entry.intersectionRect.x);
testing.expectEqual(315, entry.intersectionRect.y);
testing.expectEqual(125, entry.intersectionRect.x);
testing.expectEqual(125, entry.intersectionRect.y);
testing.expectEqual(5, entry.intersectionRect.width);
testing.expectEqual(5, entry.intersectionRect.height);
testing.expectEqual(true, entry.isIntersecting);

View File

@@ -1,60 +0,0 @@
<!DOCTYPE html>
<script src="../testing.js"></script>
<script id=messageChannel>
const mc1 = new MessageChannel();
testing.expectEqual(mc1.port1, mc1.port1);
testing.expectEqual(mc1.port2, mc1.port2);
testing.expectEqual(true, mc1.port1 != mc1.port2);
mc1.port1.postMessage('msg1');
let message = null;
let target = null;
let currentTarget = null;
mc1.port2.onmessage = (e) => {
message = e.data;
target = e.target;
currentTarget = e.currentTarget;
};
// as soon as onmessage is called, queued messages are delivered
testing.expectEqual('msg1', message);
testing.expectEqual(mc1.port2, target);
testing.expectEqual(mc1.port2, currentTarget);
mc1.port1.postMessage('msg2');
testing.expectEqual('msg2', message);
testing.expectEqual(mc1.port2, target);
testing.expectEqual(mc1.port2, currentTarget);
message = null;
mc1.port1.close();
mc1.port1.postMessage('msg3');
testing.expectEqual(null, message);
const mc2 = new MessageChannel();
mc2.port2.postMessage('msg1');
mc2.port1.postMessage('msg2');
let message1 = null;
mc2.port1.addEventListener('message', (e) => {
message1 = e.data;
});
let message2 = null;
mc2.port2.addEventListener('message', (e) => {
message2 = e.data;
});
testing.expectEqual(null, message1);
testing.expectEqual(null, message2);
mc2.port2.start();
testing.expectEqual(null, message1);
testing.expectEqual('msg2', message2);
message2 = null;
mc2.port1.start();
testing.expectEqual('msg1', message1);
testing.expectEqual(null, message2);
</script>

View File

@@ -1,49 +0,0 @@
<!DOCTYPE html>
<div id=conflict>node</div>
<script src="../testing.js"></script>
<script id=shadow_root>
const div1 = document.createElement('div');
let sr1 = div1.attachShadow({mode: 'open'});
testing.expectEqual(div1, sr1.host);
testing.expectEqual(sr1, div1.attachShadow({mode: 'open'}));
testing.expectEqual(sr1, div1.shadowRoot);
testing.expectError('Error: NotSupportedError', () => {
div1.attachShadow({mode: 'closed'});
});
sr1.append(document.createElement('div'));
sr1.append(document.createElement('span'));
testing.expectEqual(2, sr1.childElementCount);
// re-attaching clears it
testing.expectEqual(sr1, div1.attachShadow({mode: 'open'}));
testing.expectEqual(0, sr1.childElementCount);
const div2 = document.createElement('di2');
let sr2 = div2.attachShadow({mode: 'closed'});
testing.expectEqual(div2, sr2.host);
testing.expectEqual(null, div2.shadowRoot) // null when attached with 'closed'
testing.expectEqual(null, sr2.getElementById('conflict'));
const n1 = document.createElement('div');
n1.id = 'conflict';
sr2.append(n1);
testing.expectEqual(n1, sr2.getElementById('conflict'));
const acss = sr2.adoptedStyleSheets;
testing.expectEqual(0, acss.length);
acss.push(new CSSStyleSheet());
testing.expectEqual(1, acss.length);
sr1.innerHTML = '<p>hello</p>';
testing.expectEqual('<p>hello</p>', sr1.innerHTML);
testing.expectEqual('[object HTMLParagraphElement]', sr1.querySelector('*').toString());
sr1.innerHTML = null;
testing.expectEqual('', sr1.innerHTML);
testing.expectEqual(null, sr1.querySelector('*'));
</script>

View File

@@ -51,6 +51,7 @@ _active_element: ?*Element = null,
_style_sheets: ?*StyleSheetList = null,
_write_insertion_point: ?*Node = null,
_script_created_parser: ?Parser.Streaming = null,
_adopted_style_sheets: ?js.Object = null,
pub const Type = union(enum) {
generic,
@@ -250,7 +251,7 @@ pub fn createTextNode(_: *const Document, data: []const u8, page: *Page) !*Node
pub fn createCDATASection(self: *const Document, data: []const u8, page: *Page) !*Node {
switch (self._type) {
.html => return error.NotSupported,
.html => return error.NotSupported, // cannot create a CDataSection in an HTMLDocument
.xml => return page.createCDATASection(data),
.generic => return page.createCDATASection(data),
}
@@ -537,6 +538,51 @@ pub fn close(self: *Document, page: *Page) !void {
page.documentIsComplete();
}
pub fn getFirstElementChild(self: *Document) ?*Element {
var it = self.asNode().childrenIterator();
while (it.next()) |child| {
if (child.is(Element)) |el| {
return el;
}
}
return null;
}
pub fn getLastElementChild(self: *Document) ?*Element {
var maybe_child = self.asNode().lastChild();
while (maybe_child) |child| {
if (child.is(Element)) |el| {
return el;
}
maybe_child = child.previousSibling();
}
return null;
}
pub fn getChildElementCount(self: *Document) u32 {
var i: u32 = 0;
var it = self.asNode().childrenIterator();
while (it.next()) |child| {
if (child.is(Element) != null) {
i += 1;
}
}
return i;
}
pub fn getAdoptedStyleSheets(self: *Document, page: *Page) !js.Object {
if (self._adopted_style_sheets) |ass| {
return ass;
}
const obj = try page.js.createArray(0).persist();
self._adopted_style_sheets = obj;
return obj;
}
pub fn setAdoptedStyleSheets(self: *Document, sheets: js.Object) !void {
self._adopted_style_sheets = try sheets.persist();
}
const ReadyState = enum {
loading,
interactive,
@@ -603,6 +649,10 @@ pub const JsApi = struct {
pub const open = bridge.function(Document.open, .{ .dom_exception = true });
pub const close = bridge.function(Document.close, .{ .dom_exception = true });
pub const doctype = bridge.accessor(Document.getDocType, null, .{});
pub const firstElementChild = bridge.accessor(Document.getFirstElementChild, null, .{});
pub const lastElementChild = bridge.accessor(Document.getLastElementChild, null, .{});
pub const childElementCount = bridge.accessor(Document.getChildElementCount, null, .{});
pub const adoptedStyleSheets = bridge.accessor(Document.getAdoptedStyleSheets, Document.setAdoptedStyleSheets, .{});
pub const defaultView = bridge.accessor(struct {
fn defaultView(_: *const Document, page: *Page) *@import("Window.zig") {

View File

@@ -18,6 +18,7 @@
const std = @import("std");
const js = @import("../../js/js.zig");
const String = @import("../../..//string.zig").String;
const Page = @import("../../Page.zig");
const Event = @import("../Event.zig");
@@ -52,6 +53,25 @@ pub fn init(typ: []const u8, opts_: ?Options, page: *Page) !*CustomEvent {
return event;
}
pub fn initCustomEvent(
self: *CustomEvent,
event_string: []const u8,
bubbles: bool,
cancelable: bool,
detail_: ?js.Object,
page: *Page,
) !void {
// This function can only be called after the constructor has called.
// So we assume proto is initialized already by constructor.
self._proto._type_string = try String.init(page.arena, event_string, .{});
self._proto._bubbles = bubbles;
self._proto._cancelable = cancelable;
// Detail is stored separately.
if (detail_) |detail| {
self._detail = try detail.persist();
}
}
pub fn asEvent(self: *CustomEvent) *Event {
return self._proto;
}
@@ -71,6 +91,7 @@ pub const JsApi = struct {
pub const constructor = bridge.constructor(CustomEvent.init, .{});
pub const detail = bridge.accessor(CustomEvent.getDetail, null, .{});
pub const initCustomEvent = bridge.function(CustomEvent.initCustomEvent, .{});
};
const testing = @import("../../../testing.zig");