mirror of
https://github.com/status-im/react-native.git
synced 2025-01-14 19:44:13 +00:00
02b6e38bee
Summary:D3092867 / 1d3db4c5dc8763d16f2d051fdf04a2976c0fb154 caused deadlock when chrome debugging was turned on, so it was reverted as D3128586 / 144dc3066144a48fc13bb7832abc9e645024fb88. The reason: I was calling `[_bridge dispatchBlock:^{ [self flushEventsQueue]; } queue:RCTJSThread];` from main thread and expecting it will `dispatch_async` to another, since a held lock was being accessed the dispatched block and was released after the dispatch. Turns out `RCTWebSocketExecutor` (which is used when chrome debugger is turned on) executes all blocks dispatched this way to `RCTJSThread` synchronously on the main thread. This resulted in a deadlock. The "dispatched" block was trying to acquired lock which held by the same thread in the dispatching phase. A fix for this is pretty simple. We will release the lock before dispatching the block. However it's not super straightforward to see this won't introduce some race condition in a case with two threads where we would end up with events not being processed. My thinking why that shouldn't happen goes like this: We could get in a bad state if `flushEventsQueue` would run on JS thread while `sendEvent:` is running on MT. (I don't have a specific example how, maybe it's not possible. However when I show this case is safe we know we are good.) The way how locking is setup in this diff the only possible scenario where these two threads would execute in these methods concurrently is JS holding the lock and MT going to enqueue another block on JS thread (since that's outside of "locked" zone). But this scenarion can never happen, since if MT is about to enqueue the block on JS thread it means there cannot be a not yet fully executed block on JS thread. Therefore nothing bad can happen. So this diff brings back the reverted diff and adds to it the fix for the deadlock. Reviewed By: javache Differential Revision: D3130375 fb-gh-sync-id: 885a166f2f808551d7cd4e4eb98634d26afe6a11 fbshipit-source-id: 885a166f2f808551d7cd4e4eb98634d26afe6a11
106 lines
3.1 KiB
Objective-C
106 lines
3.1 KiB
Objective-C
/**
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*/
|
|
|
|
#import <UIKit/UIKit.h>
|
|
|
|
#import "RCTBridge.h"
|
|
|
|
typedef NS_ENUM(NSInteger, RCTTextEventType) {
|
|
RCTTextEventTypeFocus,
|
|
RCTTextEventTypeBlur,
|
|
RCTTextEventTypeChange,
|
|
RCTTextEventTypeSubmit,
|
|
RCTTextEventTypeEnd,
|
|
RCTTextEventTypeKeyPress
|
|
};
|
|
|
|
typedef NS_ENUM(NSInteger, RCTScrollEventType) {
|
|
RCTScrollEventTypeStart,
|
|
RCTScrollEventTypeMove,
|
|
RCTScrollEventTypeEnd,
|
|
RCTScrollEventTypeStartDeceleration,
|
|
RCTScrollEventTypeEndDeceleration,
|
|
RCTScrollEventTypeEndAnimation,
|
|
};
|
|
|
|
/**
|
|
* The threshold at which text inputs will start warning that the JS thread
|
|
* has fallen behind (resulting in poor input performance, missed keys, etc.)
|
|
*/
|
|
RCT_EXTERN const NSInteger RCTTextUpdateLagWarningThreshold;
|
|
|
|
/**
|
|
* Takes an input event name and normalizes it to the form that is required
|
|
* by the events system (currently that means starting with the "top" prefix,
|
|
* but that's an implementation detail that may change in future).
|
|
*/
|
|
RCT_EXTERN NSString *RCTNormalizeInputEventName(NSString *eventName);
|
|
|
|
@protocol RCTEvent <NSObject>
|
|
|
|
@required
|
|
|
|
@property (nonatomic, strong, readonly) NSNumber *viewTag;
|
|
@property (nonatomic, copy, readonly) NSString *eventName;
|
|
@property (nonatomic, assign, readonly) uint16_t coalescingKey;
|
|
|
|
- (BOOL)canCoalesce;
|
|
- (id<RCTEvent>)coalesceWithEvent:(id<RCTEvent>)newEvent;
|
|
|
|
// used directly for doing a JS call
|
|
+ (NSString *)moduleDotMethod;
|
|
// must contain only JSON compatible values
|
|
- (NSArray *)arguments;
|
|
|
|
@end
|
|
|
|
|
|
/**
|
|
* This class wraps the -[RCTBridge enqueueJSCall:args:] method, and
|
|
* provides some convenience methods for generating event calls.
|
|
*/
|
|
@interface RCTEventDispatcher : NSObject <RCTBridgeModule>
|
|
|
|
/**
|
|
* Send an application-specific event that does not relate to a specific
|
|
* view, e.g. a navigation or data update notification.
|
|
*/
|
|
- (void)sendAppEventWithName:(NSString *)name body:(id)body;
|
|
|
|
/**
|
|
* Send a device or iOS event that does not relate to a specific view,
|
|
* e.g.rotation, location, keyboard show/hide, background/awake, etc.
|
|
*/
|
|
- (void)sendDeviceEventWithName:(NSString *)name body:(id)body;
|
|
|
|
/**
|
|
* Send a user input event. The body dictionary must contain a "target"
|
|
* parameter, representing the React tag of the view sending the event
|
|
*/
|
|
- (void)sendInputEventWithName:(NSString *)name body:(NSDictionary *)body;
|
|
|
|
/**
|
|
* Send a text input/focus event.
|
|
*/
|
|
- (void)sendTextEventWithType:(RCTTextEventType)type
|
|
reactTag:(NSNumber *)reactTag
|
|
text:(NSString *)text
|
|
key:(NSString *)key
|
|
eventCount:(NSInteger)eventCount;
|
|
|
|
/**
|
|
* Send a pre-prepared event object.
|
|
*
|
|
* Events are sent to JS as soon as the thread is free to process them.
|
|
* If an event can be coalesced and there is another compatible event waiting, the coalescing will happen immediately.
|
|
*/
|
|
- (void)sendEvent:(id<RCTEvent>)event;
|
|
|
|
@end
|