CLI
The inspector
The dev tools of `surf dev`: the panel, what it shows, and its protocol.This page as MarkdownThe inspector shows what a running app does. surf dev starts it, for the web target and for the desktop target. ADR-0105 gives the reasons for this design.The sides of a box have the order top, right, bottom, left. A gap has the order row gap, column gap.A part deeper than 6 levels shows as ..., and a text stops after 2000 characters.The text (not computed) means that nothing read the derived value after its last change. The inspector runs no code of the app, so it does not compute the value.A release build does not have the inspector. tests/inspector-release.sh proves this for the web target and for the desktop target.The agent in the app has no hooks while no panel is open. A panel attaches with its first poll. The agent removes its hooks 3 seconds after the last poll, for example after you close the panel.Three parts talk to each other. All text is JSON in UTF-8, and all connections stay on the loopback address.The broker refuses a request with a Host header that is not a loopback name, or with an Origin header of another address. It also refuses a Sec-Fetch-Site header other than same-origin or none, because a browser sends no Origin for <script src>. Each response has Cross-Origin-Resource-Policy: same-origin. Security, section 5, has the rules of surf dev.Each path starts with /__inspector/.A web page gets its messages on /events, the stream of hot reload. The dev host uses GET agent. The frames are the same: event: inspect, then one data: line with a JSON message. With more than one app, the newest app gets the messages.The answer of a poll:A message has the field method. The broker adds seq, the number of the request. attach and detach come from the broker, and they get no answer.An answer is { "seq": 7, "result": ... } or { "seq": 7, "error": "text" }. Without attach, each method gives the error no panel is attached.The broker also adds reset when an app connects during a session, and when an app goes away.Each change of the protocol changes three files: agent.js, crates/surf-desktop/src/dev/inspector.rs and panel/api.surfs.Use these tests:
- Start the app with surf dev, or with surf dev --target desktop.
- Find the line surf dev: inspector at http://127.0.0.1:8000/__inspector/ in the output.
- Open this address in a browser.
Part
What it shows
Tree
The components and their elements, in tree order. An element shows its own text.
Values
The props, the states and the derived values of the selected component. For a selected element, the values of the component that owns it.
Layout box
The position, the size, the padding, the margin, the border and the gap of the selected element, in logical px. For a selected component, the box of its first element.
Frame timings
The number of frames, the average and worst time, and a bar for each frame. The panel has the last 120 frames that changed something.
Redraw regions
The last 60 regions, the newest first.
- Press a row of the tree. The app marks the element.
- Press Pick, and move the pointer over the app. The app marks the element under the pointer. Press the element to select it. The press does not reach the app. Press Escape to stop.
Value
Text
Int, Float, Bool
5, 2.5, true
String
"first"
No value
none
A list
["a", "b"]
A map or a Set
Map {"p": 1}
A record
{x: 1, y: 2.5}
An enum
.idle, .running(level: 3)
Bytes
Bytes(16)
A function, a task
fn, task
Part
Where it runs
Panel
A browser. Its source is in crates/surf-cli/src/inspector/panel. surf compiles it for the first request.
Broker
The surf process: crates/surf-cli/src/inspector/mod.rs.
Agent
The app: agent.js on the web, and crates/surf-desktop/src/dev/inspector.rs on the desktop.
Request
Who sends it
Function
GET (the path alone)
Browser
The page of the panel.
GET app.js, GET app.css
Browser
The compiled panel.
GET agent.js
Web page
The web agent. A page loads it for the first message.
GET poll?after=N
Panel
The events after number N. The answer comes after an event, or after 1 second. A poll also tells the broker that the panel is open.
POST call
Panel
Sends a request to the agent. The answer is the result, or status 502 with the text of the error.
GET agent
Dev host
The stream of messages for the agent.
POST reply
Agent
An answer or an event.
json
{ "protocol": 1, "target": "web", "connected": true, "next": 12, "events": [{ "event": "changed" }] }
Method
Fields
Result
attach
The agent adds its hooks, and sends the event attached.
detach
The agent removes its hooks, its marks and its records.
tree
{ rows }
inspect
id
{ id, name, component, values, box }
select
id, or null for no selection
null. The app marks the element.
pick
on
null. Turns the pick mode on or off.
flash
on
null. Shows the redraw regions in the app, or stops.
frames
{ frames }
regions
{ regions }
Record
Fields
A row
id, depth, kind (component or element), name, text
A value
name, kind (prop, state or derived), ty, value
A box
x, y, width, height, padding, margin, border, gap. It is null for a component with no element.
A frame
n, at, update, render
A region
n, at, x, y, width, height
- An id is text. It stays the same for the life of its element or component, and it has no other meaning.
- n counts the frames and the regions of a session.
- at is the time in milliseconds after attach.
- update is the time of the batches or events in milliseconds, and render is the time of the frame in milliseconds.
Event
Fields
Meaning
attached
protocol, target
The hooks are ready.
changed
The tree or a value can have changed. It comes at most once in 200 ms.
picked
id, or null after Escape
The pick mode ended.
reset
A new app took the place of the old app, for example after a reload. Each id is old.
- cargo test -p surf-cli inspector: the broker, and the compile of the panel.
- cargo test -p surf-desktop --features dev inspector: the desktop agent.
- tests/browser/inspector.spec.js: the panel and the web agent, in Chromium.
- tests/inspector-desktop.sh: a real window, on a Mac.
- tests/inspector-release.sh: the size rule.