react-x11 2.52.0 → 2.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -10
- package/docs/README.md +160 -314
- package/docs/accessibility.md +176 -229
- package/docs/appearance.md +77 -176
- package/docs/click-to-component.md +18 -51
- package/docs/clipboard.md +40 -59
- package/docs/components.md +518 -1036
- package/docs/dbus.md +61 -133
- package/docs/debugging.md +152 -245
- package/docs/desktop-calendar.md +51 -88
- package/docs/desktop.md +222 -347
- package/docs/devtools.md +50 -167
- package/docs/drag-and-drop.md +126 -204
- package/docs/ecosystem/animation.md +91 -125
- package/docs/ecosystem/data-fetching.md +38 -53
- package/docs/ecosystem/dev-tooling.md +159 -202
- package/docs/ecosystem/forms.md +61 -97
- package/docs/ecosystem/headless.md +64 -89
- package/docs/ecosystem/i18n.md +18 -21
- package/docs/ecosystem/icons.md +93 -126
- package/docs/ecosystem/layout.md +42 -52
- package/docs/ecosystem/routing.md +18 -29
- package/docs/ecosystem/state.md +71 -88
- package/docs/ecosystem/testing.md +131 -157
- package/docs/ecosystem/theming.md +119 -165
- package/docs/ecosystem.md +145 -179
- package/docs/elements.md +1091 -1774
- package/docs/embedding.md +83 -132
- package/docs/events.md +412 -695
- package/docs/extending.md +784 -1326
- package/docs/eyedropper.md +63 -122
- package/docs/filedialog.md +71 -107
- package/docs/frame.md +195 -339
- package/docs/gl.md +65 -62
- package/docs/globalmenu.md +63 -146
- package/docs/macos.md +531 -3234
- package/docs/notifications.md +33 -47
- package/docs/packaging.md +166 -309
- package/docs/permissions.md +9 -14
- package/docs/react-features.md +81 -106
- package/docs/remote.md +32 -76
- package/docs/scale.md +72 -186
- package/docs/styling.md +329 -547
- package/docs/system.md +200 -280
- package/docs/testing.md +63 -83
- package/docs/typescript.md +6 -48
- package/docs/uri-schemes.md +67 -107
- package/docs/wayland-backend.md +200 -459
- package/docs/windows-integrations.md +75 -131
- package/docs/windows.md +343 -1367
- package/package.json +3 -2
- package/src/Reconciler.js +2 -2
- package/src/a11y.js +1 -1
- package/src/backend/context2d.js +3 -3
- package/src/bootstrap.js +1 -1
- package/src/cocoa/app.js +6 -6
- package/src/cocoa/bezels.js +1 -1
- package/src/cocoa/fonts.js +1 -1
- package/src/cocoa/globalmenu.js +1 -1
- package/src/cocoa/keymap.js +1 -1
- package/src/cocoa/panewindow.js +1 -1
- package/src/cocoa/player.js +1 -1
- package/src/cocoa/presenter.js +2 -2
- package/src/cocoa/promotion.js +1 -1
- package/src/cocoa/relaunch.js +1 -1
- package/src/cocoa/threaded.js +1 -1
- package/src/cocoa/video.js +1 -1
- package/src/cocoa/window.js +4 -4
- package/src/components/Menu.js +7 -2
- package/src/components/Switch.js +1 -1
- package/src/components/native.js +1 -1
- package/src/dnd.js +2 -2
- package/src/glnodes.js +1 -1
- package/src/grid.js +1 -1
- package/src/layouts.js +1 -1
- package/src/nodes/animation.js +1 -1
- package/src/nodes/invalidate.js +1 -1
- package/src/nodes/layouthost.js +1 -1
- package/src/nodes/video.js +19 -8
- package/src/nodes/window/droptarget.js +1 -1
- package/src/pacing.js +1 -1
- package/src/refresh/index.js +2 -1
- package/src/types/video.d.ts +5 -2
- package/src/videobackend.js +28 -0
- package/src/videoframes.js +29 -16
- package/src/wayland/app.js +27 -0
- package/src/wayland/video.js +376 -0
- package/src/win32/a11y.js +1 -1
- package/src/win32/app.js +2 -2
- package/src/win32/fonts.js +1 -1
- package/src/win32/glarea.js +4 -4
- package/src/win32/overlay.js +1 -1
- package/src/win32/panewindow.js +3 -3
- package/src/win32/shell.js +1 -1
- package/src/win32/window.js +2 -2
- package/src/windowid.js +1 -1
- package/src/xvideo.js +189 -0
- package/docs/architecture/accessibility.md +0 -470
- package/docs/architecture/animation.md +0 -707
- package/docs/architecture/container-queries.md +0 -525
- package/docs/architecture/custom-layout.md +0 -334
- package/docs/architecture/drag-and-drop.md +0 -941
- package/docs/architecture/element-layer-contents.md +0 -622
- package/docs/architecture/frame-pacing.md +0 -255
- package/docs/architecture/grid-layout.md +0 -358
- package/docs/architecture/protocol-efficiency.md +0 -357
- package/docs/architecture/video.md +0 -1149
- package/docs/architecture/windowed-regions.md +0 -854
- package/docs/glx.md +0 -137
- package/docs/wayland.md +0 -545
- package/docs/windows-embedding.md +0 -271
- package/docs/windows-gl.md +0 -221
package/docs/devtools.md
CHANGED
|
@@ -26,14 +26,12 @@ What you get:
|
|
|
26
26
|
|
|
27
27
|
- the **component tree**, live as the app updates;
|
|
28
28
|
- **props, hooks and state** when selecting a component, and editing any of
|
|
29
|
-
them — the
|
|
30
|
-
app really re-renders;
|
|
29
|
+
them — the app really re-renders;
|
|
31
30
|
- **highlight-on-hover** — hovering an element in the tree tints its rect
|
|
32
|
-
in the
|
|
31
|
+
in the window;
|
|
33
32
|
- **"highlight updates when components render"** — the rects that just
|
|
34
|
-
re-rendered are outlined
|
|
35
|
-
render through amber for one that keeps re-rendering), fading out
|
|
36
|
-
backend's clock;
|
|
33
|
+
re-rendered are outlined in DevTools' own colour ramp (teal for a first
|
|
34
|
+
render through amber for one that keeps re-rendering), fading out;
|
|
37
35
|
- the **element picker** — the crosshair in the DevTools toolbar. While it
|
|
38
36
|
is on, the pointer belongs to DevTools: motion tints whatever is under
|
|
39
37
|
it, a click selects that element in the tree, `Escape` gives up. The app
|
|
@@ -44,9 +42,8 @@ What you get:
|
|
|
44
42
|
"host components") to have something with a style to select;
|
|
45
43
|
- the Profiler's commit list and flamegraph, including **"reload and start
|
|
46
44
|
profiling"**, which re-execs the app with profiling already on so the
|
|
47
|
-
mount itself is recorded. **Not** its Timeline view, which
|
|
48
|
-
|
|
49
|
-
there is nothing to enable;
|
|
45
|
+
mount itself is recorded. **Not** its Timeline view, which this reconciler
|
|
46
|
+
build does not support;
|
|
50
47
|
- **DevTools' own settings** — component filters, console patching — kept
|
|
51
48
|
between runs, in `$XDG_CACHE_HOME/react-x11/devtools.json`
|
|
52
49
|
(`~/Library/Caches/react-x11/devtools.json` on macOS).
|
|
@@ -61,23 +58,20 @@ X app runs on a headless box). `REACT_X11_DEVTOOLS_STATE` moves the
|
|
|
61
58
|
settings file.
|
|
62
59
|
|
|
63
60
|
DevTools has no network panel — nothing in its protocol carries network
|
|
64
|
-
data
|
|
65
|
-
|
|
61
|
+
data. For that, `node --inspect` and `chrome://inspect` still work alongside
|
|
62
|
+
all of this.
|
|
66
63
|
|
|
67
64
|
## Opening the source from the DevTools panel
|
|
68
65
|
|
|
69
66
|
The inspected-element panel already shows where a component was written —
|
|
70
|
-
`file:///…/tasks.jsx:42:7`,
|
|
71
|
-
|
|
72
|
-
_clickable_ is a standalone-side setting, and it has two independent
|
|
73
|
-
routes:
|
|
67
|
+
`file:///…/tasks.jsx:42:7`, absolute and source-mapped. Making that line
|
|
68
|
+
_clickable_ is a standalone-side setting, with two independent routes:
|
|
74
69
|
|
|
75
70
|
- **Spawn an editor.** The standalone launches one itself, choosing it from
|
|
76
|
-
`REACT_EDITOR` (a full command line, shell-quoted), else — on macOS —
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
is the route to reach for:
|
|
71
|
+
`REACT_EDITOR` (a full command line, shell-quoted), else — on macOS — an
|
|
72
|
+
editor already running, else `VISUAL`, else `EDITOR`. It knows each
|
|
73
|
+
editor's argument style (vim's `+42`, sublime's and JetBrains' `file:42`),
|
|
74
|
+
so this is the route to reach for:
|
|
81
75
|
|
|
82
76
|
```sh
|
|
83
77
|
REACT_EDITOR=cursor npx react-devtools
|
|
@@ -85,158 +79,47 @@ routes:
|
|
|
85
79
|
|
|
86
80
|
- **Open a URL.** ⚙ → General → "Open local files directly in your code
|
|
87
81
|
editor", with the VS Code preset or a custom template using `{path}`,
|
|
88
|
-
`{line}` and `{column}`. The
|
|
89
|
-
|
|
90
|
-
own storage, not the app's.
|
|
82
|
+
`{line}` and `{column}`. The setting lives in the standalone's own
|
|
83
|
+
storage, not the app's.
|
|
91
84
|
|
|
92
85
|
Both are configured where the standalone runs, which may be a different
|
|
93
|
-
machine from the app
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
runs somewhere without your editor on it.
|
|
86
|
+
machine from the app; the app cannot inject either.
|
|
87
|
+
[Click-to-component](click-to-component.md) is the app-side answer to the same
|
|
88
|
+
question, and the one that works when DevTools runs somewhere without your
|
|
89
|
+
editor on it.
|
|
98
90
|
|
|
99
91
|
The same backend, minus the socket, powers `react-x11/test`'s component
|
|
100
92
|
inspection: `inspect()`/`setHook` in
|
|
101
|
-
[testing.md](testing.md#inspectnode-and-sethook)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
`REACT_X11_DEVTOOLS=1`, the two share one renderer registration (see the
|
|
105
|
-
guard in `connect()`).
|
|
106
|
-
|
|
107
|
-
## Watching the wire
|
|
108
|
-
|
|
109
|
-
The bridge is a plain WebSocket carrying text frames of `{"event": …,
|
|
110
|
-
"payload": …}` — no CDP, no binary framing. `scripts/devtools-proxy.mjs`
|
|
111
|
-
sits in the middle of it and prints what goes past, decoding the packed
|
|
112
|
-
`operations` arrays (the tree deltas) into readable lines:
|
|
113
|
-
|
|
114
|
-
```sh
|
|
115
|
-
npx react-devtools # terminal 1 — the real UI on :8097
|
|
116
|
-
npm run devtools:proxy # terminal 2 — :8098 -> :8097
|
|
117
|
-
REACT_X11_DEVTOOLS=1 REACT_X11_DEVTOOLS_PORT=8098 npm run examples:dashboard
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
```
|
|
121
|
-
0.008 ▲ app operations 193B
|
|
122
|
-
· renderer 1, root 1
|
|
123
|
-
· add root 1
|
|
124
|
-
· add 3 <Counter> (Function) under 2
|
|
125
|
-
0.291 ▼ devtools inspectElement {"id":3,"rendererID":1,…}
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
`--only`/`--skip` filter by event name, `--full` prints whole payloads, and
|
|
129
|
-
`--jsonl FILE` appends every frame for later analysis.
|
|
93
|
+
[testing.md](testing.md#inspectnode-and-sethook) run entirely in-process — no
|
|
94
|
+
standalone app, no `ws`, no env variable. A test run that also sets
|
|
95
|
+
`REACT_X11_DEVTOOLS=1` shares one renderer registration with them.
|
|
130
96
|
|
|
131
97
|
## How it works (and its sharp edges)
|
|
132
98
|
|
|
133
|
-
`
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
- **`injectIntoDevTools()` takes no arguments** in react-reconciler 0.34.
|
|
158
|
-
What it reports comes from the host config — `rendererPackageName`,
|
|
159
|
-
`rendererVersion`, `extraDevToolsConfig` — and an argument passed here is
|
|
160
|
-
ignored without a word, which is how react-x11 shipped for a while with
|
|
161
|
-
its renderer name and version quietly missing (#121). A test in
|
|
162
|
-
`test/smoke.test.js` asserts what reaches the hook, so the next
|
|
163
|
-
reconciler bump cannot repeat it.
|
|
164
|
-
- react-devtools-core v7 requires `initialize()` before
|
|
165
|
-
`connectToDevTools`, exposes its API on the **default export** under
|
|
166
|
-
node ESM interop, and expects browser-ish globals (`self`, `window`) —
|
|
167
|
-
all handled in `prepare()`.
|
|
168
|
-
- The Highlighter only emits `showNativeHighlight` for host instances that
|
|
169
|
-
implement `getClientRects()` returning a non-empty rect, and anything
|
|
170
|
-
with `getClientRects` is measured at mount through
|
|
171
|
-
`instance.ownerDocument.documentElement` — nodes therefore expose both
|
|
172
|
-
(see `Node.getClientRects` / the `ownerDocument` stub in
|
|
173
|
-
`src/nodes/`).
|
|
174
|
-
- Highlight events arrive on the backend agent
|
|
175
|
-
(`hook.reactDevtoolsAgent`, or the `'react-devtools'` hook event);
|
|
176
|
-
`attachHighlightAgent` maps the public instance to its owning window
|
|
177
|
-
node and paints a translucent overlay.
|
|
178
|
-
- **What makes the native paths run at all** is
|
|
179
|
-
`isReactNativeEnvironment()`, which the backend defines as
|
|
180
|
-
`window.document == null`. That is true for a node process with
|
|
181
|
-
`window = global`, so the backend takes React Native's route everywhere:
|
|
182
|
-
it _asks the host_ to draw the highlight and the update outlines, and to
|
|
183
|
-
drive the picker, instead of drawing into a DOM overlay of its own. Every
|
|
184
|
-
injection below is one of those asks.
|
|
185
|
-
- **Update outlines**: the backend counts updates, picks each rect's colour
|
|
186
|
-
and expires it on its own clock, then emits `drawTraceUpdates`
|
|
187
|
-
(`[{node, color}]` — the whole live set, every time) and
|
|
188
|
-
`disableTraceUpdates`. `attachTraceUpdatesAgent` groups them by window
|
|
189
|
-
and hands each root the rects; `WindowNode.setTraceUpdates` is a dumb
|
|
190
|
-
overlay that replaces rather than accumulates. It schedules those redraws
|
|
191
|
-
on `requestAnimationFrame`, which node does not have — `prepare()`
|
|
192
|
-
installs an unref'd `setTimeout` shim, and without it the first traced
|
|
193
|
-
commit throws inside the backend.
|
|
194
|
-
- **The picker**: with no `window.addEventListener` to install, the backend
|
|
195
|
-
emits `startInspectingNative` and waits. `attachPickerAgent` takes the
|
|
196
|
-
pointer through `setInspectHandler` (events.js) — motion, press and
|
|
197
|
-
release are answered and go no further — and calls `agent.selectNode()`
|
|
198
|
-
then `agent.stopInspectingNative(true)`. Cancelling from the DevTools
|
|
199
|
-
side arrives as a bridge message with no host-facing event, so the
|
|
200
|
-
picker also listens on `agent._bridge` directly; without that a
|
|
201
|
-
cancelled picker would keep swallowing the app's input.
|
|
202
|
-
- **The style editor** needs three things and is offered only if it gets
|
|
203
|
-
them: `resolveRNStyle` (our `flattenStyle`, minus state blocks, which are
|
|
204
|
-
not editable values), `nativeStyleEditorValidAttributes`
|
|
205
|
-
(`STYLE_PROP_NAMES`), and `instance.measure(cb)` on host instances for
|
|
206
|
-
the box model — RN's contract, implemented by `Node.measure`. Edits
|
|
207
|
-
arrive as `overrideValueAtPath` on `['style']` with the value wrapped in
|
|
208
|
-
an array, which works here only because a react-x11 `style` prop already
|
|
209
|
-
takes an array.
|
|
210
|
-
- **Reload and profile** is gated on a backend check that asks whether
|
|
211
|
-
synchronous XHR works, so `isReloadAndProfileSupported: true` is passed
|
|
212
|
-
explicitly. Registering a renderer does not start profiling, either — the
|
|
213
|
-
run that comes back from the restart starts it itself, before the first
|
|
214
|
-
commit, which is the only reason to restart at all.
|
|
215
|
-
- `localStorage`/`sessionStorage` are **defined** on the global rather than
|
|
216
|
-
assigned: reading `global.localStorage` first is what makes node print
|
|
217
|
-
its `--localstorage-file` warning on every DevTools run.
|
|
218
|
-
- **Hook names and sources need a deeper stack than V8 keeps.** React reads
|
|
219
|
-
each hook's location — and the custom-hook nesting the names come from —
|
|
220
|
-
off a stack captured at the hook dispatch, and `Error.stackTraceLimit` is
|
|
221
|
-
10 by default. A loader leaves frames of its own between the hook and its
|
|
222
|
-
call site (`tsx`, which every `npm run examples:*` goes through, costs
|
|
223
|
-
about ten), so the identifying frames fall off the end: `hookSource`
|
|
224
|
-
comes back `{fileName: null, lineNumber: null, …}`, the frontend logs
|
|
225
|
-
"Hook source code location not found", and the element shows its hooks
|
|
226
|
-
with no names and no source lines (#514). `prepare()` raises the limit to
|
|
227
|
-
50 when the bridge is enabled, and only upwards, so an app that asked for
|
|
228
|
-
more keeps it. `test/devtools-hooks.test.js` squeezes the budget and
|
|
229
|
-
asserts the names and sources still come back over the bridge.
|
|
230
|
-
- **Selecting a component with hooks can blank the DevTools window.** That
|
|
231
|
-
is the standalone app's own renderer process aborting, upstream of
|
|
232
|
-
anything the host sends: it happens with every hook source complete, and
|
|
233
|
-
under runtimes with no loader at all. Turning ⚙ → Components → "Always
|
|
234
|
-
parse hook names for the selected element" off makes it intermittent
|
|
235
|
-
rather than reliable; restarting `npx react-devtools` reconnects to the
|
|
236
|
-
app, which is unaffected.
|
|
237
|
-
- `test/devtools.test.js` drives the real backend over a socket for all of
|
|
238
|
-
the above; the fake-agent tests in `test/smoke.test.js` prove the drawing
|
|
239
|
-
but not that the backend still asks for it.
|
|
99
|
+
The bridge is installed by `createRoot()` when `REACT_X11_DEVTOOLS` is set (by
|
|
100
|
+
`react-x11 dev`, earlier, before React Refresh loads). Its socket is `ws` from
|
|
101
|
+
`react-devtools-core`'s own dependencies, so `ws` is not a separate install.
|
|
102
|
+
What an app can notice while it is on:
|
|
103
|
+
|
|
104
|
+
- **It does not keep the process alive.** The backend's retry timer and socket
|
|
105
|
+
are unref'd, so the process still exits when the app's last window closes;
|
|
106
|
+
the app's own `setTimeout` and `WebSocket` are untouched.
|
|
107
|
+
- **Browser-ish globals appear.** `self` and `window` are set to the global
|
|
108
|
+
where absent, `requestAnimationFrame`/`cancelAnimationFrame` are shimmed
|
|
109
|
+
where absent, and `localStorage`/`sessionStorage` are defined (the store
|
|
110
|
+
behind DevTools' settings file).
|
|
111
|
+
- **`Error.stackTraceLimit` is raised to 50** (never lowered), because React
|
|
112
|
+
reads hook names and sources off a stack captured at each hook call and a
|
|
113
|
+
loader such as `tsx` eats the default 10 frames. Without it, hooks show with
|
|
114
|
+
no names and no source lines.
|
|
115
|
+
- **Selecting a component with hooks can blank the DevTools window.** That is
|
|
116
|
+
the standalone app's own renderer process aborting, upstream of anything the
|
|
117
|
+
app sends. Turning ⚙ → Components → "Always parse hook names for the
|
|
118
|
+
selected element" off makes it intermittent rather than reliable;
|
|
119
|
+
restarting `npx react-devtools` reconnects to the app, which is unaffected.
|
|
120
|
+
|
|
121
|
+
Design notes and maintainer notes:
|
|
122
|
+
[design/devtools.md](../design/devtools.md#how-it-works-and-its-sharp-edges).
|
|
240
123
|
|
|
241
124
|
## Other debugging aids
|
|
242
125
|
|
|
@@ -245,6 +128,6 @@ Notes for maintainers:
|
|
|
245
128
|
- Refs: drawn elements expose the retained node (`abs` rect, `scrollTo`,
|
|
246
129
|
…); `<window>`/`<popup>` expose the live ntk window (`getContext('2d')`,
|
|
247
130
|
`queryTree`, `setCursor`, …).
|
|
248
|
-
- The in-process X server (`
|
|
249
|
-
pixels back
|
|
250
|
-
|
|
131
|
+
- The in-process X server (node-x11's `lib/xserver`) renders headlessly and
|
|
132
|
+
reads pixels back; `react-x11/test` is built on it
|
|
133
|
+
([testing.md](testing.md#pixels)).
|