This introduces `adblock`; which implements parsing rules required to generate `NetworkFilter`s out of fed easy list bytes. Cosmetic filters and conditionals are currently omitted.
Some WPT tests just take more memory, e.g. shadow-dom/declarative/gethtml.html.
Also left some placeholder comments for profiling JS (which I used to make sure
this was just v8 memory usage). These placeholders used to exist but didn't
survive the session multi-page refactor (figured I'd fix it next time I needed
it, and now I needed it).
Supports prebuild-v8 shared library and adds a `download-v8-shared` make target.
Depends on: https://github.com/lightpanda-io/zig-v8-fork/pull/198
The auto-discovery of the .so is done in the build.zig, which is different than
the auto-discovery of the .a which is done in the Makefile. This is intentional
and if we inverse -Ddev_fast so that it's on by default, the .a's auto discovery
will be moved to build.zig for consistency and explicitness. As-is, we have no
way to tell whether -Dprebuilt_v8_path=v8.a is being injected by Makefile or
is explicit (which isn't a problem so long as we're not doing dev_fast by
default).
Saw a non-fatal error on cnn.com related to console. All members are supposed
to be static. Ran it through WPT /console/ and improved a few different thigns:
- added dir and dirxml
- assert condition is optional
Cancel termination only when all context have a call_depth == 0. This ensures
that termination "sticks" all the way up a nested call. Without this, a nested
call could clear a terminate which targeted something up the stack.
A JS entry (JSEntry) clears V8's terminating state when the termination
exception unwinds past it, which is what tryCall and friends rely on.
A microtask checkpoint does not: when a requested termination (watchdog,
CDP-disconnect kill) lands inside a checkpoint-delivered callback such
as MutationObserver delivery, PerformCheckpoint returns with
IsExecutionTerminating still set and nothing ever clears it. Every
later V8 call in that isolate then runs against a terminating isolate
and can return empty where callers don't expect it, ending in SIGSEGV
during connection teardown.
Cancel the V8-level termination after a checkpoint in which a terminate
landed, keeping the sticky terminate_requested so the existing entry
gates keep refusing new JS, and skip the remaining context queues.
Production-observed sequence this covers (SIGSEGV/139 tails):
watchdog stall -> MutObserver.deliverRecords err=ExecutionTerminated
-> frame.deliverMutations -> closing connection (pending terminate)
-> SIGSEGV
Assisted-By: devx/95b8cb7f-8baf-4a28-93bf-61bc21612890
Split active_conns and active_threads to free a CDP conn slot as soon as
possible.
It gives a room where we have more active threads than allowed CDP
connections while threads shudown.
Adds the getHTML methods to Element and ShadowRoot. This is expected to add
another ~6K passing WPT tests (significantly improving out score in the
/shadow-dom/ category). It's also probably also a useful API to implement.
All add/remove node operations come down to Frame.removeNode and
Frame._insertNodeRelative. But not all remove/insert are the same, e.g. removing
a disconnect node is different than removing a connected node. Also, a "move"
operation is a remove+insert, but some move operations appear more atomic than
others. There is both a correctness and an optimization side to these
differences.
Previously, removeNode took a will_be_reconnected: bool option and insert took
a child_already_connected: bool. Essentially, remove wants to know the
post-removal intention, and insert wants to know the pre-insert state.
The simple booleans work for simple cases, but fail for ShadowDOM: it isn't
enough to know if `will_be_reconnected`...we need to know in what root it'll
be reconnected. Both remove and insert become tristate:
1 - is staying in the same root
2 - is staying connected, but in a different root
3 - is becoming connected for the first time
This commits changes `will_be_reconnected: bool` to `reconnect_to: ?*Node` and
`child_already_connected: bool` to `previous_root: ?*Node`. So most callsites
had to be updated - which is why so many files were touched. But the bulk of
the change is in those two Frame method which must now handle the tristate.
buildJSONVersionResponse() previously formatted whatever Config.advertiseHost()
returned straight into webSocketDebuggerUrl. When serve was started with
--host 0.0.0.0 (or ::) without an explicit --advertise-host, advertiseHost()
returned the literal wildcard, so CDP discovery handed remote clients a
URL like ws://0.0.0.0:9222/ that can never be dialed. This was the root
cause reported in issue #1922: Playwright MCP and chromedp fail with
ECONNREFUSED when connecting through the official Docker image, which
sets --host 0.0.0.0 unconditionally.
AdvertiseHost now substitutes 127.0.0.1 for wildcard binds so the
discovery URL stays connectable from the same host (covers the official
Docker image via its published port, plus WSL's localhost bridge).
Users who serve from a dedicated interface can still pin the URL with
--advertise-host.
buildJSONVersionResponse now emits a one-time log.note when the bind
host is a wildcard so operators know to set --advertise-host for
multi-host setups. Tests cover the wildcard, the explicit-override and
the concrete-host cases.