Skip to content

finding(fields): clearing a GeolocationField coordinate emits undefined, where the other three type="number" widgets emit null #6848

Description

@os-sales

Found while re-deriving the divergence table for #6793. Not fixed there — that card is test-only and touches no widget source.

What was measured

Chromium 141.0.7390.37 (Playwright 1.62.1) was driven key by key on a real input type="number", and the resulting .value sequence was then driven through each widget in happy-dom. Typing 1e into an empty box is the reachable "clear" route: the browser moves .value from '' to '1' to '', and the widget is told the box is now empty.

widgetemission when the box goes empty
CurrencyFieldnull
PercentFieldnull
NumberFieldnull
GeolocationField{ latitude: undefined }

Same for plain deletion — any route that leaves the box empty. Pinned as current product behaviour in packages/fields/src/__tests__/NumberInputWidgets.browserDeliverable.test.tsx (PR for #6793).

Why it is not cosmetic

GeolocationField builds an object instead of emitting a scalar:

onChange({ ...location, [fieldName]: fieldValue ? Number(fieldValue) : undefined });

undefined and null part company at the persistence boundary. JSON.stringifydrops an undefined key entirely, so a cleared latitude can reach the server as an ABSENT key rather than an explicit null. On a PATCH-shaped update an absent key conventionally means "leave it alone" — so the user clears a coordinate, sees an empty box, and the old coordinate survives the save. The other three widgets of this class send an explicit null and do not have that ambiguity.

Not measured here: whether any data adapter in this repo actually round-trips a geolocation clear that way. That is the first thing to check before choosing a fix — the emission asymmetry is measured, the downstream consequence is reasoned.

Context, not a second finding

The class also carries two different parsers — parseFloat in CurrencyField / PercentField, Number in NumberField / GeolocationField. On every string a real browser can deliver they were measured to agree on all rows, so this is latent rather than live; it is worth knowing only because it is the same "one class, two spellings" shape.

Related

#6793 (the test-oracle card this came out of) · #6780 / PR #6801 (the badInput announcement across the same four widgets) · #6765

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions