Repository navigation
Conversation
lxsmnsyc
left a comment
There was a problem hiding this comment.
Thanks for this. Plain signal and store slot edits work: I ran writeReactiveValue against the browser dev build of solid-js and a dependent memo updated for a plain signal, a nested path in an object signal, a top-level store key and a nested store path (todos[0].done). A few things hold it back.
Blocking
- A no-op edit rewrites object values.
OwnershipSignalRowfills the input withJSON.stringify(value). On blur,parseValueInputreturns a new object fromJSON.parse, which is never===the old value, sowriteReactiveValueruns. Double-clicking an object signal and clicking away replaces it with a JSON copy:Map,Set,Date, class instances, functions andundefinedfields are lost, and identity changes. Fix: skip the write when the draft equals the initial draft, and only offer JSON editing for plain objects and arrays.
Should fix
- Editing inside a
Mapturns it into a plain object.ValueInspectorpasses thecontainerEntrieskey down as the path. For aMap, that key is the formatted string ("k"with quotes), andupdatePathspreads theMapinto{}. Repro: signal{ m: new Map([['k', 1]]) },writeReactiveValue(node, ['m', '"k"'], 2)givesm === { '"k"': 2 }. The same applies toSetand typed arrays. Fix: turn offeditablebelow non-plain containers, or handle them inupdatePath. - The unit tests do not reach the bridge. Vitest runs in Node, so
solid-jsresolves todist/server.dev.js. ThewriteReactiveValuetests use hand-made{ _value, _subs: null }objects and only check_value. The test named "notifies observers" createscountanddoublebut never connects them to the node. Please test with realcreateSignalandcreateStorenodes under thebrowser+developmentconditions and assert a dependent memo updates. - Failure is reported as success. When the bridge cannot be set up,
writesetstarget._valuedirectly and returnstrue. No subscriber is notified and the UI shows the new value while the app does not. Returnfalsehere and show it in the UI. - The
$TARGET/ own-symbol branch looks unreachable and is unsafe. Both callers pass a reactive node (signal.node,node().raw), not a store proxy. Any node with an own symbol key enters this branch, and if it hasv, it mutates the raw store object without notifying anyone. Please remove it or show the case that needs it.
Cost
The writer depends on about 20 hard-coded private field names of the Solid 2 runtime (_value, _subs, _pendingValue, _statusFlags, ...) and re-points one shared signal node at each target. A rename in a solid-js release breaks editing without a type error. A write hook in solid-js DEV would remove this. I'd like the maintainer to decide whether to take the bridge for now.
Nits
parseValueInputturns any input other thantrueor1intofalsefor a boolean (yesgivesfalse). Return the raw input or keep the old value.- Editing a
bigintleaf writes anumber. EditableValueandOwnershipSignalRowrepeat the same draft, commit and cancel logic.
This PR and #42 both change src/dev-toolbar/ownership/index.tsx and conflict there; whichever merges second needs a rebase.
Checks: CI test job passed (build, unit, typecheck, e2e, lint, format).
Summary
Adds live state and store editing directly from the Start Devtools toolbar. Developers can now inspect and update signals and stores on-the-fly, with immediate reactive propagation across dependent memos, effects, and the DOM.
Both the Ownership Tree (component detail view) and the Reactivity Graph (signal/store node detail view) support editing.
What's Changed
Reactivity Write Bridge (
value-editor.ts):createSignal(0)) and property delegation.runWithOwner(null, ...)to respect Solid 2.0 runtime invariants and prevent[REACTIVE_WRITE_IN_OWNED_SCOPE].updatePath), store slot signals (_host), and store proxies ($TARGET).Safe Input Serialization & Parsing:
formatDraftValue()cleanly formats primitives and usesJSON.stringify()for objects and arrays.parseValueInput()parses numbers, booleans, null, undefined, JSON objects/arrays, and strings.selected-entryindemo:explorer) from being inadvertently corrupted into the string"[object Object]".Ownership Panel Integration:
OwnershipSignalRow: inline editing with draft commit onEnter/ blur and cancel onEscape.true⇄false).<ValueInspector>tree with inline property editing.Reactivity Graph Integration:
editable={!node().errored && (node().kind === 'signal' || node().kind === 'store')}).<ValueInspector>.Showcase
2026-10-30.16-58-20.mp4
Verification
value-editor.test.ts(all 166 Vitest unit tests pass across 15 test files).<Counter>'scountsignal in both Ownership Tree and Reactivity Graph, asserting live DOM updates (count 0->42->100). All 15 E2E tests pass.pnpm typecheck, 0 errors).oxfmtcheck..changeset/live-state-editor.md.