mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 15:13:28 +00:00
get fetch campire working
This commit is contained in:
@@ -2,10 +2,14 @@ const std = @import("std");
|
|||||||
const Node = @import("webapi/Node.zig");
|
const Node = @import("webapi/Node.zig");
|
||||||
|
|
||||||
pub const Opts = struct {
|
pub const Opts = struct {
|
||||||
|
// @ZIGDOM (none of these do anything)
|
||||||
|
with_base: bool = false,
|
||||||
strip_mode: StripMode = .{},
|
strip_mode: StripMode = .{},
|
||||||
|
|
||||||
const StripMode = struct {
|
pub const StripMode = struct {
|
||||||
// @ZIGDOM
|
js: bool = false,
|
||||||
|
ui: bool = false,
|
||||||
|
css: bool = false,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -387,7 +387,6 @@ pub fn throw(self: *Context, err: []const u8) js.Exception {
|
|||||||
pub fn zigValueToJs(self: *Context, value: anytype, comptime opts: Caller.CallOpts) !v8.Value {
|
pub fn zigValueToJs(self: *Context, value: anytype, comptime opts: Caller.CallOpts) !v8.Value {
|
||||||
const isolate = self.isolate;
|
const isolate = self.isolate;
|
||||||
|
|
||||||
|
|
||||||
// Check if it's a "simple" type. This is extracted so that it can be
|
// Check if it's a "simple" type. This is extracted so that it can be
|
||||||
// reused by other parts of the code. "simple" types only require an
|
// reused by other parts of the code. "simple" types only require an
|
||||||
// isolate to create (specifically, they don't our templates array)
|
// isolate to create (specifically, they don't our templates array)
|
||||||
@@ -595,7 +594,6 @@ pub fn mapZigInstanceToJs(self: *Context, js_obj_: ?v8.Object, value: anytype) !
|
|||||||
};
|
};
|
||||||
const JsApi = bridge.Struct(ptr.child).JsApi;
|
const JsApi = bridge.Struct(ptr.child).JsApi;
|
||||||
|
|
||||||
|
|
||||||
// The TAO contains the pointer to our Zig instance as
|
// The TAO contains the pointer to our Zig instance as
|
||||||
// well as any meta data we'll need to use it later.
|
// well as any meta data we'll need to use it later.
|
||||||
// See the TaggedAnyOpaque struct for more details.
|
// See the TaggedAnyOpaque struct for more details.
|
||||||
|
|||||||
@@ -311,7 +311,6 @@ fn generateConstructor(comptime JsApi: type, isolate: v8.Isolate) v8.FunctionTem
|
|||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ZIGDOM (HTMLAllCollection I think)
|
// ZIGDOM (HTMLAllCollection I think)
|
||||||
// fn generateUndetectable(comptime Struct: type, template: v8.ObjectTemplate) void {
|
// fn generateUndetectable(comptime Struct: type, template: v8.ObjectTemplate) void {
|
||||||
// const has_js_call_as_function = @hasDecl(Struct, "jsCallAsFunction");
|
// const has_js_call_as_function = @hasDecl(Struct, "jsCallAsFunction");
|
||||||
|
|||||||
@@ -401,7 +401,6 @@ pub const SubType = enum {
|
|||||||
webassemblymemory,
|
webassemblymemory,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
pub const JsApis = flattenTypes(&.{
|
pub const JsApis = flattenTypes(&.{
|
||||||
@import("../webapi/AbortController.zig"),
|
@import("../webapi/AbortController.zig"),
|
||||||
@import("../webapi/AbortSignal.zig"),
|
@import("../webapi/AbortSignal.zig"),
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ pub const PersistentPromiseResolver = struct {
|
|||||||
|
|
||||||
pub fn resolve(self: PersistentPromiseResolver, value: anytype) !void {
|
pub fn resolve(self: PersistentPromiseResolver, value: anytype) !void {
|
||||||
const context = self.context;
|
const context = self.context;
|
||||||
const js_value = try context.zigValueToJs(value);
|
const js_value = try context.zigValueToJs(value, .{});
|
||||||
|
|
||||||
// resolver.resolve will return null if the promise isn't pending
|
// resolver.resolve will return null if the promise isn't pending
|
||||||
const ok = self.resolver.castToPromiseResolver().resolve(context.v8_context, js_value) orelse return;
|
const ok = self.resolver.castToPromiseResolver().resolve(context.v8_context, js_value) orelse return;
|
||||||
@@ -117,7 +117,7 @@ pub const PersistentPromiseResolver = struct {
|
|||||||
|
|
||||||
pub fn reject(self: PersistentPromiseResolver, value: anytype) !void {
|
pub fn reject(self: PersistentPromiseResolver, value: anytype) !void {
|
||||||
const context = self.context;
|
const context = self.context;
|
||||||
const js_value = try context.zigValueToJs(value);
|
const js_value = try context.zigValueToJs(value, .{});
|
||||||
|
|
||||||
// resolver.reject will return null if the promise isn't pending
|
// resolver.reject will return null if the promise isn't pending
|
||||||
const ok = self.resolver.castToPromiseResolver().reject(context.v8_context, js_value) orelse return;
|
const ok = self.resolver.castToPromiseResolver().reject(context.v8_context, js_value) orelse return;
|
||||||
|
|||||||
@@ -58,6 +58,10 @@ _parse_mode: enum { document, fragment },
|
|||||||
// even thoug we'll create very few (if any) actual *Attributes.
|
// even thoug we'll create very few (if any) actual *Attributes.
|
||||||
_attribute_lookup: std.AutoHashMapUnmanaged(usize, *Element.Attribute),
|
_attribute_lookup: std.AutoHashMapUnmanaged(usize, *Element.Attribute),
|
||||||
|
|
||||||
|
// Same as _atlribute_lookup, but instead of individual attributes, this is for
|
||||||
|
// the return of elements.attributes.
|
||||||
|
_attribute_named_node_map_lookup: std.AutoHashMapUnmanaged(usize, *Element.Attribute.NamedNodeMap),
|
||||||
|
|
||||||
_script_manager: ScriptManager,
|
_script_manager: ScriptManager,
|
||||||
|
|
||||||
_polyfill_loader: polyfill.Loader = .{},
|
_polyfill_loader: polyfill.Loader = .{},
|
||||||
@@ -119,6 +123,7 @@ pub fn deinit(self: *Page) void {
|
|||||||
log.debug(.page, "page.deinit", .{ .url = self.url });
|
log.debug(.page, "page.deinit", .{ .url = self.url });
|
||||||
}
|
}
|
||||||
self.js.deinit();
|
self.js.deinit();
|
||||||
|
self._script_manager.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset(self: *Page, comptime initializing: bool) !void {
|
fn reset(self: *Page, comptime initializing: bool) !void {
|
||||||
@@ -144,6 +149,7 @@ fn reset(self: *Page, comptime initializing: bool) !void {
|
|||||||
self._parse_state = .pre;
|
self._parse_state = .pre;
|
||||||
self._load_state = .parsing;
|
self._load_state = .parsing;
|
||||||
self._attribute_lookup = .empty;
|
self._attribute_lookup = .empty;
|
||||||
|
self._attribute_named_node_map_lookup = .empty;
|
||||||
self._event_manager = EventManager.init(self);
|
self._event_manager = EventManager.init(self);
|
||||||
|
|
||||||
self._script_manager = ScriptManager.init(self);
|
self._script_manager = ScriptManager.init(self);
|
||||||
@@ -165,7 +171,7 @@ fn registerBackgroundTasks(self: *Page) !void {
|
|||||||
const Browser = @import("Browser.zig");
|
const Browser = @import("Browser.zig");
|
||||||
|
|
||||||
try self.scheduler.add(self._session.browser, struct {
|
try self.scheduler.add(self._session.browser, struct {
|
||||||
fn runMicrotasks(ctx: *anyopaque) ?u32 {
|
fn runMicrotasks(ctx: *anyopaque) !?u32 {
|
||||||
const b: *Browser = @ptrCast(@alignCast(ctx));
|
const b: *Browser = @ptrCast(@alignCast(ctx));
|
||||||
b.runMicrotasks();
|
b.runMicrotasks();
|
||||||
return 5;
|
return 5;
|
||||||
@@ -173,7 +179,7 @@ fn registerBackgroundTasks(self: *Page) !void {
|
|||||||
}.runMicrotasks, 5, .{ .name = "page.microtasks" });
|
}.runMicrotasks, 5, .{ .name = "page.microtasks" });
|
||||||
|
|
||||||
try self.scheduler.add(self._session.browser, struct {
|
try self.scheduler.add(self._session.browser, struct {
|
||||||
fn runMessageLoop(ctx: *anyopaque) ?u32 {
|
fn runMessageLoop(ctx: *anyopaque) !?u32 {
|
||||||
const b: *Browser = @ptrCast(@alignCast(ctx));
|
const b: *Browser = @ptrCast(@alignCast(ctx));
|
||||||
b.runMessageLoop();
|
b.runMessageLoop();
|
||||||
return 100;
|
return 100;
|
||||||
@@ -992,7 +998,7 @@ fn populateElementAttributes(self: *Page, element: *Element, list: anytype) !voi
|
|||||||
if (@TypeOf(list) == ?*Element.Attribute.List) {
|
if (@TypeOf(list) == ?*Element.Attribute.List) {
|
||||||
// from cloneNode
|
// from cloneNode
|
||||||
|
|
||||||
var existing = list orelse return ;
|
var existing = list orelse return;
|
||||||
|
|
||||||
var attributes = try self.arena.create(Element.Attribute.List);
|
var attributes = try self.arena.create(Element.Attribute.List);
|
||||||
attributes.* = .{};
|
attributes.* = .{};
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
const firstScript = document.querySelector('script');
|
const firstScript = document.querySelector('script');
|
||||||
testing.expectEqual('SCRIPT', firstScript.tagName);
|
testing.expectEqual('SCRIPT', firstScript.tagName);
|
||||||
|
|
||||||
testing.expectEqual(null, document.querySelector('select'));
|
testing.expectEqual(null, document.querySelector('article'));
|
||||||
testing.expectEqual(null, document.querySelector('another'));
|
testing.expectEqual(null, document.querySelector('another'));
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ pub fn createTreeWalker(_: *const Document, root: *Node, what_to_show: ?u32, fil
|
|||||||
return DOMTreeWalker.init(root, show, filter, page);
|
return DOMTreeWalker.init(root, show, filter, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ZIGDOM what_to_show tristate (null vs undefined vs value)
|
// @ZIGDOM what_to_show tristate (null vs undefined vs value)
|
||||||
pub fn createNodeIterator(_: *const Document, root: *Node, what_to_show: ?u32, filter: ?DOMNodeIterator.FilterOpts, page: *Page) !*DOMNodeIterator {
|
pub fn createNodeIterator(_: *const Document, root: *Node, what_to_show: ?u32, filter: ?DOMNodeIterator.FilterOpts, page: *Page) !*DOMNodeIterator {
|
||||||
const show = what_to_show orelse NodeFilter.SHOW_ALL;
|
const show = what_to_show orelse NodeFilter.SHOW_ALL;
|
||||||
return DOMNodeIterator.init(root, show, filter, page);
|
return DOMNodeIterator.init(root, show, filter, page);
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ pub fn getTagNameLower(self: *const Element) []const u8 {
|
|||||||
.script => "script",
|
.script => "script",
|
||||||
.select => "select",
|
.select => "select",
|
||||||
.style => "style",
|
.style => "style",
|
||||||
.text_area => "textara",
|
.text_area => "textarea",
|
||||||
.title => "title",
|
.title => "title",
|
||||||
.ul => "ul",
|
.ul => "ul",
|
||||||
.unknown => |e| e._tag_name.str(),
|
.unknown => |e| e._tag_name.str(),
|
||||||
@@ -311,9 +311,14 @@ pub fn getAttributeNames(self: *const Element, page: *Page) ![][]const u8 {
|
|||||||
return attributes.getNames(page);
|
return attributes.getNames(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getAttributeNamedNodeMap(self: *Element) Attribute.NamedNodeMap {
|
pub fn getAttributeNamedNodeMap(self: *Element, page: *Page) !*Attribute.NamedNodeMap {
|
||||||
const attributes = self._attributes orelse return .{};
|
const gop = try page._attribute_named_node_map_lookup.getOrPut(page.arena, @intFromPtr(self));
|
||||||
return .{ ._list = attributes.*, ._element = self };
|
if (!gop.found_existing) {
|
||||||
|
const attributes = try self.getOrCreateAttributeList(page);
|
||||||
|
const named_node_map = try page._factory.create(Attribute.NamedNodeMap{ ._list = attributes, ._element = self });
|
||||||
|
gop.value_ptr.* = named_node_map;
|
||||||
|
}
|
||||||
|
return gop.value_ptr.*;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getStyle(self: *Element, page: *Page) !*CSSStyleProperties {
|
pub fn getStyle(self: *Element, page: *Page) !*CSSStyleProperties {
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ fn needsLowerCasing(name: []const u8) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const NamedNodeMap = struct {
|
pub const NamedNodeMap = struct {
|
||||||
_list: List = .{},
|
_list: *List,
|
||||||
|
|
||||||
// Whenever the NamedNodeMap creates an Attribute, it needs to provide the
|
// Whenever the NamedNodeMap creates an Attribute, it needs to provide the
|
||||||
// "ownerElement".
|
// "ownerElement".
|
||||||
@@ -418,6 +418,12 @@ pub const InnerIterator = struct {
|
|||||||
|
|
||||||
fn formatAttribute(name: []const u8, value: []const u8, writer: *std.Io.Writer) !void {
|
fn formatAttribute(name: []const u8, value: []const u8, writer: *std.Io.Writer) !void {
|
||||||
try writer.writeAll(name);
|
try writer.writeAll(name);
|
||||||
|
|
||||||
|
// Boolean attributes with empty values are serialized without a value
|
||||||
|
if (value.len == 0 and boolean_attributes_lookup.has(name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try writer.writeByte('=');
|
try writer.writeByte('=');
|
||||||
if (value.len == 0) {
|
if (value.len == 0) {
|
||||||
return writer.writeAll("\"\"");
|
return writer.writeAll("\"\"");
|
||||||
@@ -433,6 +439,37 @@ fn formatAttribute(name: []const u8, value: []const u8, writer: *std.Io.Writer)
|
|||||||
return writer.writeByte('"');
|
return writer.writeByte('"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const boolean_attributes = [_][]const u8{
|
||||||
|
"checked",
|
||||||
|
"disabled",
|
||||||
|
"required",
|
||||||
|
"readonly",
|
||||||
|
"multiple",
|
||||||
|
"selected",
|
||||||
|
"autofocus",
|
||||||
|
"autoplay",
|
||||||
|
"controls",
|
||||||
|
"loop",
|
||||||
|
"muted",
|
||||||
|
"hidden",
|
||||||
|
"async",
|
||||||
|
"defer",
|
||||||
|
"novalidate",
|
||||||
|
"formnovalidate",
|
||||||
|
"ismap",
|
||||||
|
"reversed",
|
||||||
|
"default",
|
||||||
|
"open",
|
||||||
|
};
|
||||||
|
|
||||||
|
const boolean_attributes_lookup = std.StaticStringMap(void).initComptime(blk: {
|
||||||
|
var entries: [boolean_attributes.len]struct { []const u8, void } = undefined;
|
||||||
|
for (boolean_attributes, 0..) |attr, i| {
|
||||||
|
entries[i] = .{ attr, {} };
|
||||||
|
}
|
||||||
|
break :blk entries;
|
||||||
|
});
|
||||||
|
|
||||||
fn writeEscapedAttributeValue(value: []const u8, first_offset: usize, writer: *std.Io.Writer) !void {
|
fn writeEscapedAttributeValue(value: []const u8, first_offset: usize, writer: *std.Io.Writer) !void {
|
||||||
// Write everything before the first special character
|
// Write everything before the first special character
|
||||||
try writer.writeAll(value[0..first_offset]);
|
try writer.writeAll(value[0..first_offset]);
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
|
const log = @import("../../../log.zig");
|
||||||
|
const Http = @import("../../../http/Http.zig");
|
||||||
|
|
||||||
const js = @import("../../js/js.zig");
|
const js = @import("../../js/js.zig");
|
||||||
const Page = @import("../../Page.zig");
|
const Page = @import("../../Page.zig");
|
||||||
|
|
||||||
@@ -8,15 +11,64 @@ const Response = @import("Response.zig");
|
|||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
_arena: Allocator,
|
const Fetch = @This();
|
||||||
_promise: js.Promise,
|
|
||||||
_has_response: bool,
|
_page: *Page,
|
||||||
|
_response: std.ArrayList(u8),
|
||||||
|
_resolver: js.PersistentPromiseResolver,
|
||||||
|
|
||||||
pub const Input = Request.Input;
|
pub const Input = Request.Input;
|
||||||
|
|
||||||
|
// @ZIGDOM just enough to get campire demo working
|
||||||
pub fn init(input: Input, page: *Page) !js.Promise {
|
pub fn init(input: Input, page: *Page) !js.Promise {
|
||||||
// @ZIGDOM
|
const request = try Request.init(input, page);
|
||||||
_ = input;
|
|
||||||
_ = page;
|
const fetch = try page.arena.create(Fetch);
|
||||||
return undefined;
|
fetch.* = .{
|
||||||
|
._page = page,
|
||||||
|
._response = .empty,
|
||||||
|
._resolver = try page.js.createPromiseResolver(.page),
|
||||||
|
};
|
||||||
|
|
||||||
|
const http_client = page._session.browser.http_client;
|
||||||
|
const headers = try http_client.newHeaders();
|
||||||
|
|
||||||
|
try http_client.request(.{
|
||||||
|
.ctx = fetch,
|
||||||
|
.url = request._url,
|
||||||
|
.method = .GET,
|
||||||
|
.headers = headers,
|
||||||
|
.cookie_jar = &page._session.cookie_jar,
|
||||||
|
.resource_type = .fetch,
|
||||||
|
.header_callback = httpHeaderDoneCallback,
|
||||||
|
.data_callback = httpDataCallback,
|
||||||
|
.done_callback = httpDoneCallback,
|
||||||
|
.error_callback = httpErrorCallback,
|
||||||
|
});
|
||||||
|
return fetch._resolver.promise();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn httpHeaderDoneCallback(transfer: *Http.Transfer) !void {
|
||||||
|
const self: *Fetch = @ptrCast(@alignCast(transfer.ctx));
|
||||||
|
_ = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn httpDataCallback(transfer: *Http.Transfer, data: []const u8) !void {
|
||||||
|
const self: *Fetch = @ptrCast(@alignCast(transfer.ctx));
|
||||||
|
try self._response.appendSlice(self._page.arena, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn httpDoneCallback(ctx: *anyopaque) !void {
|
||||||
|
const self: *Fetch = @ptrCast(@alignCast(ctx));
|
||||||
|
|
||||||
|
const page = self._page;
|
||||||
|
const res = try Response.initFromFetch(page.arena, self._response.items, page);
|
||||||
|
return self._resolver.resolve(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn httpErrorCallback(ctx: *anyopaque, err: anyerror) void {
|
||||||
|
const self: *Fetch = @ptrCast(@alignCast(ctx));
|
||||||
|
self._resolver.reject(@errorName(err)) catch |inner| {
|
||||||
|
log.err(.bug, "failed to reject", .{ .source = "fetch", .err = inner, .reject = err });
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ pub fn getJson(self: *Response, page: *Page) !js.Promise {
|
|||||||
) catch |err| {
|
) catch |err| {
|
||||||
return page.js.rejectPromise(.{@errorName(err)});
|
return page.js.rejectPromise(.{@errorName(err)});
|
||||||
};
|
};
|
||||||
return page.js.resolvePromise(.{value});
|
return page.js.resolvePromise(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const JsApi = struct {
|
pub const JsApi = struct {
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ const Allocator = std.mem.Allocator;
|
|||||||
|
|
||||||
pub const FetchOpts = struct {
|
pub const FetchOpts = struct {
|
||||||
wait_ms: u32 = 5000,
|
wait_ms: u32 = 5000,
|
||||||
dump_opts: dump.Opts,
|
dump: dump.Opts,
|
||||||
dump_file: ?std.fs.File = null,
|
writer: ?*std.Io.Writer = null,
|
||||||
};
|
};
|
||||||
pub fn fetch(app: *App, url: [:0]const u8, opts: FetchOpts) !void {
|
pub fn fetch(app: *App, url: [:0]const u8, opts: FetchOpts) !void {
|
||||||
const Browser = @import("browser/Browser.zig");
|
const Browser = @import("browser/Browser.zig");
|
||||||
@@ -40,12 +40,9 @@ pub fn fetch(app: *App, url: [:0]const u8, opts: FetchOpts) !void {
|
|||||||
_ = try page.navigate(url, .{});
|
_ = try page.navigate(url, .{});
|
||||||
_ = session.fetchWait(opts.wait_ms);
|
_ = session.fetchWait(opts.wait_ms);
|
||||||
|
|
||||||
const file = opts.dump_file orelse return;
|
const writer = opts.writer orelse return;
|
||||||
|
try dump.deep(page.document.asNode(), opts.dump, writer);
|
||||||
var buf: [4096]u8 = undefined;
|
try writer.flush();
|
||||||
var writer = file.writer(&buf);
|
|
||||||
try dump.deep(page.document.asNode(), opts.dump_opts, &writer.interface);
|
|
||||||
try writer.interface.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
|||||||
@@ -352,7 +352,7 @@ fn elapsed() struct { time: f64, unit: []const u8 } {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const datetime = @import("datetime.zig");
|
const datetime = @import("datetime.zig");
|
||||||
fn timestamp(mode: datetime.TimestampMode) u64 {
|
fn timestamp(comptime mode: datetime.TimestampMode) u64 {
|
||||||
if (comptime @import("builtin").is_test) {
|
if (comptime @import("builtin").is_test) {
|
||||||
return 1739795092929;
|
return 1739795092929;
|
||||||
}
|
}
|
||||||
|
|||||||
21
src/main.zig
21
src/main.zig
@@ -38,19 +38,17 @@ pub fn main() !void {
|
|||||||
if (gpa.detectLeaks()) std.posix.exit(1);
|
if (gpa.detectLeaks()) std.posix.exit(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
var global_allocator = lp.GlobalAllocator.init(allocator);
|
|
||||||
|
|
||||||
// arena for main-specific allocations
|
// arena for main-specific allocations
|
||||||
var main_arena = std.heap.ArenaAllocator.init(global_allocator.allocator());
|
var main_arena = std.heap.ArenaAllocator.init(allocator);
|
||||||
defer main_arena.deinit();
|
defer main_arena.deinit();
|
||||||
|
|
||||||
run(&global_allocator, main_arena.allocator()) catch |err| {
|
run(allocator, main_arena.allocator()) catch |err| {
|
||||||
log.fatal(.app, "exit", .{ .err = err });
|
log.fatal(.app, "exit", .{ .err = err });
|
||||||
std.posix.exit(1);
|
std.posix.exit(1);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(allocator: *lp.GlobalAllocator, main_arena: Allocator) !void {
|
fn run(allocator: Allocator, main_arena: Allocator) !void {
|
||||||
const args = try parseArgs(main_arena);
|
const args = try parseArgs(main_arena);
|
||||||
|
|
||||||
switch (args.mode) {
|
switch (args.mode) {
|
||||||
@@ -102,7 +100,6 @@ fn run(allocator: *lp.GlobalAllocator, main_arena: Allocator) !void {
|
|||||||
|
|
||||||
switch (args.mode) {
|
switch (args.mode) {
|
||||||
.serve => {
|
.serve => {
|
||||||
log.fatal(.app, "serve not not supported in the zigdom branch yet\n", .{});
|
|
||||||
return;
|
return;
|
||||||
// @ZIGDOM-CDP
|
// @ZIGDOM-CDP
|
||||||
// .serve => |opts| {
|
// .serve => |opts| {
|
||||||
@@ -131,13 +128,15 @@ fn run(allocator: *lp.GlobalAllocator, main_arena: Allocator) !void {
|
|||||||
var fetch_opts = lp.FetchOpts{
|
var fetch_opts = lp.FetchOpts{
|
||||||
.wait_ms = 5000,
|
.wait_ms = 5000,
|
||||||
.dump = .{
|
.dump = .{
|
||||||
.with_base = opts.with_base,
|
.with_base = opts.withbase,
|
||||||
.strip_mode = opts.strip_mode,
|
.strip_mode = opts.strip_mode,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var stdout = std.fs.File.stdout();
|
||||||
|
var writer = stdout.writer(&.{});
|
||||||
if (opts.dump) {
|
if (opts.dump) {
|
||||||
fetch_opts.dump_file = std.fs.File.stdout();
|
fetch_opts.writer = &writer.interface;
|
||||||
}
|
}
|
||||||
|
|
||||||
lp.fetch(app, url, fetch_opts) catch |err| {
|
lp.fetch(app, url, fetch_opts) catch |err| {
|
||||||
@@ -245,7 +244,7 @@ const Command = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Fetch = struct {
|
const Fetch = struct {
|
||||||
url: []const u8,
|
url: [:0]const u8,
|
||||||
dump: bool = false,
|
dump: bool = false,
|
||||||
common: Common,
|
common: Common,
|
||||||
withbase: bool = false,
|
withbase: bool = false,
|
||||||
@@ -513,7 +512,7 @@ fn parseFetchArgs(
|
|||||||
) !Command.Fetch {
|
) !Command.Fetch {
|
||||||
var dump: bool = false;
|
var dump: bool = false;
|
||||||
var withbase: bool = false;
|
var withbase: bool = false;
|
||||||
var url: ?[]const u8 = null;
|
var url: ?[:0]const u8 = null;
|
||||||
var common: Command.Common = .{};
|
var common: Command.Common = .{};
|
||||||
var strip_mode: lp.dump.Opts.StripMode = .{};
|
var strip_mode: lp.dump.Opts.StripMode = .{};
|
||||||
|
|
||||||
@@ -576,7 +575,7 @@ fn parseFetchArgs(
|
|||||||
log.fatal(.app, "duplicate fetch url", .{ .help = "only 1 URL can be specified" });
|
log.fatal(.app, "duplicate fetch url", .{ .help = "only 1 URL can be specified" });
|
||||||
return error.TooManyURLs;
|
return error.TooManyURLs;
|
||||||
}
|
}
|
||||||
url = try allocator.dupe(u8, opt);
|
url = try allocator.dupeZ(u8, opt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url == null) {
|
if (url == null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user