This is not safe from GC. Unfortunately we cannot add a test to capture
the issue, as the allocation which may trigger GC is internal and not
observable from JS.
This input event handling change is intended to address the following
design issues:
- Having `DOM::Position` is unnecessary complexity when `Selection`
exists because caret position could be described by the selection
object with a collapsed state. Before this change, we had to
synchronize those whenever one of them was modified, and there were
already bugs caused by that, i.e., caret position was not changed when
selection offset was modified from the JS side.
- Selection API exposes selection offset within `<textarea>` and
`<input>`, which is not supposed to happen. These objects should
manage their selection state by themselves and have selection offset
even when they are not displayed.
- `EventHandler` looks only at `DOM::Text` owned by `DOM::Position`
while doing text manipulations. It works fine for `<input>` and
`<textarea>`, but `contenteditable` needs to consider all text
descendant text nodes; i.e., if the cursor is moved outside of
`DOM::Text`, we need to look for an adjacent text node to move the
cursor there.
With this change, `EventHandler` no longer does direct manipulations on
caret position or text content, but instead delegates them to the active
`InputEventsTarget`, which could be either
`FormAssociatedTextControlElement` (for `<input>` and `<textarea>`) or
`EditingHostManager` (for `contenteditable`). The `Selection` object is
used to manage both selection and caret position for `contenteditable`,
and text control elements manage their own selection state that is not
exposed by Selection API.
This change improves text editing on Discord, as now we don't have to
refocus the `contenteditable` element after character input. The problem
was that selection manipulations from the JS side were not propagated
to `DOM::Position`.
I expect this change to make future correctness improvements for
`contenteditable` (and `designMode`) easier, as now it's decoupled from
`<input>` and `<textarea>` and separated from `EventHandler`, which is
quite a busy file.
This ensures we cannot set or get cookies on non-HTTP(S) origins. Since
this would prevent our ability to test cookies during LibWeb tests, this
also adds an internals API to allow cookie access on file:// URLs.
This just updates our copied spec steps - new steps are not implemented
here. This is mostly just to highlight new steps we are missing around
MessagePorts.
No behavior change, but this does resolve an outstanding FIXME around
spec step ordering.
We were hard-coding "about:blank" as the document URL for parsed HTML
documents, which was definitely not correct.
This fixes a bunch of WPT tests under /domparsing/ :^)
I had made a stab at implementing this to determine whether it could
assist in fixing an issue where scroll_to_the_fragment was not getting
called at the appropriate time. It did not fix that issue, and actually
ended up breaking one of our in tree tests. In the meantime, factor out
this method into a standalone function.
These don't have to worry about the input not being valid UTF-8 and
so can be infallible (and can even return self if no changes needed.)
We use this instead of Infra::to_ascii_{upper,lower}_case in LibWeb.
There was no need to use FlyString for error messages, and it just
caused a bunch of churn since these strings typically only existed
during the lifetime of the error.
This way we don't have to allocate separate vector with both scroll and
sticky frame that is used for display list player (scroll and sticky
frames share id pool), so player could access offset by frame id.
No behavior change.
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.
Implements https://github.com/whatwg/html/pull/10007 which basically
moves style, layout and painting from HTML processing task into HTML
task with "rendering" source.
The biggest difference is that now we no longer schedule HTML event loop
processing whenever we might need a repaint, but instead queue a global
rendering task 60 times per second that will check if any documents
need a style/layout/paint update.
That is a great simplification of our repaint scheduling model. Before
we had:
- Optional timer that schedules animation updates 60 hz
- Optional timer that schedules rAF updates
- PaintWhenReady state to schedule a paint if navigable doesn't have a
rendering opportunity on the last event loop iteration
Now all that is gone and replaced with a single timer that drives
repainting at 60 hz and we don't have to worry about excessive repaints.
In the future, hard-coded 60 hz refresh interval could be replaced with
CADisplayLink on macOS and similar API on linux to drive repainting in
synchronization with display's refresh rate.
update_layout() need to be invoked before checking if layout node is
present, because layout not being updated might be the reason why layout
node doesn't exist yet.
The expensive part of creating a segmenter is doing the locale and UCD
data lookups at creation time. Instead of doing this once per text node,
cache the segmenters on the document, and clone them as needed (cloning
is much, much cheaper).
On a profile loading Ladybird's GitHub repo, the following hot methods
changed as follows:
ChunkIterator ctor: 6.08% -> 0.21%
Segmenter factory: 5.86% -> 0%
Segmenter clone: N/A -> 0.09%
This patch implements `Range::getClientRects` and
`Range::getBoundingClientRect`. Since the rects returned by invoking
getClientRects can be accessed without adding them to the Selection,
`ViewportPaintable::recompute_selection_states` has been updated to
accept a Range as a parameter, rather than acquiring it through the
Document's Selection.
With this change, the following tests now pass:
- wpt[css/cssom-view/range-bounding-client-rect-with-nested-text.html]
- wpt[css/cssom-view/DOMRectList.html]
Note: The test
"css/cssom-view/range-bounding-client-rect-with-display-contents.html"
still fails due to an issue with Element::getClientRects, which will
be addressed in a future commit.
Before this change, a formatting context was responsible for layout of
absolutely positioned boxes whose FC root box was their parent (either
directly or indirectly). This only worked correctly when the containing
block of the absolutely positioned child did not escape the FC root.
This is because the width and height of an absolutely positioned box are
resolved based on the size of its containing block, so we needed to
ensure that the containing block's layout was completed before laying
out an absolutely positioned box.
With this change, the layout of absolutely positioned boxes is delayed
until the FC responsible for the containing block's layout is complete.
This has affected the way we calculate the static position. It is no
longer possible to ask the FC for a box's static position, as this FC's
state might be gone by the time the layout for absolutely positioned
elements occurs. Instead, the "static position rectangle" (a concept
from the spec) is saved in the layout state, along with information on
how to align the box within this rectangle when its width and height are
resolved.
FormattingContext::run() does not allow reentrancy, so it's safe to
save and access layout mode from FC object. This avoids need to drill it
through methods of a formatting context and makes it clear that this
value could never be changed after FC construction.
Root formatting context box is passed into constructor and saved in FC,
so it's possible to access it from there instead of passing the same
box into run().
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.
This API is a relic from the time when it was important for objects to
have easy access to the Window, and to know it was the global object.
We now have more spec-related concepts like relevant_global_object and
current_global_object to pull the Window out of thin air.