This change replaces our LibXML parser with a new implementation that
wraps libxml2's SAX2 API.
The new Parser class uses libxml2's SAX2 callbacks to drive the existing
XML::Listener interface. That preserves backward compatibility with all
existing consumers (XMLDocumentBuilder, DOMParser, etc.).
This adds visit_edges(Cell::Visitor&) methods to various helper structs
that contain GC pointers, and makes sure they are called from owning
GC-heap-allocated objects as needed.
These were found by our Clang plugin after expanding its capabilities.
The added rules will be enforced by CI going forward.
When content changes inside a layout node, we now reset intrinsic size
caches only up to the nearest absolutely positioned ancestor, rather
than all the way to the document root.
This optimization is safe because absolutely positioned elements don't
contribute to their ancestors' intrinsic sizes - they are skipped in
min/max content width calculations.
The needs_layout_update flag still propagates to all ancestors so the
document knows layout is needed. Only the cache reset is bounded.
The `:has()` pseudo-class requires traversing descendants (or siblings)
to find matches.
With this change we cache results keyed by `(Selector*, Element*)`
pairs. The cache is stored in `StyleComputer` and cleared at the start
of each style computation pass in `Document::update_style()`.
When `:has()` uses a descendant combinator and we find a match, we also
cache that all ancestors between the matching descendant and the
anchor match. For example with `div:has(.target)`:
```html
<div id="A"> <!-- checking :has(.target) here -->
<div id="B">
<div id="C">
<span class="target"/>
</div>
</div>
</div>
```
When we find `.target` while checking `div#A`, we also cache that
`div#B` and `div#C` match `:has(.target)` since they also contain
`.target`. Later when styling these elements, we get cache hits and skip
traversal.
...instead of doing it on every iteration.
This function is hot in profiles on github.com landing page (invoked
through `for_each_matching_attribute()`), so this helps a bit.
Documents that have never been associated with a browsing context will
never become "fully active" so we shouldn't schedule tasks in them since
they'll never run.
The microtask is conceptually global and fires pending observers at the
agent level. As such, it doesn't make sense for it to be associated with
any specific document.
This prevents GC leaks caused by a DocumentLoadEventDelayer that is
never destroyed (for example, when its Document becomes inactive) from
holding a strong reference to the Document and keeping it alive.
There are times that we want to update an animation regardless of
whether it's timelines time has changed, for example if an animation
associated with a scroll timeline has a pending task we should run that
on the next update regardless of whether the user has scrolled
An animation with an orphaned owning element should continue to be
ticked by the timeline.
Reverts c8b574e and instead avoids leaking animations by not visiting
`Animation`s from `AnimationTimeline`s.
Fixes a timeout in the imported test
There were a bunch of places that we created
`HTML::TemporaryExecutionContext`s when updating animations in order to
resolve various promises, this worked but as part of the destructor it
would perform a microtask checkpoint which would result in us executing
microtasks earlier than intended, this is solved by instead having a
single temporary execution context for the entire animation update
process which we then destruct at the intended time.
Instead, let functions have a view into the AST's SourceCode object's
underlying string data. The source string is kept alive by the AST, so
it's fine to have views into it as long as the AST exists.
Reduces memory footprint on my x.com home feed by 65 MiB.
This avoids keeping elements cached in an HTMLCollection alive longer
than necessary in the following scenario:
1. The HTMLCollection cache is populated by querying it.
2. Elements that were included in the cache are removed from the DOM.
3. The cached elements are kept alive by strong references in the cache
until it is updated, which might never happen.
It maps part names to the elements (or pseudo-elements) that have them.
The spec warns about this concept being expensive to calculate, and it
is: you have to walk the entire subtree. To make that less painful, I'm
keeping it cached on the ShadowRoot and recalculating it if the DOM
tree version has changed since. This will invalidate it more often than
necessary, but it's also simple and shouldn't be able to miss any cases,
so it seems reasonable for now.
The existing part_list() method used by the bindings lazily creates a
DOMTokenList, which we don't want to do just to check if an Element has
any parts defined.
Introduce the HTMLSelectedContentElement and integrate it into
<select>, <option> and HTMLParser.
See whatwg/html#10548.
There are two bugs with WPT tests which causes the third subtest
in selectedcontent.html and selectedcontent-mutations.html fail.
See whatwg/html#11882, web-platform-tests/wpt#55849.
In level 2 of the web animations spec, times are no longer always
measures in milliseconds, they can also be percents when dealing with
progress-based (i.e. scroll-based) timelines.
We don't actually support percent times yet but this change will make it
easier to implement when we do.
Web Animations Level 2 disallows setting some `AnimationEffect` timing
values (start delay, end delay, iteration duration) directly and instead
allows authors to set the specified values which are then normalized
into the actual used values taking into account the type of the
associated timeline (i.e. progress- vs time-based)
This method did two things:
1) on the base class (`AnimationTimeline`) it was a setter for
`m_current_time` and;
2) on the child classes (e.g. `DocumentTimeline`) it updated the
timeline's current time given a document timestamp
It makes more sense for theses to be distinct methods
Instead of calculating the cursor rect separately, reuse
PaintableFragment::range_rect() and check for the selection state of
'None' where appropriate.
Computing the font for an element in `compute_font` is premature since
we are yet to apply animated properties - instead we should compute the
value on the fly (with a cache to avoid unnecessary work) to ensure we
are respecting the latest values
Font computation and loading is distinct enough from style computation
that it makes more sense to have this in it's own class.
This will be useful later when we move the font loading process to
`ComputedProperties` in order to respect animated values.
From the spec:
> The owning element of a transition refers to the element or
pseudo-element to which the transition-property property was applied
that generated the animation.
https://drafts.csswg.org/css-transitions-2/#owning-element
Previously we only stored the element.