Commit graph

936 commits

Author SHA1 Message Date
Martin Robinson
ebb12cb298 libservo: Add a WebView::take_screenshot() API and use it for reftests
Co-authored-by: Delan Azabani <dazabani@igalia.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-09-26 10:47:46 +02:00
Martin Robinson
ffdb7d3663
script: Chain up keyboard scrolling to parent <iframe>s (#39469)
When an `<iframe>` cannot scroll because the size of the frame is
greater than or
equal to the size of page contents, chain up the keyboard scroll
operation to the parent frame.

Testing: A new Servo-only WPT tests is added, though needs to be
manually
run with `--product servodriver`.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Delan Azabani <dazabani@igalia.com>
2025-09-25 11:16:41 +00:00
Narfinger
033da09800
Move signals_slots to ScriptMutationObservers (#39275)
Both places where we access signals_slots already have a reference to
ScriptMutationObserver. This saves us another access to
with_script_thread.


Testing: This does not change functionality.
Fixes: Part of addressing: https://github.com/servo/servo/issues/37969

Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
2025-09-12 18:43:59 +00:00
Kenzie Raditya Tirtarahardja
097a69169a
webdriver: Support "scroll into view" for commands (#38508)
Implement scroll into view steps for all WebDriver command that requires
it (element click, element send keys, element clear, and take element
screenshot).

Testing: `element_send_keys/scroll_into_view.py`,
`element_click/scroll_into_view.py`, `element_clear/clear.py`

---------

Signed-off-by: PotatoCP <Kenzie.Raditya.Tirtarahardja@huawei.com>
2025-09-12 06:07:58 +00:00
Narfinger
19f70dccf6
Combine some access to the thread local variable for script thread. (#38752)
This combines some access to the thread local variable for script
thread.

- We introduce a new UserInteractingScriptGuard which on drop handles
  the resetting of was_interacting to the previous value. Sometimes
throughout the code `ScriptThread::is_user_interacting` was reset to the
previous value while sometimes just set to false. This should
remove this footgun.
- This also reduces the amount of thread local access for
MutationObservers and task queue.

Testing: WPT tests should cover this.
Fixes: This addresses part of
https://github.com/servo/servo/issues/37969 but there is probably still
stuff to be done.

---------

Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
Signed-off-by: Josh Matthews <josh@joshmatthews.net>
Co-authored-by: Josh Matthews <josh@joshmatthews.net>
2025-09-11 09:40:32 +00:00
Narfinger
84465e7768
Removed FnvHash and transformed the rest to FxHashmap (#39233)
This should be the final PR for the Hash Function series that is
trivial.

Of note: I decided to transform `HashMapTracedValues<Atom,..>` to use
FxBuildHasher. This is likely not going to improve performance as Atom's
already have a unique u32 that is used as the Hash but it safes a few
bytes for the RandomState that is normally in the HashMap.

Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>

Testing: Hash function changes should not change functionality, we
slightly decrease the size and unit tests still work.

Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
2025-09-10 13:34:54 +00:00
Narfinger
177f6d6502
Replace Hash Algorithm in HashMap/Set with FxHashMap/Set for simple types (#39166)
FxHash is faster than FnvHash and SipHash for simple types up to at
least 64 bytes. The cryptographic guarantees are not needed for any
types changed here because they are simple ids.
This changes the types in script and net crates.
In a future PR we will change the remaining Fnv to be also Fx unless
there is a reason to keep them as Fnv.

Testing: Should not change functionality but unit test and wpt will find
it.

Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
2025-09-09 08:33:46 +00:00
Tim van der Lippe
a672ffb850
Add resource header for mime sniffing (#39167)
The concept of a "resource header" is not well specced, since it is
unclear what a "resource" is. That said, it most closely matches a
"response" as part of the navigation params.

With this change, we now delay loading the document until either two
things happen:
1. We reached the end of the file
2. We processed 1445 bytes (as defined by spec)

We initially store bytes in the resource header and then after loading
parse the stored bytes. Any subsequent loading will process as before.

Part of #14024

Signed-off-by: Tim van der Lippe <tvanderlippe@gmail.com>
2025-09-07 12:31:57 +00:00
Narfinger
5c7ea4bdee
constellation: Use FnvHashMap for hashmaps that use ids as keys (#39106)
FNV is faster for hashing less than 16 bytes of data and the
cryptographic properties of the default HashMap are not needed for the
various ids.

Testing: This does not change functionality.

Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
2025-09-03 18:15:19 +00:00
Narfinger
b73c81630a
Change BrowingContextId from WebViewId explicitly (#39095)
There were still some accesses to the inner BrowsingContextId from the
WebViewId. This changes it to completely rely on the From trait for
these methods. This also means we can make the field private.

For testing we add a way to create arbitrary WebViewIds.

Testing: Does not change functionality.

Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
2025-09-03 12:18:08 +00:00
Jonathan Schwender
f4dd2960b8
Add direct script to embedder channel (#39039)
This PR **removes** `ScriptToConstellationMessage::ForwardToEmbedder`,
and replaces it with an explicit `ScriptToEmbedderChannel`. This new
channel is based on `GenericCallback` and in single-process mode will
directly send the message the to the embedder and wake it. In
multi-process mode, the message is routed via the ROUTER, since waking
is only possible from the same process currently. This means in
multi-process mode there are likely no direct perf benefits, since we
still need to hop the message over the ROUTER (instead of over the
constellation).
In single-process mode we can directly send the message to the embedder,
which should provide a noticable latency improvement in all cases where
script is blocked waiting on the embedder to reply.

This does not change the way the embedder receives messages - the
receiving end is unchanged.

## How was sending messages to the embedder working before?

1. Script wraps it's message to the embedder in
`ScriptToConstellationMessage::ForwardToEmbedder` and sends it to
constellation.
2. The [constellation event loop] receives the message in
[handle_request]
3. If deserialization fails, [an error is logged and the message is
ignored]
4. Since our message came from script, it is handle in
[handle_request_from_script]
5. The message is logged with trace log level
6. If the pipeline is closed, [a warning is logged and the message
ignored]
7. The wrapped `EmbedderMsg` [is forwarded to the embedder]. Sending the
message also invokes `wake()` on the embedder eventloop waker.

[constellation event loop]:
2e1b2e7260/components/constellation/constellation.rs (L755)

[handle request]:
2e1b2e7260/components/constellation/constellation.rs (L1182)

[an error is logged and the message is ignored]:
2e1b2e7260/components/constellation/constellation.rs (L1252)

[handle_request_from_script]:
https://github.com/servo/servo/blob/main/components/constellation/constellation.rs#L1590
 
[a warning is logged and the message ignored]:
2e1b2e7260/components/constellation/constellation.rs (L1599)

[is forwarded to the embedder]:
2e1b2e7260/components/constellation/constellation.rs (L1701)

Testing: Communication between Script and Embedder is extensive, so this
should be covered by existing tests.

Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
2025-09-02 06:33:44 +00:00
Ashwin Naren
c92cd9e624
script: Move HTML DOM interfaces to script/dom/html/ (#39046)
See #38901.

Testing: Refactor
Fixes: Partially #38901

Signed-off-by: Ashwin Naren <arihant2math@gmail.com>
2025-08-31 01:00:09 +00:00
Josh Matthews
0481477f35
script_bindings: Remove Cell wrapper from thread-local RootCollection. (#39043)
This doesn't appear to make a big difference in speedometer results, but
this removes some code from the hot path of creating DomRoot values.

Before: `Score: 30.381097406624708 ± 2.0393225244958018`
After: `Score: 30.344639420871395 ± 1.9359337921154696`

Testing: Existing WPT coverage

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
2025-08-30 19:47:26 +00:00
Josh Matthews
6565d982bd
servoshell: Support runtime preference manipulation (#38159)
These changes add a custom servo:preferences URL that allows modifying
selected preferences at runtime. The goal of this work is to make it
easy to test pages while toggling experimental web platform features,
and support quickly changing the User-Agent header.

Testing: Manually verified that spacex.com loads correctly after
changing the user agent, and that https://polygon.io/ displays grid
elements correctly and no console errors with the experimental prefs
enabled.
Fixes: #35862

<img width="1136" height="880" alt="Screenshot 2025-07-18 at 1 06 23 AM"
src="https://github.com/user-attachments/assets/2d27c321-6ca0-43c3-a347-7bc4b55272df"
/>

---------

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
2025-08-30 16:51:58 +00:00
Josh Matthews
c97ec1b2fb
script: Reduce ScriptThread TLS usage (#38875)
We store a pointer to the ScriptThread singleton for a thread in
thread-local storage. While we don't have yet have profiles pointing to
this TLS access as a hot spot, we can remove a potential performance
footgun without a lot of effort by passing around small pieces of data
that we otherwise need to fetch from the ScriptThread.

Testing: Existing WPT is sufficient
Fixes: part of #37969

---------

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
2025-08-30 16:51:40 +00:00
Andrei Volykhin
d253fe70f1
webgpu: Add the dedicated WebGPU task source (#39020)
According to the WebGPU specification there are the dedicated task
source
which is used to queue a global task for a GPUDevice on content
timeline.
https://gpuweb.github.io/gpuweb/#-webgpu-task-source

Tasks on content timeline:
- to fire "uncaptureevent" event
- to resolve GPUDevice.lost promise

Also fixed the "isTrusted" attribute status (false -> true) of the
"uncaptureevent" event by using non JS version of event dispatching.

Testing: No changes in WebGPU CTS expectations
- webgpu:api,operation,uncapturederror:*
- webgpu:api,operation,device,lost:*
- webgpu:api,validation,state,device_lost,destroy:*

Signed-off-by: Andrei Volykhin <volykhin.andrei@huawei.com>
Co-authored-by: Andrei Volykhin <volykhin.andrei@huawei.com>
2025-08-29 20:09:03 +00:00
Sam
b44b461a76
script: do not update Document rendering when waiting on asynchronous canvas image updates (#39022)
This is fixup for #37776. We forget to skip documents with
waiting_on_canvas_image_updates flag.

Testing: Existing WPT tests and manual testing
Fixes: #39021

---------

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
2025-08-29 15:09:19 +00:00
Sam
8beef6c21f
compositor: Allow canvas to upload rendered contents asynchronously (#37776)
Adds epoch to each WR image op command that is sent to compositor. The
renderer now has a `FrameDelayer` data structure that is responsible for
tracking when a frame is ready to be displayed. When asking canvases to
update their rendering, they are given an optional `Epoch` which denotes
the `Document`'s canvas epoch. When all image updates for that `Epoch`
are seen in the renderer, the frame can be displayed.

Testing: Existing WPT tests
Fixes: #35733

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
2025-08-29 10:04:41 +00:00
Tim van der Lippe
84f478a47a
Implement trusted types processing for JavaScript URL (#38623)
We pass in the new trait implementation to process the value,
which the CSP crate calls in its implementation. Additionally,
since the request url can change, we need to propagate that
to load_data as well.

This also avoids a crash when a discarded browsing context is
accessed while navigating the iframes in the WPT tests. This
is a known issue, but hampers investigation into actual
Trusted Types support.

All tests using iframes don't work, as they don't have the
correct browsing context. The other tests do work, but some
fail on header ascii parsing (#36801) or error while handling
errors. That last one I don't understand based on the current
code and I would need to do a deep-dive in the existing code
to understand better what's going on.

Part of #36258
Part of #37920

---------

Signed-off-by: Tim van der Lippe <tvanderlippe@gmail.com>
2025-08-27 21:53:18 +00:00
Jonathan Schwender
33e934421e
compositor: Hide IpcSender as implementation detail (#38963)
The `CrossProcessCompositorApi` already provides methods for most
messages.
Remove the `sender()` method, and hide the IpcSender as an
implementation detail. This is a preparation for abstracting over the
internal IpcSender.

Testing: No functional changes

---------

Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
2025-08-27 09:42:01 +00:00
Martin Robinson
87fe202ded
script: Integrate animated image updates into ScriptThread event loop (#38941)
Instead of manually triggering `ScriptThread::update_the_rendering`,
have animated images trigger rendering updates via the `ScriptThread`
event loop. This should result in fewer calls to
`ScriptThread::update_the_rendering`.

Testing: This should not change behavior and is thus covered by existing
tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
2025-08-26 17:24:12 +00:00
Martin Robinson
e7a963cca0
script: Generate only a single frame during "update the rendering" (#38858)
Instead of generating a frame for every display list, which might be one
rendered frame per `<iframe>`, generate only a single frame per call to
"update the rendering." This should make rendering more efficient when
there are `<iframe>`s present and also open up optimizations for
non-display list frames.

Testing: This could potentially reduce flashing of content during
rendering
updates, but that is very difficult to test.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-08-26 16:09:10 +00:00
criskell
9082217272
Move unsafe to the wrap method for global objects (#38896)
The method now doesn't need unsafe in its signature because it no longer
accepts unsafe pointers as arguments. We move the unsafe marker to the
method itself.

Testing: I opened the browser and went to google.com; I ran some WPT
(IndexedDB) tests.
Fixes: #38361

---------

Signed-off-by: criskell <96352451+criskell@users.noreply.github.com>
2025-08-25 22:02:55 +00:00
Gregory Terzian
ddf5f1eb2f
script: when handling page headers, stop if pipeline closed already (#38739)
Previously, the script-thread would assert the pipeline was closed if no
pending load was found, but it did not check whether the pipeline was
closed before processing the page headers. Since incomplete loads are
removed only when page headers are processed, this means the page
headers were processed even if the pipeline had been closed before the
page headers were available. If the pipeline had been closed as part of
exiting the constellation, it was possible for the constellation to have
exited by the time the page headers became available(since the
script-thread closes a pipeline independently from ongoing navigation
fetches), which would produce a panic on trying to communicate with the
constellation to obtain the browsing context info.

Note: due to the nature of the problem, I cannot verify that this fixes
the crash test, although logically this appears to make sense, and a
couple of days of WPT runs should tell us more.

Testing: A crash test was added; unfortunately the crash was
intermittent.
Fixes: https://github.com/servo/servo/issues/36747

---------

Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
2025-08-25 19:04:39 +00:00
Jonathan Schwender
ea5d786506
generic_channel: Preserve IPC errors (#38854)
We should not be using `route_ipc_receiver_to_new_crossbeam_receiver` or
similar methods, that `unwrap()` on the ROUTER thread if they encounter
IPC errors. Instead, we now propagate the error to the crossbeam
receiver.
In the GenericChannel::Crossbeam case this means, that we need to use a
`Result<T>` as the data type, even though the Result variant is always
okay, so that the receiver type is the same regardless of `IPC` or not.
This is required, so we have the same channel type, and can pass the
inner crossbeam channel into e.g. `select!`, without having to wrap or
re-implement select.

This also means, that as we switch towards GenericChannel, we will
gradually improve our error handling and eventually remove the existing
panics on IPC errors.

These changes were extracted out of
https://github.com/servo/servo/pull/38782

Testing: Covered by existing tests. No new panics were introduced.

Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
2025-08-25 04:19:41 +00:00
Martin Robinson
4784ff0375
script: Ensure that leaving the WebView sets the cursor back to the default cursor (#38759)
This changes makes a variety of changes to ensure that the cursor is set
back to the default cursor when it leaves the `WebView`:

1. Display list updates can come after a mouse leaves the `WebView`, so
   when refreshing the cursor after the update, base the updated cursor
   on the last hovered location in the `DocumentEventHandler`, rather
   than the compositor. This allows us to catch when the last hovered
   position is `None` (ie the cursor has left the `WebView`).
2. When handling `MouseLeftViewport` events for the cursor leaving the
   entire WebView, properly set the
   MouseLeftViewport::focus_moving_to_another_iframe` on the input event
   passed to the script thread.
3. When moving out of the `WebView` entirely, explicitly ask the
   embedder to set the cursor back to the default.

Testing: This change adds a unit test verifying this behavior.
Fixes: #38710.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-08-22 07:49:56 +00:00
lumiscosity
39f3ce7a2e
Make DOM geometry structs serializable (#38828)
Makes the following DOM geometry structs serializable:
- `DOMRect`
- `DOMRectReadOnly`
- `DOMQuad`
- `DOMMatrix`
- `DOMMatrixReadOnly`

Testing: Covered by WPT (`css/geometry/structured-serialization.html`).

---------

Signed-off-by: lumiscosity <averyrudelphe@gmail.com>
2025-08-21 23:19:42 +00:00
batu_hoang
bce9f06cf8
webdriver: Refactor webdriver session and improve window handles (#38745)
This PR contains 2 parts:

1. Refactor webdriver session.
2. Improve webdriver window handles:
- Webdriver always get window handles from script thread by default.
- If script thread is blocked by user prompt, embedder stores the window
handle before user prompt appears, then webdriver can get window handle
from embedder.

Testing: Clear timeout cause by user prompt blocking script thread:
https://github.com/longvatrong111/servo/actions/runs/17033900026

---------

Signed-off-by: batu_hoang <hoang.binh.trong@huawei.com>
Signed-off-by: batu_hoang <longvatrong111@gmail.com>
Co-authored-by: Euclid Ye <euclid.ye@huawei.com>
2025-08-21 22:46:13 +00:00
Josh Matthews
ed6bf196c9
constellation: Broadcast preference changes to all content processes (#38716)
Building on the preference observer work from #38649, we now
automatically install an observer when multiprocess mode is enabled.
This observer notifies the constellation of updated preferences, which
in turn notifies each content process so the changes will be reflected
into script/layout as expected. There's a unit test that verifies this
works correctly by checking a preference-gated WebIDL property before
and after the preference is toggled.

Testing: New unit test added.
Fixes: #35966

Depends on #38649.

---------

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
2025-08-20 06:43:16 +00:00
Jonathan Schwender
8587536755
Use GenericChannel for script_chan (#38645)
Motivation: 
Using our GenericChannel abstraction allows us to optimize IPC in
single-process mode to just use cross-beam channel.
To keep the diff low, and get early feedback, this PR only tackles a
single channel, but the intention is to port all ipc channels to the
generic channel, which allows us to skip serializing and deserializing
messages in single process mode.

Based on: 
- https://github.com/servo/servo/pull/38638
- https://github.com/servo/servo/pull/38636

Testing: Covered by existing tests

---------

Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
2025-08-19 09:59:20 +00:00
Euclid Ye
ec5872992b
webdriver: Reuse JSValue as WebDriverJSValue (#38751)
After #38748, `WebDriverJSValue` is almost same as `JSValue`. Now we
turn "potentially merge into one in the future" into reality. The only
thing we should be cautious is to properly serialize `WebFrame`,
`WebWindow`, `WebElement` for WebDriver.

Testing: No regression. Some error is fixed previously by #38709 which
didn't update test :)
Binary size reduced by 134KB.

---------

Signed-off-by: Euclid Ye <euclid.ye@huawei.com>
2025-08-18 17:38:48 +00:00
batu_hoang
f24f225db8
webdriver: Implement the "Get Window Handles" command (#38622)
Implment get window handles according to
[spec](https://w3c.github.io/webdriver/#dfn-window-handles).
- Window handles are supposed to identify `browsing context`. However,
based on `get window handle command` and `get window handles command`,
we only need to care about top level browsing context.
- Back then, we use a random generated uuid for eacch webview id, it is
not correct but still work because all commands depend on `webview id`
and `browsing context id`. The only case we need window handle is is
when webdriver gets window object with js script. Since the object is
converted to the id of window's document node, `get window handle`
should return the same thing.

Action run (with updated expectation):
https://github.com/longvatrong111/servo/actions/runs/16957610535
https://github.com/longvatrong111/servo/actions/runs/16957612027

Some tests may sporadically timeout due to unstable hit test.

cc: @xiaochengh

---------

Signed-off-by: batu_hoang <hoang.binh.trong@huawei.com>
2025-08-15 03:30:56 +00:00
lumiscosity
b747589286
script: Strip javascript URL scheme using Position::AfterScheme rather than Position::BeforePath (#38599)
This makes the initial split match step 2 of
https://html.spec.whatwg.org/multipage/browsing-the-web.html#evaluate-a-javascript%3A-url.

Testing: Covered by WPT tests.
Fixes: #38547

---------

Signed-off-by: lumiscosity <averyrudelphe@gmail.com>
2025-08-14 12:49:07 +00:00
Gregory Terzian
70be996a29
net: Remove CoreResourceThread from FetchThread state (#38422)
In single process mode, there is a race condition on the initialization
of the global fetch thread: once initialized the global fetch thread
will always use a given core resource thread, and this will be
determined by the component who first initializes it. For example, if
the canvas paint thread first does an async fetch, then this will set
the public core resource as used for all future fetches, including those
coming from a pipeline in private mode.

In multi-process mode, there is a race condition per window event-loop:
the first pipeline to use the fetch will set the core resource thread
for all others.

To ensure the fetch thread uses the correct core resource thread(private
vs public), we need to
pass the core resource thread to each fetch thread operation for which
is it needed.

Testing: It should not break existing fetch WPT tests. The race
condition is not something that can be tested reliably, but it seems to
be based on solid logic.
Fixes: follow-up from
https://github.com/servo/servo/pull/38421/files#r2248950924

---------

Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
2025-08-13 17:40:10 +00:00
Martin Robinson
069ad40872
script: Move the majority of the input event handling code to DocumentEventHandler (#38584)
This moves the majority of the input event handler code to the
`DocumentEventHandler` helper structure. It better encapsulates event
handling, hiding most of the details from both `ScriptThread` and
`Document`. The benefit here is that the majority of the functions can
become private and `Document` is over 1000 lines shorter.

Testing: This should not change any behavior so is covered by existing
WPT tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-08-13 09:38:58 +00:00
Rodion Borovyk
e5a73ede17
script: Send JS evaluation errors to constellation (#38602)
Send JS evaluation errors to constellation in
`script_thread::handle_evaluate_javascript` instead of silently
swallowing.

Testing: New test cases in `tests/webview.rs`: one for compilation
failure, another for evaluation failure.
Fixes: #37810

Signed-off-by: Rodion Borovyk <rodion.borovyk@gmail.com>
2025-08-12 07:19:39 +00:00
batu_hoang
9effdce5a1
Implement webdriver extract script arguments (#38357)
Fix script parsing step.
Implement webdriver `extract script arguments`.
Implement `deserialize_web_element` and `deserialize_shadow_root` from
script command argument.

Testing:
`/tests/wpt/tests/webdriver/tests/classic/execute_script/`
`/tests/wpt/tests/webdriver/tests/classic/execute_async_script/`

cc: @xiaochengh

---------

Signed-off-by: batu_hoang <hoang.binh.trong@huawei.com>
2025-08-12 06:57:19 +00:00
shuppy
f5b631e270
devtools: Show clients where they can set breakpoints (#37667)
devtools clients query source actors to determine where the user can set
breakpoints in a source. there are two relevant requests here:
`getBreakableLines` controls which line numbers can be clicked in the
margin, and once a line number is clicked,
`getBreakpointPositionsCompressed` controls where to show breakpoint
buttons within that line.

this patch handles those requests by querying the [SpiderMonkey Debugger
API](https://firefox-source-docs.mozilla.org/js/Debugger/) for that
information:
- devtools sends its script thread a GetPossibleBreakpoints message for
the source’s
[`spidermonkey_id`](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.Source.html#id)
- the script thread fires a `getPossibleBreakpoints` event into its
debugger global
- the debugger script looks up the
[root](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.html#onnewscript-script-global)
[Debugger.Script](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.Script.html#getpossiblebreakpoints-query)
for that source, calls
[getPossibleBreakpoints()](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.Script.html#getpossiblebreakpoints-query),
and returns the result via
DebuggerGlobalScope#getPossibleBreakpointsResult()
- that method takes the pending result sender, and sends the result back
to devtools
- devtools massages the result into the format required by the request,
and replies to the client

as a result, users of the Firefox devtools client can now set
breakpoints, though they don’t have any effect.

Testing: this patch adds new devtools tests
Fixes: part of #36027

<img width="1433" height="1328" alt="image"
src="https://github.com/user-attachments/assets/f0cd31e0-742f-44d3-8c5d-ceedd9a2706d"
/>

---------

Signed-off-by: Delan Azabani <dazabani@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
2025-08-12 04:53:53 +00:00
Martin Robinson
b75c3feb97
script/compositor: Send mouseleave events when cursor moves between <iframe>s (#38539)
Properly send `mouseleave` events when the cursor moves between
`<iframe>`s. This allows a better handling of cursor changes and status
text updates. Specifically, we do not need to continuously update the
cursor and the value can be cached in the `Document`. In addition,
status updates can now be sent properly when moving focus between
`<iframe>`s.

Note that style updates for `:hover` values are still broken, but less
so than before. Now the hover state on the `Node` is updated, but for
some
reason the restyle isn't taking place properly. This maintains the
status quo as far as behavior goes when hover moves between `<iframe>`s.

This change also adds a helper data structure to `Document` which will
eventually be responsible for event handling.

Testing: Cursor and status change are currently very hard to test as
the API test harness makes this difficult at the moment.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-08-11 12:31:54 +00:00
Rodion Borovyk
4f8731d562
script: Return a Result from GlobalScope::evaluate_script_on_global_with_result (#38549)
Make GlobalScope::evaluate_script_on_global_with_result return a Result
instead of a boolean. This is the first step to resolve issue #37810.

Testing: Should not break or fix any existing tests

---------

Signed-off-by: Rodion Borovyk <rodion.borovyk@gmail.com>
2025-08-10 16:51:46 +00:00
shuppy
a3e0a34802
script: Add new worker globals as debuggees (#38551)
to debug workers in a page with the [SpiderMonkey Debugger
API](https://firefox-source-docs.mozilla.org/js/Debugger/), we need to
pass the worker’s global object to
[Debugger.prototype.**addDebuggee()**](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.html#adddebuggee-global).
we could pick up the global via the [onNewGlobalObject()
hook](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.html#onnewglobalobject-global),
but if our script system passes the global to the debugger script
instead, we can later add details like the PipelineId that will help
servo identify debuggees that the API is notifying us about (#38334).

this patch creates a debugger global in worker threads, runs the
debugger script in those new globals, and plumbs new worker globals from
those threads into addDebuggee() via the debugger script. since worker
threads can’t generate PipelineId values, but they only ever run workers
on behalf of one pipeline, we use that pipeline’s PipelineId as the
PipelineId of the debugger global, rather than generating a unique
PipelineId like we do in script threads.

Testing: will undergo many automated tests in #38334
Fixes: part of #36027

Signed-off-by: Delan Azabani <dazabani@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
2025-08-09 11:28:06 +00:00
shuppy
6471587fb4
script: Set correct introductionType values in more places (#38550)
to use the [SpiderMonkey Debugger
API](https://firefox-source-docs.mozilla.org/js/Debugger/) as the single
source of truth about scripts and their sources for devtools purposes
(servo/servo#38334), we need to keep track of whether scripts come from
an actual file or from things like setTimeout(), because for some
[introductionType](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.Source.html#introductiontype)
[values](https://firefox-source-docs.mozilla.org/devtools-user/debugger-api/debugger.source/#accessor-properties-of-the-debugger-source-prototype-object),
we want to disregard the script unless it has a [`//# sourceURL=`
override](https://tc39.es/ecma426/#sec-linking-eval)
([displayURL](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.Source.html#displayurl)).

this patch builds on #38363, setting the correct introductionType value
in several more cases.

Testing: will undergo many automated tests in #38334
Fixes: part of #36027

---------

Signed-off-by: Delan Azabani <dazabani@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
2025-08-09 05:05:54 +00:00
Martin Robinson
6651f37c05
script/compositor: Handle cursor updates from script (#38518)
Instead of using WebRender hit testing to update the cursor, base it on
layout hit tests. This allows removing the majority of WebRender hit
test items and finally opens up the possibility of adding support for
custom cursors. In addition, this change fixes an issue where cursors
were not set properly on areas of the viewport that extended past the
page content.

Testing: This is difficult to test as verifying that the cursor changed
properly is beyond the capabilities of Servo's test harnesses.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-08-07 18:49:38 +00:00
Martin Robinson
ad805e3110
compositor/layout: Rely on layout for fine-grained input event hit testing (#38480)
Before, the compositor was responsible for doing the hit testing during
input events within a page. This change moves that hit testing to
layout.  With this change, epoch mismatches are no longer a bit deal and
we can simply ignore them, as the Constellation and Script will take
care of ignoring hit tests against scroll nodes and browsing contexts
that no longer exist. This means that hit testing retry support can be
removed.

Add the concept of a Script `HitTest` that transforms the coarse-grained
renderer hit test into one that hit tests against the actual layout
items.

Testing: Currently we do not have good tests for verifying the behavior
of
input events, but WebDriver tests should cover this.
Fixes: This is part of #37932.
Fixes: #26608.
Fixes: #25282.
Fixes: #38090.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
Co-authored-by: kongbai1996 <1782765876@qq.com>
2025-08-07 08:38:43 +00:00
Gregory Terzian
a99ad240a0
constellation: join on script-threads (#38424)
We currently send exit signals to script-threads, and we also join on
the BHM worker. This ensure the constellation shuts-down only after
script has dropped it's sender to the BHM worker. By joining on the
script-threads, we have a guarantee that they have exited(which is
stronger than having dropped their senders) by the time the
constellation exits.

Testing: Manually opened many tabs and closed the window, both in
single- and multi-process modes.
Fixes: Part of - https://github.com/servo/servo/issues/30849

---------

Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com>
2025-08-06 18:05:18 +00:00
Martin Robinson
3e856cbf11
layout: Introduce ReflowPhasesRun (#38467)
There were various booleans on `ReflowResults` that represented various
actions that might have been taken during a reflow request. Replace
those with a bitflags that better represents what reflow phases have
actually been run. Update variable names to reflect what they mean.

In addition, run some post-layout tasks unconditionally. They are
already contingent on the results returned from layout.

This simplifies and clarifies the code a good deal.

Testing: This should not change observable behavior and thus is covered
by existing WPT tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
2025-08-05 08:39:42 +00:00
shuppy
92a9d24a13
script: Add new Window globals as debuggees (#38333)
to debug the scripts in a page with the [SpiderMonkey Debugger
API](https://firefox-source-docs.mozilla.org/js/Debugger/), we need to
pass the page’s global object to
[Debugger.prototype.**addDebuggee()**](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.html#adddebuggee-global).
we could pick up the global via the [onNewGlobalObject()
hook](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.html#onnewglobalobject-global),
but if our script system passes the global to the debugger script
instead, we can later add details like the PipelineId that will help
servo identify debuggees that the API is notifying us about (#38334).

this patch plumbs new Window globals from script into addDebuggee() via
the debugger script. to call into the debugger script with structured
input, we create a new DOM event type, DebuggerEvent, that the debugger
script listens for as the “addDebuggee” event.

Testing: no testable effects yet, but will be used in #37667
Fixes: part of #36027

---------

Signed-off-by: Delan Azabani <dazabani@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
2025-08-05 05:48:53 +00:00
Martin Robinson
9416251cab
script: Unify script-based "update the rendering" and throttle it to 60 FPS (#38431)
Instead of running "update the rendering" at every IPC message, only run
it when a timeout has occured in script. In addition, avoid updating the
rendering if a rendering update isn't necessary. This should greatly
reduce the amount of processing that has to happen in script.

Because we are running many fewer calls to "update the rendering" it is
reasonable now to ensure that these always work the same way. In
particular, we always run rAF and update the animation timeline when
updating the ernder

In addition, pull the following things out of reflow:

 - Code dealing with informing the Constellation that a Pipeline has
   become Idle when waiting for a screenshot.
 - Detecting when it is time to fulfill the `document.fonts.ready`
   promise.

The latter means that reflow can never cause a garbage collection,
making timing of reflows more consistent and simplifying many callsites
that need to do script queries.

Followup changes will seek to simplify the way that ScriptThread-driven
animation timeouts happen even simpler.

Testing: In general, this should not change testable behavior so much,
though it
does seem to fix one test.  The main improvement here should be that
the ScriptThread does less work.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Oriol Brufau <obrufau@igalia.com>
2025-08-04 16:27:00 +00:00
Jo Steven Novaryo
a063b5e78a
script: Fire scroll event whenever JS scrolled (#38321)
Implement JS scroll event firing compliant to
https://drafts.csswg.org/cssom-view/#scrolling-events. Basically
whenever, the an element or the viewport is scrolled, we will fire a
scroll event. The changes push a scroll event whenever an API causes a
scroll position to change.

Testing: New WPT tests for basic APIs.
Part of: https://github.com/servo/servo/issues/31665

---------

Signed-off-by: Jo Steven Novaryo <jo.steven.novaryo@huawei.com>
2025-08-01 07:30:22 +00:00
shuppy
c09e117bfe
script: Create a debugger script for the SpiderMonkey Debugger API (#38331)
to use the [SpiderMonkey Debugger
API](https://firefox-source-docs.mozilla.org/js/Debugger/), we need to
call it from an internal debugger script that we will supply. this
script must run in the same runtime as the debuggee(s), but in a
separate
[compartment](https://udn.realityripple.com/docs/Mozilla/Projects/SpiderMonkey/Compartments)
([more
details](https://hacks.mozilla.org/2020/03/future-proofing-firefoxs-javascript-debugger-implementation/)).

this patch defines a new DebuggerGlobalScope type and a new debugger
script resource. when creating each script thread, we create a debugger
global, load the debugger script from resources/debugger.js, and run
that script in the global to initialise the Debugger API.

subsequent patches will use the debugger script as an RPC mechanism for
the Debugger API.

Testing: no testable effects yet, but will be used in #37667
Fixes: part of #36027

---------

Signed-off-by: Delan Azabani <dazabani@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
2025-07-31 06:17:23 +00:00