Commit Graph
9609 Commits
Author SHA1 Message Date
Karl Seguin ee4d54928d webdriver: increase http default / max limit
The http max default was 4K with a 16KB hard limit. The default limit is now 1MB
with an initial default of 4K. This is to accommodate larger WebDriver payloads.
2026-09-21 17:52:41 +08:00
Karl Seguin b1ffc164a9 Merge pull request #3574 from lightpanda-io/orderfile-regen
orderfile: regenerate the hot-code profile
2026-09-19 09:18:44 +08:00
github-actions[bot] d70045ba6d orderfile: regenerate the hot-code profile
hot set 15072KB resident at 4KB fault-around: 21264 text, 21413 rodata symbols
2026-09-19 01:04:00 +00:00
Karl Seguin d5ba56eaf9 Merge pull request #3565 from lightpanda-io/isSecureContext
webapi: more accurate window.isSecureContext
2026-09-19 07:52:39 +08:00
Karl Seguin 7cb98ad977 webapi: more accurate window.isSecureContext
Previously, our window.isSecureContext was hard-coded to false. This commit
(a) reports the correct value and (b) disables [some] secure-context-only APIs
in a non-secure context. This change is somewhat related to the ongoing Service
Worker work and will need to be adjusted accordingly, e.g. when #3562 lands,
the Cache will need to be disabled when isSecureContext == false.
2026-09-19 07:28:14 +08:00
Karl Seguin ae928a91b1 Merge pull request #3568 from lightpanda-io/speedup-unit-tests
dev: speedup unit tests
2026-09-19 07:13:56 +08:00
Karl Seguin 268931092b Merge pull request #3566 from lightpanda-io/CDP-frame-ownership
internal: CDP Node / Element frame ownership
2026-09-19 07:13:45 +08:00
Karl Seguin 21ca960dd6 Merge pull request #3564 from lightpanda-io/fetch-metadata
webapi: include Sec-Fetch-Site and Sec-Fetch-Mode headers
2026-09-19 07:13:28 +08:00
Karl Seguin ff3116432d Merge pull request #3562 from lightpanda-io/service-worker-cachestore
WebApi: Add Cache/CacheStore when ServiceWorker is enabled
2026-09-19 07:13:16 +08:00
Karl Seguin ce409c244f Merge pull request #3558 from lightpanda-io/cdp-frame-owner
cdp: DOM.getFrameOwner returns the owner <iframe>, nodes carry frameId
2026-09-18 16:45:04 +08:00
Adrià Arrufat dcc90d60c9 cdp: emit frameId on the document element, not the document node
Chrome sets frameId on frame-owner elements and on the element whose
parent is the document, never on the document node itself.
2026-09-18 10:00:37 +02:00
Adrià Arrufat acb6b835fe cdp: DOM.getFrameOwner returns the owner <iframe>, nodes carry frameId
DOM.getFrameOwner answered with the child frame's document instead of the
element hosting it. Clients that map an <iframe> to its frame compare the
backendNodeId it returns with the one they resolved in the parent
(Stagehand's frameLocator/deepLocator, Playwright's contentFrame), so the
lookup never matched and they could not descend into frames.

Return the owner element, as Chrome does, and error for the main frame.
The node writer now emits frameId on frame-owner elements and on document
nodes, which is the other half of that pairing.
2026-09-18 10:00:37 +02:00
Adrià Arrufat e56045f4bf Merge pull request #3560 from lightpanda-io/agent-repl-simplify
agent: REPL output fixes and command dispatch simplification
2026-09-18 09:51:49 +02:00
Karl Seguin e2299e2c05 dev: speedup unit tests
Directly improve a couple slow tests (crash_handler actually generating crash
dumps on some systems, e.g. mine). The runWebApiTest prefers to poll for work
when possible rather than a blind sleep -> check loop. (e.g. if we have
websocket connections, prefer an http tick).

For me, it's 22s -> 17s.
2026-09-18 15:17:39 +08:00
Karl Seguin b3684847a8 internal: CDP Node / Element frame ownership
Continuation of cleaning up frame ownership (#3549, #3536, #3520, ...).

Element.blur/focus are noop on a frameless element.

AXNode.Writer rejects frameless nodes. DOM.resolveNodes keeps its fallback
bacause it's stateless - just needs the context.
2026-09-18 13:14:28 +08:00
Karl Seguin f70705b2ce webapi: include Sec-Fetch-Site and Sec-Fetch-Mode headers 2026-09-18 12:34:19 +08:00
Karl Seguin e3aa36f83a Merge pull request #3563 from lightpanda-io/wpt-build-fix
fix build for wpt_extensions
2026-09-18 11:11:59 +08:00
Karl Seguin 50c4f52df8 fix build for wpt_extensions 2026-09-18 11:11:36 +08:00
Karl Seguin 4d1d5f1291 Merge pull request #3561 from lightpanda-io/orderfile-regen
orderfile: regenerate the hot-code profile
2026-09-18 09:25:35 +08:00
Karl Seguin b43c6087b7 WebApi: Add Cache/CacheStore when ServiceWorker is enabled
This adds the Cache and CacheStore APIs when ServiceWorker is enabled. Purely
in-memory, tied to the Session's lifetime. These generally don't do unbounded
growth, but simply load a fixed set of resources.

In firefox, when ServiceWorker is disabled, the cache is still available on the
Window. I tied it to the existing --experimental-features serviceworker flag
(at least for now).
2026-09-18 09:20:47 +08:00
github-actions[bot] b275a3960c orderfile: regenerate the hot-code profile
hot set 15196KB resident at 4KB fault-around: 21450 text, 21408 rodata symbols
2026-09-18 01:05:13 +00:00
Karl Seguin 6db04f694a Merge pull request #3548 from lightpanda-io/img-srcset
webapi: img srcset support
2026-09-18 08:04:21 +08:00
Karl Seguin 790a6e5bb9 hook up child srcset when created via fragment parser 2026-09-18 06:49:58 +08:00
Adrià Arrufat 290e4f81d9 agent: simplify REPL command dispatch and provider bookkeeping
- `available_providers` holds the static enum tag names; drop the dupe
  loop, its errdefer and the per-string frees.
- `reconcileModel` returns `error.ModelNotAvailable` directly instead of
  a `use`/`abort` union the caller only mapped to that same error.
- `runCommand`/`printCommandResult` take `Command.ToolCall`; the caller
  already has it, so the unreachable "no tool mapping" branches go.
- `handleSave` reuses `rememberSavePath`, which now propagates its
  allocation failure so a first save under OOM warns instead of
  unwrapping a null `save_path`.
- `SlashCommand.all_names` is a comptime `++` of the three name lists.
- `buildUserMessageParts` reads the attachment once for both text and
  image, and prepends the text part instead of copying the list.
- `printSeverity`/`formatBulletLine` use `allocPrint` and the shared
  `emitStderr`; drop an unreachable `ends_ws` check in `renderMetaHint`.
2026-09-18 00:45:55 +02:00
Adrià Arrufat 9b7225b580 agent: don't drop REPL tool lines or cut result text mid-codepoint
In a REPL whose stderr isn't a tty the spinner is disabled, so
`agentToolDone`'s `emitAbove` returned false and the `● [tool: …]` line
was discarded. `printToolOutcome` already fell back to a raw stderr write
in that case; share that fallback through `emitStderr`.

The non-REPL result line sliced `text` at a byte offset, which could
split a multi-byte codepoint and emit garbage. Truncate on a UTF-8
boundary instead.
2026-09-18 00:44:49 +02:00
Karl Seguin dbe6271479 Merge pull request #3559 from lightpanda-io/fix-preload-import-build
ScriptManagerBase: fix main build after #3485/#3543 merge
2026-09-18 06:31:24 +08:00
Karl Seguin 798d054699 Merge pull request #3542 from lightpanda-io/cdp-device-pixel-ratio-and-char-input
cdp: window.devicePixelRatio from viewport scale and Input char text insertion
2026-09-18 06:29:58 +08:00
Adrià Arrufat 80a526b813 ScriptManagerBase: pass headersForRequest options in preloadImport
#3485 added an options argument to headersForRequest and #3543 added
this call without it. Each merged cleanly on its own; main no longer
builds.
2026-09-18 00:19:04 +02:00
Karl Seguin bd34894996 Merge pull request #3552 from lightpanda-io/webdriver-apis
WebDriver: add various basic WebDriver APIs
2026-09-18 05:54:14 +08:00
Karl Seguin 437a9c27d6 Merge pull request #3543 from lightpanda-io/fix-import-crash
crash: fix a rare import crash
2026-09-18 05:53:27 +08:00
Karl Seguin 3c4e260274 Merge pull request #3557 from lightpanda-io/test-runner-unnamed-slowest
test_runner: keep unnamed tests out of the slowest list
2026-09-18 05:53:14 +08:00
Pierre Tachoire 66e15748a6 Merge pull request #3485 from lightpanda-io/fetch-referrer-policy
Fetch Referrer Policy + CorsGate referrer checking
2026-09-17 18:14:53 +02:00
Adrià Arrufat 4cd522c58a test_runner: no trailing blank line after the summary
Each optional block after the pass count (slowest list, metrics JSON,
failed-test summary) now prints its own leading separator instead of the
previous block printing a trailing one, so the output never ends with an
empty line. Printer.status places the color reset before a trailing
newline so the escape sequence no longer opens the next line.
2026-09-17 17:42:21 +02:00
Adrià Arrufat 5bcea2fc83 test_runner: skip the slowest-tests block when nothing was timed 2026-09-17 17:37:48 +02:00
Adrià Arrufat a39fa8fac6 test_runner: keep unnamed refAllDecls tests out of the slowest list
The Zig 0.16 port of SlowTracker.endTiming dropped the early return for
unnamed tests and discarded the flag, so the refAllDecls blocks were
timed and queued like real tests. With a filter that matches nothing they
were the only candidates and filled the "Slowest 5 tests" output.
2026-09-17 17:36:32 +02:00
Karl Seguin 0afa6aa47b Merge pull request #3554 from lightpanda-io/semantic-tree-frame-coverage
test: child-frame coverage for the JSON tree and the MCP tree tools
2026-09-17 21:15:20 +08:00
Adrià Arrufat 21c2d71e84 input: one key target resolver and shared activation predicates
Every key path resolves its target through user_input.focusedElement,
which is document.activeElement with the <body> fallback. WebDriver and
the MCP press action used to fall back to the document node instead, a
target no default action or char step handles.

The Enter and Space activation rules share isButton, and the text-entry
rule (no text goes into a checkbox or radio) lives on the TextEntry
mixin as acceptsTextEntry rather than as a type test inside the shared
insertion helper. pressKey takes its extra ref only when a keypress will
be built from the keydown.
2026-09-17 14:09:12 +02:00
Adrià Arrufat 7b30a7447e input: activate buttons on Enter's keypress, submit once
Chrome clicks a button on the keypress Enter produces, after the keypress
fires; only links follow Enter on the keydown. Clicking on the keydown put
the click before the keypress and, with the char step also submitting for
button-type inputs, submitted the form twice.

The MCP press action relied on the same char step for Enter, so its own
implicit submission is gone with the double submit it caused on buttons.
2026-09-17 12:45:49 +02:00
Karl Seguin 243ff0b8be Merge pull request #3553 from lightpanda-io/semantic-tree-init
SemanticTree: resolve the owner frame once in init
2026-09-17 18:29:46 +08:00
Adrià Arrufat a6e7767533 test: child-frame coverage for the JSON tree and the MCP tree tools
The #3549 test only covered LP.getSemanticTree's text format. Cover
the JSON format with interactiveOnly on the same fixture, and drive the
MCP tree and nodeDetails tools through call() with a child-frame
backendNodeId. Passing the main frame in either tool now fails the
suite instead of only tripping a debug assert.
2026-09-17 12:28:48 +02:00
Adrià Arrufat a160b8d552 SemanticTree: resolve the owner frame once in init
Every caller resolved node.ownerFrame(frame) before building a
SemanticTree or calling getNodeDetails, and every one made the same
decision on a frameless node. Move that into SemanticTree.init, which
returns error.FramelessNode, and turn getNodeDetails into a method so
it goes through the same constructor.

With init as the only entry point the per-method assertOwns is
redundant, so drop it along with its copy of StyleManager's helper.
2026-09-17 11:59:01 +02:00
Karl Seguin 18dcb8ac63 WebDriver: add various basic WebDriver APIs
Basic stuff that builds ontop of navigate support (https://github.com/lightpanda-io/browser/pull/3538)

The first two already existed. And I added a few more than the last 3, but the
last 3 demo better in a commit message:

```zig
$ curl -X POST "http://localhost:9222/session" --data '{}'
{"value":{"sessionId":"695a066e-4f79-4856-9af9-b92fdf18da7a",....

$ curl -X POST "http://localhost:9222/session/695a066e-4f79-4856-9af9-b92fdf18da7a/url" --data '{"url": "https://lightpanda.io"}'
{"value":null}

$ curl -X GET "http://localhost:9222/session/695a066e-4f79-4856-9af9-b92fdf18da7a/title"
{"value":"Lightpanda | The headless browser"}

$ curl -X GET "http://localhost:9222/session/695a066e-4f79-4856-9af9-b92fdf18da7a/source"
{"value":"<!DOCTYPE html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewpor....

$ curl -X GET "http://localhost:9222/session/695a066e-4f79-4856-9af9-b92fdf18da7a/screenshot"
{"value":"iVBORw0KGgoAAAANSUhEUgAAB4AAAAQ4CAYAAADo08FDAAE/fUl
```
2026-09-17 17:35:07 +08:00
Karl Seguin 1631755f71 Merge pull request #3549 from lightpanda-io/semantic-tree-frame
internal: Always correct SemanticTree context
2026-09-17 17:26:19 +08:00
Karl Seguin 93230fd4aa Merge pull request #3551 from lightpanda-io/interactive-elements-frame
cdp: LP.getInteractiveElements reads the node's own frame
2026-09-17 16:24:23 +08:00
Adrià Arrufat f81d72c0dc cdp: LP.getInteractiveElements reads the node's own frame
A nodeId root inside a child frame was walked with the main frame. The
style checks already resolve the owner frame per element, but the
listener map was built from the main frame's event manager, so
listener-only elements in the iframe were reported non-interactive, and
relative hrefs resolved against the parent's base URL.

Resolve the root's owner frame before the walk, as getSemanticTree and
getNodeDetails do.
2026-09-17 10:05:50 +02:00
Adrià Arrufat 74bf43e732 input: type text in a char step, not in the keydown default action
Follow Chrome's model. A keydown only runs its own default action (Tab,
caret moves, Backspace, Enter activation). Text is typed by the char half
of the press, which fires keypress and then beforeinput/textInput, so
either can veto the edit.

A keyDown carrying `text` runs the char step inline (Puppeteer,
Playwright). A text-less keyDown followed by a `char` message runs it on
the char (chromedp), so each character is typed once. A cancelled
text-less keyDown drops the char that follows it, as Chrome does.

BiDi, WebDriver and the MCP press action go through the same pressKey,
deriving the text from the key. pressKey holds a ref on the keydown for
the keypress it builds, so nothing reads the event after dispatch.
Input.insertText fires beforeinput like a key press does.
2026-09-17 09:53:47 +02:00
Muki Kiboigo b776bad190 add option to headersForRequest 2026-09-16 22:49:49 -07:00
Karl Seguin 582df9a874 Merge pull request #3550 from lightpanda-io/fix-service-worker-log-msg-len
dumb: fix log message length
2026-09-17 13:04:13 +08:00
Karl Seguin 912e6e383e dumb: fix log message length 2026-09-17 12:41:32 +08:00
Karl Seguin 13638ff50b internal: Always correct SemanticTree context
Applies the frame-ownership pass to SemanticTree, copying what we did for
StyleManager (1). SemanticTree doesn't visit iframes, so the frame of the root
is the frame/frame._style_manager we need to target for all visited nodes.

Like #3536, it's up to the callers to (a) get the correct frame and (b) decide
what to do on a frameless-node.

(1) https://github.com/lightpanda-io/browser/pull/3536
2026-09-17 12:13:53 +08:00