Commit Graph

6001 Commits

Author SHA1 Message Date
Karl Seguin
87b7ebfc00 Merge pull request #2340 from lightpanda-io/tick_efficiency
More aggressive popup cleanup, more efficient load tick
2026-05-04 11:29:24 +08:00
Karl Seguin
cf04873d7a Merge pull request #2334 from lightpanda-io/script_mode
Split Script
2026-05-04 11:28:25 +08:00
Karl Seguin
150c401a27 Merge pull request #2313 from lightpanda-io/callback_fixes
Fix more DOM assumptions that callback and document.write can break
2026-05-04 11:28:05 +08:00
Karl Seguin
501bfe65f0 Merge pull request #2333 from webcoyote/display-dynamic-port
Display actual port when binding --port 0
2026-05-04 11:15:58 +08:00
Karl Seguin
ab93cbb56c Merge pull request #2318 from lightpanda-io/atob_btoa
Fix atob/btoa
2026-05-04 08:29:11 +08:00
Karl Seguin
0da32a73b7 Merge pull request #2337 from lightpanda-io/about_blank_navigation_assertion
Fix failed navigation assertion
2026-05-04 08:27:28 +08:00
Karl Seguin
9bea9c9dc7 Merge pull request #2347 from lightpanda-io/fix/summary-click-toggles-details
Fix/summary click toggles details
2026-05-04 08:26:57 +08:00
Karl Seguin
1b90ef58be Summary click opens details
Tweak on https://github.com/lightpanda-io/browser/pull/2342
2026-05-04 08:02:56 +08:00
Karl Seguin
e69bcfa4da Merge pull request #2345 from lightpanda-io/fix/cookie-samesite-json-case-guyua9
Fix/cookie samesite json case guyua9
2026-05-02 13:30:25 +08:00
Karl Seguin
3ec507773c change sameSite to string to deal with case-insensitive values 2026-05-02 12:10:57 +08:00
Karl Seguin
4704185980 Merge pull request #2341 from lightpanda-io/script_manager_encode
Encode script urls before making request
2026-05-02 09:39:17 +08:00
swaroski
55b5c134dc dom: toggle parent <details>.open on <summary> click
Per HTML §4.11.1.2, a <summary>'s activation behavior runs the
toggle-details-state algorithm on its parent <details>, but only when
the summary is the first summary child of that details.

Frame.handleClick previously had no arm for .generic, so summary clicks
fell into `else => {}` and details.open never changed. Add a .generic
arm gated on `_tag == .summary` that walks the parent's element
children to confirm first-summary-child, then flips details.open via
the existing Details.setOpen.

Out of scope (tracked separately): firing ToggleEvent on the parent
(no ToggleEvent type yet); activating when a descendant of <summary>
is clicked (same gap exists for <a>/<label>; needs a broader walk-up
refactor of handleClick).

Tests: src/browser/tests/element/html/summary_click.html covers
closed→open, open→closed, non-first summary no-op, and orphan summary
no-op.
2026-05-01 18:31:01 -04:00
Pierre Tachoire
47ea77f7b2 Merge pull request #2286 from navidemad/fix-b6-validity-api 2026-05-01 20:53:53 +02:00
Pierre Tachoire
76deb2552a fix Input.sameFormOwner regression 2026-05-01 18:40:49 +02:00
Karl Seguin
9fdd13a626 Encode script urls before making request
This comes from a WPT crash in /content-security-policy/blob/self-doesnt-match-blob.sub.html

The core issue is double-free on the request header list. This is a fundamental
issue about ambiguous ownership. On error, who's responsible for freeing the
request? The caller or the HttpClient. Answer: it depends when/where the error
happens. That just doesnt' work, and needs to be fixed. BUT....

There's also the issue that this specific test is failing because we aren't
properly encoding script URLs. This is a real and separate issue that also needs
to be fixed. That's what this commit does. In some ways, it's a bit superficial
because there's a real double-free issue, but this is a real issue to fix.
2026-05-01 13:00:12 +08:00
Karl Seguin
560b15c9b2 update v8 dep 2026-05-01 09:11:16 +08:00
Karl Seguin
2b95b1e743 More aggressive popup cleanup, more efficient load tick
Follow up to https://github.com/lightpanda-io/browser/pull/2335 which hooks
into the tick's GC hint to close any closed window (rather than having to wait
until page unload).

Also, use schedule task for dispatchLoad which removes an check in every tick.
2026-05-01 09:06:47 +08:00
Navid EMAD
604f812827 forms: address review feedback on constraint validation API
- Cache `ValidityState` per element so repeated `el.validity` access
  returns the same instance (also avoids allocating a struct per
  per-keystroke call).
- Use `Event.initTrusted` for the `invalid` event — browser-generated.
- Use `frame.dupeString(message)` (interns short strings) instead of
  `frame.arena.dupe(u8, message)` for `setCustomValidity` storage.
- Cascade `*const Input` / `*const Select` through `getValidationMessage`,
  `suffersValueMissing`, and Select.effectiveOption.
- Factor radio-group walking into a shared `radioGroupIterator`; add the
  same-form check to `radioGroupHasChecked` (was only in
  `uncheckRadioGroup`). The form comparison uses a frame-less helper so
  it can run from the const validation path.
- Narrow `numericRangeBreach` to `.number, .range` — date/time/month/
  week/datetime-local need type-specific conversion before comparison
  (was silently returning false). TODO comment left in place.
- Add `getMinLength`/`setMinLength` getters to Input and TextArea, plus
  `getMaxLength`/`setMaxLength` to TextArea (Input already had them).
  Used internally by `suffersTooLong`/`suffersTooShort` and exposed via
  IDL.
- TODO prefix on the file-input value-missing comment so the limitation
  is greppable.

Tests cover the new IDL surface (`minLength`/`maxLength` on Input and
TextArea), the validity-state caching guarantee
(`el.validity === el.validity`), and the trusted-event flag on the
`invalid` event for Input, Select, TextArea, and Button.
2026-04-30 22:35:44 +02:00
Karl Seguin
b254671fa1 Fix failed navigation assertion
When the root frame navigates to about:blank, we still need to create an
navigation entry, else navigation's expectation (via assertions) fail.
2026-04-30 22:54:22 +08:00
Pierre Tachoire
9a9e79ebc1 Merge pull request #2328 from lightpanda-io/ci-cdp-log
ci: save cdp logs by using cdpproxy
2026-04-30 14:55:35 +02:00
Karl Seguin
216cec5e42 Merge pull request #2335 from lightpanda-io/window_close
Defer window.close()
2026-04-30 19:58:21 +08:00
Pierre Tachoire
ba28324a9e ci: save cdp logs by using cdpproxy 2026-04-30 12:35:30 +02:00
Karl Seguin
f921869fb6 Defer window.close()
Cannot Frame.deinit in window.close() as that's happening inside JS runtime.
Instead, defer on Page.deinit. This is MUCH later than necessary, but I'd like
to address the timing separately. This commit, as-is, prevents real crashes.
2026-04-30 18:04:56 +08:00
Karl Seguin
fe77694437 Merge pull request #2310 from navidemad/fix-a22-iscontenteditable
dom: implement HTMLElement.isContentEditable IDL attribute
2026-04-30 16:09:56 +08:00
Karl Seguin
a591956dcc Split Script
This is a follow up to https://github.com/lightpanda-io/browser/pull/2290. That
PR spit ScriptManager into ScriptManager and ScriptManagerBase, with the
goal of letting a Worker have a ScriptManagerBase that works without needing
a frame.

But the Script object was still a large object meant to work with any type of
script invocation, e.g. it has a nullable element. This commit swaps out these
fields for a better-typed "extra" union field. So that Element only exists in
the extra.frame tag. In the end, it just makes it more explicit about what
fields are valid under specific conditions.
2026-04-30 15:30:37 +08:00
Navid EMAD
2af95af678 dom: return false from isContentEditable, log when spec says true
Per maintainer review (PR #2310), Lightpanda has no caret/keyboard editing
pipeline, so honoring the spec-correct value risks routing downstream CDP
clients (notably Puppeteer's dispatchKeyEvent path) into an input pipeline
that silently no-ops. Switch to always returning false and emit
log.info(.not_implemented, "IsContentEditable", .{}) when the spec walk
would have produced true, so the unsupported case surfaces in telemetry
rather than masquerading as a working state.

The HTML §7.7.5.2 walk is preserved (nearest ancestor with `contenteditable`
wins, "false" disables) but only used to gate the log emission. The fixture
is reduced to assert the always-false return across the same shape of
inputs, with a comment pointing back at the rationale.
2026-04-30 07:28:43 +02:00
Patrick Wyatt
47d96ab8ad Display actual port when binding --port 0
This change causes lightpanda to display the actual port number (instead of 0)
when binding a dynamic port (--port 0), which makes automating based on
scraping lightpanda output simple.
2026-04-29 21:44:41 -07:00
Karl Seguin
e42acc5335 Merge pull request #2322 from navidemad/fix-a27-prompt-default-text
cdp: fall back to dialog defaultText when LP.handleJavaScriptDialog promptText is null
2026-04-30 12:12:33 +08:00
Karl Seguin
2c52e9b34c Merge pull request #2324 from navidemad/fix-a28-label-click-activation
dom: run label activation behavior on click
2026-04-30 11:56:59 +08:00
Karl Seguin
dd4a46dc16 Merge pull request #2331 from sunguru98/bugfix/element-getelements-by-tagname
browser: change node filter from lower to tag_name
2026-04-30 11:56:29 +08:00
Karl Seguin
64fbd55746 Merge pull request #2327 from lightpanda-io/nikneym/httponly-cookie
`Cookie`: don't allow JS context to mutate HttpOnly cookies
2026-04-30 11:52:44 +08:00
Sundeep Charan Ramkumar
91c0edddad browser: change node filter from lower to tag_name 2026-04-30 08:28:18 +05:30
Karl Seguin
1f40c30901 Merge pull request #2290 from lightpanda-io/worker-script-manager-split
Split ScriptManager to support worker module imports
2026-04-30 10:27:54 +08:00
Karl Seguin
896adc14d0 Merge pull request #2299 from lightpanda-io/idn
Initial idn support
2026-04-30 09:30:38 +08:00
Karl Seguin
c2a1b6fd64 Split ScriptManager to support worker module imports
Extract module-loading plumbing into ScriptManagerBase so workers can
use it. Previously Context.script_manager was null for worker contexts,
which crashed on dynamic import() via the unwrap in dynamicModuleCallback.

ScriptManagerBase owns the HTTP fetch + V8 module resolution path
(preloadImport, waitForImport, getAsyncImport, resolveSpecifier, the
Script struct) and reaches per-owner fields through an Owner union.
ScriptManager wraps it for Frame and keeps the parser/DOM-bound surface
(addFromElement, parseImportmap, Frame-specific evaluate tail via
tail_hook). WorkerGlobalScope gets its own ScriptManagerBase directly.

This is similar to the work done in https://github.com/lightpanda-io/browser/pull/2093
which split EventManager into EventManager + EventManagerBase (for the same
reason).

add tests
2026-04-30 09:05:51 +08:00
Karl Seguin
39d9ac9b4c Merge pull request #2285 from lightpanda-io/form_submitter
Form Submitter should only override when it's a submit input
2026-04-30 08:47:20 +08:00
Karl Seguin
ce2f6d9bdb Form Submitter should only override when it's a submit input 2026-04-30 08:19:21 +08:00
Karl Seguin
20e1aeaacb Merge pull request #2282 from lightpanda-io/input_file
Input file foundation
2026-04-30 08:09:23 +08:00
Karl Seguin
3f11e6148e Merge pull request #2296 from lightpanda-io/crypto_generateKey_errors
Improve correctness of generateKey error
2026-04-30 08:08:52 +08:00
Halil Durak
0c3d5573f0 Cookie: don't allow JS context to mutate HttpOnly cookies
Changes function signature for `Jar.add` in order to do this, not sure if we should have separate functions for that or comptime-if sufficient.
2026-04-29 17:40:48 +03:00
Navid EMAD
3b3e4e4129 Merge remote-tracking branch 'origin/main' into fix-b6-validity-api 2026-04-29 15:49:37 +02:00
Navid EMAD
31e0e7c81a dom: run label activation behavior on click
`Frame.handleClick` had no `.label` arm, so clicking an `HTMLLabelElement`
fired the click event but never dispatched the synthetic click activation
on the labeled control. Per HTML §4.10.4 "The label element", a label's
activation behavior is to run the synthetic click activation steps on the
labeled control; without it `cb.checked` stays unchanged when the click
target is a `<label>`.

Resolve the labeled control via the existing `Label.getControl(frame)`
(handles both `for=` and the wrapping-descendant case) and call `.click()`
on it, mirroring Chrome's `HTMLLabelElement::DefaultEventHandler`.

Closes #2323
2026-04-29 15:24:42 +02:00
Navid EMAD
71af170658 cdp: fall back to dialog defaultText when LP.handleJavaScriptDialog promptText is null
When a CDP client pre-arms `LP.handleJavaScriptDialog {accept: true}` with
no `promptText` and the page subsequently calls `window.prompt(message,
defaultText)`, Lightpanda discarded the dialog's `defaultText` argument
and returned `""`. Chrome's behavior is to surface `defaultText` as the
prompt's return value — that's the natural "user accepted without typing
anything" outcome per the HTML simple-dialog algorithm.

The fix is one line in `Window.zig`'s `prompt` JS binding: keep the
second argument named (`default_text` instead of `_`) and use it as the
fallback. Pre-armed `promptText` still wins when the client supplies it;
`accept = false` still returns null regardless. When neither
`promptText` nor `defaultText` is provided, the binding still returns
`""` per the CDP spec.

Adds four new assertions to the existing `cdp.lp` integration test
covering the matrix: defaultText fallback (no promptText), promptText
overrides defaultText, accept=false ignores defaultText, and the
existing no-defaultText case continues to return `""`.
2026-04-29 15:01:18 +02:00
Pierre Tachoire
6e881e0a9e Merge pull request #2320 from lightpanda-io/wp/mrdimidium/fix-crash-on-frame-deinit
Fix segfault on Frame deinit
2026-04-29 14:45:10 +02:00
Navid EMAD
d66c7aad50 Merge remote-tracking branch 'origin/main' into fix-a22-iscontenteditable 2026-04-29 14:40:12 +02:00
Nikolay Govorov
91f5988fe5 Fix segfault on Frame deinit 2026-04-29 13:33:10 +01:00
Karl Seguin
f7c3ccaf85 initial (file-free) multi-part form encoding 2026-04-29 19:19:34 +08:00
Karl Seguin
7c40d2fb98 FormData File support
Move FormData from using KeyValueList to using its own List(Entry), where
entry's value is a union over a String or File. Preparatory stuff for input
type=file support.
2026-04-29 19:19:33 +08:00
Karl Seguin
e981ec7587 Merge pull request #2319 from lightpanda-io/fix-popup-close-queued-nav
On Window.close, remove any queued navigation
2026-04-29 19:19:20 +08:00
Karl Seguin
b375603258 On Window.close, remove any queued navigation 2026-04-29 18:59:35 +08:00