react-native 0.72.0-rc.1 → 0.72.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Libraries/Components/View/ReactNativeStyleAttributes.js +0 -7
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/NativeComponent/BaseViewConfig.android.js +0 -8
- package/Libraries/NativeComponent/BaseViewConfig.ios.js +0 -8
- package/Libraries/StyleSheet/StyleSheetTypes.d.ts +0 -7
- package/Libraries/StyleSheet/StyleSheetTypes.js +0 -74
- package/Libraries/Text/TextInput/RCTBackedTextInputDelegateAdapter.m +3 -3
- package/React/Base/RCTVersion.m +1 -1
- package/React/CoreModules/RCTDevMenu.mm +3 -3
- package/React/Fabric/Mounting/ComponentViews/Image/RCTImageComponentView.mm +12 -1
- package/React/Fabric/RCTSurfacePresenter.mm +4 -0
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/animated/NativeAnimatedModule.java +10 -0
- package/ReactAndroid/src/main/java/com/facebook/react/bridge/ReactContext.java +29 -0
- package/ReactAndroid/src/main/java/com/facebook/react/bridge/UIManagerListener.java +25 -2
- package/ReactAndroid/src/main/java/com/facebook/react/bridge/interop/InteropModuleRegistry.java +56 -0
- package/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +8 -0
- package/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt +1 -0
- package/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManagerBase.java +26 -8
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +21 -0
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/interop/InteropEvent.java +41 -0
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/interop/InteropEventEmitter.java +65 -0
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountItemDispatcher.java +9 -0
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/ThemedReactContext.java +1 -0
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java +32 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/scroll/MaintainVisibleScrollPositionHelper.java +19 -0
- package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
- package/ReactCommon/react/renderer/components/view/YogaLayoutableShadowNode.cpp +0 -21
- package/ReactCommon/react/renderer/components/view/YogaStylableProps.cpp +0 -49
- package/ReactCommon/react/renderer/components/view/YogaStylableProps.h +0 -9
- package/ReactCommon/react/renderer/core/CoreFeatures.cpp +1 -0
- package/ReactCommon/react/renderer/core/CoreFeatures.h +4 -0
- package/ReactCommon/react/renderer/imagemanager/ImageRequest.h +7 -3
- package/ReactCommon/react/renderer/imagemanager/platform/cxx/react/renderer/imagemanager/ImageRequest.cpp +0 -11
- package/ReactCommon/react/renderer/imagemanager/platform/ios/react/renderer/imagemanager/ImageRequest.cpp +4 -14
- package/package.json +9 -9
- package/scripts/cocoapods/__tests__/flipper-test.rb +9 -1
- package/scripts/cocoapods/__tests__/jsengine-test.rb +6 -2
- package/scripts/cocoapods/__tests__/test_utils/podSpy.rb +2 -1
- package/scripts/cocoapods/__tests__/utils-test.rb +0 -68
- package/scripts/cocoapods/flipper.rb +2 -2
- package/scripts/cocoapods/jsengine.rb +6 -1
- package/scripts/cocoapods/utils.rb +0 -7
- package/scripts/react_native_pods.rb +3 -6
- package/sdks/hermesc/linux64-bin/hermesc +0 -0
- package/sdks/hermesc/osx-bin/hermesc +0 -0
- package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
- package/template/android/app/build.gradle +7 -2
- package/template/package.json +5 -5
- package/types/index.d.ts +4 -0
|
@@ -46,13 +46,6 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
|
|
|
46
46
|
flexWrap: true,
|
|
47
47
|
gap: true,
|
|
48
48
|
height: true,
|
|
49
|
-
inset: true,
|
|
50
|
-
insetBlock: true,
|
|
51
|
-
insetBlockEnd: true,
|
|
52
|
-
insetBlockStart: true,
|
|
53
|
-
insetInline: true,
|
|
54
|
-
insetInlineEnd: true,
|
|
55
|
-
insetInlineStart: true,
|
|
56
49
|
justifyContent: true,
|
|
57
50
|
left: true,
|
|
58
51
|
margin: true,
|
|
@@ -258,14 +258,6 @@ const validAttributesForNonEventProps = {
|
|
|
258
258
|
top: true,
|
|
259
259
|
bottom: true,
|
|
260
260
|
|
|
261
|
-
inset: true,
|
|
262
|
-
insetBlock: true,
|
|
263
|
-
insetBlockEnd: true,
|
|
264
|
-
insetBlockStart: true,
|
|
265
|
-
insetInline: true,
|
|
266
|
-
insetInlineEnd: true,
|
|
267
|
-
insetInlineStart: true,
|
|
268
|
-
|
|
269
261
|
position: true,
|
|
270
262
|
|
|
271
263
|
style: ReactNativeStyleAttributes,
|
|
@@ -236,14 +236,6 @@ const validAttributesForNonEventProps = {
|
|
|
236
236
|
bottom: true,
|
|
237
237
|
left: true,
|
|
238
238
|
|
|
239
|
-
inset: true,
|
|
240
|
-
insetBlock: true,
|
|
241
|
-
insetBlockEnd: true,
|
|
242
|
-
insetBlockStart: true,
|
|
243
|
-
insetInline: true,
|
|
244
|
-
insetInlineEnd: true,
|
|
245
|
-
insetInlineStart: true,
|
|
246
|
-
|
|
247
239
|
width: true,
|
|
248
240
|
height: true,
|
|
249
241
|
|
|
@@ -69,13 +69,6 @@ export interface FlexStyle {
|
|
|
69
69
|
flexShrink?: number | undefined;
|
|
70
70
|
flexWrap?: 'wrap' | 'nowrap' | 'wrap-reverse' | undefined;
|
|
71
71
|
height?: DimensionValue | undefined;
|
|
72
|
-
inset?: DimensionValue | undefined;
|
|
73
|
-
insetBlock?: DimensionValue | undefined;
|
|
74
|
-
insetBlockEnd?: DimensionValue | undefined;
|
|
75
|
-
insetBlockStart?: DimensionValue | undefined;
|
|
76
|
-
insetInline?: DimensionValue | undefined;
|
|
77
|
-
insetInlineEnd?: DimensionValue | undefined;
|
|
78
|
-
insetInlineStart?: DimensionValue | undefined;
|
|
79
72
|
justifyContent?:
|
|
80
73
|
| 'flex-start'
|
|
81
74
|
| 'flex-end'
|
|
@@ -134,80 +134,6 @@ type ____LayoutStyle_Internal = $ReadOnly<{
|
|
|
134
134
|
*/
|
|
135
135
|
top?: DimensionValue,
|
|
136
136
|
|
|
137
|
-
/** `inset` is a shorthand that corresponds to the top, right, bottom, and/or left properties.
|
|
138
|
-
*
|
|
139
|
-
* It works similarly to `inset` in CSS, but in React Native you
|
|
140
|
-
* must use points or percentages. Ems and other units are not supported.
|
|
141
|
-
*
|
|
142
|
-
* See https://developer.mozilla.org/en-US/docs/Web/CSS/inset
|
|
143
|
-
* for more details of how `inset` affects layout.
|
|
144
|
-
*/
|
|
145
|
-
inset?: DimensionValue,
|
|
146
|
-
|
|
147
|
-
/** `insetBlock` is a shorthand that corresponds to the `insetBlockStart` and `insetBlockEnd` properties.
|
|
148
|
-
*
|
|
149
|
-
* It works similarly to `inset-block` in CSS, but in React Native you
|
|
150
|
-
* must use points or percentages. Ems and other units are not supported.
|
|
151
|
-
*
|
|
152
|
-
* See https://developer.mozilla.org/en-US/docs/Web/CSS/inset-block
|
|
153
|
-
* for more details of how `inset-block` affects layout.
|
|
154
|
-
*/
|
|
155
|
-
insetBlock?: DimensionValue,
|
|
156
|
-
|
|
157
|
-
/** `insetBlockEnd` is a logical property that sets the length that an
|
|
158
|
-
* element is offset in the block direction from its ending edge.
|
|
159
|
-
*
|
|
160
|
-
* It works similarly to `inset-block-end` in CSS, but in React Native you
|
|
161
|
-
* must use points or percentages. Ems and other units are not supported.
|
|
162
|
-
*
|
|
163
|
-
* See https://developer.mozilla.org/en-US/docs/Web/CSS/inset-block-end
|
|
164
|
-
* for more details of how `inset-block-end` affects layout.
|
|
165
|
-
*/
|
|
166
|
-
insetBlockEnd?: DimensionValue,
|
|
167
|
-
|
|
168
|
-
/** `insetBlockStart` is a logical property that sets the length that an
|
|
169
|
-
* element is offset in the block direction from its starting edge.
|
|
170
|
-
*
|
|
171
|
-
* It works similarly to `inset-block-start` in CSS, but in React Native you
|
|
172
|
-
* must use points or percentages. Ems and other units are not supported.
|
|
173
|
-
*
|
|
174
|
-
* See https://developer.mozilla.org/en-US/docs/Web/CSS/inset-block-start
|
|
175
|
-
* for more details of how `inset-block-start` affects layout.
|
|
176
|
-
*/
|
|
177
|
-
insetBlockStart?: DimensionValue,
|
|
178
|
-
|
|
179
|
-
/** `insetInline` is a shorthand that corresponds to the `insetInlineStart` and `insetInlineEnd` properties.
|
|
180
|
-
*
|
|
181
|
-
* It works similarly to `inset-inline` in CSS, but in React Native you
|
|
182
|
-
* must use points or percentages. Ems and other units are not supported.
|
|
183
|
-
*
|
|
184
|
-
* See https://developer.mozilla.org/en-US/docs/Web/CSS/inset-inline
|
|
185
|
-
* for more details of how `inset-inline` affects layout.
|
|
186
|
-
*/
|
|
187
|
-
insetInline?: DimensionValue,
|
|
188
|
-
|
|
189
|
-
/** `insetInlineEnd` is a logical property that sets the length that an
|
|
190
|
-
* element is offset in the starting inline direction.
|
|
191
|
-
*
|
|
192
|
-
* It works similarly to `inset-inline-end` in CSS, but in React Native you
|
|
193
|
-
* must use points or percentages. Ems and other units are not supported.
|
|
194
|
-
*
|
|
195
|
-
* See https://developer.mozilla.org/en-US/docs/Web/CSS/inset-inline-end
|
|
196
|
-
* for more details of how `inset-inline-end` affects layout.
|
|
197
|
-
*/
|
|
198
|
-
insetInlineEnd?: DimensionValue,
|
|
199
|
-
|
|
200
|
-
/** `insetInlineStart` is a logical property that sets the length that an
|
|
201
|
-
* element is offset in the starting inline direction.
|
|
202
|
-
*
|
|
203
|
-
* It works similarly to `inset-inline-start` in CSS, but in React Native you
|
|
204
|
-
* must use points or percentages. Ems and other units are not supported.
|
|
205
|
-
*
|
|
206
|
-
* See https://developer.mozilla.org/en-US/docs/Web/CSS/inset-inline-start
|
|
207
|
-
* for more details of how `inset-inline-start` affects layout.
|
|
208
|
-
*/
|
|
209
|
-
insetInlineStart?: DimensionValue,
|
|
210
|
-
|
|
211
137
|
/** `minWidth` is the minimum width for this component, in logical pixels.
|
|
212
138
|
*
|
|
213
139
|
* It works similarly to `min-width` in CSS, but in React Native you
|
|
@@ -256,21 +256,21 @@ static void *TextFieldSelectionObservingContext = &TextFieldSelectionObservingCo
|
|
|
256
256
|
|
|
257
257
|
- (void)textViewDidChange:(__unused UITextView *)textView
|
|
258
258
|
{
|
|
259
|
-
if (_ignoreNextTextInputCall
|
|
259
|
+
if (_ignoreNextTextInputCall) {
|
|
260
260
|
_ignoreNextTextInputCall = NO;
|
|
261
261
|
return;
|
|
262
262
|
}
|
|
263
|
-
_lastStringStateWasUpdatedWith = _backedTextInputView.attributedText;
|
|
264
263
|
_textDidChangeIsComing = NO;
|
|
265
264
|
[_backedTextInputView.textInputDelegate textInputDidChange];
|
|
266
265
|
}
|
|
267
266
|
|
|
268
267
|
- (void)textViewDidChangeSelection:(__unused UITextView *)textView
|
|
269
268
|
{
|
|
270
|
-
if (![_lastStringStateWasUpdatedWith isEqual:_backedTextInputView.attributedText]) {
|
|
269
|
+
if (_lastStringStateWasUpdatedWith && ![_lastStringStateWasUpdatedWith isEqual:_backedTextInputView.attributedText]) {
|
|
271
270
|
[self textViewDidChange:_backedTextInputView];
|
|
272
271
|
_ignoreNextTextInputCall = YES;
|
|
273
272
|
}
|
|
273
|
+
_lastStringStateWasUpdatedWith = _backedTextInputView.attributedText;
|
|
274
274
|
[self textViewProbablyDidChangeSelection];
|
|
275
275
|
}
|
|
276
276
|
|
package/React/Base/RCTVersion.m
CHANGED
|
@@ -428,10 +428,10 @@ RCT_EXPORT_METHOD(show)
|
|
|
428
428
|
? UIAlertControllerStyleActionSheet
|
|
429
429
|
: UIAlertControllerStyleAlert;
|
|
430
430
|
|
|
431
|
-
NSString *
|
|
432
|
-
NSString *
|
|
431
|
+
NSString *devMenuType = self.bridge ? @"Bridge" : @"Bridgeless";
|
|
432
|
+
NSString *devMenuTitle = [NSString stringWithFormat:@"React Native Dev Menu (%@)", devMenuType];
|
|
433
433
|
|
|
434
|
-
_actionSheet = [UIAlertController alertControllerWithTitle:
|
|
434
|
+
_actionSheet = [UIAlertController alertControllerWithTitle:devMenuTitle message:description preferredStyle:style];
|
|
435
435
|
|
|
436
436
|
NSArray<RCTDevMenuItem *> *items = [self _menuItemsToPresent];
|
|
437
437
|
for (RCTDevMenuItem *item in items) {
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
#import <react/renderer/components/image/ImageComponentDescriptor.h>
|
|
15
15
|
#import <react/renderer/components/image/ImageEventEmitter.h>
|
|
16
16
|
#import <react/renderer/components/image/ImageProps.h>
|
|
17
|
+
#import <react/renderer/core/CoreFeatures.h>
|
|
17
18
|
#import <react/renderer/imagemanager/ImageRequest.h>
|
|
18
19
|
#import <react/renderer/imagemanager/RCTImagePrimitivesConversions.h>
|
|
19
20
|
|
|
@@ -97,8 +98,18 @@ using namespace facebook::react;
|
|
|
97
98
|
- (void)_setStateAndResubscribeImageResponseObserver:(ImageShadowNode::ConcreteState::Shared const &)state
|
|
98
99
|
{
|
|
99
100
|
if (_state) {
|
|
100
|
-
auto &
|
|
101
|
+
auto const &imageRequest = _state->getData().getImageRequest();
|
|
102
|
+
auto &observerCoordinator = imageRequest.getObserverCoordinator();
|
|
101
103
|
observerCoordinator.removeObserver(_imageResponseObserverProxy);
|
|
104
|
+
if (CoreFeatures::cancelImageDownloadsOnRecycle) {
|
|
105
|
+
// Cancelling image request because we are no longer observing it.
|
|
106
|
+
// This is not 100% correct place to do this because we may want to
|
|
107
|
+
// re-create RCTImageComponentView with the same image and if it
|
|
108
|
+
// was cancelled before downloaded, download is not resumed.
|
|
109
|
+
// This will only become issue if we decouple life cycle of a
|
|
110
|
+
// ShadowNode from ComponentView, which is not something we do now.
|
|
111
|
+
imageRequest.cancel();
|
|
112
|
+
}
|
|
102
113
|
}
|
|
103
114
|
|
|
104
115
|
_state = state;
|
|
@@ -285,6 +285,10 @@ static BackgroundExecutor RCTGetBackgroundExecutor()
|
|
|
285
285
|
CoreFeatures::cacheNSTextStorage = true;
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
+
if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:cancel_image_downloads_on_recycle")) {
|
|
289
|
+
CoreFeatures::cancelImageDownloadsOnRecycle = true;
|
|
290
|
+
}
|
|
291
|
+
|
|
288
292
|
auto componentRegistryFactory =
|
|
289
293
|
[factory = wrapManagedObject(_mountingManager.componentViewRegistry.componentViewFactory)](
|
|
290
294
|
EventDispatcher::Weak const &eventDispatcher, ContextContainer::Shared const &contextContainer) {
|
|
@@ -295,6 +295,16 @@ public class NativeAnimatedModule extends NativeAnimatedModuleSpec
|
|
|
295
295
|
mCurrentFrameNumber++;
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
+
@Override
|
|
299
|
+
public void willMountItems(UIManager uiManager) {
|
|
300
|
+
// noop
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
@Override
|
|
304
|
+
public void didMountItems(UIManager uiManager) {
|
|
305
|
+
// noop
|
|
306
|
+
}
|
|
307
|
+
|
|
298
308
|
// For FabricUIManager only
|
|
299
309
|
@Override
|
|
300
310
|
@UiThread
|
|
@@ -21,6 +21,7 @@ import com.facebook.common.logging.FLog;
|
|
|
21
21
|
import com.facebook.infer.annotation.Assertions;
|
|
22
22
|
import com.facebook.infer.annotation.ThreadConfined;
|
|
23
23
|
import com.facebook.proguard.annotations.DoNotStrip;
|
|
24
|
+
import com.facebook.react.bridge.interop.InteropModuleRegistry;
|
|
24
25
|
import com.facebook.react.bridge.queue.MessageQueueThread;
|
|
25
26
|
import com.facebook.react.bridge.queue.ReactQueueConfiguration;
|
|
26
27
|
import com.facebook.react.common.LifecycleState;
|
|
@@ -69,6 +70,8 @@ public class ReactContext extends ContextWrapper {
|
|
|
69
70
|
private @Nullable JSExceptionHandler mJSExceptionHandler;
|
|
70
71
|
private @Nullable JSExceptionHandler mExceptionHandlerWrapper;
|
|
71
72
|
private @Nullable WeakReference<Activity> mCurrentActivity;
|
|
73
|
+
|
|
74
|
+
private @Nullable InteropModuleRegistry mInteropModuleRegistry;
|
|
72
75
|
private boolean mIsInitialized = false;
|
|
73
76
|
|
|
74
77
|
public ReactContext(Context base) {
|
|
@@ -93,6 +96,7 @@ public class ReactContext extends ContextWrapper {
|
|
|
93
96
|
|
|
94
97
|
ReactQueueConfiguration queueConfig = catalystInstance.getReactQueueConfiguration();
|
|
95
98
|
initializeMessageQueueThreads(queueConfig);
|
|
99
|
+
initializeInteropModules();
|
|
96
100
|
}
|
|
97
101
|
|
|
98
102
|
/** Initialize message queue threads using a ReactQueueConfiguration. */
|
|
@@ -120,6 +124,14 @@ public class ReactContext extends ContextWrapper {
|
|
|
120
124
|
mIsInitialized = true;
|
|
121
125
|
}
|
|
122
126
|
|
|
127
|
+
protected void initializeInteropModules() {
|
|
128
|
+
mInteropModuleRegistry = new InteropModuleRegistry();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
protected void initializeInteropModules(ReactContext reactContext) {
|
|
132
|
+
mInteropModuleRegistry = reactContext.mInteropModuleRegistry;
|
|
133
|
+
}
|
|
134
|
+
|
|
123
135
|
public void resetPerfStats() {
|
|
124
136
|
if (mNativeModulesMessageQueueThread != null) {
|
|
125
137
|
mNativeModulesMessageQueueThread.resetPerfStats();
|
|
@@ -163,6 +175,10 @@ public class ReactContext extends ContextWrapper {
|
|
|
163
175
|
}
|
|
164
176
|
throw new IllegalStateException(EARLY_JS_ACCESS_EXCEPTION_MESSAGE);
|
|
165
177
|
}
|
|
178
|
+
if (mInteropModuleRegistry != null
|
|
179
|
+
&& mInteropModuleRegistry.shouldReturnInteropModule(jsInterface)) {
|
|
180
|
+
return mInteropModuleRegistry.getInteropModule(jsInterface);
|
|
181
|
+
}
|
|
166
182
|
return mCatalystInstance.getJSModule(jsInterface);
|
|
167
183
|
}
|
|
168
184
|
|
|
@@ -546,4 +562,17 @@ public class ReactContext extends ContextWrapper {
|
|
|
546
562
|
Assertions.assertNotNull(mCatalystInstance).registerSegment(segmentId, path);
|
|
547
563
|
Assertions.assertNotNull(callback).invoke();
|
|
548
564
|
}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Register a {@link JavaScriptModule} within the Interop Layer so that can be consumed whenever
|
|
568
|
+
* getJSModule is invoked.
|
|
569
|
+
*
|
|
570
|
+
* <p>This method is internal to React Native and should not be used externally.
|
|
571
|
+
*/
|
|
572
|
+
public <T extends JavaScriptModule> void internal_registerInteropModule(
|
|
573
|
+
Class<T> interopModuleInterface, Object interopModule) {
|
|
574
|
+
if (mInteropModuleRegistry != null) {
|
|
575
|
+
mInteropModuleRegistry.registerInteropModule(interopModuleInterface, interopModule);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
549
578
|
}
|
|
@@ -12,10 +12,33 @@ public interface UIManagerListener {
|
|
|
12
12
|
/**
|
|
13
13
|
* Called right before view updates are dispatched at the end of a batch. This is useful if a
|
|
14
14
|
* module needs to add UIBlocks to the queue before it is flushed.
|
|
15
|
+
*
|
|
16
|
+
* <p>This is called by Paper only.
|
|
15
17
|
*/
|
|
16
18
|
void willDispatchViewUpdates(UIManager uiManager);
|
|
17
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Called on UIThread right before view updates are executed.
|
|
21
|
+
*
|
|
22
|
+
* <p>This is called by Fabric only.
|
|
23
|
+
*/
|
|
24
|
+
void willMountItems(UIManager uiManager);
|
|
25
|
+
/**
|
|
26
|
+
* Called on UIThread right after view updates are executed.
|
|
27
|
+
*
|
|
28
|
+
* <p>This is called by Fabric only.
|
|
29
|
+
*/
|
|
30
|
+
void didMountItems(UIManager uiManager);
|
|
31
|
+
/**
|
|
32
|
+
* Called on UIThread right after view updates are dispatched for a frame. Note that this will be
|
|
33
|
+
* called for every frame even if there are no updates.
|
|
34
|
+
*
|
|
35
|
+
* <p>This is called by Fabric only.
|
|
36
|
+
*/
|
|
18
37
|
void didDispatchMountItems(UIManager uiManager);
|
|
19
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Called right after scheduleMountItems is called in Fabric, after a new tree is committed.
|
|
40
|
+
*
|
|
41
|
+
* <p>This is called by Fabric only.
|
|
42
|
+
*/
|
|
20
43
|
void didScheduleMountItems(UIManager uiManager);
|
|
21
44
|
}
|
package/ReactAndroid/src/main/java/com/facebook/react/bridge/interop/InteropModuleRegistry.java
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and 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
|
+
package com.facebook.react.bridge.interop;
|
|
9
|
+
|
|
10
|
+
import androidx.annotation.Nullable;
|
|
11
|
+
import com.facebook.react.bridge.JavaScriptModule;
|
|
12
|
+
import com.facebook.react.config.ReactFeatureFlags;
|
|
13
|
+
import java.util.HashMap;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A utility class that takes care of returning {@link JavaScriptModule} which are used for the
|
|
17
|
+
* Fabric Interop Layer. This allows us to override the returned classes once the user is invoking
|
|
18
|
+
* `ReactContext.getJsModule()`.
|
|
19
|
+
*
|
|
20
|
+
* <p>Currently we only support a `RCTEventEmitter` re-implementation, being `InteropEventEmitter`
|
|
21
|
+
* but this class can support other re-implementation in the future.
|
|
22
|
+
*/
|
|
23
|
+
public class InteropModuleRegistry {
|
|
24
|
+
|
|
25
|
+
@SuppressWarnings("rawtypes")
|
|
26
|
+
private final HashMap<Class, Object> supportedModules;
|
|
27
|
+
|
|
28
|
+
public InteropModuleRegistry() {
|
|
29
|
+
this.supportedModules = new HashMap<>();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public <T extends JavaScriptModule> boolean shouldReturnInteropModule(Class<T> requestedModule) {
|
|
33
|
+
return checkReactFeatureFlagsConditions() && supportedModules.containsKey(requestedModule);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@Nullable
|
|
37
|
+
public <T extends JavaScriptModule> T getInteropModule(Class<T> requestedModule) {
|
|
38
|
+
if (checkReactFeatureFlagsConditions()) {
|
|
39
|
+
//noinspection unchecked
|
|
40
|
+
return (T) supportedModules.get(requestedModule);
|
|
41
|
+
} else {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public <T extends JavaScriptModule> void registerInteropModule(
|
|
47
|
+
Class<T> interopModuleInterface, Object interopModule) {
|
|
48
|
+
if (checkReactFeatureFlagsConditions()) {
|
|
49
|
+
supportedModules.put(interopModuleInterface, interopModule);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private boolean checkReactFeatureFlagsConditions() {
|
|
54
|
+
return ReactFeatureFlags.enableFabricRenderer && ReactFeatureFlags.unstable_useFabricInterop;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -34,6 +34,14 @@ public class ReactFeatureFlags {
|
|
|
34
34
|
*/
|
|
35
35
|
public static volatile boolean enableFabricRenderer = false;
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Should this application enable the Fabric Interop Layer for Android? If yes, the application
|
|
39
|
+
* will behave so that it can accept non-Fabric components and render them on Fabric. This toggle
|
|
40
|
+
* is controlling extra logic such as custom event dispatching that are needed for the Fabric
|
|
41
|
+
* Interop Layer to work correctly.
|
|
42
|
+
*/
|
|
43
|
+
public static volatile boolean unstable_useFabricInterop = false;
|
|
44
|
+
|
|
37
45
|
/**
|
|
38
46
|
* Feature flag to enable the new bridgeless architecture. Note: Enabling this will force enable
|
|
39
47
|
* the following flags: `useTurboModules` & `enableFabricRenderer`.
|
package/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultNewArchitectureEntryPoint.kt
CHANGED
|
@@ -31,6 +31,7 @@ object DefaultNewArchitectureEntryPoint {
|
|
|
31
31
|
) {
|
|
32
32
|
ReactFeatureFlags.useTurboModules = turboModulesEnabled
|
|
33
33
|
ReactFeatureFlags.enableFabricRenderer = fabricEnabled
|
|
34
|
+
ReactFeatureFlags.unstable_useFabricInterop = fabricEnabled
|
|
34
35
|
|
|
35
36
|
this.privateFabricEnabled = fabricEnabled
|
|
36
37
|
this.privateTurboModulesEnabled = turboModulesEnabled
|
|
@@ -24,6 +24,7 @@ import android.util.Pair;
|
|
|
24
24
|
import android.view.Gravity;
|
|
25
25
|
import android.view.View;
|
|
26
26
|
import android.widget.EditText;
|
|
27
|
+
import android.widget.LinearLayout;
|
|
27
28
|
import android.widget.TextView;
|
|
28
29
|
import android.widget.Toast;
|
|
29
30
|
import androidx.annotation.Nullable;
|
|
@@ -553,17 +554,30 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
|
|
|
553
554
|
return;
|
|
554
555
|
}
|
|
555
556
|
|
|
556
|
-
final
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
557
|
+
final LinearLayout header = new LinearLayout(getApplicationContext());
|
|
558
|
+
header.setOrientation(LinearLayout.VERTICAL);
|
|
559
|
+
|
|
560
|
+
final TextView title = new TextView(getApplicationContext());
|
|
561
|
+
title.setText("React Native Dev Menu (" + getUniqueTag() + ")");
|
|
562
|
+
title.setPadding(0, 50, 0, 0);
|
|
563
|
+
title.setGravity(Gravity.CENTER);
|
|
564
|
+
title.setTextColor(Color.DKGRAY);
|
|
565
|
+
title.setTextSize(16);
|
|
566
|
+
title.setTypeface(title.getTypeface(), Typeface.BOLD);
|
|
567
|
+
|
|
568
|
+
final TextView jsExecutorLabel = new TextView(getApplicationContext());
|
|
569
|
+
jsExecutorLabel.setText(getJSExecutorDescription());
|
|
570
|
+
jsExecutorLabel.setPadding(0, 20, 0, 0);
|
|
571
|
+
jsExecutorLabel.setGravity(Gravity.CENTER);
|
|
572
|
+
jsExecutorLabel.setTextColor(Color.GRAY);
|
|
573
|
+
jsExecutorLabel.setTextSize(14);
|
|
574
|
+
|
|
575
|
+
header.addView(title);
|
|
576
|
+
header.addView(jsExecutorLabel);
|
|
563
577
|
|
|
564
578
|
mDevOptionsDialog =
|
|
565
579
|
new AlertDialog.Builder(context)
|
|
566
|
-
.setCustomTitle(
|
|
580
|
+
.setCustomTitle(header)
|
|
567
581
|
.setItems(
|
|
568
582
|
options.keySet().toArray(new String[0]),
|
|
569
583
|
new DialogInterface.OnClickListener() {
|
|
@@ -587,6 +601,10 @@ public abstract class DevSupportManagerBase implements DevSupportManager {
|
|
|
587
601
|
}
|
|
588
602
|
}
|
|
589
603
|
|
|
604
|
+
private String getJSExecutorDescription() {
|
|
605
|
+
return "Running " + getReactInstanceDevHelper().getJavaScriptExecutorFactory().toString();
|
|
606
|
+
}
|
|
607
|
+
|
|
590
608
|
/**
|
|
591
609
|
* {@link ReactInstanceDevCommandsHandler} is responsible for enabling/disabling dev support when
|
|
592
610
|
* a React view is attached/detached or when application state changes (e.g. the application is
|
|
@@ -56,6 +56,7 @@ import com.facebook.react.config.ReactFeatureFlags;
|
|
|
56
56
|
import com.facebook.react.fabric.events.EventBeatManager;
|
|
57
57
|
import com.facebook.react.fabric.events.EventEmitterWrapper;
|
|
58
58
|
import com.facebook.react.fabric.events.FabricEventEmitter;
|
|
59
|
+
import com.facebook.react.fabric.interop.InteropEventEmitter;
|
|
59
60
|
import com.facebook.react.fabric.mounting.MountItemDispatcher;
|
|
60
61
|
import com.facebook.react.fabric.mounting.MountingManager;
|
|
61
62
|
import com.facebook.react.fabric.mounting.SurfaceMountingManager;
|
|
@@ -81,6 +82,7 @@ import com.facebook.react.uimanager.ViewManagerRegistry;
|
|
|
81
82
|
import com.facebook.react.uimanager.events.EventCategoryDef;
|
|
82
83
|
import com.facebook.react.uimanager.events.EventDispatcher;
|
|
83
84
|
import com.facebook.react.uimanager.events.EventDispatcherImpl;
|
|
85
|
+
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
|
84
86
|
import com.facebook.react.views.text.TextLayoutManager;
|
|
85
87
|
import com.facebook.react.views.text.TextLayoutManagerMapBuffer;
|
|
86
88
|
import java.util.HashMap;
|
|
@@ -390,6 +392,11 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
|
|
390
392
|
|
|
391
393
|
ReactMarker.addFabricListener(mDevToolsReactPerfLogger);
|
|
392
394
|
}
|
|
395
|
+
if (ReactFeatureFlags.unstable_useFabricInterop) {
|
|
396
|
+
InteropEventEmitter interopEventEmitter = new InteropEventEmitter(mReactApplicationContext);
|
|
397
|
+
mReactApplicationContext.internal_registerInteropModule(
|
|
398
|
+
RCTEventEmitter.class, interopEventEmitter);
|
|
399
|
+
}
|
|
393
400
|
}
|
|
394
401
|
|
|
395
402
|
// This is called on the JS thread (see CatalystInstanceImpl).
|
|
@@ -1171,6 +1178,20 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
|
|
1171
1178
|
}
|
|
1172
1179
|
|
|
1173
1180
|
private class MountItemDispatchListener implements MountItemDispatcher.ItemDispatchListener {
|
|
1181
|
+
@Override
|
|
1182
|
+
public void willMountItems() {
|
|
1183
|
+
for (UIManagerListener listener : mListeners) {
|
|
1184
|
+
listener.willMountItems(FabricUIManager.this);
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
@Override
|
|
1189
|
+
public void didMountItems() {
|
|
1190
|
+
for (UIManagerListener listener : mListeners) {
|
|
1191
|
+
listener.didMountItems(FabricUIManager.this);
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1174
1195
|
@Override
|
|
1175
1196
|
public void didDispatchMountItems() {
|
|
1176
1197
|
for (UIManagerListener listener : mListeners) {
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and 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
|
+
package com.facebook.react.fabric.interop;
|
|
9
|
+
|
|
10
|
+
import androidx.annotation.Nullable;
|
|
11
|
+
import com.facebook.react.bridge.WritableMap;
|
|
12
|
+
import com.facebook.react.common.annotations.VisibleForTesting;
|
|
13
|
+
import com.facebook.react.uimanager.events.Event;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* An {@link Event} class used by the {@link InteropEventEmitter}. This class is just holding the
|
|
17
|
+
* event name and the data which is received by the `receiveEvent` method and will be passed over
|
|
18
|
+
* the the {@link com.facebook.react.uimanager.events.EventDispatcher}
|
|
19
|
+
*/
|
|
20
|
+
class InteropEvent extends Event<InteropEvent> {
|
|
21
|
+
|
|
22
|
+
private final String mName;
|
|
23
|
+
private final WritableMap mEventData;
|
|
24
|
+
|
|
25
|
+
InteropEvent(String name, @Nullable WritableMap eventData, int surfaceId, int viewTag) {
|
|
26
|
+
super(surfaceId, viewTag);
|
|
27
|
+
mName = name;
|
|
28
|
+
mEventData = eventData;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@Override
|
|
32
|
+
public String getEventName() {
|
|
33
|
+
return mName;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@Override
|
|
37
|
+
@VisibleForTesting
|
|
38
|
+
public WritableMap getEventData() {
|
|
39
|
+
return mEventData;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and 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
|
+
package com.facebook.react.fabric.interop;
|
|
9
|
+
|
|
10
|
+
import androidx.annotation.Nullable;
|
|
11
|
+
import com.facebook.react.bridge.ReactContext;
|
|
12
|
+
import com.facebook.react.bridge.WritableArray;
|
|
13
|
+
import com.facebook.react.bridge.WritableMap;
|
|
14
|
+
import com.facebook.react.common.annotations.VisibleForTesting;
|
|
15
|
+
import com.facebook.react.uimanager.UIManagerHelper;
|
|
16
|
+
import com.facebook.react.uimanager.events.EventDispatcher;
|
|
17
|
+
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A reimplementation of {@link RCTEventEmitter} which is using a {@link EventDispatcher} under the
|
|
21
|
+
* hood.
|
|
22
|
+
*
|
|
23
|
+
* <p>On Fabric, you're supposed to use {@link EventDispatcher} to dispatch events. However, we
|
|
24
|
+
* provide an interop layer for non-Fabric migrated components.
|
|
25
|
+
*
|
|
26
|
+
* <p>This instance will be returned if the user is invoking `context.getJsModule(RCTEventEmitter)
|
|
27
|
+
* and is providing support for the `receiveEvent` method, so that non-Fabric ViewManagers can
|
|
28
|
+
* continue to deliver events also when Fabric is turned on.
|
|
29
|
+
*/
|
|
30
|
+
public class InteropEventEmitter implements RCTEventEmitter {
|
|
31
|
+
|
|
32
|
+
private final ReactContext mReactContext;
|
|
33
|
+
|
|
34
|
+
private @Nullable EventDispatcher mEventDispatcherOverride;
|
|
35
|
+
|
|
36
|
+
public InteropEventEmitter(ReactContext reactContext) {
|
|
37
|
+
mReactContext = reactContext;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@Override
|
|
41
|
+
public void receiveEvent(int targetReactTag, String eventName, @Nullable WritableMap eventData) {
|
|
42
|
+
EventDispatcher dispatcher;
|
|
43
|
+
if (mEventDispatcherOverride != null) {
|
|
44
|
+
dispatcher = mEventDispatcherOverride;
|
|
45
|
+
} else {
|
|
46
|
+
dispatcher = UIManagerHelper.getEventDispatcherForReactTag(mReactContext, targetReactTag);
|
|
47
|
+
}
|
|
48
|
+
int surfaceId = UIManagerHelper.getSurfaceId(mReactContext);
|
|
49
|
+
if (dispatcher != null) {
|
|
50
|
+
dispatcher.dispatchEvent(new InteropEvent(eventName, eventData, surfaceId, targetReactTag));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@Override
|
|
55
|
+
public void receiveTouches(
|
|
56
|
+
String eventName, WritableArray touches, WritableArray changedIndices) {
|
|
57
|
+
throw new UnsupportedOperationException(
|
|
58
|
+
"EventEmitter#receiveTouches is not supported by the Fabric Interop Layer");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@VisibleForTesting
|
|
62
|
+
void overrideEventDispatcher(EventDispatcher eventDispatcherOverride) {
|
|
63
|
+
mEventDispatcherOverride = eventDispatcherOverride;
|
|
64
|
+
}
|
|
65
|
+
}
|