Two fixes for crash handling:
1. Re-setup output capture after WebContent respawns. When WebContent
crashes, a new process is spawned with new stdout/stderr pipes.
We need to set up new notifiers to drain them, otherwise the new
WebContent blocks on write() when its pipe buffer fills up.
2. Disconnect child view crash handlers between tests. Child views
(from window.open, iframes, etc.) persist after a test completes.
If they crash later, we don't want that to affect subsequent tests.
The timeout timer for ref tests was stored in a local variable that
went out of scope when run_ref_test() returned, causing the timer to
be destroyed before it could fire.
Store the timer in test.timeout_timer (like dump tests already do)
so it persists until the test completes.
When multiple views share a WebContent process (e.g. parent and child
views created via window.open()), we need to notify ALL of them when
the process crashes, not just one.
Previously, each view would overwrite the single crash callback on
WebContentClient, so only the last view to initialize would be notified.
This adds WebContentClient::notify_all_views_of_crash() which iterates
over all registered views and notifies each one. Child views also now
propagate crashes to their parent, and can be disconnected between
tests to prevent stale crashes from affecting subsequent tests.
Async IPC messages are fire-and-forget by design. If the peer has
disconnected (e.g. crashed), attempting to send will fail, but there's
nothing meaningful we can do about it.
Change the generated code from MUST() to (void) so we don't crash when
trying to send async messages to a dead peer.
When a WebContent process crashes, its stdout/stderr pipes will signal
POLLHUP. The output capture notifiers were not handling this case,
causing the event loop to spin at 100% CPU as poll() kept returning
immediately with POLLHUP set.
Fix by disabling the notifiers when read() returns 0 or an error.
After a WebContent process crashes, the view's client is no longer
valid. Calling reset_zoom() would attempt to send IPC messages to the
dead process. Skip this operation when the test result indicates a
crash.
This commit makes several improvements to crash handling for headless
mode (used by test-web and other automated tools):
1. Always respawn WebContent after crashes, ignoring the crash count
limit. The limit is meant for interactive use to prevent infinite
crash loops; in headless mode, each test needs a working WebContent.
2. Skip the error page when respawning, as there's no UI to display it.
3. Suppress crash log messages that would corrupt live terminal output.
These changes allow test-web to properly recover from WebContent crashes
and continue running subsequent tests.
When a child process exits, the SIGCHLD handler was destroying the
Process object synchronously within the signal dispatch context. This
triggered Process::~Process() which called m_connection->shutdown(),
attempting to join the IPC IO thread.
Joining threads from within signal handler context can cause deadlocks,
as observed when WebContent crashes during test-web runs.
Fix this by deferring the on_process_exited callback using
Core::deferred_invoke(), ensuring the Process destruction happens in
normal event loop context.
The wakeup pipe is created with O_NONBLOCK, but MUST() was used for
reads. This could cause crashes on spurious wakeups when EAGAIN is
returned. Since the read is just to drain the pipe and wake the IO
thread, we can safely ignore any errors.
- Generate colorized HTML diff files (.diff.html) alongside plain text
diffs (.diff.txt) for each failing test
- Add total test count to results summary
- Improve the results-index.html viewer with a dark theme, keyboard
navigation, search/filter, and tabbed interface for viewing diffs,
expected/actual output, and stdout/stderr
- Move s_total_tests assignment outside live display block so it's
always set
- Add --results-dir CLI flag to specify output directory
- Default to {tempdir}/test-web-results if not specified
- Capture stdout/stderr from all helper processes (WebContent,
RequestServer, ImageDecoder) to prevent output spam
- Save captured output to per-test files in results directory
- Save test diffs (expected vs actual) to results directory
- Generate HTML index of failed tests with links to diffs
- Display live-updating concurrent test status with progress bar
- Defer warning messages until after test run completes
Issue #6294 describes an edge case where the browser crash if the same
module is loaded three times in a document, but all attempts fail.
Failure scenario:
1. Module load 1 set the state to "Fetching"
2. Module load 2 registers a callback to `on_complete` since the
current state is "Fetching"
3. Module load 1 finish with a failure, invoking the callback for load
number 2
4. Module load 3 cause a crash. The state is neither "Fetching" or
"ModuleScript", so we'll reset the state to "Fetching". This invokes
the callback for module load 2 again, now with an unexpected state
which will cause an assert violation.
Proposed fix is to remove the condition that invokes `on_complete`
immediately for successfully loaded modules only, the callback should
be invoked regardless of whether the fetch succeeded or failed.
This reveals a separate bug in HTMLScriptElement, where
`mark_as_ready()` can be invoked before
`m_steps_to_run_when_the_result_is_ready` is assigned.
This appears to be a spec bug, reported as
https://github.com/whatwg/html/issues/12073 and addressed by delaying
the callback by a task, similar to the issue was resolved for inline
scripts.
In the next commit, we will rely on global scope's URL being
initialized even earlier in the process of setting up the environment
for the Worker global. Move this hack just before that.
This change is currently entirely undetectable because of what the
added FIXME talks about. Currently, the HTML element's overflow is
always set to visible in both axes, so it getting set to "clip" in
the imported test ends up not mattering at all.
Previously we would just set the attributes to the serialized
descriptors, even if they were the empty string.
We now apply defaults when we have empty descriptors and apply parsing
logic from the various `set_*` methods (only applicable to `font-family`
so far where we now extract the value from either a string or a
custom-ident)
Fixes an issue in some css/css-shapes WPT tests where we weren't
properly matching fonts.
Previously we would always try to load the font URL relative to the
document's base URL. This commit means that for CSS-connected
`FontFace`s we now try to load relative to the URL of the stylesheet
that contains the associated `CSSFontFaceRule`
The spec states that updates to descriptors in a `@font-face` rule
should be reflected in the connected `FontFace`'s attributes.
Previously this was achieved by directly accessing those descriptors
when calling the attribute getters, but this has a couple of issues:
a) The changes are only reflected if we use the accessors (i.e.
`FontFace::family()` rather than `FontFace::m_family`) which isn't
the case everywhere
b) The changes aren't persisted after the `FontFace` is disconnected
from it's `CSSFontFaceRule`
To fix these issues we now reparse and store the `FontFace`'s attributes
whenever the `CSSFontFaceRule`'s descriptors change.
This means we now allow oblique angles when parsing the `font`
shorthand.
This also required us to rename the existing `FontStyle` enum to
`FontStyleKeyword`
Use the newly added `partial interface mixin` support to move the
CSS animation event handler attributes to their proper location as
specified in CSS Animations Level 1.
This adds parsing support for `partial interface mixin` as specified
in WebIDL. Partial mixins are merged into their corresponding mixins
before the mixins are resolved into interfaces.
Previously, setting designMode to "on" would only modify the selection
range if one already existed. Since selections start empty, this meant
no range was created and no selectionchange event was fired.
Use Selection::collapse() instead, which creates a new range if needed
and properly triggers the selectionchange event.