Add support for navigation requests ("navigateTo", "goBack", and
"goForward") over the Remote Debugging Protocol. These may be sent by a
UI client in response to user input (for example the address bar in the
Firefox inspector), or they can be used to automate navigation during
unit tests.
This currently only supports navigation within the URL domain at which
servoshell is initially launched, due to a bug in servo's
`BrowsingContextActor` implementation. (Unit tests covering a fix for
that issue will depend on this change.)
Testing: The behavior of all 3 new message types is covered by a new
test case—`test_navigation`—in the devtools unit test suite.
Fixes: #38668
---------
Signed-off-by: Brent Schroeter <contact@brentsch.com>
Co-authored-by: eri <eri@igalia.com>
Pass `ListFrames` back to devtools
Testing: existing test passes
Fixes: part of #36027
Signed-off-by: atbrakhi <atbrakhi@igalia.com>
Co-authored-by: eri <eri@igalia.com>
This change implements listing all frames from youngest to oldest. This
is in order to send correct frame message from thread actor
This is needed for our upcoming work!
Testing: Current tests are passing + manual test
Fixes: #36027
Signed-off-by: atbrakhi <atbrakhi@igalia.com>
Co-authored-by: eri <eri@igalia.com>
This is a preparation for publishing to crates.io. Changes include:
- Add `servo-` prefixes to avoid name collisions on crates.io
- Use `-` instead of `_` in package names.
- Rename the crates to their original names in Cargo.toml,
to keep the diff minimal
- Rename `media` to `servo-media-thread` to avoid name collision with
`servo-media` (originally from the media repository).
This is an outcome of the previous discussion at [#general > Switch
remaining git dependencies to
crates.io](https://servo.zulipchat.com/#narrow/channel/263398-general/topic/Switch.20remaining.20git.20dependencies.20to.20crates.2Eio/with/576336288)
Testing: This should be mostly covered by our CI, but some amount of
breakage is to be expected, since some package names could still be
referenced from scripts which are not tested or run in CI. [mach try
run](https://github.com/jschwe/servo/actions/runs/22502945949)
---------
Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
Before we were creating a new frame actor each time we paused, even if
the frame object in debugger.js was the same. Now we avoid this by
reusing the same frame actor id.
This helps our upcoming work on onStep, onPop, and onEnterFrame hooks.
Testing: Ran `mach test-devtools` and manually check that it works
Part of: #36027
Signed-off-by: eri <eri@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
devtools: Make `why` attribute use `PauseReasons`
Currently we have why attribute hardcoded as per the event. In this PR
we introduce `PAUSE_REASON` and make sure `why` attribute is using
`PAUSE_REASONS`.
This is in order to support the upcoming work on `onStep`, `onPop`, and
`onEnterFrame` hook.
Testing: all existing tests are passing
Fixes: Part of #36027
Signed-off-by: atbrakhi <atbrakhi@igalia.com>
Co-authored-by: eri <eri@igalia.com>
We need a map between frame actor ids (from devtools) and frame objects
(from debugger.js) to implement stepping hooks in the future.
To achieve this, we register the frame actor with a call to the devtools
before entering the event loop when the debugger is paused. Instead of
creating the frame actor in `handle_debugger_pause`, we create it
before.
Testing: It passes existing devtools tests
Part of: #36027
Signed-off-by: eri <eri@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
The pause debugger screen should be shown for both pausing manually
(interrupt) and hitting a breakpoint.
Reuse the logic for pausing breakpoints to pause the debugger when the
user manually clicks the pause button.
Rename the pause event to interrupt to match the language of the
DevTools client and to avoid confusion with paused frames, which can
happen on interrupt or on a breakpoint.
https://github.com/user-attachments/assets/ceb0007d-0e57-44d6-a159-55980ff8b517
Testing: New DevTools test and manual testing.
Part of: #36027
cc @atbrakhi
---------
Signed-off-by: eri <eri@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
The inspector view allows modifying the attributes of DOM elements.
However, we lie to the devtools client: While it looks like the
attributes change, the changes are never actually applied to the DOM.
This change fixes that, and also makes it so attribute modifications
from non-inspector sources are shown in the inspector.
Testing: This change adds two tests
---------
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
Both the `DevtoolsInstance` and the `BrowsingContextActor` maintain a
list of live connections. When a new global is created, its
`BrowsingContextActor` copies the list of active connections from the
`DevtoolsInstance`. When a client handler thread exits, the
`BrowsingContextActor`s remove the connection from their list of
connections.
This has two implications:
* `BrowsingContextActor`s don't know about connections that are created
after they were constructed, causing them to possibly incorrectly tell
script that it doesn't need to send devtools updates anymore
* the `DevtoolsInstance` never notices when connections are closed and
panics when writing to them.
To fix this, I've removed the list of connections from the
`BrowsingContextActor` and adjusted the logic to notify script when
updates aren't needed anymore accordingly.
For some reason, our tests always open two connections and close the
first one immediately, which is how I found this bug in the first place.
Part of https://github.com/servo/servo/issues/42454 - previously
d5d400c7d6/components/script/dom/globalscope.rs (L240-L242)
was always false during our tests.
---------
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This change makes the devtools inspector show any event listeners that
are attached to a node. The primary motivation is making the devtools
more useful for debugging real-world websites.
<img width="536" height="268" alt="image"
src="https://github.com/user-attachments/assets/5ba13e41-14b4-4202-b994-eadff5d1c6b5"
/>
You can also click on the event listener to show some more info, though
most of that (everything except the event type and the event phase) is
currently just placeholder text:
<img width="1360" height="456" alt="image"
src="https://github.com/user-attachments/assets/ec025847-43fc-489c-8b26-46afb6dada64"
/>
Testing: This change adds a new test
---------
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This implements MallocSizeOf for DevtoolsInstance. Major changes:
- Newtype for ActorRegistry because AtomicRefCell<HashMap<String,
Arc<dyn Actor>>> did not like mallocsizeof (even with trait bound on
Actor)
- Implement MallocSizeOf for BTreeSet.
- Implement MallocSizeOf of 0 for AtomicU32 and TcpStream
- Ignore a couple of MallocSizeof for http::Method, http::HeaderMap and
json::Value
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
Testing: Compilation is the test.
Fixes: Part of addressing https://github.com/servo/servo/issues/42453
---------
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
This allows us to `console.log` objects from JS and have a preview of
them appear in the console.
Interacting with said preview doesn't work yet, because the devtools
object actor is a stub.
<img width="600" height="78" alt="image"
src="https://github.com/user-attachments/assets/d896471f-3982-4406-94d4-b13eebabe337"
/>
Testing: This change adds a test
---------
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
There were some `#[serde(untagged)]` and `#[serde(skip*)]` annotations
in the shared devtools types. These are needed for correct JSON
serialization when sending messages to Firefox, but they fail in
multiprocess mode since we are sharing them through the IPC channel with
bincode, which doesn't support certain serde tags.
The workaround is to keep all shared types free from problematic
annotations, and defining wrapping types that are only used in the
devtools crate.
One instance are console messages and page errors. They have been moved
to `console.rs`, with `shared/devtools` only keeping the parts that are
needed for communication between threads.
The other instance are auto margins. Now the final message is built in
`page_style.rs`.
Apologies since both of them were introduced by me, I wasn't aware that
we were limited by bincode in multiprocess mode. A warning has been
added to `shared/devtools` listing the problematic annotations that
shouldn't be used in this file.
Testing: `mach test-devtools` and manual testing using `--multiprocess`.
Fixes: #42170
Signed-off-by: eri <eri@igalia.com>
Add an event listener for `clearBreakpoint` to `debugger.js` and the
necessary glue to access it from the `devtools` crate.
Testing: `./mach test-devtools` and manual testing.
Fixes: Part of: https://github.com/servo/servo/issues/36027
---------
Signed-off-by: atbrakhi <atbrakhi@igalia.com>
Co-authored-by: eri <eri@igalia.com>
Add an event listener for `pause` to `debugger.js` and the necessary
glue to access it from the `devtools` crate. This returns important
information to know where we are paused, such as the source location and
frame state.
Fix frame and object actor encoding into messages. Use information from
`debugger.js` to correctly fill the fields.
Add a new `frames` list to the thread actor and handle the `frames`
message.
Fix `getEnvironment` reply in the frame actor. It is out of form (has a
`type` field but it doesn't require a followup empty message, it already
counts as a reply), so we need to handle it specially.
Note: For now we are focusing on the protocol side of the debugger, and
this patch only shows where the pause would happen. Pausing Servo itself
will happen in a followup.

Testing: `mach test-devtools` and manual testing. No errors (apart from
#42006).
Part of: #36027
---------
Signed-off-by: eri <eri@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
Co-authored-by: Josh Matthews <josh@joshmatthews.net>
Listen for `setBreakpoint` on `debugger.js` and add the relevant WebIDLs
and Servo counterparts to trigger this event and notify SpiderMonkey.
Implement `find_source` for `SourceManager` and `find_offset` for
`SourceActor`.
Testing: Manual testing and `./mach test-devtools` (note, the latter
seems to have some failing tests, we are investigating this, but this
patch doesn't add any new failure).
Fixes: Part of #36027
---------
Signed-off-by: eri <eri@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
Fix caching before the console is opened and stop sending messages
prematurely.
Fix line numbers not showing in console messages because of a missing
`rename_all`.
Remove `getCachedMessages` in favour of sending a list of messages as a
reply to the `watchResources` for `console-message`/`error-message` in
the watcher.
Remove `startListeners` and `stopListeners`. These are legacy methods of
watching properties before the watcher actor. It is preferred to enable
properties in `supported_resources` in the watcher than to use these
messages.
Remove `clearMessagesCache`, only `clearMessagesCacheAsync` seems to be
used now. Add a reply to `clearMessagesCacheAsync`.
Simplify a bit the structs for console messages and prefer serde's
annotations to manual serialization. Merge `handle_console_message` and
`handle_page_error`, and improve the usability of `ConsoleResource`.
Fix some fields in console messages. We are missing `source_id` for now.
This will be easier to add after better support for source actors. We
are also missing stack traces.
| Before | After |
| --- | --- |
| 
| 
|
Testing: Manual testing
Fixes: #26666
---------
Signed-off-by: eri <eri@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Fix a panic when calling `determine_auto_margins` for nodes without
`.style()`. Now it returns an empty `AutoMargins` (all options set to
`None`), which matches the behaviour in Firefox:
```json
"autoMargins": {}
"autoMargins": {"top": "auto", "bottom": "auto", "left": "auto", "right": "auto"}
```
Refactor `GetLayoutReply` and `ComputedNodeLayout` to take advantage of
serde's flatten feature, making the serialization much cleaner.
Testing: Manual testing with the example provided in the issue.
Fixes: #41743
---------
Signed-off-by: eri <eri@igalia.com>
First PR for #40232.
Implement the getSecurityInfo protocol message to allow DevTools clients
to inspect TLS connection details for HTTPS requests, including:
- Protocol version (TLS 1.2/1.3)
- Cipher suite
- Key exchange group
- ALPN protocol
- HSTS and ECH status
- Security state
Security state is simplified (secure/insecure only) and certificate
details are stubbed out; both will be completed in follow-up work.
Signed-off-by: jiang1997 <jieke@live.cn>
Switch the devtools part to GenericCallback and GenericSender.
To keep the diff small the names where not changes as a Sender almost
fills the same requirement as a callback.
Testing: As this is mostly type changes, the compilation is the test but
also devtools seem to work fine with these changes. ./mach try run is
here: https://github.com/Narfinger/servo/actions/runs/19931697694
---------
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
Adds a wrapper type for vectors that can contain large response bodies
to prevent flooding debug logs with the contents of those bodies.
Testing: Can't test debug log output.
Fixes: #37769
---------
Signed-off-by: Josh Matthews <josh@joshmatthews.net>
Expose cache status for requests in network monitor.
Testing: Net tests pass. No existing test infrastructure for devtools,
adding them seems outside the scope of this PR.
Fixes: #40237
Signed-off-by: Mark Buer <flux.syntax@proton.me>
You can copy the XPath selector from the inspector by right-clicking on
a node and selecting `Copy->XPath`.
Testing: I tried adding a test but the effort didn't seem worth it. The
devtools tests are currently very specifically tailored towards
source-list tests.
Part of https://github.com/servo/servo/issues/39862
Part of #34527
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
currently our devtools impl creates source actors in script, when
executing scripts in HTMLScriptElement or DedicatedWorkerGlobalScope.
this approach is cumbersome, and it means that many pathways to running
scripts are missed, such as imported ES modules.
with the [SpiderMonkey Debugger
API](https://firefox-source-docs.mozilla.org/js/Debugger/), we can pick
up all of the scripts and all of their sources without any extra code,
as long as we tell it about every global we create (#38333, #38551).
this patch adds a [Debugger#onNewScript()
hook](https://firefox-source-docs.mozilla.org/js/Debugger/Debugger.html#onnewscript-script-global)
to the debugger script, which calls
DebuggerGlobalScope#notifyNewSource() to notify our script system when a
new script runs. if the source is relevant to the file tree in the
Sources tab, script tells devtools to create a source actor.
Testing: adds several new automated devtools tests
Fixes: part of #36027
Signed-off-by: Delan Azabani <dazabani@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
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>
in the devtools protocol, [source
forms](https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html#loading-script-sources)
announced in `resources-available-array` messages can include the
`introductionType`, which more or less mirrors the field of the same
name in SpiderMonkey’s CompileOptions.
this patch exposes `introductionType` accordingly, allowing us to check
for the correct values in automated tests.
Testing: new coverage in devtools tests
Fixes: part of #36027
---------
Signed-off-by: Delan Azabani <dazabani@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
The cause_type in NetworkEventActor was derived from a hard-coded
pattern match on the request URL file extension.
This patch replaces the hard-coded pattern matching with the Destination
field of Request, to provide a better alignment with the Fetch
specification.
Testing: Updated unit tests.
Fixes: #38151
---------
Signed-off-by: Kingsley Yung <kingsley@kkoyung.dev>
This change refactors how we notify DevTools about network activity so
that all fetches (even those served from cache) appear correctly in the
Network panel, and so that DevTools sees request metadata as soon as
possible rather than waiting until the end of a full HTTP cycle.
- Before, we only send DevTools events inside http_network_fetch, so
cached responses (which skip that path) never show up. By emitting a
minimal HttpRequest event at the very start of main_fetch (with URL,
method, pipeline and browsing IDs), we guarantee every fetch shows up
immediately.
- Then, by moving HttpResponse notifications out of http_network_fetch
into main_fetch (right after process_response and process_response_eof),
we ensure DevTools gets status, header, and completion events for both
network and cache hits. Leveraging nullable fields in NetworkEventActor
lets us incrementally fill in timing, header, and body data later,
improving DevTools’ visibility.
Testing: Ran servo with `--devtools=6080` flag, cached responses now
appear in the network panel
Fixes: https://github.com/servo/servo/issues/37869
---------
Signed-off-by: Uthman Yahaya Baba <uthmanyahayababa@gmail.com>
The will-navigate message tells the devtools client to expect a
navigation for a browsing context. This makes the network monitor clear
any previous entries and show the requests for the new page that is
loaded. In order to support this correctly, we need to send the
navigation notification from the constellation instead of the script
thread, otherwise we silently ignore navigations triggered by the
browser URL bar.
Testing: Ran servo in devtools mode , now the requests appear for new
loaded page
Fixes: https://github.com/servo/servo/issues/37334
---------
Signed-off-by: Uthman Yahaya Baba <uthmanyahayababa@gmail.com>
This enables console.* commands in javascript to be forwarded to the
logger and not just stdout.
The domain for this will be `script::dom::console` which seems
appropate.
Testing: Logs do not have any tests.
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
To show the contents of inline scripts in the Sources panel, we need to
send the whole HTML file from script to devtools, not just the script
code. This is trickier than the external script case, but we can look to
[how Firefox does
it](https://servo.zulipchat.com/#narrow/channel/263398-general/topic/Getting.20the.20original.20page.20HTML.20from.20script/near/524392861)
for some inspiration. The process is as follows:
- when we execute a script
- notify devtools to create the source actor
- if it’s an external script, send the script code to the devtools
server
- if it’s an inline script, don’t send any source contents yet
- devtools stores the contents in the source actor
- while loading a new document
- buffer the markup, so we can send it to devtools
- when we finish loading a new document
- send the buffered markup to the devtools server
- devtools stores the contents in any source actors with no contents yet
- when a source actor gets a `source` request
- if we have the contents, send those contents to the client
- if we don’t have the contents (inline script that loaded while
devtools was closed)
- FUTURE: try to fetch the markup out of cache
- otherwise send `<!-- not available; please reload! -->`
Testing: Several tests added to test the changes, also updates an
existing test with correct assertion
Fixes: https://github.com/servo/servo/issues/36874
---------
Signed-off-by: atbrakhi <atbrakhi@igalia.com>
Signed-off-by: Delan Azabani <dazabani@igalia.com>
Co-authored-by: Delan Azabani <dazabani@igalia.com>
This patch adds support for showing source_content in `Debugger >
Source` panel. This works by handling the clients `source` messages in
the source actor. These source actors are already advertised as resource
via the watcher, populating the source list. We also update the
`sources` handler in thread actor for future work in thread debugging.
Note: while this PR also adds support for showing worker script
source_content, worker has been broken (See
https://github.com/servo/servo/issues/37012). I was able to confirm the
`content_type` and `source_content` for worker script in logs.

Fixes: part of https://github.com/servo/servo/issues/36027
---------
Signed-off-by: atbrakhi <atbrakhi@igalia.com>
This change connects the `HighlighterActor` from the devtools with the
document, which will draw a blue rectangle over any highlighted dom
node.
https://github.com/user-attachments/assets/571b2dab-497f-4102-9e55-517cdcc040ba
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by
`[X]` when the step is complete, and replace `___` with appropriate
data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes do not require tests because we don't have devtools
tests
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This patch adds support for listing scripts in the Sources panel.
Classic scripts, both external and inline, are implemented, but worker
scripts and imported module scripts are not yet implemented.
For example:
```html
<!-- sources.html -->
<!doctype html><meta charset=utf-8>
<script src="classic.js"></script>
<script>
console.log("inline classic");
new Worker("worker.js");
</script>
<script type="module">
import module from "./module.js";
console.log("inline module");
</script>
<script src="https://servo.org/js/load-table.js"></script>
```
```js
// classic.js
console.log("external classic");
```
```js
// worker.js
console.log("external classic worker");
```
```js
// module.js
export default 1;
console.log("external module");
```

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by
`[X]` when the step is complete, and replace `___` with appropriate
data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes partially implement #36027
<!-- Either: -->
- [ ] There are tests for these changes OR
- [x] These changes require tests, but they are blocked on #36325
Signed-off-by: Delan Azabani <dazabani@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>