This reverts commit 2e9858837251cf16c9ffd19ba2eaeaa1012c8977 (#751).
The reason we can't wait for the coming CA's layout pass is that cell node visibility events occur before the pass, at which time the cell's subnodes don't have correct frames for impression tracking.
The root cause of this problem is that, right now, cell node visible states are set by ASRangeController well before the layout pass of the hosting collection/table view. That means we're "jumping the gun". The more I think about this, the more I agree with @Adlai-Holler that we need to treat visible state differently. That is, a node should only be visible (and thus get visibility events) after it's fully loaded, it's view/layer attached to the hierarchy and laid out by a CA transaction. In other words, at the end of the CA layout pass. Such change needs time and effort to be thoroughly reviewed and tested. Until then, let's roll with this fix.
- After #706, a layout pass is forced on an ASM-enabled node that enters preload state to make sure that its subnodes can start preloading as well. However, when the node is visible, a (coalesced, thus more efficient) layout pass will be triggered by CA soon anyways, so rely on it instead.
* Add "ASGraphicsContext" to skip copying our rendered images
* Zero the buffer before making a context
* Update license header
* Update dangerfile
* Make it a runtime flag
* Restore GState for good measure
* Free buffer if end without image
* Enable the experiment, and cut out the middle-man
* Fix typo
* Make our async deallocation functions take a double pointer, so we can be sure we've released before the queue drains
* Make it a class property
* Fix the return type
* Use a locker
* Improve release notes
* Clear ivar after scheduling for main thread deallocation
After scheduling the ivar for main thread deallocation we have clear out the ivar, otherwise we can run into a race condition where the main queue is drained earlier than this node is deallocated and the ivar is still deallocated on a background thread
* First clear and than schedule
* [ASCornerRounding] Initial (untested) implementation of ASCornerRounding features.
* [ASCornerRounding] Working version of both clip corners and precomposited corners.
* [ASCornerRounding] Improve factoring and documentation of corner rounding features.
* [ASCornerRounding] Some final fixups.
* Add entry to changelog for .cornerRoundingType
* [Yoga] Add insertYogaNode:atIndex: method. Improve handling of relayouts.
* Add new "version" parameter to Yoga initialization of ASDisplayNodeLayout C++ struct.
After consulting Apple documentation and working with some a11y experts,
we've found that aggregating objects that have a11y labels but are not
themselves interactable is significantly preferred for these users.
It makes it much quicker to navigate scrolling content if VoiceOver only
stops to select entire cells, and then allows drilling down into the cell
to select individual components. This implementation achieves that behavior.
We should consider enabling isAccessibilityContainer by default on ASCellNode.
This would be an improvement for 95% of a11y use cases. Aggregation can be
enabled or disabled on any node.
With these changes, I'd also like to propose that we move ASNodeController
out of Beta (renaming the files without +Beta). Let me know what you think!
Because we don't support ASNodeController directly in ASCV / ASTV, it is still
important to allow flipping the ownership in certain cases (in particular, for
root CellNodeController objects that should follow the lifecycle of the
ASCellNode rather than owning the ASCellNode).
* Be more aggressive at invalidating layouts during transitions, add a debug method, fix some build errors when verbose logging
* Add a changelog entry
* Fix infinite layout loop
- The problem will occur if a node does either of the followings:
1. Keeps using a stale pending layout over a calculated layout
2. Doesn't update the next layout's version after calling _setNeedsLayoutFromAbove.
* Update CHANGELOG
This makes it much easier to use the ASCoreAnimationExtras method which offers by
far the most efficient way to display a stretchable image.
In the future, we should move that function to UIImage+ASConvenience or another
header where it can be more easily found and enjoyed!
This was originally added for ASCollectionNode and ASTableNode preloading to work
as intended when nested inside of another ASRangeController-powered node. Indeed,
it is still necessary to trigger layout on these UIKit-backed components in order
for their own ASRangeControllers to start preparing content within them.
However, unlike the comment suggests, it is *not* necessary to do this for image
nodes. ASNetworkImageNode has only one .URL, and does not use the .bounds or
.calculatedLayout at all during loading. Even the ASMultiplexImageNode does not
use the .bounds, and the ASMapNode uses .calculatedLayout instead of .bounds.
This change has important performance benefits. In particular, it avoids
layouts that would occur on the main thread, often including text sizing,
and also can result in redundant layout passes (even during a layout pass that
triggers a node to enter the preload range, it may force its own layout early).
It would be great to test this change with Pinterest to confirm its safety, but
based on a full audit of the framework codebase, the only possibility that I
see for a regression is if app implementations of -didEnterPreloadState make
direct use of .bounds instead of .calculatedLayout (which is easy to fix).
This has one important benefit: fixing the stretching behavior of spacer nodes.
In addition, it should help efficiency of Yoga and certainly minimize calls
to layoutThatFits:.
Next up for Yoga is a mostly-red diff, deleting the non-Contiguous code branches.
* [Yoga] Rewrite YOGA_TREE_CONTIGUOUS mode with support for mixing with ASLayoutSpec.
After experimentation with the ASYogaLayoutSpec (or non-contiguous) approach to
integrating Yoga, test results and feedback from the authors of Yoga have shown
that this approach can't be made completely correct,
There are issues with some of the features required to represent Web-style
flexbox; in particular: padding, margins, and border handling have varience.
This diff is a first step towards a truly correct and elegant implementation of
Yoga integration with Texture. In addition to reducing the footprint of
the integration, which is an explicit goal of work at this stage, these changes
already support improved behavior - including mixing between ASLayoutSpecs
even as subnodes of Yoga layout-driven nodes, in addition to above them. Yoga
may be used for any set of nodes.
Because Yoga usage is limited at this time, it's safe to merge this diff and
further improvements will be refinements in this direction.
* [ASDKgram] Add Yoga layout implementation for PhotoCellNode.
* [Yoga] Final fixes for the upgraded implementation of the Contiguous layout mode.
* [Yoga] Add CHANGELOG.md entry and fix for Yoga rounding to screen scale.
* [Yoga] Minor cleanup to remove old comments and generalize utility methods.
* Small changes required by the layout debugger
- `ASDisplayNode` can be told to not flatten its layout immediately but later on. The unflattened layout is also stored in a separate property. It's needed for inspecting not only display nodes but also layout specs used to compute a layout tree.
- `ASLayout` can be told to always retain its sublayout elements. This is needed especially for layout specs since they are usually not retained after an ASLayout was computed.
* Update CHANGELOG
* Address comments
* [Yoga] Implement ASYogaLayoutSpec, an experimental alternative to full-tree integration.
This approach allows us to avoid any ASDisplayNode.mm integration points.
However, it is not yet proven to be possible to achieve correctness with this approach.
The entry point (to start calculating), and the measurement function inputs, lack
the full expressiveness of ASSizeRange; we need to make sure that workarounds like
using style.minSize are successful in simulating the behavior of a full Yoga tree.
* [Yoga] Fix file comments, move towards <ASLayoutElement> support.
* [Yoga] Important fix for simplified, non-contiguous Yoga integration.
* [Yoga] Complete implementation of manual memory management (__bridge_transfer, YGNodeFree)
* [ASDisplayNode] Convert isSynchronous to an Objective-C atomic BOOL.
This reduces lock contention, and should also fix a very rarely seen deadlock.
* [ASDisplayNode] Implement a std::atomic-based flag system for superb performance
Although Objective-C atomics are equally fast, or better that std::atomic when
access through method calls, for the most intense use cases it is best to avoid
method calls entirely.
In ASDisplayNode, we could benefit significantly from avoiding both method calls
(already true today) but also avoid locking the mutex, for both CPU and contention
gains.
There will still be many methods that need locking for transactional
consistency - however, there are currently dozens of accessor methods that could
avoid frequent lock / unlock cycles with use of atomics, and other usages of the
ivars directly where locking could be delayed until after early-return conditions
are checked and passed.