Commit Graph
8199 Commits
Author SHA1 Message Date
Thibaud-VdbandPierre Tachoire e25ea46cd8 chore(readme): remove plumber badge
Co-authored-by: Pierre Tachoire <pierre@tch.re>
2026-07-20 15:33:28 +02:00
Thibaud-Vdb 1d553ff5ee ci: add plumber to watch workflow security
Runs on pushes to main and on pull requests. The config starts from
the generated defaults and is scoped to this repo: the few controls
that are off carry a note explaining why and what would let them
come back on.

Reports are uploaded to code scanning, except on PRs from forks
where the token cannot write security events. Each run on main also
publishes the score through OIDC, which feeds the live badge added
to the README next to the existing ones.
2026-07-20 15:12:58 +02:00
Pierre Tachoire 32479b1299 Merge pull request #2984 from Totara-thib/pin-actions
ci: pin github actions to commit shas
2026-07-20 15:12:03 +02:00
Thibaud-Vdb cca00c022e ci: pin github actions to commit shas
Mutable tags like @v6 can be re-pointed by whoever controls the action,
so the next run executes code nobody here reviewed, with the job's
token and secrets. Pinning to the full commit sha freezes what runs.
Version tags are kept as comments so renovate or dependabot can still
track updates.

dtolnay/rust-toolchain is pinned to a master commit with the toolchain
moved to an explicit input, as its readme recommends for sha pinning.
2026-07-20 14:56:59 +02:00
Karl Seguin 1ded9da773 Merge pull request #2995 from lightpanda-io/cookie-store
Cookie store
2026-07-20 20:16:29 +08:00
Karl Seguin 795c1a96bb Merge pull request #2988 from lightpanda-io/iframe-invalid-url
iframe: load about:blank on un-parsable URL
2026-07-20 18:50:07 +08:00
Karl Seguin 42f089780c move stripFragment to URL.zig 2026-07-20 18:47:00 +08:00
Karl Seguin 3d59f0eec2 uaf: Fix potential UAF from js-created CookieChangeEvent
Add WebDriver.getNamedCookie to give WPT access to http-only cookie.
2026-07-20 18:47:00 +08:00
Karl Seguin 4cdf8b441e webapi: Support max-age for CookieStore
Normalize get name so that it matches the normalize stored cookie name.

Don't queue cookie change event if there's no listener. This one's a bit tricky
since we do this check inside the callback already. But that means a listener
added after the event is created (but before it's delivered) gets a change
event it should not. So we need to check it both at event-creation time and
at delivery time.
2026-07-20 18:47:00 +08:00
Karl Seguin 9090869420 Merge pull request #2991 from lightpanda-io/blob-origin
webapi: Blob shared per origin
2026-07-20 18:46:34 +08:00
Karl Seguin 5736be9740 Merge pull request #2997 from lightpanda-io/robots-fix
robots.txt: Improve robots.txt correctness.
2026-07-20 18:41:23 +08:00
Karl Seguin 7a9b93becc robots.txt: Improve robots.txt correctness.
This applies two individual fixes to our robots.txt parser. The first is that
instead of doing an exact match with the User-Agent, it extracts the
"productToken". A UA of Lightpanda/1.0, should match "Lightpanda". The second is
that an empty directive matches.

Given:

User-agent: Lightpanda
Disallow:

User-agent: *
Disallow: /

We would have failed for 2 reasons. Fix #1 is necessary, otherwise
"Lightpanda" != "Lightpanda/1.0". Fix #2 is necessary  because this robots.txt
does _not_ disallow Lightpanda from anything (e.g. the fallback doesn't apply
to us).
2026-07-20 15:00:04 +08:00
Karl Seguin 0cffa933d4 Merge pull request #2996 from lightpanda-io/root-page-no-cache
cache: Never cache the top-level root page
2026-07-20 14:58:52 +08:00
Pierre Tachoire 9e1e045458 Merge pull request #2998 from lightpanda-io/wpt-change
wpt: set a memory limit per browser instead of per process
2026-07-20 08:58:09 +02:00
Pierre Tachoire af3a552af7 wpt: set a memory limit per browser instead of per process 2026-07-20 08:29:44 +02:00
Karl Seguin 299eb2c5f9 Merge pull request #2989 from lightpanda-io/http-client-no-poll-after-dispatch
perf: If a message is dispatched, don't poll
2026-07-19 08:37:42 +08:00
Karl Seguin 996815d570 zig fmt 2026-07-18 17:19:02 +08:00
Karl Seguin 86bf28216a webapi: Blob shared per origin
This reworks blob URLs from being owned by the Frame to being owned by the Page
and shared / protected by origin. This allows, for example, a worker/popup/
iframe from accessing blobs created by its page, provided they share the same
origin.

This was already working on a small (but common) set of cases, but has now been
reworked (by moving the blob registry up to the Page, where it can be shared) to
cover every case.
2026-07-18 14:24:39 +08:00
Karl Seguin 20cde7a6f5 perf: If a message is dispatched, don't poll
Polling delays processing of messages. So don't poll after we know we've
dispatched. Largely impacts CDP which is more likely to poll (for data on the
CDP connection).
2026-07-18 09:54:41 +08:00
Adrià Arrufat fc461e05a9 Merge pull request #2920 from lightpanda-io/run-command
cli: add `run` command for script replay
2026-07-17 23:59:23 +02:00
Adrià Arrufat 805b60d626 Merge branch 'main' into run-command
# Conflicts:
#	src/Config.zig
#	src/help.zon
2026-07-17 22:46:47 +02:00
Pierre Tachoire ac0e6c86a9 Merge pull request #2970 from lightpanda-io/navigation-dispose-event
Dispose Event for `NavigationHistoryEntry`
2026-07-17 15:31:06 +02:00
Karl Seguin 6b6b17240e iframe: load about:blank on un-parsable URL
Spec says this is what we should do and it's apparently used a part of bot
detections (because bots don't load about:blank and thus the iframe's state
can easily be checked to be invalid, I guess).
2026-07-17 20:45:24 +08:00
Karl Seguin 11f9777282 cache: Never cache the top-level root page
The idea is that, for most cases, the top level page isn't revisited, so
caching is just overhead + wasted space. Plus, if someone does revisit it,
chances are they want a fresh copy.

Imagine someone scraping a typical ecommerce site. Sure, they want to cache
the .js files which get re-used from product to product. But do they want to
cache each individual product page?
2026-07-17 18:55:31 +08:00
Pierre Tachoire d4ea815369 Merge pull request #2981 from lightpanda-io/help-pager
cli: page help output through $PAGER when stdout is a tty
0.3.5
2026-07-17 12:06:30 +02:00
Pierre Tachoire 8b110ff5c5 fire dispose even when currententrychange dispatch fails
The disposed entries are already out of _entries, so an error during
the currententrychange dispatch leaked their _on_dispose callbacks
(onRemoveFrame only walks _entries). Fire dispose in a defer and log
per-entry failures instead of propagating them.
2026-07-17 12:04:19 +02:00
Adrià Arrufat f02fba40cd cli: drop redundant SIGPIPE ignore in the help pager
std.start.maybeIgnoreSigpipe() already installs a noop SIGPIPE handler
at startup (std.options.keep_sigpipe defaults to false), so a write to
a dead pager returns error.BrokenPipe — which the existing catch
handles — instead of killing the process. The manual SIG_IGN was also
the disposition std deliberately avoids, since ignored dispositions
survive exec and would leak to child processes.
2026-07-17 11:50:51 +02:00
Pierre Tachoire 4a995f9544 fire dispose after currententrychange per spec 2026-07-17 11:38:11 +02:00
Pierre Tachoire 5c0c2920db release previous oncurrententrychange on overwrite 2026-07-17 11:23:03 +02:00
Pierre Tachoire bf775696de don't skip dispose dispatch when ondispose is unset 2026-07-17 11:17:05 +02:00
Pierre Tachoire a59abc7f4f Merge pull request #2972 from lightpanda-io/sanitize-utf8-headers
cdp: emit non-UTF-8 header values as Latin-1 strings, not byte arrays
2026-07-17 10:06:35 +02:00
Muki Kiboigo 1bea30ac4e clear callbacks on onRemoveFrame for Navigation 2026-07-17 01:03:47 -07:00
Muki Kiboigo b0c0b3fe3a release on dispose 2026-07-17 01:01:25 -07:00
Muki Kiboigo 9ba8d8c564 fix reentrancy on dispose and clean up 2026-07-17 01:00:06 -07:00
Muki Kiboigo 35f128d264 use hasDirectListeners for fireDispose 2026-07-17 00:57:08 -07:00
Karl Seguin b19b57250a Merge pull request #2719 from navidemad/css-layer-cascade
css: apply @layer block rules to the cascade
2026-07-17 11:49:24 +08:00
Karl Seguin 28b4a31b59 Merge pull request #2963 from lightpanda-io/dom-pr-22-allocation-lifetimes
webapi: bound scroll task allocations; tighten DOM allocation lifetimes
2026-07-17 11:28:20 +08:00
Francis Bouvier 50a896f4c0 webapi: tighten DOM allocation lifetimes
Use the call arena only for the AbortSignal dependent list that must survive re-entrant abort handlers, and move scratch-only DOM reads to the local arena. Store BeforeUnloadEvent.returnValue in the event-owned arena so it remains valid without accumulating in the longer-lived frame arena.

These allocator changes bound temporary memory to the shortest safe lifetime while preserving existing Web API behavior. Add coverage for replacing BeforeUnloadEvent.returnValue.
2026-07-17 10:52:10 +08:00
Francis Bouvier 8f42b72d18 webapi: bound element scroll task allocations
Keep one slab-allocated scheduler task per active element scroll sequence and recycle it on completion or scheduler cancellation. This prevents repeated programmatic scrolling from growing the frame arena and task queue without bound.

Advance the throttle state before dispatching scroll and scrollend so nested JavaScript callbacks cannot be overwritten, and avoid scheduling events for clamped no-op scrollBy calls. Add coverage for coalescing, both re-entrant event paths, and no-op scrolling.
2026-07-17 10:52:09 +08:00
Karl Seguin 1cebd1c1ce Merge pull request #2962 from lightpanda-io/dom-pr-21-handler-return-fragment-nav
webapi: handler return-false cancels events; same-fragment navigations don't reload
2026-07-17 10:51:28 +08:00
Karl Seguin 51dbad5a6a allow location.reload() on fragmented url to cause navigation 2026-07-17 10:40:08 +08:00
Francis BouvierandKarl Seguin 65a3ce33c0 webapi: use the local arena for the normalized hash
Review pattern from #2943: prefer the local arena for scratch-only
allocations. scheduleNavigation dupes the URL into its own arena
synchronously at entry, so the normalized fragment does not need to
survive the call.

Co-Authored-By: Karl Seguin <karlseguin@users.noreply.github.com>
2026-07-17 10:12:44 +08:00
Francis Bouvier 027936ef90 webapi: same-fragment navigations must not reload the page
After rebasing onto main, WPT
/dom/events/Event-dispatch-single-activation-behavior.html went from
3/132 to 0/0 (harness never reported): the test repeatedly clicks
`<a href="#link">` anchors and resets with `location.hash = ""`, and
both patterns ended up scheduling full same-URL reloads, putting the
page in a reload loop. As with the previous commit, the pre-rebase
code masked this because queued navigations rarely executed; the
HttpClient refactor made them reliable.

Two fixes, per the HTML navigate steps (a navigation is a fragment
navigation when the URL equals the document's URL excluding fragments
and its fragment is non-null) and the Location hash setter (if the
fragment doesn't change, no navigation happens):

- Frame.scheduleNavigationWithArena: re-navigating to the exact
  current URL is only a reload when the URL has no fragment. With a
  fragment (e.g. re-clicking the same `#link` anchor) it's now a
  no-op fragment navigation: no reload, and since the fragment didn't
  change, no hashchange and no history entry. Upstream's "identical
  URL reloads" behavior (iframe.src = "about:blank" twice) is
  untouched — those URLs carry no fragment.

- Location.setHash: skip the navigation entirely when the normalized
  fragment equals the current one, so `location.hash = ""` on a
  fragment-less URL (and re-assigning the current fragment) no longer
  schedules a same-URL reload. Assigning "" still strips the fragment
  from the URL, matching the existing tests/window/location.html
  expectations.

Unit test added in tests/window/location.html: href stays stable
across repeated `hash = ""` and same-fragment re-assignments.

Coverage: /dom/events/Event-dispatch-single-activation-behavior.html
0/0 -> 83/132 (3/132 before the rebase; the gain past 3 comes from
the handler-return-value fix in the previous commit).
2026-07-17 10:12:44 +08:00
Francis Bouvier daa3b1d451 webapi: event handlers returning false cancel the event
After rebasing onto main (HttpClient refactor: queued navigations now
reliably execute), WPT /dom/events/Event-dispatch-click.html went from
33/33 to 0/0: its form subtests cancel submission with
`form.onsubmit = () => { ...; return false }`, but the inline-handler
invocation discarded the return value, so the form really submitted,
the scheduled form navigation reloaded the page in a loop and the
harness never reported. Before the refactor the queued navigation
never ran, which masked the missing behavior.

Per the HTML "event handler processing algorithm" (§8.1.8.1, "Process
the return value"), an event handler attached via an on* property or
attribute that returns exactly false cancels the event — unlike
addEventListener listeners, whose return value is ignored. The
inverted onerror special case only applies to the global's onerror,
which is invoked via Window.reportError, not through node dispatch.

Implementation: the two inline-handler invocation sites in
EventManager.dispatchNode (at-target and bubble phase) now call the
handler with a js.Value return type and route it through a new
processHandlerReturnValue helper, which calls event.preventDefault()
when the returned value is strictly false (skipping "error" events).

Unit test added in tests/events.html covering: at-target handler,
ancestor (bubble-phase) handler, other falsy return values not
canceling, and addEventListener return values staying ignored.

Coverage: /dom/events/Event-dispatch-click.html 0/0 -> 33/33
(restores the previously claimed 33/33); also a prerequisite for
/dom/events/Event-dispatch-single-activation-behavior.html (see next
commit).
2026-07-17 10:12:44 +08:00
Karl Seguin 5160735508 Merge pull request #2961 from lightpanda-io/dom-pr-20-html-elements
webapi: cookie-averse docs, script insertion steps, moveBefore reactions, outerText
2026-07-17 10:09:25 +08:00
Karl Seguin f5ace3701f Improve gating around nodeIsReadySubtree to prevent unnecessary calls
Free temp DocumentFragment when possible
2026-07-17 09:44:19 +08:00
Karl Seguin ef91047983 Merge pull request #2964 from rohitsux/feat/cdp-navigated-within-document
feat(cdp): emit Page.navigatedWithinDocument for same-document navigations
2026-07-17 09:30:51 +08:00
Karl Seguin 0e49d6f280 Remove unused timestamp field
Move notification directly into history. Improve test.
2026-07-17 09:13:33 +08:00
Karl Seguin 7671732451 Merge pull request #2982 from lightpanda-io/focus-visible-only
reject focus() on non-rendered elements (display:none)
2026-07-17 07:50:48 +08:00
Karl Seguin 9205edb1f4 Merge pull request #2965 from lightpanda-io/script-preload
perf: Pre-parse HTML to find and preload scripts
2026-07-17 07:49:39 +08:00