Commit Graph

4897 Commits

Author SHA1 Message Date
Pierre Tachoire
d15c29b1a3 add dummy Performance.Navigation 2026-02-25 10:52:17 +01:00
Karl Seguin
b083910a51 Handle dynamicModuleCallback being called with undefined/null resource_name
Fixes WPT test:
/semantics/scripting-1/the-script-element/module/dynamic-import/string-compilation-of-promise-result.html
2026-02-25 17:05:40 +08:00
Pierre Tachoire
235aad32a6 add dummy PerformanceTiming 2026-02-25 08:35:53 +01:00
Karl Seguin
a818560344 Add a --with_frames argument to fetch
When set (defaults to not set/false), --dump will include iframe contents.

I was hoping I could add a mode to strip_mode to this, but since dump is used
extensively (e.g. innerHTML), this is something that has to be off by default
(for correctness).
2026-02-25 15:29:27 +08:00
Nikolay Govorov
8f179becf7 Merge pull request #1639 from lightpanda-io/wp/mrdimidium/cleanup-io-layer
Some checks failed
e2e-test / zig build release (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
e2e-test / browser fetch (push) Has been cancelled
zig-test / zig test using v8 in debug mode (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
Separates network and the browser specific t
2026-02-25 06:12:56 +00:00
Nikolay Govorov
e1695a0874 Strict visibility for Net functions 2026-02-25 05:58:08 +00:00
Karl Seguin
af7498d283 Run the MessageLoop [a lot] more.
Depends on: https://github.com/lightpanda-io/zig-v8-fork/pull/152

We previously ran the message loop every 250ms. This commit changes it to run on
every tick (much more frequently). It also runs microtasks after draining the
message loop (since it can generate microtasks).

Also, we use to run microtasks after each script execution. Now we drain the
message Loop + microtasks.

We still only drain the microtasks when executing v8 callbacks.

As part of this change, we also adjust our wait time based on whether or not
there are pending background tasks in v8 in order to try to execute them (in
general) and in a timely manner.

The goal is to ensure that tasks v8 enqueued on the foreground thread are
executed promptly.

This change is particularly useful for calls to webassembly as compilation
happens in the background and eventually requires the message loop to be drained
to continue.

Previously, if a script did `await WebAssembly.instantiate(....)`, there was
a good chance we'd never finish the code - we'd wait too long to run the
message loop AND, after running it, we wouldn't necessarily resolve the promise.
2026-02-25 13:55:35 +08:00
Nikolay Govorov
3e2a4d8053 Move curl_multi to Net layer 2026-02-25 05:31:28 +00:00
Nikolay Govorov
29982e2caf Move all curl_easy ops to Connection 2026-02-25 05:31:24 +00:00
Nikolay Govorov
5fea1df42b Move Net staff to clean network module 2026-02-25 05:31:19 +00:00
Nikolay Govorov
a041162b32 Merge pull request #1649 from ireydiak/fix/cdp-json-version-trailing-slash
fix: handle trailing slash on /json/version CDP endpoint
2026-02-25 05:20:33 +00:00
Nikolay Govorov
32cd3981d8 Update libcurl version, use build based on config file 2026-02-25 05:05:00 +00:00
Nikolay Govorov
ca5af87196 Build C libs in isolated modules 2026-02-25 05:04:58 +00:00
Nikolay Govorov
a8164f612f Use zig package manager instead of submodules 2026-02-25 05:04:57 +00:00
ireydiak
d3bb0b6ff0 fix: handle trailing slash on /json/version CDP endpoint
Some CDP clients (e.g. playwright-go) request /json/version/ with a
trailing
slash. Added handling for this variant to match the exact same behavior
as /json/version
2026-02-24 22:23:11 -05:00
Karl Seguin
0ef10c1e13 fix event leak on dispatchEvent 2026-02-25 09:36:13 +08:00
Karl Seguin
4017911373 Merge pull request #1643 from lightpanda-io/nikneym/invalid-timer-test
Add a test for invalid timer/timer-like remove
2026-02-25 09:00:53 +08:00
Karl Seguin
048034d4b1 Merge pull request #1645 from lightpanda-io/fix-empty-struct
fix: add _pad to IdleDeadline to avoid identity_map pointer aliasing
2026-02-25 08:58:58 +08:00
Karl Seguin
fcb3f08bcb Add url encoding option to URL.resolve
Given:

a.href = "over 9000!"

Then:

a.href === BASE_URL + '/over%209000!';

This commits adds an escape: bool option to URL.resolve which will escape the
path, query and fragment when true.

Also changes the Anchor, Image, Link and IFrame getSrc to escape. Escaping is
also used when navigating a frame.
2026-02-25 08:17:05 +08:00
Karl Seguin
d2a05bb622 Merge pull request #1642 from lightpanda-io/html-noscript-no-escape
Some checks failed
e2e-test / zig build release (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
e2e-test / browser fetch (push) Has been cancelled
zig-test / zig test using v8 in debug mode (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
nightly build / build-linux-x86_64 (push) Has been cancelled
nightly build / build-linux-aarch64 (push) Has been cancelled
nightly build / build-macos-aarch64 (push) Has been cancelled
nightly build / build-macos-x86_64 (push) Has been cancelled
wpt / web platform tests json output (push) Has been cancelled
wpt / perf-fmt (push) Has been cancelled
e2e-integration-test / zig build release (push) Has been cancelled
e2e-integration-test / demo-integration-scripts (push) Has been cancelled
don't escape noscript content on html dump
2026-02-25 07:31:26 +08:00
Karl Seguin
f7254ee169 Merge pull request #1641 from lightpanda-io/contexts_no_realloc
Store Env.Contexts in an [fixed-length] array.
2026-02-25 07:30:42 +08:00
Pierre Tachoire
a0e5c9d570 add padding field for some other webapi 2026-02-24 21:36:38 +01:00
Pierre Tachoire
8291e4ba73 fix: add _pad to IdleDeadline to avoid identity_map pointer aliasing 2026-02-24 21:31:41 +01:00
Pierre Tachoire
b324be3b0b Merge pull request #1638 from lightpanda-io/performance-mark-name
accept more performance mark name and return dummy 0
2026-02-24 19:15:04 +01:00
Halil Durak
6ba0ba7126 add a test for invalid timer removal
We cover such cases; yet its better to have a test.
2026-02-24 18:25:26 +03:00
Pierre Tachoire
1d8e0629af don't escape noscript content on html dump 2026-02-24 15:22:43 +01:00
Pierre Tachoire
42df54869f performance: use a comptime StaticStringMap for string comparison 2026-02-24 15:18:25 +01:00
Karl Seguin
7b758b85ec fix test 2026-02-24 19:41:15 +08:00
Karl Seguin
82987ec401 Store Env.Contexts in an [fixed-length] array.
We currently store all of the env's contexts in an ArrayList. When performing
micro/macro tasks, we iterate through this list and perform the micro/macro
tasks. This can result in the ArrayList being invalidated (e.g. a microtask can
result in a context being created, a promise resolving and creating an iframe).
Invalidating the arrylist while we iterate through it is a use-after-free.

This commit stores contexts in a fixed array (64) so that it doesn't move.
Iteration is slower, unfortunately, as the new `env.context_count` has to be
checked.

Fixes WPT crash on
/html/cross-origin-embedder-policy/cross-origin-isolated-permission-iframe.https.window.html url=http://web-platform.test:8000/html/cross-origin-embedder-policy/cross-origin-isolated-permission-iframe.https.window.html

This commit also prevents microtasks execution from causing microtask execution.
On the above test, I saw runMicrotasks which I don't think we're supposed to do.
2026-02-24 19:26:43 +08:00
Pierre Tachoire
71707b5aa7 accept more performance mark name and return dummy 0 2026-02-24 09:12:18 +01:00
Karl Seguin
ca2df83928 Merge pull request #1637 from lightpanda-io/page_url_log
Some checks failed
e2e-test / zig build release (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
e2e-test / browser fetch (push) Has been cancelled
zig-test / zig test using v8 in debug mode (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
Include url in page logs
2026-02-24 15:55:26 +08:00
Karl Seguin
085771c2f0 Merge pull request #1636 from lightpanda-io/null_GetOwnPropertyNames
Handle v8:Object::GetOwnPropertyNames returning null
2026-02-24 15:55:10 +08:00
Karl Seguin
607a638858 Merge pull request #1635 from lightpanda-io/frame_shared_memory
All frames must share the same Arena/Factory
2026-02-24 15:54:29 +08:00
Karl Seguin
5f6d06d05d Merge pull request #1634 from lightpanda-io/event_rc
Add [basic] reference counting to events
2026-02-24 15:53:52 +08:00
Karl Seguin
19ecb87b07 Include url in page logs
Wasn't really needed before frames and multithreading,but it's pretty essential
now to figure out what's going on. Probably needs to be applied more
broadly.
2026-02-24 15:11:20 +08:00
Karl Seguin
2a332c0883 Handle v8:Object::GetOwnPropertyNames returning null
This seems to only happen in error cases, most notably someone changes the
object to return an invalid ownKeys, as we see in WPT
/fetch/api/headers/headers-record.any.html
2026-02-24 13:31:34 +08:00
Karl Seguin
bb773c6c13 All frames must share the same Arena/Factory
This is a bit sad, but at least for now, all frames must share the same
page.arena and page.factory (they still get their own v8::Context and
call_arena).

Consider this case (from WPT /css/cssom-view/scrollingElement.html):

```
    let nonQuirksFrame = document.createElement("iframe");
    nonQuirksFrame.onload = this.step_func_done(function() {
      var nonQuirksDoc = nonQuirksFrame.contentDocument;
      nonQuirksDoc.removeChild(nonQuirksDoc.documentElement);
    });
    nonQuirksFrame.src = URL.createObjectURL(new Blob([`<!doctype html>`], { type:
"text/html" }));
    document.body.append(nonQuirksFrame);
```

We have the root page (p0) and the frame page (p1). When the frame (p1) is
created, it's [currently] given its own arena/factory and parses the page. Those
nodes are created with p1's factory.

The onload callback executes on p0, so when we call removeChild that's executing
with p0's arena/factory and tries to release memory using that factory - which
is NOT the factory that created them.

A better approach might be that _memory_ operations aren't tied to the current
calling context, but rather the owning document's page. But:
1 - That would mean we have 2 execution contexts: the v8 context where the code
    is running, and the memory context that owns the code
2 - Nodes can be disconnected, what page should we use?
3 - Some operations can behave across frames, p0 could adoptNode on p1, so we'd
    have to carefully use p1's factory when cleaning up and re-create the node
    in p0's factory.

So much hassle.

Using a shared factory/arena solves these problems at the cost of bloat - when
a frame goes away or navigates, we can't free its old memory. At some point, we
should fix that. But I don't have a quick and easy solution, and sharing the
arena/factory is _really_ quick and easy.
2026-02-24 12:57:05 +08:00
Karl Seguin
238de489c1 Add [basic] reference counting to events
Previously, we used a boolean, `_v8_handoff` to detect whether or not an event
was handed off to v8. When it _was_ handed off, then we relied on the Global
finalizer (or context shutdown) to cleanup the instance. When it wasn't handed
off, we could immediately free the instance.

The issue is that, under pressure, v8 might finalize the event _before_ we've
checked the handoff flag. This was the old code:

```zig
    const event = try Event.initTrusted(.wrap("DOMContentLoaded"), .{ .bubbles = true }, self);
    defer if (!event._v8_handoff) event.deinit(false);
    try self._event_manager.dispatch(
        self.document.asEventTarget(),
        event,
    );
```

But what happens if, during the call to dispatch, v8 finalizes the event? The
defer statement will access event after its been freed.

Rather than a boolean, we now track a basic reference count. deinit decreases
the reference count, and only frees the object when it reaches 0. Any handoff
to v8 automatically increases the reference count by 1. The above code becomes
a simpler:

```zig
    const event = try Event.initTrusted(.wrap("DOMContentLoaded"), .{ .bubbles = true }, self);
    defer event.deinit(false);
    try self._event_manager.dispatch(
        self.document.asEventTarget(),
        event,
    );
```

The deinit is un-conditional. The dispatch function itself increases the RC by 1,
and then the v8 handoff  increases it to 2. On v8 finalization the RC is
decreased to 1. The defer deinit decreases it to 0, at which point it is freed.

Fixes WPT /css/css-transitions/properties-value-003.html
2026-02-24 12:31:20 +08:00
Karl Seguin
6b4db330d8 Merge pull request #1629 from lightpanda-io/script_event_dispatch
Use EventManager.dispatch for Script events
2026-02-24 09:46:38 +08:00
Karl Seguin
ea5d7c0dee Use EventManager.dispatch for Script events
Should be updated and merged after:
https://github.com/lightpanda-io/browser/pull/1623 else we'll have a double-free.

The ScriptManager used to directly call the "onload" and "onerror" attributes.
The implementation predates EventManager.dispatch support attribute-based
callbacks. But now the EventManager is attribute-aware and correctly times
the attribute dispatch AND details such as cancellation. So this commit moves
the old attribute-only ScriptManager-specific callback to the EventManager.

With one little wrinkle: 'load' listeners added during a script's execution
should NOT receive a 'load' event when the script finishes. This makes no
sense to me. The EventManager now maintains an ignore_list for "load" events
which is reset after each script execution. A comptime flag is passed to
dispatch to indicate whether the ignore list should be checked. This is only
ever set when the ScriptManager dispatches the 'load' event, so there's no
overhead to dispatch for most events.
2026-02-24 08:50:04 +08:00
Karl Seguin
0f189f1af3 Merge pull request #1628 from lightpanda-io/optimize_resource_load_event
Optimize Resource "load" event
2026-02-24 08:43:00 +08:00
Karl Seguin
0f1b8dd51a Optimize Resource "load" event
An amazon product page has 345 resources and not a single DOM "load" listener.
This, I believe, is pretty common (reddit also has no "load" listener). So this
is a simple optimization to skip dispatching the resource "load" event when
there's no listener for it.

The check could be more granular, i.e. checking the specific parents of the
element. But I believe the global no "load" listener is common enough that this
simpler approach is the best.

The worst case is that we dispatch unnecessary "load" events, which is exactly
what the code was doing before.
2026-02-24 07:30:15 +08:00
Karl Seguin
d7e6946a78 Merge pull request #1632 from lightpanda-io/Response_arrayBuffer
Some checks failed
e2e-test / zig build release (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
e2e-test / browser fetch (push) Has been cancelled
zig-test / zig test using v8 in debug mode (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
nightly build / build-linux-x86_64 (push) Has been cancelled
nightly build / build-linux-aarch64 (push) Has been cancelled
nightly build / build-macos-aarch64 (push) Has been cancelled
nightly build / build-macos-x86_64 (push) Has been cancelled
wpt / web platform tests json output (push) Has been cancelled
wpt / perf-fmt (push) Has been cancelled
e2e-integration-test / zig build release (push) Has been cancelled
e2e-integration-test / demo-integration-scripts (push) Has been cancelled
Add Response.arrayBuffer()
2026-02-24 07:27:20 +08:00
Karl Seguin
255b7b1a54 Merge pull request #1631 from lightpanda-io/improve_tests_outside_of_runner
Improve tests when running outside of our test runner
2026-02-24 07:27:08 +08:00
Karl Seguin
79e1c751a1 Merge pull request #1630 from lightpanda-io/getpeername
Log actual client address
2026-02-24 07:26:52 +08:00
Karl Seguin
fc745b9614 Merge pull request #1627 from lightpanda-io/dom_load_no_window
Don't bubble "load" event to Window
2026-02-24 07:24:58 +08:00
Karl Seguin
95b1baebd2 Merge pull request #1626 from lightpanda-io/optimize_property_and_noop_functions
Optimizes properties and noop functions
2026-02-24 07:24:45 +08:00
Karl Seguin
56fe1ceb97 Merge pull request #1623 from lightpanda-io/finalizer_tweaks
Tweak Finalizer callbacks
2026-02-24 07:24:29 +08:00
Karl Seguin
863a51e556 Merge pull request #1614 from lightpanda-io/fix_v8_context_queue_lifetime
Improve Context shutdown
2026-02-24 07:24:18 +08:00
Karl Seguin
69b3064b45 Add Response.arrayBuffer() 2026-02-23 19:53:57 +08:00