feat(react): expose Children API with dev-mode freeze for map/toArray#2376
feat(react): expose Children API with dev-mode freeze for map/toArray#2376Huxpro wants to merge 2 commits intolynx-family:mainfrom
Conversation
- Wrap preact/compat Children with a custom compat layer - Object.freeze the arrays returned by Children.map and Children.toArray in __DEV__ to surface accidental mutations that break snapshot optimizations - Export Children from @lynx-js/react public API - Add integration tests for Children.toArray, and freeze behavior Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughAdded a local Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
Exposes Children on @lynx-js/react’s public API by routing through a compat wrapper that freezes arrays returned from Children.map / Children.toArray in __DEV__, plus adds integration tests and updates the generated API/type surface.
Changes:
- Export
Childrenfrom the package entry and type/docs surfaces. - Introduce
runtime/src/compat/children.tswrapper that freezesmap/toArrayresults in dev. - Add integration tests validating
toArraybehavior and dev-mode freezing formap/toArray.
Reviewed changes
Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/react/types/react.docs.d.ts | Adds Children to the documented/type export list. |
| packages/react/runtime/src/index.ts | Switches Children export to come from the new compat wrapper. |
| packages/react/runtime/src/compat/children.ts | Implements the dev-freeze Children wrapper around preact/compat. |
| packages/react/runtime/test/children.test.jsx | Adds tests for Children.toArray and dev-freeze behavior. |
| packages/react/etc/react.api.md | Updates API Extractor report to include Children. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| map(children: any, fn: any): any[] { | ||
| const arr = PreactChildren.map(children, fn); | ||
| if (__DEV__) { |
There was a problem hiding this comment.
Children.map in preact/compat returns null when children is null/undefined, and also accepts an optional third thisArg/context parameter. The wrapper currently always calls Object.freeze(arr) (which will throw when arr is null) and drops the third parameter, changing behavior vs React/Preact. Guard the freeze with an array check (or arr != null) and forward the optional context argument; also update the wrapper’s return type to allow null (e.g., use ReturnType<typeof PreactChildren.map>).
| map(children: any, fn: any): any[] { | |
| const arr = PreactChildren.map(children, fn); | |
| if (__DEV__) { | |
| map(children: any, fn: any, thisArg?: any): ReturnType<typeof PreactChildren.map> { | |
| const arr = PreactChildren.map(children, fn, thisArg); | |
| if (__DEV__ && arr != null) { |
| // Non-mutating operations should still work | ||
| expect([...results]).toHaveLength(2); | ||
| expect(results.filter(() => true)).toHaveLength(2); | ||
| }); |
There was a problem hiding this comment.
The new dev-freeze tests cover mutation attempts, but there’s no regression test for Children.map(null, fn) (should return null and not throw) or for Children.map(children, fn, thisArg) preserving the this binding. Adding these cases would catch the wrapper-specific behavioral changes introduced here.
| }); | |
| }); | |
| it('Children.map returns null when children is null', function() { | |
| const result = Children.map(null, (child) => child); | |
| expect(result).toBeNull(); | |
| }); | |
| it('Children.map respects thisArg binding', function() { | |
| const children = [<view key="a" />, <view key="b" />]; | |
| const context = { multiplier: 2 }; | |
| const seenThis = []; | |
| const results = Children.map( | |
| children, | |
| function(child, index) { | |
| seenThis.push(this); | |
| return index * this.multiplier; | |
| }, | |
| context, | |
| ); | |
| expect(results).toEqual([0, 2]); | |
| expect(seenThis.every((ctx) => ctx === context)).toBe(true); | |
| }); |
| only: typeof PreactChildren.only; | ||
| toArray: (children: ComponentChild | ComponentChild[]) => readonly any[]; | ||
| } = { | ||
| forEach: PreactChildren.forEach, |
There was a problem hiding this comment.
should keep same with map?
Web Explorer#8395 Bundle Size — 724.73KiB (0%).c940164(current) vs fcda36a main#8391(baseline) Bundle metrics
Bundle size by type
|
| Current #8395 |
Baseline #8391 |
|
|---|---|---|
382.38KiB |
382.38KiB |
|
340.36KiB |
340.36KiB |
|
1.99KiB |
1.99KiB |
Bundle analysis report Branch Huxpro:feat/react-children-api Project dashboard
Generated by RelativeCI Documentation Report issue
Merging this PR will improve performance by ×4.3
Performance Changes
Comparing Footnotes
|
…, wrap forEach - Guard Object.freeze with null check (preact returns null for null children) - Forward thisArg to map/forEach via fn.bind(thisArg) - Wrap forEach for consistency (correct void return type, thisArg support) - Add tests for Children.map(null) and thisArg binding Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
@HuJean Addressed all review comments in dab7f22:
PTAL, thanks! |
Summary
Childrenfrom@lynx-js/reactpublic API by wrappingpreact/compat'sChildrenwith a custom compat layerObject.freezethe arrays returned byChildren.mapandChildren.toArrayin__DEV__to surface accidental mutations (push/splice/sort) that break compile-time snapshot optimizationsChildren.toArrayand freeze behavior for bothmapandtoArrayTest plan
Children.toArraytest (flatten, filter null/undefined)Children.toArrayfreeze test (frozen, push throws, non-mutating ops work)Children.mapfreeze test (frozen, push throws, non-mutating ops work)🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
ChildrenAPI as a public export for managing component children.Improvements
Tests
Childrenbehaviors, immutability in dev, null handling, and thisArg binding in mapping.