[General] Hide non-serializable gesture fields from enumeration - #4556
Conversation
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (1)
Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review. 📝 SummarySummary by CodeRabbit
Walkthrough
ChangesGesture properties
Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to The change hides gesture internals from enumeration while preserving direct access and composition behavior. No merge-blocking issue is established; merge after normal checks. Architecture SummaryArchitecture risk: 🔵 Low · up to The change affects 1 system. Changed systems: Architecture concerns Review detailsSystems and components
Before / after behavior
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The new serialization contract needs an automated regression test.
Review effort: Balanced
Findings: 1
What changed in this PR
Prevents Worklets from serializing and freezing internal v3 gesture fields.
Changes:
- Makes internal gesture fields non-enumerable.
- Keeps
handlerTagenumerable and named property access unchanged.
| File | Description |
|---|---|
packages/react-native-gesture-handler/src/v3/hooks/useGesture.ts |
Restricts gesture enumeration to handlerTag. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| Object.defineProperties(g, { | ||
| type: { enumerable: false }, | ||
| config: { enumerable: false }, | ||
| detectorCallbacks: { enumerable: false }, | ||
| gestureRelations: { enumerable: false }, |

Description
When a gesture object is captured by a worklet, for example
onActivate: () => GestureStateManager.fail(pan.handlerTag)inside a workletized callback, Worklets serializes the whole object withObject.entriesand, in dev, freezes every enumerated field. That draggedconfig(all callbacks and shared values),detectorCallbacksandgestureRelationsto the UI runtime and left the JS-side objects frozen. The freeze turned thegestureRelationsreassignment intraverseAndConfigureRelationsinto a silent no-op and pushing into the frozen relation arrays throws once they are non-empty.First, the following warning appears:
Then after trying to modify frozen relations:
The only field that needs to cross to the UI runtime is
handlerTag. This PR markstype,config,detectorCallbacksandgestureRelationsas non-enumerable inuseGesture. All consumers read them by name or with theinoperator, so library behaviour is unchanged; only enumeration-based cloning, spreading andconsole.lognow see{ handlerTag }.Composed gestures returned by
useComposedGestureare left as they are.Test plan
Tested on the following code: