Remove reliance on shared_ptr for ASDisplayNodeLayouts (#1131)

* Remove reliance on shared_ptr for ASDisplayNodeLayouts

* Fix up

* Fix in yoga

* Back to let

* Returns inner pointer

* Trivial change to kick the CI
This commit is contained in:
Adlai Holler 2018-09-19 11:23:19 -07:00 committed by Huy Nguyen
parent cd608c9b18
commit ceed2d2008
10 changed files with 99 additions and 124 deletions

View File

@ -148,7 +148,6 @@
6947B0C01E36B4E30007C478 /* ASStackUnpositionedLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6947B0BD1E36B4E30007C478 /* ASStackUnpositionedLayout.mm */; }; 6947B0C01E36B4E30007C478 /* ASStackUnpositionedLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6947B0BD1E36B4E30007C478 /* ASStackUnpositionedLayout.mm */; };
6947B0C31E36B5040007C478 /* ASStackPositionedLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 6947B0C11E36B5040007C478 /* ASStackPositionedLayout.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6947B0C31E36B5040007C478 /* ASStackPositionedLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 6947B0C11E36B5040007C478 /* ASStackPositionedLayout.h */; settings = {ATTRIBUTES = (Private, ); }; };
6947B0C51E36B5040007C478 /* ASStackPositionedLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6947B0C21E36B5040007C478 /* ASStackPositionedLayout.mm */; }; 6947B0C51E36B5040007C478 /* ASStackPositionedLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6947B0C21E36B5040007C478 /* ASStackPositionedLayout.mm */; };
6959433F1D70815300B0EE1F /* ASDisplayNodeLayout.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6959433C1D70815300B0EE1F /* ASDisplayNodeLayout.mm */; };
695943401D70815300B0EE1F /* ASDisplayNodeLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 6959433D1D70815300B0EE1F /* ASDisplayNodeLayout.h */; settings = {ATTRIBUTES = (Private, ); }; }; 695943401D70815300B0EE1F /* ASDisplayNodeLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 6959433D1D70815300B0EE1F /* ASDisplayNodeLayout.h */; settings = {ATTRIBUTES = (Private, ); }; };
695BE2551DC1245C008E6EA5 /* ASWrapperSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 695BE2541DC1245C008E6EA5 /* ASWrapperSpecSnapshotTests.mm */; }; 695BE2551DC1245C008E6EA5 /* ASWrapperSpecSnapshotTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 695BE2541DC1245C008E6EA5 /* ASWrapperSpecSnapshotTests.mm */; };
696F01EC1DD2AF450049FBD5 /* ASEventLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 696F01EA1DD2AF450049FBD5 /* ASEventLog.h */; settings = {ATTRIBUTES = (Public, ); }; }; 696F01EC1DD2AF450049FBD5 /* ASEventLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 696F01EA1DD2AF450049FBD5 /* ASEventLog.h */; settings = {ATTRIBUTES = (Public, ); }; };
@ -705,7 +704,6 @@
6947B0BD1E36B4E30007C478 /* ASStackUnpositionedLayout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASStackUnpositionedLayout.mm; sourceTree = "<group>"; }; 6947B0BD1E36B4E30007C478 /* ASStackUnpositionedLayout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASStackUnpositionedLayout.mm; sourceTree = "<group>"; };
6947B0C11E36B5040007C478 /* ASStackPositionedLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASStackPositionedLayout.h; sourceTree = "<group>"; }; 6947B0C11E36B5040007C478 /* ASStackPositionedLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASStackPositionedLayout.h; sourceTree = "<group>"; };
6947B0C21E36B5040007C478 /* ASStackPositionedLayout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASStackPositionedLayout.mm; sourceTree = "<group>"; }; 6947B0C21E36B5040007C478 /* ASStackPositionedLayout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASStackPositionedLayout.mm; sourceTree = "<group>"; };
6959433C1D70815300B0EE1F /* ASDisplayNodeLayout.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASDisplayNodeLayout.mm; sourceTree = "<group>"; };
6959433D1D70815300B0EE1F /* ASDisplayNodeLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDisplayNodeLayout.h; sourceTree = "<group>"; }; 6959433D1D70815300B0EE1F /* ASDisplayNodeLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASDisplayNodeLayout.h; sourceTree = "<group>"; };
695BE2541DC1245C008E6EA5 /* ASWrapperSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASWrapperSpecSnapshotTests.mm; sourceTree = "<group>"; }; 695BE2541DC1245C008E6EA5 /* ASWrapperSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASWrapperSpecSnapshotTests.mm; sourceTree = "<group>"; };
696F01EA1DD2AF450049FBD5 /* ASEventLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASEventLog.h; sourceTree = "<group>"; }; 696F01EA1DD2AF450049FBD5 /* ASEventLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASEventLog.h; sourceTree = "<group>"; };
@ -1490,7 +1488,6 @@
690BC8C020F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.m */, 690BC8C020F6D3490052A434 /* ASDisplayNodeCornerLayerDelegate.m */,
058D0A0C195D050800B7D73C /* ASDisplayNodeInternal.h */, 058D0A0C195D050800B7D73C /* ASDisplayNodeInternal.h */,
6959433D1D70815300B0EE1F /* ASDisplayNodeLayout.h */, 6959433D1D70815300B0EE1F /* ASDisplayNodeLayout.h */,
6959433C1D70815300B0EE1F /* ASDisplayNodeLayout.mm */,
CCA282C61E9EB64B0037E8B7 /* ASDisplayNodeTipState.h */, CCA282C61E9EB64B0037E8B7 /* ASDisplayNodeTipState.h */,
CCA282C71E9EB64B0037E8B7 /* ASDisplayNodeTipState.m */, CCA282C71E9EB64B0037E8B7 /* ASDisplayNodeTipState.m */,
68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */, 68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */,
@ -2497,7 +2494,6 @@
DB78412E1C6BCE1600A9E2B4 /* _ASTransitionContext.m in Sources */, DB78412E1C6BCE1600A9E2B4 /* _ASTransitionContext.m in Sources */,
B350620B1B010EFD0018CF92 /* ASTableView.mm in Sources */, B350620B1B010EFD0018CF92 /* ASTableView.mm in Sources */,
B350620E1B010EFD0018CF92 /* ASTextNode.mm in Sources */, B350620E1B010EFD0018CF92 /* ASTextNode.mm in Sources */,
6959433F1D70815300B0EE1F /* ASDisplayNodeLayout.mm in Sources */,
68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.m in Sources */, 68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.m in Sources */,
CC034A141E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.m in Sources */, CC034A141E649F1300626263 /* AsyncDisplayKit+IGListKitMethods.m in Sources */,
509E68661B3AEDD7009B9150 /* CoreGraphics+ASConvenience.m in Sources */, 509E68661B3AEDD7009B9150 /* CoreGraphics+ASConvenience.m in Sources */,

View File

@ -49,6 +49,7 @@
- Small optimization to the layout spec & yoga layout systems by eliminating array copies. [Adlai Holler](https://github.com/Adlai-Holler) - Small optimization to the layout spec & yoga layout systems by eliminating array copies. [Adlai Holler](https://github.com/Adlai-Holler)
- Optimize layout process by removing `ASRectMap`. [Adlai Holler](https://github.com/Adlai-Holler) - Optimize layout process by removing `ASRectMap`. [Adlai Holler](https://github.com/Adlai-Holler)
- Remove necessity to use view to access rangeController in ASTableNode, ASCollectionNode. [Michael Schneider](https://github.com/maicki) - Remove necessity to use view to access rangeController in ASTableNode, ASCollectionNode. [Michael Schneider](https://github.com/maicki)
- Remove display node's reliance on shared_ptr. [Adlai Holler](https://github.com/Adlai-Holler)
## 2.7 ## 2.7
- Fix pager node for interface coalescing. [Max Wang](https://github.com/wsdwsd0829) [#877](https://github.com/TextureGroup/Texture/pull/877) - Fix pager node for interface coalescing. [Max Wang](https://github.com/wsdwsd0829) [#877](https://github.com/TextureGroup/Texture/pull/877)

View File

@ -70,19 +70,19 @@
ASLayout *layout = nil; ASLayout *layout = nil;
NSUInteger version = _layoutVersion; NSUInteger version = _layoutVersion;
if (_calculatedDisplayNodeLayout->isValid(constrainedSize, parentSize, version)) { if (_calculatedDisplayNodeLayout.isValid(constrainedSize, parentSize, version)) {
ASDisplayNodeAssertNotNil(_calculatedDisplayNodeLayout->layout, @"-[ASDisplayNode layoutThatFits:parentSize:] _calculatedDisplayNodeLayout->layout should not be nil! %@", self); ASDisplayNodeAssertNotNil(_calculatedDisplayNodeLayout.layout, @"-[ASDisplayNode layoutThatFits:parentSize:] _calculatedDisplayNodeLayout.layout should not be nil! %@", self);
layout = _calculatedDisplayNodeLayout->layout; layout = _calculatedDisplayNodeLayout.layout;
} else if (_pendingDisplayNodeLayout != nullptr && _pendingDisplayNodeLayout->isValid(constrainedSize, parentSize, version)) { } else if (_pendingDisplayNodeLayout.isValid(constrainedSize, parentSize, version)) {
ASDisplayNodeAssertNotNil(_pendingDisplayNodeLayout->layout, @"-[ASDisplayNode layoutThatFits:parentSize:] _pendingDisplayNodeLayout->layout should not be nil! %@", self); ASDisplayNodeAssertNotNil(_pendingDisplayNodeLayout.layout, @"-[ASDisplayNode layoutThatFits:parentSize:] _pendingDisplayNodeLayout.layout should not be nil! %@", self);
layout = _pendingDisplayNodeLayout->layout; layout = _pendingDisplayNodeLayout.layout;
} else { } else {
// Create a pending display node layout for the layout pass // Create a pending display node layout for the layout pass
layout = [self calculateLayoutThatFits:constrainedSize layout = [self calculateLayoutThatFits:constrainedSize
restrictedToSize:self.style.size restrictedToSize:self.style.size
relativeToParentSize:parentSize]; relativeToParentSize:parentSize];
as_log_verbose(ASLayoutLog(), "Established pending layout for %@ in %s", self, sel_getName(_cmd)); as_log_verbose(ASLayoutLog(), "Established pending layout for %@ in %s", self, sel_getName(_cmd));
_pendingDisplayNodeLayout = std::make_shared<ASDisplayNodeLayout>(layout, constrainedSize, parentSize, version); _pendingDisplayNodeLayout = ASDisplayNodeLayout(layout, constrainedSize, parentSize,version);
ASDisplayNodeAssertNotNil(layout, @"-[ASDisplayNode layoutThatFits:parentSize:] newly calculated layout should not be nil! %@", self); ASDisplayNodeAssertNotNil(layout, @"-[ASDisplayNode layoutThatFits:parentSize:] newly calculated layout should not be nil! %@", self);
} }
@ -156,16 +156,16 @@ ASLayoutElementStyleExtensibilityForwarding
- (ASLayout *)calculatedLayout - (ASLayout *)calculatedLayout
{ {
ASDN::MutexLocker l(__instanceLock__); ASDN::MutexLocker l(__instanceLock__);
return _calculatedDisplayNodeLayout->layout; return _calculatedDisplayNodeLayout.layout;
} }
- (CGSize)calculatedSize - (CGSize)calculatedSize
{ {
ASDN::MutexLocker l(__instanceLock__); ASDN::MutexLocker l(__instanceLock__);
if (_pendingDisplayNodeLayout != nullptr && _pendingDisplayNodeLayout->isValid(_layoutVersion)) { if (_pendingDisplayNodeLayout.isValid(_layoutVersion)) {
return _pendingDisplayNodeLayout->layout.size; return _pendingDisplayNodeLayout.layout.size;
} }
return _calculatedDisplayNodeLayout->layout.size; return _calculatedDisplayNodeLayout.layout.size;
} }
- (ASSizeRange)constrainedSizeForCalculatedLayout - (ASSizeRange)constrainedSizeForCalculatedLayout
@ -177,10 +177,10 @@ ASLayoutElementStyleExtensibilityForwarding
- (ASSizeRange)_locked_constrainedSizeForCalculatedLayout - (ASSizeRange)_locked_constrainedSizeForCalculatedLayout
{ {
ASAssertLocked(__instanceLock__); ASAssertLocked(__instanceLock__);
if (_pendingDisplayNodeLayout != nullptr && _pendingDisplayNodeLayout->isValid(_layoutVersion)) { if (_pendingDisplayNodeLayout.isValid(_layoutVersion)) {
return _pendingDisplayNodeLayout->constrainedSize; return _pendingDisplayNodeLayout.constrainedSize;
} }
return _calculatedDisplayNodeLayout->constrainedSize; return _calculatedDisplayNodeLayout.constrainedSize;
} }
@end @end
@ -246,10 +246,10 @@ ASLayoutElementStyleExtensibilityForwarding
// Figure out constrainedSize to use // Figure out constrainedSize to use
ASSizeRange constrainedSize = ASSizeRangeMake(boundsSizeForLayout); ASSizeRange constrainedSize = ASSizeRangeMake(boundsSizeForLayout);
if (_pendingDisplayNodeLayout != nullptr) { if (_pendingDisplayNodeLayout.layout != nil) {
constrainedSize = _pendingDisplayNodeLayout->constrainedSize; constrainedSize = _pendingDisplayNodeLayout.constrainedSize;
} else if (_calculatedDisplayNodeLayout->layout != nil) { } else if (_calculatedDisplayNodeLayout.layout != nil) {
constrainedSize = _calculatedDisplayNodeLayout->constrainedSize; constrainedSize = _calculatedDisplayNodeLayout.constrainedSize;
} }
__instanceLock__.unlock(); __instanceLock__.unlock();
@ -305,20 +305,20 @@ ASLayoutElementStyleExtensibilityForwarding
// Prefer a newer and not yet applied _pendingDisplayNodeLayout over _calculatedDisplayNodeLayout // Prefer a newer and not yet applied _pendingDisplayNodeLayout over _calculatedDisplayNodeLayout
// If there is no such _pending, check if _calculated is valid to reuse (avoiding recalculation below). // If there is no such _pending, check if _calculated is valid to reuse (avoiding recalculation below).
BOOL pendingLayoutIsPreferred = NO; BOOL pendingLayoutIsPreferred = NO;
if (_pendingDisplayNodeLayout != nullptr && _pendingDisplayNodeLayout->isValid(_layoutVersion)) { if (_pendingDisplayNodeLayout.isValid(_layoutVersion)) {
NSUInteger calculatedVersion = _calculatedDisplayNodeLayout->version; NSUInteger calculatedVersion = _calculatedDisplayNodeLayout.version;
NSUInteger pendingVersion = _pendingDisplayNodeLayout->version; NSUInteger pendingVersion = _pendingDisplayNodeLayout.version;
if (pendingVersion > calculatedVersion) { if (pendingVersion > calculatedVersion) {
pendingLayoutIsPreferred = YES; // Newer _pending pendingLayoutIsPreferred = YES; // Newer _pending
} else if (pendingVersion == calculatedVersion } else if (pendingVersion == calculatedVersion
&& !ASSizeRangeEqualToSizeRange(_pendingDisplayNodeLayout->constrainedSize, && !ASSizeRangeEqualToSizeRange(_pendingDisplayNodeLayout.constrainedSize,
_calculatedDisplayNodeLayout->constrainedSize)) { _calculatedDisplayNodeLayout.constrainedSize)) {
pendingLayoutIsPreferred = YES; // _pending with a different constrained size pendingLayoutIsPreferred = YES; // _pending with a different constrained size
} }
} }
BOOL calculatedLayoutIsReusable = (_calculatedDisplayNodeLayout->isValid(_layoutVersion) BOOL calculatedLayoutIsReusable = (_calculatedDisplayNodeLayout.isValid(_layoutVersion)
&& (_calculatedDisplayNodeLayout->requestedLayoutFromAbove && (_calculatedDisplayNodeLayout.requestedLayoutFromAbove
|| CGSizeEqualToSize(_calculatedDisplayNodeLayout->layout.size, boundsSizeForLayout))); || CGSizeEqualToSize(_calculatedDisplayNodeLayout.layout.size, boundsSizeForLayout)));
if (!pendingLayoutIsPreferred && calculatedLayoutIsReusable) { if (!pendingLayoutIsPreferred && calculatedLayoutIsReusable) {
return; return;
} }
@ -341,15 +341,15 @@ ASLayoutElementStyleExtensibilityForwarding
} }
// Figure out previous and pending layouts for layout transition // Figure out previous and pending layouts for layout transition
std::shared_ptr<ASDisplayNodeLayout> nextLayout = _pendingDisplayNodeLayout; ASDisplayNodeLayout nextLayout = _pendingDisplayNodeLayout;
#define layoutSizeDifferentFromBounds !CGSizeEqualToSize(nextLayout->layout.size, boundsSizeForLayout) #define layoutSizeDifferentFromBounds !CGSizeEqualToSize(nextLayout.layout.size, boundsSizeForLayout)
// nextLayout was likely created by a call to layoutThatFits:, check if it is valid and can be applied. // nextLayout was likely created by a call to layoutThatFits:, check if it is valid and can be applied.
// If our bounds size is different than it, or invalid, recalculate. Use #define to avoid nullptr-> // If our bounds size is different than it, or invalid, recalculate. Use #define to avoid nullptr->
BOOL pendingLayoutApplicable = NO; BOOL pendingLayoutApplicable = NO;
if (nextLayout == nullptr) { if (nextLayout.layout == nil) {
as_log_verbose(ASLayoutLog(), "No pending layout."); as_log_verbose(ASLayoutLog(), "No pending layout.");
} else if (nextLayout->isValid(_layoutVersion) == NO) { } else if (!nextLayout.isValid(_layoutVersion)) {
as_log_verbose(ASLayoutLog(), "Pending layout is stale."); as_log_verbose(ASLayoutLog(), "Pending layout is stale.");
} else if (layoutSizeDifferentFromBounds) { } else if (layoutSizeDifferentFromBounds) {
as_log_verbose(ASLayoutLog(), "Pending layout size %@ doesn't match bounds size.", NSStringFromCGSize(nextLayout->layout.size)); as_log_verbose(ASLayoutLog(), "Pending layout size %@ doesn't match bounds size.", NSStringFromCGSize(nextLayout->layout.size));
@ -366,10 +366,10 @@ ASLayoutElementStyleExtensibilityForwarding
ASLayout *layout = [self calculateLayoutThatFits:constrainedSize ASLayout *layout = [self calculateLayoutThatFits:constrainedSize
restrictedToSize:self.style.size restrictedToSize:self.style.size
relativeToParentSize:boundsSizeForLayout]; relativeToParentSize:boundsSizeForLayout];
nextLayout = std::make_shared<ASDisplayNodeLayout>(layout, constrainedSize, boundsSizeForLayout, version); nextLayout = ASDisplayNodeLayout(layout, constrainedSize, boundsSizeForLayout, version);
// Now that the constrained size of pending layout might have been reused, the layout is useless // Now that the constrained size of pending layout might have been reused, the layout is useless
// Release it and any orphaned subnodes it retains // Release it and any orphaned subnodes it retains
_pendingDisplayNodeLayout = nullptr; _pendingDisplayNodeLayout.layout = nil;
} }
if (didCreateNewContext) { if (didCreateNewContext) {
@ -378,8 +378,8 @@ ASLayoutElementStyleExtensibilityForwarding
// If our new layout's desired size for self doesn't match current size, ask our parent to update it. // If our new layout's desired size for self doesn't match current size, ask our parent to update it.
// This can occur for either pre-calculated or newly-calculated layouts. // This can occur for either pre-calculated or newly-calculated layouts.
if (nextLayout->requestedLayoutFromAbove == NO if (nextLayout.requestedLayoutFromAbove == NO
&& CGSizeEqualToSize(boundsSizeForLayout, nextLayout->layout.size) == NO) { && CGSizeEqualToSize(boundsSizeForLayout, nextLayout.layout.size) == NO) {
as_log_verbose(ASLayoutLog(), "Layout size doesn't match bounds size. Requesting layout from above."); as_log_verbose(ASLayoutLog(), "Layout size doesn't match bounds size. Requesting layout from above.");
// The layout that we have specifies that this node (self) would like to be a different size // The layout that we have specifies that this node (self) would like to be a different size
// than it currently is. Because that size has been computed within the constrainedSize, we // than it currently is. Because that size has been computed within the constrainedSize, we
@ -387,7 +387,7 @@ ASLayoutElementStyleExtensibilityForwarding
// However, in some cases apps may manually interfere with this (setting a different bounds). // However, in some cases apps may manually interfere with this (setting a different bounds).
// In this case, we need to detect that we've already asked to be resized to match this // In this case, we need to detect that we've already asked to be resized to match this
// particular ASLayout object, and shouldn't loop asking again unless we have a different ASLayout. // particular ASLayout object, and shouldn't loop asking again unless we have a different ASLayout.
nextLayout->requestedLayoutFromAbove = YES; nextLayout.requestedLayoutFromAbove = YES;
{ {
ASDN::MutexUnlocker u(__instanceLock__); ASDN::MutexUnlocker u(__instanceLock__);
@ -396,11 +396,11 @@ ASLayoutElementStyleExtensibilityForwarding
// Update the layout's version here because _u_setNeedsLayoutFromAbove calls __setNeedsLayout which in turn increases _layoutVersion // Update the layout's version here because _u_setNeedsLayoutFromAbove calls __setNeedsLayout which in turn increases _layoutVersion
// Failing to do this will cause the layout to be invalid immediately // Failing to do this will cause the layout to be invalid immediately
nextLayout->version = _layoutVersion; nextLayout.version = _layoutVersion;
} }
// Prepare to transition to nextLayout // Prepare to transition to nextLayout
ASDisplayNodeAssertNotNil(nextLayout->layout, @"nextLayout->layout should not be nil! %@", self); ASDisplayNodeAssertNotNil(nextLayout.layout, @"nextLayout->layout should not be nil! %@", self);
_pendingLayoutTransition = [[ASLayoutTransition alloc] initWithNode:self _pendingLayoutTransition = [[ASLayoutTransition alloc] initWithNode:self
pendingLayout:nextLayout pendingLayout:nextLayout
previousLayout:_calculatedDisplayNodeLayout]; previousLayout:_calculatedDisplayNodeLayout];
@ -431,17 +431,16 @@ ASLayoutElementStyleExtensibilityForwarding
CGSize boundsSizeForLayout = ASCeilSizeValues(self.threadSafeBounds.size); CGSize boundsSizeForLayout = ASCeilSizeValues(self.threadSafeBounds.size);
// Checkout if constrained size of pending or calculated display node layout can be used // Checkout if constrained size of pending or calculated display node layout can be used
if (_pendingDisplayNodeLayout != nullptr if (_pendingDisplayNodeLayout.requestedLayoutFromAbove
&& (_pendingDisplayNodeLayout->requestedLayoutFromAbove || CGSizeEqualToSize(_pendingDisplayNodeLayout.layout.size, boundsSizeForLayout)) {
|| CGSizeEqualToSize(_pendingDisplayNodeLayout->layout.size, boundsSizeForLayout))) {
// We assume the size from the last returned layoutThatFits: layout was applied so use the pending display node // We assume the size from the last returned layoutThatFits: layout was applied so use the pending display node
// layout constrained size // layout constrained size
return _pendingDisplayNodeLayout->constrainedSize; return _pendingDisplayNodeLayout.constrainedSize;
} else if (_calculatedDisplayNodeLayout->layout != nil } else if (_calculatedDisplayNodeLayout.layout != nil
&& (_calculatedDisplayNodeLayout->requestedLayoutFromAbove && (_calculatedDisplayNodeLayout.requestedLayoutFromAbove
|| CGSizeEqualToSize(_calculatedDisplayNodeLayout->layout.size, boundsSizeForLayout))) { || CGSizeEqualToSize(_calculatedDisplayNodeLayout.layout.size, boundsSizeForLayout))) {
// We assume the _calculatedDisplayNodeLayout is still valid and the frame is not different // We assume the _calculatedDisplayNodeLayout is still valid and the frame is not different
return _calculatedDisplayNodeLayout->constrainedSize; return _calculatedDisplayNodeLayout.constrainedSize;
} else { } else {
// In this case neither the _pendingDisplayNodeLayout or the _calculatedDisplayNodeLayout constrained size can // In this case neither the _pendingDisplayNodeLayout or the _calculatedDisplayNodeLayout constrained size can
// be reused, so the current bounds is used. This is usual the case if a frame was set manually that differs to // be reused, so the current bounds is used. This is usual the case if a frame was set manually that differs to
@ -458,10 +457,10 @@ ASLayoutElementStyleExtensibilityForwarding
ASLayout *layout; ASLayout *layout;
{ {
ASDN::MutexLocker l(__instanceLock__); ASDN::MutexLocker l(__instanceLock__);
if (_calculatedDisplayNodeLayout->version < _layoutVersion) { if (_calculatedDisplayNodeLayout.version < _layoutVersion) {
return; return;
} }
layout = _calculatedDisplayNodeLayout->layout; layout = _calculatedDisplayNodeLayout.layout;
} }
for (ASDisplayNode *node in self.subnodes) { for (ASDisplayNode *node in self.subnodes) {
@ -654,10 +653,10 @@ ASLayoutElementStyleExtensibilityForwarding
// Update calculated layout // Update calculated layout
let previousLayout = _calculatedDisplayNodeLayout; let previousLayout = _calculatedDisplayNodeLayout;
let pendingLayout = std::make_shared<ASDisplayNodeLayout>(newLayout, let pendingLayout = ASDisplayNodeLayout(newLayout,
constrainedSize, constrainedSize,
constrainedSize.max, constrainedSize.max,
newLayoutVersion); newLayoutVersion);
[self _locked_setCalculatedDisplayNodeLayout:pendingLayout]; [self _locked_setCalculatedDisplayNodeLayout:pendingLayout];
// Setup pending layout transition for animation // Setup pending layout transition for animation
@ -869,7 +868,7 @@ ASLayoutElementStyleExtensibilityForwarding
{ {
ASAssertUnlocked(__instanceLock__); ASAssertUnlocked(__instanceLock__);
ASLayoutTransition *pendingLayoutTransition = nil; ASLayoutTransition *pendingLayoutTransition;
{ {
ASDN::MutexLocker l(__instanceLock__); ASDN::MutexLocker l(__instanceLock__);
pendingLayoutTransition = _pendingLayoutTransition; pendingLayoutTransition = _pendingLayoutTransition;
@ -918,7 +917,7 @@ ASLayoutElementStyleExtensibilityForwarding
} }
NSArray *subnodes = [self subnodes]; NSArray *subnodes = [self subnodes];
NSArray *sublayouts = _calculatedDisplayNodeLayout->layout.sublayouts; NSArray *sublayouts = _calculatedDisplayNodeLayout.layout.sublayouts;
let currentSubnodes = [[NSHashTable alloc] initWithOptions:NSHashTableObjectPointerPersonality let currentSubnodes = [[NSHashTable alloc] initWithOptions:NSHashTableObjectPointerPersonality
capacity:subnodes.count]; capacity:subnodes.count];
@ -970,8 +969,7 @@ ASLayoutElementStyleExtensibilityForwarding
if (_placeholderEnabled && !_placeholderImage && [self _locked_displaysAsynchronously]) { if (_placeholderEnabled && !_placeholderImage && [self _locked_displaysAsynchronously]) {
// Zero-sized nodes do not require a placeholder. // Zero-sized nodes do not require a placeholder.
ASLayout *layout = _calculatedDisplayNodeLayout->layout; CGSize layoutSize = _calculatedDisplayNodeLayout.layout.size;
CGSize layoutSize = (layout ? layout.size : CGSizeZero);
if (layoutSize.width * layoutSize.height <= 0.0) { if (layoutSize.width * layoutSize.height <= 0.0) {
return; return;
} }
@ -995,26 +993,26 @@ ASLayoutElementStyleExtensibilityForwarding
_pendingLayoutTransition = nil; _pendingLayoutTransition = nil;
} }
- (void)_setCalculatedDisplayNodeLayout:(std::shared_ptr<ASDisplayNodeLayout>)displayNodeLayout - (void)_setCalculatedDisplayNodeLayout:(const ASDisplayNodeLayout &)displayNodeLayout
{ {
ASDN::MutexLocker l(__instanceLock__); ASDN::MutexLocker l(__instanceLock__);
[self _locked_setCalculatedDisplayNodeLayout:displayNodeLayout]; [self _locked_setCalculatedDisplayNodeLayout:displayNodeLayout];
} }
- (void)_locked_setCalculatedDisplayNodeLayout:(std::shared_ptr<ASDisplayNodeLayout>)displayNodeLayout - (void)_locked_setCalculatedDisplayNodeLayout:(const ASDisplayNodeLayout &)displayNodeLayout
{ {
ASAssertLocked(__instanceLock__); ASAssertLocked(__instanceLock__);
ASDisplayNodeAssertTrue(displayNodeLayout->layout.layoutElement == self); ASDisplayNodeAssertTrue(displayNodeLayout.layout.layoutElement == self);
ASDisplayNodeAssertTrue(displayNodeLayout->layout.size.width >= 0.0); ASDisplayNodeAssertTrue(displayNodeLayout.layout.size.width >= 0.0);
ASDisplayNodeAssertTrue(displayNodeLayout->layout.size.height >= 0.0); ASDisplayNodeAssertTrue(displayNodeLayout.layout.size.height >= 0.0);
_calculatedDisplayNodeLayout = displayNodeLayout;
// Flatten the layout if it wasn't done before (@see -calculateLayoutThatFits:). // Flatten the layout if it wasn't done before (@see -calculateLayoutThatFits:).
if ([ASDisplayNode shouldStoreUnflattenedLayouts]) { if ([ASDisplayNode shouldStoreUnflattenedLayouts]) {
_unflattenedLayout = displayNodeLayout->layout; _unflattenedLayout = _calculatedDisplayNodeLayout.layout;
displayNodeLayout->layout = [_unflattenedLayout filteredNodeLayoutTree]; _calculatedDisplayNodeLayout.layout = [_unflattenedLayout filteredNodeLayoutTree];
} }
_calculatedDisplayNodeLayout = displayNodeLayout;
} }
@end @end

View File

@ -209,7 +209,7 @@
// For the root node in a Yoga tree, make sure to preserve the constrainedSize originally provided. // For the root node in a Yoga tree, make sure to preserve the constrainedSize originally provided.
// This will be used for all relayouts triggered by children, since they escalate to root. // This will be used for all relayouts triggered by children, since they escalate to root.
ASSizeRange range = parentNode ? ASSizeRangeUnconstrained : self.constrainedSizeForCalculatedLayout; ASSizeRange range = parentNode ? ASSizeRangeUnconstrained : self.constrainedSizeForCalculatedLayout;
_pendingDisplayNodeLayout = std::make_shared<ASDisplayNodeLayout>(layout, range, parentSize, _layoutVersion); _pendingDisplayNodeLayout = ASDisplayNodeLayout(layout, range, parentSize, _layoutVersion);
} }
} }

View File

@ -292,8 +292,6 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
_primitiveTraitCollection = ASPrimitiveTraitCollectionMakeDefault(); _primitiveTraitCollection = ASPrimitiveTraitCollectionMakeDefault();
_calculatedDisplayNodeLayout = std::make_shared<ASDisplayNodeLayout>();
_pendingDisplayNodeLayout = nullptr;
_layoutVersion = 1; _layoutVersion = 1;
_defaultLayoutTransitionDuration = 0.2; _defaultLayoutTransitionDuration = 0.2;
@ -3812,21 +3810,19 @@ ASDISPLAYNODE_INLINE BOOL subtreeIsRasterized(ASDisplayNode *node) {
[props addObject:@{ @"layoutVersion": @(_layoutVersion.load()) }]; [props addObject:@{ @"layoutVersion": @(_layoutVersion.load()) }];
[props addObject:@{ @"bounds": [NSValue valueWithCGRect:self.bounds] }]; [props addObject:@{ @"bounds": [NSValue valueWithCGRect:self.bounds] }];
if (_calculatedDisplayNodeLayout != nullptr) { if (_calculatedDisplayNodeLayout.layout) {
ASDisplayNodeLayout c = *_calculatedDisplayNodeLayout; [props addObject:@{ @"calculatedLayout": _calculatedDisplayNodeLayout.layout }];
[props addObject:@{ @"calculatedLayout": c.layout }]; [props addObject:@{ @"calculatedVersion": @(_calculatedDisplayNodeLayout.version) }];
[props addObject:@{ @"calculatedVersion": @(c.version) }]; [props addObject:@{ @"calculatedConstrainedSize" : NSStringFromASSizeRange(_calculatedDisplayNodeLayout.constrainedSize) }];
[props addObject:@{ @"calculatedConstrainedSize" : NSStringFromASSizeRange(c.constrainedSize) }]; if (_calculatedDisplayNodeLayout.requestedLayoutFromAbove) {
if (c.requestedLayoutFromAbove) {
[props addObject:@{ @"calculatedRequestedLayoutFromAbove": @"YES" }]; [props addObject:@{ @"calculatedRequestedLayoutFromAbove": @"YES" }];
} }
} }
if (_pendingDisplayNodeLayout != nullptr) { if (_pendingDisplayNodeLayout.layout) {
ASDisplayNodeLayout p = *_pendingDisplayNodeLayout; [props addObject:@{ @"pendingLayout": _pendingDisplayNodeLayout.layout }];
[props addObject:@{ @"pendingLayout": p.layout }]; [props addObject:@{ @"pendingVersion": @(_pendingDisplayNodeLayout.version) }];
[props addObject:@{ @"pendingVersion": @(p.version) }]; [props addObject:@{ @"pendingConstrainedSize" : NSStringFromASSizeRange(_pendingDisplayNodeLayout.constrainedSize) }];
[props addObject:@{ @"pendingConstrainedSize" : NSStringFromASSizeRange(p.constrainedSize) }]; if (_pendingDisplayNodeLayout.requestedLayoutFromAbove) {
if (p.requestedLayoutFromAbove) {
[props addObject:@{ @"pendingRequestedLayoutFromAbove": (id)kCFNull }]; [props addObject:@{ @"pendingRequestedLayoutFromAbove": (id)kCFNull }];
} }
} }

View File

@ -164,8 +164,8 @@ AS_EXTERN NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimest
std::atomic<int32_t> _pendingTransitionID; std::atomic<int32_t> _pendingTransitionID;
ASLayoutTransition *_pendingLayoutTransition; ASLayoutTransition *_pendingLayoutTransition;
std::shared_ptr<ASDisplayNodeLayout> _calculatedDisplayNodeLayout; ASDisplayNodeLayout _calculatedDisplayNodeLayout;
std::shared_ptr<ASDisplayNodeLayout> _pendingDisplayNodeLayout; ASDisplayNodeLayout _pendingDisplayNodeLayout;
/// Sentinel for layout data. Incremented when we get -setNeedsLayout / -invalidateCalculatedLayout. /// Sentinel for layout data. Incremented when we get -setNeedsLayout / -invalidateCalculatedLayout.
/// Starts at 1. /// Starts at 1.

View File

@ -43,10 +43,16 @@ struct ASDisplayNodeLayout {
/** /**
* Returns whether this is valid for a given version * Returns whether this is valid for a given version
*/ */
BOOL isValid(NSUInteger version); BOOL isValid(NSUInteger versionArg) {
return layout != nil && version >= versionArg;
}
/** /**
* Returns whether this is valid for a given constrained size, parent size, and version * Returns whether this is valid for a given constrained size, parent size, and version
*/ */
BOOL isValid(ASSizeRange constrainedSize, CGSize parentSize, NSUInteger version); BOOL isValid(ASSizeRange theConstrainedSize, CGSize theParentSize, NSUInteger versionArg) {
return isValid(versionArg)
&& CGSizeEqualToSize(parentSize, theParentSize)
&& ASSizeRangeEqualToSizeRange(constrainedSize, theConstrainedSize);
}
}; };

View File

@ -1,22 +0,0 @@
//
// ASDisplayNodeLayout.mm
// Texture
//
// Copyright (c) Facebook, Inc. and its affiliates. All rights reserved.
// Changes after 4/13/2017 are: Copyright (c) Pinterest, Inc. All rights reserved.
// Licensed under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0
//
#import <AsyncDisplayKit/ASDisplayNodeLayout.h>
BOOL ASDisplayNodeLayout::isValid(NSUInteger versionArg)
{
return layout != nil && version >= versionArg;
}
BOOL ASDisplayNodeLayout::isValid(ASSizeRange theConstrainedSize, CGSize theParentSize, NSUInteger versionArg)
{
return isValid(versionArg)
&& CGSizeEqualToSize(parentSize, theParentSize)
&& ASSizeRangeEqualToSizeRange(constrainedSize, theConstrainedSize);
}

View File

@ -15,8 +15,6 @@
#import <AsyncDisplayKit/ASDisplayNode.h> #import <AsyncDisplayKit/ASDisplayNode.h>
#import <AsyncDisplayKit/ASLayoutSpec.h> #import <AsyncDisplayKit/ASLayoutSpec.h>
#import <memory>
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
#pragma mark - ASLayoutElementTransition #pragma mark - ASLayoutElementTransition
@ -52,12 +50,12 @@ AS_SUBCLASSING_RESTRICTED
/** /**
* Previous layout to transition from * Previous layout to transition from
*/ */
@property (nonatomic, readonly) std::shared_ptr<ASDisplayNodeLayout> previousLayout; @property (nonatomic, readonly) const ASDisplayNodeLayout &previousLayout NS_RETURNS_INNER_POINTER;
/** /**
* Pending layout to transition to * Pending layout to transition to
*/ */
@property (nonatomic, readonly) std::shared_ptr<ASDisplayNodeLayout> pendingLayout; @property (nonatomic, readonly) const ASDisplayNodeLayout &pendingLayout NS_RETURNS_INNER_POINTER;
/** /**
* Returns if the layout transition needs to happen synchronously * Returns if the layout transition needs to happen synchronously
@ -68,8 +66,8 @@ AS_SUBCLASSING_RESTRICTED
* Returns a newly initialized layout transition * Returns a newly initialized layout transition
*/ */
- (instancetype)initWithNode:(ASDisplayNode *)node - (instancetype)initWithNode:(ASDisplayNode *)node
pendingLayout:(std::shared_ptr<ASDisplayNodeLayout>)pendingLayout pendingLayout:(const ASDisplayNodeLayout &)pendingLayout
previousLayout:(std::shared_ptr<ASDisplayNodeLayout>)previousLayout NS_DESIGNATED_INITIALIZER; previousLayout:(const ASDisplayNodeLayout &)previousLayout NS_DESIGNATED_INITIALIZER;
/** /**
* Insert and remove subnodes that were added or removed between the previousLayout and the pendingLayout * Insert and remove subnodes that were added or removed between the previousLayout and the pendingLayout

View File

@ -60,11 +60,13 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) {
NSArray<ASDisplayNode *> *_removedSubnodes; NSArray<ASDisplayNode *> *_removedSubnodes;
std::vector<NSUInteger> _insertedSubnodePositions; std::vector<NSUInteger> _insertedSubnodePositions;
std::vector<std::pair<ASDisplayNode *, NSUInteger>> _subnodeMoves; std::vector<std::pair<ASDisplayNode *, NSUInteger>> _subnodeMoves;
ASDisplayNodeLayout _pendingLayout;
ASDisplayNodeLayout _previousLayout;
} }
- (instancetype)initWithNode:(ASDisplayNode *)node - (instancetype)initWithNode:(ASDisplayNode *)node
pendingLayout:(std::shared_ptr<ASDisplayNodeLayout>)pendingLayout pendingLayout:(const ASDisplayNodeLayout &)pendingLayout
previousLayout:(std::shared_ptr<ASDisplayNodeLayout>)previousLayout previousLayout:(const ASDisplayNodeLayout &)previousLayout
{ {
self = [super init]; self = [super init];
if (self) { if (self) {
@ -80,7 +82,7 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) {
- (BOOL)isSynchronous - (BOOL)isSynchronous
{ {
ASDN::MutexSharedLocker l(__instanceLock__); ASDN::MutexSharedLocker l(__instanceLock__);
return !ASLayoutCanTransitionAsynchronous(_pendingLayout->layout); return !ASLayoutCanTransitionAsynchronous(_pendingLayout.layout);
} }
- (void)commitTransition - (void)commitTransition
@ -156,8 +158,8 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) {
// Create an activity even if no subnodes affected. // Create an activity even if no subnodes affected.
as_activity_create_for_scope("Calculate subnode operations"); as_activity_create_for_scope("Calculate subnode operations");
ASLayout *previousLayout = _previousLayout->layout; ASLayout *previousLayout = _previousLayout.layout;
ASLayout *pendingLayout = _pendingLayout->layout; ASLayout *pendingLayout = _pendingLayout.layout;
if (previousLayout) { if (previousLayout) {
#if AS_IG_LIST_KIT #if AS_IG_LIST_KIT
@ -226,9 +228,9 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) {
{ {
ASDN::MutexSharedLocker l(__instanceLock__); ASDN::MutexSharedLocker l(__instanceLock__);
if ([key isEqualToString:ASTransitionContextFromLayoutKey]) { if ([key isEqualToString:ASTransitionContextFromLayoutKey]) {
return _previousLayout->layout; return _previousLayout.layout;
} else if ([key isEqualToString:ASTransitionContextToLayoutKey]) { } else if ([key isEqualToString:ASTransitionContextToLayoutKey]) {
return _pendingLayout->layout; return _pendingLayout.layout;
} else { } else {
return nil; return nil;
} }
@ -238,9 +240,9 @@ static inline BOOL ASLayoutCanTransitionAsynchronous(ASLayout *layout) {
{ {
ASDN::MutexSharedLocker l(__instanceLock__); ASDN::MutexSharedLocker l(__instanceLock__);
if ([key isEqualToString:ASTransitionContextFromLayoutKey]) { if ([key isEqualToString:ASTransitionContextFromLayoutKey]) {
return _previousLayout->constrainedSize; return _previousLayout.constrainedSize;
} else if ([key isEqualToString:ASTransitionContextToLayoutKey]) { } else if ([key isEqualToString:ASTransitionContextToLayoutKey]) {
return _pendingLayout->constrainedSize; return _pendingLayout.constrainedSize;
} else { } else {
return ASSizeRangeMake(CGSizeZero, CGSizeZero); return ASSizeRangeMake(CGSizeZero, CGSizeZero);
} }