Commit Graph

8347 Commits

Author SHA1 Message Date
Karl Seguin
b78170c71e fix: Reject xhr send() when send already active
This builds on top of 995efd57e6. That commit
tracked the number of requests being made on a single XHR instance (because a
new request can be initiated from a load/error callback of an existing one).
However, that was unbound. It wasn't just 1 old + 1 new, it was an unlimited
number of new requests, because we didn't prevent sending while sending was
already active.

This adds a boolean to track our send state, and prevents a send from happening
when a send is already active.
2026-06-27 09:05:26 +08:00
Boyd Ebsworthy
b94052dfa7 webapi: Fix cross-origin MessageEvent.source WindowProxy identity
MessageEvent.getSource returned the bare *Window, the only window accessor
that did not go through Window.Access.init. Every other accessor
(iframe.contentWindow, window.parent, window.top) wraps a cross-origin target
as *CrossOriginWindow. JS object identity is keyed by Zig pointer
(identity_map), so cross-origin event.source (the *Window) and
iframe.contentWindow (&window._cross_origin_wrapper) resolved to different JS
objects: `event.source === iframe.contentWindow` was false cross-origin while
true same-origin.

The WHATWG HTML spec requires these to be the same object regardless of origin
(one WindowProxy per browsing context; MessageEvent.source is that
WindowProxy). The mismatch breaks postMessage handshakes that authenticate the
sender by reference identity, e.g. keycloak-js's 3rd-party-cookie check
(`if (iframe.contentWindow !== event.source) return;`), which then times out
and fails OIDC init.

Route getSource through Window.Access.init(frame.window, source) — exactly like
IFrame.getContentWindow — so both paths resolve to the same per-frame proxy.
Same-origin behaviour is unchanged. Verified against Chrome 149 (identity holds
cross- and same-origin). Adds a regression test, cross_origin_message_source.html.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 18:10:25 +02:00
Karl Seguin
97cef1e900 Merge pull request #2822 from lightpanda-io/worker_requestAnimationFrame
fix: Crash on requestAnimationFrame from Worker
2026-06-26 22:53:52 +08:00
Boyd Ebsworthy
e6bd65626e cdp: Fix Page.frameAttached params double-wrapping that broke sub-frame interception
frameChildFrameCreated emitted Page.frameAttached with its payload wrapped
in an extra `.{ .params = ... }`. CDP.sendEvent already places the payload
into the event's `params` field, so this produced a malformed wire event
with double-nested params (`params.params.frameId`) — unlike every sibling
frame event in the same function, which passes its fields flat.

CDP clients (e.g. Playwright via connectOverCDP + page.route) parse
frameId/parentFrameId at the top level of params. With the fields one level
too deep the client never registers the child frame, so when that frame's
Fetch.requestPaused arrives it is bare-continued instead of matched against
a route. The result: request interception (page.route / Fetch) silently does
not apply to iframe (sub-frame) document navigations — the iframe loads from
the real network. The interception layer itself was never at fault; it does
emit requestPaused for sub-frames.

Drop the extra wrapper so the payload is flat. Add a regression test that
dispatches frame_child_frame_created and asserts Page.frameAttached carries
frameId/parentFrameId directly under params (fails on the double-nested shape).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 14:11:20 +02:00
Karl Seguin
700b4daf2e webapi: replaceWith called with DocumentFragment should append its children 2026-06-26 18:46:36 +08:00
Karl Seguin
bf14d2f05c fix: Fix innerHTML parsing based on the target
The parsing behavior of HTML depends on what we're parsing it for. innerHTML on
a script is parsed (slightly) differently than for, say, the body. html5ever
supports this, we just have to give it the tag name (which we have access to
in the html5ever bridge already).

Also, extend the tag types that dump does NOT escape for beyond noscript/script.

Fixes warnings with some NextJS sites
2026-06-26 18:05:06 +08:00
Karl Seguin
2439f6150e css: normalize fractions without leading 0
This causes some feature detection (jquery/amazon) to think we're some old
version of IE, which then requires IE-specific APIs. It sets a ".55" value and
then reads it, expecting 0.55.
2026-06-26 16:37:45 +08:00
Karl Seguin
78e008d5ec webapi, fake: Navigator.sendBeacon
This is a noop implementation of navigator.sendBeacon. It often shows up in the
logs. I believe that returning "true" to signal successful queuing is correct
as it'll prevent any attempts to fallback. However, I'm less sure that noop'ing
the entire thing is better than just implementing it.
2026-06-26 16:10:59 +08:00
Karl Seguin
32d52a828a webapi: Add Select.add 2026-06-26 15:51:16 +08:00
Karl Seguin
6a1e1f5ace fix: Crash on requestAnimationFrame from Worker
https://github.com/lightpanda-io/browser/pull/2817 added support for RAF to
workers (largely as a consequence of the real effort), but this wasn't wired
all the way through.
2026-06-26 15:29:18 +08:00
Karl Seguin
ba5323e51e Merge pull request #2817 from lightpanda-io/DedicatedWorkerGlobalScope
webapi: Make Worker a proper DedicatedWorkerGlobalScope
2026-06-26 15:07:56 +08:00
Pierre Tachoire
9c224c59b6 Merge pull request #2815 from lightpanda-io/version-fmt
ci: Generate a versions.json file
2026-06-26 05:44:43 +00:00
Pierre Tachoire
9cae6b07e6 Merge pull request #2797 from lightpanda-io/brotli-false-err
fix: work around libcurl Brotli trailing-byte rejection (CURLE_WRITE_ERROR)
2026-06-26 05:43:38 +00:00
Karl Seguin
b473b019cb Merge pull request #2814 from lightpanda-io/telemetry_thread
telemetry: Move telemetry worker to its own thread
2026-06-26 08:55:26 +08:00
Karl Seguin
05986de731 Merge pull request #2818 from lightpanda-io/no_note_logs_on_test
minor: don't log .note level logs during unit tests
2026-06-26 08:43:46 +08:00
Karl Seguin
13eb35720a telemetry: Move telemetry worker to its own thread
This reverts recent(ish) changes to telemetry which moved it from its own thread
onto the main thread.

The downside is: we have an extra thread.

The upside is largely that Network.zig becomes drastically simpler and more
efficient. There's a bunch of machinery in Network.zig to support arbitrary
workers, of which Telemetry is the only one. There's also a lot of code to
support an optional multi and requests made to is. This is all removed.

Also, fetch, agent and mcp without a cdp server no longer even need to start
the network loop. And, it IS started (e.g. serve/cdp), there's no longer an
arbitrary 250ms wakeup on poll to progress workers. Nor can telemtry block CDP.

Telemetry's implementation itself was changed. The ring buffer was removed in
favor of a double-buffer arraylist. When telemetry is disabled, this saves
64Kb of memory. When it's enabled, it creates more allocator churn, but should
still use less memory in most cases (and never more). Finally, Telemetry is
given its own easy connection rather than using one out of the pool (which
workers would maybe like to use).
2026-06-26 08:38:49 +08:00
Karl Seguin
5fcdc1c5ad Merge pull request #2808 from lightpanda-io/fetch-multiple-urls
cli: fetch multiple urls
2026-06-26 08:36:26 +08:00
Karl Seguin
cd6c027dd9 Merge pull request #2807 from lightpanda-io/runner
design: Runner supports multi-pages
2026-06-26 08:36:07 +08:00
Karl Seguin
ec1d6fcb27 minor: don't log .note level logs during unit tests 2026-06-26 08:34:24 +08:00
Karl Seguin
5d604d109f slight optimization to hasRunnablePage 2026-06-26 08:22:33 +08:00
Karl Seguin
e1a8e036c6 webapi: Make Worker a proper DedicatedWorkerGlobalScope
When you create a worker (new Worker(...)), it creates 2 objects: the Worker
that lives in the caller, and the WorkerGlobalScope (WGS) which is more or less
like a Window, with its own v8::Context.

But WGS is really a base class meant to be used with various types of workers.
new Worker() shouldn't create a WGS directly, it should create a
DedicatedWorkerGloblaScope, which inherits from WGS. For now, our WGS can only
have 1 type (DedicatedWGS).

This fixes various errors on www.kitandace.com which would launch workers, and
then do a check (if (this === DedicatedWorkerGloblaScope)). It _should_ have
returned true, but it didn't (because our workers were WGS).
2026-06-26 07:50:39 +08:00
Pierre Tachoire
4d07f47da1 Generate a versions.json file 2026-06-25 17:45:19 +02:00
Halil Durak
004dbf259e Anchor: update tests 2026-06-25 18:06:09 +03:00
Halil Durak
30f10b4966 prefer error-less URL resolver for various getters 2026-06-25 18:06:09 +03:00
Halil Durak
f6fb653a35 prefer resolveNavigation at page, target and fetch 2026-06-25 18:06:08 +03:00
Halil Durak
67cc2be817 URL.zig: update tests 2026-06-25 18:05:49 +03:00
Halil Durak
6bd4fddf62 URL: add resolveNavigation
This is needed for schemeless "address bar" style URLs. Would love to have a path that doesn't allocate for this...
2026-06-25 18:05:49 +03:00
Halil Durak
82d78ecd00 Node: add resolveURLReflect 2026-06-25 18:05:49 +03:00
Halil Durak
a499c0cb92 URL: update tests 2026-06-25 18:05:48 +03:00
Halil Durak
7d5553238e URL: changes on host(name) setter, introduce clean_hostname_input 2026-06-25 18:05:48 +03:00
Halil Durak
0c4f6f0d87 getProtocol(Anchor, Area): return : if resolved href is null 2026-06-25 18:05:48 +03:00
Halil Durak
84fe33c679 URL(EncodeSet): bring back component value
Lost and found.
2026-06-25 18:05:48 +03:00
Halil Durak
a12d781d4a KeyValueList.zig: update tests 2026-06-25 18:05:48 +03:00
Halil Durak
2cdcecaba4 KeyValueList(urlEncodeUnreserved): drop ~ case 2026-06-25 18:05:48 +03:00
Halil Durak
84870d5524 URL: include leading '?' in search/query 2026-06-25 18:05:48 +03:00
Halil Durak
8d41c6e221 KeyValueList: write = between key and value at all modes 2026-06-25 18:05:48 +03:00
Halil Durak
20c9a873fd URL: update tests 2026-06-25 18:05:47 +03:00
Halil Durak
e223827789 URL: reintroduce parse static method 2026-06-25 18:05:47 +03:00
Halil Durak
3c91f3b3e2 URL: fix missing port problem in setter 2026-06-25 18:05:47 +03:00
Halil Durak
7bf68a484d URL: replace ensureEncoded with resolve
Both essentially do the same; we can stick to `resolve` for further IDNA compat.
2026-06-25 18:05:47 +03:00
Halil Durak
9732c33c3c URL: remove always_dupe option from all call sites 2026-06-25 18:05:08 +03:00
Halil Durak
3512f1fb1a update URL-involving tests 2026-06-25 18:05:08 +03:00
Halil Durak
be6f1c9155 Caller: remove error.Idna case 2026-06-25 18:05:08 +03:00
Halil Durak
fc00421870 URL: retake on resolve function 2026-06-25 18:05:08 +03:00
Halil Durak
0ddca754a4 URL: move resolver functions to Rust
Implements `url_resolve_with_encoding` and `url_resolve_without_encoding` in Rust; that way, we don't pay the cost of extra `Box`es we allocate during resolving.
2026-06-25 18:05:08 +03:00
Karl Seguin
93ff42b161 debug: limit macrotask runner to when we have a page
This is the only main change in this branch compared to main that could explain
the Debug check failed: isolate()->CurrentLocalHeap()->IsRunning() failure
being reported.
2026-06-25 18:53:44 +08:00
Karl Seguin
bb15e5ff08 pr feedback: Run background tasks, push wait errors to caller
This fixes two bugs introduced in the previous PR. First, in non-CDP mode, when
there's nothing to do except v8 background tasks, we wait for those background
tasks.

Second, the various wait helpers (e.g. waitForFrame) now return the first error
of any WaitCondition.
2026-06-25 18:16:27 +08:00
Karl Seguin
dcab57cd05 Merge pull request #2813 from lightpanda-io/fix-handlescope-corruption
crash: Fix handlescope corruption on iframe load
2026-06-25 17:42:42 +08:00
Karl Seguin
108d5c68fd crash: Fix handlescope corruption on iframe load
In trying to fuzz test a different issue, I ran into a reproducible case where
we end up with a broken handlescope stack. The issue requires a large number
of handlescopes created with aggressive GC, so hopefully it isn't something
that too many users have run into.

The issue is that a single HandleScope address is used to initialize two
HandleScopes. The fix could just be to create a 2nd HS variable (to get a 2nd
address), but the first initialization is unnecessary and can just be removed.

(Note that EventManager dispatch creates its own HandleScope, so the one
removed in frameCompletedLoading really did nothing)
2026-06-25 17:41:42 +08:00
Pierre Tachoire
4faed74af0 Merge pull request #2809 from lightpanda-io/intercepted_abort_double_free
uaf: Prevent double-free on BrowserContext deinit with pending interc…
2026-06-25 09:26:37 +00:00