Commit Graph

1400 Commits

Author SHA1 Message Date
Zaggy1024
04cc5bced9 LibWeb: Update video elements' natural dimensions during playback
This tightens the implementation of video element sizing to the spec by
implementing two spec concepts:
- The media resource's natural width and height, and
- The video element's natural width and height.
The element's natural dimensions change based on the representation,
which has many inputs, so update checks are triggered from many
locations.

The resize event is fired when the media resource's natural dimensions
change, and the layout is invalidated if the element's natural
dimensions change.

Tests for a few important resize triggers have been added.
2026-04-21 19:11:24 -05:00
Zaggy1024
9494f4e8c5 LibWeb: Relayout video elements when setting the initial size
A while ago, we removed the relayout upon rendering a new frame. In
doing so, it became possible for the layout to remain stale after the
video metadata had loaded, leaving the video drawn in a 0x0 box.
2026-04-21 19:11:24 -05:00
Tim Ledbetter
e5d615cb11 LibWeb: Implement autofocus candidate processing
This change implements the algorithms necessary to focus elements with
the autofocus attribute on page load.
2026-04-21 23:47:05 +02:00
Jonathan Gamble
d388502a3a LibWeb: Add placeholders for mic/camera perms 2026-04-21 16:40:46 -05:00
InvalidUsernameException
06a7723ee3 LibWeb: Convert early return into assertions
When we are recomputing inherited styles, we should already have
computed style for that element at least once, so cascaded and computed
properties should exist at that point. So make the invariant explicit.
2026-04-21 18:39:00 +02:00
InvalidUsernameException
67e3b2d446 LibWeb: Recompute inherited style even if there is no layout node
`recompute_inherited_style()` assumed that there is no work to do if the
element has no layout node. This however is not necessarily true.

In particular, the following can happen:
1. The element in question is a descendant at least two layers below an
   element that has `display: none`, i.e. with at least one other
   element between them. (If it is a direct child, a full style
   recomputation will be forced for unrelated reasons).
2. TreeBuilder decides to skip creating layout nodes for the `display:
   none` element and all its descendants.
3. Due to some change on the ancestor (e.g. class added, id changed),
   the value of a property that can be inherited changes on the
   ancestor.
4. The property value of the descendant now also needs to change.

In that scenario, we won't compute the entire style of the descendant,
since that already happened. But we do need to update its inherited
properties because the old ones are now stale. At that point we still
don't have a layout node for the element since it will only be created
after this style update.

Instead of skipping the update for inherited properties, simply allow
`recompute_inherited_style()` to run even in absence of a layout node.
And then apply the style to the layout node only if one exists. If none
exists, the style will be applied later if and when a corresponding
layout node is created.

This partially fixes the blank main navigation menus on
https://bleepingcomputer.com.
2026-04-21 18:39:00 +02:00
Shannon Booth
fd44da6829 LibWeb/Bindings: Emit one bindings header and cpp per IDL
Previously, the LibWeb bindings generator would output multiple per
interface files like Prototype/Constructor/Namespace/GlobalMixin
depending on the contents of that IDL file.

This complicates the build system as it means that it does not know
what files will be generated without knowledge of the contents of that
IDL file.

Instead, for each IDL file only generate a single Bindings/<IDLFile>.h
and Bindings/<IDLFile>.cpp.
2026-04-21 07:36:13 +02:00
Andreas Kling
7a5b1d9de1 LibWeb: Delay generic :has() sibling scans until sibling roots
Mark elements reached by stepping through sibling combinators inside
:has() and use that breadcrumb during generic invalidation walks.

Keep the existing conservative sibling scans for mutations outside
those marked subtrees so nested :is(), :not(), and nesting cases
continue to invalidate correctly.

Also keep :has() eager within compounds that contain ::part(). Those
selectors retarget the remaining simple selectors to the part host, so
deferring :has() there changes which element the pseudo-class runs
against and can make ::part(foo):has(.match) spuriously match.

Add a counter-based sibling-scan test and a regression test covering
the ::part()/ :has() selector orderings.
2026-04-20 13:20:41 +02:00
Andreas Kling
85ff13870f LibWeb: Stop :has() invalidation walk when out of :has() scope
A DOM mutation under a document that uses any :has() rule currently
walks every ancestor up to the root, invoking invalidate_style_if_
affected_by_has() on each. Most of those ancestors have nothing to
do with :has(), so the work scales linearly with DOM depth.

Introduce an in_has_scope flag on Element, set while evaluating :has()
arguments for invalidation metadata. StyleScope's upward invalidation
walk now terminates at the first element that is neither in :has()
scope nor a :has() anchor, so it only traverses the region where some
:has() rule might actually care about the change.

Keep the existing fast :has() matching paths for normal selector
matching, but bypass them while collecting per-element metadata so the
scope markers still get populated. Node insertion also schedules the
parent for the :has() walk so newly inserted nodes still reach the real
anchor.

The css-has-invalidation suite adds focused coverage for these shapes
and updates the expected counters to reflect the shorter walks.
2026-04-20 13:20:41 +02:00
Andreas Kling
029b4998e5 LibWeb: Skip useless sibling scans in generic :has() walks
Track whether any :has() relative selector in a style scope uses a
sibling combinator and let the generic ancestor walk consult that
before scanning ancestor siblings.

This keeps descendant-only :has() invalidations from walking unrelated
siblings while preserving the existing behavior for selectors that use
+ or ~. Add counter-based test coverage so the reduced sibling scans
stay visible through the invalidation counters.
2026-04-20 13:20:41 +02:00
Andreas Kling
e1d62eaf85 LibWeb: Bucket :has() invalidation metadata by feature
Record per-feature :has() invalidation metadata instead of only tracking
whether some selector somewhere mentions a class, id, attribute, tag,
or pseudo-class. The new buckets preserve the relative selector and a
coarse scope classification for each :has() argument, which gives the
next invalidation step enough information to route mutations more
precisely.

Keep this commit behavior-preserving for mutation handling by only
switching the lookup path over to the new metadata buckets. Expose a
test-only counter for the number of candidate :has() metadata entries a
mutation matched, and add coverage showing that one feature can map to
one or multiple :has() buckets without forcing a document-wide yes/no
answer.
2026-04-20 13:20:41 +02:00
Andreas Kling
97e2b05004 LibWeb: Merge equivalent style invalidation plans
Compare invalidation sets, rules, and plans structurally so repeated
descendant and sibling invalidation entries can be merged even when
they were built as separate payload objects.

Also deduplicate pending and active descendant invalidations in the
style invalidator so equivalent rules are not re-applied as the DOM
walk descends. This reduces :has() invalidation fanout while keeping
behavior the same.
2026-04-20 13:20:41 +02:00
Andreas Kling
a72fae8d36 LibWeb: Add test-only counters for :has() invalidation work
Introduce a small set of counters on Document that track the work done
while processing :has() invalidation: how often the upward walk runs,
how many elements it visits, how often matches_has_pseudo_class() is
invoked, how well the per-pass result cache performs, and how many
elements transition from clean to needs-style-update.

Expose the counters through internals so tests can assert precise bounds
on the invalidation work triggered by a mutation, which regular
reference tests cannot express.

Add a css-has-invalidation test suite that covers subject-position,
non-subject-position, sibling-combinator, and no-:has() cases. The
baseline tests share a helper script so later coverage can reuse the
same counter-printing path.

The counters are test-only observation; they do not affect style
computation itself.
2026-04-20 13:20:41 +02:00
Andreas Kling
d629cc379a LibWeb: Cache parsed selectors in Element.matches() and .closest()
Element::matches() and Element::closest() were re-parsing the selector
string on every call. The document already maintains a parsed-selector
cache for querySelector/querySelectorAll.

This patch folds that cache's lookup, parse, namespace filtering and
insertion behind a Document::parse_or_cache_selector_list(string)
and calls it from all four entry points. We also bump the cache's
limit to get more hits.

Saves 100ms of main thread time when loading the "insights" view on
our GitHub repo on my Linux machine. :^)
2026-04-19 21:32:55 +02:00
Sam Atkins
f4372de6e8 LibWeb/DOM: Collapse ranges before DOM mutations
The spec text has also changed since we implemented it, but moving when
we collapse the range is the only actual behaviour change.

Corresponds to:
9363c6ddac
2026-04-17 19:01:35 +02:00
Andreas Kling
8caca053a3 LibWeb: Avoid IntersectionObserver registration lookups
IntersectionObserver updates already iterate over each observer and its
observation targets. We then looked the same target and observer pair up
again through Element's registered observer list just to read and write
previousThresholdIndex and previousIsIntersecting.

Store that mutable state with the observer-side observation target
instead. The element-side list now only keeps strong observer
references for lifetime management and unobserve/disconnect.

This deviates from the spec's storage model, so document the difference
next to the preserved spec comments.
2026-04-17 08:02:30 +02:00
Andreas Kling
e330d5b9ab LibWeb: Make Node::is_connected() O(1) via a cached flag
Previously this walked up the parent chain on every call, which shows
up as a 2.5% item in the profile while watching YouTube videos.

Cache an m_is_connected bit on Node instead, maintained by the DOM
insertion and removal steps.
2026-04-16 08:26:34 +02:00
Callum Law
8a547a3f31 LibWeb: Clear counter style cache when CSSCounterStyleRule modified 2026-04-15 11:07:38 +01:00
Callum Law
8d2995c785 LibWeb: Apply correct invalidations when effective counter style changes
The counter style used for an element (in either the `content` or
`list-style-type`) may change despite the computed values of properties
on that element remaining the same (e.g. if a new rule is inserted with
higher cascade precedence).
2026-04-15 11:07:38 +01:00
Callum Law
2313460ab6 LibWeb: Make null content on ComputedValues more explicit
In a later commit we can use the null state for an optimization.
2026-04-15 11:07:38 +01:00
Callum Law
64ccb9a015 LibWeb: Make @counter-style tree-scoped
This was a pretty straightforward change of storing registered counter
styles on the relevant `StyleScope`s and resolving by following the
process to dereference a global tree-scoped name, the only things of
note are:
 - We only define predefined counter styles (e.g. decimal) on the
   document's scope (since otherwise overrides in outer scopes would
   themselves be overriden).
 - When registering counter styles we don't have the full list of
   extendable styles so we defer fallback to "decimal" for undefined
   styles until `CounterStyle::from_counter_style_definition`.
2026-04-15 11:07:38 +01:00
Callum Law
b9e9c4e655 LibWeb: Remove outdated FIXME in counter style registration
This was done in #8180 but the FIXME wasn't removed
2026-04-15 11:07:38 +01:00
Shannon Booth
8642801889 LibWeb: Set fragment scripting mode from the context document
This corresponds with the editorial change to the HTML standard
introducing the parsing mode enum of:

https://github.com/whatwg/html/commit/01c45cede

And a follow up normative change of:

https://github.com/whatwg/html/commit/508706c80

Making fragment parsing derive its scripting mode from the context
document.
2026-04-14 23:01:36 +02:00
Andreas Kling
88d4d1b1a6 LibWeb: Use VM helpers for execution context access
Inline JS-to-JS frames no longer live in the raw execution context
vector, so LibWeb callers that need to inspect or pop contexts now go
through VM helpers instead of peeking into that storage directly.

This keeps the execution context bookkeeping encapsulated while
preserving existing microtask and realm-entry checks.
2026-04-13 18:29:43 +02:00
Andreas Kling
0f4575e7d0 LibWeb: Clear stale layout state for inactive documents
IntersectionObserver can keep elements from a navigated iframe's old
document alive until a later rendering update. Once that document tears
down its layout tree, descendant nodes and pseudo-elements can still
retain stale layout and paintable pointers, and destruction can bypass
the usual inactive-document teardown entirely.

Clear per-node layout and paintable pointers across the inactive
document subtree before tearing down the layout tree, and do the same
from destroy() for documents that never go through
did_stop_being_active_document_in_navigable().

Add a crash test that observes an iframe target, navigates the iframe,
and waits for rendering updates without touching stale layout state.

Fixes #8670
2026-04-11 16:03:26 +02:00
Sam Atkins
f11207fee1 LibWeb/CSS: Pass AbstractElement to SelectorEngine::matches
...instead of separate Element and PseudoElement arguments.

As noted, AbstractElement's constness is weird currently, but that's a
tangent I don't want to go on right now.
2026-04-08 10:37:05 +01:00
Zaggy1024
55262fb6a3 LibWeb: Close IDB connections when the page is destroyed
This fixes a timeout in WPT's abort-in-initial-upgradeneeded.any.html
test. The timeout was a rare one, caused by idbfactory_open.any.html
leaving the second connection in the final test open, since support.js
only tracks the connection created by the first createdb call. By
leaving the connection open, the harness's deleteDatabase() call would
never take effect. This in turn meant that the upgradeneeded test would
fail an assertion on the number of databases. That assertion was also
uncaught by the harness, turning it into a timeout instead of a fail.

By closing the connections when a document is destroyed, we can ensure
that the connection doesn't leak over to the next test and cause the
exception to be thrown.
2026-04-08 03:03:38 +02:00
Aliaksandr Kalenik
4735908d41 LibWeb: Make ViewportPaintable::visual_context_tree() return reference
The visual context tree is expected to be non-null at all call sites.
Change the return type from raw pointer to reference with VERIFY(),
making the contract explicit and removing unnecessary null checks from
callers.
2026-04-08 02:41:29 +02:00
Aliaksandr Kalenik
ad2ee4fe7a LibWeb: Rasterize each Navigable independently on its own thread
Previously, iframes were rasterized synchronously as nested display
lists inside their parent's display list: the parent's paint walk called
record_display_list() on each hosted iframe document and emitted a
PaintNestedDisplayList command that the player would recurse into. Only
the top-level traversable's RenderingThread was ever active, even though
every Navigable already owned one.

The motivation for splitting this apart:
- Work in the outer document no longer has to be re-recorded when only
  an iframe changes. The parent's cached display list now references the
  iframe's rasterized output live via an ExternalContentSource, so an
  iframe invalidation just needs the parent's display list replayed, not
  re-recorded.
- Each iframe now has a self-contained rasterization pipeline, which is
  prep work for moving iframes into separate sandboxed processes.
2026-04-07 15:09:43 +02:00
Aliaksandr Kalenik
115531eef1 LibWeb: Sort update-the-rendering docs per HTML spec
Prep for rasterizing each Navigable independently, where children must
paint before their parents — the event loop needs to walk documents in
an order where every child comes after its container. The HTML spec
already mandates such an order for the "docs" list: each document
appears after its container, with siblings in shadow-including tree
order.

Maintain m_documents in that sorted order, re-sorting lazily when a
document is registered or its navigable is reassigned.
2026-04-07 15:09:43 +02:00
Andreas Kling
a5dd857380 LibWeb: Fix XML processing instruction placement
DOM pre-insertion validity allows processing instructions as
children of a document. However, Document::is_child_allowed()
still rejected them, so XML documents silently dropped valid
processing-instruction nodes and produced the wrong sibling
relationships.

Processing instructions that appear inside a DTD subset are not
document children and should not surface in the DOM tree. Ignore
those SAX callbacks while libxml is parsing the subset so the XML
parser builds the correct document structure.
2026-04-06 12:07:45 +02:00
Shannon Booth
bb0f244667 LibWeb: Remove ShadowRealm HTML integration 2026-04-05 13:57:58 +02:00
Andreas Kling
e2e3c7fcdf LibWeb: Rebuild counter style cache lazily
Stop rebuilding the counter style cache from every style update.
That made unrelated restyles pay the full counter-style cost even when
no relevant stylesheet state had changed.

Dirty the cache when stylesheet rule caches are invalidated and rebuild
it on the first counter-style lookup instead. Also make cold cache
rebuilds include user stylesheets.

Add regression tests covering insertRule() and replaceSync() updates
that should make newly defined counter styles take effect.
2026-04-05 12:34:28 +02:00
Andreas Kling
0b5ef8fa22 LibWeb: Invalidate styles after constructable sheet updates
Constructed stylesheets updated their rule lists, but adopted documents
and shadow roots were not restyled when replace(), replaceSync(),
or disabled-state changes modified the sheet.  That left several CSSOM
tests passing stale computed styles.

Invalidate stylesheet owners after those updates so adopted sheets
recompute promptly. Also set replace()-produced rules' parent
stylesheet so non-import rules keep their stylesheet context.

The imported baseURL test assumes a tuple origin, so move it to the
HTTP fixture now that replaceSync() actually triggers a restyle.
2026-04-05 12:34:28 +02:00
Aliaksandr Kalenik
e875f2b18b LibWeb: Make SessionHistoryEntry and DocumentState ref-counted
WebContent process keeps session history entries for pages we have
navigated away from. Before this change, those entries could prevent GC
objects (e.g. PolicyContainer and its CSP PolicyList) from being
collected, since the GC-allocated SHE/DocumentState held live GC::Ref
pointers into the heap.

By making both classes RefCounted and storing SerializedPolicyContainer
instead of a live PolicyContainer, history entries no longer keep alive
any GC objects. This eliminates the leak and is also a step toward
moving the session history entry tree to the UI process.
2026-04-03 14:20:09 +02:00
Jelle Raaijmakers
00397b4808 LibWeb: Keep track of elements with an anchor-name set
We maintain a registry of elements with an anchor-name so once they are
referenced for anchor positioning, we can find them with an O(1) lookup
instead of traversing the entire DOM tree.
2026-04-01 19:41:46 +01:00
Psychpsyo
44ef574902 LibWeb: Properly set visibility state for nested documents
This cannot happen inside the Make Active algorithm, since that gets
called during document creation, which commonly happens before the
document's navigable is created.

Aligns us with a recent spec change and rids us of some AD_HOC
behavior.
2026-04-01 17:26:46 +02:00
Psychpsyo
947fec9bcc LibWeb: Mark startViewTransition() as experimental 2026-04-01 13:41:36 +01:00
Aliaksandr Kalenik
4985dabf3d LibWeb: Replace cached navigable with Navigable-maintained back-pointer
Now that Navigable directly owns its active document (m_active_document)
we can have Navigable maintain a back-pointer on Document instead of
using the old cache-with-validation pattern that fell back to a linear
scan of all navigables via navigable_with_active_document().
2026-04-01 11:51:43 +02:00
Aliaksandr Kalenik
2645695fdd LibWeb: Make Navigable directly own its active document
Previously, the active document's lifecycle was bound to
SessionHistoryEntry via DocumentState. The ownership chain was:
  Navigable → SessionHistoryEntry → DocumentState → Document

This made it impossible to move SessionHistoryEntry to the UI process
(which cannot own DOM::Document). This commit decouples the two by
giving Navigable a direct m_active_document field that serves as the
authoritative source for active_document().

- Navigable owns m_active_document directly; active_document() reads
  from it instead of going through the active session history entry.

- DocumentState no longer holds a Document pointer. Instead, it stores
  a document_id for "same document?" checks. Same-document navigations
  share a DocumentState and thus the same document_id, while
  cross-document navigations create a new DocumentState with a new ID.

- A pending_document parameter is threaded through
  finalize_a_cross_document_navigation → apply_the_push_or_replace →
  apply_the_history_step so the newly created document reaches
  activation without being stored on DocumentState.

- For traversal, the population output delivers the document.
  A resolved_document is computed per continuation from either the
  pending document, the population output, or the current active
  document (for same-document traversals).
2026-04-01 11:51:43 +02:00
Aliaksandr Kalenik
f3ea882d6e LibWeb: Remove "signal to continue SHTQ" from document loading
This promise was previously used to signal the session history traversal
queue that it could continue processing, but is no longer needed.
2026-04-01 06:47:59 +02:00
Shannon Booth
0086a7899d LibWeb: Remove some uneeded navigation error propogation
We should not have any errors to propogate down these paths.
2026-04-01 04:41:11 +02:00
Psychpsyo
269aaeea21 LibWeb: Move standalone SVG document layout handling out of BFC
I'm simplifying the BFC code in preparation for multicol layout.
2026-03-31 10:49:15 +02:00
Aliaksandr Kalenik
2a69fd4c52 LibWeb: Replace spin_until in apply_the_history_step with state machine
Replace the blocking spin_processing_tasks_with_source_until calls
in apply_the_history_step_after_unload_check() with an event-driven
ApplyHistoryStepState GC cell that tracks 5 phases, following the
same pattern used by CheckUnloadingCanceledState.

Key changes:
- Introduce ApplyHistoryStepState with phases:
  WaitingForDocumentPopulation, ProcessingContinuations,
  WaitingForChangeJobCompletion, WaitingForNonChangingJobs and Completed
- Add on_complete callbacks to apply_the_push_or_replace_history_step,
  finalize_a_same_document_navigation,
  finalize_a_cross_document_navigation, and
  update_for_navigable_creation_or_destruction
- Remove spin_until from Document::open()
- Use null-document tasks for non-changing navigable updates and
  document unload/destroy to avoid stuck tasks when documents become
  non-fully-active
- Defer completely_finish_loading when document has no navigable yet,
  and re-trigger post-load steps in activate_history_entry for documents
  that completed loading before activation

Co-Authored-By: Shannon Booth <shannon@serenityos.org>
2026-03-31 09:47:59 +02:00
Adam Colvin
f79c3a4bfe LibWeb: Implement exportparts forwarding in part element map
Implement the forwarded part names step of the CSS Shadow Parts
spec in ShadowRoot::calculate_part_element_map(). When a shadow
host has an exportparts attribute, the inner shadow root's part
element map is consulted and matching parts are added to the
outer shadow root's map under the exported name.

This supports both shorthand same-name forwarding (exportparts=
"foo") and renamed forwarding (exportparts="foo: bar"), and
chains transitively through nested shadow boundaries via
recursive part_element_map() calls.

Fixes 4 WPT tests: simple-forward, simple-forward-shorthand,
double-forward, and precedence-part-vs-part.
2026-03-30 16:47:34 +01:00
Tim Ledbetter
f601c0cd4b LibWeb: Disable Navigation API after document.open() on about:blank
This matches the behavior of other engines.
2026-03-29 16:39:03 +02:00
Aliaksandr Kalenik
76d9cc4baf LibWeb: Replace spin_until in execute_script with deferred parser start
HTMLScriptElement::execute_script() and SVGScriptElement had spin_until
calls waiting for ready_to_run_scripts to become true. The race exists
because load_html_document() resolves the session history signal and
starts the parser in the same deferred_invoke — so the parser can hit a
<script> before update_for_history_step_application() sets the flag.

Instead of spinning, defer parser->run() until the document is ready.
Document gains a m_deferred_parser_start callback that is invoked when
set_ready_to_run_scripts() is called. The callback is cleared before
invocation to avoid reentrancy issues (parser->run() can synchronously
execute scripts). All three document loading paths (HTML, XML, text)
now check ready_to_run_scripts before starting the parser and defer if
needed.

create_document_for_inline_content() (used for error pages) now calls
set_ready_to_run_scripts() before mutating the document, ensuring the
invariant holds for all parser paths.

The spin_until calls are replaced with VERIFY assertions.
2026-03-29 01:05:35 +01:00
Aliaksandr Kalenik
df96b69e7a LibWeb: Replace spin_until in HTMLParser::the_end() with state machine
HTMLParser::the_end() had three spin_until calls that blocked the event
loop: step 5 (deferred scripts), step 7 (ASAP scripts), and step 8
(load event delay). This replaces them with an HTMLParserEndState state
machine that progresses asynchronously via callbacks.

The state machine has three phases matching the three spin_until calls:
- WaitingForDeferredScripts: loops executing ready deferred scripts
- WaitingForASAPScripts: waits for ASAP script lists to empty
- WaitingForLoadEventDelay: waits for nothing to delay the load event

Notification triggers re-evaluate the state machine when conditions
change: HTMLScriptElement::mark_as_ready, stylesheet unblocking in
StyleElementBase/HTMLLinkElement, did_stop_being_active_document, and
DocumentLoadEventDelayer decrements. NavigableContainer state changes
(session history readiness, content navigable cleared, lazy load flag)
also trigger re-evaluation of the load event delay check.

Key design decisions and why:

1. Microtask checkpoint in schedule_progress_check(): The old spin_until
   called perform_a_microtask_checkpoint() before checking conditions.
   This is critical because HTMLImageElement::update_the_image_data step
   8 queues a microtask that creates the DocumentLoadEventDelayer.
   Without the checkpoint, check_progress() would see zero delayers and
   complete before images start delaying the load event.

2. deferred_invoke in schedule_progress_check():
   I tried Core::Timer (0ms), queue_global_task, and synchronous calls.
   Timers caused non-deterministic ordering with the HTML event loop's
   task processing timer, leading to image layout tests failing (wrong
   subtest pass/fail patterns). Synchronous calls fired too early during
   image load processing before dimensions were set, causing 0-height
   images in layout tests. queue_global_task had task ordering issues
   with the session history traversal queue. deferred_invoke runs after
   the current callback returns but within the same event loop pump,
   giving the right balance.

3. Navigation load event guard (m_navigation_load_event_guard): During
   cross-document navigation, finalize_a_cross_document_navigation step
   2 calls set_delaying_load_events(false) before the session history
   traversal activates the new document. This creates a transient state
   where the parent's load event delay check sees the about:blank (which
   has ready_for_post_load_tasks=true) as the active document and
   completes prematurely.
2026-03-28 23:14:55 +01:00
Sam Atkins
ed6a5f25a0 LibWeb: Implement scoped custom element registries 2026-03-27 19:49:55 +00:00
Sam Atkins
90c39c214d LibWeb/DOM: Bring create_element() closer to spec
I believe the test regressions were previous false positives, that now
fail because we partially implement things instead of not implementing
them at all.
2026-03-27 19:49:55 +00:00