Previously arrays were falling back to Object previewer which was
showing indices as properties- which was not correct. This PR implements
dedicated `ArrayPreviewer` that follows Firefox's `ArrayLike` pattern.
Currently array preview support only length display, it does not
implement showing array items yet.
Now(Correct and follows Firefox pattern, Array items coming in a
follow-up PR):
<img width="510" height="167" alt="image"
src="https://github.com/user-attachments/assets/a51f04d4-333c-4d7c-8159-18121c967670"
/>
Before(We shouldn't see these values- it's incorrect):
<img width="1294" height="721" alt="image"
src="https://github.com/user-attachments/assets/2218a622-c791-4436-958e-1a5553de7864"
/>
Testing: Current tests are passing.
Fixes: Part of #36027
Signed-off-by: atbrakhi <atbrakhi@igalia.com>
This fixes a warning of `cargo publish`:
```
warning: manifest has no description, documentation, homepage or repository
```
Testing: Compiling. Manual testing of `cargo publish --dry-run` (with
some additional patches, and until the next error, shows this warning
has been fixed)
Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
Implement `PropertyIteratorActor` boilerplate
This is prerequisite for implementing object property enumeration in the
debugger. It is part of popup preview work in debugger.
Testing: Should not change behavior
Fixes: part of #36027
Signed-off-by: atbrakhi <atbrakhi@igalia.com>
This change implements showing scope variable in Debugger tab. This is
still early and we have more work to do.
Next step is building correct data structure and showing different types
of variables.
Testing: Manual as well as current tests are passing.
Fixes: part of #36027
Signed-off-by: atbrakhi <atbrakhi@igalia.com>
Co-authored-by: eri <eri@igalia.com>
In order to prepare for publishing this PR does the following steps (see
commits):
- Move all `path` dependencies to the workspace Cargo.toml, and
reference that.
- Move all path dependencies in the workspace Cargo.toml into a
dedicated section, to make bumping version numbers easier later.
- Add the version requirement. Note that we currently only version bump
servoshell. There was agreement to version everything with the same
version as servoshell, but that be done in a follow-up. The diff is
already large enough as is.
- Add a tidy lint to catch `path` usages outside the root Cargo.toml. I
switched to [`tomllib`] (which was added to the python stdlib in 3.11),
since the third-party `toml` library failed to parse Cargo.toml files
with `workspace.version` (did not like the `.` in a `key`).
[`tomllib`]: https://docs.python.org/3/library/tomllib.html
Testing: Should be covered by regular CI testing.
---------
Signed-off-by: Jonathan Schwender <schwenderjonathan@gmail.com>
`reply_unchecked` was added in #42007 since `getEnvironment` from the
frame actor has a `type` field but it already counts as a final reply,
unlike every other message like it. Since it is only used there, we can
revert the `reply_unchecked` change and use the new `mark_handled`
instead.
Depends on: #43230
Testing: DevTools tests
Signed-off-by: eri <eri@igalia.com>
Some Remote Debugging Protocol message types are specified as `oneway`,
meaning that they expect no reply. Sending anything—including an
error—in response to these messages throws the devtools client and actor
out of sync.
As noted in the `ClientRequest` docstring, most client messages expect
exactly one reply, so `ClientRequest::handle()` includes a fail-safe
that automatically sends an error message if none of the `reply()`,
`reply_unchecked()`, or `reply_final()` methods have been called.
This change introduces an additional method,
`ClientRequest::mark_handled()`, which allows the actor handling the
request to disarm the fail-safe without sending a reply over the wire,
and it adds handling logic for 3 one-way message types that are
frequently emitted by the Firefox Toolbox.
Testing: This change introduces no new tests. Unless we take the unusual
step of enumerating all supported one-way message types and validating
each, automated tests provide little assurance of correctness.
Meaningfully testing this feature would be cumbersome, and it would
likely hamper future development more than it would help.
Signed-off-by: Brent Schroeter <contact@brentsch.com>
The `InspectorActor` and its children now query the
`BrowsingContextActor` for the active pipeline ID and script sender
instead of storing their own copies, which become outdated on
navigation. Previously, the inspector remained permanently stuck to the
pipeline that was active upon launch. Now, connecting a fresh devtools
client session after navigation allows inspection of each
`BrowsingContext`'s active DOM.
Navigation within a continuous remote debugging session still breaks the
Firefox inspector panel. This is due to multiple compatibility issues
with the protocol implementation, which will be addressed in separate
PRs.
This PR does not touch `TimelineActor` or `FramerateActor`. These are
theoretically affected by the same issue as the `InspectorActor`, but in
practice neither is ever instantiated. It seems both have been
effectively unreachable code since 1aab10f2 and will require more
extensive work and testing that is beyond the scope of this change.
Testing: Updates to the `WalkerActor` and `BrowsingContextActor` are
unit tested via the new `test_walker_observes_new_dom_after_nav` case in
`devtools_tests.py`. There are no existing unit tests to reference for
the highlighter and style actors; these have been tested manually but
this PR does not introduce further automated tests. This PR also
improves handling of `tabNavigated` messages to simplify the unit test
written for 4c69d85.
---------
Signed-off-by: Brent Schroeter <contact@brentsch.com>
Initial work to support scopes in the debugger. They don't show at the
moment since we are not processing variables yet. Depends on #43166.
Testing: Ran `mach test-devtools` and manual testing.
Part of: #36027
Signed-off-by: eri <eri@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
This functionality will be used in a follow up patch to implement the
getEnvironment message.
Testing: Check `mach test-devtools` and manual test
Part of: #36027
Signed-off-by: eri <eri@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@igalia.com>
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>
Currently, `script` and `devtools` use a node's unique id to identify it
across requests. The unique ID is part of a node's rare data field and
is really only meant for debugging. Instantiating it on a node causes
it's memory usage to go up significantly. Now, when the devtools ask for
information about a specific `Node` then they send the unique ID to
`script`, and the script thread then walks the whole DOM tree searching
for that specific ID. This happens here:
6d0b651218/components/script/devtools.rs (L142-L153)
So, in the worst case, all of the nodes in the tree now have a unique
ID. That's not great!
Also, when `script` notifies `devtools` about changes to a DOM node then
`devtools` expects a `NodeActor` to exist for that Node. The actor might
not exist if the inspector doesn't know about that node yet - that
happens when the user hasn't expanded their parent yet.
That is an oversight from https://github.com/servo/servo/pull/42601 and
causes problems now(https://github.com/servo/servo/issues/42784) because
for the longest time, `devtools` was mostly the one sending requests. Of
course, we could make `devtools` simply ignore updates for nodes that it
doesn't know about, but ideally we shouldn't send these updates in the
first place.
This change implements a lookup map on the `ScriptThread` that contains
all nodes that have been sent to the devtools inspector. The map allows
us to efficiently resolve a unique ID to a `Node` in O(1), without
creating unique IDs for the whole tree. It also allows us to only send
DOM updates for nodes that the inspector cares about.
For now, entries from the cache are not evicted unless the relevant
pipeline is closed. That reflects reality, because the inspector also
keeps using them forever.
In the future we will tell the inspector when nodes are removed from the
tree - then it can't interact with them anymore, and we can remove them
from the script-side map.
This is change is not all that complicated but it involves moving a lot
of code around, so feel free to ask for clarification when something is
unclear!
Testing: This change adds a test
Fixes part of https://github.com/servo/servo/issues/42784
---------
Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
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>
Previously we listened to 0.0.0.0. which means any connection coming to
a specific port. That seems a bit ill advised as not everybody has a
good firewall setup. Now we default listen only on 127.0.0.1 but
optionally can describe a full SocketAddr such as "192.168.1.23:1234".
Side note: Cleaned up the ipc-channel syntax.
Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
Testing: Currently we don't have an automatic way to test this. Manually
run devtools and it connects.
---------
Signed-off-by: Narfinger <Narfinger@users.noreply.github.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>
When the servo window is closed while there is an active devtools
connection then the devtools threads reliably panics because it can't
talk to script anymore. We can simply ignore the `Disconnected` error
when shutting down. If the script thread already shut down then there's
nothing meaningful for the devtools to send anyways.
Testing: This kind of interaction is hard to test. I've not written an
automated test.
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>
Handle `enumProperties`, `enumSymbols` and `prototype` messages.
Create `PropertyIteratorActor` and `SymbolIteratorActor`.
This shows hover information when paused in the debugger, but only for
built-in Javascript objects. Next step would be to fix `evaluateJSAsync`
to take into account the frame / context in which we are evaluating
messages, so that we can do the same for local variables and functions.
Testing: Ran `mach test-tidy` and manual testing.
Part-of: #36027
@atbrakhi
Signed-off-by: eri <eri@igalia.com>
Co-authored-by: atbrakhi <atbrakhi@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>
Make the `start` and `end` parameters in
`getBreakpointPositionsCompressed` optional.
Send a resource array even if it is empty.
Testing: Ran `mach test-devtools`.
---------
Signed-off-by: eri <eri@igalia.com>
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>
This change is to make visibility uniformly crate wide across all of the
structs and their props within devtools.
Testing: Tested using `.\mach build -d` `.\mach fmt` `.\mach test-tidy`
all passed
Part of: #41893
---------
Signed-off-by: Seiran <bo646ru@gmail.com>