Skip to content

getSegmentBreakableFitAdvances: cached result does not distinguish BreakableFitMode #137

@shaun0927

Description

@shaun0927

Summary

getSegmentBreakableFitAdvances() in measurement.ts:196–264 accepts a mode: BreakableFitMode parameter (sum-graphemes, segment-prefixes, or pair-context), but the cache check at line 203 returns the stored result without verifying the mode matches:

if (metrics.breakableFitAdvances !== undefined) return metrics.breakableFitAdvances
// mode is not consulted

If the same segment text were ever requested with two different modes, the first-cached result would silently serve both.

Why it is safe today

The mode is fully determined by text content and the session-invariant engine profile:

  1. isNumericRunSegment(text) is true → always pair-context
  2. engineProfile.preferPrefixWidthsForBreakableRuns is true → always segment-prefixes
  3. Otherwise → always sum-graphemes

Because isNumericRunSegment is a pure text predicate and the engine profile does not change within a session, the same segment text always arrives with the same mode. I verified this by calling getSegmentBreakableFitAdvances with different modes on the same segment — the cache returns the identical object reference, confirming the mode is ignored, but the current call pattern prevents a mismatch from occurring.

Suggestion

The function's type signature promises mode-awareness that the implementation does not deliver. One of:

  1. Assert: add assert(cachedMode === mode) guarded by process.env.NODE_ENV !== 'production' — zero production cost, catches future regressions
  2. Document: add a comment at the cache check noting the invariant and why it holds
  3. Refactor: remove mode from the signature entirely and let the caller compute advances externally, making the cache contract explicit

Not filing this as a bug — the invariant holds — but the gap between the API surface and the implementation could surprise a future caller.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions