Skip to content

finding(core): ValueDataSource's JSON deep-clone rewrites the data it stores — NaN becomes null, undefined keys vanish, Date becomes a string #7380

Description

@os-project-manager

Observation measured while repairing #7349 (PR #7377) on origin/maind53e472. Not a fix request — filing so the behaviour is written down somewhere other than a test comment. Dedupe: listed all 334 open issues via the repo-scoped REST endpoint and grepped titles for valuedatasource / deep.clone / JSON.stringify / NaN — only #7349 itself and two unrelated cards; control term 7349 fired on the same listing.

What was measured

packages/core/src/adapters/ValueDataSource.ts, constructor:

// Deep clone to prevent external mutationthis.items=JSON.parse(JSON.stringify(config.items));

The intent (isolating the adapter's copy from caller mutation) is sound. The mechanism is lossy, and silently so:

input [{id:'NaN', v:NaN}, {id:'undefined', v:undefined}, {id:'array', v:[]}]
stored [{"id":"NaN","v":null}, {"id":"undefined"}, {"id":"array","v":[]}]
  • NaN and Infinity are stored as null
  • a key whose value is undefined is dropped, so "explicitly undefined" and "absent" become indistinguishable
  • a Date becomes an ISO string, and stops comparing as a date
  • functions, Symbol keys and Map / Set values are dropped or emptied

Why it surfaced now, and why it is mild

It was invisible before #7349 because the matcher excluded nothing — no filter ever ran, so no coercion could change an answer. With filtering repaired, a row holding NaN is now correctly excluded by is_not_null, and the reason is the clone rather than the operator. That surprise is recorded in packages/core/src/utils/__tests__/filter-dialect-equivalence-7221.test.ts.

For the adapter's declared job the loss is mostly theoretical: provider: 'value' is fed viewData.items from authored metadata, which is already JSON, and JSON has no NaN or Date to lose.

The two in-repo call sites that construct one programmatically are where it could bite, since their inputs are runtime objects rather than parsed JSON:

  • packages/plugin-designer/src/ObjectManager.tsx:101new ValueDataSource({ items: displayObjects })
  • packages/plugin-designer/src/FieldDesigner.tsx:152new ValueDataSource({ items: filteredFields })

A Date-valued field reaching either would be stored as a string, sort as a string, and render as a string. Whether either actually carries one is unmeasured — that is the first question if this is ever picked up.

If it is ever worth acting on

structuredClone is available in every runtime this package targets and preserves Date, Map, Set, NaN and explicit undefined. It throws on functions rather than dropping them, which is arguably the better failure. That would be the whole change; the reason it is filed as a finding rather than a fix is that nothing measured is currently broken by it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions