Drains and prints console messages during the REPL loop. This ensures
console output is surfaced in JS mode, where slash commands like
`/consoleLogs` are unreachable.
Depends on https://github.com/lightpanda-io/zig-v8-fork/pull/179
An improvement to https://github.com/lightpanda-io/browser/pull/2515 to prevent
a v8 assertion if we terminate as an inspector dispatch is happening.
The problem is that if we just immediately terminate, we aren't sure what the
worker thread is doing, and, apparently, if we terminate then dispatch a message
to the inspector, we fail an assertion.
With the way the code was, the only safe solution would be to hold a mutex
over the session dispatch, but that could block the network thread.
So instead of terminating from the network thread, we now ask v8 to execute
a callback. This gets executed on the worker thread, which can then terminate
the execution.
The initial version of 2515 delayed the termination from the network thread.
It's possible that solution would "solve" the issue, simply because it's very
unlikely that a worker would be "stuck" for 5 seconds and then get unstuck.
More likely that it exits immediately, or is stuck in an endless loop. But
that would still leave a window where we could terminate in network and then
dispatch in the worker. Less likely, but still possible. Hopefully this new
mechanism eliminates this from being a problem in all circumstances.
Consolidates the switch block in `extractArgs` to extract the schema
string first before wrapping it. Simplifies `extractSchemaString` by
reusing `normalizeExtractSchemaString` for array schemas.
Use the current isolate context instead of the receiver's context
when invoking primitives, fixing failures in strict-mode scripts.
Also, explicitly perform a microtask checkpoint after running a
script to ensure promise continuations run.
Removes the `--self-heal` CLI option, the `scriptStep` and `scriptHeal`
MCP tools, and associated verification/iterator machinery. Replaces
"PandaScript" terminology with "slash commands" and moves shared
helpers to `tools.zig`.
BREAKING CHANGE: The `--self-heal` CLI flag and the `scriptStep` and
`scriptHeal` MCP tools have been removed.
- Use `std.enums.values` and `@tagName` in `ScriptRuntime` to eliminate
the manual `primitive_specs` and `console_specs` arrays.
- Simplify `Primitive.tool()` using `std.meta.stringToEnum`.
- Clean up `writeConsoleLine` and remove `writeJsPositional`.
This specifically fixes a crash on WPT:
/html/syntax/parsing/html5lib_scripted_webkit01.html?run_type=write
Claude wrote a simple reproducing unit test, and you can see it's a
document.write that calls document.write.
Replace recorded agent replay with a standalone JavaScript script runtime.
Install synchronous agent primitives in an isolated V8 context, add console
output, return structured extract values as JS objects/arrays, and route script
execution through the new runtime.
Update recording to emit .js function calls, default /save filenames to .js,
drop script-level extract save support, and refresh agent docs/tutorials for
the new format.
Self-healing is disabled for now.
There can be cases where the data referenced by Request does not live for the
duration of a Transfer. The most obvious case is a QueuedNavigation..this is
generally a problem, but it's particularly problematic under load when the
request gets queued in the HttpClient.
Most of the data is small, so just _always_ duping it is worth it. The body
can be large, so we provide a flag for callers to set to turn off the body
duping (essentially saying "I promise to keep the body alive for the duration
of the transfer). Currently, only XHR is able to make this guarantee.
Extracts provider and model settings logic from `Agent.zig` into a new
`settings.zig` module. Replaces custom UTF-8 truncation logic with
`truncateUtf8` from `string.zig`. Also updates the `zenai` dependency.
When processFrameNavigation fails, we catch the error and log the `qn.url`. But
`qn` has been been freed by this point. This refactors the code to make
`procesFrameNavigation` clearly take ownership of `qn` and of logging any
errors while `qn` is still active.
Extracts the API key and LLM setup hint strings into reusable constants.
Also refactors the REPL to use the `requireLlm` helper instead of
duplicating the LLM check logic.
Global objects (Window, WorkerGlobalState) should have accessors and functions
defined directly on the global object. This is in addition to having it defined
on the prototype.
This prevents some weird overwriting that scripts can otherwise achieve.
Something I saw on espn where window.navigator was being overwritten by a global
`navigator` variable.
When `[]const u8` is a web api parameter, we'll coerce the value to a string,
e.g. true -> "true". This is correct for almost every API. APIs can also opt
to use a string.String (or string.String.Global). This is purely meant as an
optimization, but its behavior is currently different than `[]const u8` as the
bridge will only map actual JS strings to it.
This commit makes String and []const u8 behave the same, so that the only
decision as to which to use is about performance.
(APIs that strictly want a string should use js.String or js.Value and do the
type check)
This is driven by import-maps WPT tests. It generally does 3 high level
additions, plus various small compliance tweaks.
1 - Entries with a trailing match are used for prefix matching
2 - Supports scopes (which are entries group into a specific route-like prefix)
3 - Because of the above, resolves in correct order with fallback
Resolution is based on longest-match wins, so it doesn't require a fancy
data structures. We use ordered (by length) slices, and just iterate until we
find a match. Neither our parsing nor our matching is super efficient. While
a page might have hundreds of scripts, it likely has only 0-1 import maps and
relatively few values.
ImportMap.resolve always returns the final URL. So even if a match isn't found
based on the parsed JSON, it'll return the URL.resolve(base, url). Just to make
WPT tests pass, we do have to track invalid entries in the ImportMap, e.g.
"key": "not-a-url". In the previous version, we'd fallback to URL.resolve(base,
url). Now we return null and leave it to the caller to decide.