Will have to come up with a solution for search getter/setter and URLSearchParams still; We've also encountered with a bug in URLSearchParams, a fix for it will also be included in the second phase.
A synthetic Tab delivered via Input.dispatchKeyEvent did not move
document.activeElement. Two gaps in Frame.zig caused this: handleKeydown
(the keydown default-action handler) had no Tab branch, and triggerKeyboard
dropped the keydown entirely when nothing was focused — it read the raw
_active_element field, which is null until an element is explicitly focused.
The first Tab on a page therefore went nowhere, and keyboard focus traversal
was impossible over CDP.
Dispatch the keydown to the effective active element (getActiveElement(),
which resolves to <body> when nothing is focused) so the event fires and its
default action can run, and add a Tab branch to handleKeydown that performs
HTML sequential focus navigation: move focus to the next (Shift+Tab:
previous) focusable element ordered by tabindex, then document position.
The order is computed from tabindex + tree position, so no layout is needed.
Closes#2699
If the comptime snapshot isn't valid, we currently create the snapshot on the
fly (as if -Dsnapshot_path wasn't specified). This change now returns an error.
This eliminates a good chunk of code when -Dsnapshot_path. It replaces a silent
fallback with a hard-fail. The advantage is that it's explicit..if you specify
-Dsnapshot_path you either use the snapshot or it fails.
Note: Snapshot.create came up when analyzing the binary as being particularly
big. But in our release build, it's dead code. I didn't expect it to change
RSS, but I thought it couldn't hurt to try, and in the end, I like this change
anyways.
* ci: raise cdp bench MAX_VmHWM to 29000
The agent branch grew .text by ~2.8MB (mostly std monomorphization from
the new script/agent modules); none of it executes in serve mode and
anonymous/heap memory is byte-identical to main (716-724KB Private_Dirty
across main, agent-dev, and a build with the agent code compiled out).
The VmHWM delta is file-backed pages of the binary: the kernel maps them
in large readahead/THP chunks around each touched page, so peak RSS
shifts with link layout on every relink. The agent-less test build
measured 4.2MB *below* main while running the identical serve path,
purely from folio/window boundaries moving. At 28000 the gate was
failing on layout noise (28028-28064), not a regression.
* agent: improve docs agent_script
* Revert "ci: raise cdp bench MAX_VmHWM to 29000"
This reverts commit b6b704d43e.
---------
Co-authored-by: Adrià Arrufat <adria.arrufat@gmail.com>
The default viewport dimensions were duplicated across six independent
sites. Point window.innerWidth/innerHeight, screen.width/height/availWidth,
visualViewport.width/height, Page.getLayoutMetrics and the
IntersectionObserver root rect at the single MediaQuery.Viewport.default
(which already documents itself as the rewire point).
No behavior change: every site keeps the same 1920x1080 values, now from
one source. This is the groundwork requested on #2664 so a future
Emulation.setDeviceMetricsOverride can move all of them together.
Similar to https://github.com/lightpanda-io/browser/pull/2675. That PR added
support for rel=preload, this one adds it for rel=modulepreload. The impact here
is generally less significant. Modules were already asynchronously preloaded
as part of the module-loading flow. What this does is potentially start the
preload earlier (i.e. when the link is encountered). You can imagine:
// pseudo-html
<link rel=modulepreload href=mod1.js>
<link rel=modulepreload href=mod2.j2>
<script src=s1.js></script>
<script src=s2.js></script>
If s1.js imports mod1 and mod2, then there won't be a huge difference...I mean
mod1 and mod2 can start loading before s1.js is complete, but it won't be huge.
If s1.js doesn't import mod1 and/or mod2, but s2.js does, then the gain is a
little more (because now we have to wait for both s1 and s2 to load). So it
really depends.
This commit also better manages preloaded scripts. There were common cases where
a preloaded script might remain preloaded until page teardown..well past its
actual usage. This happened because, while every preload increments the waiters
count, only the first to fetch it decrements it. Once cached, waiters was never
decremented. This is now fixed.
Experiment to see if this shrinks the build by any significant amount. Some
investigation did surface this as some of the code we control directly which
did stand out.
This commit is in the same vein as 0d9482ccbf. A
dynamic async script which completes during an evalute() does not evaluate if
`is_evaluating == true`. That's good, but we need to make sure that it _does_
eventually get evaluated. As-is, we rely on a done callback to call evaluate()
again which works for all but the last script.
This commit creates a more robust reentrancy flow. is_evaluating still guards
against reentrancy, but a new flag, `evaluate_pending` is set to true. Whenever
`is_evaluating` is set to false if `evaluate_pending` is true, we evaluate().
Similalry, during evaluate(), we better handle completed scripts during
evaluate() and process them immediately (via an outer loop).
- DataTransferItem/DataTransferItemList/Iterator forward acquireRef/releaseRef
to the owning DataTransfer, so its pooled arena outlives any JS-held wrapper
(fixes a potential use-after-free when JS keeps an item/list/iterator alive
past the DataTransfer).
- addItem reads strings straight into the persistent arena via
toStringSliceWithAlloc, removing the intermediate call_arena copy.
- normalizeFormat uses std.ascii.allocLowerString instead of dupe + lowerString.
- setData: rename dup -> owned_data for clarity.
Move console message listener registration out of Session initialization
into an explicit `enableConsoleCapture` method. This avoids buffering
console logs when they are not needed.
This was driven by various WPT tests in the /shadow-dom/ category. There are
4 distinct changes.
1. Template hooks into "cloned" to include the _content. This change required
passing `deep: bool` which is why TextArea and Input are also changed (they
ignore that new parameter)
2. Node.getRootNode and Node.ownerDocument will now traverse through the
ShadowRoot to find the root/document
3. DOM events won't gain the Window when triggered from within a ShadowRoot
4. attachShadow now takes a full option, not just a string mode. This also
touched a few different places since it's called internally too.
* Revert "agent: enhance /save progress and verification feedback"
This reverts commit 54f467d1fa.
* Revert "agent: verify synthesized scripts during /save"
This reverts commit b141da30ca.
* agent: extract save helpers to save.zig
Moves pure helper functions related to the `/save` command (parsing,
validation, file writing, prompt shaping) from `Agent.zig` to a
dedicated `save.zig` module.
Introduces a multi-step synthesis process for `/save` that derives a
logical JSON output schema and uses a dry-run runtime to verify
candidate scripts. The LLM can now run and self-correct its scripts
using a new `run_script` tool before finalizing the save.