fix: address various stability and reliability issues
- Cache stderr TTY check in Config to optimize log hot path.
- Cap signal handler attempts during no-hard-exit.
- Always duplicate URL segments to prevent invalid frees.
- Write live file before backup in atomic writes.
- Settle microtasks before verifying DOM elements.
- Add diagnostics to command parsing to report invalid field values.
- Fix UTF-8 truncation in spinner to avoid splitting codepoints.
- Fix swapped arguments in log error formatting.
- Distinguish "null" values from missing elements in verifier.
- Handle MCP tool cancellation and timeouts with specific error codes.
This fixes two things. First, it better tracks the calling context and the
target context, so that if a parent frame does a document.write within a child
frame, any JavaScript is executed in the child frame's context (previously, it
would be executed in the parent's context).
Second, it ensures that, on document.write, we force-execute any pending
scripts. This is related to https://github.com/lightpanda-io/browser/pull/2542
but applies specifically to document.write.
Currently, any inline deferred script, e.g:
<script type=module>
...
</script>
That happens AFTER load, never executes. Unclear how serious an issue this is,
but it _does_ cause problems for some WPT tests which use document.write to
inject a <script type="module">...</script> block after an iframe is loaded.
For typically name-less elements, check the "role" attribute to see if we should
fallback to the content.
Improves a handful of WPT tests, e.g.: /accname/name/comp_text_node.html
(It seems impossible to get 100% on these tests without knowing what is and
isn't a block-level element which would require more knowledge in the
StyleManager).
- Limit UTF-8 walkback in `capToolOutput` to 3 bytes to prevent
excessive scanning on malformed input.
- Track consecutive backslashes in `tokenize` to correctly handle
even-count backslashes before a closing quote.
Explicitly reject backslash-escaped quotes with a clear error
message, suggesting alternative quote styles or triple quotes.
Bare backslashes (e.g. in Windows paths) remain supported.
Detects multi-line block openers (e.g., `/eval '''`) and indexes the
entire block up to its closing fence as a single span. This prevents
body lines from being indexed individually and orphaned during splicing.
Falls back to single-line indexing if the block is unterminated.
Strip carriage returns from CRLF line endings before indexing so that
LLM-supplied keys (using plain LF) match files saved with Windows
line endings. The span still covers the full CRLF sequence.
Introduces `Input.getRedactedValue` to mask password values in
LLM-facing dumps (semantic tree, forms, AXNode) instead of
exposing raw values or using ad-hoc checks.
Strips control characters from tool arguments to avoid breaking the
carriage-return redraw. Queries the terminal width and truncates
arguments to fit on a single row, appending an ellipsis if needed.
Mirrors user-typed slash commands into the message history as synthetic
tool calls. This ensures the LLM conversation remains in sync and the
next prompt can see the action's result.
Rename the system prompt constant to reflect its broader usage.
Also add instructions to guide the agent on handling follow-up
questions after navigation.
popAndInvoke captured the reactions queue as a slice at loop entry. If
firing a reaction triggered a nested scope whose enqueue grew the
underlying ArrayList, the captured slice became dangling and the next
iteration read freed memory. Switch to indexed iteration so the queue
pointer is re-read each step. Repros via wpt/custom-elements/
enqueue-custom-element-callback-reactions-inside-another-callback.html.
The rest of the diff adds .ce_reactions = true to bridge declarations
that were missing it per WebIDL [CEReactions] *and* whose Zig impl
actually performs a DOM/attribute mutation (verified by reading each
setter). Without the flag, the algorithm's enqueue path hits
assertScopeActive and panics. Runtime-state-only setters (Input.value,
Input.checked, Select.value, Option.selected, Media.muted/volume, etc.)
are deliberately left untagged.
Covered:
- CustomElementRegistry.define, .upgrade
- HTMLDocument: body, title, dir
- Document: open, close
- HTMLElement base: insertAdjacentHTML, dir, hidden, lang, tabIndex,
title, innerText
- Range: insertNode, deleteContents, extractContents,
surroundContents, createContextualFragment
- Selection: deleteFromDocument
- HTMLOptionsCollection: add, remove
- DOMStringMap (dataset): namedIndexed setter/deleter — required adding
.ce_reactions to NamedIndexed.Opts in bridge.zig
- ~28 HTMLxxxElement files: every settable attribute that resolves to
setAttributeSafe/removeAttribute (Anchor, Button, Canvas, Data,
Details, Dialog, FieldSet, Form, IFrame, Image, Input, Label, Link,
LI, Media, Meta, OL, OptGroup, Option, Quote, Script, Select, Slot,
Style, TableCell, Template, TextArea, Time, Track, Video)
While this PR touches a lot of files, and isn't trivial, many of the changes
are either:
1 - removing guards added in previous PRs, e.g.
https://github.com/lightpanda-io/browser/pull/1969https://github.com/lightpanda-io/browser/pull/2172https://github.com/lightpanda-io/browser/pull/2313https://github.com/lightpanda-io/browser/pull/2366
2 - Adding the `.ce_reactions = true` flag to various WebAPIs
CustomElements have callbacks, e.g. connectedCallback. Also, many WebAPI calls
are implemented as a series of mutations, e.g. appendChild = remove from current
+ append to new.
These two things interact in an important way: when should callbacks execute?
Before this PR, we were invoking callbacks at each individual step. This is
(a) technically wrong and (b) breaks a lot of assumptions (the reason the above
4 PRs were needed to fix bugs).
This PR adds a `_ce_reactions` queue to the frame. And, instead of invoking
callbacks, we "enqueue" the reaction. At various boundaries, a scope is created
the DOM manipulation is done, and then we pop the scope, invoking all queued
reactions.