Commit Graph
80 Commits
Author SHA1 Message Date
muki 57b86112b3 Merge pull request #3240 from lightpanda-io/xhr-async-flag
XHR Sync Request
2026-08-26 17:11:48 -07:00
Karl Seguin fce38a1aa8 Merge pull request #3289 from lightpanda-io/fix-double-releases
fix: Fix double-release and other (edge-case) memory issues
2026-08-27 07:34:45 +08:00
Karl Seguin cfd921ecab fix: Fix double-release and other (edge-case) memory issues
Our `Arena` from the `ArenaPool` now tracks if it's already been released. On
a subsequent release, it panics then and there. Without this, the code will
almost certainly panic anyways, but it will panic in a seemingly unrelated
place. Hopefully this makes identifying future cases of this easier (since we'll
get the stack trace of the re-releaser).

Fix 3 separate memory issues, all edge cases.

1 - an XHR error handler that re-open/sends would incorrectly null the new
    transfer (maybe this isn't that odd, maybe it's a common retry-on-error).

2 - On a curl_easy_pause error (from WebSocket.zig) we now unqueue the just-
    queued message, because the error will errdefer the message arena to be
    cleaned up.

3 - ScriptManager now cleans up after itself on a failure prior to submit()
    being called.
2026-08-26 18:24:12 +08:00
Pierre Tachoire 467167d6e6 http: strip Authorization on cross-origin redirects 2026-08-26 10:00:11 +02:00
Muki Kiboigo 234d47d0e2 syncRequest -> submitSync on Transfer 2026-08-25 17:43:03 -07:00
Halil Durak 87a87ba62e HttpClient: remove pending_low_queue, separate keys for headers_only in cache, more eager connection reuse 2026-08-25 14:20:38 +03:00
Halil Durak c1079444c4 addHeader -> setHeader + enable low prio for images 2026-08-25 14:18:46 +03:00
Halil Durak e58f99da18 add --load-resources CLI arg, supporting image param 2026-08-25 14:18:45 +03:00
Karl Seguin a6618fff63 http: Guarantee Transfer contract of single outcome callback
HttpClient guarantees that only one of done/error/shtudown callback will be
called. But that guarantee had a hole when a done/error callback would trigger
JS that caused an HttpClient.abort (e.g. by scheduling a navigation).

So far, this isn't a problem. fetch/XHR guard against this themselves, and
ScriptManager doesn't care of it happens.

But https://github.com/lightpanda-io/browser/pull/3230 doesn't guard against it
and would crash if it happens: its doneCallback frees `self` but can re-enter
shutdown which needs `self`. While 3230 could fix this issue, I'd prefer to
bake this contract into the HttpClient. Transfers now have an
`_outcome_delivered: bool` which guarantees that only one of done/error/shutdown
is called.
2026-08-22 11:09:52 +08:00
Karl Seguin 57bcdfed10 chore: Simplify Network and HttpClient init
Remove app field from Network
2026-08-22 07:05:05 +08:00
Karl Seguin decedca6e7 chore: Network cleanup
Network has accumulated a bit of bagged. It knows a lot about certificates, it
knows a lot of the cache. I have plans to expand Network, and wanted to clean it
up.

1 - certificate logic moved to dedicated Certificates.zig
2 - Removed CurlDebugAllocator
    - this makes setup easier, to Updater can just init libcurl directly
3 - Change Updater to be a single function
4 - Cache initialization is don in the Cache
5 - ?Cache => Cache{.kind = .noop}
2026-08-22 07:04:58 +08:00
Karl Seguin 9f4b39d723 Merge pull request #3239 from lightpanda-io/ratelimiter
http: Add optional rate limit
2026-08-22 06:58:52 +08:00
Karl Seguin 09edfd3ce5 http: Add optional rate limit
Add an optional per-host rate limit. This currently only applies to the top-
level navigation. This makes it simpler to implement and simpler to reason
about. The full load of a page is only ever delayed at its head, not
sporadically through the page loading.

The use-case where a RateLimiter is most useful is when the browser is crawling
multiple pages of the same site, and in that case, the top-level rate limit
still applies some degree of limit to any linked resources (e.g. a JS on a
different host).

`--http-nav-delay` is the delay, in milliseconds, to apply to top level
navigates per host. Currently defaults to 0 (disabled).

`--http-nav-burst` is the burst allowed per host. Defaults to 1 (has no impact
when `--http-nav-delay` is disabled).
2026-08-20 16:03:42 +08:00
Karl Seguin b70f7a325e webapi: Blob / File conformance
1-
Per spec, dictionary objects should be loaded in lexicographical order (a). So
the following always pushes `endings` before `type`

```js
  new Blob([], {
    get type()    { order.push('type'); return ''; },
    get endings() { order.push('endings'); return 'transparent'; },
  });
```

This requirement is now enforced by a comptime check. So, a lot of files were
updated to satisfy this requirement.

2-
Blob parts now work with the @@iterator protocol. This is done more generically
(via `value.iterator())` but is currently only used by Blob (and File). Other
types that need this (e.g. URLSearchParams) can be done in a follow up.

3-
Add support for Blob.textStream

4-
Reject XHR/Fetch requests on blob URLs if the method isn't GET

5-
Strip #hash from blob URL when doing lookup

All of this fixes ~175 FileAPI WPT cases, though it's possible #1 (the
dictionary ordering) helps with a few others.

(a) https://webidl.spec.whatwg.org/#js-dictionary
2026-08-20 13:57:51 +08:00
Pierre Tachoire 067709bb58 cdp: add obeyRobots to lp.configureCDP 2026-08-18 17:07:18 +02:00
Karl Seguin d3c26f589e Merge pull request #3219 from lightpanda-io/sec-ch-ua-full-version
send Sec-Ch-Ua-Full-Version-List header
2026-08-18 20:00:44 +08:00
Pierre Tachoire 9ff1ad8306 fix header key case for Sec-Ch-Ua* 2026-08-18 12:25:40 +02:00
Pierre Tachoire a961156283 send Sec-Ch-Ua-Full-Version-List header
Add Sec-Ch-Ua-Full-Version-List header with the full LP version

```
Sec-Ch-Ua-Full-Version-List: "Lightpanda";v="1.0.0-dev.8713+33867c727"
```
2026-08-18 09:38:00 +02:00
Karl Seguin 5c0aa90ea4 Merge pull request #3187 from lightpanda-io/http-header-option
add --http-header option to send headers on every HTTP requests
2026-08-18 15:24:10 +08:00
Pierre Tachoire 33867c7275 Merge pull request #3116 from lightpanda-io/nikneym/adblocker-init
Initial implementation for easy list parsing and AdBlocker
2026-08-18 08:50:42 +02:00
Pierre Tachoire a6afdce444 add --http-header option to send headers on every HTTP requests 2026-08-17 17:18:13 +02:00
Karl Seguin 737f69ee44 http: improve header overwrite/enforcement
Builds ontop of https://github.com/lightpanda-io/browser/pull/3200 to centralize
header enforcement and standardize merge vs overwrite header logic.

The API is still a `setHeader` and `appendHeader`, with a source, but set/append
both are thin wrappers around private `putHeader`. putHeader blocks overwriting
restricted headers (user-agent). The `source` acts as a priority (ordered enum)
which further restricts the header AND depending on whether set or append were
called, controls if the value is overwritten or appended to.

3200 had an always-append which can cause problems, e.g. a script setting
Accept-Language: fr would have results in the value being appended to the
default, e.g.: 'en-US,en;q=0.9, fr'.
2026-08-15 12:09:08 +08:00
Pierre Tachoire dd83300095 htttp: add Transfer.appendHeader
and make transfer.addHeader private.
2026-08-14 16:33:49 +02:00
Pierre Tachoire 6e72441001 make Sec-Ch-Ua not modifiable via cdp 2026-08-14 16:05:19 +02:00
Pierre Tachoire 80e45ab016 apply user-agent validation rules on request intercepted 2026-08-14 12:26:33 +02:00
Muki Kiboigo fb5a9b6a35 get rid of allocator stored in RobotsGate 2026-08-13 08:20:15 -07:00
Halil Durak c4b0b7cc33 HttpClient: check the adblocker inside isUrlBlocked` 2026-08-13 16:39:16 +03:00
Halil Durak c111fc5675 load and parse block list once and share between HTTP clients 2026-08-13 16:39:14 +03:00
Halil Durak 835cf8917b update tests 2026-08-13 16:39:13 +03:00
Halil Durak b1b9a64573 CLI option for adblock list passing + integrate adblocker to http client 2026-08-13 16:39:13 +03:00
Muki Kiboigo f7e6464370 SingleFlight should own the key 2026-08-13 00:25:33 -07:00
Muki Kiboigo 82e9496409 use SingleFlight in RobotsGate 2026-08-12 18:04:04 -07:00
Scott Taylor ba01f0a963 cdp: scope redirect response to redirect events
Assisted-By: devx/c10f9997-2afd-4688-a7fa-f3839c4cc22e
2026-08-11 14:24:57 -04:00
Scott Taylor ff975b106f cdp: report redirect chains before interception
Assisted-By: devx/c10f9997-2afd-4688-a7fa-f3839c4cc22e
2026-08-11 14:15:09 -04:00
Karl Seguin abc6f1ef76 http: recalculate Referer header on each redirect
On a redirect, recalculate the Referer header based on the new target.

Also, allow SVG anchors to be clicked (doesn't seem related, but it came up
in referrer-policy WPT tests).
2026-08-07 16:19:41 +08:00
Karl Seguin 7c89a462eb cdp: send request information (RI) notifications on redirect
Extracted from https://github.com/lightpanda-io/browser/pull/3122. Sends RI for
redirect. Also, on a continueRequest which does redirect, restores the original
headers (continueRequest's headers are only valid for a single request).

To make this work in all drivers, CDP now decouples the transfer_id from the
intercept_id. Each unique request gets a distinct intercept_id which is managed
in CDP (with a intercept_id -> transfer_id mapping).
2026-08-06 06:53:54 +08:00
Karl Seguin b691603823 Merge pull request #3135 from lightpanda-io/ensureTotalCapacityPrecise
mem: prefer ensureTotalCapacityPrecise to reduce memory usage
2026-08-05 08:44:32 +08:00
Karl Seguin c86d969ce0 mem: prefer ensureTotalCapacityPrecise to reduce memory usage
When we know the precise final length, prefer ensureTotalCapacityPrecise over
ensureTotalCapacity. The latter goes through `growCapacity` which will allocate
~1.5x padding.
2026-08-04 17:44:05 +08:00
Karl Seguin d4642d8afc http: redirect even on missing close_notify
We already had special handling for BoringSSL's RecvError on improperly closed
TLS connection. This moves the handling up, so that redirect handling is
covered by it too.
2026-08-04 17:37:07 +08:00
Muki Kiboigo 7d6299895f fix minor compilation issues 2026-08-03 18:26:58 -07:00
Muki Kiboigo 0b74224b15 use CachePutRequest for puts instead of CacheMetadata 2026-08-03 18:26:57 -07:00
Muki Kiboigo 6c56144ef9 rework get to be strictly deferred 2026-08-03 18:26:12 -07:00
Muki Kiboigo 84405ad930 remove cache eviction path from HttpClient 2026-08-03 18:17:44 -07:00
Muki Kiboigo 94c029ff32 get rid of file variant in CachedData 2026-08-03 18:17:43 -07:00
Muki Kiboigo 0f2957cda2 add SqliteCache as default local impl 2026-08-03 18:17:40 -07:00
Karl Seguin fd2e6a8512 refactor: rework how httpclient headers work
Adding headers to an HTTP request was a bit awkward due to my desire to avoid
having an intermediate representation (e.g. an ArrayList(Header)). Going
straight to a curl slist avoids double-copying the headers (first to Zig, then
to curl).

But the CORS work (https://github.com/lightpanda-io/browser/pull/3002) showcases
that this micro-optimization simply isn't worth it, since it needs that
intermediate representation anyways.

And, this change isn't just for CORS. Headers have been a silly pain in the past
like unclear ownership, and messy APIs used in _a lot_ of places (WebBotAuth,
WebSocket, Fetch, ...)

This new approach stores headers on the transfer in an ArrayList. The API is:

```
const transfer = try client.newRequest(.{...}, owner);
{
    errdefer transfer.deinit();
    try transfer.addHeader("Over", "9000", .{});
}
try transfer.submit();
```

This:
1 - Eliminates ambiguity about errdefer cleanup responsibility
2 - Eliminates a bunch of stringZ concat that Frame, Config, CDP were doing
3 - Transfer.arena is now available for headers
2026-08-03 18:26:32 +08:00
Karl Seguin 6a83881634 chore: add lp.IS_DEBUG and lp.IS_TEST
Change all users to builtin.mode and built.is_test
2026-08-01 09:15:18 +08:00
Karl Seguin 2bd9848c07 mem: improve ArenaPool usage
1 - Add a metric to track the number of inlight arenas from the pool
2 - Script now use 2 arenas:
    - An initial (small) one for the script
    - A sized one for the body
    Should result in less pressure on our limited .large arenas
3 - DOMPoint and DOMPointRO are now arena free (they live on the slab only)
4 - TextDecoder no longer accumulate garbage in its arena
5 - Response object is much better at picking its arena size, rather than just
    using a .large
2026-07-31 14:36:22 +08:00
Karl Seguin bdce49a4b5 refactor: Introduce Arena wrapper
Introduces a ArenaAllocator wrappre (lp.Arena). This is groundwork for better
memory tracking and reporting memory usage to v8. This is almost purely a
mechanical change to lay a foundation for a follow up PR that will address
https://github.com/lightpanda-io/browser/issues/3027

Some code became a bit leaner: a pooled arena can release itself (it has a
reference to the ArenaPool).

Some code became uglier: The Frame has a `_local_arena: *lp.Arena` and a
`local_arena: Allocator` (same with call_arena, and same with a few other types)
so that consumers aren't impacted (they continue to use `frame.local_arena`).
2026-07-30 13:02:13 +08:00
Karl Seguin dcb98853b9 chore: make our use of clock/timestamp more consistent
Zig 0.16 changed clocks/timestamps. Our migration to Zig 0.16 took the path of
least resistance. For example, we kept 'monotonic' and 'real' even though Zig
0.16 renamed them to 'boot' and 'clock'

This commit tries to standardize all timestamp usage to: lp.datetime.timestamp
and lp.datetime.milliTimestamp using the new zig 0.16 names ('boot' and 'clock')
2026-07-27 09:28:48 +08:00