@ccheever/exact-renderer 0.1.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/package.json +118 -0
- package/src/__tests__/adapter-window-state.test.tsx +190 -0
- package/src/__tests__/attrs.test.ts +157 -0
- package/src/__tests__/classname.test.ts +332 -0
- package/src/__tests__/color.test.ts +169 -0
- package/src/__tests__/dom-mirror.test.ts +682 -0
- package/src/__tests__/dom-shim.test.ts +274 -0
- package/src/__tests__/fixtures/SvelteCounter.svelte +7 -0
- package/src/__tests__/fixtures/SvelteInput.svelte +8 -0
- package/src/__tests__/host-config.test.ts +51 -0
- package/src/__tests__/host-ops.test.ts +2234 -0
- package/src/__tests__/image-source.test.ts +135 -0
- package/src/__tests__/liquid-glass.test.ts +72 -0
- package/src/__tests__/multi-root.test.ts +118 -0
- package/src/__tests__/native-view-events.test.ts +102 -0
- package/src/__tests__/nodes.test.ts +399 -0
- package/src/__tests__/normalize.test.ts +576 -0
- package/src/__tests__/paragraph-lowering.test.tsx +144 -0
- package/src/__tests__/props.test.ts +518 -0
- package/src/__tests__/protocol-encoder.test.ts +732 -0
- package/src/__tests__/protocol-fixture-bytes.test.ts +41 -0
- package/src/__tests__/reconciler.test.tsx +241 -0
- package/src/__tests__/svelte-adapter.test.ts +166 -0
- package/src/__tests__/svg-source.test.ts +71 -0
- package/src/__tests__/tags.test.ts +354 -0
- package/src/__tests__/toggle.test.ts +441 -0
- package/src/__tests__/transitions.test.ts +106 -0
- package/src/__tests__/web-primitives.test.tsx +454 -0
- package/src/__tests__/window-hooks.test.tsx +447 -0
- package/src/adapter-contract.ts +68 -0
- package/src/attrs.ts +596 -0
- package/src/classname-contract.ts +87 -0
- package/src/classname-resolve.ts +553 -0
- package/src/classname-runtime.ts +29 -0
- package/src/components.ts +214 -0
- package/src/css-variable-context.ts +83 -0
- package/src/dom-hydration.ts +160 -0
- package/src/dom-mirror.ts +1459 -0
- package/src/dom-shim.ts +1736 -0
- package/src/group-context.ts +69 -0
- package/src/host-config.ts +431 -0
- package/src/host-ops.ts +3167 -0
- package/src/image-source.native.ts +703 -0
- package/src/image-source.ts +554 -0
- package/src/index.ts +278 -0
- package/src/inspector-runtime.ts +244 -0
- package/src/inspector.ts +3570 -0
- package/src/jsx-augmentations.ts +54 -0
- package/src/keyboard-avoidance.ts +217 -0
- package/src/native-primitives.ts +43 -0
- package/src/native-view-events.ts +322 -0
- package/src/native-view.ts +60 -0
- package/src/nodes/index.ts +41 -0
- package/src/nodes/node.ts +531 -0
- package/src/peer-context.ts +100 -0
- package/src/primitives.native.ts +8 -0
- package/src/primitives.ts +8 -0
- package/src/props/index.ts +14 -0
- package/src/props/normalize.ts +816 -0
- package/src/protocol/encoder.ts +940 -0
- package/src/protocol/index.ts +33 -0
- package/src/reconciler.ts +581 -0
- package/src/runtime.ts +11 -0
- package/src/safe-area.ts +543 -0
- package/src/solid.ts +490 -0
- package/src/style/color.js +1 -0
- package/src/style/color.ts +15 -0
- package/src/style/index.js +1 -0
- package/src/style/index.ts +22 -0
- package/src/style/normalize.js +1 -0
- package/src/style/normalize.ts +1426 -0
- package/src/svelte.ts +349 -0
- package/src/svg-source.ts +222 -0
- package/src/tags/index.ts +21 -0
- package/src/tags/tag-map.ts +289 -0
- package/src/text/paragraph-lowering.ts +310 -0
- package/src/types.ts +1175 -0
- package/src/vue.ts +535 -0
- package/src/web-host.ts +19 -0
- package/src/web-primitives.ts +1654 -0
package/src/index.ts
ADDED
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
// @system @ref LLP 0007 — Renderer-facing behavior primitives
|
|
2
|
+
/**
|
|
3
|
+
* Exact Renderer
|
|
4
|
+
*
|
|
5
|
+
* Main entry point for the Exact React renderer.
|
|
6
|
+
*
|
|
7
|
+
* This module provides:
|
|
8
|
+
* - render/unmount functions for mounting React trees
|
|
9
|
+
* - Primitive components (web-style and RN-style)
|
|
10
|
+
* - Type definitions for props and styles
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* import React from 'react';
|
|
15
|
+
* import { render, View, Text, Pressable } from '@exact/runtime';
|
|
16
|
+
*
|
|
17
|
+
* function App() {
|
|
18
|
+
* const [count, setCount] = React.useState(0);
|
|
19
|
+
*
|
|
20
|
+
* return (
|
|
21
|
+
* <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
|
|
22
|
+
* <Text style={{ fontSize: 24 }}>Count: {count}</Text>
|
|
23
|
+
* <Pressable
|
|
24
|
+
* style={{ padding: 16, backgroundColor: '#007AFF', borderRadius: 8 }}
|
|
25
|
+
* onPress={() => setCount(c => c + 1)}
|
|
26
|
+
* >
|
|
27
|
+
* <Text style={{ color: '#fff' }}>Increment</Text>
|
|
28
|
+
* </Pressable>
|
|
29
|
+
* </View>
|
|
30
|
+
* );
|
|
31
|
+
* }
|
|
32
|
+
*
|
|
33
|
+
* render(<App />);
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
import './jsx-augmentations.js';
|
|
38
|
+
|
|
39
|
+
// =============================================================================
|
|
40
|
+
// Render Functions
|
|
41
|
+
// =============================================================================
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
render,
|
|
45
|
+
unmount,
|
|
46
|
+
forceUpdate,
|
|
47
|
+
syncWindowState,
|
|
48
|
+
reset,
|
|
49
|
+
createExactRoot,
|
|
50
|
+
prepareForBundleReplacement,
|
|
51
|
+
} from './reconciler.js';
|
|
52
|
+
export type { ExactRoot } from './reconciler.js';
|
|
53
|
+
// Keep the root barrel native-safe. Optional DOM/framework adapters belong on
|
|
54
|
+
// explicit subpaths so native startup does not eagerly import them.
|
|
55
|
+
export type { ExactDOMHandle } from './dom-shim.js';
|
|
56
|
+
|
|
57
|
+
// =============================================================================
|
|
58
|
+
// Web-Style Components
|
|
59
|
+
// =============================================================================
|
|
60
|
+
|
|
61
|
+
export {
|
|
62
|
+
div,
|
|
63
|
+
span,
|
|
64
|
+
text,
|
|
65
|
+
img,
|
|
66
|
+
input,
|
|
67
|
+
button,
|
|
68
|
+
toggle,
|
|
69
|
+
} from './components.js';
|
|
70
|
+
|
|
71
|
+
// =============================================================================
|
|
72
|
+
// React Native-Style Components
|
|
73
|
+
// =============================================================================
|
|
74
|
+
|
|
75
|
+
export {
|
|
76
|
+
View,
|
|
77
|
+
Text,
|
|
78
|
+
Image,
|
|
79
|
+
Svg,
|
|
80
|
+
SelectionGroup,
|
|
81
|
+
List,
|
|
82
|
+
ScrollView,
|
|
83
|
+
TextInput,
|
|
84
|
+
Pressable,
|
|
85
|
+
Toggle,
|
|
86
|
+
Switch,
|
|
87
|
+
} from './components.js';
|
|
88
|
+
export {
|
|
89
|
+
createNativeViewComponent,
|
|
90
|
+
} from './native-view.js';
|
|
91
|
+
|
|
92
|
+
// =============================================================================
|
|
93
|
+
// Style Types
|
|
94
|
+
// =============================================================================
|
|
95
|
+
|
|
96
|
+
export type {
|
|
97
|
+
// Style types
|
|
98
|
+
ViewStyle,
|
|
99
|
+
FullStyle,
|
|
100
|
+
FlexStyle,
|
|
101
|
+
LayoutStyle,
|
|
102
|
+
SpacingStyle,
|
|
103
|
+
PositionStyle,
|
|
104
|
+
AppearanceStyle,
|
|
105
|
+
TransformStyle,
|
|
106
|
+
TransitionStyle,
|
|
107
|
+
TextStyle,
|
|
108
|
+
TransitionPropertyName,
|
|
109
|
+
TransitionPhase,
|
|
110
|
+
TransitionEasingName,
|
|
111
|
+
CubicBezierEasing,
|
|
112
|
+
TransitionEasing,
|
|
113
|
+
TimingTransition,
|
|
114
|
+
SpringTransition,
|
|
115
|
+
NoneTransition,
|
|
116
|
+
TransitionConfig,
|
|
117
|
+
TransitionMap,
|
|
118
|
+
StyleTransition,
|
|
119
|
+
|
|
120
|
+
// Dimension types
|
|
121
|
+
DimensionValue,
|
|
122
|
+
DimensionInput,
|
|
123
|
+
|
|
124
|
+
// Flexbox types
|
|
125
|
+
FlexDirection,
|
|
126
|
+
FlexWrap,
|
|
127
|
+
JustifyContent,
|
|
128
|
+
AlignItems,
|
|
129
|
+
AlignSelf,
|
|
130
|
+
AlignContent,
|
|
131
|
+
|
|
132
|
+
// Other types
|
|
133
|
+
PositionType,
|
|
134
|
+
Overflow,
|
|
135
|
+
Display,
|
|
136
|
+
SafeAreaEdge,
|
|
137
|
+
SafeAreaEdgeMode,
|
|
138
|
+
SafeAreaInsetProp,
|
|
139
|
+
SafeAreaProp,
|
|
140
|
+
SafeAreaRegionSet,
|
|
141
|
+
FontWeight,
|
|
142
|
+
FontStyle,
|
|
143
|
+
TextAlign,
|
|
144
|
+
EllipsizeMode,
|
|
145
|
+
SelectableMode,
|
|
146
|
+
NativeViewSelectionTier,
|
|
147
|
+
NativeViewSelectionGesturePolicy,
|
|
148
|
+
ResizeMode,
|
|
149
|
+
ImageColorScheme,
|
|
150
|
+
ImageCandidate,
|
|
151
|
+
ImageThemeTreatment,
|
|
152
|
+
ColorSchemeImageSource,
|
|
153
|
+
ImagePlaceholder,
|
|
154
|
+
ImageLoading,
|
|
155
|
+
ImageObjectFit,
|
|
156
|
+
ImageSource,
|
|
157
|
+
SvgSource,
|
|
158
|
+
} from './types.js';
|
|
159
|
+
|
|
160
|
+
// =============================================================================
|
|
161
|
+
// Component Prop Types
|
|
162
|
+
// =============================================================================
|
|
163
|
+
|
|
164
|
+
export type {
|
|
165
|
+
// Base props
|
|
166
|
+
BaseProps,
|
|
167
|
+
ContainerProps,
|
|
168
|
+
TextElementProps,
|
|
169
|
+
ImageElementProps,
|
|
170
|
+
RNImageProps,
|
|
171
|
+
SvgProps,
|
|
172
|
+
PressableElementProps,
|
|
173
|
+
ScrollContainerProps,
|
|
174
|
+
TextInputProps,
|
|
175
|
+
ToggleProps,
|
|
176
|
+
|
|
177
|
+
// Event types
|
|
178
|
+
PressEvent,
|
|
179
|
+
ScrollEvent,
|
|
180
|
+
ChangeEvent,
|
|
181
|
+
ToggleChangeEvent,
|
|
182
|
+
TransitionEndEvent,
|
|
183
|
+
} from './types.js';
|
|
184
|
+
|
|
185
|
+
// =============================================================================
|
|
186
|
+
// Internal/Advanced Exports
|
|
187
|
+
// =============================================================================
|
|
188
|
+
//
|
|
189
|
+
// These exports are intended for advanced usage, testing, or building custom
|
|
190
|
+
// renderers. They are not part of the stable public API and may change.
|
|
191
|
+
//
|
|
192
|
+
// =============================================================================
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Internal types for custom renderer implementations.
|
|
196
|
+
* @internal
|
|
197
|
+
*/
|
|
198
|
+
export type {
|
|
199
|
+
RGBAColor,
|
|
200
|
+
CanonicalStyle,
|
|
201
|
+
CanonicalProps,
|
|
202
|
+
CanonicalTagType,
|
|
203
|
+
WebTagType,
|
|
204
|
+
RNTagType,
|
|
205
|
+
TagType,
|
|
206
|
+
} from './types.js';
|
|
207
|
+
export type {
|
|
208
|
+
NativeViewComponentProps,
|
|
209
|
+
NativeViewRuntimeDef,
|
|
210
|
+
NativeViewSelectionDef,
|
|
211
|
+
} from './native-view.js';
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Style utilities for parsing and normalizing styles.
|
|
215
|
+
* @internal
|
|
216
|
+
*/
|
|
217
|
+
export { parseColor, isValidColor, colorToHex, colorToRgba } from './style/index.js';
|
|
218
|
+
export {
|
|
219
|
+
normalizeStyle,
|
|
220
|
+
normalizeTransition,
|
|
221
|
+
stylesEqual,
|
|
222
|
+
transitionsEqual,
|
|
223
|
+
parseDimension,
|
|
224
|
+
parseFontWeight,
|
|
225
|
+
} from './style/index.js';
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Props utilities for normalizing component props.
|
|
229
|
+
* @internal
|
|
230
|
+
*/
|
|
231
|
+
export { normalizeProps, propsEqual, extractTextContent } from './props/index.js';
|
|
232
|
+
|
|
233
|
+
export {
|
|
234
|
+
CSSVariableProvider,
|
|
235
|
+
useCSSVariables,
|
|
236
|
+
extractCSSVariables,
|
|
237
|
+
} from './css-variable-context.js';
|
|
238
|
+
export type { CSSVariableMap } from './css-variable-context.js';
|
|
239
|
+
|
|
240
|
+
export {
|
|
241
|
+
GroupStateProvider,
|
|
242
|
+
useGroupStates,
|
|
243
|
+
extractGroupName,
|
|
244
|
+
} from './group-context.js';
|
|
245
|
+
|
|
246
|
+
export {
|
|
247
|
+
createPeerStore,
|
|
248
|
+
usePeerStore,
|
|
249
|
+
usePeerState,
|
|
250
|
+
extractPeerName,
|
|
251
|
+
} from './peer-context.js';
|
|
252
|
+
export type { PeerStore } from './peer-context.js';
|
|
253
|
+
export type {
|
|
254
|
+
ExactAdapterHostOps,
|
|
255
|
+
ExactAdapterOps,
|
|
256
|
+
ExactAdapterRoot,
|
|
257
|
+
} from './adapter-contract.js';
|
|
258
|
+
export type { ExactSvelteRoot } from './svelte.js';
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Tag configuration utilities.
|
|
262
|
+
* @internal
|
|
263
|
+
*/
|
|
264
|
+
export { getTagConfig, isValidTag, isWebTag, isRNTag } from './tags/index.js';
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Internal debugging utilities.
|
|
268
|
+
* These are prefixed with underscore and should not be used in production code.
|
|
269
|
+
* @internal
|
|
270
|
+
*/
|
|
271
|
+
export {
|
|
272
|
+
_getRootContainer,
|
|
273
|
+
_isRendering,
|
|
274
|
+
_getEventQueueLength,
|
|
275
|
+
} from './reconciler.js';
|
|
276
|
+
|
|
277
|
+
export { _getEncoder, _clearHandlers, getHandler } from './host-config.js';
|
|
278
|
+
export { NodeKind, _resetNodeIdCounter } from './nodes/index.js';
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AgentEvent,
|
|
3
|
+
ElementRef,
|
|
4
|
+
ElementRefInfo,
|
|
5
|
+
Frame,
|
|
6
|
+
Point,
|
|
7
|
+
RootInfo,
|
|
8
|
+
ViewNode,
|
|
9
|
+
} from '@exact/core/agent/types';
|
|
10
|
+
import {
|
|
11
|
+
recordCommitTimestamp,
|
|
12
|
+
resetAgentInteractionStateTracking,
|
|
13
|
+
} from '@exact/core/agent/interaction-state';
|
|
14
|
+
|
|
15
|
+
import type { ElementNode, HostNode, RootNode } from './nodes/node.js';
|
|
16
|
+
import { NodeKind } from './nodes/node.js';
|
|
17
|
+
import { getScreenDimensions } from './protocol/index.js';
|
|
18
|
+
|
|
19
|
+
type InspectorListener = (event: AgentEvent) => void;
|
|
20
|
+
type CommitAnalyzer = (root: RootNode) => void;
|
|
21
|
+
type ResetHook = () => void;
|
|
22
|
+
|
|
23
|
+
interface SnapshotRecord {
|
|
24
|
+
snapshotId: string;
|
|
25
|
+
rootId: number;
|
|
26
|
+
stateVersion: number;
|
|
27
|
+
timestamp: number;
|
|
28
|
+
frameCount: number;
|
|
29
|
+
refs: Record<ElementRef, ElementRefInfo>;
|
|
30
|
+
tree?: ViewNode;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface SharedInspectorState {
|
|
34
|
+
roots: Map<number, RootNode>;
|
|
35
|
+
listeners: Set<InspectorListener>;
|
|
36
|
+
snapshots: Map<string, SnapshotRecord>;
|
|
37
|
+
snapshotOrder: string[];
|
|
38
|
+
textOverrides: Map<number, string>;
|
|
39
|
+
toggleOverrides: Map<number, boolean>;
|
|
40
|
+
valueOverrides: Map<number, unknown>;
|
|
41
|
+
scrollOffsets: Map<number, Point>;
|
|
42
|
+
snapshotCounter: number;
|
|
43
|
+
stateVersion: number;
|
|
44
|
+
frameCount: number;
|
|
45
|
+
lastCommitAt: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
type InspectorGlobal = typeof globalThis & {
|
|
49
|
+
__exactRendererInspectorState?: SharedInspectorState;
|
|
50
|
+
__exactRendererCommitAnalyzers?: Set<CommitAnalyzer>;
|
|
51
|
+
__exactRendererInspectorResetHooks?: Set<ResetHook>;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
function inspectorGlobal(): InspectorGlobal {
|
|
55
|
+
return globalThis as InspectorGlobal;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function getSharedInspectorState(): SharedInspectorState {
|
|
59
|
+
const scope = inspectorGlobal();
|
|
60
|
+
if (scope.__exactRendererInspectorState) {
|
|
61
|
+
return scope.__exactRendererInspectorState;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const state: SharedInspectorState = {
|
|
65
|
+
roots: new Map<number, RootNode>(),
|
|
66
|
+
listeners: new Set<InspectorListener>(),
|
|
67
|
+
snapshots: new Map<string, SnapshotRecord>(),
|
|
68
|
+
snapshotOrder: [],
|
|
69
|
+
textOverrides: new Map<number, string>(),
|
|
70
|
+
toggleOverrides: new Map<number, boolean>(),
|
|
71
|
+
valueOverrides: new Map<number, unknown>(),
|
|
72
|
+
scrollOffsets: new Map<number, Point>(),
|
|
73
|
+
snapshotCounter: 0,
|
|
74
|
+
stateVersion: 0,
|
|
75
|
+
frameCount: 0,
|
|
76
|
+
lastCommitAt: 0,
|
|
77
|
+
};
|
|
78
|
+
scope.__exactRendererInspectorState = state;
|
|
79
|
+
return state;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const sharedState = getSharedInspectorState();
|
|
83
|
+
const roots = sharedState.roots;
|
|
84
|
+
const listeners = sharedState.listeners;
|
|
85
|
+
const snapshots = sharedState.snapshots;
|
|
86
|
+
const snapshotOrder = sharedState.snapshotOrder;
|
|
87
|
+
const textOverrides = sharedState.textOverrides;
|
|
88
|
+
const toggleOverrides = sharedState.toggleOverrides;
|
|
89
|
+
const valueOverrides = sharedState.valueOverrides;
|
|
90
|
+
const scrollOffsets = sharedState.scrollOffsets;
|
|
91
|
+
|
|
92
|
+
function currentTimestamp(): number {
|
|
93
|
+
return Date.now();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function makeRootInfo(root: RootNode): RootInfo {
|
|
97
|
+
const { width, height } = getScreenDimensions(root.rootId);
|
|
98
|
+
return {
|
|
99
|
+
rootId: root.rootId,
|
|
100
|
+
label: root.rootId === 0 ? 'Main' : `Root ${root.rootId}`,
|
|
101
|
+
size: {
|
|
102
|
+
width,
|
|
103
|
+
height,
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function emit(event: AgentEvent): void {
|
|
109
|
+
for (const listener of listeners) {
|
|
110
|
+
try {
|
|
111
|
+
listener(event);
|
|
112
|
+
} catch (error) {
|
|
113
|
+
console.error('[RendererInspector] listener failed:', error);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function collectChangedViews(root: RootNode): number[] {
|
|
119
|
+
const collected: number[] = [];
|
|
120
|
+
const collect = (node: HostNode): void => {
|
|
121
|
+
collected.push(node.id);
|
|
122
|
+
if (node.kind === NodeKind.Element || node.kind === NodeKind.Root) {
|
|
123
|
+
for (const child of node.children) {
|
|
124
|
+
collect(child);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
collect(root);
|
|
130
|
+
return collected;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function commitAnalyzers(): Set<CommitAnalyzer> {
|
|
134
|
+
const scope = inspectorGlobal();
|
|
135
|
+
if (!scope.__exactRendererCommitAnalyzers) {
|
|
136
|
+
scope.__exactRendererCommitAnalyzers = new Set<CommitAnalyzer>();
|
|
137
|
+
}
|
|
138
|
+
return scope.__exactRendererCommitAnalyzers;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function resetHooks(): Set<ResetHook> {
|
|
142
|
+
const scope = inspectorGlobal();
|
|
143
|
+
if (!scope.__exactRendererInspectorResetHooks) {
|
|
144
|
+
scope.__exactRendererInspectorResetHooks = new Set<ResetHook>();
|
|
145
|
+
}
|
|
146
|
+
return scope.__exactRendererInspectorResetHooks;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function registerInspectorCommitAnalyzer(analyzer: CommitAnalyzer): () => void {
|
|
150
|
+
const analyzers = commitAnalyzers();
|
|
151
|
+
analyzers.add(analyzer);
|
|
152
|
+
return () => {
|
|
153
|
+
analyzers.delete(analyzer);
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function registerInspectorResetHook(hook: ResetHook): () => void {
|
|
158
|
+
const hooks = resetHooks();
|
|
159
|
+
hooks.add(hook);
|
|
160
|
+
return () => {
|
|
161
|
+
hooks.delete(hook);
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function registerRoot(root: RootNode): void {
|
|
166
|
+
roots.set(root.rootId, root);
|
|
167
|
+
sharedState.stateVersion += 1;
|
|
168
|
+
const rootInfo = makeRootInfo(root);
|
|
169
|
+
emit({
|
|
170
|
+
type: 'connect',
|
|
171
|
+
rootId: root.rootId,
|
|
172
|
+
label: rootInfo.label,
|
|
173
|
+
size: rootInfo.size,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function unregisterRoot(rootId: number): void {
|
|
178
|
+
if (!roots.delete(rootId)) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
sharedState.stateVersion += 1;
|
|
182
|
+
emit({
|
|
183
|
+
type: 'disconnect',
|
|
184
|
+
reason: `root:${rootId}:unregistered`,
|
|
185
|
+
exitCode: null,
|
|
186
|
+
signal: null,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export function notifyCommit(
|
|
191
|
+
root: RootNode,
|
|
192
|
+
options: {
|
|
193
|
+
changedViews?: Iterable<number>;
|
|
194
|
+
analyzeWarnings?: boolean;
|
|
195
|
+
} = {},
|
|
196
|
+
): void {
|
|
197
|
+
roots.set(root.rootId, root);
|
|
198
|
+
sharedState.frameCount += 1;
|
|
199
|
+
sharedState.stateVersion += 1;
|
|
200
|
+
sharedState.lastCommitAt = currentTimestamp();
|
|
201
|
+
recordCommitTimestamp(sharedState.lastCommitAt);
|
|
202
|
+
|
|
203
|
+
if (options.analyzeWarnings !== false) {
|
|
204
|
+
for (const analyzer of commitAnalyzers()) {
|
|
205
|
+
analyzer(root);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (listeners.size === 0) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
emit({
|
|
214
|
+
type: 'render',
|
|
215
|
+
frameCount: sharedState.frameCount,
|
|
216
|
+
changedViews:
|
|
217
|
+
options.changedViews !== undefined
|
|
218
|
+
? Array.from(options.changedViews)
|
|
219
|
+
: collectChangedViews(root),
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function _resetInspectorState(): void {
|
|
224
|
+
roots.clear();
|
|
225
|
+
listeners.clear();
|
|
226
|
+
snapshots.clear();
|
|
227
|
+
snapshotOrder.length = 0;
|
|
228
|
+
resetAgentInteractionStateTracking();
|
|
229
|
+
for (const hook of resetHooks()) {
|
|
230
|
+
try {
|
|
231
|
+
hook();
|
|
232
|
+
} catch (error) {
|
|
233
|
+
console.error('[RendererInspector] reset hook failed:', error);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
textOverrides.clear();
|
|
237
|
+
toggleOverrides.clear();
|
|
238
|
+
valueOverrides.clear();
|
|
239
|
+
scrollOffsets.clear();
|
|
240
|
+
sharedState.snapshotCounter = 0;
|
|
241
|
+
sharedState.stateVersion = 0;
|
|
242
|
+
sharedState.frameCount = 0;
|
|
243
|
+
sharedState.lastCommitAt = 0;
|
|
244
|
+
}
|