fix STF Vector JSON serialization circular reference#82
Conversation
StateTransition.Codec decodes `block` as a `Block.Codec.View`, which holds Descriptor references whose `View` property self-loops. Walking it with JSON.stringify threw "Converting circular structure to JSON". Materialize ObjectView/SequenceView values in the replacer so they serialize as plain objects. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughExtended JSON serialization logic in the Codec page to materialize Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
✅ Deploy Preview for fluffy-codec ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/pages/Codec.tsx (1)
73-95: Extract the JSON replacer into a shared helper to avoid drift.The replacer logic is duplicated here and in
src/test/stf-vector-json.test.ts(Line 7-27). Centralizing it will keep production and regression behavior in sync.♻️ Suggested refactor (shared helper)
+// src/lib/codecJsonReplacer.ts +import * as bytes from "@typeberry/lib/bytes"; +import * as codec from "@typeberry/lib/codec"; + +export const codecJsonReplacer = (_key: string, value: unknown) => { + if (value instanceof codec.ObjectView) return value.materialize(); + if (value instanceof codec.SequenceView) return value.map((v) => v.materialize()); + if (value instanceof bytes.BytesBlob) return value.toString(); + if (value instanceof bytes.Bytes) return value.toString(); + if (value instanceof Map) return Object.fromEntries(value.entries()); + if (typeof value === "bigint") return value.toString(); + return value; +};-const json = JSON.stringify( - decoded, - (_key, value) => { - ... - }, - 2, -); +import { codecJsonReplacer } from "../lib/codecJsonReplacer"; +const json = JSON.stringify(decoded, codecJsonReplacer, 2);-const replacer = (_key: string, value: unknown) => { - ... -}; +import { codecJsonReplacer } from "../lib/codecJsonReplacer"; ... -expect(() => JSON.stringify(decoded, replacer, 2)).not.toThrow(); +expect(() => JSON.stringify(decoded, codecJsonReplacer, 2)).not.toThrow();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/pages/Codec.tsx` around lines 73 - 95, The JSON.stringify replacer used in src/pages/Codec.tsx duplicates logic found in src/test/stf-vector-json.test.ts; extract that logic into a shared helper (e.g., export a function named createMaterializeReplacer or materializeJsonReplacer) that handles codec.ObjectView, codec.SequenceView, bytes.BytesBlob, bytes.Bytes, Map, and bigint conversions, then replace the inline replacer in Codec.tsx with a call to that helper and update the test to import and reuse the same helper to keep production and regression behavior in sync.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@src/pages/Codec.tsx`:
- Around line 73-95: The JSON.stringify replacer used in src/pages/Codec.tsx
duplicates logic found in src/test/stf-vector-json.test.ts; extract that logic
into a shared helper (e.g., export a function named createMaterializeReplacer or
materializeJsonReplacer) that handles codec.ObjectView, codec.SequenceView,
bytes.BytesBlob, bytes.Bytes, Map, and bigint conversions, then replace the
inline replacer in Codec.tsx with a call to that helper and update the test to
import and reuse the same helper to keep production and regression behavior in
sync.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: bfde2340-7d27-4e9d-9a44-343b53efc0dd
📒 Files selected for processing (2)
src/pages/Codec.tsxsrc/test/stf-vector-json.test.ts
Summary
STF Vectorexample in the codec UI threwTypeError: Converting circular structure to JSON --> property 'View' closes the circle.StateTransition.Codecdecodes itsblockfield usingBlock.Codec.View, so the decoded object'sblockis anObjectView.ObjectViewholdsDescriptorreferences, andDescriptor.Viewdefaults tothiswhen there's no dedicated view — a self-loop thatJSON.stringifywalks into.JSON.stringifyreplacer inCodec.tsx, detectcodec.ObjectView/codec.SequenceViewand materialize them to plain values before serialization.Test plan
npm run test— 154 passed, including the new regression testsrc/test/stf-vector-json.test.tswhich encodes/decodes the STF Vector example and asserts it is JSON-serializable for both chain specs.npm run qaclean.npm run buildclean.STF Vector, clickExample STF Vector— JSON pane renders without error.🤖 Generated with Claude Code