We want the "raw" value here. The spec sort of assumes we are sending JS
values over the wire, whereas we are actually sending AK::JsonValue. So
using the JSON clone AO here is our best bet.
Chromium has a larger list of boolean attributes, and WPT depends on it.
We must also compare attribute names case-insensitively.
Note this method is only used by WebDriver.
The spec is a bit out-of-date here, so this works around an issue with
closing top-level traversables while a dialog is open in another window
within the same agent.
For example, if a dialog is open and the session is configured to ignore
dialogs (instead of automatically closing them), then the Close Window
endpoint will have failed. We can't remove the client-side window handle
in that case.
Capabilities are configured on a per-session basis, but we were only
applying these options to the first WebContent process created. We will
need to pass these options to new windows created from that process.
This patch re-organizes capability processing so that our session can
remember them for new windows.
Unfortunately, there isn't an exact spec method to get the rendered text
of an element, including its shadow DOM. The WebDriver spec requires
just doing exactly what Selenium does.
This patch does not implement this, but is a step in the right direction
as we will now handle text transforms.
Instead of maintaining a list of script execution result types, which we
then map to WebDriver error types, just return the WebDriver error that
is specified by the spec. Then perform the JSON clone algorithm from the
caller in WebDriverConnection, again as specified by the spec. To do so,
this moves the JSON clone algorithm to its own file. This will also be
the future home of the JSON deserialize algorithm, which will need some
of the internal AOs implemented there.
We have to handle user prompts during the exection of most WebDriver
endpoints. Of the ~50 endpoints which call this AO, ~20 are currently
currently async and handled here.
There are approximately 1000 WPT subtests that rely on the handling of
user prompts being completely asynchronous. It will take a bit of elbow
grease to make all of our WebDriver endpoints comply with this. So for
now, we will deprecate the currently synchronous implementation, and a
future patch will implement an asynchronous version that already-async
endpoints can use.
Some WebDriver hooks will need to inform the client that execution has
completed, but without any knowledge of what endpoint was running. Since
there can only ever be a single WebDriver endpoint executing at once, we
can replace the completion callbacks with a single callback.
If a dialog is opened while a script is executing, we must give control
back to the WebDriver client. The script must also continue executing
though, so once it completes, we ignore its result.
We currently spin the event loop to wait for the specified element to
become available. As we've seen with other endpoints, this can result
in dead locks if another web component also spins the event loop.
This patch makes the locator implementations asynchronous.
This will allow us to remove the use of SafeFunction in it's
implementation. This requires a fair amount of plumbing to wire up the
GC heap to the appropriate places in order to create the timers.
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.
We implement these built-in accessors via a lexical environment override
on the inspected document's global scope. However, ClassicScript will
parse the script we provide as a JS program, in which any evaluated
bindings will be interpreted as global bindings. Our global binding
lookup in the bytecode interpreter does not search the lexical env for
the binding, thus scripts like "$0" fail to evaluate.
Instead, we can create an ECMAScriptFunctionObject to evaluate scripts
entered into the Inspector. These are not evaluated as JS programs, and
thus any evaluated bindings are interpreted as non-global bindings. The
lexical environment override we set will then be considered.
It's currently possible for window size/position updates to hang, as the
underlying IPCs are synchronous. This updates the WebDriver endpoint to
be async, to unblock the WebContent process while the update is ongoing.
The UI process is now responsible for informing WebContent when the
update is complete.
There was a timing issue here where WebDriver would dismiss a dialog,
and then invoke another endpoint before the dialog was actually closed.
This is because the dismissal first has to hop over to the UI process to
close the graphical dialog, which then asynchronously informs WebContent
of the result. It's not until WebContent receives that result that the
dialog is considered closed, thus those subsequent endpoints would abort
due a dialog being "open".
We now wait for dialogs to be fully closed before returning from the
dismissal endpoints.
Similar to commit c2cf65adac, we should
avoid spinning the event loop from the WebContent-side of the WebDriver
connection. This can result in deadlocks if another component in LibWeb
also spins the event loop.
The AO to await navigations has two event loop spinners - waiting for
the navigation to complete and for the document to reach the target
readiness state. We now use NavigationObserver and DocumentObserver to
be notified when these conditions are met. And we use the same async IPC
mechanism as script execution to notify the WebDriver process when all
conditions are met (or timed out).
A NodeIterator rooted at some element cannot produce an element before
that root. That is, in a DOM tree such as:
<div id=one><div id=two><div id=three></div></div></div>
If we create a NodeIterator rooted at element `three`, then invoking the
previousNode() method on that iterator is guaranteed to return null.
There was also a bug here where if we ever did enter the while() loop,
we would have looped indefinitely, as we were not updating the current
node.
Our currently ad-hoc method of tracking element references is basically
a process-wide map, rather than grouping elements according to their
browsing context groups. This prevents us from recognizing when an
element reference is invalid due to its browsing context having been
closed.
This implements the WebDriver spec concept of element references grouped
according to their browsing context groups.
This patch is a bit noisy because we now need to plumb the current BC
through to the element reference AOs.
This abstraction will help us to support multiple IPC transport
mechanisms going forward. For now, we only have a TransportSocket that
implements the same behavior we previously had, using Unix Sockets for
IPC.