Skip to content

Commit f016bda

Browse files
committed
Refactor the walker to take an element interface object
1 parent 6170f49 commit f016bda

9 files changed

Lines changed: 476 additions & 358 deletions

File tree

packages/debugger/src/locator/index.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {createKeyHold} from '@solid-primitives/keyboard'
55
import {scheduleIdle} from '@solid-primitives/scheduled'
66
import {makeHoverElementListener} from '@solid-devtools/shared/primitives'
77
import {msg, warn} from '@solid-devtools/shared/utils'
8-
import * as registry from '../main/component-registry.ts'
8+
import * as walker from '../structure/walker.ts'
99
import {ObjectType, getObjectById} from '../main/id.ts'
1010
import SolidAPI from '../main/setup.ts'
1111
import {type NodeID, type OutputEmit} from '../main/types.ts'
@@ -27,11 +27,12 @@ export {parseLocationString} from './find-components.ts'
2727

2828
export * from './types.ts'
2929

30-
export function createLocator(props: {
31-
locatorEnabled: s.Accessor<boolean>
32-
setLocatorEnabledSignal(signal: s.Accessor<boolean>): void
33-
onComponentClick(componentId: NodeID, next: VoidFunction): void
34-
emit: OutputEmit
30+
export function createLocator<TEl extends object>(props: {
31+
locatorEnabled: s.Accessor<boolean>,
32+
setLocatorEnabledSignal(signal: s.Accessor<boolean>): void,
33+
onComponentClick(componentId: NodeID, next: VoidFunction): void,
34+
emit: OutputEmit,
35+
component_registry: walker.ComponentRegistry<TEl>,
3536
}) {
3637
const [enabledByPressingSignal, setEnabledByPressingSignal] = s.createSignal((): boolean => false)
3738
props.setLocatorEnabledSignal(s.createMemo(() => enabledByPressingSignal()()))
@@ -55,7 +56,7 @@ export function createLocator(props: {
5556

5657
// target is an element
5758
if (target instanceof HTMLElement) {
58-
const comp = registry.findComponent(target)
59+
const comp = walker.findComponent(props.component_registry, target)
5960
if (!comp) return []
6061
return [
6162
{
@@ -68,7 +69,7 @@ export function createLocator(props: {
6869
}
6970

7071
// target is a component or an element of a component (in DOM walker mode)
71-
const comp = registry.getComponent(target.id)
72+
const comp = walker.getComponent(props.component_registry, target.id)
7273
if (!comp) return []
7374
return comp.elements.map(element => ({
7475
element,
@@ -91,7 +92,7 @@ export function createLocator(props: {
9192
// notify of component hovered by using the debugger
9293
s.createEffect((prev: NodeID | undefined) => {
9394
const target = hoverTarget()
94-
const comp = target && registry.findComponent(target)
95+
const comp = target && walker.findComponent(props.component_registry, target)
9596
if (prev) {
9697
props.emit(msg('HoveredComponent', {nodeId: prev, state: false}))
9798
}

packages/debugger/src/main/component-registry.ts

Lines changed: 0 additions & 147 deletions
This file was deleted.

packages/debugger/src/main/id.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const enum ObjectType {
1111

1212
type ValueMap = {
1313
[ObjectType.Owner]: Solid.Owner
14-
[ObjectType.Element]: Element
14+
[ObjectType.Element]: object
1515
[ObjectType.Signal]: Solid.Signal
1616
[ObjectType.Store]: Solid.Store
1717
[ObjectType.StoreNode]: Solid.StoreNode

packages/debugger/src/main/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {createDependencyGraph} from '../dependency/index.ts'
66
import {createInspector} from '../inspector/index.ts'
77
import {createLocator} from '../locator/index.ts'
88
import {createStructure} from '../structure/index.ts'
9+
import * as walker from '../structure/walker.ts'
910
import {getObjectById, getSdtId, ObjectType} from './id.ts'
1011
import {initRoots} from './roots.ts'
1112
import setup from './setup.ts'
@@ -18,6 +19,7 @@ import {
1819
type NodeID,
1920
type OutputListener,
2021
type OutputMessage,
22+
dom_element_interface,
2123
} from './types.ts'
2224

2325
function createDebugger() {
@@ -137,6 +139,9 @@ function createDebugger() {
137139
})
138140
}
139141
}
142+
143+
let eli = dom_element_interface
144+
let component_registry = walker.makeComponentRegistry(eli)
140145

141146
//
142147
// Structure:
@@ -152,6 +157,7 @@ function createDebugger() {
152157
},
153158
onNodeUpdate: pushNodeUpdate,
154159
enabled: debuggerEnabled,
160+
component_registry: component_registry,
155161
})
156162

157163
//
@@ -190,6 +196,7 @@ function createDebugger() {
190196
}
191197
},
192198
emit: emitOutput,
199+
component_registry: component_registry,
193200
})
194201

195202
// Opens the source code of the inspected component

packages/debugger/src/main/types.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,27 @@ export type OutputListener = (e: OutputMessage) => void
130130

131131
export type OutputEmit = (e: OutputMessage) => void
132132

133+
/**
134+
* When using a custom solid renderer, you should provide a custom element interface.
135+
* By default the debugger assumes that rendered elements are DOM elements.
136+
*/
137+
export type ElementInterface<T extends object> = {
138+
isElement: (obj: object | T) => obj is T,
139+
getElementName: (el: T) => string,
140+
getElementChildren: (el: T) => Iterable<T>,
141+
getElementAt: (e: MouseEvent) => T | null,
142+
}
143+
144+
/**
145+
* Implementation of {@link ElementInterface} for {@link Element}
146+
*/
147+
export const dom_element_interface: ElementInterface<Element> = {
148+
isElement: obj => obj instanceof Element,
149+
getElementName: el => el.localName,
150+
getElementChildren: el => el.children,
151+
getElementAt: e => e.target as Element | null,
152+
}
153+
133154
//
134155
// EXPOSED SOLID API
135156
//

packages/debugger/src/main/utils.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,31 @@ import {trimString} from '@solid-devtools/shared/utils'
22
import {type Node, type Solid, NodeType} from './types.ts'
33
import setup from './setup.ts'
44

5+
export function* unwrap_each<T>(arr: readonly T[] | null | undefined): ArrayIterator<T> {
6+
if (arr != null) {
7+
yield* arr.values()
8+
}
9+
}
10+
11+
export function append_array<T>(arr: T[], items: readonly T[]): void {
12+
arr.push.apply(arr, items as any)
13+
}
14+
export function unwrap_append<T>(arr: T[], item: T | null | undefined): void {
15+
if (item != null) {
16+
arr.push(item)
17+
}
18+
}
19+
export function unwrap_append_array<T>(arr: T[], items: readonly T[] | null | undefined): void {
20+
if (items != null) {
21+
arr.push.apply(arr, items as any)
22+
}
23+
}
24+
25+
export function* owner_each_child(o: Solid.Owner): ArrayIterator<Solid.Owner> {
26+
yield* unwrap_each(o.owned)
27+
yield* unwrap_each(o.sdtSubRoots)
28+
}
29+
530
export const isSolidOwner = (o: Solid.SourceMapValue | Solid.Owner | Solid.Store | Solid.Signal): o is Solid.Owner =>
631
'owned' in o
732

packages/debugger/src/structure/index.ts

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import {throttle} from '@solid-primitives/scheduled'
2-
import * as registry from '../main/component-registry.ts'
32
import {ObjectType, getSdtId} from '../main/id.ts'
43
import * as roots from '../main/roots.ts'
54
import {type Mapped, type NodeID, type Solid, DEFAULT_WALKER_MODE, DevtoolsMainView, NodeType, TreeWalkerMode} from '../main/types.ts'
65
import {isDisposed, markOwnerType} from '../main/utils.ts'
7-
import {type ComputationUpdateHandler, walkSolidTree} from './walker.ts'
6+
import * as walker from './walker.ts'
87

98
export type StructureUpdates = {
109
/** Partial means that the updates are based on the previous structure state */
@@ -43,10 +42,11 @@ function getClosestIncludedOwner(owner: Solid.Owner, mode: TreeWalkerMode): Soli
4342
return root
4443
}
4544

46-
export function createStructure(props: {
45+
export function createStructure<TEl extends object>(props: {
4746
onStructureUpdate: (updates: StructureUpdates) => void
4847
onNodeUpdate: (nodeId: NodeID) => void
4948
enabled: () => boolean
49+
component_registry: walker.ComponentRegistry<TEl>,
5050
}) {
5151

5252
let treeWalkerMode: TreeWalkerMode = DEFAULT_WALKER_MODE
@@ -57,7 +57,7 @@ export function createStructure(props: {
5757
const removedRoots = new Set<NodeID>()
5858
let shouldUpdateAllRoots = true
5959

60-
const onComputationUpdate: ComputationUpdateHandler = (
60+
const onComputationUpdate: walker.ComputationUpdateHandler = (
6161
rootId, owner, changedStructure,
6262
) => {
6363
// separate the callback from the computation
@@ -72,9 +72,9 @@ export function createStructure(props: {
7272
}
7373

7474
function forceFlushRootUpdateQueue(): void {
75-
75+
7676
if (props.enabled()) {
77-
77+
7878
let partial = !shouldUpdateAllRoots
7979
shouldUpdateAllRoots = false
8080

@@ -92,16 +92,17 @@ export function createStructure(props: {
9292
}
9393

9494
for (let owner of owners) {
95-
let rootId = getRootId(owner)
96-
let tree = walkSolidTree(owner, {
97-
rootId,
98-
mode: treeWalkerMode,
99-
onComputationUpdate,
100-
registerComponent: registry.registerComponent,
95+
let root_id = getRootId(owner)
96+
let tree = walker.walkSolidTree(owner, {
97+
rootId: root_id,
98+
mode: treeWalkerMode,
99+
onUpdate: onComputationUpdate,
100+
eli: props.component_registry.eli,
101+
registry: props.component_registry,
101102
})
102-
let map = updated[rootId]
103-
if (map) map[tree.id] = tree
104-
else updated[rootId] = {[tree.id]: tree}
103+
let map = updated[root_id]
104+
if (map != null) map[tree.id] = tree
105+
else updated[root_id] = {[tree.id]: tree}
105106
}
106107

107108
props.onStructureUpdate({partial, updated, removed: [...removedRoots]})
@@ -143,7 +144,7 @@ export function createStructure(props: {
143144
function setTreeWalkerMode(mode: TreeWalkerMode): void {
144145
treeWalkerMode = mode
145146
updateAllRoots()
146-
registry.clearComponentRegistry()
147+
walker.clearComponentRegistry(props.component_registry)
147148
}
148149

149150
return {

0 commit comments

Comments
 (0)