Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/bright-rabbits-nail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solid-devtools/debugger": minor
---

Require `ElementInterface.getChildren` to return `ArrayLike<T>`. (76ab4096a2ad531ae015e35c2475b78f08ac45a7)
5 changes: 5 additions & 0 deletions .changeset/orange-islands-drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@solid-devtools/debugger": patch
---

Improve tree walking algorithm for mapping elements. (#348)
124 changes: 61 additions & 63 deletions examples/sandbox/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -163,69 +163,67 @@ const App: s.Component = () => {

const [showBroken, setShowBroken] = s.createSignal(false)

return (
<>
{header()}
{objmemo().subheader}
<div>
<header>
<Button onClick={() => setCount(p => ++p)} text={`Count: ${count()}`} />
<Button onClick={() => setCount(p => ++p)} text={`Count: ${count()}`} />
</header>
<sweb.Dynamic
component='div'
style={{height: '1rem', 'margin-top': '1rem'}}
>
<s.Show when={showEven()}>
{s.createComponent(() => <>
<BoldWrapper/>
</>, {})}
</s.Show>
</sweb.Dynamic>
{/* <button onClick={() => disposeApp()}>Dispose whole application</button>
<br /> */}
<button onClick={() => setShowBroken(p => !p)}>
{showBroken() ? 'Hide' : 'Show'} broken component.
</button>
<s.ErrorBoundary
fallback={(err, reset) => <>
{err.toString()}
<button
onClick={() => {
setShowBroken(false)
reset()
}}
>
Reset
</button>
</>}
>
<s.Show when={showBroken()}>
<Broken />
</s.Show>
</s.ErrorBoundary>
<br />
<br />
</div>
<DynamicSpreadParent />
<button onClick={() => setRootCount(p => ++p)}>Update root count</button>
<button onClick={() => disposeOuterRoot()}>Dispose OUTSIDE_ROOT</button>
<Article />
<Todos title='Simple Todos Example' />
{s.untrack(() => {
const MARGIN = '24px'
return <>
<div style={{margin: MARGIN}}>
<CountingComponent />
</div>
<div style={{margin: MARGIN}}>
<ThemeExample />
</div>
</>
})}
<Recursive />
</>
)
return <>
{header()}
{objmemo().subheader}
<div>
<header>
<Button onClick={() => setCount(p => ++p)} text={`Count: ${count()}`} />
<Button onClick={() => setCount(p => ++p)} text={`Count: ${count()}`} />
</header>
<sweb.Dynamic
component='div'
style={{height: '1rem', 'margin-top': '1rem'}}
>
<s.Show when={showEven()} fallback={<span>Count is very odd</span>}>
{s.createComponent(() => <>
<BoldWrapper/>
</>, {})}
</s.Show>
</sweb.Dynamic>
{/* <button onClick={() => disposeApp()}>Dispose whole application</button>
<br /> */}
<button onClick={() => setShowBroken(p => !p)}>
{showBroken() ? 'Hide' : 'Show'} broken component.
</button>
<s.ErrorBoundary
fallback={(err, reset) => <>
{err.toString()}
<button
onClick={() => {
setShowBroken(false)
reset()
}}
>
Reset
</button>
</>}
>
<s.Show when={showBroken()}>
<Broken />
</s.Show>
</s.ErrorBoundary>
<br />
<br />
</div>
<DynamicSpreadParent />
<button onClick={() => setRootCount(p => ++p)}>Update root count</button>
<button onClick={() => disposeOuterRoot()}>Dispose OUTSIDE_ROOT</button>
<Article />
<Todos title='Simple Todos Example' />
{s.untrack(() => {
const MARGIN = '24px'
return <>
<div style={{margin: MARGIN}}>
<CountingComponent />
</div>
<div style={{margin: MARGIN}}>
<ThemeExample />
</div>
</>
})}
<Recursive />
</>
}

const CountingComponent = () => {
Expand Down
7 changes: 7 additions & 0 deletions packages/debugger/src/main/id.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ export function getSdtId<T extends ObjectType>(obj: ValueMap[T], objType: T): No
return id
}

export const get_id_owner = (o: Solid.Owner): NodeID => getSdtId(o, ObjectType.Owner)
export const get_id_el = (o: object): NodeID => getSdtId(o, ObjectType.Element)
export const get_id_signal = (o: Solid.Signal): NodeID => getSdtId(o, ObjectType.Signal)
export const get_id_store = (o: Solid.Store): NodeID => getSdtId(o, ObjectType.Store)
export const get_id_store_node = (o: Solid.StoreNode): NodeID => getSdtId(o, ObjectType.StoreNode)
export const get_id_custom_value = (o: Solid.SourceMapValue): NodeID => getSdtId(o, ObjectType.CustomValue)

export function getObjectById<T extends ObjectType>(id: NodeID, objType: T): ValueMap[T] | null {
const ref = RefMapMap[objType].get(id)
return ref?.deref() ?? null
Expand Down
27 changes: 13 additions & 14 deletions packages/debugger/src/main/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ export type Rect = {
height: number
}

export type ElementChildren<T extends object> = Iterable<T> & ArrayLike<T>

/**
* When using a custom solid renderer, you should provide a custom element interface.
* By default the debugger assumes that rendered elements are DOM elements.
Expand All @@ -151,7 +153,7 @@ export type ElementInterface<T extends object> = {
isElement: (obj: object | T) => obj is T,
getElementAt: (e: MouseEvent) => T | null,
getName: (el: T) => string | null,
getChildren: (el: T) => Iterable<T>,
getChildren: (el: T) => ElementChildren<T>,
getParent: (el: T) => T | null,
getLocation: (el: T) => SourceLocation | null,
getRect: (el: T) => Rect | null,
Expand Down Expand Up @@ -196,17 +198,14 @@ export const getValueItemId = <T extends ValueItemType>(
export type ValueUpdateListener = (newValue: unknown, oldValue: unknown) => void

export namespace Solid {
export type OwnerBase = import('solid-js').Owner
export type SourceMapValue = import('solid-js/types/reactive/signal.d.ts').SourceMapValue
export type Signal = import('solid-js/types/reactive/signal.d.ts').SignalState<unknown>
export type Computation = import('solid-js/types/reactive/signal.d.ts').Computation<unknown>
export type Memo = import('solid-js/types/reactive/signal.d.ts').Memo<unknown>
export type OwnerBase = import('solid-js').Owner
export type SourceMapValue = import('solid-js/types/reactive/signal.d.ts').SourceMapValue
export type Signal = import('solid-js/types/reactive/signal.d.ts').SignalState<unknown>
export type Computation = import('solid-js/types/reactive/signal.d.ts').Computation<unknown>
export type Memo = import('solid-js/types/reactive/signal.d.ts').Memo<unknown>
export type RootFunction<T> = import('solid-js/types/reactive/signal.d.ts').RootFunction<T>
export type EffectFunction =
import('solid-js/types/reactive/signal.d.ts').EffectFunction<unknown>
export type Component = import('solid-js/types/reactive/signal.d.ts').DevComponent<{
[key: string]: unknown
}>
export type EffectFunction = import('solid-js/types/reactive/signal.d.ts').EffectFunction<unknown>
export type Component = import('solid-js/types/reactive/signal.d.ts').DevComponent<{[key: string]: unknown}>

export type CatchError = Omit<Computation, 'fn'> & {fn: undefined}

Expand All @@ -230,10 +229,10 @@ export namespace Solid {
// STORE
//

export type StoreNode = import('solid-js/store').StoreNode
export type NotWrappable = import('solid-js/store').NotWrappable
export type StoreNode = import('solid-js/store').StoreNode
export type NotWrappable = import('solid-js/store').NotWrappable
export type OnStoreNodeUpdate = import('solid-js/store/types/store.d.ts').OnStoreNodeUpdate
export type Store = SourceMapValue & {value: StoreNode}
export type Store = SourceMapValue & {value: StoreNode}
}

declare module 'solid-js/types/reactive/signal.d.ts' {
Expand Down
7 changes: 4 additions & 3 deletions packages/debugger/src/structure/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,14 @@ export function createStructure<TEl extends object>(props: {
let shouldUpdateAllRoots = true

const onComputationUpdate: walker.ComputationUpdateHandler = (
rootId, owner, changedStructure,
root_id, owner, changed_structure,
) => {
// separate the callback from the computation
queueMicrotask(() => {
if (!props.enabled()) return
if (changedStructure) {
updateOwner(owner, rootId)
if (changed_structure) {
let owner_to_update = getClosestIncludedOwner(owner, treeWalkerMode) ?? owner
updateOwner(owner_to_update, root_id)
}
let id = getSdtId(owner, ObjectType.Owner)
props.onNodeUpdate(id)
Expand Down
6 changes: 3 additions & 3 deletions packages/debugger/src/structure/walker.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -362,10 +362,10 @@ test.describe('TreeWalkerMode.DOM', () => {

let to_trigger: (() => void)[] = []
let test_components: Solid.Component[] = []

let el_header!: HTMLElement
let el_h1!: HTMLHeadingElement

let el_footer!: HTMLElement
let el_main!: HTMLElement
let el_h2!: HTMLHeadingElement
Expand All @@ -392,7 +392,7 @@ test.describe('TreeWalkerMode.DOM', () => {
<span ref={el_span}>Click me</span>
</button>
}

const App = () => {
return (
<>
Expand Down
Loading
Loading