-
Notifications
You must be signed in to change notification settings - Fork 6k
Started clearing out the parent of orphaned semantic objects. #17499
Changes from all commits
3185a9f
dd64273
534845d
da3ffbf
c32f9ac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,8 @@ | |
#include "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h" | ||
#include "flutter/shell/platform/darwin/ios/platform_view_ios.h" | ||
|
||
FLUTTER_ASSERT_NOT_ARC | ||
|
||
namespace { | ||
|
||
constexpr int32_t kRootNodeId = 0; | ||
|
@@ -162,8 +164,14 @@ - (instancetype)initWithSemanticsObject:(SemanticsObject*)semanticsObject | |
|
||
@end | ||
|
||
@interface SemanticsObject () | ||
/** Should only be called in conjunction with setting child/parent relationship. */ | ||
- (void)privateSetParent:(SemanticsObject*)parent; | ||
@end | ||
|
||
@implementation SemanticsObject { | ||
fml::scoped_nsobject<SemanticsObjectContainer> _container; | ||
NSMutableArray<SemanticsObject*>* _children; | ||
} | ||
|
||
#pragma mark - Override base class designated initializers | ||
|
@@ -197,7 +205,7 @@ - (instancetype)initWithBridge:(fml::WeakPtr<flutter::AccessibilityBridge>)bridg | |
|
||
- (void)dealloc { | ||
for (SemanticsObject* child in _children) { | ||
child.parent = nil; | ||
[child privateSetParent:nil]; | ||
} | ||
[_children removeAllObjects]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was added previously to prevent a different memory leak. Are we sure we're not leaking a11y objects with this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is redundant, the next line deletes the whole collection which will release all of its items. If this appeared to fix something, there is a deeper problem somewhere else. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may have just been paranoia :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The most likely scenario is that if this fixed something, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another possibility is that someone is holding onto the |
||
[_children release]; | ||
|
@@ -239,6 +247,28 @@ - (BOOL)hasChildren { | |
return [self.children count] != 0; | ||
} | ||
|
||
- (void)privateSetParent:(SemanticsObject*)parent { | ||
_parent = parent; | ||
} | ||
|
||
- (void)setChildren:(NSArray<SemanticsObject*>*)children { | ||
for (SemanticsObject* child in _children) { | ||
[child privateSetParent:nil]; | ||
} | ||
[_children release]; | ||
_children = [[NSMutableArray alloc] initWithArray:children]; | ||
for (SemanticsObject* child in _children) { | ||
[child privateSetParent:self]; | ||
} | ||
} | ||
|
||
- (void)replaceChildAtIndex:(NSInteger)index withChild:(SemanticsObject*)child { | ||
SemanticsObject* oldChild = _children[index]; | ||
[oldChild privateSetParent:nil]; | ||
[child privateSetParent:self]; | ||
[_children replaceObjectAtIndex:index withObject:child]; | ||
} | ||
|
||
#pragma mark - UIAccessibility overrides | ||
|
||
- (BOOL)isAccessibilityElement { | ||
|
@@ -653,7 +683,7 @@ - (NSInteger)indexOfAccessibilityElement:(id)element { | |
return ((FlutterPlatformViewSemanticsContainer*)element).index; | ||
} | ||
|
||
NSMutableArray<SemanticsObject*>* children = [_semanticsObject children]; | ||
NSArray<SemanticsObject*>* children = [_semanticsObject children]; | ||
for (size_t i = 0; i < [children count]; i++) { | ||
SemanticsObject* child = children[i]; | ||
if ((![child hasChildren] && child == element) || | ||
|
@@ -741,7 +771,6 @@ - (BOOL)accessibilityScroll:(UIAccessibilityScrollDirection)direction { | |
[[[NSMutableArray alloc] initWithCapacity:newChildCount] autorelease]; | ||
for (NSUInteger i = 0; i < newChildCount; ++i) { | ||
SemanticsObject* child = GetOrCreateObject(node.childrenInTraversalOrder[i], nodes); | ||
child.parent = object; | ||
[newChildren addObject:child]; | ||
} | ||
object.children = newChildren; | ||
|
@@ -847,10 +876,8 @@ static void ReplaceSemanticsObject(SemanticsObject* oldObject, | |
assert(oldObject.node.id == newObject.node.id); | ||
NSNumber* nodeId = @(oldObject.node.id); | ||
NSUInteger positionInChildlist = [oldObject.parent.children indexOfObject:oldObject]; | ||
SemanticsObject* parent = oldObject.parent; | ||
[objects removeObjectForKey:nodeId]; | ||
newObject.parent = parent; | ||
[newObject.parent.children replaceObjectAtIndex:positionInChildlist withObject:newObject]; | ||
[oldObject.parent replaceChildAtIndex:positionInChildlist withChild:newObject]; | ||
objects[nodeId] = newObject; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see how this really helps us vs. having the parent property be writable. It's not like there were other TUs setting the property. Can you explain a bit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the point is we want to control the editing of the parent property. We want to enforce that editing it happens in conjunction with editing children. If we were using another language I could make the setter private. Here i just do it by convention and naming. We could split SemanticsObject into its own file and make it truly private if you aren't happy with how it's setup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we just leave it as
_parent = parent
? Am I just forgetting how Objective C works?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because you are calling it on someone else:
We want only SemanticObject to have access to the setter, we don't want the accessibility bridge or whoever fiddling with it (private in a c++ sense). My hope was that when people see a method called "privateSetParent" they might think twice about who is suppose to be calling it and why.