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.
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.tsxguards its display branches with falsy tests on the parsed NUMBER, so a legitimate0coordinate — 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/fieldssuite), readingdocument.body.textContent:{ latitude: 30.2741, longitude: 120.1551 }(control)"30.274100, 120.155100View on map"{ latitude: 0, longitude: 120.1551 }(a real point on the equator)"—0""0.000000, 120.155100View on map"{ latitude: 0, longitude: 0 }"—0"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 theEmptyValueplaceholder.formatLocationisso 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
0leaks into the rendered output — the trailing0in"—0". The guard is written as a JSX render expression:With
location.latitude === 0,0 && xevaluates to0, and React renders the number 0 as a text node rather than rendering nothing. The user sees a stray0next 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):153if (!loc.latitude || !loc.longitude) return '';—formatLocation:158if (!location.latitude || !location.longitude) return;—openInMapsrefuses to open a valid location:174{location.latitude && location.longitude && (— readonly "View on map"; the0-leaking site:210{location.latitude && location.longitude && (— editable "View on map"; same shape:268{location.accuracy && (— an accuracy of0hides the accuracy row; same shape, and it renders a stray0too:230value={location.latitude ?? ''}is correct already — it uses??, so the input box shows0properly (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 — so0is emitted correctly as0. That was measured under #6848 and is now pinned inpackages/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
LocationFieldhas 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.