This is a mixin in the IDL, so let's treat it as a mixin in our code and
let both SVGElement and MathMLElement reuse the implementations that we
wrote for HTMLElement.
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.
And here's the wild part: instead of cloning WPT tests, import the
relevant WPT tests that this fixes into our own test suite.
This works by adding a small Ladybird-specific callback in
resources/testharnessreport.js (which is what that file is meant for!)
Note that these run as text tests, and so they must signal the runner
when they are done. Tests using the "usual" WPT harness should just
work, but tests that do something more freestyle will need manual
signaling if they are to be imported.
I've also increased the test timeout here from 30 to 60 seconds,
to accommodate the larger WPT-style tests.
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.
Navigables are re-used for navigations within the same tab. Its current
ownership of the cursor position is a bit ad-hoc, so nothing in the spec
indicates when to reset the cursor, nor do we manually do so. So when a
cursor update happens on one page, that cursor is retained on the next
page.
Instead, let's have the document own the cursor. Each navigation results
in a new document, thus we don't need to worry about resetting cursors.
This also makes many of the callsites feel nicer. We were previously
often going from the node, to the document, to the navigable, to the
cursor. This patch removes the navigable hop.
We now follow the rules from the spec more closely, along with an
unspecified quirk for when the offsetParent is a non-positioned body
element. (Spec bug linked in a comment.)
This fixes a whole bunch of css-flexbox tests on WPT, which already had
correct layout, but the reported metrics from JS API were wrong.
This was resulting in a whole lot of rebuilding whenever a new IDL
interface was added.
Instead, just directly include the prototype in every C++ file which
needs it. While we only really need a forward declaration in each cpp
file; including the full prototype header (which itself only includes
LibJS/Object.h, which is already transitively brought in by
PlatformObject) - it seems like a small price to pay compared to what
feels like a full rebuild of LibWeb whenever a new IDL file is added.
Given all of these includes are only needed for the ::initialize
method, there is probably a smart way of avoiding this problem
altogether. I've considered both using some macro trickery or generating
these functions somehow instead.
As defined in: https://w3c.github.io/pointerevents
With the exception of the getCoalescedEvents and getPredictedEvents
APIs.
There are still many other parts of that spec (such as the event
handlers) left to implement, but this does get us at least some of the
way.
This commit introduces a WEB_SET_PROTOTYPE_FOR_INTERFACE macro that
caches the interface name in a local static FlyString. This means that
we only pay for FlyString-from-literal lookup once per browser lifetime
instead of every time the interface is instantiated.
The specification says the final step of this algorithm is to return
null. Previously, the browser would crash if the content of an iframe
was appended to the document before its offsetParent property was
queried.
(Or rather, bring offsetLeft and offsetTop closer to spec, and implement
the previously-missing offsetParent)
This makes mouse inputs on https://nerget.com/fluidSim/ work properly.
With this change, we now have ~1200 CellAllocators across both LibJS and
LibWeb in a normal WebContent instance.
This gives us a minimum heap size of 4.7 MiB in the scenario where we
only have one cell allocated per type. Of course, in practice there will
be many more of each type, so the effective overhead is quite a bit
smaller than that in practice.
I left a few types unconverted to this mechanism because I got tired of
doing this. :^)
This commit removes DeprecatedString's "null" state, and replaces all
its users with one of the following:
- A normal, empty DeprecatedString
- Optional<DeprecatedString>
Note that null states of DeprecatedFlyString/StringView/etc are *not*
affected by this commit. However, DeprecatedString::empty() is now
considered equal to a null StringView.
This should allow us to add a Element::attribute which returns an
Optional<String>. Eventually all callers should be ported to switch from
the DeprecatedString version, but in the meantime, this should allow us
to port some more IDL interfaces away from DeprecatedString.
Stop worrying about tiny OOMs. Work towards #20449.
While going through these, I also changed the function signature in many
places where returning ThrowCompletionOr<T> is no longer necessary.