fix(widgets): reconcile widget store entry when widget type changes#13774
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
🎭 Playwright: ✅ 1715 passed, 0 failed · 1 flaky📊 Browser Reports
🎨 Storybook: ✅ Built — View Storybook📦 Bundle Size
⚡ Performance Report
Absolute values
Raw data{
"timestamp": "2026-07-18T00:15:11.867Z",
"gitSha": "3eccadf0522f678d03e75e0b583d06a335585cfd",
"branch": "fix/widget-store-type-reconcile",
"measurements": [
{
"name": "canvas-idle",
"durationMs": 2111.684999999994,
"styleRecalcs": 10,
"styleRecalcDurationMs": 11.762,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 534.033,
"heapDeltaBytes": -19182428,
"heapUsedBytes": 49601308,
"domNodes": -264,
"jsHeapTotalBytes": 19017728,
"scriptDurationMs": 17.971999999999998,
"eventListeners": -133,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-idle",
"durationMs": 2012.584000000004,
"styleRecalcs": 11,
"styleRecalcDurationMs": 8.681,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 400.2129999999999,
"heapDeltaBytes": -23019876,
"heapUsedBytes": 46072856,
"domNodes": -266,
"jsHeapTotalBytes": 19279872,
"scriptDurationMs": 15.745,
"eventListeners": -133,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1856.6549999999893,
"styleRecalcs": 76,
"styleRecalcDurationMs": 41.102,
"layouts": 12,
"layoutDurationMs": 3.73,
"taskDurationMs": 814.451,
"heapDeltaBytes": -15265988,
"heapUsedBytes": 53692920,
"domNodes": -265,
"jsHeapTotalBytes": 20066304,
"scriptDurationMs": 123.71600000000002,
"eventListeners": -133,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-mouse-sweep",
"durationMs": 1858.5919999999874,
"styleRecalcs": 78,
"styleRecalcDurationMs": 40.574,
"layouts": 12,
"layoutDurationMs": 3.697,
"taskDurationMs": 817.8689999999999,
"heapDeltaBytes": -14499908,
"heapUsedBytes": 54386808,
"domNodes": -265,
"jsHeapTotalBytes": 19804160,
"scriptDurationMs": 128.343,
"eventListeners": -133,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1726.7350000000192,
"styleRecalcs": 31,
"styleRecalcDurationMs": 17.522999999999996,
"layouts": 6,
"layoutDurationMs": 0.626,
"taskDurationMs": 368.36199999999997,
"heapDeltaBytes": 7398244,
"heapUsedBytes": 76131140,
"domNodes": 78,
"jsHeapTotalBytes": 19677184,
"scriptDurationMs": 25.284000000000002,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "canvas-zoom-sweep",
"durationMs": 1739.328999999998,
"styleRecalcs": 32,
"styleRecalcDurationMs": 15.925000000000002,
"layouts": 6,
"layoutDurationMs": 0.6099999999999999,
"taskDurationMs": 290.877,
"heapDeltaBytes": 7564364,
"heapUsedBytes": 76445460,
"domNodes": 79,
"jsHeapTotalBytes": 19152896,
"scriptDurationMs": 16.241,
"eventListeners": 19,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "dom-widget-clipping",
"durationMs": 545.9010000000148,
"styleRecalcs": 13,
"styleRecalcDurationMs": 9.221,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 327.42699999999996,
"heapDeltaBytes": -11905240,
"heapUsedBytes": 56882504,
"domNodes": 22,
"jsHeapTotalBytes": 19677184,
"scriptDurationMs": 55.852,
"eventListeners": 2,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "dom-widget-clipping",
"durationMs": 578.314999999975,
"styleRecalcs": 12,
"styleRecalcDurationMs": 8.522000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 344.10400000000004,
"heapDeltaBytes": -11588516,
"heapUsedBytes": 57176584,
"domNodes": 20,
"jsHeapTotalBytes": 19939328,
"scriptDurationMs": 57.394,
"eventListeners": 0,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-idle",
"durationMs": 2033.2629999999767,
"styleRecalcs": 8,
"styleRecalcDurationMs": 8.602000000000002,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 548.081,
"heapDeltaBytes": 4947972,
"heapUsedBytes": 64117796,
"domNodes": -267,
"jsHeapTotalBytes": 4145152,
"scriptDurationMs": 91.60499999999999,
"eventListeners": -129,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-idle",
"durationMs": 2054.3069999999943,
"styleRecalcs": 10,
"styleRecalcDurationMs": 9.623,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 529.822,
"heapDeltaBytes": 5827928,
"heapUsedBytes": 65155920,
"domNodes": -263,
"jsHeapTotalBytes": 5455872,
"scriptDurationMs": 90.33000000000001,
"eventListeners": -129,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2178.1969999999546,
"styleRecalcs": 70,
"styleRecalcDurationMs": 16.274,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1106.896,
"heapDeltaBytes": -76132,
"heapUsedBytes": 61817108,
"domNodes": -267,
"jsHeapTotalBytes": 5398528,
"scriptDurationMs": 392.69899999999996,
"eventListeners": -127,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "large-graph-pan",
"durationMs": 2178.5320000000183,
"styleRecalcs": 70,
"styleRecalcDurationMs": 15.615,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 1134.382,
"heapDeltaBytes": 1684028,
"heapUsedBytes": 61749708,
"domNodes": -269,
"jsHeapTotalBytes": 5136384,
"scriptDurationMs": 413.038,
"eventListeners": -129,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "large-graph-zoom",
"durationMs": 3181.1460000000125,
"styleRecalcs": 65,
"styleRecalcDurationMs": 15.305000000000003,
"layouts": 60,
"layoutDurationMs": 7.323999999999999,
"taskDurationMs": 1394.406,
"heapDeltaBytes": -3882252,
"heapUsedBytes": 57966204,
"domNodes": -272,
"jsHeapTotalBytes": 8601600,
"scriptDurationMs": 517.231,
"eventListeners": -133,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "large-graph-zoom",
"durationMs": 3177.707000000055,
"styleRecalcs": 65,
"styleRecalcDurationMs": 15.172999999999998,
"layouts": 60,
"layoutDurationMs": 7.302000000000001,
"taskDurationMs": 1384.429,
"heapDeltaBytes": -3013616,
"heapUsedBytes": 58930884,
"domNodes": -273,
"jsHeapTotalBytes": 7815168,
"scriptDurationMs": 510.625,
"eventListeners": -133,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2026.034999999979,
"styleRecalcs": 8,
"styleRecalcDurationMs": 9.069999999999999,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 597.826,
"heapDeltaBytes": 5535204,
"heapUsedBytes": 66584488,
"domNodes": -267,
"jsHeapTotalBytes": 4407296,
"scriptDurationMs": 101.89,
"eventListeners": -129,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "minimap-idle",
"durationMs": 2022.3300000000108,
"styleRecalcs": 10,
"styleRecalcDurationMs": 8.866000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 521.6859999999999,
"heapDeltaBytes": 4714628,
"heapUsedBytes": 65979436,
"domNodes": -267,
"jsHeapTotalBytes": 5455872,
"scriptDurationMs": 87.04899999999999,
"eventListeners": -129,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 596.7850000000112,
"styleRecalcs": 46,
"styleRecalcDurationMs": 10.758000000000003,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 374.09700000000004,
"heapDeltaBytes": -11610280,
"heapUsedBytes": 57567728,
"domNodes": 18,
"jsHeapTotalBytes": 21250048,
"scriptDurationMs": 122.33700000000002,
"eventListeners": 8,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-dom-widget-clipping",
"durationMs": 559.0180000000373,
"styleRecalcs": 48,
"styleRecalcDurationMs": 11.309,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 368.437,
"heapDeltaBytes": -11449616,
"heapUsedBytes": 57499364,
"domNodes": 22,
"jsHeapTotalBytes": 20987904,
"scriptDurationMs": 122.057,
"eventListeners": 6,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333335,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "subgraph-idle",
"durationMs": 2033.7859999999637,
"styleRecalcs": 11,
"styleRecalcDurationMs": 9.914000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 399.236,
"heapDeltaBytes": -20561132,
"heapUsedBytes": 48395564,
"domNodes": -263,
"jsHeapTotalBytes": 19279872,
"scriptDurationMs": 14.57,
"eventListeners": -133,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-idle",
"durationMs": 2035.2080000000115,
"styleRecalcs": 11,
"styleRecalcDurationMs": 9.347,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 404.45700000000005,
"heapDeltaBytes": -22156132,
"heapUsedBytes": 46932908,
"domNodes": -263,
"jsHeapTotalBytes": 19542016,
"scriptDurationMs": 13.513,
"eventListeners": -133,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1696.3170000000218,
"styleRecalcs": 76,
"styleRecalcDurationMs": 37.301,
"layouts": 16,
"layoutDurationMs": 3.823,
"taskDurationMs": 662.6999999999999,
"heapDeltaBytes": -5214056,
"heapUsedBytes": 63779116,
"domNodes": 64,
"jsHeapTotalBytes": 19415040,
"scriptDurationMs": 90.599,
"eventListeners": 4,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-mouse-sweep",
"durationMs": 1733.3070000000816,
"styleRecalcs": 75,
"styleRecalcDurationMs": 36.821,
"layouts": 16,
"layoutDurationMs": 4.252000000000001,
"taskDurationMs": 743.514,
"heapDeltaBytes": -21613800,
"heapUsedBytes": 47366136,
"domNodes": -264,
"jsHeapTotalBytes": 19017728,
"scriptDurationMs": 96.374,
"eventListeners": -133,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.700000000000728
},
{
"name": "subgraph-transition-enter",
"durationMs": 982.8510000000392,
"styleRecalcs": 18,
"styleRecalcDurationMs": 30.67299999999999,
"layouts": 14,
"layoutDurationMs": 13.291999999999998,
"taskDurationMs": 771.269,
"heapDeltaBytes": 27492780,
"heapUsedBytes": 97613076,
"domNodes": 13673,
"jsHeapTotalBytes": 16777216,
"scriptDurationMs": 27.932000000000013,
"eventListeners": 2369,
"totalBlockingTimeMs": 147,
"frameDurationMs": 16.670000000000012,
"p95FrameDurationMs": 16.800000000000182
},
{
"name": "viewport-pan-sweep",
"durationMs": 8182.201000000021,
"styleRecalcs": 250,
"styleRecalcDurationMs": 37.932,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3865.613,
"heapDeltaBytes": 15942348,
"heapUsedBytes": 74928484,
"domNodes": -268,
"jsHeapTotalBytes": 6447104,
"scriptDurationMs": 1251.541,
"eventListeners": -115,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "viewport-pan-sweep",
"durationMs": 8161.080999999967,
"styleRecalcs": 249,
"styleRecalcDurationMs": 36.614000000000004,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 3707.6019999999994,
"heapDeltaBytes": 15404968,
"heapUsedBytes": 74757148,
"domNodes": -266,
"jsHeapTotalBytes": 6447104,
"scriptDurationMs": 1244.988,
"eventListeners": -113,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 12980.31800000001,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 12966.051,
"heapDeltaBytes": -46722668,
"heapUsedBytes": 167591460,
"domNodes": -8311,
"jsHeapTotalBytes": -12521472,
"scriptDurationMs": 603.185,
"eventListeners": -16384,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.77333333333336,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-idle",
"durationMs": 12108.009000000038,
"styleRecalcs": 0,
"styleRecalcDurationMs": 0,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 12084.327,
"heapDeltaBytes": -40885096,
"heapUsedBytes": 169589556,
"domNodes": -8311,
"jsHeapTotalBytes": -10948608,
"scriptDurationMs": 561.3459999999999,
"eventListeners": -16386,
"totalBlockingTimeMs": 0,
"frameDurationMs": 17.220000000000073,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 15768.554999999993,
"styleRecalcs": 83,
"styleRecalcDurationMs": 13.61000000000001,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 15744.434,
"heapDeltaBytes": -29670308,
"heapUsedBytes": 179158228,
"domNodes": -8311,
"jsHeapTotalBytes": -16539648,
"scriptDurationMs": 849.905,
"eventListeners": -16386,
"totalBlockingTimeMs": 9,
"frameDurationMs": 17.219999999999953,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "vue-large-graph-pan",
"durationMs": 15598.930999999993,
"styleRecalcs": 82,
"styleRecalcDurationMs": 12.191000000000008,
"layouts": 0,
"layoutDurationMs": 0,
"taskDurationMs": 15557.081,
"heapDeltaBytes": -16967024,
"heapUsedBytes": 184007176,
"domNodes": -8311,
"jsHeapTotalBytes": -13656064,
"scriptDurationMs": 891.849,
"eventListeners": -16384,
"totalBlockingTimeMs": 19,
"frameDurationMs": 17.776666666666642,
"p95FrameDurationMs": 16.80000000000291
},
{
"name": "workflow-execution",
"durationMs": 490.73800000002166,
"styleRecalcs": 19,
"styleRecalcDurationMs": 24.366,
"layouts": 3,
"layoutDurationMs": 1.4549999999999998,
"taskDurationMs": 126.221,
"heapDeltaBytes": -15604532,
"heapUsedBytes": 52682236,
"domNodes": 154,
"jsHeapTotalBytes": 6307840,
"scriptDurationMs": 11.257000000000001,
"eventListeners": 67,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.666666666666668,
"p95FrameDurationMs": 16.799999999999272
},
{
"name": "workflow-execution",
"durationMs": 448.4429999999975,
"styleRecalcs": 14,
"styleRecalcDurationMs": 19.158,
"layouts": 2,
"layoutDurationMs": 0.42599999999999993,
"taskDurationMs": 105.02099999999999,
"heapDeltaBytes": -16401916,
"heapUsedBytes": 51706668,
"domNodes": 119,
"jsHeapTotalBytes": 7094272,
"scriptDurationMs": 9.073,
"eventListeners": 65,
"totalBlockingTimeMs": 0,
"frameDurationMs": 16.66333333333332,
"p95FrameDurationMs": 16.800000000000182
}
]
} |
🎨 Storybook: 🚧 Building... |
Codecov Report✅ All modified and coverable lines are covered by tests. @@ Coverage Diff @@
## fix/widget-store-custom-node-widgets #13774 +/- ##
======================================================================
Coverage 78.29% 78.29%
======================================================================
Files 1683 1683
Lines 98527 98514 -13
Branches 35479 34808 -671
======================================================================
- Hits 77141 77134 -7
+ Misses 20921 20915 -6
Partials 465 465
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 1 file with indirect coverage changes 🚀 New features to boost your workflow:
|
registerWidget returned the existing store entry unconditionally, so when a subgraph convert reused a graphId:nodeId:name key for a different widget, the stale entry won and the widget rendered with the wrong type (a multiline text widget showed as an int widget until a page reload rehydrated the store). Keep the idempotent return only when the existing entry's type matches; on a type mismatch the id now belongs to a different widget, so overwrite with the live type and value. Same-type re-registration still preserves edited values. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3488996 to
dc3e229
Compare
AustinMroz
left a comment
There was a problem hiding this comment.
I recall arguing against having registrations that don't actually perform registration, but I allowed it through.
This fix is objectively safer and has my approval.
1b5e292
into
fix/widget-store-custom-node-widgets
Summary
On subgraph convert, a widget could render with the wrong type (a multiline text widget appeared as an int widget until a page reload) because the widget value store returned a stale entry keyed by
graphId:nodeId:name.Changes
registerWidgetreturned the existing store entry unconditionally (idempotent to preserve edited values across re-render). But when a subgraph convert reuses the samegraphId:nodeId:namekey for a different widget, the stale entry won — wrong type, wrong value, only corrected by a reload that rehydrates the store from serialized data. Now the idempotent return applies only whenexisting.type === init.type; on a type mismatch the id belongs to a different widget, so the store overwrites with the live type/value. Same-type re-registration still preserves edited values (unchanged behavior).Review Focus
type; please sanity-check that no legitimate re-registration changestypefor the same logical widget. Reload already produces the correct result, which is the evidence the in-memory path diverges here.fix/widget-store-custom-node-widgets). Rebase tomainonce that lands.QA source: staging 1.47 — "multiline text widget converts to int inside/outside nested subgraph; refresh fixes it", working on 1.45.21.