88// of patent rights can be found in the PATENTS file in the same directory.
99//
1010
11- #import " ASLayoutSpec.h"
11+ #import " ASLayoutSpec+Private .h"
1212
1313#import " ASAssert.h"
1414#import " ASEnvironmentInternal.h"
1717#import " ASThread.h"
1818#import " ASTraitCollection.h"
1919
20- #import < objc/runtime.h>
21- #import < map>
2220#import < vector>
2321
24- typedef std::map<unsigned long , id <ASLayoutable>, std::less<unsigned long >> ASChildMap;
25-
2622@interface ASLayoutSpec () {
2723 ASEnvironmentState _environmentState;
2824 ASDN::RecursiveMutex __instanceLock__;
29- ASChildMap _children ;
25+ ASChildrenMap _childrenMap ;
3026}
3127@end
3228
@@ -35,6 +31,7 @@ @implementation ASLayoutSpec
3531// these dynamic properties all defined in ASLayoutOptionsPrivate.m
3632@dynamic spacingAfter, spacingBefore, flexGrow, flexShrink, flexBasis,
3733 alignSelf, ascender, descender, sizeRange, layoutPosition, layoutableType;
34+ @synthesize parent = _parent;
3835@synthesize isFinalLayoutable = _isFinalLayoutable;
3936
4037- (instancetype )init
@@ -105,27 +102,35 @@ - (ASLayout *)measureWithSizeRange:(ASSizeRange)constrainedSize
105102 return child;
106103}
107104
105+ #pragma mark - Parent
106+
108107- (void )setParent : (id <ASLayoutable>)parent
109108{
110- // FIXME: Locking should be evaluated here. _parent is not widely used yet, though.
111109 _parent = parent;
112110
113111 if ([parent supportsUpwardPropagation ]) {
114112 ASEnvironmentStatePropagateUp (parent, self.environmentState .layoutOptionsState );
115113 }
116114}
117115
116+ - (id <ASLayoutable>)parent
117+ {
118+ return _parent;
119+ }
120+
121+ #pragma mark - Children
122+
118123- (void )setChild : (id <ASLayoutable>)child
119124{
120125 ASDisplayNodeAssert (self.isMutable , @" Cannot set properties when layout spec is not mutable" );
121126 if (child) {
122127 id <ASLayoutable> finalLayoutable = [self layoutableToAddFromLayoutable: child];
123128 if (finalLayoutable) {
124- _children [0 ] = finalLayoutable;
129+ _childrenMap [0 ] = finalLayoutable;
125130 [self propagateUpLayoutable: finalLayoutable];
126131 }
127132 } else {
128- _children .erase (0 );
133+ _childrenMap .erase (0 );
129134 }
130135}
131136
@@ -134,9 +139,9 @@ - (void)setChild:(id<ASLayoutable>)child forIndex:(NSUInteger)index
134139 ASDisplayNodeAssert (self.isMutable , @" Cannot set properties when layout spec is not mutable" );
135140 if (child) {
136141 id <ASLayoutable> finalLayoutable = [self layoutableToAddFromLayoutable: child];
137- _children [index] = finalLayoutable;
142+ _childrenMap [index] = finalLayoutable;
138143 } else {
139- _children .erase (index);
144+ _childrenMap .erase (index);
140145 }
141146 // TODO: Should we propagate up the layoutable at it could happen that multiple children will propagated up their
142147 // layout options and one child will overwrite values from another child
@@ -147,37 +152,69 @@ - (void)setChildren:(NSArray<id<ASLayoutable>> *)children
147152{
148153 ASDisplayNodeAssert (self.isMutable , @" Cannot set properties when layout spec is not mutable" );
149154
150- _children .clear ();
155+ _childrenMap .clear ();
151156 NSUInteger i = 0 ;
152157 for (id <ASLayoutable> child in children) {
153- _children [i] = [self layoutableToAddFromLayoutable: child];
158+ _childrenMap [i] = [self layoutableToAddFromLayoutable: child];
154159 i += 1 ;
155160 }
156161}
157162
158163- (id <ASLayoutable>)childForIndex : (NSUInteger )index
159164{
160- if (index < _children .size ()) {
161- return _children [index];
165+ if (index < _childrenMap .size ()) {
166+ return _childrenMap [index];
162167 }
163168 return nil ;
164169}
165170
166171- (id <ASLayoutable>)child
167172{
168- return _children [0 ];
173+ return _childrenMap [0 ];
169174}
170175
171176- (NSArray *)children
172177{
178+ // If used inside ASDK, the childrenMap property should be preferred over the children array to prevent unecessary
179+ // boxing
173180 std::vector<ASLayout *> children;
174- for (ASChildMap::iterator it = _children. begin (); it != _children. end (); ++it ) {
175- children.push_back (it-> second );
181+ for (auto const &entry : _childrenMap ) {
182+ children.push_back (entry. second );
176183 }
177-
184+
178185 return [NSArray arrayWithObjects: &children[0 ] count: children.size ()];
179186}
180187
188+ #pragma mark - NSFastEnumeration
189+
190+ - (NSUInteger )countByEnumeratingWithState : (NSFastEnumerationState *)state
191+ objects : (id __unsafe_unretained [])stackbuf
192+ count : (NSUInteger )stackbufLength
193+ {
194+ NSUInteger count = 0 ;
195+ unsigned long countOfItemsAlreadyEnumerated = state->state ;
196+
197+ if (countOfItemsAlreadyEnumerated == 0 ) {
198+ state->mutationsPtr = &state->extra [0 ];
199+ }
200+
201+ if (countOfItemsAlreadyEnumerated < _childrenMap.size ()) {
202+ state->itemsPtr = stackbuf;
203+
204+ while ((countOfItemsAlreadyEnumerated < _childrenMap.size ()) && (count < stackbufLength)) {
205+ stackbuf[count] = _childrenMap[countOfItemsAlreadyEnumerated];
206+ countOfItemsAlreadyEnumerated++;
207+ count++;
208+ }
209+ } else {
210+ count = 0 ;
211+ }
212+
213+ state->state = countOfItemsAlreadyEnumerated;
214+
215+ return count;
216+ }
217+
181218#pragma mark - ASEnvironment
182219
183220- (ASEnvironmentState)environmentState
@@ -233,6 +270,15 @@ - (ASTraitCollection *)asyncTraitCollection
233270
234271@end
235272
273+ @implementation ASLayoutSpec (Private)
274+
275+ - (ASChildrenMap)childrenMap
276+ {
277+ return _childrenMap;
278+ }
279+
280+ @end
281+
236282@implementation ASLayoutSpec (Debugging)
237283
238284#pragma mark - ASLayoutableAsciiArtProtocol
0 commit comments