Skip to content

Commit ba73836

Browse files
christophpurrerroryabraham
authored andcommitted
Avoid sharing mutable attributed string across threads in RCTBaseTextInputShadowView
Summary: The `NSMutableAttributedString` was initialized with the same backing store as the cached attributed string on the shadow queue (background thread), but then passed to the main thread and ultimately the JS thread. This explicitly copies the mutable attributed string into an immutable one on the shadow thread before passed off to other threads, which hopefully will address the `convertIdToFollyDynamic` crash that always includes `RCTBaseTextInputShadowView` touching an attributed string on the shadow queue in the trace. Changelog: [iOS][Fixed] - Possible fix for convertIdToFollyDynamic crash in RCTBaseTextInputView and RCTEventDispatcher Reviewed By: sammy-SC Differential Revision: D38133150 fbshipit-source-id: f371da5d17a32c3341287cd3e9730b31a98495f9
1 parent 546c4b4 commit ba73836

File tree

1 file changed

+7
-8
lines changed

1 file changed

+7
-8
lines changed

Libraries/Text/TextInput/RCTBaseTextInputShadowView.m

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,7 @@ - (void)uiManagerWillPerformMounting
144144

145145
RCTTextAttributes *textAttributes = [self.textAttributes copy];
146146

147-
NSMutableAttributedString *attributedText =
148-
[[NSMutableAttributedString alloc] initWithAttributedString:[self attributedTextWithBaseTextAttributes:nil]];
147+
NSMutableAttributedString *attributedText = [[self attributedTextWithBaseTextAttributes:nil] mutableCopy];
149148

150149
// Removing all references to Shadow Views and tags to avoid unnecessary retaining
151150
// and problems with comparing the strings.
@@ -162,13 +161,13 @@ - (void)uiManagerWillPerformMounting
162161
[attributedText insertAttributedString:propertyAttributedText atIndex:0];
163162
}
164163

165-
BOOL isAttributedTextChanged = NO;
164+
NSAttributedString *newAttributedText;
166165
if (![_previousAttributedText isEqualToAttributedString:attributedText]) {
167166
// We have to follow `set prop` pattern:
168167
// If the value has not changed, we must not notify the view about the change,
169168
// otherwise we may break local (temporary) state of the text input.
170-
isAttributedTextChanged = YES;
171-
_previousAttributedText = [attributedText copy];
169+
newAttributedText = [attributedText copy];
170+
_previousAttributedText = newAttributedText;
172171
}
173172

174173
NSNumber *tag = self.reactTag;
@@ -183,10 +182,10 @@ - (void)uiManagerWillPerformMounting
183182
baseTextInputView.reactBorderInsets = borderInsets;
184183
baseTextInputView.reactPaddingInsets = paddingInsets;
185184

186-
if (isAttributedTextChanged) {
185+
if (newAttributedText) {
187186
// Don't set `attributedText` if length equal to zero, otherwise it would shrink when attributes contain like `lineHeight`.
188-
if (attributedText.length != 0) {
189-
baseTextInputView.attributedText = attributedText;
187+
if (newAttributedText.length != 0) {
188+
baseTextInputView.attributedText = newAttributedText;
190189
} else {
191190
baseTextInputView.attributedText = nil;
192191
}

0 commit comments

Comments
 (0)