Commit Graph
947 Commits
Author SHA1 Message Date
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 5c1c2a1b8b Merge pull request #3150 from lightpanda-io/cdp-post-data
cdp: add request post data
2026-08-08 08:14:52 +08:00
Karl Seguin d35aa90959 fix build 2026-08-07 12:00:05 +08:00
Karl Seguin 63a4283989 reset arena after use, verify user input 2026-08-07 11:45:50 +08:00
Halil Durak 92b1eae4c7 introduce header_parser.parseRequest 2026-08-06 19:16:59 +03:00
Halil Durak 46ce6cc1dc rework Connection.upgrade with header_parser 2026-08-06 19:16:58 +03:00
Karl Seguin 93bcf5c93a cdp: add request post data
Fixes https://github.com/lightpanda-io/browser/issues/3141

We now capture request body provided they are <= 64KB (arbitrary limit, we can
revisit, but this doesn't seem to be an overly common request and this pins
the bodies in memory until frame end, so I wanted to take it slowly).

Adds Network.getRequestPostData and the `postData` and the `postDataEntries`
fields to the Request object.
2026-08-06 18:44:59 +08:00
Adrià Arrufat f55aa1a669 Merge pull request #3140 from lightpanda-io/goto-waituntil
goto: optional waitUntil + dcl-gated selector waits
2026-08-06 07:32:05 +02: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 835b3e1e01 Merge pull request #3144 from lightpanda-io/custom-element-creation
Custom element creation
2026-08-06 06:48:51 +08:00
Karl Seguin 390c5c0e2d Merge pull request #3122 from staylor/fix/playwright-cdp-session-routing
Fix Playwright auxiliary CDP session interception
2026-08-06 06:48:07 +08:00
Adrià Arrufat 17c30c3a52 Merge branch 'main' into goto-waituntil 2026-08-05 13:08:23 +02:00
Karl Seguin 83db6a394d Simplify termination tracking, remove undefined.
1. Every `var caught: js.TryCatch.Caught = undefined;` is now defaulted to .{}.
   This eliminates a possible dirty read. Function tryCall (and its variants)
   were guarding against this, but newInstance wasn't.

2. Env.terminate() now immediately sets `terminate_requested` which means
   `isExecutionTerminating` is removed and only `terminatePending` exists, and
   it only needs to check `terminate_requested`.
2026-08-05 16:51:43 +08:00
Adrià Arrufat c793ea8c0f cdp: LP.waitForSelector shares the state-dependent wait default
Review flag: the dcl gating in actions.waitForSelector also changed the CDP
extension, which kept a flat 5s default. It now uses the same rule as the
tool layer (5s at load, 15s before), so a mid-navigation call keeps the wall
budget it had when the pre-wait ran to load. Explicit timeouts unchanged.
2026-08-05 09:11:08 +02:00
Karl Seguin f9071d1cf8 split PR, fix non-playwright drivers
As-is, this PR (3122) includes 2 distinct fixes:
1 - a Target.attachToTarget should create a distinct session_id
2 - http redirects with request interception (RI) should:
    a - not preserve the original RI headers, and
    b - should send their own RI request to the driver

This commit removes #2 so that it can be done in its own follow up. #2 is
relatively big. The commit also removes the integration test and CI changes.
These will be ported to the demo project to leverage the existing CI flow.

3122 breaks non-playwright drivers on both features. #2, will be addressed
in the follow up PR. For #1, when attachToTarget is called when bc.session_id
is null, then the existing behavior is maintained. This happens for example,
with chromedp which doesn't autoAttach.
2026-08-05 10:59:20 +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 850004d088 Merge pull request #3132 from lightpanda-io/dedupe-isolated-worlds
cdp: avoid creating duplicate isolated worlds
2026-08-05 08:43:37 +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 aa22b7feea cdp: avoid creating duplicate isolated worlds
If a driver asks to create an isolated world that already exists, don't create
it, return the existing one.
2026-08-04 14:27:15 +08:00
Karl Seguin 83e47447b5 perf: Reduce memory pressure notification to v8
Only notify v8 of memory pressure when (a) there's memory to claim and (b)
there are dead context.

Also clean up code that relied on undefined behavior which might have left
local scopes un-freed and caused a v8 leak.
2026-08-04 12:18:31 +08:00
Scott Taylor caaf53dc9f Fix Playwright CDP session interception routing
Assisted-By: devx/e284dddf-2391-42ce-9dff-5ce418d0ab2f
2026-08-03 23:13:46 -04:00
Karl Seguin 5f88b33ed6 Merge pull request #3118 from lightpanda-io/refactor-http-client-headers
refactor: rework how httpclient headers work
2026-08-04 06:42:10 +08:00
Karl Seguin f5c40da81c Merge pull request #3111 from lightpanda-io/cdp-json-protocol
cdp: add /json/protocol endpoint
2026-08-04 06:41:55 +08:00
Karl Seguin 1d5a25bf4e remove reference to generator (didn't like it, don't want to include it) 2026-08-03 18:48:40 +08: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 f4783d8fcc cdp: add /json/protocol endpoint
https://krabarena.com/claims/browserless-exposes-57-cdp-domains-for-discovery-lightpanda-s-endpoint-is-a-404
2026-08-03 15:51:42 +08:00
Karl Seguin 7db42891a7 mem: Switch Node's _type to a bare tag
Alignment allowing (1) this reduces Node size by 8 bytes. It also aligns with
previous cdata changes with the end-goal to have the entire Node chain adopt
bare tags.

(1) string.String is 16-byte aligned, so Text doesn't shrink with this change.
Hopefully this can be addressed separately.
2026-08-03 12:19:41 +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 c726b022e8 tests: improve test output and test log handling
1 - TEST_VERBOSE is now off by default
2 - There's a afterEach callback that is automatically run after each tests, it:
     a - clears the log filters
     b - resets the test arena
3 - LogFilter replace with
     a - testing.silenceLog(&.{...scopes...}); to silence all logs for the given
         scopes.
     b - testing.expectLog(&.{...scopes}); to set log expectations, 1 per log.
         The goal here isn't so much to expect logs (though, you can do that),
         but rather to silence an expected # of logs, without silencing more.
2026-07-31 07:30:25 +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 a1a8fb6dc3 design: TaggedOpaque fromJS is now offset based
As part of the ongoing effort to remove the `_proto: *Parent` field,
TaggedOpaque.fromJS is now offset based. Technically this should perform better
since we're no longer walking through pointers. But the real goal is that we
can now start removing _proto fields.

But, for fromJS to be offset-based, we had to make sure every prototype chain
was a contiguous allocation. The Factory did this, but not everything used the
factory. Now, everything does. This change alone, without the fromJS change,
made every WebAPI allocation more consistent.
2026-07-29 10:34:03 +08:00
Karl Seguin 678971e320 design: rework cdata _type field
Ultimately, our goal is to remove the `_proto: *Field`. That would save 24
bytes per Text node (or Element, ...). Large websites have 20K+ nodes, so we're
talking 300-500KB savings.

ef756b0c96 was the first phase of this. This is
the second, and it's targetting at CData for a simple reason: CData currently
has an optimization that makes removal of `_proto: *Field` difficult: it
directly embeds its empty types (most notably, Text). Zig's @offsetOf doesn't
work on tagged unions, so we'd have to jump through hoops to figure it out (it
is doable though). Also, CData has a "incorrect" flattened CDATASection
specifically so that Text doesn't inherit a _type union..so that's another
problem.

The solution is to move to bare unions, which allows us to use our Factory
to control the layout of the CData and thus have predictable offsets.

CData is now an inconsistent with the rest, but, at the very least, all Node
types will move in this direction.
2026-07-29 10:34:03 +08:00
Karl Seguin 5fe387a46a Merge pull request #3065 from lightpanda-io/remove-sendMessageToTarget-assertion
crash: remove Target.sendMessageToTarget session_id assertion
2026-07-28 09:23:51 +08:00
Karl Seguin cc33bb38d1 Merge pull request #3061 from lightpanda-io/consistent-clocks
chore: make our use of clock/timestamp more consistent
2026-07-28 09:20:18 +08:00
Karl Seguin 708835b08b crash: remove Target.sendMessageToTarget session_id assertion
closeTarget above implies that the state this assertion guards against IS valid
AND we just had a crash report confirming. That's enough for me to remove it.
2026-07-27 18:56:29 +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
Karl Seguin 6716f1c12a chore: Replace deprecated MemoryPool with Managed Memory Pool 2026-07-27 07:56:30 +08:00
Karl Seguin 5acfd38250 Improve CDP response event data
Give accurate connectionId, connectionReused, initialPriority and securityState
values.

Always set `referrerPolicy` to `unsafe-url` as the most honest answer (we should
implement proper referrer policy!).

For workers, track the underlying frame_id so that it can be used for the
`documentURL` field.
2026-07-25 11:36:13 +08:00
Ppsoft1991 e3ec937f78 cdp: emit worker network requests
Keep worker requests visible on the page CDP session when their WorkerGlobalScope frame id is absent from the document frame tree. Add a regression fixture covering the worker script and a fetch from inside the worker.
2026-07-25 08:01:04 +08:00
Ppsoft1991 39981f2534 cdp: complete Network event payloads
Add required timestamp, type, request, response, and timing fields so strict CDP clients can deserialize emitted events.
2026-07-25 07:37:53 +08:00
Karl Seguin ed9a25f470 fix test 2026-07-24 10:18:59 +08:00
Karl Seguin 2b945aa1f9 cdp: ignore duplicate enable calls
CDP driver can send multiple Network.enable which would register the same
listener multiple times. This commit makes it so that only one (the first)
callback registered for a listener+eventtype is used. Subsequent registration
for the same listener+eventtype are ignored. This is safe because all callbacks
are currently static. It's a mistake (enforced by a debug-only assertion) for
code to try to register a different callback for an already registered listener+
eventtype.

This generalizes https://github.com/lightpanda-io/browser/pull/3038
2026-07-24 08:20:32 +08:00
Karl Seguin 8fbcc7e5c1 Merge pull request #3015 from lightpanda-io/cdp-utf8-sanitization
cdp: Sanitize non-UTF 8 values
2026-07-24 08:03:38 +08:00
Matt Van Horn dee40075a0 feat(cdp): implement Network.setBlockedURLs via urlPatterns
Reimplement request blocking on the non-deprecated urlPatterns shape:
each pattern carries an explicit block/allow flag (first match wins),
UrlBlocklist owns the compiled patterns plus their block flags, and the
legacy setBlockedUrls path stays for back-compat. Tests updated.
2026-07-23 12:15:49 +02:00
Matt Van Horn 311ab3aaae feat(cdp): add Network.setBlockedURLs and --block-urls request blocking 2026-07-23 12:15:47 +02:00
Karl Seguin 6374dab634 refactor: Use JSON writer to serialize CDP Frame
This has the benefit of avoiding a few arena dupes, but those were small. The
real benefit is consistency with the rest of the code.
2026-07-23 12:22:24 +08:00
Ppsoft1991 f88564b56d cdp: expose child frame metadata
Include parentId on child frame navigation events and recursively serialize child frames in Page.getFrameTree using their live frame and loader IDs.

Fixes #3014
2026-07-23 12:08:45 +08:00
Karl Seguin 8f562330c8 perf: Improve Runner tick signaling on macrotask-only wait
Currently, Runner assumes that HttpClient.tick did something. But it's possible
that HttpClient had nothing to do, and thus didn't poll. In that case, Runner
would return .{.ok = 0} and Runner's caller would also certainly call
Runner.tick again, resulting in a spin-loop.

The reason Runner allows this to happen is because it can still have macrotasks
to run. So now, when HttpClient.tick has done nothing, Runner will return its
ms_to_next_task, rather than 0.

On sites where all i/o is completed, and only macrotasks are waiting, this
significantly reduces CPU usage.
2026-07-23 07:28:32 +08:00