Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inspecting values in the console #328

Merged
merged 8 commits into from
Jan 1, 2025
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
7 changes: 7 additions & 0 deletions .changeset/lucky-rats-care.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@solid-devtools/extension": minor
"@solid-devtools/debugger": minor
"@solid-devtools/frontend": minor
---

New feature: inspecting values in the console. (Closes #166)
35 changes: 32 additions & 3 deletions extension/src/panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

import * as s from 'solid-js'
import * as web from 'solid-js/web'
import {log} from '@solid-devtools/shared/utils'
import {error, log} from '@solid-devtools/shared/utils'
import * as frontend from '@solid-devtools/frontend'
import * as debug from '@solid-devtools/debugger/types'

import {
ConnectionName, Place_Name, port_on_message, port_post_message_obj,
Expand Down Expand Up @@ -62,8 +63,36 @@ function App() {
}
})

/* Devtools -> Client */
devtools.output.listen(e => port_post_message_obj(port, e))
devtools.output.listen(e => {
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check
switch (e.name) {
case 'ConsoleInspectValue': {
/*
`chrome.devtools.inspectedWindow.eval` runs in a devtools console
so the value can be additionally inspected with `inspect()`
*/
let get_value = `window[${JSON.stringify(debug.GLOBAL_GET_VALUE)}]`
let value_id = JSON.stringify(e.details)

chrome.devtools.inspectedWindow.eval(
/*js*/`typeof ${get_value} === 'function' && (() => {
let v = ${get_value}(${value_id})
inspect(v)
console.log(v)
})()`,
(_, err?: chrome.devtools.inspectedWindow.EvaluationExceptionInfo) => {
if (err && (err.isError || err.isException)) {
error(err.description)
}
})
break
}
default:
/* Devtools -> Client */
port_post_message_obj(port, e)
break
}
})

return (
<div
Expand Down
22 changes: 18 additions & 4 deletions packages/debugger/src/inspector/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {onOwnerDispose} from '../main/utils.ts'
import {type ObservedPropsMap, ValueNodeMap, clearOwnerObservers, collectOwnerDetails} from './inspector.ts'
import {encodeValue} from './serialize.ts'
import {type StoreNodeProperty, type StoreUpdateData, observeStoreNode, setOnStoreNodeUpdate} from './store.ts'
import {type InspectorUpdate, type InspectorUpdateMap, PropGetterState} from './types.ts'
import {GLOBAL_GET_VALUE, type InspectorUpdate, type InspectorUpdateMap, PropGetterState} from './types.ts'

export * from './types.ts'

Expand All @@ -24,13 +24,22 @@ export function createInspector(props: {
resetInspectedNode: VoidFunction
emit: OutputEmit
}) {

let lastDetails: Mapped.OwnerDetails | undefined
let inspectedOwner: Solid.Owner | null
let valueMap = new ValueNodeMap()
const propsMap: ObservedPropsMap = new WeakMap()
/** compare props object with the previous one to see whats changed */
let checkProxyProps: (() => InspectorUpdateMap['propKeys'] | null) | null

/*
For the extension for inspecting values through `inspect()`
*/
function getValue(id: ValueItemID): unknown {
return valueMap.get(id)?.getValue?.()
}
window[GLOBAL_GET_VALUE] = getValue

// Batch and dedupe inspector updates
// these will include updates to signals, stores, props, and node value
const {pushPropState, pushValueUpdate, pushInspectToggle, triggerPropsCheck, clearUpdates} =
Expand Down Expand Up @@ -156,11 +165,12 @@ export function createInspector(props: {
})

props.emit('InspectedNodeDetails', result.details)
valueMap = result.valueMap
lastDetails = result.details

valueMap = result.valueMap
lastDetails = result.details
checkProxyProps = result.checkProxyProps || null
} else {
lastDetails = undefined
lastDetails = undefined
checkProxyProps = null
}

Expand All @@ -186,5 +196,9 @@ export function createInspector(props: {
node.setSelected(selected)
pushInspectToggle(id, selected)
},
consoleLogValue(value_id: ValueItemID): void {
// eslint-disable-next-line no-console
console.log(getValue(value_id))
}
}
}
11 changes: 11 additions & 0 deletions packages/debugger/src/inspector/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,14 @@ export type InspectorUpdateMap = {
export type InspectorUpdate = {
[T in keyof InspectorUpdateMap]: [type: T, data: InspectorUpdateMap[T]]
}[keyof InspectorUpdateMap]

/*
For the extension for inspecting values through `inspect()`
*/
export const GLOBAL_GET_VALUE = '$SdtGetValue'

declare global {
interface Window {
[GLOBAL_GET_VALUE]?: (id: ValueItemID) => unknown
}
}
6 changes: 5 additions & 1 deletion packages/debugger/src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {createStructure, type StructureUpdates} from '../structure/index.ts'
import {DebuggerModule, DEFAULT_MAIN_VIEW, DevtoolsMainView, TreeWalkerMode} from './constants.ts'
import {getObjectById, getSdtId, ObjectType} from './id.ts'
import setup from './setup.ts'
import {type Mapped, type NodeID} from './types.ts'
import {type Mapped, type NodeID, type ValueItemID} from './types.ts'

export type InspectedState = {
readonly ownerId: NodeID | null
Expand All @@ -37,6 +37,7 @@ export type InputChannels = {
ResetState: void
InspectNode: {ownerId: NodeID | null; signalId: NodeID | null} | null
InspectValue: ToggleInspectedValueData
ConsoleInspectValue: ValueItemID
HighlightElementChange: HighlightElementPayload
OpenLocation: void
TreeViewModeChange: TreeWalkerMode
Expand Down Expand Up @@ -280,6 +281,9 @@ function createDebugger() {
case 'InspectValue':
inspector.toggleValueNode(e.details)
break
case 'ConsoleInspectValue':
inspector.consoleLogValue(e.details)
break
case 'OpenLocation':
openInspectedNodeLocation()
break
Expand Down
10 changes: 5 additions & 5 deletions packages/frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const App: s.Component<{headerSubtitle?: s.JSX.Element}> = props => {
>
<header class="p-2 flex items-center gap-x-2 bg-panel-bg b-b b-solid b-panel-border text-text">
<div class="flex items-center gap-x-2">
<ui.Icon.SolidWhite class="w-4 h-4 text-disabled" />
<ui.icon.SolidWhite class="w-4 h-4 text-disabled" />
<div>
<h3>Solid Developer Tools</h3>
{props.headerSubtitle && (
Expand Down Expand Up @@ -80,7 +80,7 @@ const Options: s.Component = () => {
}}>
<summary
class={`${ui.toggle_button} rounded-md ml-auto w-7 h-7`}>
<ui.Icon.Options
<ui.icon.Options
class="w-4.5 h-4.5"
/>
</summary>
Expand All @@ -97,7 +97,7 @@ const Options: s.Component = () => {
class='
flex items-center gap-1 p-1 rounded-md outline-none
text-text transition-colors hover:bg-orange-500/10 focus:bg-orange-500/10'>
<ui.Icon.Bug class='w-3 h-3 mb-px text-orange-500 dark:text-orange-400' />
<ui.icon.Bug class='w-3 h-3 mb-px text-orange-500 dark:text-orange-400' />
Report a bug
</a>
<a
Expand All @@ -108,7 +108,7 @@ const Options: s.Component = () => {
class='
flex items-center gap-1 p-1 rounded-md outline-none
text-text transition-colors hover:bg-pink-500/10 focus:bg-pink-500/10'>
<ui.Icon.Heart class='w-3 h-3 mb-px text-pink-500 dark:text-pink-400' />
<ui.icon.Heart class='w-3 h-3 mb-px text-pink-500 dark:text-pink-400' />
Support the project
</a>
</div>
Expand Down Expand Up @@ -141,4 +141,4 @@ const Options: s.Component = () => {
// View: {view.get().toUpperCase()}
// </button>
// )
// }
// }
4 changes: 2 additions & 2 deletions packages/frontend/src/SidePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,15 @@ export function createSidePanel() {
class={action_button}
onClick={openComponentLocation}
>
<ui.Icon.Code class={action_icon} />
<ui.icon.Code class={action_icon} />
</button>
)}
<button
title="Close inspector"
class={action_button}
onClick={() => setInspectedOwner(null)}
>
<ui.Icon.Close class={action_icon} />
<ui.icon.Close class={action_icon} />
</button>
</div>
<ui.ToggleTabs
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export {createDevtools} from './controller.tsx'
export type {OutputEventBus, InputEventBus, DevtoolsOptions as DevtoolsProps} from './controller.tsx'
export {Icon, MountIcons} from './ui/index.ts'
export {icon as Icon, MountIcons} from './ui/index.ts'
export type {IconComponent} from './ui/index.ts'
Loading
Loading