mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-28 22:53:28 +00:00
@@ -39,3 +39,5 @@ pub const Interfaces = generate.Tuple(.{
|
||||
Storage.Interfaces,
|
||||
URL.Interfaces,
|
||||
});
|
||||
|
||||
pub const UserContext = @import("user_context.zig").UserContext;
|
||||
|
||||
@@ -39,6 +39,9 @@ const storage = @import("../storage/storage.zig");
|
||||
|
||||
const FetchResult = std.http.Client.FetchResult;
|
||||
|
||||
const UserContext = @import("../user_context.zig").UserContext;
|
||||
const HttpClient = @import("../async/Client.zig");
|
||||
|
||||
const log = std.log.scoped(.browser);
|
||||
|
||||
// Browser is an instance of the browser.
|
||||
@@ -92,6 +95,7 @@ pub const Session = struct {
|
||||
// TODO move the shed to the browser?
|
||||
storageShed: storage.Shed,
|
||||
page: ?*Page = null,
|
||||
httpClient: HttpClient,
|
||||
|
||||
jstypes: [Types.len]usize = undefined,
|
||||
|
||||
@@ -105,9 +109,11 @@ pub const Session = struct {
|
||||
.loader = Loader.init(alloc),
|
||||
.loop = try Loop.init(alloc),
|
||||
.storageShed = storage.Shed.init(alloc),
|
||||
.httpClient = undefined,
|
||||
};
|
||||
|
||||
self.env = try Env.init(self.arena.allocator(), &self.loop);
|
||||
self.env = try Env.init(self.arena.allocator(), &self.loop, null);
|
||||
self.httpClient = .{ .allocator = alloc, .loop = &self.loop };
|
||||
try self.env.load(&self.jstypes);
|
||||
|
||||
return self;
|
||||
@@ -122,6 +128,7 @@ pub const Session = struct {
|
||||
self.loader.deinit();
|
||||
self.loop.deinit();
|
||||
self.storageShed.deinit();
|
||||
self.httpClient.deinit();
|
||||
self.alloc.destroy(self);
|
||||
}
|
||||
|
||||
@@ -289,6 +296,12 @@ pub const Page = struct {
|
||||
log.debug("start js env", .{});
|
||||
try self.session.env.start(alloc);
|
||||
|
||||
// replace the user context document with the new one.
|
||||
try self.session.env.setUserContext(.{
|
||||
.document = html_doc,
|
||||
.httpClient = &self.session.httpClient,
|
||||
});
|
||||
|
||||
// add global objects
|
||||
log.debug("setup global env", .{});
|
||||
try self.session.env.bindGlobal(&self.session.window);
|
||||
|
||||
@@ -15,13 +15,45 @@
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
const std = @import("std");
|
||||
|
||||
const parser = @import("../netsurf.zig");
|
||||
|
||||
const jsruntime = @import("jsruntime");
|
||||
const Case = jsruntime.test_utils.Case;
|
||||
const checkCases = jsruntime.test_utils.checkCases;
|
||||
|
||||
const CharacterData = @import("character_data.zig").CharacterData;
|
||||
|
||||
const UserContext = @import("../user_context.zig").UserContext;
|
||||
|
||||
// https://dom.spec.whatwg.org/#interface-comment
|
||||
pub const Comment = struct {
|
||||
pub const Self = parser.Comment;
|
||||
pub const prototype = *CharacterData;
|
||||
pub const mem_guarantied = true;
|
||||
|
||||
pub fn constructor(userctx: UserContext, data: ?[]const u8) !*parser.Comment {
|
||||
return parser.documentCreateComment(
|
||||
parser.documentHTMLToDocument(userctx.document),
|
||||
data orelse "",
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Tests
|
||||
// -----
|
||||
|
||||
pub fn testExecFn(
|
||||
_: std.mem.Allocator,
|
||||
js_env: *jsruntime.Env,
|
||||
) anyerror!void {
|
||||
var constructor = [_]Case{
|
||||
.{ .src = "let comment = new Comment('foo')", .ex = "undefined" },
|
||||
.{ .src = "comment.data", .ex = "foo" },
|
||||
|
||||
.{ .src = "let emptycomment = new Comment()", .ex = "undefined" },
|
||||
.{ .src = "emptycomment.data", .ex = "" },
|
||||
};
|
||||
try checkCases(js_env, &constructor);
|
||||
}
|
||||
|
||||
@@ -40,14 +40,26 @@ const DocumentType = @import("document_type.zig").DocumentType;
|
||||
const DocumentFragment = @import("document_fragment.zig").DocumentFragment;
|
||||
const DOMImplementation = @import("implementation.zig").DOMImplementation;
|
||||
|
||||
const UserContext = @import("../user_context.zig").UserContext;
|
||||
|
||||
// WEB IDL https://dom.spec.whatwg.org/#document
|
||||
pub const Document = struct {
|
||||
pub const Self = parser.Document;
|
||||
pub const prototype = *Node;
|
||||
pub const mem_guarantied = true;
|
||||
|
||||
pub fn constructor() !*parser.Document {
|
||||
return try parser.domImplementationCreateHTMLDocument(null);
|
||||
pub fn constructor(userctx: UserContext) !*parser.DocumentHTML {
|
||||
const doc = try parser.documentCreateDocument(
|
||||
try parser.documentHTMLGetTitle(userctx.document),
|
||||
);
|
||||
|
||||
// we have to work w/ document instead of html document.
|
||||
const ddoc = parser.documentHTMLToDocument(doc);
|
||||
const ccur = parser.documentHTMLToDocument(userctx.document);
|
||||
try parser.documentSetDocumentURI(ddoc, try parser.documentGetDocumentURI(ccur));
|
||||
try parser.documentSetInputEncoding(ddoc, try parser.documentGetInputEncoding(ccur));
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
// JS funcs
|
||||
@@ -262,6 +274,13 @@ pub fn testExecFn(
|
||||
.{ .src = "newdoc.children.length", .ex = "0" },
|
||||
.{ .src = "newdoc.getElementsByTagName('*').length", .ex = "0" },
|
||||
.{ .src = "newdoc.getElementsByTagName('*').item(0)", .ex = "null" },
|
||||
.{ .src = "newdoc.inputEncoding === document.inputEncoding", .ex = "true" },
|
||||
.{ .src = "newdoc.documentURI === document.documentURI", .ex = "true" },
|
||||
.{ .src = "newdoc.URL === document.URL", .ex = "true" },
|
||||
.{ .src = "newdoc.compatMode === document.compatMode", .ex = "true" },
|
||||
.{ .src = "newdoc.characterSet === document.characterSet", .ex = "true" },
|
||||
.{ .src = "newdoc.charset === document.charset", .ex = "true" },
|
||||
.{ .src = "newdoc.contentType === document.contentType", .ex = "true" },
|
||||
};
|
||||
try checkCases(js_env, &constructor);
|
||||
|
||||
|
||||
@@ -20,20 +20,37 @@ const std = @import("std");
|
||||
|
||||
const parser = @import("../netsurf.zig");
|
||||
|
||||
const jsruntime = @import("jsruntime");
|
||||
const Case = jsruntime.test_utils.Case;
|
||||
const checkCases = jsruntime.test_utils.checkCases;
|
||||
|
||||
const Node = @import("node.zig").Node;
|
||||
|
||||
const UserContext = @import("../user_context.zig").UserContext;
|
||||
|
||||
// WEB IDL https://dom.spec.whatwg.org/#documentfragment
|
||||
pub const DocumentFragment = struct {
|
||||
pub const Self = parser.DocumentFragment;
|
||||
pub const prototype = *Node;
|
||||
pub const mem_guarantied = true;
|
||||
|
||||
// TODO add constructor, but I need to associate the new DocumentFragment
|
||||
// with the current document global object...
|
||||
// > The new DocumentFragment() constructor steps are to set this’s node
|
||||
// > document to current global object’s associated Document.
|
||||
// https://dom.spec.whatwg.org/#dom-documentfragment-documentfragment
|
||||
pub fn constructor() !*parser.DocumentFragment {
|
||||
return error.NotImplemented;
|
||||
pub fn constructor(userctx: UserContext) !*parser.DocumentFragment {
|
||||
return parser.documentCreateDocumentFragment(
|
||||
parser.documentHTMLToDocument(userctx.document),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Tests
|
||||
// -----
|
||||
|
||||
pub fn testExecFn(
|
||||
_: std.mem.Allocator,
|
||||
js_env: *jsruntime.Env,
|
||||
) anyerror!void {
|
||||
var constructor = [_]Case{
|
||||
.{ .src = "const dc = new DocumentFragment()", .ex = "undefined" },
|
||||
.{ .src = "dc.constructor.name", .ex = "DocumentFragment" },
|
||||
};
|
||||
try checkCases(js_env, &constructor);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ pub const DOMImplementation = struct {
|
||||
return try parser.domImplementationCreateDocument(cnamespace, cqname, doctype);
|
||||
}
|
||||
|
||||
pub fn _createHTMLDocument(_: *DOMImplementation, title: ?[]const u8) !*parser.Document {
|
||||
pub fn _createHTMLDocument(_: *DOMImplementation, title: ?[]const u8) !*parser.DocumentHTML {
|
||||
return try parser.domImplementationCreateHTMLDocument(title);
|
||||
}
|
||||
|
||||
@@ -95,7 +95,8 @@ pub fn testExecFn(
|
||||
) anyerror!void {
|
||||
var getImplementation = [_]Case{
|
||||
.{ .src = "let impl = document.implementation", .ex = "undefined" },
|
||||
.{ .src = "impl.createHTMLDocument();", .ex = "[object Document]" },
|
||||
.{ .src = "impl.createHTMLDocument();", .ex = "[object HTMLDocument]" },
|
||||
.{ .src = "impl.createHTMLDocument('foo');", .ex = "[object HTMLDocument]" },
|
||||
.{ .src = "impl.createDocument(null, 'foo');", .ex = "[object Document]" },
|
||||
.{ .src = "impl.createDocumentType('foo', 'bar', 'baz')", .ex = "[object DocumentType]" },
|
||||
.{ .src = "impl.hasFeature()", .ex = "true" },
|
||||
|
||||
@@ -277,14 +277,30 @@ pub const Node = struct {
|
||||
return try Node.toInterface(res);
|
||||
}
|
||||
|
||||
// Check if the hierarchy node tree constraints are respected.
|
||||
// For now, it checks only if new nodes are not self.
|
||||
// TODO implements the others contraints.
|
||||
// see https://dom.spec.whatwg.org/#concept-node-tree
|
||||
pub fn hierarchy(self: *parser.Node, nodes: ?Variadic(*parser.Node)) !bool {
|
||||
if (nodes == null) return true;
|
||||
if (nodes.?.slice.len == 0) return true;
|
||||
|
||||
for (nodes.?.slice) |node| if (self == node) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO according with https://dom.spec.whatwg.org/#parentnode, the
|
||||
// function must accept either node or string.
|
||||
// blocked by https://github.com/lightpanda-io/jsruntime-lib/issues/114
|
||||
pub fn prepend(self: *parser.Node, nodes: ?Variadic(*parser.Node)) !void {
|
||||
if (nodes == null) return;
|
||||
if (nodes.?.slice.len == 0) return;
|
||||
const first = try parser.nodeFirstChild(self);
|
||||
|
||||
// check hierarchy
|
||||
if (!try hierarchy(self, nodes)) return parser.DOMError.HierarchyRequest;
|
||||
|
||||
const first = try parser.nodeFirstChild(self);
|
||||
if (first == null) {
|
||||
for (nodes.?.slice) |node| {
|
||||
_ = try parser.nodeAppendChild(self, node);
|
||||
@@ -303,6 +319,10 @@ pub const Node = struct {
|
||||
pub fn append(self: *parser.Node, nodes: ?Variadic(*parser.Node)) !void {
|
||||
if (nodes == null) return;
|
||||
if (nodes.?.slice.len == 0) return;
|
||||
|
||||
// check hierarchy
|
||||
if (!try hierarchy(self, nodes)) return parser.DOMError.HierarchyRequest;
|
||||
|
||||
for (nodes.?.slice) |node| {
|
||||
_ = try parser.nodeAppendChild(self, node);
|
||||
}
|
||||
@@ -312,12 +332,15 @@ pub const Node = struct {
|
||||
// function must accept either node or string.
|
||||
// blocked by https://github.com/lightpanda-io/jsruntime-lib/issues/114
|
||||
pub fn replaceChildren(self: *parser.Node, nodes: ?Variadic(*parser.Node)) !void {
|
||||
// remove existing children
|
||||
try removeChildren(self);
|
||||
|
||||
if (nodes == null) return;
|
||||
if (nodes.?.slice.len == 0) return;
|
||||
|
||||
// check hierarchy
|
||||
if (!try hierarchy(self, nodes)) return parser.DOMError.HierarchyRequest;
|
||||
|
||||
// remove existing children
|
||||
try removeChildren(self);
|
||||
|
||||
// add new children
|
||||
for (nodes.?.slice) |node| {
|
||||
_ = try parser.nodeAppendChild(self, node);
|
||||
|
||||
@@ -28,6 +28,8 @@ const parser = @import("../netsurf.zig");
|
||||
const CharacterData = @import("character_data.zig").CharacterData;
|
||||
const CDATASection = @import("cdata_section.zig").CDATASection;
|
||||
|
||||
const UserContext = @import("../user_context.zig").UserContext;
|
||||
|
||||
// Text interfaces
|
||||
pub const Interfaces = generate.Tuple(.{
|
||||
CDATASection,
|
||||
@@ -38,6 +40,13 @@ pub const Text = struct {
|
||||
pub const prototype = *CharacterData;
|
||||
pub const mem_guarantied = true;
|
||||
|
||||
pub fn constructor(userctx: UserContext, data: ?[]const u8) !*parser.Text {
|
||||
return parser.documentCreateTextNode(
|
||||
parser.documentHTMLToDocument(userctx.document),
|
||||
data orelse "",
|
||||
);
|
||||
}
|
||||
|
||||
// JS funcs
|
||||
// --------
|
||||
|
||||
@@ -62,6 +71,15 @@ pub fn testExecFn(
|
||||
_: std.mem.Allocator,
|
||||
js_env: *jsruntime.Env,
|
||||
) anyerror!void {
|
||||
var constructor = [_]Case{
|
||||
.{ .src = "let t = new Text('foo')", .ex = "undefined" },
|
||||
.{ .src = "t.data", .ex = "foo" },
|
||||
|
||||
.{ .src = "let emptyt = new Text()", .ex = "undefined" },
|
||||
.{ .src = "emptyt.data", .ex = "" },
|
||||
};
|
||||
try checkCases(js_env, &constructor);
|
||||
|
||||
var get_whole_text = [_]Case{
|
||||
.{ .src = "let text = document.getElementById('link').firstChild", .ex = "undefined" },
|
||||
.{ .src = "text.wholeText === 'OK'", .ex = "true" },
|
||||
|
||||
@@ -25,6 +25,7 @@ const apiweb = @import("apiweb.zig");
|
||||
const Window = @import("html/window.zig").Window;
|
||||
|
||||
pub const Types = jsruntime.reflect(apiweb.Interfaces);
|
||||
pub const UserContext = apiweb.UserContext;
|
||||
|
||||
const socket_path = "/tmp/browsercore-server.sock";
|
||||
|
||||
@@ -103,5 +104,5 @@ pub fn main() !void {
|
||||
try server.listen(addr);
|
||||
std.debug.print("Listening on: {s}...\n", .{socket_path});
|
||||
|
||||
try jsruntime.loadEnv(&arena, execJS);
|
||||
try jsruntime.loadEnv(&arena, null, execJS);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ const jsruntime = @import("jsruntime");
|
||||
const apiweb = @import("apiweb.zig");
|
||||
|
||||
pub const Types = jsruntime.reflect(apiweb.Interfaces);
|
||||
pub const UserContext = apiweb.UserContext;
|
||||
|
||||
pub const std_options = struct {
|
||||
pub const log_level = .debug;
|
||||
|
||||
@@ -28,6 +28,8 @@ const storage = @import("storage/storage.zig");
|
||||
const html_test = @import("html_test.zig").html;
|
||||
|
||||
pub const Types = jsruntime.reflect(apiweb.Interfaces);
|
||||
pub const UserContext = apiweb.UserContext;
|
||||
const Client = @import("async/Client.zig");
|
||||
|
||||
var doc: *parser.DocumentHTML = undefined;
|
||||
|
||||
@@ -39,6 +41,14 @@ fn execJS(
|
||||
try js_env.start(alloc);
|
||||
defer js_env.stop();
|
||||
|
||||
var cli = Client{ .allocator = alloc, .loop = js_env.nat_ctx.loop };
|
||||
defer cli.deinit();
|
||||
|
||||
try js_env.setUserContext(UserContext{
|
||||
.document = doc,
|
||||
.httpClient = &cli,
|
||||
});
|
||||
|
||||
var storageShelf = storage.Shelf.init(alloc);
|
||||
defer storageShelf.deinit();
|
||||
|
||||
|
||||
@@ -49,6 +49,7 @@ const Out = enum {
|
||||
|
||||
pub const Types = jsruntime.reflect(apiweb.Interfaces);
|
||||
pub const GlobalType = apiweb.GlobalType;
|
||||
pub const UserContext = apiweb.UserContext;
|
||||
|
||||
// TODO For now the WPT tests run is specific to WPT.
|
||||
// It manually load js framwork libs, and run the first script w/ js content in
|
||||
|
||||
@@ -1763,21 +1763,29 @@ pub inline fn domImplementationCreateDocumentType(
|
||||
return dt.?;
|
||||
}
|
||||
|
||||
pub inline fn domImplementationCreateHTMLDocument(title: ?[]const u8) !*Document {
|
||||
var doc: ?*Document = undefined;
|
||||
const err = c.dom_implementation_create_document(
|
||||
c.DOM_IMPLEMENTATION_HTML,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
&doc,
|
||||
);
|
||||
try DOMErr(err);
|
||||
// TODO set title
|
||||
_ = title;
|
||||
return doc.?;
|
||||
pub inline fn domImplementationCreateHTMLDocument(title: ?[]const u8) !*DocumentHTML {
|
||||
const doc_html = try documentCreateDocument(title);
|
||||
const doc = documentHTMLToDocument(doc_html);
|
||||
|
||||
// add hierarchy: html, head, body.
|
||||
const html = try documentCreateElement(doc, "html");
|
||||
_ = try nodeAppendChild(documentToNode(doc), elementToNode(html));
|
||||
|
||||
const head = try documentCreateElement(doc, "head");
|
||||
_ = try nodeAppendChild(elementToNode(html), elementToNode(head));
|
||||
|
||||
if (title) |t| {
|
||||
try documentHTMLSetTitle(doc_html, t);
|
||||
const htitle = try documentCreateElement(doc, "title");
|
||||
const txt = try documentCreateTextNode(doc, t);
|
||||
_ = try nodeAppendChild(elementToNode(htitle), @as(*Node, @ptrCast(txt)));
|
||||
_ = try nodeAppendChild(elementToNode(head), elementToNode(htitle));
|
||||
}
|
||||
|
||||
const body = try documentCreateElement(doc, "body");
|
||||
_ = try nodeAppendChild(elementToNode(html), elementToNode(body));
|
||||
|
||||
return doc_html;
|
||||
}
|
||||
|
||||
// Document
|
||||
@@ -1833,6 +1841,28 @@ pub inline fn documentGetInputEncoding(doc: *Document) ![]const u8 {
|
||||
return strToData(s.?);
|
||||
}
|
||||
|
||||
pub inline fn documentSetInputEncoding(doc: *Document, enc: []const u8) !void {
|
||||
const err = documentVtable(doc).dom_document_set_input_encoding.?(doc, try strFromData(enc));
|
||||
try DOMErr(err);
|
||||
}
|
||||
|
||||
pub inline fn documentCreateDocument(title: ?[]const u8) !*DocumentHTML {
|
||||
var doc: ?*Document = undefined;
|
||||
const err = c.dom_implementation_create_document(
|
||||
c.DOM_IMPLEMENTATION_HTML,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
&doc,
|
||||
);
|
||||
try DOMErr(err);
|
||||
const doc_html = @as(*DocumentHTML, @ptrCast(doc.?));
|
||||
if (title) |t| try documentHTMLSetTitle(doc_html, t);
|
||||
return doc_html;
|
||||
}
|
||||
|
||||
pub inline fn documentCreateElement(doc: *Document, tag_name: []const u8) !*Element {
|
||||
var elem: ?*Element = undefined;
|
||||
const err = documentVtable(doc).dom_document_create_element.?(doc, try strFromData(tag_name), &elem);
|
||||
|
||||
@@ -30,6 +30,7 @@ const xhr = @import("xhr/xhr.zig");
|
||||
const storage = @import("storage/storage.zig");
|
||||
const url = @import("url/url.zig");
|
||||
const urlquery = @import("url/query.zig");
|
||||
const Client = @import("async/Client.zig");
|
||||
|
||||
const documentTestExecFn = @import("dom/document.zig").testExecFn;
|
||||
const HTMLDocumentTestExecFn = @import("html/document.zig").testExecFn;
|
||||
@@ -46,6 +47,8 @@ const NodeListTestExecFn = @import("dom/nodelist.zig").testExecFn;
|
||||
const AttrTestExecFn = @import("dom/attribute.zig").testExecFn;
|
||||
const EventTargetTestExecFn = @import("dom/event_target.zig").testExecFn;
|
||||
const ProcessingInstructionTestExecFn = @import("dom/processing_instruction.zig").testExecFn;
|
||||
const CommentTestExecFn = @import("dom/comment.zig").testExecFn;
|
||||
const DocumentFragmentTestExecFn = @import("dom/document_fragment.zig").testExecFn;
|
||||
const EventTestExecFn = @import("events/event.zig").testExecFn;
|
||||
const XHRTestExecFn = xhr.testExecFn;
|
||||
const ProgressEventTestExecFn = @import("xhr/progress_event.zig").testExecFn;
|
||||
@@ -54,6 +57,7 @@ const URLTestExecFn = url.testExecFn;
|
||||
const HTMLElementTestExecFn = @import("html/elements.zig").testExecFn;
|
||||
|
||||
pub const Types = jsruntime.reflect(apiweb.Interfaces);
|
||||
pub const UserContext = @import("user_context.zig").UserContext;
|
||||
|
||||
var doc: *parser.DocumentHTML = undefined;
|
||||
|
||||
@@ -81,6 +85,14 @@ fn testExecFn(
|
||||
std.debug.print("documentHTMLClose error: {s}\n", .{@errorName(err)});
|
||||
};
|
||||
|
||||
var cli = Client{ .allocator = alloc, .loop = js_env.nat_ctx.loop };
|
||||
defer cli.deinit();
|
||||
|
||||
try js_env.setUserContext(.{
|
||||
.document = doc,
|
||||
.httpClient = &cli,
|
||||
});
|
||||
|
||||
// alias global as self and window
|
||||
var window = Window.create(null);
|
||||
|
||||
@@ -111,6 +123,8 @@ fn testsAllExecFn(
|
||||
DOMTokenListExecFn,
|
||||
NodeListTestExecFn,
|
||||
AttrTestExecFn,
|
||||
CommentTestExecFn,
|
||||
DocumentFragmentTestExecFn,
|
||||
EventTargetTestExecFn,
|
||||
EventTestExecFn,
|
||||
XHRTestExecFn,
|
||||
@@ -315,7 +329,7 @@ fn testJSRuntime(alloc: std.mem.Allocator) !void {
|
||||
var arena_alloc = std.heap.ArenaAllocator.init(alloc);
|
||||
defer arena_alloc.deinit();
|
||||
|
||||
try jsruntime.loadEnv(&arena_alloc, testsAllExecFn);
|
||||
try jsruntime.loadEnv(&arena_alloc, null, testsAllExecFn);
|
||||
}
|
||||
|
||||
test "DocumentHTMLParseFromStr" {
|
||||
|
||||
@@ -21,6 +21,7 @@ const std = @import("std");
|
||||
const tests = @import("run_tests.zig");
|
||||
|
||||
pub const Types = tests.Types;
|
||||
pub const UserContext = tests.UserContext;
|
||||
|
||||
pub fn main() !void {
|
||||
try tests.main();
|
||||
|
||||
8
src/user_context.zig
Normal file
8
src/user_context.zig
Normal file
@@ -0,0 +1,8 @@
|
||||
const std = @import("std");
|
||||
const parser = @import("netsurf.zig");
|
||||
const Client = @import("async/Client.zig");
|
||||
|
||||
pub const UserContext = struct {
|
||||
document: *parser.DocumentHTML,
|
||||
httpClient: *Client,
|
||||
};
|
||||
@@ -30,6 +30,8 @@ const Window = @import("../html/window.zig").Window;
|
||||
const storage = @import("../storage/storage.zig");
|
||||
|
||||
const Types = @import("../main_wpt.zig").Types;
|
||||
const UserContext = @import("../main_wpt.zig").UserContext;
|
||||
const Client = @import("../async/Client.zig");
|
||||
|
||||
// runWPT parses the given HTML file, starts a js env and run the first script
|
||||
// tags containing javascript sources.
|
||||
@@ -50,7 +52,14 @@ pub fn run(arena: *std.heap.ArenaAllocator, comptime dir: []const u8, f: []const
|
||||
// create JS env
|
||||
var loop = try Loop.init(alloc);
|
||||
defer loop.deinit();
|
||||
var js_env = try Env.init(alloc, &loop);
|
||||
|
||||
var cli = Client{ .allocator = alloc, .loop = &loop };
|
||||
defer cli.deinit();
|
||||
|
||||
var js_env = try Env.init(alloc, &loop, UserContext{
|
||||
.document = html_doc,
|
||||
.httpClient = &cli,
|
||||
});
|
||||
defer js_env.deinit();
|
||||
|
||||
var storageShelf = storage.Shelf.init(alloc);
|
||||
|
||||
@@ -37,6 +37,8 @@ const Client = @import("../async/Client.zig");
|
||||
|
||||
const parser = @import("../netsurf.zig");
|
||||
|
||||
const UserContext = @import("../user_context.zig").UserContext;
|
||||
|
||||
const log = std.log.scoped(.xhr);
|
||||
|
||||
// XHR interfaces
|
||||
@@ -149,7 +151,7 @@ pub const XMLHttpRequest = struct {
|
||||
|
||||
proto: XMLHttpRequestEventTarget = XMLHttpRequestEventTarget{},
|
||||
alloc: std.mem.Allocator,
|
||||
cli: Client,
|
||||
cli: *Client,
|
||||
impl: YieldImpl,
|
||||
|
||||
priv_state: PrivState = .new,
|
||||
@@ -185,7 +187,7 @@ pub const XMLHttpRequest = struct {
|
||||
|
||||
const min_delay: u64 = 50000000; // 50ms
|
||||
|
||||
pub fn constructor(alloc: std.mem.Allocator, loop: *Loop) !XMLHttpRequest {
|
||||
pub fn constructor(alloc: std.mem.Allocator, loop: *Loop, userctx: UserContext) !XMLHttpRequest {
|
||||
return .{
|
||||
.alloc = alloc,
|
||||
.headers = .{ .allocator = alloc, .owned = true },
|
||||
@@ -195,8 +197,7 @@ pub const XMLHttpRequest = struct {
|
||||
.url = null,
|
||||
.uri = undefined,
|
||||
.state = UNSENT,
|
||||
// TODO retrieve the HTTP client globally to reuse existing connections.
|
||||
.cli = .{ .allocator = alloc, .loop = loop },
|
||||
.cli = userctx.httpClient,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -235,9 +236,6 @@ pub const XMLHttpRequest = struct {
|
||||
self.response_headers.deinit();
|
||||
|
||||
self.proto.deinit(alloc);
|
||||
|
||||
// TODO the client must be shared between requests.
|
||||
self.cli.deinit();
|
||||
}
|
||||
|
||||
pub fn get_readyState(self: *XMLHttpRequest) u16 {
|
||||
|
||||
2
vendor/zig-js-runtime
vendored
2
vendor/zig-js-runtime
vendored
Submodule vendor/zig-js-runtime updated: fff1a6778d...d4a2eaefd8
Reference in New Issue
Block a user