After removing the unwind context stack, ExecutionContextRareData only
held two GC::Ptr fields — both trivially destructible. The indirection
cost more than it saved: a GC cell allocation per EC, an extra pointer
chase on every source range lookup, and unnecessary complexity.
Replace the rare data cell with two inline fields on ExecutionContext:
cached_source_range and context_owner.
...and SVGDecodedImageData.h
These headers only use Document via forward-declarable references and
smart pointers. Add explicit Document.h includes to .cpp files that
were relying on the transitive include.
...and WorkerEnvironmentSettingsObject.h
These headers only use Document via forward-declarable references and
smart pointers, so the full include is unnecessary.
This reduces the recompilation cascade when Document.h is modified,
cutting off the transitive path through ~30 SVG element headers.
Move the inline try_resolve_url_to() template body in
SVGGraphicsElement.h to a non-template helper in the .cpp file to
avoid needing Document.h and ShadowRoot.h in the header.
Add explicit includes to files that relied on the transitive dependency.
When triple clicking on text, we should select the entire paragraph, or
entire line in <input>s and <textarea>s. If the mouse button is held
down and the user starts dragging, the selection expands with additional
paragraphs or lines.
This expands on the work of Kai Wildberger (PR #7681) but was adjusted
for the work that happened previously to support double click + drag
moves and includes triple click support for our Qt UI.
Co-authored-by: Kai Wildberger <kiawildberger@gmail.com>
This code that used `charset` created a second `environment_encoding`
variable which shadowed the outer one, making it a no-op. Now we
actually use its value.
We weren't doing this before either, but through a slightly sneaky
mechanism: we had overridden Cell::initialize() in
ShadowRealmGlobalScope as a no-op.
Instead of that, do the same thing Window and Worker globals do and
make all of the globals that inherit UniversalGlobalScopeMixin opt
out of WEB_SET_PROTOTYPE_FOR_INTERFACE in EventTarget::initialize().
LibJS+DevTools: Implement console.trace() with source locations
- Add Console::TraceFrame struct with source location data
- Implement Console::trace() to gather stack information
- Add WebView::StackFrame and ConsoleTrace for IPC
- Implement DevToolsConsoleClient::printer() for traces
- Update FrameActor to format traces for DevTools
- Update WorkerDebugConsoleClient trace handling
- Update ReplConsoleClient to format trace output
The VERIFY() this was triggering wasn't actually to spec, and by the
time it gets encountered, the browsing context isn't technically a top-
level context yet, because it has just been created and the definition
of a top-level browsing context requires the document to be the
navigables active document, which it only becomes once a history entry
has been created for it.
Therefore we cannot just verify a top-level browsing context actually
being a top-level browsing context when inserting it into the group,
because that happens to early in its life-cycle as a top-level context.
This makes it so that JS console commands from the devtools no longer
get sent to the last created nested frame in the tab, because nested
frames no longer pretend to have a top-level browsing context.
If our UI informed the page of a DPI change, we would store the new
device pixel ratio and leave it at that. It would take a layout/style
update (e.g. by clicking the page) to actually render the page using the
new DPI. This is very visible on macOS when moving the Ladybird window
from a 1x resolution monitor to a HiDPI 2x monitor.
We now instantly update the backing stores and mark media queries for
reevaluation. Moving the Ladybird window on macOS now immediately
updates the page when dragging it to a HiDPI monitor.
Every user of this actually wants an ancestor in the flat tree - taking
things like `<slot>` into account. So rename it and adjust its behavior
to use that.
Previously we would resolve font features
(https://drafts.csswg.org/css-fonts-4/#feature-variation-precedence)
per element, while this works for the current subset of the font feature
resolution algorithm that we support, some as yet unimplemented parts
require us to know whether we are resolving against a CSS @font-face
rule, and if so which one (e.g. applying descriptors from the @font-face
rule, deciding which @font-feature-values rules to apply, etc).
To achieve this we store the data required to resolve font features in a
struct and pass that to `FontComputer` which resolves the font features
and stores them with the computed `Font`.
We no longer need to invalidate the font shaping cache when features
change since the features are defined per font (and therefore won't ever
change).
Storage keys are strings, even when they look numeric. Advertising
support for indexed properties caused numeric keys (e.g. "0") to be
exposed twice during enumeration: once via indexed property enumeration
and once via named properties.
Disable indexed property support while keeping the indexed setter
enabled, so assignments like storage[42] = "x" still work by coercing
the index to a string key, without introducing a separate indexed
property space.
This commit provides IPC endpoint to WebWorker processes that allows new
WebWorker processes to be requested (just like what WebContent has).
This is implemented by proxying the request_worker_agent call from
WebWorker through WebContent to LibWebView. This allows the WPT test...
http://wpt.live/referrer-policy/gen/worker-classic.http-rp/unsafe-url/worker-classic.http.html
...to pass, and the same is likely true for similar tests.
Since no part of the process of constructing a Worker needs anything
from the document, the realm makes more sense to use, especially since
we're given one to begin with. This change is necessary to allow Workers
to be constructed by workers.
The fetch requests for web worker scripts should be treated as if they
occurred in the caller global scope (which may be a Window) and not the
new worker's global scope. The referrer-policy/4K WPT subtests,
specifically those that test worker subresources, depend on this
behavior to work correctly. This commit fixes many of these subtests,
albeit via a hack where the serialized ESO's creation url is set to
the caller's document URL.
When the visual viewport scrolls (e.g. panning while zoomed in), the
transform matrix baked into the AccumulatedVisualContext tree becomes
stale. Previously only set_needs_display(InvalidateDisplayList::No) was
called, which re-rendered with the old transform — making hit testing
and painting incorrect after visual viewport panning.
This change introduces SlotRegistry to track slot elements per shadow
root. This allows us to iterate slots directly when assigning
slottables for a tree instead of walking an entire subtree.
Add a clang plugin check that flags GC::Cell subclasses (and their
base classes within the Cell hierarchy) that have destructors with
non-trivial bodies. Such logic should use Cell::finalize() instead.
Add GC_ALLOW_CELL_DESTRUCTOR annotation macro for opting out in
exceptional cases (currently only JS::Object).
This prevents us from accidentally adding code in destructors that
runs after something we're pointing to may have been destroyed.
(This could become a problem when the garbage collector sweeps
objects in an unfortunate order.)
This new check uncovered a handful of bugs which are then also fixed
in this commit. :^)
Currently, this just respects the reported value from Accept-Ranges,
but we could also just try sending a range request and see if the
server rejects it, then fall back to a normal request after. For now,
this is fine, and we can make it use a fallback later if needed.
The spec's steps for pausing an HTMLMediaElements prescribe setting the
official playback position to the current playback position, but the
seeking steps are not synchronous, so there's no guarantee that the
current playback position reflects the seek. Therefore, we need to skip
that step if we're in the middle of a seek.
This is included in a pull request to the HTML spec:
https://github.com/whatwg/html/pull/11792
Using the response's header over our own request's byte range is likely
to be a little more reliable for piecing the data together in the
stream, in case the server decides to give us a slightly different
range than we requested. The media element spec requires that the
Content-Range parses correctly anyway, so we should make use of the
values we get out of it.
This makes media playback able to start without having to wait for data
to sequentially download, especially when seeking the media to a
timestamp residing in data that hasn't loaded yet.
Initially, the HTMLMediaElement will request the file without range a
range request. Then, if the IncrementallyPopulatedStream finds that it
needs data that is not yet available, it will decide whether to wait
for that data to be received through the current request, or start a
new request that is closer to the required data.
In this commit, it assumes that the server will support range requests.
I noticed that when performing a smooth scroll up or down, we would
repeatedly enter `Navigable::perform_a_scroll_of_the_viewport()` when
the top or bottom (respectively) of the page was reached. Optimize this
case by returning early when we've reached the intended target scroll
position and we're not performing any vertical or horizontal scrolling.
Previously, click handling for labels was handled in layout and
painting code. This change implements activation_behavior on
HTMLLabelElement, which clicks and focuses the element.
In preparation for handling input events on the rendering thread, move
backpressure management to RenderingThread. The rendering thread needs
to manage this independently without querying the main thread.
Previously, the main thread would block when the UI process hadn't yet
released the backing surface. Now, the main thread can continue
producing display lists while the UI process is busy, allowing more work
to happen in parallel. When rasterization is slow and display lists are
produced faster than they can be consumed, presentation requests are
naturally coalesced using a flag-based approach -
multiple present_frame() calls simply update the pending state,
resulting in a single rasterization with the latest display list.
See: 976d272
This fixes a timeout in the included test. In order for the
test to run properly in our test harness it is modified slightly
(as we are loading the HTML from a file:// URL).
This is preparation for future work where the rendering thread will
initiate rasterization independently and notify the UI process without
requiring coordination with the main thread.
This change prepares for a future where the rendering thread handles
input events directly, allowing it to trigger repainting without
waiting for the main thread. To support this, the compositor needs to
own the display list, scroll state, and backing stores rather than
receiving them per-frame from the main thread.
Add proper style invalidation when the `open` attribute changes on
HTMLDetailsElement and HTMLDialogElement. The :open pseudo-class can
affect sibling selectors (e.g., `dialog:open + sibling`), so we need
full subtree + sibling invalidation.
Previously, when loading a document, we would try to sniff the MIME
type by reading from the response body's source. However, for streaming
HTTP responses, the body source is Empty (the data comes through the
stream instead), so we had no bytes to sniff.
This caused pages like hypr.land (which sends no Content-Type header)
to be misidentified as plain text instead of HTML, since the MIME
sniffing algorithm would receive zero bytes and fall back to the
default type.
The fix captures the first bytes of the response body during fetch,
storing them on the Body object. These bytes are the "resource header"
defined by the MIME Sniffing spec - up to 1445 bytes, which is enough
to identify any MIME type the spec can detect.
Since bytes may arrive asynchronously during streaming, we use a
callback mechanism: if bytes aren't ready yet when load_document()
needs them, it registers a callback that fires once enough bytes have
been captured (or the stream ends).
The flow is:
1. FetchedDataReceiver receives network bytes, buffers them
2. When Body is created, buffered bytes are flushed to Body's sniff
buffer, and subsequent bytes are appended as they arrive
3. Before calling load_document(), Navigable waits for sniff bytes
4. load_document() passes the bytes to MimeSniff::Resource::sniff()