chore(client): scrub style={[...]} on DOM-leaf primitives + ESLint guardrail (#239) #384
No reviewers
Labels
No labels
area:auth
area:ci
area:db
area:infra
area:native
area:pwa
area:service
epic
feature
foundation
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
james/carol!384
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "239-style-array-scrub"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #239
React DOM's
setValueForStylesfor-in-iterates thestyleprop and writesnode.style[key]; a style array (or RNW passing a nested array through certain Link/Pressable merges) iterates numeric indices and throwsCSSStyleProperties doesn't have an indexed property setter for '0'— the real crash from PR #209. Most array sites flatten fine, but the failures are subtle and context-dependent, so the arrays are land mines.What changed
style/contentContainerStylearray sites on DOM-leaf primitives (View/Text/Pressable/TextInput/Image/ScrollView) migrated to merged objects:[E1, E2]→{ ...(E1), ...(E2) }. Order-preserving (later spreads win); spreading a falsy conditional is a no-op. Style-shape only — no visual change. Done with a one-shot TS-compiler-API codemod (run, then removed — not committed).eslint.config.mjs: ano-restricted-syntaxrule (error) flagsstyle={[...]}on the leaf primitives, with a message explaining the crash, pointing at #239 / PR #209, and the merged-object pattern. Opt-out viaeslint-disablefor a genuine animated/Reanimated style array.CONTRIBUTING.md: a Conventions note on the rule + pattern.KeyboardAwareScrollView/FlatListarrays (non-leaf, flatten reliably); there are no animated-style arrays in the repo.Verification
export:web(Exported: dist) / semgrep 0 — all pass.{ ...(textStyle), ... }). All current callers pass a single style object, so this is correct today; if a caller ever passed an array as that prop the merge would misbehave — worth an eye in review, but no such caller exists.Merge note
Overlaps #236 (PR #382) on
apps/client/app/server-setup.tsx. Merge #382 first, then rebase this branch — the only conflict is the 8 style sites inserver-setup.tsx.🤖 Generated with Claude Code
📊 Test coverage
Patch coverage: no testable lines changed.
Overall (
app/,lib/,db/, excluding UI per ADR-0019):Soft thresholds per ADR-0019. Coverage is informational and does not block merge.
26ba0c323d1c35e77bfd