fix(react): guard mapDensity against prototype-member rowHeight spellings (#4442) - #4457
Merged
Merged
Conversation
…ings (#4442) bridgeListView's mapDensity indexed a plain object literal with an unchecked key, so the lookup reached Object.prototype. The parameter is typed RowHeight, but the boundary a host's stored view definition actually crosses is SpecBridge.transformListView, whose parameter is any -- so rowHeight: 'toString' came back as Object.prototype.toString, a function, out of a read whose return type is three strings or nothing. bridgeListView writes the key under `if (density)` and a function is truthy, so the value was stored on a SchemaNode whose renderer expects 'compact' | 'comfortable' | 'spacious'. Guarded with Object.prototype.hasOwnProperty.call(...), the same guard @object-ui/core's rowHeightToDensityMode grew in #4440 (PR #4447) and the repo's convention at eight other sites. The #4440 agreement pin now covers the prototype-member family in both of its off-spec lists instead of excluding it with a comment pointing here. Closes #4442
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
Collaborator
Author
|
ACCEPT — step-7 复核 by PM session
Flipping ready + arming auto-merge. Slot NOT refilled per maintainer's wind-down instruction. Generated by Claude Code Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #4442
Defect
bridgeListView'smapDensityindexed a plain object literal with an unchecked key, so the lookup reachedObject.prototype. The parameter is typedRowHeight, but the boundary a host's stored view definition actually crosses isSpecBridge.transformListView, whose parameter isany:That is a function returned from a read whose return type is three strings or nothing.
bridgeListViewwrites the key underif (density), and a function is truthy — so the bad value was not merely returned, it was stored on aSchemaNodewhose renderer expects'compact' | 'comfortable' | 'spacious'. Same forconstructor,valueOf,hasOwnProperty,isPrototypeOf,propertyIsEnumerableandtoLocaleString.Fix
One guard, the exact convention PR #4447 applied to the core twin (
rowHeightToDensityMode) and the repo's existing shape at eight other sites (freeze-schema.ts:135,metadata-admin/predicate.ts:305, …):Test half: #4440's agreement pin (
RowHeightDensityAgreement.test.ts) carried a comment saying prototype-member keys were deliberately excluded because the bridge still leaked a function, pointing here. That exclusion comment is gone and both of its off-spec lists now carry the seven prototype-member spellings, plus one separate case pinning the exact expression the issue measured.Red-first evidence
Method: commit the work, then restore only the pre-fix source from
HEAD~(git checkout HEAD~ -- packages/react/src/spec-bridge/bridges/list-view.ts) so the extended pin runs unchanged against the unfixed bridge. Nogit stash— the stash stack is shared across worktrees (AGENTS.md §9).Pre-fix, 9 of 19 fail — the 7 new
it.eachrows, the boundary case, and the agreement invariant:Restoring the fix (
git checkout HEAD -- …) turns the same run green with a cleangit status --porcelain:Verification
pnpm --filter '@object-ui/react^...' build(dependency closure, first)pnpm exec vitest run packages/react/pnpm --filter '@object-ui/react' type-check(tsc --noEmitandtsc -p tsconfig.test.json)pnpm exec eslinton the two changed filesno-explicit-anywarnings on untouchedmapColumnlines).d.tsdiff, pre-fix vs post-fix buildGrading
Patch for
@object-ui/react. The ruling made this conditional on the emitted.d.tsnot moving; it does not — the guard is runtime-only inside a non-exported function whose signature is unchanged, verified by rebuilding the package on both sides and diffing all 62 declaration files (identical). So no escalation to minor under the #4403/#4177 precedent. No spec-validrowHeightchanges its answer; only off-spec prototype-member spellings move, from a leaked function to abstention.Merged
origin/main(d0c3b26 — #4448/#4449/#4450) before verifying:git diffconfirms those three touch no file underpackages/react/src/spec-bridge/, so #4450's repo-widetype="button"sweep is disjoint from this surface. Fast-forward, no conflicts.Generated by Claude Code