Terminal.zig references md_term and prompt_assist from a test block, but
nothing referenced Terminal, so those 30-odd tests never ran. Adding it
to Agent.zig's discovery block surfaced one rotted test sink in
js_highlight.zig still using ArrayList.writer(), ported to
Io.Writer.Allocating.
Similar to https://github.com/lightpanda-io/browser/pull/3289.
This pattern:
```zig
errdefer freesomething()
try transfer.submit();
```
is dangerous.`sumbit()` guarantees that the errorCallback is called on any
error. So if the transfer's errorCallback also does `freesomething()` then we
end up with a double-free.
The code was generally cleaned up to be:
```zig
{
errdefer freesomething();
try transfer.addHeader(....);
}
transfer.submit() catch {};
```
Mutating a searchParam that was created from a url.searchParams now keeps the
URL in sync. This helps ensure the that url.search keeps its original form.
Improves a WPT url-searchparams.any.html and urlsearchparams-stringifier along
with a few other cases.
By default, iframes and workers no longer loaded. Use `--load-resources iframe`
and `--load-resources worker` to restore the previous behavior. The disabling
makes resource loading more consistent.
To further make things more consistent, Config seems the following changes:
1. remove `--timeout` from `serve` which does nothing but has printed a
deprecation warning for a long time
2. added .deprecated field to CLI config flags which now logs the specified
deprecated warning when used
3. `--log-filter-scopes` is deprecated in favor of `--log-scopes`
4. `--disable_subframes` is deprecated. Iframe loading is disabled by default,
use `--load-resources iframe` to enable iframe loading
5. `--disable_workers` is deprecated. Worker loading is disabled by default,
use `--load-resources worker` to enable worker loading
6. `--enable_external_stylesheets` is deprecated. Stylesheets remain disabled
by default. Use `--load-resources stylesheet` to enable loading external
stylesheets
CLI log parameters now alter the logger behavior on parse. This helps minimze
the window where default log settings are in-play. It also means things like
this work:
```
./lightpanda --log-level fatal --disable_subframes --log-level warn
```
More seriously, there's now an optional `beforeParse` fired once the mode is
known. This is used by mcp to set the default log level to logfmt. Previously
this was done much later and could easily result in a mix of pretty and logfmt
logs.
The agent section still listed the provider set from a few releases ago,
omitting Vercel AI Gateway, Mistral, llama.cpp and OPENAI_BASE_URL-based
OpenAI-compatible endpoints. Add them with examples, plus --list-models.
Prompted by #3290.
Mimic's https://github.com/lightpanda-io/browser/pull/3294
I looked into this a little bit, and the main issue is that we build the binary
in releasefast twice: once for the snapshot and once for the browser itself.
Each build takes ~10 minutes.
The snapshot cache almost always misses (since any change to webapi/*
invalidates it). I don't see a great solution.
A trusted backspace/delete or printable character now:
1 - fires beforeinput and textInput (which can cancel the edit)
2 - change the input's value
Input and TextArea share enough in common and this change has enough selection
logic that a new text_entry.zig helper is added to implement the shared logic.
Review feedback: markdown caps its own output through Opts.max_bytes while
the html dump left it to each caller, so the html tool and fetch each
carried a copy of the LimitedWriter wrapping. root and deep now do it,
with a no-cap fast path so innerHTML/outerHTML are unaffected.
A wait failure on one URL aborted the whole multi-URL fetch with no
output, the wait_ms budget was computed once before the loop so N pages
could take N times the budget, navigation failures exited 0 with an empty
dump, and HTTP 4xx/5xx were indistinguishable from success by exit code.
Each page now has its own error slot: wait, navigation and dump failures
are recorded there instead of returned, every page is still written (the
JSON envelope carries the name under "error"), then the first failure is
returned so the process exits 1. The remaining budget is recomputed per
page. --fail-on-http-error turns a status >= 400 into exit 22, curl's
code for the same condition; the dump is written first either way.
--strip-mode was silently ignored for --dump markdown, and fetch had no
way to scope a dump to one element or cap its size although the markdown
and html tools have both.
--selector dumps the first matching element in any dump mode, --max-bytes
caps html and markdown with the tools' truncation marker, and markdown
now honors strip ui (images; scripts, styles and hidden elements are
never rendered, so the other groups don't apply).
The links tool returned every a[href] verbatim: hidden nav entries,
one row per duplicate href, and null text for image and icon links even
though markdown already knows to use alt. Nav-heavy pages produced
thousands of rows for an agent looking for one link.
One entry per resolved href (the first, upgraded with text from a later
duplicate), hidden anchors skipped with the same check tree uses, text
falling back to aria-label, title, then a descendant img alt. The tool
gains an optional limit.
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.
A worker gets a distinct Navigator type (WorkerNavigator) which only exposes
a subset of what Navigator does.
Previously, we achieved this by exposing Navigator but with a bunch of accessors
/ functions with .{.exposed = .window}. That worked fine, except the type name
was still "Navigator". This introduces an actual WorkerNavigator.