Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[macos] FlutterKeyboardManager memory leak fix #48824

Merged
merged 2 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,24 @@ - (nonnull instancetype)initWithViewDelegate:(nonnull id<FlutterKeyboardViewDele
[FlutterMethodChannel methodChannelWithName:@"flutter/keyboard"
binaryMessenger:[_viewDelegate getBinaryMessenger]
codec:[FlutterStandardMethodCodec sharedInstance]];

[keyboardChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
[self handleKeyboardMethodCall:call result:result];
}];

_primaryResponders = [[NSMutableArray alloc] init];

__weak __typeof__(self) weakSelf = self;
[self addPrimaryResponder:[[FlutterEmbedderKeyResponder alloc]
initWithSendEvent:^(const FlutterKeyEvent& event,
FlutterKeyEventCallback callback,
void* userData) {
[_viewDelegate sendKeyEvent:event
callback:callback
userData:userData];
__strong __typeof__(weakSelf) strongSelf = weakSelf;
[strongSelf.viewDelegate sendKeyEvent:event
callback:callback
userData:userData];
}]];

[self
addPrimaryResponder:[[FlutterChannelKeyResponder alloc]
initWithChannel:[FlutterBasicMessageChannel
Expand All @@ -143,14 +149,14 @@ - (nonnull instancetype)initWithViewDelegate:(nonnull id<FlutterKeyboardViewDele
getBinaryMessenger]
codec:[FlutterJSONMessageCodec
sharedInstance]]]];

_pendingEvents = [[NSMutableArray alloc] init];
_layoutMap = [NSMutableDictionary<NSNumber*, NSNumber*> dictionary];
[self buildLayout];
for (id<FlutterKeyPrimaryResponder> responder in _primaryResponders) {
responder.layoutMap = _layoutMap;
}

__weak __typeof__(self) weakSelf = self;
[_viewDelegate subscribeToKeyboardLayoutChange:^() {
[weakSelf buildLayout];
}];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,9 +426,11 @@ - (bool)getPressedState;
- (bool)keyboardChannelGetPressedState;
- (bool)racingConditionBetweenKeyAndText;
- (bool)correctLogicalKeyForLayouts;
- (bool)shouldNotHoldStrongReferenceToViewDelegate;
@end

namespace flutter::testing {

TEST(FlutterKeyboardManagerUnittests, SinglePrimaryResponder) {
ASSERT_TRUE([[FlutterKeyboardManagerUnittestsObjC alloc] singlePrimaryResponder]);
}
Expand Down Expand Up @@ -461,6 +463,11 @@ - (bool)correctLogicalKeyForLayouts;
ASSERT_TRUE([[FlutterKeyboardManagerUnittestsObjC alloc] correctLogicalKeyForLayouts]);
}

TEST(FlutterKeyboardManagerUnittests, ShouldNotHoldStrongReferenceToViewDelegate) {
ASSERT_TRUE(
[[FlutterKeyboardManagerUnittestsObjC alloc] shouldNotHoldStrongReferenceToViewDelegate]);
}

} // namespace flutter::testing

@implementation FlutterKeyboardManagerUnittestsObjC
Expand Down Expand Up @@ -809,4 +816,30 @@ - (bool)correctLogicalKeyForLayouts {
return TRUE;
}

- (bool)shouldNotHoldStrongReferenceToViewDelegate {
__strong FlutterKeyboardManager* strongKeyboardManager;
__weak id weakViewDelegate;

@autoreleasepool {
id binaryMessengerMock = OCMStrictProtocolMock(@protocol(FlutterBinaryMessenger));
OCMStub([binaryMessengerMock setMessageHandlerOnChannel:[OCMArg any]
binaryMessageHandler:[OCMArg any]]);

id viewDelegateMock = OCMStrictProtocolMock(@protocol(FlutterKeyboardViewDelegate));
OCMStub([viewDelegateMock getBinaryMessenger]).andReturn(binaryMessengerMock);
OCMStub([viewDelegateMock subscribeToKeyboardLayoutChange:[OCMArg any]]);

LayoutClue layoutClue;
OCMStub([viewDelegateMock lookUpLayoutForKeyCode:0 shift:NO])
.ignoringNonObjectArgs()
.andReturn(layoutClue);
FlutterKeyboardManager* keyboardManager =
[[FlutterKeyboardManager alloc] initWithViewDelegate:viewDelegateMock];
strongKeyboardManager = keyboardManager;
weakViewDelegate = viewDelegateMock;
}

return weakViewDelegate == nil;
}

@end