While Origin is defined in the HTML spec - this leaves us with quite an
awkward relationship as the URL spec makes use of AO's from what is
defined in the HTML spec.
To simplify this factoring, relocate Origin into LibURL.
When an element is invalidated, it's possible for any subsequent sibling
or any of their descendants to also need invalidation. (Due to the CSS
sibling combinators, `+` and `~`)
For DOM node insertion/removal, we must also invalidate preceding
siblings, since they could be affected by :first-child, :last-child or
:nth-child() selectors.
This increases the amount of invalidation we do, but it's more correct.
In the future, we will implement optimizations that drastically reduce
the number of elements invalidated.
DOM nodes that didn't have a layout node before being removed from the
DOM are not going to change the shape of the layout tree after being
removed.
Observing this, we can avoid a full layout tree rebuild on some DOM node
removals.
This avoids a bunch of tree building work when loading https://x.com/
You can now build with STYLE_INVALIDATION_DEBUG and get a debug stream
of reasons why style invalidations are happening and where.
I've rewritten this code many times, so instead of throwing it away once
again, I figured we should at least have it behind a flag.
If a DOM node is an element with pseudo-elements, but it has no child
DOM nodes and is not a shadow host, then the code that serializes its
pseudo-elements would get skipped, making them not show up in the
inspector.
To avoid expensive lookups, we now cache a weak pointer from document to
the last known node navigable. Before using the cache, we validate that
the document is still the navigable's active document.
The spec says to just call the XML serialization algorithm, but it
returns the "outer serialization", and we need the "inner" one. Let's
just concatenate serializations of children; then the result produced is
similar to one from Blink or Gecko.
This method puts the given node and all of its sub-tree into a
normalized form. A normalized sub-tree has no empty text nodes and no
adjacent text nodes.
And let the old shadow_root(), which was only supposed to be used by
bindings, be called shadow_root_for_bindings() instead.
This makes it much easier to read DOM code, and we don't have to worry
about when to use shadow_root_internal() or why.
Link elements that aren't "browsing-context connected" should not
trigger a resource fetch when their attributes change.
This fixes an issue where we'd waste time by loading every style sheet
twice! :^)
We can't rely on Element.setAttribute() in cloneNode() since that will
throw on weird attribute names. Instead, just follow the spec and copy
attributes into cloned elements verbatim.
This fixes a crash when loading the "issues" tab on GitHub repos.
They are actually sending us unintentionally broken markup, but we
should still support cloning it. :^)
If a DOM node isn't connected, there's no need to invalidate, since it's
not going to be visible anyway. The node will be automatically inserted
if/when it becomes connected in the future.
This piggybacks on the same fragment serialization code that innerHTML
uses, but instead of constructing an imaginary parent element like the
spec asks us to, we just add a separate serialization mode that includes
the context element in the serialized markup.
This makes the image carousel on https://utah.edu/ show up :^)
A bunch of this is leftover from pre porting over to new AK::String.
For example, for functions which previously took a ByteString const&
now accepting a StringView.
`Node::shadow_including_root()` was missing a null check, which caused
a crash when manipulating a select element, whose option elements were
initially detached.
This patch adds a u64 version counter to DOM::Document that increments
whenever the tree structure changes (via node insertion or removal),
or an element attribute is changed somehow.
This will be used as a crude invalidation mechanism for HTMLCollection
to cache its elements.
When inserting a node into a parent, any live DOM ranges that reference
the parent may need to be updated. The spec does this by increasing or
decreasing the start/end offsets of each live range *before* actually
performing the insertion.
This caused us to crash with a verification failure, since it was
possible to set the range offset to an invalid value (that would go on
to immediately become valid after the insertion was finished).
This patch fixes the issue by adding special badged helpers on Range for
Node to reach into it and increase/decrease the offsets during node
insertion. This skips the offset validity check and actually makes our
code read slightly more like the spec.
Found by Domato :^)
When a node is removed from the DOM tree, its paintable needs to be
removed to ensure that it is not used to obtain sizes that are no
longer valid.
This change enables the ResizeObserver to send a notification if a node
is removed, as it should, because a removed node now has a size of zero
It should be okay to nullify pointers without concerning
parent/sibling/child relationships because the layout and paintable
trees will be rebuilt following any DOM mutation anyway.
If the entire document is invalidated, we know a full style update is
coming soon, and there's no need to try and invalidate a smaller part.
This avoids a *lot* of work on some pages. As an example, we are able to
skip ~1.5 million style invalidations on https://html.spec.whatwg.org/
We were previously assuming that the input offsets and lengths were all
in raw byte offsets into a UTF-8 string. While internally our String
representation may be in UTF-8 from the external world it is seen as
UTF-16, with code unit offsets passed through, and used as the returned
length.
Beforehand, the included test included in this commit would crash
ladybird (and otherwise return wrong values).
The implementation here is very inefficient, I am sure there is a
much smarter way to write it so that we would not need a conversion
from UTF-8 to a UTF-16 string (and then back again).
Fixes: #20971
This commit un-deprecates DeprecatedString, and repurposes it as a byte
string.
As the null state has already been removed, there are no other
particularly hairy blockers in repurposing this type as a byte string
(what it _really_ is).
This commit is auto-generated:
$ xs=$(ack -l \bDeprecatedString\b\|deprecated_string AK Userland \
Meta Ports Ladybird Tests Kernel)
$ perl -pie 's/\bDeprecatedString\b/ByteString/g;
s/deprecated_string/byte_string/g' $xs
$ clang-format --style=file -i \
$(git diff --name-only | grep \.cpp\|\.h)
$ gn format $(git ls-files '*.gn' '*.gni')
No functional impact intended. This is just a more complicated way of
writing what we have now.
The goal of this commit is so that we are able to store the 'name' of a
pseudo element for use in serializing 'unknown -webkit-
pseudo-elements', see:
https://www.w3.org/TR/selectors-4/#compat
This is quite awkward, as in pretty much all cases just the selector
type enum is enough, but we will need to cache the name for serializing
these unknown selectors. I can't figure out any reason why we would need
this name anywhere else in the engine, so pretty much everywhere is
still just passing around this raw enum. But this change will allow us
to easily store the name inside of this new struct for when it is needed
for serialization, once those webkit unknown elements are supported by
our engine.
After commit ff48b7333c, we remove shadow
roots from elements that are removed from the DOM. Setting a node's
shadow root to null also sets that shadow root's host to null. Thus, the
comment in Node::is_shadow_including_descendant_of that assumes the host
is always non-null is not true.
The test added here would previously crash when interacting with a node
that is a descendant of a removed shadow root.