UNPKG

5.79 kBPlain TextView Raw
1/*
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#import "RCTSurfacePresenterBridgeAdapter.h"
9
10#import <cxxreact/MessageQueueThread.h>
11#import <jsi/jsi.h>
12
13#import <React/RCTAssert.h>
14#import <React/RCTBridge+Private.h>
15#import <React/RCTImageLoader.h>
16#import <React/RCTImageLoaderWithAttributionProtocol.h>
17#import <React/RCTSurfacePresenter.h>
18#import <React/RCTSurfacePresenterStub.h>
19
20#import <react/utils/ContextContainer.h>
21#import <react/utils/ManagedObjectWrapper.h>
22#import <react/utils/RuntimeExecutor.h>
23
24using namespace facebook::react;
25
26@interface RCTBridge ()
27- (std::shared_ptr<facebook::react::MessageQueueThread>)jsMessageThread;
28- (void)invokeAsync:(std::function<void()> &&)func;
29@end
30
31static ContextContainer::Shared RCTContextContainerFromBridge(RCTBridge *bridge)
32{
33 auto contextContainer = std::make_shared<ContextContainer const>();
34
35 RCTImageLoader *imageLoader = RCTTurboModuleEnabled()
36 ? [bridge moduleForName:@"RCTImageLoader" lazilyLoadIfNecessary:YES]
37 : [bridge moduleForClass:[RCTImageLoader class]];
38
39 contextContainer->insert("Bridge", wrapManagedObjectWeakly(bridge));
40 contextContainer->insert("RCTImageLoader", wrapManagedObject((id<RCTImageLoaderWithAttributionProtocol>)imageLoader));
41 return contextContainer;
42}
43
44static RuntimeExecutor RCTRuntimeExecutorFromBridge(RCTBridge *bridge)
45{
46 auto bridgeWeakWrapper = wrapManagedObjectWeakly([bridge batchedBridge] ?: bridge);
47
48 RuntimeExecutor runtimeExecutor = [bridgeWeakWrapper](
49 std::function<void(facebook::jsi::Runtime & runtime)> &&callback) {
50 [unwrapManagedObjectWeakly(bridgeWeakWrapper) invokeAsync:[bridgeWeakWrapper, callback = std::move(callback)]() {
51 RCTCxxBridge *batchedBridge = (RCTCxxBridge *)unwrapManagedObjectWeakly(bridgeWeakWrapper);
52
53 if (!batchedBridge) {
54 return;
55 }
56
57 auto runtime = (facebook::jsi::Runtime *)(batchedBridge.runtime);
58
59 if (!runtime) {
60 return;
61 }
62
63 callback(*runtime);
64 }];
65 };
66
67 return runtimeExecutor;
68}
69
70@implementation RCTSurfacePresenterBridgeAdapter {
71 RCTSurfacePresenter *_Nullable _surfacePresenter;
72 __weak RCTBridge *_bridge;
73 __weak RCTBridge *_batchedBridge;
74}
75
76- (instancetype)initWithBridge:(RCTBridge *)bridge contextContainer:(ContextContainer::Shared)contextContainer
77{
78 if (self = [super init]) {
79 contextContainer->update(*RCTContextContainerFromBridge(bridge));
80 _surfacePresenter = [[RCTSurfacePresenter alloc] initWithContextContainer:contextContainer
81 runtimeExecutor:RCTRuntimeExecutorFromBridge(bridge)];
82
83 _bridge = bridge;
84 _batchedBridge = [_bridge batchedBridge] ?: _bridge;
85
86 [self _updateSurfacePresenter];
87 [self _addBridgeObservers:_bridge];
88 }
89
90 return self;
91}
92
93- (void)dealloc
94{
95 [_surfacePresenter suspend];
96}
97
98- (RCTBridge *)bridge
99{
100 return _bridge;
101}
102
103- (void)setBridge:(RCTBridge *)bridge
104{
105 if (bridge == _bridge) {
106 return;
107 }
108
109 [self _removeBridgeObservers:_bridge];
110
111 [_surfacePresenter suspend];
112
113 _bridge = bridge;
114 _batchedBridge = [_bridge batchedBridge] ?: _bridge;
115
116 [self _updateSurfacePresenter];
117
118 [self _addBridgeObservers:_bridge];
119
120 [_surfacePresenter resume];
121}
122
123- (void)_updateSurfacePresenter
124{
125 _surfacePresenter.runtimeExecutor = RCTRuntimeExecutorFromBridge(_bridge);
126 _surfacePresenter.contextContainer->update(*RCTContextContainerFromBridge(_bridge));
127
128 [_bridge setSurfacePresenter:_surfacePresenter];
129 [_batchedBridge setSurfacePresenter:_surfacePresenter];
130}
131
132- (void)_addBridgeObservers:(RCTBridge *)bridge
133{
134 if (!bridge) {
135 return;
136 }
137
138 [[NSNotificationCenter defaultCenter] addObserver:self
139 selector:@selector(handleBridgeWillReloadNotification:)
140 name:RCTBridgeWillReloadNotification
141 object:bridge];
142 [[NSNotificationCenter defaultCenter] addObserver:self
143 selector:@selector(handleJavaScriptDidLoadNotification:)
144 name:RCTJavaScriptDidLoadNotification
145 object:bridge];
146 [[NSNotificationCenter defaultCenter] addObserver:self
147 selector:@selector(handleBridgeWillBeInvalidatedNotification:)
148 name:RCTBridgeWillBeInvalidatedNotification
149 object:bridge];
150}
151
152- (void)_removeBridgeObservers:(RCTBridge *)bridge
153{
154 if (!bridge) {
155 return;
156 }
157
158 [[NSNotificationCenter defaultCenter] removeObserver:self name:RCTBridgeWillReloadNotification object:bridge];
159 [[NSNotificationCenter defaultCenter] removeObserver:self name:RCTJavaScriptDidLoadNotification object:bridge];
160 [[NSNotificationCenter defaultCenter] removeObserver:self name:RCTBridgeWillBeInvalidatedNotification object:bridge];
161}
162
163#pragma mark - Bridge events
164
165- (void)handleBridgeWillReloadNotification:(NSNotification *)notification
166{
167 [_surfacePresenter suspend];
168}
169
170- (void)handleBridgeWillBeInvalidatedNotification:(NSNotification *)notification
171{
172 [_surfacePresenter suspend];
173}
174
175- (void)handleJavaScriptDidLoadNotification:(NSNotification *)notification
176{
177 RCTBridge *bridge = notification.userInfo[@"bridge"];
178 if (bridge == _batchedBridge) {
179 // Nothing really changed.
180 return;
181 }
182
183 _batchedBridge = bridge;
184 _batchedBridge.surfacePresenter = _surfacePresenter;
185
186 [self _updateSurfacePresenter];
187
188 [_surfacePresenter resume];
189}
190
191@end