Skip to content

Commit 47e2acd

Browse files
committed
add a separate check for this special case
1 parent 9c730fc commit 47e2acd

File tree

2 files changed

+11
-6
lines changed

2 files changed

+11
-6
lines changed

Source/ASDisplayNode.mm

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2104,7 +2104,7 @@ - (void)_insertSubnode:(ASDisplayNode *)subnode atSubnodeIndex:(NSInteger)subnod
21042104
ASDisplayNodeFailAssert(@"Cannot add a view-backed node as a subnode of a layer-backed node. Supernode: %@, subnode: %@", self, subnode);
21052105
return;
21062106
}
2107-
2107+
21082108
BOOL isRasterized = subtreeIsRasterized(self);
21092109
if (isRasterized && subnode.nodeLoaded) {
21102110
ASDisplayNodeFailAssert(@"Cannot add loaded node %@ to rasterized subtree of node %@", ASObjectDescriptionMakeTiny(subnode), ASObjectDescriptionMakeTiny(self));
@@ -2114,13 +2114,18 @@ - (void)_insertSubnode:(ASDisplayNode *)subnode atSubnodeIndex:(NSInteger)subnod
21142114
__instanceLock__.lock();
21152115
NSUInteger subnodesCount = _subnodes.count;
21162116
__instanceLock__.unlock();
2117-
2118-
// If the subnodeIndex is out of bounds OR it will be once we call [subnode removeFromSupernode], exit early
2119-
if (subnodeIndex > subnodesCount || subnodeIndex < 0 || (subnode.supernode == self && subnodeIndex >= subnodesCount)) {
2117+
2118+
if (subnodeIndex > subnodesCount || subnodeIndex < 0) {
21202119
ASDisplayNodeFailAssert(@"Cannot insert a subnode at index %ld. Count is %ld", (long)subnodeIndex, (long)subnodesCount);
21212120
return;
21222121
}
2123-
2122+
2123+
// Check if subnode is already a in _subnodes. If so make sure the subnodeIndex will not be out of bounds once we call [subnode removeFromSupernode]
2124+
if (subnode.supernode == self && subnodeIndex >= subnodesCount) {
2125+
ASDisplayNodeFailAssert(@"node %@ is already a subnode of %@. index %ld will be out of bounds once we call [subnode removeFromSupernode]. This can be caused by using automaticallyManagesSubnodes while also calling addSubnode explicitly.", subnode, self, subnodeIndex);
2126+
return;
2127+
}
2128+
21242129
// Disable appearance methods during move between supernodes, but make sure we restore their state after we do our thing
21252130
ASDisplayNode *oldParent = subnode.supernode;
21262131
BOOL disableNotifications = shouldDisableNotificationsForMovingBetweenParents(oldParent, self);

Tests/ASDisplayNodeTests.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2789,7 +2789,7 @@ - (void)testInsertExistingSubnode
27892789
DeclareNodeNamed(child);
27902790

27912791
[parent addSubnode:child];
2792-
// Previously this would cause a crash. We now protect inserting an already existing subnode
2792+
// Previously this would cause a crash. We now protect inserting an already existing subnode out of bounds
27932793
XCTAssertThrows([parent insertSubnode:child atIndex:1]);
27942794
XCTAssertTrue(parent.subnodes.count == 1);
27952795
}

0 commit comments

Comments
 (0)