Skip to content

Commit 5fb0ad0

Browse files
mdvaccafacebook-github-bot
authored andcommitted
Integrate execution of C++ ViewManagers in React Native Android renderer
Summary: Execution of C++ ViewManagers in RN Android renderer changelog: [internal] internal Reviewed By: sammy-SC Differential Revision: D38725770 fbshipit-source-id: cd18e02940c4cb2559acdaf535e60f98b4cada13
1 parent 0519dfe commit 5fb0ad0

File tree

6 files changed

+86
-5
lines changed

6 files changed

+86
-5
lines changed

ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/mountitems/IntBufferBatchMountItem.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import com.facebook.proguard.annotations.DoNotStrip;
1717
import com.facebook.react.bridge.ReactMarker;
1818
import com.facebook.react.bridge.ReactMarkerConstants;
19+
import com.facebook.react.fabric.CppViewMutationsWrapper;
1920
import com.facebook.react.fabric.events.EventEmitterWrapper;
2021
import com.facebook.react.fabric.mounting.MountingManager;
2122
import com.facebook.react.fabric.mounting.SurfaceMountingManager;
@@ -50,6 +51,7 @@ public class IntBufferBatchMountItem implements MountItem {
5051
static final int INSTRUCTION_UPDATE_PADDING = 512;
5152
static final int INSTRUCTION_UPDATE_OVERFLOW_INSET = 1024;
5253
static final int INSTRUCTION_REMOVE_DELETE_TREE = 2048;
54+
static final int INSTRUCTION_RUN_CPP_VIEWS = 4096;
5355

5456
private final int mSurfaceId;
5557
private final int mCommitNumber;
@@ -97,6 +99,10 @@ private static EventEmitterWrapper castToEventEmitter(Object obj) {
9799
return obj != null ? (EventEmitterWrapper) obj : null;
98100
}
99101

102+
private static CppViewMutationsWrapper castToCppViewMutationWrapper(Object obj) {
103+
return obj != null ? (CppViewMutationsWrapper) obj : null;
104+
}
105+
100106
@Override
101107
public void execute(@NonNull MountingManager mountingManager) {
102108
SurfaceMountingManager surfaceMountingManager = mountingManager.getSurfaceManager(mSurfaceId);
@@ -178,6 +184,8 @@ public void execute(@NonNull MountingManager mountingManager) {
178184
} else if (type == INSTRUCTION_UPDATE_EVENT_EMITTER) {
179185
surfaceMountingManager.updateEventEmitter(
180186
mIntBuffer[i++], castToEventEmitter(mObjBuffer[j++]));
187+
} else if (type == INSTRUCTION_RUN_CPP_VIEWS) {
188+
castToCppViewMutationWrapper(mObjBuffer[j++]).runCppViewMutations();
181189
} else {
182190
throw new IllegalArgumentException(
183191
"Invalid type argument to IntBufferBatchMountItem: " + type + " at index: " + i);
@@ -280,6 +288,9 @@ public String toString() {
280288
} else if (type == INSTRUCTION_UPDATE_EVENT_EMITTER) {
281289
j += 1;
282290
s.append(String.format("UPDATE EVENTEMITTER [%d]\n", mIntBuffer[i++]));
291+
} else if (type == INSTRUCTION_RUN_CPP_VIEWS) {
292+
j += 1;
293+
s.append(String.format("RUN CPP_VIEWS [%d]\n", mIntBuffer[i++]));
283294
} else {
284295
FLog.e(TAG, "String so far: " + s.toString());
285296
throw new IllegalArgumentException(

ReactAndroid/src/main/jni/react/fabric/BUCK

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ rn_xplat_cxx_library(
2424
soname = "libfabricjni.$(ext)",
2525
visibility = ["PUBLIC"],
2626
deps = [
27+
react_native_xplat_target("butter:butter"),
2728
react_native_xplat_target("react/renderer/mapbuffer:mapbuffer"),
2829
react_native_xplat_target("react/config:config"),
2930
react_native_xplat_target("react/renderer/animations:animations"),

ReactAndroid/src/main/jni/react/fabric/Binding.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,13 +382,17 @@ void Binding::installFabricUIManager(
382382
<< this << ").";
383383
}
384384

385+
sharedCppComponentRegistry_ =
386+
std::shared_ptr<const facebook::react::CppComponentRegistry>(
387+
cppComponentRegistry ? cppComponentRegistry : nullptr);
388+
385389
// Use std::lock and std::adopt_lock to prevent deadlocks by locking mutexes
386390
// at the same time
387391
std::unique_lock<butter::shared_mutex> lock(installMutex_);
388392

389393
auto globalJavaUiManager = make_global(javaUIManager);
390-
mountingManager_ =
391-
std::make_shared<FabricMountingManager>(config, globalJavaUiManager);
394+
mountingManager_ = std::make_shared<FabricMountingManager>(
395+
config, sharedCppComponentRegistry_, globalJavaUiManager);
392396

393397
ContextContainer::Shared contextContainer =
394398
std::make_shared<ContextContainer>();

ReactAndroid/src/main/jni/react/fabric/FabricMountItem.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ struct CppMountItem final {
7373
UpdatePadding = 512,
7474
UpdateOverflowInset = 1024,
7575
RemoveDeleteTree = 2048,
76+
RunCPPMutations = 4096
7677
};
7778

7879
#pragma mark - Fields

ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.cpp

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
#include "FabricMountingManager.h"
9+
#include "CppViewMutationsWrapper.h"
910
#include "EventEmitterWrapper.h"
1011
#include "StateWrapperImpl.h"
1112
#include "viewPropConversions.h"
@@ -38,8 +39,10 @@ static bool getFeatureFlagValue(const char *name) {
3839

3940
FabricMountingManager::FabricMountingManager(
4041
std::shared_ptr<const ReactNativeConfig> &config,
42+
std::shared_ptr<const CppComponentRegistry> &cppComponentRegistry,
4143
global_ref<jobject> &javaUIManager)
4244
: javaUIManager_(javaUIManager),
45+
cppComponentRegistry_(cppComponentRegistry),
4346
enableEarlyEventEmitterUpdate_(
4447
config->getBool("react_fabric:enable_early_event_emitter_update")),
4548
disablePreallocateViews_(
@@ -82,6 +85,8 @@ static inline int getIntBufferSizeForType(CppMountItem::Type mountItemType) {
8285
return 7; // tag, parentTag, x, y, w, h, DisplayType
8386
case CppMountItem::Type::UpdateOverflowInset:
8487
return 5; // tag, left, top, right, bottom
88+
case CppMountItem::Type::RunCPPMutations:
89+
return 1;
8590
case CppMountItem::Undefined:
8691
case CppMountItem::Multiple:
8792
return -1;
@@ -124,7 +129,8 @@ static inline void computeBufferSizes(
124129
std::vector<CppMountItem> &cppUpdatePaddingMountItems,
125130
std::vector<CppMountItem> &cppUpdateLayoutMountItems,
126131
std::vector<CppMountItem> &cppUpdateOverflowInsetMountItems,
127-
std::vector<CppMountItem> &cppUpdateEventEmitterMountItems) {
132+
std::vector<CppMountItem> &cppUpdateEventEmitterMountItems,
133+
ShadowViewMutationList &cppViewMutations) {
128134
CppMountItem::Type lastType = CppMountItem::Type::Undefined;
129135
int numSameType = 0;
130136
for (auto const &mountItem : cppCommonMountItems) {
@@ -183,6 +189,11 @@ static inline void computeBufferSizes(
183189
cppDeleteMountItems.size(),
184190
batchMountItemIntsSize,
185191
batchMountItemObjectsSize);
192+
193+
if (cppViewMutations.size() > 0) {
194+
batchMountItemIntsSize++;
195+
batchMountItemObjectsSize++;
196+
}
186197
}
187198

188199
static inline void writeIntBufferTypePreamble(
@@ -293,7 +304,7 @@ void FabricMountingManager::executeMount(
293304
std::vector<CppMountItem> cppUpdateLayoutMountItems;
294305
std::vector<CppMountItem> cppUpdateOverflowInsetMountItems;
295306
std::vector<CppMountItem> cppUpdateEventEmitterMountItems;
296-
307+
auto cppViewMutations = ShadowViewMutationList();
297308
{
298309
std::lock_guard allocatedViewsLock(allocatedViewsMutex_);
299310

@@ -318,6 +329,25 @@ void FabricMountingManager::executeMount(
318329

319330
bool isVirtual = mutation.mutatedViewIsVirtual();
320331

332+
// Detect if the mutation instruction belongs to C++ view managers
333+
if (cppComponentRegistry_) {
334+
auto componentName = newChildShadowView.componentName
335+
? newChildShadowView.componentName
336+
: oldChildShadowView.componentName;
337+
auto name = std::string(componentName);
338+
if (cppComponentRegistry_->containsComponentManager(name)) {
339+
// is this thread safe?
340+
cppViewMutations.push_back(mutation);
341+
342+
// This is a hack that could be avoided by using Portals
343+
// Only execute mutations instructions for Root C++ ViewManagers
344+
// because Root C++ Components have a Android view counterpart.
345+
if (!cppComponentRegistry_->isRootComponent(name)) {
346+
continue;
347+
}
348+
}
349+
}
350+
321351
switch (mutationType) {
322352
case ShadowViewMutation::Create: {
323353
bool revisionCheck =
@@ -502,7 +532,8 @@ void FabricMountingManager::executeMount(
502532
cppUpdatePaddingMountItems,
503533
cppUpdateLayoutMountItems,
504534
cppUpdateOverflowInsetMountItems,
505-
cppUpdateEventEmitterMountItems);
535+
cppUpdateEventEmitterMountItems,
536+
cppViewMutations);
506537

507538
static auto createMountItemsIntBufferBatchContainer =
508539
jni::findClassStatic(UIManagerJavaDescriptor)
@@ -809,6 +840,36 @@ void FabricMountingManager::executeMount(
809840
}
810841
}
811842

843+
if (cppViewMutations.size() > 0) {
844+
writeIntBufferTypePreamble(
845+
CppMountItem::Type::RunCPPMutations,
846+
1,
847+
env,
848+
intBufferArray,
849+
intBufferPosition);
850+
851+
// TODO review this logic and memory mamangement
852+
// this might not be necessary:
853+
// temp[0] = 1234;
854+
// env->SetIntArrayRegion(intBufferArray, intBufferPosition, 1, temp);
855+
// intBufferPosition += 1;
856+
857+
// Do not hold a reference to javaCppMutations from the C++ side.
858+
auto javaCppMutations = CppViewMutationsWrapper::newObjectJavaArgs();
859+
CppViewMutationsWrapper *cppViewMutationsWrapper = cthis(javaCppMutations);
860+
861+
// TODO move this to init methods
862+
cppViewMutationsWrapper->cppComponentRegistry = cppComponentRegistry_;
863+
// TODO is moving the cppViewMutations safe / thread safe?
864+
// cppViewMutations will be accessed from the UI Thread in a near future
865+
// can they dissapear?
866+
cppViewMutationsWrapper->cppViewMutations =
867+
std::make_shared<std::vector<facebook::react::ShadowViewMutation>>(
868+
std::move(cppViewMutations));
869+
870+
(*objBufferArray)[objBufferPosition++] = javaCppMutations.get();
871+
}
872+
812873
// If there are no items, we pass a nullptr instead of passing the object
813874
// through the JNI
814875
auto batch = createMountItemsIntBufferBatchContainer(

ReactAndroid/src/main/jni/react/fabric/FabricMountingManager.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#pragma once
99

10+
#include "CppComponentRegistry.h"
1011
#include "FabricMountItem.h"
1112

1213
#include <react/config/ReactNativeConfig.h>
@@ -33,6 +34,7 @@ class FabricMountingManager final {
3334

3435
FabricMountingManager(
3536
std::shared_ptr<const ReactNativeConfig> &config,
37+
std::shared_ptr<const CppComponentRegistry> &cppComponentRegistry,
3638
jni::global_ref<jobject> &javaUIManager);
3739

3840
void onSurfaceStart(SurfaceId surfaceId);
@@ -68,6 +70,7 @@ class FabricMountingManager final {
6870

6971
butter::map<SurfaceId, butter::set<Tag>> allocatedViewRegistry_{};
7072
std::recursive_mutex allocatedViewsMutex_;
73+
std::shared_ptr<const CppComponentRegistry> cppComponentRegistry_;
7174

7275
bool const enableEarlyEventEmitterUpdate_{false};
7376
bool const disablePreallocateViews_{false};

0 commit comments

Comments
 (0)