mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-21 20:24:42 +00:00
Move more asserts to custom asserter.
Deciding what should be an lp.assert, vs an std.debug.assert, vs a debug-only assert is a little arbitrary. debug-only asserts, guarded with an `if (comptime IS_DEBUG)` obviously avoid the check in release and thus have a performance advantage. We also use them at library boundaries. If libcurl says it will always emit a header line with a trailing \r\n, is that really a check we need to do in production? I don't think so. First, that code path is checked _a lot_ in debug. Second, it feels a bit like we're testing libcurl (in production!)..why? A debug-only assertion should be good enough to catch any changes in libcurl.
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const log = @import("log.zig");
|
||||
const Page = @import("browser/Page.zig");
|
||||
@@ -241,7 +242,7 @@ pub fn unregister(self: *Notification, comptime event: EventType, receiver: anyt
|
||||
if (listeners.items.len == 0) {
|
||||
listeners.deinit(self.allocator);
|
||||
const removed = self.listeners.remove(@intFromPtr(receiver));
|
||||
std.debug.assert(removed == true);
|
||||
lp.assert(removed == true, "Notification.unregister", .{ .type = event });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const net = std.net;
|
||||
@@ -157,7 +158,7 @@ fn readLoop(self: *Server, socket: posix.socket_t, timeout_ms: u32) !void {
|
||||
});
|
||||
defer http.removeCDPClient();
|
||||
|
||||
std.debug.assert(client.mode == .http);
|
||||
lp.assert(client.mode == .http, "Server.readLoop invalid mode", .{});
|
||||
while (true) {
|
||||
if (http.poll(timeout_ms) != .cdp_socket) {
|
||||
log.info(.app, "CDP timeout", .{});
|
||||
@@ -236,7 +237,7 @@ pub const Client = struct {
|
||||
const socket_flags = try posix.fcntl(socket, posix.F.GETFL, 0);
|
||||
const nonblocking = @as(u32, @bitCast(posix.O{ .NONBLOCK = true }));
|
||||
// we expect the socket to come to us as nonblocking
|
||||
std.debug.assert(socket_flags & nonblocking == nonblocking);
|
||||
lp.assert(socket_flags & nonblocking == nonblocking, "Client.init blocking", .{});
|
||||
|
||||
var reader = try Reader(true).init(server.allocator);
|
||||
errdefer reader.deinit();
|
||||
@@ -311,7 +312,7 @@ pub const Client = struct {
|
||||
}
|
||||
|
||||
fn processHTTPRequest(self: *Client) !bool {
|
||||
std.debug.assert(self.reader.pos == 0);
|
||||
lp.assert(self.reader.pos == 0, "Client.HTTP pos", .{ .pos = self.reader.pos });
|
||||
const request = self.reader.buf[0..self.reader.len];
|
||||
|
||||
if (request.len > MAX_HTTP_REQUEST_SIZE) {
|
||||
@@ -592,8 +593,7 @@ pub const Client = struct {
|
||||
// blocking and switch it back to non-blocking after the write
|
||||
// is complete. Doesn't seem particularly efficiently, but
|
||||
// this should virtually never happen.
|
||||
std.debug.assert(changed_to_blocking == false);
|
||||
log.debug(.app, "CDP write would block", .{});
|
||||
lp.assert(changed_to_blocking == false, "Client.double block", .{});
|
||||
changed_to_blocking = true;
|
||||
_ = try posix.fcntl(self.socket, posix.F.SETFL, self.socket_flags & ~@as(u32, @bitCast(posix.O{ .NONBLOCK = true })));
|
||||
continue :LOOP;
|
||||
@@ -821,7 +821,7 @@ fn Reader(comptime EXPECT_MASK: bool) type {
|
||||
const pos = self.pos;
|
||||
const len = self.len;
|
||||
|
||||
std.debug.assert(pos <= len);
|
||||
lp.assert(pos <= len, "Client.Reader.compact precondition", .{ .pos = pos, .len = len });
|
||||
|
||||
// how many (if any) partial bytes do we have
|
||||
const partial_bytes = len - pos;
|
||||
@@ -842,7 +842,7 @@ fn Reader(comptime EXPECT_MASK: bool) type {
|
||||
const next_message_len = length_meta.@"1";
|
||||
// if this isn't true, then we have a full message and it
|
||||
// should have been processed.
|
||||
std.debug.assert(next_message_len > partial_bytes);
|
||||
lp.assert(pos <= len, "Client.Reader.compact postcondition", .{ .next_len = next_message_len, .partial = partial_bytes });
|
||||
|
||||
const missing_bytes = next_message_len - partial_bytes;
|
||||
|
||||
@@ -929,7 +929,7 @@ fn fillWebsocketHeader(buf: std.ArrayListUnmanaged(u8)) []const u8 {
|
||||
// makes the assumption that our caller reserved the first
|
||||
// 10 bytes for the header
|
||||
fn websocketHeader(buf: []u8, op_code: OpCode, payload_len: usize) []const u8 {
|
||||
std.debug.assert(buf.len == 10);
|
||||
lp.assert(buf.len == 10, "Websocket.Header", .{ .len = buf.len });
|
||||
|
||||
const len = payload_len;
|
||||
buf[0] = 128 | @intFromEnum(op_code); // fin | opcode
|
||||
|
||||
@@ -17,10 +17,8 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const builtin = @import("builtin");
|
||||
const reflect = @import("reflect.zig");
|
||||
const IS_DEBUG = builtin.mode == .Debug;
|
||||
|
||||
const log = @import("../log.zig");
|
||||
const String = @import("../string.zig").String;
|
||||
@@ -38,6 +36,9 @@ const XMLHttpRequestEventTarget = @import("webapi/net/XMLHttpRequestEventTarget.
|
||||
const Blob = @import("webapi/Blob.zig");
|
||||
const AbstractRange = @import("webapi/AbstractRange.zig");
|
||||
|
||||
const IS_DEBUG = builtin.mode == .Debug;
|
||||
const assert = std.debug.assert;
|
||||
|
||||
const Factory = @This();
|
||||
_page: *Page,
|
||||
_slab: SlabAllocator,
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
const std = @import("std");
|
||||
const JS = @import("js/js.zig");
|
||||
const lp = @import("lightpanda");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
@@ -786,7 +787,9 @@ fn _wait(self: *Page, wait_ms: u32) !Session.WaitResult {
|
||||
// an extra socket, so it should not be possibl to
|
||||
// get an cdp_socket message when exit_when_done
|
||||
// is true.
|
||||
std.debug.assert(exit_when_done == false);
|
||||
if (IS_DEBUG) {
|
||||
std.debug.assert(exit_when_done == false);
|
||||
}
|
||||
|
||||
// data on a socket we aren't handling, return to caller
|
||||
return .cdp_socket;
|
||||
@@ -822,7 +825,9 @@ fn _wait(self: *Page, wait_ms: u32) !Session.WaitResult {
|
||||
// we don't need to consider http_client.intercepted here
|
||||
// because exit_when_done is true, and that can only be
|
||||
// the case when interception isn't possible.
|
||||
std.debug.assert(http_client.intercepted == 0);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(http_client.intercepted == 0);
|
||||
}
|
||||
|
||||
const ms = ms_to_next_task orelse blk: {
|
||||
if (wait_ms - ms_remaining < 100) {
|
||||
@@ -1019,7 +1024,9 @@ fn getElementIdMap(page: *Page, node: *Node) ElementIdMaps {
|
||||
};
|
||||
}
|
||||
// Detached nodes should not have IDs registered
|
||||
std.debug.assert(false);
|
||||
if (IS_DEBUG) {
|
||||
std.debug.assert(false);
|
||||
}
|
||||
return .{
|
||||
.lookup = &page.document._elements_by_id,
|
||||
.removed_ids = &page.document._removed_ids,
|
||||
@@ -1265,14 +1272,14 @@ pub fn deliverSlotchangeEvents(self: *Page) void {
|
||||
}
|
||||
|
||||
fn notifyNetworkIdle(self: *Page) void {
|
||||
std.debug.assert(self._notified_network_idle == .done);
|
||||
lp.assert(self._notified_network_idle == .done, "Page.notifyNetworkIdle", .{});
|
||||
self._session.browser.notification.dispatch(.page_network_idle, &.{
|
||||
.timestamp = timestamp(.monotonic),
|
||||
});
|
||||
}
|
||||
|
||||
fn notifyNetworkAlmostIdle(self: *Page) void {
|
||||
std.debug.assert(self._notified_network_almost_idle == .done);
|
||||
lp.assert(self._notified_network_almost_idle == .done, "Page.notifyNetworkAlmostIdle", .{});
|
||||
self._session.browser.notification.dispatch(.page_network_almost_idle, &.{
|
||||
.timestamp = timestamp(.monotonic),
|
||||
});
|
||||
@@ -1298,7 +1305,7 @@ pub fn appendNew(self: *Page, parent: *Node, child: Node.NodeOrText) !void {
|
||||
},
|
||||
};
|
||||
|
||||
std.debug.assert(node._parent == null);
|
||||
lp.assert(node._parent == null, "Page.appendNew", .{});
|
||||
try self._insertNodeRelative(true, parent, node, .append, .{
|
||||
// this opts has no meaning since we're passing `true` as the first
|
||||
// parameter, which indicates this comes from the parser, and has its
|
||||
@@ -2213,7 +2220,7 @@ pub fn removeNode(self: *Page, parent: *Node, child: *Node, opts: RemoveNodeOpts
|
||||
const children = parent._children.?;
|
||||
switch (children.*) {
|
||||
.one => |n| {
|
||||
std.debug.assert(n == child);
|
||||
lp.assert(n == child, "Page.removeNode.one", .{});
|
||||
parent._children = null;
|
||||
self._factory.destroy(children);
|
||||
},
|
||||
@@ -2340,7 +2347,8 @@ pub fn insertNodeRelative(self: *Page, parent: *Node, child: *Node, relative: In
|
||||
}
|
||||
pub fn _insertNodeRelative(self: *Page, comptime from_parser: bool, parent: *Node, child: *Node, relative: InsertNodeRelative, opts: InsertNodeOpts) !void {
|
||||
// caller should have made sure this was the case
|
||||
std.debug.assert(child._parent == null);
|
||||
|
||||
lp.assert(child._parent == null, "Page.insertNodeRelative parent", .{ .url = self.url });
|
||||
|
||||
const children = blk: {
|
||||
// expand parent._children so that it can take another child
|
||||
@@ -2369,14 +2377,14 @@ pub fn _insertNodeRelative(self: *Page, comptime from_parser: bool, parent: *Nod
|
||||
},
|
||||
.after => |ref_node| {
|
||||
// caller should have made sure this was the case
|
||||
std.debug.assert(ref_node._parent.? == parent);
|
||||
lp.assert(ref_node._parent.? == parent, "Page.insertNodeRelative after", .{ .url = self.url });
|
||||
// if ref_node is in parent, and expanded _children above to
|
||||
// accommodate another child, then `children` must be a list
|
||||
children.list.insertAfter(&ref_node._child_link, &child._child_link);
|
||||
},
|
||||
.before => |ref_node| {
|
||||
// caller should have made sure this was the case
|
||||
std.debug.assert(ref_node._parent.? == parent);
|
||||
lp.assert(ref_node._parent.? == parent, "Page.insertNodeRelative before", .{ .url = self.url });
|
||||
// if ref_node is in parent, and expanded _children above to
|
||||
// accommodate another child, then `children` must be a list
|
||||
children.list.insertBefore(&ref_node._child_link, &child._child_link);
|
||||
@@ -2654,7 +2662,7 @@ pub fn parseHtmlAsChildren(self: *Page, node: *Node, html: []const u8) !void {
|
||||
// https://github.com/servo/html5ever/issues/583
|
||||
const children = node._children orelse return;
|
||||
const first = children.one;
|
||||
std.debug.assert(first.is(Element.Html.Html) != null);
|
||||
lp.assert(first.is(Element.Html.Html) != null, "Page.parseHtmlAsChildren root", .{ .type = first._type });
|
||||
node._children = first._children;
|
||||
|
||||
if (self.hasMutationObservers()) {
|
||||
|
||||
@@ -95,7 +95,9 @@ fn runQueue(self: *Scheduler, queue: *Queue) !?u64 {
|
||||
|
||||
if (repeat_in_ms) |ms| {
|
||||
// Task cannot be repeated immediately, and they should know that
|
||||
std.debug.assert(ms != 0);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(ms != 0);
|
||||
}
|
||||
task.run_at = now + ms;
|
||||
try self.low_priority.add(task);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const js = @import("js/js.zig");
|
||||
@@ -484,7 +485,7 @@ pub fn getAsyncImport(self: *ScriptManager, url: [:0]const u8, cb: ImportAsync.C
|
||||
// Called from the Page to let us know it's done parsing the HTML. Necessary that
|
||||
// we know this so that we know that we can start evaluating deferred scripts.
|
||||
pub fn staticScriptsDone(self: *ScriptManager) void {
|
||||
std.debug.assert(self.static_scripts_done == false);
|
||||
lp.assert(self.static_scripts_done == false, "ScriptManager.staticScriptsDone", .{});
|
||||
self.static_scripts_done = true;
|
||||
self.evaluate();
|
||||
}
|
||||
@@ -675,7 +676,7 @@ pub const Script = struct {
|
||||
// set `CURLOPT_SUPPRESS_CONNECT_HEADERS` and CONNECT to a proxy, this
|
||||
// will fail. This assertion exists to catch incorrect assumptions about
|
||||
// how libcurl works, or about how we've configured it.
|
||||
std.debug.assert(self.source.remote.capacity == 0);
|
||||
lp.assert(self.source.remote.capacity == 0, "ScriptManager.HeaderCallback", .{ .capacity = self.source.remote.capacity });
|
||||
var buffer = self.manager.buffer_pool.get();
|
||||
if (transfer.getContentLength()) |cl| {
|
||||
try buffer.ensureTotalCapacity(self.manager.allocator, cl);
|
||||
@@ -750,10 +751,12 @@ pub const Script = struct {
|
||||
|
||||
fn eval(self: *Script, page: *Page) void {
|
||||
// never evaluated, source is passed back to v8, via callbacks.
|
||||
std.debug.assert(self.mode != .import_async);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(self.mode != .import_async);
|
||||
|
||||
// never evaluated, source is passed back to v8 when asked for it.
|
||||
std.debug.assert(self.mode != .import);
|
||||
// never evaluated, source is passed back to v8 when asked for it.
|
||||
std.debug.assert(self.mode != .import);
|
||||
}
|
||||
|
||||
if (page.isGoingAway()) {
|
||||
// don't evaluate scripts for a dying page.
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const ResolveOpts = struct {
|
||||
@@ -93,7 +94,7 @@ pub fn resolve(allocator: Allocator, base: [:0]const u8, path: anytype, comptime
|
||||
}
|
||||
|
||||
if (std.mem.startsWith(u8, out[in_i..], "../")) {
|
||||
std.debug.assert(out[out_i - 1] == '/');
|
||||
lp.assert(out[out_i - 1] == '/', "URL.resolve", .{ .out = out });
|
||||
|
||||
if (out_i > path_marker) {
|
||||
// go back before the /
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
const lp = @import("lightpanda");
|
||||
const log = @import("../../log.zig");
|
||||
|
||||
const js = @import("js.zig");
|
||||
@@ -203,7 +203,7 @@ pub fn module(self: *Context, comptime want_result: bool, src: []const u8, url:
|
||||
|
||||
if (cacheable) {
|
||||
// compileModule is synchronous - nothing can modify the cache during compilation
|
||||
std.debug.assert(gop.value_ptr.module == null);
|
||||
lp.assert(gop.value_ptr.module == null, "Context.module has module", .{});
|
||||
gop.value_ptr.module = try m.persist();
|
||||
if (!gop.found_existing) {
|
||||
gop.key_ptr.* = owned_url;
|
||||
@@ -220,7 +220,9 @@ pub fn module(self: *Context, comptime want_result: bool, src: []const u8, url:
|
||||
}
|
||||
|
||||
const evaluated = mod.evaluate() catch {
|
||||
std.debug.assert(mod.getStatus() == .kErrored);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(mod.getStatus() == .kErrored);
|
||||
}
|
||||
|
||||
// Some module-loading errors aren't handled by TryCatch. We need to
|
||||
// get the error from the module itself.
|
||||
@@ -233,7 +235,7 @@ pub fn module(self: *Context, comptime want_result: bool, src: []const u8, url:
|
||||
|
||||
// https://v8.github.io/api/head/classv8_1_1Module.html#a1f1758265a4082595757c3251bb40e0f
|
||||
// Must be a promise that gets returned here.
|
||||
std.debug.assert(evaluated.isPromise());
|
||||
lp.assert(evaluated.isPromise(), "Context.module non-promise", .{});
|
||||
|
||||
if (comptime !want_result) {
|
||||
// avoid creating a bunch of persisted objects if it isn't
|
||||
@@ -247,14 +249,16 @@ pub fn module(self: *Context, comptime want_result: bool, src: []const u8, url:
|
||||
|
||||
// anyone who cares about the result, should also want it to
|
||||
// be cached
|
||||
std.debug.assert(cacheable);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(cacheable);
|
||||
}
|
||||
|
||||
// entry has to have been created atop this function
|
||||
const entry = self.module_cache.getPtr(owned_url).?;
|
||||
|
||||
// and the module must have been set after we compiled it
|
||||
std.debug.assert(entry.module != null);
|
||||
std.debug.assert(entry.module_promise == null);
|
||||
lp.assert(entry.module != null, "Context.module with module", .{});
|
||||
lp.assert(entry.module_promise == null, "Context.module with module_promise", .{});
|
||||
|
||||
entry.module_promise = try evaluated.toPromise().persist();
|
||||
return if (comptime want_result) entry.* else {};
|
||||
@@ -692,7 +696,9 @@ pub fn jsValueToZig(self: *Context, comptime T: type, js_value: js.Value) !T {
|
||||
return error.InvalidArgument;
|
||||
}
|
||||
if (@hasDecl(ptr.child, "JsApi")) {
|
||||
std.debug.assert(bridge.JsApiLookup.has(ptr.child.JsApi));
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(bridge.JsApiLookup.has(ptr.child.JsApi));
|
||||
}
|
||||
return typeTaggedAnyOpaque(*ptr.child, js_value.handle);
|
||||
}
|
||||
},
|
||||
@@ -1066,7 +1072,7 @@ fn _jsStringToZig(self: *const Context, comptime null_terminate: bool, str: anyt
|
||||
const allocator = opts.allocator orelse self.call_arena;
|
||||
const buf = try (if (comptime null_terminate) allocator.allocSentinel(u8, @intCast(len), 0) else allocator.alloc(u8, @intCast(len)));
|
||||
const n = v8.v8__String__WriteUtf8(handle, self.isolate.handle, buf.ptr, buf.len, v8.NO_NULL_TERMINATION | v8.REPLACE_INVALID_UTF8);
|
||||
std.debug.assert(n == len);
|
||||
lp.assert(n == len, "Context.jsStringToZig", .{ .n = n, .len = len });
|
||||
|
||||
return buf;
|
||||
}
|
||||
@@ -1394,7 +1400,7 @@ fn _dynamicModuleCallback(self: *Context, specifier: [:0]const u8, referrer: []c
|
||||
// We need to do part of what the first case is going to do in
|
||||
// `dynamicModuleSourceCallback`, but we can skip some steps
|
||||
// since the module is alrady loaded,
|
||||
std.debug.assert(gop.value_ptr.module != null);
|
||||
lp.assert(gop.value_ptr.module != null, "Context._dynamicModuleCallback has module", .{});
|
||||
|
||||
// If the module hasn't been evaluated yet (it was only instantiated
|
||||
// as a static import dependency), we need to evaluate it now.
|
||||
@@ -1411,11 +1417,13 @@ fn _dynamicModuleCallback(self: *Context, specifier: [:0]const u8, referrer: []c
|
||||
} else {
|
||||
// the module was loaded, but not evaluated, we _have_ to evaluate it now
|
||||
const evaluated = mod.evaluate() catch {
|
||||
std.debug.assert(status == .kErrored);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(status == .kErrored);
|
||||
}
|
||||
_ = resolver.local().reject("module evaluation", self.newString("Module evaluation failed"));
|
||||
return promise.local();
|
||||
};
|
||||
std.debug.assert(evaluated.isPromise());
|
||||
lp.assert(evaluated.isPromise(), "Context._dynamicModuleCallback non-promise", .{});
|
||||
gop.value_ptr.module_promise = try evaluated.toPromise().persist();
|
||||
}
|
||||
}
|
||||
@@ -1466,9 +1474,11 @@ fn resolveDynamicModule(self: *Context, state: *DynamicModuleResolveState, modul
|
||||
|
||||
// we can only be here if the module has been evaluated and if
|
||||
// we have a resolve loading this asynchronously.
|
||||
std.debug.assert(module_entry.module_promise != null);
|
||||
std.debug.assert(module_entry.resolver_promise != null);
|
||||
std.debug.assert(self.module_cache.contains(state.specifier));
|
||||
lp.assert(module_entry.module_promise != null, "Context.resolveDynamicModule has module_promise", .{});
|
||||
lp.assert(module_entry.resolver_promise != null, "Context.resolveDynamicModule has resolver_promise", .{});
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(self.module_cache.contains(state.specifier));
|
||||
}
|
||||
state.module = module_entry.module.?;
|
||||
|
||||
// We've gotten the source for the module and are evaluating it.
|
||||
|
||||
@@ -17,9 +17,10 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const log = @import("../../log.zig");
|
||||
const Page = @import("../Page.zig");
|
||||
|
||||
const js = @import("js.zig");
|
||||
const v8 = js.v8;
|
||||
@@ -28,9 +29,8 @@ const Env = @import("Env.zig");
|
||||
const bridge = @import("bridge.zig");
|
||||
const Context = @import("Context.zig");
|
||||
|
||||
const Page = @import("../Page.zig");
|
||||
|
||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
const CONTEXT_ARENA_RETAIN = 1024 * 64;
|
||||
|
||||
@@ -71,7 +71,7 @@ pub fn deinit(self: *ExecutionWorld) void {
|
||||
// We also maintain our own "context_arena" which allows us to have
|
||||
// all page related memory easily managed.
|
||||
pub fn createContext(self: *ExecutionWorld, page: *Page, enter: bool) !*Context {
|
||||
std.debug.assert(self.context == null);
|
||||
lp.assert(self.context == null, "ExecptionWorld.createContext has context", .{});
|
||||
|
||||
const env = self.env;
|
||||
const isolate = env.isolate;
|
||||
|
||||
@@ -426,7 +426,9 @@ fn attachClass(comptime JsApi: type, isolate: *v8.Isolate, template: *v8.Functio
|
||||
v8.v8__ObjectTemplate__SetAccessorProperty__DEFAULT(target, js_name, getter_callback);
|
||||
}
|
||||
} else {
|
||||
std.debug.assert(value.static == false);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(value.static == false);
|
||||
}
|
||||
const setter_callback = @constCast(v8.v8__FunctionTemplate__New__DEFAULT2(isolate, value.setter.?).?);
|
||||
v8.v8__ObjectTemplate__SetAccessorProperty__DEFAULT2(target, js_name, getter_callback, setter_callback);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
const std = @import("std");
|
||||
const js = @import("js.zig");
|
||||
const lp = @import("lightpanda");
|
||||
const log = @import("../../log.zig");
|
||||
|
||||
const v8 = js.v8;
|
||||
@@ -743,7 +744,9 @@ pub const Accessor = struct {
|
||||
defer caller.deinit();
|
||||
|
||||
const info = FunctionCallbackInfo{ .handle = handle.? };
|
||||
std.debug.assert(info.length() == 1);
|
||||
if (comptime IS_DEBUG) {
|
||||
lp.assert(info.length() == 1, "bridge.setter", .{ .len = info.length() });
|
||||
}
|
||||
|
||||
caller.method(T, setter, info, .{
|
||||
.as_typed_array = opts.as_typed_array,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
const h5e = @import("html5ever.zig");
|
||||
|
||||
const Page = @import("../Page.zig");
|
||||
@@ -162,7 +163,7 @@ pub const Streaming = struct {
|
||||
}
|
||||
|
||||
pub fn start(self: *Streaming) !void {
|
||||
std.debug.assert(self.handle == null);
|
||||
lp.assert(self.handle == null, "Parser.start non-null handle", .{});
|
||||
|
||||
self.handle = h5e.html5ever_streaming_parser_create(
|
||||
&self.parser.container,
|
||||
@@ -357,7 +358,7 @@ fn getDataCallback(ctx: *anyopaque) callconv(.c) *anyopaque {
|
||||
const pn: *ParsedNode = @ptrCast(@alignCast(ctx));
|
||||
// For non-elements, data is null. But, we expect this to only ever
|
||||
// be called for elements.
|
||||
std.debug.assert(pn.data != null);
|
||||
lp.assert(pn.data != null, "Parser.getDataCallback null data", .{});
|
||||
return pn.data.?;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const log = @import("../../log.zig");
|
||||
const String = @import("../../string.zig").String;
|
||||
@@ -509,7 +510,7 @@ pub fn getOrCreateAttributeList(self: *Element, page: *Page) !*Attribute.List {
|
||||
}
|
||||
|
||||
pub fn createAttributeList(self: *Element, page: *Page) !*Attribute.List {
|
||||
std.debug.assert(self._attributes == null);
|
||||
lp.assert(self._attributes == null, "Element.createAttributeList non-null _attributes", .{});
|
||||
const a = try page.arena.create(Attribute.List);
|
||||
a.* = .{ .normalize = self._namespace == .html };
|
||||
self._attributes = a;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
const log = @import("../../log.zig");
|
||||
|
||||
const crypto = @import("../../crypto.zig");
|
||||
@@ -387,7 +388,7 @@ pub const CryptoKey = struct {
|
||||
|
||||
// HMAC is simply CSPRNG.
|
||||
const res = crypto.RAND_bytes(key.ptr, key.len);
|
||||
std.debug.assert(res == 1);
|
||||
lp.assert(res == 1, "SubtleCrypto.initHMAC", .{ .res = res });
|
||||
|
||||
const crypto_key = try page._factory.create(CryptoKey{
|
||||
._type = .hmac,
|
||||
@@ -581,7 +582,7 @@ pub const CryptoKey = struct {
|
||||
return error.Internal;
|
||||
}
|
||||
// Sanity check.
|
||||
std.debug.assert(derived_key.len == out_key_len);
|
||||
lp.assert(derived_key.len == out_key_len, "SubtleCrypto.deriveBitsX25519", .{});
|
||||
|
||||
// Length is in bits, convert to byte length.
|
||||
const length = (length_in_bits / 8) + (7 + (length_in_bits % 8)) / 8;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const js = @import("../../js/js.zig");
|
||||
const Page = @import("../../Page.zig");
|
||||
@@ -58,7 +59,7 @@ pub fn length(self: *HTMLAllCollection, page: *const Page) u32 {
|
||||
}
|
||||
}
|
||||
|
||||
std.debug.assert(self._last_index == 0);
|
||||
lp.assert(self._last_index == 0, "HTMLAllCollection.length", .{ .last_index = self._last_index });
|
||||
|
||||
var tw = &self._tw;
|
||||
defer tw.reset();
|
||||
|
||||
@@ -25,6 +25,8 @@ const NodeList = @import("NodeList.zig");
|
||||
const RadioNodeList = @import("RadioNodeList.zig");
|
||||
const HTMLCollection = @import("HTMLCollection.zig");
|
||||
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
const HTMLFormControlsCollection = @This();
|
||||
|
||||
_proto: *HTMLCollection,
|
||||
@@ -95,7 +97,9 @@ pub fn namedItem(self: *HTMLFormControlsCollection, name: []const u8, page: *Pag
|
||||
}
|
||||
|
||||
// case == 2 was handled inside the loop
|
||||
std.debug.assert(count == 1);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(count == 1);
|
||||
}
|
||||
|
||||
return .{ .element = first_element.? };
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const String = @import("../../../string.zig").String;
|
||||
|
||||
@@ -124,7 +125,7 @@ pub fn NodeLive(comptime mode: Mode) type {
|
||||
// _tw is reset. Again, this should always be the case, but we're
|
||||
// asserting to make sure, else we'll have weird behavior, namely
|
||||
// the wrong item being returned for the wrong index.
|
||||
std.debug.assert(self._last_index == 0);
|
||||
lp.assert(self._last_index == 0, "NodeLives.length", .{ .last_index = self._last_index });
|
||||
|
||||
var tw = &self._tw;
|
||||
defer tw.reset();
|
||||
|
||||
@@ -26,6 +26,8 @@ const GenericIterator = @import("../collections/iterator.zig").Entry;
|
||||
const Page = @import("../../Page.zig");
|
||||
const String = @import("../../../string.zig").String;
|
||||
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
pub fn registerTypes() []const type {
|
||||
return &.{
|
||||
Attribute,
|
||||
@@ -223,7 +225,6 @@ pub const List = struct {
|
||||
|
||||
if (is_id) {
|
||||
const parent = element.asNode()._parent orelse {
|
||||
std.debug.assert(false);
|
||||
return entry;
|
||||
};
|
||||
try page.addElementId(parent, element, entry._value.str());
|
||||
@@ -248,7 +249,9 @@ pub const List = struct {
|
||||
// not efficient, won't be called often (if ever!)
|
||||
pub fn putAttribute(self: *List, attribute: *Attribute, element: *Element, page: *Page) !?*Attribute {
|
||||
// we expect our caller to make sure this is true
|
||||
std.debug.assert(attribute._element == null);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(attribute._element == null);
|
||||
}
|
||||
|
||||
const existing_attribute = try self.getAttribute(attribute._name, element, page);
|
||||
if (existing_attribute) |ea| {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
const js = @import("../../js/js.zig");
|
||||
const reflect = @import("../../reflect.zig");
|
||||
|
||||
@@ -293,11 +294,11 @@ pub fn insertAdjacentHTML(
|
||||
// <html><head></head><body>{ ... }</body></html>
|
||||
// None of the following can be null.
|
||||
const maybe_html_node = doc_node.firstChild();
|
||||
std.debug.assert(maybe_html_node != null);
|
||||
lp.assert(maybe_html_node != null, "Html.insertAdjacentHTML null html", .{});
|
||||
const html_node = maybe_html_node orelse return;
|
||||
|
||||
const maybe_body_node = html_node.lastChild();
|
||||
std.debug.assert(maybe_body_node != null);
|
||||
lp.assert(maybe_body_node != null, "Html.insertAdjacentHTML null bodys", .{});
|
||||
const body = maybe_body_node orelse return;
|
||||
|
||||
const target_node, const prev_node = try self.asElement().asNode().findAdjacentNodes(position);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
const log = @import("../../../log.zig");
|
||||
const URL = @import("../URL.zig");
|
||||
|
||||
@@ -81,7 +82,8 @@ pub fn getCurrentEntryOrNull(self: *Navigation) ?*NavigationHistoryEntry {
|
||||
pub fn getCurrentEntry(self: *Navigation) *NavigationHistoryEntry {
|
||||
// This should never fail. An entry should always be created before
|
||||
// we run the scripts on the page we are loading.
|
||||
std.debug.assert(self._entries.items.len > 0);
|
||||
const len = self._entries.items.len;
|
||||
lp.assert(len > 0, "Navigation.getCurrentEntry", .{ .len = len });
|
||||
|
||||
return self.getCurrentEntryOrNull().?;
|
||||
}
|
||||
|
||||
@@ -18,17 +18,19 @@
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const Page = @import("../../Page.zig");
|
||||
|
||||
const Node = @import("../Node.zig");
|
||||
const Selector = @import("Selector.zig");
|
||||
const Part = Selector.Part;
|
||||
const Combinator = Selector.Combinator;
|
||||
const Segment = Selector.Segment;
|
||||
const Attribute = @import("../element/Attribute.zig");
|
||||
|
||||
const Selector = @import("Selector.zig");
|
||||
|
||||
const Part = Selector.Part;
|
||||
const Segment = Selector.Segment;
|
||||
const Combinator = Selector.Combinator;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
const Parser = @This();
|
||||
|
||||
input: []const u8,
|
||||
@@ -308,8 +310,11 @@ fn consumeUntilCommaOrParen(self: *Parser) []const u8 {
|
||||
}
|
||||
|
||||
fn pseudoClass(self: *Parser, arena: Allocator, page: *Page) !Selector.PseudoClass {
|
||||
// Must be called when we're at a ':'
|
||||
std.debug.assert(self.peek() == ':');
|
||||
if (comptime IS_DEBUG) {
|
||||
// Should have been verified by caller
|
||||
std.debug.assert(self.peek() == ':');
|
||||
}
|
||||
|
||||
self.input = self.input[1..];
|
||||
|
||||
// Parse the pseudo-class name
|
||||
@@ -657,13 +662,21 @@ fn parseNthPattern(self: *Parser) !Selector.NthPattern {
|
||||
}
|
||||
|
||||
pub fn id(self: *Parser, arena: Allocator) ![]const u8 {
|
||||
std.debug.assert(self.peek() == '#');
|
||||
if (comptime IS_DEBUG) {
|
||||
// should have been verified by caller
|
||||
std.debug.assert(self.peek() == '#');
|
||||
}
|
||||
|
||||
self.input = self.input[1..]; // Skip '#'
|
||||
return self.parseIdentifier(arena, error.InvalidIDSelector);
|
||||
}
|
||||
|
||||
fn class(self: *Parser, arena: Allocator) ![]const u8 {
|
||||
std.debug.assert(self.peek() == '.');
|
||||
if (comptime IS_DEBUG) {
|
||||
// should have been verified by caller
|
||||
std.debug.assert(self.peek() == '.');
|
||||
}
|
||||
|
||||
self.input = self.input[1..]; // Skip '.'
|
||||
return self.parseIdentifier(arena, error.InvalidClassSelector);
|
||||
}
|
||||
@@ -822,8 +835,10 @@ fn tag(self: *Parser) ![]const u8 {
|
||||
}
|
||||
|
||||
fn attribute(self: *Parser, arena: Allocator, page: *Page) !Selector.Attribute {
|
||||
// Must be called when we're at a '['
|
||||
std.debug.assert(self.peek() == '[');
|
||||
if (comptime IS_DEBUG) {
|
||||
// should have been verified by caller
|
||||
std.debug.assert(self.peek() == '[');
|
||||
}
|
||||
|
||||
self.input = self.input[1..];
|
||||
_ = self.skipSpaces();
|
||||
|
||||
@@ -88,9 +88,6 @@ pub fn parse(allocator: Allocator, url: [:0]const u8, str: []const u8) !Cookie {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Make sure no one changes our max length without also expanding the size of scrap
|
||||
std.debug.assert(key_string.len <= 8);
|
||||
|
||||
const key = std.meta.stringToEnum(enum {
|
||||
path,
|
||||
domain,
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
const json = std.json;
|
||||
|
||||
@@ -35,6 +37,8 @@ const InterceptState = @import("domains/fetch.zig").InterceptState;
|
||||
pub const URL_BASE = "chrome://newtab/";
|
||||
pub const LOADER_ID = "LOADERID24DD2FD56CF1EF33C965C79C";
|
||||
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
pub const CDP = CDPT(struct {
|
||||
const Client = *@import("../Server.zig").Client;
|
||||
});
|
||||
@@ -657,7 +661,7 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
||||
pub fn onInspectorEvent(ctx: *anyopaque, msg: []const u8) void {
|
||||
if (log.enabled(.cdp, .debug)) {
|
||||
// msg should be {"method":<method>,...
|
||||
std.debug.assert(std.mem.startsWith(u8, msg, "{\"method\":"));
|
||||
lp.assert(std.mem.startsWith(u8, msg, "{\"method\":"), "onInspectorEvent prefix", .{});
|
||||
const method_end = std.mem.indexOfScalar(u8, msg, ',') orelse {
|
||||
log.err(.cdp, "invalid inspector event", .{ .msg = msg });
|
||||
return;
|
||||
@@ -716,7 +720,9 @@ pub fn BrowserContext(comptime CDP_T: type) type {
|
||||
buf.appendSliceAssumeCapacity(field);
|
||||
buf.appendSliceAssumeCapacity(session_id);
|
||||
buf.appendSliceAssumeCapacity("\"}");
|
||||
std.debug.assert(buf.items.len == message_len);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(buf.items.len == message_len);
|
||||
}
|
||||
|
||||
try cdp.client.sendJSONRaw(buf);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const CdpStorage = @import("storage.zig");
|
||||
@@ -215,7 +216,7 @@ pub fn httpRequestFail(arena: Allocator, bc: anytype, msg: *const Notification.R
|
||||
|
||||
// Isn't possible to do a network request within a Browser (which our
|
||||
// notification is tied to), without a page.
|
||||
std.debug.assert(bc.session.page != null);
|
||||
lp.assert(bc.session.page != null, "CDP.network.httpRequestFail null page", .{});
|
||||
|
||||
// We're missing a bunch of fields, but, for now, this seems like enough
|
||||
try bc.cdp.sendEvent("Network.loadingFailed", .{
|
||||
|
||||
@@ -17,13 +17,15 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
const log = @import("../../log.zig");
|
||||
const js = @import("../../browser/js/js.zig");
|
||||
const Page = @import("../../browser/Page.zig");
|
||||
const timestampF = @import("../../datetime.zig").timestamp;
|
||||
const Notification = @import("../../Notification.zig");
|
||||
const log = @import("../../log.zig");
|
||||
const js = @import("../../browser/js/js.zig");
|
||||
const v8 = js.v8;
|
||||
|
||||
const v8 = js.v8;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
pub fn processMessage(cmd: anytype) !void {
|
||||
@@ -142,7 +144,7 @@ fn close(cmd: anytype) !void {
|
||||
const target_id = bc.target_id orelse return error.TargetNotLoaded;
|
||||
|
||||
// can't be null if we have a target_id
|
||||
std.debug.assert(bc.session.page != null);
|
||||
lp.assert(bc.session.page != null, "CDP.page.close null page", .{});
|
||||
|
||||
try cmd.sendResult(.{}, .{});
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
const log = @import("../../log.zig");
|
||||
|
||||
// TODO: hard coded IDs
|
||||
@@ -164,10 +165,10 @@ fn createTarget(cmd: anytype) !void {
|
||||
}
|
||||
|
||||
// if target_id is null, we should never have a page
|
||||
std.debug.assert(bc.session.page == null);
|
||||
lp.assert(bc.session.page == null, "CDP.target.createTarget not null page", .{});
|
||||
|
||||
// if target_id is null, we should never have a session_id
|
||||
std.debug.assert(bc.session_id == null);
|
||||
lp.assert(bc.session_id == null, "CDP.target.createTarget not null session_id", .{});
|
||||
|
||||
const target_id = cmd.cdp.target_id_gen.next();
|
||||
|
||||
@@ -255,7 +256,7 @@ fn closeTarget(cmd: anytype) !void {
|
||||
}
|
||||
|
||||
// can't be null if we have a target_id
|
||||
std.debug.assert(bc.session.page != null);
|
||||
lp.assert(bc.session.page != null, "CDP.target.closeTarget null page", .{});
|
||||
|
||||
try cmd.sendResult(.{ .success = true }, .{ .include_session_id = false });
|
||||
|
||||
@@ -332,7 +333,7 @@ fn sendMessageToTarget(cmd: anytype) !void {
|
||||
return error.TargetNotLoaded;
|
||||
}
|
||||
|
||||
std.debug.assert(bc.session_id != null);
|
||||
lp.assert(bc.session_id != null, "CDP.target.sendMessageToTarget null session_id", .{});
|
||||
if (std.mem.eql(u8, bc.session_id.?, params.sessionId) == false) {
|
||||
// Is this right? Is the params.sessionId meant to be the active
|
||||
// sessionId? What else could it be? We have no other session_id.
|
||||
@@ -440,7 +441,7 @@ fn setAutoAttach(cmd: anytype) !void {
|
||||
|
||||
fn doAttachtoTarget(cmd: anytype, target_id: []const u8) !void {
|
||||
const bc = cmd.browser_context.?;
|
||||
std.debug.assert(bc.session_id == null);
|
||||
lp.assert(bc.session_id == null, "CDP.target.doAttachtoTarget not null session_id", .{});
|
||||
const session_id = cmd.cdp.session_id_gen.next();
|
||||
|
||||
// extra_headers should not be kept on a new page or tab,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
const builtin = @import("builtin");
|
||||
const posix = std.posix;
|
||||
|
||||
@@ -612,7 +613,7 @@ fn writeTime(into: []u8, time: Time) u8 {
|
||||
}
|
||||
|
||||
fn paddingTwoDigits(value: usize) [2]u8 {
|
||||
std.debug.assert(value < 61);
|
||||
lp.assert(value < 61, "datetime.paddingTwoDigits", .{ .value = value });
|
||||
const digits = "0001020304050607080910111213141516171819" ++
|
||||
"2021222324252627282930313233343536373839" ++
|
||||
"4041424344454647484950515253545556575859" ++
|
||||
|
||||
@@ -178,7 +178,9 @@ pub fn abort(self: *Client) void {
|
||||
};
|
||||
transfer.kill();
|
||||
}
|
||||
std.debug.assert(self.active == 0);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(self.active == 0);
|
||||
}
|
||||
|
||||
var n = self.queue.first;
|
||||
while (n) |node| {
|
||||
@@ -188,11 +190,10 @@ pub fn abort(self: *Client) void {
|
||||
}
|
||||
self.queue = .{};
|
||||
|
||||
// Maybe a bit of overkill
|
||||
// We can remove some (all?) of these once we're confident its right.
|
||||
std.debug.assert(self.handles.in_use.first == null);
|
||||
std.debug.assert(self.handles.available.len() == self.handles.handles.len);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(self.handles.in_use.first == null);
|
||||
std.debug.assert(self.handles.available.len() == self.handles.handles.len);
|
||||
|
||||
var running: c_int = undefined;
|
||||
std.debug.assert(c.curl_multi_perform(self.multi, &running) == c.CURLE_OK);
|
||||
std.debug.assert(running == 0);
|
||||
@@ -373,7 +374,9 @@ fn makeTransfer(self: *Client, req: Request) !*Transfer {
|
||||
fn requestFailed(self: *Client, transfer: *Transfer, err: anyerror) void {
|
||||
// this shouldn't happen, we'll crash in debug mode. But in release, we'll
|
||||
// just noop this state.
|
||||
std.debug.assert(transfer._notified_fail == false);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(transfer._notified_fail == false);
|
||||
}
|
||||
if (transfer._notified_fail) {
|
||||
return;
|
||||
}
|
||||
@@ -552,7 +555,9 @@ fn processMessages(self: *Client) !bool {
|
||||
while (c.curl_multi_info_read(multi, &messages_count)) |msg_| {
|
||||
const msg: *c.CURLMsg = @ptrCast(msg_);
|
||||
// This is the only possible message type from CURL for now.
|
||||
std.debug.assert(msg.msg == c.CURLMSG_DONE);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(msg.msg == c.CURLMSG_DONE);
|
||||
}
|
||||
|
||||
const easy = msg.easy_handle.?;
|
||||
const transfer = try Transfer.fromEasy(easy);
|
||||
@@ -893,7 +898,9 @@ pub const Transfer = struct {
|
||||
}
|
||||
|
||||
fn buildResponseHeader(self: *Transfer, easy: *c.CURL) !void {
|
||||
std.debug.assert(self.response_header == null);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(self.response_header == null);
|
||||
}
|
||||
|
||||
var url: [*c]u8 = undefined;
|
||||
try errorCheck(c.curl_easy_getinfo(easy, c.CURLINFO_EFFECTIVE_URL, &url));
|
||||
@@ -1036,7 +1043,9 @@ pub const Transfer = struct {
|
||||
// It can be called either on dataCallback or once the request for those
|
||||
// w/o body.
|
||||
fn headerDoneCallback(transfer: *Transfer, easy: *c.CURL) !void {
|
||||
std.debug.assert(transfer._header_done_called == false);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(transfer._header_done_called == false);
|
||||
}
|
||||
defer transfer._header_done_called = true;
|
||||
|
||||
try transfer.buildResponseHeader(easy);
|
||||
@@ -1076,7 +1085,9 @@ pub const Transfer = struct {
|
||||
// headerCallback is called by curl on each request's header line read.
|
||||
fn headerCallback(buffer: [*]const u8, header_count: usize, buf_len: usize, data: *anyopaque) callconv(.c) usize {
|
||||
// libcurl should only ever emit 1 header at a time
|
||||
std.debug.assert(header_count == 1);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(header_count == 1);
|
||||
}
|
||||
|
||||
const easy: *c.CURL = @ptrCast(@alignCast(data));
|
||||
var transfer = fromEasy(easy) catch |err| {
|
||||
@@ -1084,7 +1095,9 @@ pub const Transfer = struct {
|
||||
return 0;
|
||||
};
|
||||
|
||||
std.debug.assert(std.mem.endsWith(u8, buffer[0..buf_len], "\r\n"));
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(std.mem.endsWith(u8, buffer[0..buf_len], "\r\n"));
|
||||
}
|
||||
|
||||
const header = buffer[0 .. buf_len - 2];
|
||||
|
||||
@@ -1105,7 +1118,9 @@ pub const Transfer = struct {
|
||||
|
||||
// a bit silly, but it makes sure that we don't change the length check
|
||||
// above in a way that could break this.
|
||||
std.debug.assert(version_end < 13);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(version_end < 13);
|
||||
}
|
||||
|
||||
const status = std.fmt.parseInt(u16, header[version_start..version_end], 10) catch {
|
||||
if (comptime IS_DEBUG) {
|
||||
@@ -1180,7 +1195,9 @@ pub const Transfer = struct {
|
||||
|
||||
fn dataCallback(buffer: [*]const u8, chunk_count: usize, chunk_len: usize, data: *anyopaque) callconv(.c) usize {
|
||||
// libcurl should only ever emit 1 chunk at a time
|
||||
std.debug.assert(chunk_count == 1);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(chunk_count == 1);
|
||||
}
|
||||
|
||||
const easy: *c.CURL = @ptrCast(@alignCast(data));
|
||||
var transfer = fromEasy(easy) catch |err| {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
pub const c = @cImport({
|
||||
@cInclude("curl/curl.h");
|
||||
@@ -90,7 +91,7 @@ pub fn poll(self: *Http, timeout_ms: u32) Client.PerformStatus {
|
||||
}
|
||||
|
||||
pub fn addCDPClient(self: *Http, cdp_client: Client.CDPClient) void {
|
||||
std.debug.assert(self.client.cdp_client == null);
|
||||
lp.assert(self.client.cdp_client == null, "Http addCDPClient existing", .{});
|
||||
self.client.cdp_client = cdp_client;
|
||||
}
|
||||
|
||||
@@ -144,7 +145,7 @@ pub const Connection = struct {
|
||||
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_PROXY_CAINFO_BLOB, ca_blob));
|
||||
}
|
||||
} else {
|
||||
std.debug.assert(opts.tls_verify_host == false);
|
||||
lp.assert(opts.tls_verify_host == false, "Http.init tls_verify_host", .{});
|
||||
|
||||
// Verify peer checks that the cert is signed by a CA, verify host makes sure the
|
||||
// cert contains the server name.
|
||||
@@ -405,7 +406,7 @@ fn loadCerts(allocator: Allocator, arena: Allocator) !c.curl_blob {
|
||||
}
|
||||
|
||||
// Final encoding should not be larger than our initial size estimate
|
||||
std.debug.assert(buffer_size > arr.items.len);
|
||||
lp.assert(buffer_size > arr.items.len, "Http loadCerts", .{ .estiate = buffer_size, .len = arr.items.len });
|
||||
|
||||
return .{
|
||||
.len = arr.items.len,
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
const std = @import("std");
|
||||
const c = @import("Http.zig").c;
|
||||
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
pub const Error = error{
|
||||
UnsupportedProtocol,
|
||||
FailedInit,
|
||||
@@ -109,7 +111,9 @@ pub const Error = error{
|
||||
};
|
||||
|
||||
pub fn fromCode(code: c.CURLcode) Error {
|
||||
std.debug.assert(code != c.CURLE_OK);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(code != c.CURLE_OK);
|
||||
}
|
||||
|
||||
return switch (code) {
|
||||
c.CURLE_UNSUPPORTED_PROTOCOL => Error.UnsupportedProtocol,
|
||||
@@ -218,7 +222,9 @@ pub const Multi = error{
|
||||
};
|
||||
|
||||
pub fn fromMCode(code: c.CURLMcode) Multi {
|
||||
std.debug.assert(code != c.CURLM_OK);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(code != c.CURLM_OK);
|
||||
}
|
||||
|
||||
return switch (code) {
|
||||
c.CURLM_BAD_HANDLE => Multi.BadHandle,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const std = @import("std");
|
||||
const lp = @import("lightpanda");
|
||||
|
||||
// Generates incrementing prefixed integers, i.e. CTX-1, CTX-2, CTX-3.
|
||||
// Wraps to 0 on overflow.
|
||||
@@ -85,7 +86,7 @@ pub fn Incrementing(comptime T: type, comptime prefix: []const u8) type {
|
||||
}
|
||||
|
||||
pub fn uuidv4(hex: []u8) void {
|
||||
std.debug.assert(hex.len == 36);
|
||||
lp.assert(hex.len == 36, "uuidv4.len", .{ .len = hex.len });
|
||||
|
||||
var bin: [16]u8 = undefined;
|
||||
std.crypto.random.bytes(&bin);
|
||||
|
||||
Reference in New Issue
Block a user