Step 8 of "create navigation params by fetching" says "if
request's body is null, then set entry's document state's
resource to null." The condition is inverted: it checks
!body().has<Empty>(), entering the block when the body is
non-null instead of null. For GET navigations this is mostly
a no-op since resource is typically already Empty, but for
POST navigations the inverted check incorrectly clears the
POSTResource from the document state, breaking session history
entries that rely on it for form re-submission.
Step 7.3 of finalize_session_history_entry checks whether
navigationParams "is a navigation params (i.e., neither null
nor a non-fetch scheme navigation params)." The condition
checks has<NonFetchSchemeNavigationParams>() instead of
has<NavigationParams>(), matching the wrong variant type.
The block body already accesses the variant as NavigationParams,
so if the condition ever matched it would VERIFY-crash. The
identical spec clause five lines above (step 7.2.3.1) is
implemented correctly as has<NavigationParams>().
The spec assertion "navigationParams's request is not null"
does not hold for srcdoc navigations, which create
NavigationParams with a null request. The condition guards
on request being non-null instead, with an NB comment
explaining the divergence.
Add AnimatedDecodedImageData which implements DecodedImageData with
an 8-slot buffer pool instead of storing all frames in memory.
Frames are requested on demand from the ImageDecoder service as
the animation progresses.
For a 344-frame animated image at 1920x1080, this reduces
WebContent memory from ~1.3 GB to ~66 MB.
The streaming class owns frame progression and synchronizes
multiple callers (HTMLImageElement and ImageStyleValue) through
notify_frame_advanced() returning the authoritative frame index.
When a frame isn't in the pool, the last displayed frame is shown
as a fallback (brief freeze rather than blank).
Rename the old AnimatedBitmapDecodedImageData (which now only
handles static/single-frame images) to BitmapDecodedImageData.
Change the parameters types of the functions `coarsen_time` and
`coarsened_shared_current_time` from `bool` to
`CanUseCrossOriginIsolatedAPIs` for more coherence with the surrounding
code.
The full constructor for NotificationsAPI::Notification is implemented
along with the getter methods.
It is now possible to call the elements of Notification in JS without
getting undefined but the default values (or the ones passed in
options).
The method `current_wall_time` is added in EnvironmentSettingsObject.
This passes a least a few more tests because of the getter methods
that are created.
https://wpt.live/notifications/constructor-basic.https.htmlhttps://wpt.live/notifications/idlharness.https.any.html
The getter compares the current entry index against the entry
list's size, but valid indices are in the range [0, size - 1].
An index equal to size is a past-the-end state that never occurs
in practice, so the function always returns true for any valid
index. This means it reports forward navigation is possible even
when the current entry is the last one in the list, where
forward() immediately throws an InvalidStateError.
The symmetric can_go_back() correctly checks against index 0,
and forward() correctly checks against size - 1. This brings
can_go_forward() in line with both.
Previously, `<link rel=stylesheet>` would delay the load event until its
style sheet loaded, but not care about its subresources. `<style>`
would not delay the load event at all. Instead, each `@import` would
delay the load event.
Now, both `<style>` and `<link>` delay the load event until their style
sheet and its critical subresources have loaded or failed. This means
that CSSImportRules no longer need to delay the load event themselves,
because they do so implicitly as a critical subresource of their parent
style sheet.
This doesn't directly affect behavior, but means that any other critical
style resources we add will automatically delay the load event.
One wrinkle here is that the spec for the `<link>` element requires that
we wait for the style sheet's critical subresources *before* we create
a CSSStyleSheet, which means we don't yet know what those are.
https://html.spec.whatwg.org/multipage/semantics.html#fetching-and-processing-a-resource-from-a-link-element:critical-subresources
For now we simply ignore this, as we did before. That means we continue
to not delay the `<link>`'s load event.
Previously we parsed it as `<custom-ident>` in `<counter>` and as a
keyword in `list-style-type`.
The practical effect of this is:
- Spec defined counter style names in `<counter>` are ASCII lowercased
on parse.
- Non spec defined counter style names are allowed in `list-style-type.
We are still to parse the `symbols()` function but this gives us a
better base for that.
Previously, the label called `HTMLElement::click()` which dispatched a
synthetic event with all properties set to their default values. We now
preserve the properties of the original mouse event.
When a WebGL canvas is used as a CanvasImageSource, the underlying
PaintingSurface may not yet reflect the most recent GL commands.
This caused drawImage() to capture stale or empty content unless
gl.flush() was called manually from JS.
Call HTMLCanvasElement::present() before creating the snapshot so
that WebGL content is properly synchronized with the surface prior
to readback.
Fix#7901
Remove includes from Node.h that are only needed for forward
declarations (AccessibilityTreeNode.h, XMLSerializer.h,
JsonObjectSerializer.h). Extract StyleInvalidationReason and
FragmentSerializationMode enums into standalone lightweight
headers so downstream headers (CSSStyleSheet.h, CSSStyleProperties.h,
HTMLParser.h) can include just the enum they need instead of all of
Node.h. Replace Node.h with forward declarations in headers that only
use Node by pointer/reference.
This breaks the circular dependency between Node.h and
AccessibilityTreeNode.h, reducing AccessibilityTreeNode.h's
recompilation footprint from ~1399 to ~25 files.
Remove 11 heavy includes from Document.h that were only needed for
pointer/reference types (already forward-declared in Forward.h), and
extract the nested ViewportClient interface to a standalone header.
This reduces Document.h's recompilation cascade from ~1228 files to
~717 files (42% reduction). Headers like BrowsingContext.h that were
previously transitively included see even larger improvements (from
~1228 down to ~73 dependents).
This clamps the interval of repeating timers to 4ms after they have run
5 times. This prevents CPU spinning for `setInterval()` calls with low
timeouts.
HTMLInputElement calls update_placeholder_visibility() when its
placeholder attribute changes, but HTMLTextAreaElement did not. This
meant dynamically changing the attribute would not toggle the display
of the placeholder and inner text shadow DOM elements.
Previously only input elements were matched. Add placeholder_value()
to HTMLTextAreaElement mirroring the HTMLInputElement API and update
both selector matching code paths to handle textarea.
Browsers seem to make it convenient to replace an <input>'s contents by
selecting all text on focusing, but only if you used keyboard
navigation. Programmatic focus and clicking on the field do not show
this behavior.
When editing or changing the selection inside an <input> or <textarea>,
we should scroll the container so the cursor is always visible. Note
that currently the cursor might still become invisible at the end of the
container since we do not reserve enough space for it to be made
visible.
When an iframe is removed before its post-connection session history
steps finish processing, the queued steps still run and call
navigate() on the now-destroyed navigable. This calls
set_delaying_load_events(true), creating a DocumentLoadEventDelayer
on the parent document. Since the navigable is destroyed, no
finalize step ever runs to clear the delayer, permanently blocking
the parent document's load event.
Fix this by checking has_been_destroyed() at the start of
begin_navigation() and bailing out early.
When a child navigable starts loading, the navigate algorithm calls
set_delaying_load_events(true), creating a DocumentLoadEventDelayer
on the parent document. This delayer is normally cleared when the
navigation finalizes via set_delaying_load_events(false).
However, when an iframe is removed from the DOM, the child navigable
is destroyed. If the finalize step hasn't run yet, the delayer
lingers until GC collects the Navigable, which can block the parent
document's load event indefinitely.
Fix this by explicitly clearing the "is delaying load events" flag
in destroy_the_child_navigable() right after marking the navigable
as destroyed.
HTMLImageElement's "update the image data" algorithm checks
is_fully_active() at the start, but its async continuations
(microtasks, element tasks, batching dispatcher callbacks) skip
this check. When an iframe is removed or navigated, these
callbacks fire on an inactive document, causing crashes.
Fix this with two changes:
1) Add is_fully_active() bail-out checks at all async callback
entry points in HTMLImageElement. Each bail-out also clears
the DocumentLoadEventDelayer to prevent blocking the parent
document's load event forever.
2) Create the DocumentObserver eagerly in initialize() (like
HTMLMediaElement) with a document_became_inactive callback
that clears the load event delayer and stops the animation
timer. Fire document_became_inactive from Document::destroy()
in addition to did_stop_being_active_document_in_navigable(),
since iframe removal takes a different path than navigation.
A guard flag prevents duplicate firing.
When queuing tasks for changing navigables in step 12 of
apply_the_history_step, skip navigables that have been destroyed and
increment completed_change_jobs directly. This is necessary because
Document::destroy() removes tasks associated with its document from the
task queue, so a task queued for a destroyed navigable's window may
never run, causing the subsequent spin_until to wait forever.
When a document is navigated away from while HTMLParser::the_end() is
spinning the event loop (steps 7 and 8), the spin_until stays on the
call stack indefinitely, causing all subsequent event processing on the
same event loop to happen within nested spin_until pumping. Add
is_fully_active() checks to bail out early in this case.
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).