CDP driver can send multiple Network.enable which would register the same
listener multiple times. This commit makes it so that only one (the first)
callback registered for a listener+eventtype is used. Subsequent registration
for the same listener+eventtype are ignored. This is safe because all callbacks
are currently static. It's a mistake (enforced by a debug-only assertion) for
code to try to register a different callback for an already registered listener+
eventtype.
This generalizes https://github.com/lightpanda-io/browser/pull/3038
std.Io.Threaded.init_single_threaded sets .allocator = .failing, which
spawnPosix uses to build the child's argv/env, so
std.process.spawn(lp.io, ...) always returns OutOfMemory and printPaged
silently fell back to plain output. Spawn the pager through a local
Threaded instance with a real allocator and the real environ (the
single-threaded one is empty, breaking PATH lookup of the less
fallback).
Centralize empty-pattern filtering in UrlBlocklist.init/initPatterns so
the CDP setBlockedURLs path matches the CLI --block-urls behavior. Keep
blocks aligned with the filtered patterns.
Reimplement request blocking on the non-deprecated urlPatterns shape:
each pattern carries an explicit block/allow flag (first match wins),
UrlBlocklist owns the compiled patterns plus their block flags, and the
legacy setBlockedUrls path stays for back-compat. Tests updated.
Include parentId on child frame navigation events and recursively serialize child frames in Page.getFrameTree using their live frame and loader IDs.
Fixes#3014
Currently, Runner assumes that HttpClient.tick did something. But it's possible
that HttpClient had nothing to do, and thus didn't poll. In that case, Runner
would return .{.ok = 0} and Runner's caller would also certainly call
Runner.tick again, resulting in a spin-loop.
The reason Runner allows this to happen is because it can still have macrotasks
to run. So now, when HttpClient.tick has done nothing, Runner will return its
ms_to_next_task, rather than 0.
On sites where all i/o is completed, and only macrotasks are waiting, this
significantly reduces CPU usage.
This gives ResizeObserver a touch up that brings it on par with how the more
flushed out IntersectionObserver behaves. While it's impossible to fully
implement this in a headless world, we can correctly emit ResizeObserverEntry
in a number of important cases, e.g. visibility change, and style width/height
changes.
Most importantly, we not execute the callback on the initial observe, which can
unlock some cases.
1 - Blocks connection to "bad" ports
2 - new WebSocket('...'); mostly returns the instance, and errors are emitted
in a close event (1)
3 - More validation (no # allowed, ...);
4 - http -> ws, https -> wss (yes, per spec)
There's also some groundwork for better float16 support, but it turns out this
will require a new v8 build to complete. So I left the harmless float16 mapping
in (but, without the matching Float16Array, it doesn't help much).
(1) Some things cause an exception to be raised, but most don't