Commit Graph

8347 Commits

Author SHA1 Message Date
Karl Seguin
48750df46a Merge pull request #2944 from lightpanda-io/dom-pr-03-handler-plumbing
webapi: listener option validation, window-reflecting handlers, exception propagation
2026-07-15 07:08:39 +08:00
Karl Seguin
a60eaa724b Merge pull request #2930 from lightpanda-io/popup-origin
webapi: Improve popup window
2026-07-15 07:02:44 +08:00
Karl Seguin
2e9aebc6b1 Merge pull request #2935 from lightpanda-io/robots-skip-non-200-body
robots, mem: don't buffer body on a non-200 robots response
2026-07-15 07:02:28 +08:00
Adrià Arrufat
53e1dbe8e8 agent: clean up terminal and markdown rendering
- Move ANSI escape definitions to `md_term.zig`.
- Fix table cell width calculation using a scratch buffer.
- Ensure `Stream.close` fully resets markdown stream state.
- Extract helper functions for styled output and fence checks.
2026-07-14 23:13:52 +02:00
Adrià Arrufat
d0ce9a02a8 terminal: stream and render markdown incrementally
Introduces an incremental markdown renderer (`md_term.Stream`) to
format streamed assistant responses in real time. Buffers lines,
maintains code fence state across chunks, and temporarily withholds
tables to render them with proper column alignment once complete.
2026-07-14 22:51:43 +02:00
Adrià Arrufat
aacddfdbea Merge branch 'main' into agent-repl-markdown-output 2026-07-14 22:32:26 +02:00
Adrià Arrufat
74536507dd md_term: add markdown table rendering 2026-07-14 22:32:07 +02:00
Adrià Arrufat
d52e56ece8 md_term: support arbitrary nested inline styles
Introduces a stack-threaded `Style` chain to track and re-apply
parent styles upon nested resets. This fixes styling loss in
deeply nested markdown spans.
2026-07-14 22:06:25 +02:00
Adrià Arrufat
97e25b5abc Merge pull request #2929 from lightpanda-io/pandascript-skill
script: generate the PandaScript skill from the tool schemas
2026-07-14 21:53:25 +02:00
Adrià Arrufat
0618515132 terminal: fix nested markdown styles and dim color
- Use a 256-ramp gray for `ansi.dim` to improve readability.
- Track and re-apply active styles in nested markdown spans.
- Collapse extra spaces after list markers.
2026-07-14 21:51:09 +02:00
Rohit
2f4b7ec9ce feat(cdp): emit Page.navigatedWithinDocument for same-document navigations
CDP clients (Playwright/Puppeteer) never saw same-document navigations —
history.pushState / replaceState changed frame.url but fired no CDP event,
so frame.url() went stale and waitForNavigation missed SPA route changes.

Add a frame_navigated_within_document notification, dispatched from
History.pushState/replaceState, and emit Page.navigatedWithinDocument from
the Page domain with frameId, url, and navigationType. Unlike frameNavigated,
this deliberately does NOT send Runtime.executionContextsCleared or
DOM.documentUpdated — the document and its execution context are unchanged,
and clearing them would invalidate the client's live context ids and break
frame.evaluate(). Adds a cdp.frame test.

Scoped to the History-API path; fragment and Navigation-API paths are left
for follow-ups.
2026-07-15 00:40:32 +05:30
Francis Bouvier
0c0e3626f3 webapi: take *Frame in HTMLCollection.getIndexes
Same review pattern as the getNames enumerators: the bridge can inject
*Frame directly, so the manual switch on exec.js.global is unnecessary.
getIndexes was the one enumerator the earlier suggestions missed.

Co-Authored-By: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-14 15:32:43 +02:00
Karl Seguin
9965e59672 Merge pull request #2943 from lightpanda-io/dom-pr-02-htmlcollection-properties
webapi: HTMLCollection & named-collection property semantics
2026-07-14 21:20:24 +08:00
Francis Bouvier
dba25389c6 webapi: window-reflecting handlers target the body's own window
Review follow-up on #2944: the injected `frame` parameter of a bridged
function is the frame of the executing JS context - the caller's realm -
not the frame owning the element. The window-reflecting body/frameset
event handlers (onblur, onerror, onfocus, onload, onresize, onscroll)
used it directly, so a same-origin script reaching into another frame,
e.g. the parent doing

    iframe.contentDocument.body.onblur = cb;

stored the handler on the parent's window instead of the iframe's. Per
the HTML spec these handlers alias the Window of the element's node
document, whichever realm performs the access.

All Body/FrameSet getters and setters now resolve that Window through
the existing Node.ownerFrame (element -> ownerDocument -> frame, falling
back to the caller's frame for detached/frameless documents), via a
shared reflectedWindow helper. The Build hooks (parse-complete,
attributeChange, attributeRemove) do the same, and additionally pass the
owner frame to setWindowReflectingHandlerFromAttribute so attribute
handler bodies are compiled in the element's document's realm.

Unit test added: tests/frames/window_reflecting_handlers.html covers the
IDL property path and the content-attribute path (parse-time and
runtime) across realms, asserting the handler lands on the iframe's
window while the parent's window stays untouched. It fails without this
fix.

Co-Authored-By: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-14 15:19:39 +02:00
Francis Bouvier
d2cc336c74 Update src/browser/webapi/Window.zig
Co-authored-by: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-14 15:00:58 +02:00
Francis Bouvier
0872b86383 js: propagate pending JS exceptions from argument conversion
Fixes 1 failing test in WPT /dom/events/Event-constructors.any.html
(and its .worker variant): "Event constructors 2", which does
`new Event({ toString: function() { throw test_error; } })` and expects
the exact test_error object to propagate.

When a JS value's conversion runs user code that throws (here, ToString
invoking a throwing toString method), the conversion fails with
error.JsException while the user's exception is pending in the isolate.
The argument-conversion catch folded that into error.InvalidArgument,
and handleError then threw a brand new "TypeError: invalid argument"
over the pending exception, so the script observed the wrong error.

error.JsException is now passed through the argument-conversion catch,
and handleError leaves the isolate untouched for it (like the existing
TryCatchRethrow case), letting the original exception surface.

Coverage: /dom/events/Event-constructors.any.html 13/14 -> 14/14,
/dom/events/Event-constructors.any.worker.html 13/14 -> 14/14.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 15:00:58 +02:00
Francis Bouvier
ca92bb6a1b webapi: window-reflecting body/frameset event handlers
Fixes 24 failing tests in WPT /dom/events/Body-FrameSet-Event-
Handlers.html (24/48 -> 48/48).

Per the HTML spec, the onblur, onerror, onfocus, onload, onresize and
onscroll event handlers of body and frameset elements are aliases for
the Window's handlers (the "window-reflecting body element event
handler set"), and setting the corresponding content attribute on those
elements must activate the Window's handler too. Two groups of
failures:

- "Set ...": assigning a non-callable (e.g. "") to the IDL attribute
  threw "invalid argument" instead of storing null, because the setters
  took ?js.Function.Global. Per [LegacyTreatNonObjectAsNull], the
  Body/FrameSet setters now use Window.FunctionSetter (function or
  anything-else-means-null), like the existing Window handler setters.
- "Forward ... to Window": only body.onload was forwarded. Window now
  stores onblur/onfocus/onresize/onscroll handlers too (and exposes the
  matching accessors, which it lacked entirely), and Body/FrameSet
  implement getters/setters forwarding all six handlers to the Window
  of the current frame. Setting or removing one of the six content
  attributes (at parse time via Build.complete or at runtime via the
  attributeChange/attributeRemove build hooks) compiles the handler
  body and stores it on the Window, so window.onX === element.onX.

Coverage: /dom/events/Body-FrameSet-Event-Handlers.html 24/48 -> 48/48.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 15:00:58 +02:00
Francis Bouvier
f1498f2da9 webapi: throw TypeError for addEventListener({ signal: null })
Fixes 2 failing tests in WPT /dom/events/AddEventListenerOptions-
signal.any.html (and its .worker variant): "Passing null as the signal
should throw" (with a valid and with a null listener).

The AddEventListenerOptions dictionary declares `signal` as a
non-nullable AbortSignal, so per Web IDL an explicit null (or any
non-AbortSignal value) must be rejected with a TypeError during the
dictionary conversion — even when the listener argument is null. The
bridge collapsed both a missing member and an explicit null into a Zig
null, silently ignoring the signal.

EventTarget.addEventListener now receives the signal member as a raw
js.Value: an absent or undefined member means "no signal", anything
else is converted to an AbortSignal (throwing a TypeError when it
isn't one), and the conversion runs before the null-callback early
return to match the spec's argument-conversion ordering.

Coverage: /dom/events/AddEventListenerOptions-signal.any.html
9/11 -> 11/11, /dom/events/AddEventListenerOptions-signal.any.worker.html
9/11 -> 11/11.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 15:00:58 +02:00
Francis Bouvier
a00d06d2d8 webapi: finish the exec -> frame parameter conversion in enumerators
The applied review suggestions switched the getNames/getIndexes
enumerator callbacks of HTMLCollection, NamedNodeMap and DOMStringMap
from *const js.Execution to the injected *Frame, but only partially:
signatures and bodies disagreed and the build broke. Complete the
conversion — the bridge resolves *Frame from the context, so the manual
exec.js.global switch goes away, and the arenas/JS locals are reached
through the frame.

Co-Authored-By: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-14 14:59:20 +02:00
Francis Bouvier
63ad289cb1 Update src/browser/webapi/element/DOMStringMap.zig
Co-authored-by: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-14 14:50:59 +02:00
Francis Bouvier
071eee15ea Update src/browser/webapi/element/Attribute.zig
Co-authored-by: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-14 14:50:52 +02:00
Francis Bouvier
ad61533def Update src/browser/webapi/element/Attribute.zig
Co-authored-by: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-14 14:50:45 +02:00
Francis Bouvier
58b42499d9 Update src/browser/webapi/element/Attribute.zig
Co-authored-by: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-14 14:50:39 +02:00
Francis Bouvier
5072722222 Update src/browser/webapi/collections/HTMLCollection.zig
Co-authored-by: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-14 14:50:33 +02:00
Francis Bouvier
fb06ea0f44 js: rename deleteIndex helpers to deleteOrDefineIndex
The Caller.deleteIndex and Caller.deleteNamedIndex helpers are invoked
by the bridge for definer interceptors too, since definers share the
deleter's (self, index/name) -> bool calling shape. Rename them (and
their private counterparts) to deleteOrDefineIndex and
deleteOrDefineNamedIndex so the name reflects both uses.

No behavior change.

Co-Authored-By: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-14 14:48:21 +02:00
Francis Bouvier
13b253f1f8 Update src/browser/webapi/element/DOMStringMap.zig
Co-authored-by: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-14 14:38:37 +02:00
Francis Bouvier
fba0390b92 Update src/browser/webapi/element/DOMStringMap.zig
Co-authored-by: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-14 14:36:13 +02:00
Francis Bouvier
640776c9ee Update src/browser/webapi/element/DOMStringMap.zig
Co-authored-by: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-14 14:36:06 +02:00
Francis Bouvier
5f553144fb Update src/browser/webapi/element/Attribute.zig
Co-authored-by: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-14 14:35:58 +02:00
Francis Bouvier
2bf5c4abb3 Update src/browser/webapi/collections/HTMLCollection.zig
Co-authored-by: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-14 14:34:51 +02:00
Karl Seguin
adef5c39af Merge pull request #2942 from lightpanda-io/dom-pr-01-abort-signal
webapi: AbortSignal conformance fixes (dependent signals, null reason, timeout after detach)
2026-07-14 20:07:03 +08:00
Karl Seguin
123b093bba Merge pull request #2940 from rohitsux/feat/htmlarea-reflect-attributes
feat(webapi): reflect HTMLAreaElement attributes
2026-07-14 19:43:42 +08:00
Adrià Arrufat
c67b9f3ad3 terminal: stream markdown rendering to writer
Changes `md_term.render` to write directly to a writer instead of
allocating a string. Also simplifies horizontal rule parsing.
2026-07-14 12:19:26 +02:00
Adrià Arrufat
133e6ebe16 docs(skill): clarify HTTP concurrency limits
Update prose to explain the 6 per host limit and same-site fan-out.
2026-07-14 12:10:48 +02:00
Adrià Arrufat
8c0ec3d73a Merge branch 'main' into pandascript-skill 2026-07-14 12:06:05 +02:00
Karl Seguin
4d433ad028 websocket: Process WebSocket message through delivery query
This piggybacks on the HttpClient rework (1) and makes incoming WebSocket
messages get delivered in a similar fashion. Namely, WebSocket events (connect,
data, close) are queued and only delivered at safe points. The goal is to make
sure JS is never run during a libcurl callback. This has historically caused
issues and currently requires the HttpClient to have various guards (e.g.
performing flag, dirty queue, etc..).

This change removes the last cases where JS could be executed within a libcurl
callback. Consequently, HttpClient is simplified. It no longer has a perfoming
flag nor a dirty queue nor ready queue.

(1) https://github.com/lightpanda-io/browser/pull/2889
2026-07-14 17:25:52 +08:00
Rohit
9ad833c844 feat(webapi): reflect HTMLAreaElement attributes
HTMLAreaElement only implemented the URL/HTMLHyperlinkElementUtils mixin
(href, origin, protocol, host, ...). The area-specific reflected IDL
attributes were missing, so alt, coords, shape, target, download, rel,
referrerPolicy and relList all read back as undefined.

Reflect them the same way HTMLAnchorElement and HTMLLinkElement do:
plain string reflection for alt/coords/shape/target/download/rel,
enumerated reflection for referrerPolicy, and the shared DOMTokenList
helper for relList (guarded to html/svg namespaces). ping is left out to
match the current HTMLAnchorElement precedent. Adds an area.html test.
2026-07-14 13:57:25 +05:30
Karl Seguin
cfe771e776 Merge pull request #2938 from lightpanda-io/fix-debug
ooops: remove stray debug print
2026-07-14 15:39:36 +08:00
Karl Seguin
15744bca37 ooops: remove stray debug print 2026-07-14 15:15:10 +08:00
Karl Seguin
93e86cbe6a Merge pull request #2936 from lightpanda-io/silence-expected-test-errors
test: Filter out expected error messages from tests
2026-07-14 15:10:31 +08:00
Karl Seguin
3b266359d2 Merge pull request #2937 from lightpanda-io/support-large-content-length
http: u32 -> usize for [very] large content length
2026-07-14 15:10:21 +08:00
Karl Seguin
d8b2551baf Merge pull request #2911 from lightpanda-io/eventsource
webapi: Add EventSource
2026-07-14 14:45:45 +08:00
Karl Seguin
0f589567f9 update for new v8 global management 2026-07-14 14:21:44 +08:00
Karl Seguin
8ad4bd9015 webapi: Add EventSource
The EventSource API only requires a simple line-based parser. It's pretty
straightforward. It's RC'd by v8 and itself, but also by scheduled tasks (e.g.
to reconnect).

The bigger change is to the HttpClient to support streaming requests. This
changes to things:
1 - A transfer doesn't only deliver() once
2 - A transfer can be in the multi while delivering

Neither of these are surprising, but they both add complexity.
2026-07-14 14:19:27 +08:00
Karl Seguin
cebd8f15f6 Merge pull request #2904 from lightpanda-io/metrics
ops: Add prometheus metrics
2026-07-14 14:17:13 +08:00
Karl Seguin
a0549b072d http: u32 -> usize for [very] large content length
There's 1 WPT test that returns a 8GB value content-length (testing failures)
and the u32 limit fails to parse it and makes it as though no content-length
header exists.
2026-07-14 14:09:01 +08:00
Karl Seguin
46e90a984f zig fmt 2026-07-14 11:55:59 +08:00
Karl Seguin
10e91d0503 test: Filter out expected error messages from tests
Please enter the commit message for your changes. Lines starting
2026-07-14 11:50:22 +08:00
Karl Seguin
1ac4435660 extend test buffer size 2026-07-14 11:45:17 +08:00
Karl Seguin
f0784de015 add http metrics 2026-07-14 11:32:52 +08:00