You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
bridgeListView's mapDensity indexes its table with an unguarded key, so rowHeight: 'toString' returns a function as the density #4442
Found while implementing #4440 (converging @object-ui/core's rowHeightToDensityMode with this bridge). Not fixed there: packages/react/src/spec-bridge/** was outside that card's surface, and this is a different defect class from the coercion #4440 retired.
ROW_HEIGHT_TO_DENSITY is a plain object literal, so the index reaches Object.prototype. The parameter is typed RowHeight, but the boundary a host's stored JSON actually crosses is SpecBridge.transformListView, whose parameter is any — that is the untyped entry PR #4439's own pins use.
bridgeListView writes if (density) node.density = density, and a function is truthy, so the key IS written: a SchemaNode carrying a function where the renderer expects 'compact' | 'comfortable' | 'spacious'. Same for constructor, valueOf, hasOwnProperty, isPrototypeOf, propertyIsEnumerable, toLocaleString.
Measured directly, on the core twin which had the identical in-based hole before #4440 fixed it:
AssertionError: expected [Function toString] to be undefined
- Expected: undefined
+ Received: [Function toString]
#4440's ruling scoped the work to rowHeightToDensityMode and its callers, and named packages/react/src/spec-bridge/** read-only for that dispatch. #4440's agreement pin (packages/react/src/spec-bridge/__tests__/RowHeightDensityAgreement.test.ts) therefore covers the off-spec spellings the card is about and deliberately excludes prototype keys, with a comment pointing here — because on those keys the two surfaces still disagree: core now abstains, the bridge returns a function.
Impact
No user hits this today. It needs a host to author or store the literal string toString (or another Object.prototype member) as a view's rowHeight; the three-repo sweep in PR #4439, re-run at newer HEADs for #4440, found no off-spec rowHeight authored anywhere at all. Grading it is triage's call, not the filer's — an unguarded prototype-chain index is a recognized bug class and the observable result is a function leaking into a schema node, which is why this is filed as a defect rather than as an observation.
The fix, when someone takes it
One line, matching what @object-ui/core now does (packages/core/src/utils/normalize-list-view.ts) and the repo's existing convention (Object.prototype.hasOwnProperty.call(...) — used in core/src/utils/freeze-schema.ts:135, app-shell/src/views/metadata-admin/predicate.ts:305, and six other places):
Ruling (delegated authority, product-long-term-stability; open veto window): dispatched as a straight fix, graded per the #4439/#4447 behavior-on-published precedent.
Fix as the issue proposes: guard mapDensity's index with Object.prototype.hasOwnProperty.call(ROW_HEIGHT_TO_DENSITY, rowHeight) before indexing — the exact convention PR refactor(core): rowHeightToDensityMode abstains for an off-spec rowHeight, matching the spec bridge (#4440) #4447 just applied to the core twin (freeze-schema.ts:135 precedent, eight existing sites). This closes the last disagreement between the two rowHeight surfaces: off-spec input (including prototype-member spellings) now gets the same abstention on both. One resolver, one channel, one answer.
Test half: extend the agreement pin packages/react/src/spec-bridge/__tests__/RowHeightDensityAgreement.test.ts — its two it.each lists deliberately exclude prototype keys with a comment pointing at this issue; per PR refactor(core): rowHeightToDensityMode abstains for an off-spec rowHeight, matching the spec bridge (#4440) #4447's own report, "extending the two it.each lists is the natural test half of that fix". Red-first: assert transformListView({ name: 'x', rowHeight: 'toString' }).density is undefined — pre-fix this returns [Function toString] (measured in the issue body), post-fix it abstains. Cover the other Object.prototype members in the same it.each rows.
Sequencing gate: PR #4447 owns the agreement-pin file and is armed for auto-merge — the dev must poll for #4447 in origin/mainbefore creating the worktree, then build the dependency closure.
Surface (mutual exclusion): packages/react/src/spec-bridge/** (bridge + agreement pin) + one changeset file. No other in-flight card touches spec-bridge: #4045 (lint rule/button types), #4433 (calendar plugin), #4347 (coverage gate), #4325 (fields subpath) are all disjoint.
Activity
yinlianghui commentedon Aug 12, 2026
CLAIM — session
session_017Qqyix2QcnpUC9XeYVDzx3(objectui whole-repo seat), branchclaude/issue-4442-bridge-prototype-guard.Ruling (delegated authority, product-long-term-stability; open veto window): dispatched as a straight fix, graded per the #4439/#4447 behavior-on-published precedent.
mapDensity's index withObject.prototype.hasOwnProperty.call(ROW_HEIGHT_TO_DENSITY, rowHeight)before indexing — the exact convention PR refactor(core): rowHeightToDensityMode abstains for an off-spec rowHeight, matching the spec bridge (#4440) #4447 just applied to the core twin (freeze-schema.ts:135precedent, eight existing sites). This closes the last disagreement between the two rowHeight surfaces: off-spec input (including prototype-member spellings) now gets the same abstention on both. One resolver, one channel, one answer.packages/react/src/spec-bridge/__tests__/RowHeightDensityAgreement.test.ts— its twoit.eachlists deliberately exclude prototype keys with a comment pointing at this issue; per PR refactor(core): rowHeightToDensityMode abstains for an off-spec rowHeight, matching the spec bridge (#4440) #4447's own report, "extending the two it.each lists is the natural test half of that fix". Red-first: asserttransformListView({ name: 'x', rowHeight: 'toString' }).densityisundefined— pre-fix this returns[Function toString](measured in the issue body), post-fix it abstains. Cover the otherObject.prototypemembers in the sameit.eachrows.density→ absent). Changeset patch unless the emitted.d.tsdiff shows surface movement (it should not — the guard is runtime-only); if it does, escalate to minor with the change described in the body per the fix(i18n): retire the reader-lesscommon.searchkey from the ten locale packs (#4392) #4403/fix(i18n): retire the orphaned report.editor.* namespace, 105 keys across ten packs (#4145) #4177 precedent.Sequencing gate: PR #4447 owns the agreement-pin file and is armed for auto-merge — the dev must poll for #4447 in
origin/mainbefore creating the worktree, then build the dependency closure.Surface (mutual exclusion):
packages/react/src/spec-bridge/**(bridge + agreement pin) + one changeset file. No other in-flight card touches spec-bridge: #4045 (lint rule/button types), #4433 (calendar plugin), #4347 (coverage gate), #4325 (fields subpath) are all disjoint.Generated by Claude Code
Generated by Claude Code
fix(react): guard mapDensity against prototype-member rowHeight spell…