Skip to content

fix: stable option diff to prevent spurious remounts & stale config - #71

Open
ApexYash11 wants to merge 1 commit into
unlayer:mainfrom
ApexYash11:fix/issue-66-stable-option-diff
Open

fix: stable option diff to prevent spurious remounts & stale config#71
ApexYash11 wants to merge 1 commit into
unlayer:mainfrom
ApexYash11:fix/issue-66-stable-option-diff

Conversation

@ApexYash11

Copy link
Copy Markdown
Contributor

Summary

Fixes #66 — the wrapper diffed options prop changes by stringifying the
option objects with JSON.stringify and comparing the strings
(remountKey / updatableKey in src/ImageEditor.tsx). That approach had
three failure modes:

  1. Key-order sensitivity — semantically identical options differing only
    in property declaration order produced different keys → a spurious
    remount
    (destroying unsaved edits — the README explicitly warns
    remount-tier options discard edits, so this is data loss) or a spurious
    updateOptions.
  2. Dropped undefined / functionsJSON.stringify silently omits them,
    so real changes inside options (e.g. a user field) were invisible to the
    diff → stale editor configuration without warning.
  3. Throws on circular references — a circular reference inside options
    crashed during render.

Change

Adds src/optionsDiff.ts, a stable canonical serializer (stableKey) that:

ImageEditor.tsx now uses stableKey for remountKey, updatableKey, and the
mount-time appliedUpdatableRef recording, replacing all three JSON.stringify
sites (consistently, so initial apply / updateOptions guards stay in sync).

Tests

  • test/optionsDiff.test.ts — new unit tests for key-order insensitivity,
    dropped-field visibility, function-by-reference stability, circular-reference
    safety, and every primitive branch.
  • test/index.test.tsx — new component tests: no remount/updateOptions on
    key-order-only change, a remount is correctly detected when a
    previously-undefined value becomes defined, and rendering with a circular
    options object mounts exactly once without crashing.

Verification

  • npm run typecheck — passes
  • npm run test:coverage — 55/55 tests pass, 100% statements / branches /
    functions / lines
    across src/**
  • Prettier clean on all changed files (matches repo line-ending policy)

JSON.stringify-keyed option keys were fragile: semantically identical options that differ only in declaration order produced different keys (spurious remounts that discard unsaved edits, or spurious updateOptions), undefined and function values were silently dropped (stale editor config), and circular references crashed at render.

Replace the raw JSON diff with a stable canonical serializer (stableKey) that sorts object keys, treats undefined/functions as first-class values, and emits a marker for cycles instead of throwing. Add unit and component tests covering the key-order, dropped-field, and circular-reference cases; full suite stays at 100% coverage. Fixes unlayer#66.
@vercel

vercel Bot commented Sep 7, 2026

Copy link
Copy Markdown

@ApexYash11 is attempting to deploy a commit to the Unlayer Team on Vercel.

A member of the Team first needs to authorize it.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG-001: JSON.stringify-keyed option diff can cause data loss / stale config

1 participant