Skip to content

finding(fields): GeolocationField renders a valid 0 coordinate as EMPTY, and leaks a literal 0 into the DOM #8055

Description

@os-steve

Found while implementing #6848 (the emission fix). Out of that card's scope and deliberately not fixed there: #6848 is about the widget's emission path (handleFieldChange), this is its display/read path. Different code, different defect class. Filed unassigned for triage.

What was measured

packages/fields/src/widgets/GeolocationField.tsx guards its display branches with falsy tests on the parsed NUMBER, so a legitimate 0 coordinate — the equator (latitude: 0) or the prime meridian (longitude: 0) — takes the "no location" branch.

Measured by rendering the real widget (happy-dom, @object-ui/fields suite), reading document.body.textContent:

value readonly render expected
{ latitude: 30.2741, longitude: 120.1551 } (control) "30.274100, 120.155100View on map" correct
{ latitude: 0, longitude: 120.1551 } (a real point on the equator) "—0" "0.000000, 120.155100View on map"
{ latitude: 0, longitude: 0 } "—0" the coordinates

Editable mode, same value { latitude: 0, longitude: 120.1551 }: the buttons rendered are ["Use Current Location"] — the "View on map" button is suppressed. The control renders ["Use Current Location", "View on map"].

Two distinct defects in that one reading

1. A valid location displays as empty. is the EmptyValue placeholder. formatLocation is

if (!loc.latitude || !loc.longitude) return '';

so any coordinate pair containing a zero formats to '' and the widget shows the empty placeholder instead of the location the record actually holds. "View on map" is withheld from the same value by the same shape of guard.

2. A literal 0 leaks into the rendered output — the trailing 0 in "—0". The guard is written as a JSX render expression:

{location.latitude && location.longitude && (
  ... View on map button ...
)}

With location.latitude === 0, 0 && x evaluates to 0, and React renders the number 0 as a text node rather than rendering nothing. The user sees a stray 0 next to the empty-value dash. This is the standard &&-with-a-numeric-operand React hazard, not a variant of defect 1: fixing the emptiness test alone would leave it, and fixing the render guard alone would leave the emptiness.

Affected sites (re-taken on main, packages/fields/src/widgets/GeolocationField.tsx)

  • :153 if (!loc.latitude || !loc.longitude) return '';formatLocation
  • :158 if (!location.latitude || !location.longitude) return;openInMaps refuses to open a valid location
  • :174 {location.latitude && location.longitude && ( — readonly "View on map"; the 0-leaking site
  • :210 {location.latitude && location.longitude && ( — editable "View on map"; same shape
  • :268 {location.accuracy && ( — an accuracy of 0 hides the accuracy row; same shape, and it renders a stray 0 too

:230 value={location.latitude ?? ''} is correct already — it uses ??, so the input box shows 0 properly (measured: "0").

Not the same as #6848

#6848's emission guard, fieldValue ? Number(fieldValue) : null, tests the raw input string, and '0' is not empty — so 0 is emitted correctly as 0. That was measured under #6848 and is now pinned in packages/fields/src/__tests__/GeolocationClearEmission.test.tsx. The falsy-vs-zero problem is live only on the display side, which is what this card is about.

Not measured here

Whether the sibling LocationField has the same display-side shape, and whether any consumer depends on the current empty rendering. Both are cheap to check and belong to whoever picks this up.

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

    bugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpackage: fieldspm:queuepriority:p2

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions