Merge pull request #1 from francisbouvier/dom_document_createElement

Implement HTMLDocument.createElement
This commit is contained in:
Francis Bouvier
2023-03-16 18:24:15 +01:00
committed by GitHub
12 changed files with 1325 additions and 134 deletions

47
Makefile Normal file
View File

@@ -0,0 +1,47 @@
# Infos
# -----
.PHONY: help
## Display this help screen
help:
@printf "\e[36m%-35s %s\e[0m\n" "Command" "Usage"
@sed -n '/^## /{\
s/## //g;\
h;\
n;\
s/:.*//g;\
G;\
s/\n/ /g;\
p;}' Makefile | awk '{printf "\033[33m%-35s\033[0m%s\n", $$1, substr($$0,length($$1)+1)}'
# Zig commands
# ------------
.PHONY: build build-release run run-release shell test bench
## Build in debug mode
build:
@printf "\e[36mBuilding (debug)...\e[0m\n"
@zig build || (printf "\e[33mBuild ERROR\e[0m\n"; exit 1;)
@printf "\e[33mBuild OK\e[0m\n"
build-release:
@printf "\e[36mBuilding (release safe)...\e[0m\n"
@zig build -Drelease-safe || (printf "\e[33mBuild ERROR\e[0m\n"; exit 1;)
@printf "\e[33mBuild OK\e[0m\n"
## Run the server
run: build
@printf "\e[36mRunning...\e[0m\n"
@./zig-out/bin/browsercore || (printf "\e[33mRun ERROR\e[0m\n"; exit 1;)
## Run a JS shell in release-safe mode
shell:
@printf "\e[36mBuilding shell...\e[0m\n"
@zig build shell || (printf "\e[33mBuild ERROR\e[0m\n"; exit 1;)
## Test
test:
@printf "\e[36mTesting...\e[0m\n"
@zig build test || (printf "\e[33mTest ERROR\e[0m\n"; exit 1;)
@printf "\e[33mTest OK\e[0m\n"

View File

@@ -71,6 +71,7 @@ fn common(
}
fn linkLexbor(step: *std.build.LibExeObjStep) void {
// cmake . -DLEXBOR_BUILD_SHARED=OFF
const lib_path = "../lexbor/liblexbor_static.a";
step.addObjectFile(lib_path);
step.addIncludePath("../lexbor/source");

View File

@@ -1,24 +1,91 @@
const Console = @import("jsruntime").Console;
pub const EventTarget = @import("dom/event_target.zig").EventTarget;
pub const Node = @import("dom/node.zig").Node;
// DOM
const EventTarget = @import("dom/event_target.zig").EventTarget;
const Node = @import("dom/node.zig").Node;
const Element = @import("dom/element.zig").Element;
const Document = @import("dom/document.zig").Document;
pub const Element = @import("dom/element.zig").Element;
pub const HTMLElement = @import("dom/element.zig").HTMLElement;
pub const HTMLBodyElement = @import("dom/element.zig").HTMLBodyElement;
// HTML
pub const HTMLDocument = @import("html/document.zig").HTMLDocument;
pub const Document = @import("dom/document.zig").Document;
pub const HTMLDocument = @import("dom/document.zig").HTMLDocument;
const E = @import("html/elements.zig");
// Interfaces
pub const Interfaces = .{
Console,
// DOM
EventTarget,
Node,
Element,
HTMLElement,
HTMLBodyElement,
Document,
// HTML
HTMLDocument,
E.HTMLElement,
E.HTMLMediaElement,
// TODO: generate HTMLElements comptime
E.HTMLUnknownElement,
E.HTMLAnchorElement,
E.HTMLAreaElement,
E.HTMLAudioElement,
E.HTMLBRElement,
E.HTMLBaseElement,
E.HTMLBodyElement,
E.HTMLButtonElement,
E.HTMLCanvasElement,
E.HTMLDListElement,
E.HTMLDialogElement,
E.HTMLDataElement,
E.HTMLDivElement,
E.HTMLEmbedElement,
E.HTMLFieldSetElement,
E.HTMLFormElement,
E.HTMLFrameSetElement,
E.HTMLHRElement,
E.HTMLHeadElement,
E.HTMLHeadingElement,
E.HTMLHtmlElement,
E.HTMLIFrameElement,
E.HTMLImageElement,
E.HTMLInputElement,
E.HTMLLIElement,
E.HTMLLabelElement,
E.HTMLLegendElement,
E.HTMLLinkElement,
E.HTMLMapElement,
E.HTMLMetaElement,
E.HTMLMeterElement,
E.HTMLModElement,
E.HTMLOListElement,
E.HTMLObjectElement,
E.HTMLOptGroupElement,
E.HTMLOptionElement,
E.HTMLOutputElement,
E.HTMLParagraphElement,
E.HTMLPictureElement,
E.HTMLPreElement,
E.HTMLProgressElement,
E.HTMLQuoteElement,
E.HTMLScriptElement,
E.HTMLSelectElement,
E.HTMLSourceElement,
E.HTMLSpanElement,
E.HTMLStyleElement,
E.HTMLTableElement,
E.HTMLTableCaptionElement,
E.HTMLTableCellElement,
E.HTMLTableColElement,
E.HTMLTableRowElement,
E.HTMLTableSectionElement,
E.HTMLTemplateElement,
E.HTMLTextAreaElement,
E.HTMLTimeElement,
E.HTMLTitleElement,
E.HTMLTrackElement,
E.HTMLUListElement,
E.HTMLVideoElement,
};

View File

@@ -1,16 +1,9 @@
const std = @import("std");
const jsruntime = @import("jsruntime");
const Case = jsruntime.test_utils.Case;
const checkCases = jsruntime.test_utils.checkCases;
const parser = @import("../parser.zig");
const DOM = @import("../dom.zig");
const Node = DOM.Node;
const Element = DOM.Element;
const HTMLElement = DOM.HTMLElement;
const HTMLBodyElement = DOM.HTMLBodyElement;
const Node = @import("node.zig").Node;
const Element = @import("element.zig").Element;
pub const Document = struct {
proto: Node,
@@ -29,7 +22,7 @@ pub const Document = struct {
return Document.init(null);
}
fn getElementById(self: Document, elem_dom: *parser.Element, id: []const u8) ?Element {
pub fn getElementById(self: Document, elem_dom: *parser.Element, id: []const u8) ?Element {
if (self.base == null) {
return null;
}
@@ -61,62 +54,3 @@ pub const Document = struct {
return null;
}
};
pub const HTMLDocument = struct {
proto: Document,
base: *parser.DocumentHTML,
pub const prototype = *Document;
pub fn init() HTMLDocument {
return .{
.proto = Document.init(null),
.base = parser.documentHTMLInit(),
};
}
pub fn deinit(self: HTMLDocument) void {
parser.documentHTMLDeinit(self.base);
}
pub fn parse(self: *HTMLDocument, html: []const u8) !void {
try parser.documentHTMLParse(self.base, html);
self.proto.base = parser.documentHTMLToDocument(self.base);
}
// JS funcs
// --------
pub fn get_body(self: HTMLDocument) ?HTMLBodyElement {
const body_dom = parser.documentHTMLBody(self.base);
return HTMLBodyElement.init(body_dom);
}
pub fn _getElementById(self: HTMLDocument, id: []u8) ?HTMLElement {
const body_dom = parser.documentHTMLBody(self.base);
if (self.proto.getElementById(body_dom, id)) |elem| {
return HTMLElement.init(elem.base);
}
return null;
}
};
pub fn testExecFn(
js_env: *jsruntime.Env,
comptime _: []jsruntime.API,
) !void {
var constructor = [_]Case{
.{ .src = "document.__proto__.constructor.name", .ex = "HTMLDocument" },
.{ .src = "document.__proto__.__proto__.constructor.name", .ex = "Document" },
.{ .src = "document.__proto__.__proto__.__proto__.constructor.name", .ex = "Node" },
.{ .src = "document.__proto__.__proto__.__proto__.__proto__.constructor.name", .ex = "EventTarget" },
};
try checkCases(js_env, &constructor);
var getElementById = [_]Case{
.{ .src = "let getElementById = document.getElementById('content')", .ex = "undefined" },
.{ .src = "getElementById.constructor.name", .ex = "HTMLElement" },
.{ .src = "getElementById.localName", .ex = "main" },
};
try checkCases(js_env, &getElementById);
}

View File

@@ -1,13 +1,8 @@
const std = @import("std");
const jsruntime = @import("jsruntime");
const Case = jsruntime.test_utils.Case;
const checkCases = jsruntime.test_utils.checkCases;
const parser = @import("../parser.zig");
const DOM = @import("../dom.zig");
const Node = DOM.Node;
const Node = @import("node.zig").Node;
pub const Element = struct {
proto: Node,
@@ -29,26 +24,3 @@ pub const Element = struct {
return parser.elementLocalName(self.base);
}
};
// HTML elements
// -------------
pub const HTMLElement = struct {
proto: Element,
pub const prototype = *Element;
pub fn init(elem_base: *parser.Element) HTMLElement {
return .{ .proto = Element.init(elem_base) };
}
};
pub const HTMLBodyElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLBodyElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};

403
src/html/document.zig Normal file
View File

@@ -0,0 +1,403 @@
const std = @import("std");
const parser = @import("../parser.zig");
const jsruntime = @import("jsruntime");
const Case = jsruntime.test_utils.Case;
const checkCases = jsruntime.test_utils.checkCases;
const Document = @import("../dom/document.zig").Document;
const E = @import("elements.zig");
pub const HTMLDocument = struct {
proto: Document,
base: *parser.DocumentHTML,
pub const prototype = *Document;
pub fn init() HTMLDocument {
return .{
.proto = Document.init(null),
.base = parser.documentHTMLInit(),
};
}
pub fn deinit(self: HTMLDocument) void {
parser.documentHTMLDeinit(self.base);
}
pub fn parse(self: *HTMLDocument, html: []const u8) !void {
try parser.documentHTMLParse(self.base, html);
self.proto.base = parser.documentHTMLToDocument(self.base);
}
// JS funcs
// --------
pub fn get_body(self: HTMLDocument) ?E.HTMLBodyElement {
const body_dom = parser.documentHTMLBody(self.base);
return E.HTMLBodyElement.init(body_dom);
}
pub fn _getElementById(self: HTMLDocument, id: []u8) ?E.HTMLElement {
const body_dom = parser.documentHTMLBody(self.base);
if (self.proto.getElementById(body_dom, id)) |elem| {
return E.HTMLElement.init(elem.base);
}
return null;
}
pub fn _createElement(self: HTMLDocument, tag_name: []const u8) E.HTMLElements {
const base = parser.documentCreateElement(self.proto.base.?, tag_name);
// TODO: order by probability instead of alphabetically
// TODO: this does not seems very efficient, do we have a better way?
if (std.mem.eql(u8, tag_name, "a")) {
return .{ .anchor = E.HTMLAnchorElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "area")) {
return .{ .area = E.HTMLAreaElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "audio")) {
return .{ .audio = E.HTMLAudioElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "br")) {
return .{ .br = E.HTMLBRElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "base")) {
return .{ .base = E.HTMLBaseElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "body")) {
return .{ .body = E.HTMLBodyElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "button")) {
return .{ .button = E.HTMLButtonElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "canvas")) {
return .{ .canvas = E.HTMLCanvasElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "dl")) {
return .{ .dlist = E.HTMLDListElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "dialog")) {
return .{ .dialog = E.HTMLDialogElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "data")) {
return .{ .data = E.HTMLDataElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "div")) {
return .{ .div = E.HTMLDivElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "embed")) {
return .{ .embed = E.HTMLEmbedElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "fieldset")) {
return .{ .fieldset = E.HTMLFieldSetElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "form")) {
return .{ .form = E.HTMLFormElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "frameset")) {
return .{ .frameset = E.HTMLFrameSetElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "hr")) {
return .{ .hr = E.HTMLHRElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "head")) {
return .{ .head = E.HTMLHeadElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "h1")) {
return .{ .heading = E.HTMLHeadingElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "h2")) {
return .{ .heading = E.HTMLHeadingElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "h3")) {
return .{ .heading = E.HTMLHeadingElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "h4")) {
return .{ .heading = E.HTMLHeadingElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "h5")) {
return .{ .heading = E.HTMLHeadingElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "h6")) {
return .{ .heading = E.HTMLHeadingElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "html")) {
return .{ .html = E.HTMLHtmlElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "iframe")) {
return .{ .iframe = E.HTMLIFrameElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "img")) {
return .{ .img = E.HTMLImageElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "input")) {
return .{ .input = E.HTMLInputElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "li")) {
return .{ .li = E.HTMLLIElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "label")) {
return .{ .label = E.HTMLLabelElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "legend")) {
return .{ .legend = E.HTMLLegendElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "link")) {
return .{ .link = E.HTMLLinkElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "map")) {
return .{ .map = E.HTMLMapElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "meta")) {
return .{ .meta = E.HTMLMetaElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "meter")) {
return .{ .meter = E.HTMLMeterElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "ins")) {
return .{ .mod = E.HTMLModElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "del")) {
return .{ .mod = E.HTMLModElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "ol")) {
return .{ .olist = E.HTMLOListElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "object")) {
return .{ .object = E.HTMLObjectElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "optgroup")) {
return .{ .optgroup = E.HTMLOptGroupElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "option")) {
return .{ .option = E.HTMLOptionElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "output")) {
return .{ .output = E.HTMLOutputElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "p")) {
return .{ .paragraph = E.HTMLParagraphElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "picture")) {
return .{ .picture = E.HTMLPictureElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "pre")) {
return .{ .pre = E.HTMLPreElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "progress")) {
return .{ .progress = E.HTMLProgressElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "blockquote")) {
return .{ .quote = E.HTMLQuoteElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "q")) {
return .{ .quote = E.HTMLQuoteElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "script")) {
return .{ .script = E.HTMLScriptElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "select")) {
return .{ .select = E.HTMLSelectElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "source")) {
return .{ .source = E.HTMLSourceElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "span")) {
return .{ .span = E.HTMLSpanElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "style")) {
return .{ .style = E.HTMLStyleElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "table")) {
return .{ .table = E.HTMLTableElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "caption")) {
return .{ .tablecaption = E.HTMLTableCaptionElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "th")) {
return .{ .tablecell = E.HTMLTableCellElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "td")) {
return .{ .tablecell = E.HTMLTableCellElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "col")) {
return .{ .tablecol = E.HTMLTableColElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "tr")) {
return .{ .tablerow = E.HTMLTableRowElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "thead")) {
return .{ .tablesection = E.HTMLTableSectionElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "tbody")) {
return .{ .tablesection = E.HTMLTableSectionElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "tfoot")) {
return .{ .tablesection = E.HTMLTableSectionElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "template")) {
return .{ .template = E.HTMLTemplateElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "textarea")) {
return .{ .textarea = E.HTMLTextAreaElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "time")) {
return .{ .time = E.HTMLTimeElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "title")) {
return .{ .title = E.HTMLTitleElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "track")) {
return .{ .track = E.HTMLTrackElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "ul")) {
return .{ .ulist = E.HTMLUListElement.init(base) };
} else if (std.mem.eql(u8, tag_name, "video")) {
return .{ .video = E.HTMLVideoElement.init(base) };
}
return .{ .unknown = E.HTMLUnknownElement.init(base) };
}
};
// Tests
// -----
fn upper(comptime name: []const u8, comptime indexes: anytype) []u8 {
// indexes is [_]comptime_int
comptime {
var upper_name: [name.len]u8 = undefined;
for (name) |char, i| {
var toUpper = false;
for (indexes) |index| {
if (index == i) {
toUpper = true;
break;
}
}
if (toUpper) {
upper_name[i] = std.ascii.toUpper(char);
} else {
upper_name[i] = char;
}
}
return &upper_name;
}
}
// fn allUpper(comptime name: []const u8) []u8 {
// comptime {
// var upper_name: [name.len]u8 = undefined;
// for (name) |char, i| {
// upper_name[i] = std.ascii.toUpper(char);
// }
// return &upper_name;
// }
// }
pub fn testExecFn(
alloc: std.mem.Allocator,
js_env: *jsruntime.Env,
comptime _: []jsruntime.API,
) !void {
var constructor = [_]Case{
.{ .src = "document.__proto__.constructor.name", .ex = "HTMLDocument" },
.{ .src = "document.__proto__.__proto__.constructor.name", .ex = "Document" },
.{ .src = "document.__proto__.__proto__.__proto__.constructor.name", .ex = "Node" },
.{ .src = "document.__proto__.__proto__.__proto__.__proto__.constructor.name", .ex = "EventTarget" },
};
try checkCases(js_env, &constructor);
var getElementById = [_]Case{
.{ .src = "let getElementById = document.getElementById('content')", .ex = "undefined" },
.{ .src = "getElementById.constructor.name", .ex = "HTMLElement" },
.{ .src = "getElementById.localName", .ex = "main" },
};
try checkCases(js_env, &getElementById);
comptime var htmlElements = [_][]const u8{
"a", // Anchor
"area",
"audio",
"br", // BR
"base",
"body",
"button",
"canvas",
"dl", // DList
"dialog",
"data",
"div",
"embed",
"fieldset", // FieldSet
"form",
"frameset", // FrameSet
"hr", // HR
"head",
"h1", // Heading
"h2", // Heading
"h3", // Heading
"h4", // Heading
"h5", // Heading
"h6", // Heading
"html",
"iframe", // IFrame
"img", // Image
"input",
"li", // LI
"label",
"legend",
"link",
"map",
"meta",
"meter",
"ins", // Mod
"del", // Mod
"ol", // OList
"object",
"optgroup", // OptGroup
"option",
"output",
"p", // Paragraph
"picture",
"pre",
"progress",
"blockquote", // Quote
"q", // Quote
"script",
"select",
"source",
"span",
"style",
"table",
"caption", // TableCaption
"th", // TableCell
"td", // TableCell
"col", // TableCol
"tr", // TableRow
"thead", // TableSection
"tbody", // TableSection
"tfoot", // TableSection
"template",
"textarea", // TextArea
"time",
"title",
"track",
"ul", // UList
"video",
};
var createElement: [htmlElements.len * 3]Case = undefined;
inline for (htmlElements) |elem, i| {
var upperName: []const u8 = undefined;
if (std.mem.eql(u8, elem, "a")) {
upperName = "Anchor";
} else if (std.mem.eql(u8, elem, "dl")) {
upperName = "DList";
} else if (std.mem.eql(u8, elem, "fieldset")) {
upperName = "FieldSet";
} else if (std.mem.eql(u8, elem, "frameset")) {
upperName = "FrameSet";
} else if (std.mem.eql(u8, elem, "h1") or
std.mem.eql(u8, elem, "h2") or
std.mem.eql(u8, elem, "h3") or
std.mem.eql(u8, elem, "h4") or
std.mem.eql(u8, elem, "h5") or
std.mem.eql(u8, elem, "h6"))
{
upperName = "Heading";
} else if (std.mem.eql(u8, elem, "iframe")) {
upperName = "IFrame";
} else if (std.mem.eql(u8, elem, "img")) {
upperName = "Image";
} else if (std.mem.eql(u8, elem, "del") or std.mem.eql(u8, elem, "ins")) {
upperName = "Mod";
} else if (std.mem.eql(u8, elem, "ol")) {
upperName = "OList";
} else if (std.mem.eql(u8, elem, "optgroup")) {
upperName = "OptGroup";
} else if (std.mem.eql(u8, elem, "p")) {
upperName = "Paragraph";
} else if (std.mem.eql(u8, elem, "blockquote") or std.mem.eql(u8, elem, "q")) {
upperName = "Quote";
} else if (std.mem.eql(u8, elem, "caption")) {
upperName = "TableCaption";
} else if (std.mem.eql(u8, elem, "th") or std.mem.eql(u8, elem, "td")) {
upperName = "TableCell";
} else if (std.mem.eql(u8, elem, "col")) {
upperName = "TableCol";
} else if (std.mem.eql(u8, elem, "tr")) {
upperName = "TableRow";
} else if (std.mem.eql(u8, elem, "thead") or
std.mem.eql(u8, elem, "tbody") or
std.mem.eql(u8, elem, "tfoot"))
{
upperName = "TableSection";
} else if (std.mem.eql(u8, elem, "textarea")) {
upperName = "TextArea";
} else if (std.mem.eql(u8, elem, "ul")) {
upperName = "UList";
} else {
if (elem.len == 2) {
upperName = upper(elem, [_]comptime_int{ 0, 1 });
} else {
upperName = upper(elem, [_]comptime_int{0});
}
}
createElement[i * 3] = Case{
.src = try std.fmt.allocPrint(alloc, "var {s}Elem = document.createElement('{s}')", .{ elem, elem }),
.ex = "undefined",
};
createElement[(i * 3) + 1] = Case{
.src = try std.fmt.allocPrint(alloc, "{s}Elem.constructor.name", .{elem}),
.ex = try std.fmt.allocPrint(alloc, "HTML{s}Element", .{upperName}),
};
createElement[(i * 3) + 2] = Case{
.src = try std.fmt.allocPrint(alloc, "{s}Elem.localName", .{elem}),
.ex = elem,
};
}
try checkCases(js_env, &createElement);
var unknown = [_]Case{
.{ .src = "let unknown = document.createElement('unknown')", .ex = "undefined" },
.{ .src = "unknown.constructor.name", .ex = "HTMLUnknownElement" },
};
try checkCases(js_env, &unknown);
}

763
src/html/elements.zig Normal file
View File

@@ -0,0 +1,763 @@
const parser = @import("../parser.zig");
const Element = @import("../dom/element.zig").Element;
// Abstract class
// --------------
pub const HTMLElement = struct {
proto: Element,
pub const prototype = *Element;
pub fn init(elem_base: *parser.Element) HTMLElement {
return .{ .proto = Element.init(elem_base) };
}
};
const HTMLElementsTags = enum {
unknown,
anchor,
area,
audio,
br,
base,
body,
button,
canvas,
dlist,
dialog,
data,
div,
embed,
fieldset,
form,
frameset,
hr,
head,
heading,
html,
iframe,
img,
input,
li,
label,
legend,
link,
map,
meta,
meter,
mod,
olist,
object,
optgroup,
option,
output,
paragraph,
picture,
pre,
progress,
quote,
script,
select,
source,
span,
style,
table,
tablecaption,
tablecell,
tablecol,
tablerow,
tablesection,
template,
textarea,
time,
title,
track,
ulist,
video,
};
// TODO: generate comptime?
pub const HTMLElements = union(HTMLElementsTags) {
unknown: HTMLUnknownElement,
anchor: HTMLAnchorElement,
area: HTMLAreaElement,
audio: HTMLAudioElement,
br: HTMLBRElement,
base: HTMLBaseElement,
body: HTMLBodyElement,
button: HTMLButtonElement,
canvas: HTMLCanvasElement,
dlist: HTMLDListElement,
dialog: HTMLDialogElement,
data: HTMLDataElement,
div: HTMLDivElement,
embed: HTMLEmbedElement,
fieldset: HTMLFieldSetElement,
form: HTMLFormElement,
frameset: HTMLFrameSetElement,
hr: HTMLHRElement,
head: HTMLHeadElement,
heading: HTMLHeadingElement,
html: HTMLHtmlElement,
iframe: HTMLIFrameElement,
img: HTMLImageElement,
input: HTMLInputElement,
li: HTMLLIElement,
label: HTMLLabelElement,
legend: HTMLLegendElement,
link: HTMLLinkElement,
map: HTMLMapElement,
meta: HTMLMetaElement,
meter: HTMLMeterElement,
mod: HTMLModElement,
olist: HTMLOListElement,
object: HTMLObjectElement,
optgroup: HTMLOptGroupElement,
option: HTMLOptionElement,
output: HTMLOutputElement,
paragraph: HTMLParagraphElement,
picture: HTMLPictureElement,
pre: HTMLPreElement,
progress: HTMLProgressElement,
quote: HTMLQuoteElement,
script: HTMLScriptElement,
select: HTMLSelectElement,
source: HTMLSourceElement,
span: HTMLSpanElement,
style: HTMLStyleElement,
table: HTMLTableElement,
tablecaption: HTMLTableCaptionElement,
tablecell: HTMLTableCellElement,
tablecol: HTMLTableColElement,
tablerow: HTMLTableRowElement,
tablesection: HTMLTableSectionElement,
template: HTMLTemplateElement,
textarea: HTMLTextAreaElement,
time: HTMLTimeElement,
title: HTMLTitleElement,
track: HTMLTrackElement,
ulist: HTMLUListElement,
video: HTMLVideoElement,
};
// Deprecated HTMLElements in Chrome (2023/03/15)
// HTMLContentelement
// HTMLShadowElement
// Abstract sub-classes
// --------------------
pub const HTMLMediaElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLMediaElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
// HTML elements
// -------------
pub const HTMLUnknownElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLUnknownElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLAnchorElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLAnchorElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLAreaElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLAreaElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLAudioElement = struct {
proto: HTMLMediaElement,
pub const prototype = *HTMLMediaElement;
pub fn init(elem_base: *parser.Element) HTMLAudioElement {
return .{ .proto = HTMLMediaElement.init(elem_base) };
}
};
pub const HTMLBRElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLBRElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLBaseElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLBaseElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLBodyElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLBodyElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLButtonElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLButtonElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLCanvasElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLCanvasElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLDListElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLDListElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLDialogElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLDialogElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLDataElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLDataElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLDivElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLDivElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLEmbedElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLEmbedElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLFieldSetElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLFieldSetElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLFormElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLFormElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLFrameSetElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLFrameSetElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLHRElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLHRElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLHeadElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLHeadElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLHeadingElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLHeadingElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLHtmlElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLHtmlElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLIFrameElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLIFrameElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLImageElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLImageElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLInputElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLInputElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLLIElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLLIElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLLabelElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLLabelElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLLegendElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLLegendElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLLinkElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLLinkElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLMapElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLMapElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLMetaElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLMetaElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLMeterElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLMeterElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLModElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLModElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLOListElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLOListElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLObjectElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLObjectElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLOptGroupElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLOptGroupElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLOptionElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLOptionElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLOutputElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLOutputElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLParagraphElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLParagraphElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLPictureElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLPictureElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLPreElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLPreElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLProgressElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLProgressElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLQuoteElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLQuoteElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLScriptElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLScriptElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLSelectElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLSelectElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLSourceElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLSourceElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLSpanElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLSpanElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLStyleElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLStyleElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLTableElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLTableElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLTableCaptionElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLTableCaptionElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLTableCellElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLTableCellElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLTableColElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLTableColElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLTableRowElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLTableRowElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLTableSectionElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLTableSectionElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLTemplateElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLTemplateElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLTextAreaElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLTextAreaElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLTimeElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLTimeElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLTitleElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLTitleElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLTrackElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLTrackElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLUListElement = struct {
proto: HTMLElement,
pub const prototype = *HTMLElement;
pub fn init(elem_base: *parser.Element) HTMLUListElement {
return .{ .proto = HTMLElement.init(elem_base) };
}
};
pub const HTMLVideoElement = struct {
proto: HTMLMediaElement,
pub const prototype = *HTMLMediaElement;
pub fn init(elem_base: *parser.Element) HTMLVideoElement {
return .{ .proto = HTMLMediaElement.init(elem_base) };
}
};

View File

@@ -4,7 +4,7 @@ const jsruntime = @import("jsruntime");
const DOM = @import("dom.zig");
const html = @import("html.zig").html;
const html = @import("html_test.zig").html;
const socket_path = "/tmp/browsercore-server.sock";

View File

@@ -5,7 +5,7 @@ const Console = @import("jsruntime").Console;
const DOM = @import("dom.zig");
const html = @import("html.zig").html;
const html = @import("html_test.zig").html;
var doc: DOM.HTMLDocument = undefined;

View File

@@ -32,22 +32,22 @@ pub const NodeType = enum(u4) {
last_entry,
};
pub fn nodeEventTarget(node: *Node) *EventTarget {
pub inline fn nodeEventTarget(node: *Node) *EventTarget {
return c.lxb_dom_interface_event_target(node);
}
pub const nodeWalker = (fn (node: ?*Node, _: ?*anyopaque) callconv(.C) Action);
pub fn nodeName(node: *Node) [*c]const u8 {
pub inline fn nodeName(node: *Node) [*c]const u8 {
var s: usize = undefined;
return c.lxb_dom_node_name(node, &s);
}
pub fn nodeType(node: *Node) NodeType {
pub inline fn nodeType(node: *Node) NodeType {
return @intToEnum(NodeType, node.*.type);
}
pub fn nodeWalk(node: *Node, comptime walker: nodeWalker) !void {
pub inline fn nodeWalk(node: *Node, comptime walker: nodeWalker) !void {
c.lxb_dom_node_simple_walk(node, walker, null);
}
@@ -55,16 +55,17 @@ pub fn nodeWalk(node: *Node, comptime walker: nodeWalker) !void {
pub const Element = c.lxb_dom_element_t;
pub fn elementNode(element: *Element) *Node {
pub inline fn elementNode(element: *Element) *Node {
return c.lxb_dom_interface_node(element);
}
pub fn elementLocalName(element: *Element) []const u8 {
const local_name = c.lxb_dom_element_local_name(element, null);
pub inline fn elementLocalName(element: *Element) []const u8 {
var size: usize = undefined;
const local_name = c.lxb_dom_element_local_name(element, &size);
return std.mem.sliceTo(local_name, 0);
}
pub fn elementsByAttr(
pub inline fn elementsByAttr(
element: *Element,
collection: *Collection,
attr: []const u8,
@@ -89,30 +90,30 @@ pub fn elementsByAttr(
pub const DocumentHTML = c.lxb_html_document_t;
pub fn documentHTMLInit() *DocumentHTML {
pub inline fn documentHTMLInit() *DocumentHTML {
return c.lxb_html_document_create();
}
pub fn documentHTMLDeinit(document_html: *DocumentHTML) void {
pub inline fn documentHTMLDeinit(document_html: *DocumentHTML) void {
_ = c.lxb_html_document_destroy(document_html);
}
pub fn documentHTMLParse(document_html: *DocumentHTML, html: []const u8) !void {
pub inline fn documentHTMLParse(document_html: *DocumentHTML, html: []const u8) !void {
const status = c.lxb_html_document_parse(document_html, html.ptr, html.len - 1);
if (status != 0) {
return error.DocumentHTMLParse;
}
}
pub fn documentHTMLToNode(document_html: *DocumentHTML) *Node {
pub inline fn documentHTMLToNode(document_html: *DocumentHTML) *Node {
return c.lxb_dom_interface_node(document_html);
}
pub fn documentHTMLToDocument(document_html: *DocumentHTML) *Document {
pub inline fn documentHTMLToDocument(document_html: *DocumentHTML) *Document {
return &document_html.dom_document;
}
pub fn documentHTMLBody(document_html: *DocumentHTML) *Element {
pub inline fn documentHTMLBody(document_html: *DocumentHTML) *Element {
return c.lxb_dom_interface_element(document_html.body);
}
@@ -120,19 +121,23 @@ pub fn documentHTMLBody(document_html: *DocumentHTML) *Element {
pub const Document = c.lxb_dom_document_t;
pub inline fn documentCreateElement(document: *Document, tag_name: []const u8) *Element {
return c.lxb_dom_document_create_element(document, tag_name.ptr, tag_name.len, null);
}
// Collection
pub const Collection = c.lxb_dom_collection_t;
pub fn collectionInit(document: *Document, size: usize) *Collection {
pub inline fn collectionInit(document: *Document, size: usize) *Collection {
return c.lxb_dom_collection_make(document, size);
}
pub fn collectionDeinit(collection: *Collection) void {
pub inline fn collectionDeinit(collection: *Collection) void {
_ = c.lxb_dom_collection_destroy(collection, true);
}
pub fn collectionElement(collection: *Collection, index: usize) *Element {
pub inline fn collectionElement(collection: *Collection, index: usize) *Element {
return c.lxb_dom_collection_element(collection, index);
}

View File

@@ -3,15 +3,14 @@ const std = @import("std");
const jsruntime = @import("jsruntime");
const DOM = @import("dom.zig");
const document = @import("dom/document.zig");
const element = @import("dom/element.zig");
const testExecFn = @import("html/document.zig").testExecFn;
const html = @import("html.zig").html;
const html_test = @import("html_test.zig").html;
var doc: DOM.HTMLDocument = undefined;
fn testsExecFn(
_: std.mem.Allocator,
alloc: std.mem.Allocator,
js_env: *jsruntime.Env,
comptime apis: []jsruntime.API,
) !void {
@@ -24,7 +23,7 @@ fn testsExecFn(
try js_env.addObject(apis, doc, "document");
// run tests
try document.testExecFn(js_env, apis);
try testExecFn(alloc, js_env, apis);
}
test {
@@ -34,7 +33,7 @@ test {
// document
doc = DOM.HTMLDocument.init();
defer doc.deinit();
try doc.parse(html);
try doc.parse(html_test);
// create JS vm
const vm = jsruntime.VM.init();