Introducing CPP View MutationWrapper

Summary:
CppViewMutationWrapper is a class that will be used to execute operations to mutate C++ Components in React Native Android

changelog: [internal] internal

Reviewed By: sammy-SC

Differential Revision: D38725765

fbshipit-source-id: 3dfe11deb873750a78f6dbbaee82b62134908de4
This commit is contained in:
David Vacca
2022-09-15 09:48:25 -07:00
committed by Facebook GitHub Bot
parent 53d2f1891e
commit a2d2a1df90
4 changed files with 188 additions and 0 deletions
@@ -0,0 +1,47 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.fabric;
import android.annotation.SuppressLint;
import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip;
/**
* This class holds reference to the C++ CppViewMutations object. Instances of this class are
* created on the Bindings.cpp, where the pointer to the cppViewMutations is set.
*/
@SuppressLint("MissingNativeLoadLibrary")
public class CppViewMutationsWrapper {
static {
FabricSoLoader.staticInit();
}
@DoNotStrip private final HybridData mHybridData;
private static native HybridData initHybrid();
private CppViewMutationsWrapper() {
mHybridData = initHybrid();
}
public native void runCppViewMutations();
public synchronized void destroy() {
if (mHybridData != null) {
mHybridData.resetNative();
}
}
private boolean isValid() {
if (mHybridData != null) {
return mHybridData.isValid();
}
return false;
}
}
@@ -0,0 +1,100 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "CppViewMutationsWrapper.h"
#include <react/renderer/core/ReactPrimitives.h>
#include <fbjni/fbjni.h>
#include <glog/logging.h>
using namespace facebook::jni;
namespace facebook {
namespace react {
jni::local_ref<CppViewMutationsWrapper::jhybriddata>
CppViewMutationsWrapper::initHybrid(jni::alias_ref<jclass>) {
return makeCxxInstance();
}
void CppViewMutationsWrapper::registerNatives() {
registerHybrid({
makeNativeMethod("initHybrid", CppViewMutationsWrapper::initHybrid),
makeNativeMethod(
"runCppViewMutations", CppViewMutationsWrapper::runCppViewMutations),
});
}
void CppViewMutationsWrapper::runCppViewMutations() {
// TODO implement rendering logic:
// - caching of componengtManagers of views into maps
// - caching of allocated views
// - logic for each mutation instruction
// - Define API in ComponentManager
// - Define API in Component
// - see RCTMountingManager.mm for logic
for (const auto &mutation : *cppViewMutations) {
const auto &newChildShadowView = mutation.newChildShadowView;
auto &mutationType = mutation.type;
auto componentName = newChildShadowView.componentName;
auto tag = mutation.newChildShadowView.tag;
switch (mutationType) {
case ShadowViewMutation::Create: {
auto component = cppComponentRegistry->createComponentInstance(
componentName, tag, newChildShadowView.props);
break;
}
case ShadowViewMutation::Remove: {
auto parentTag = mutation.parentShadowView.tag;
auto parentComponent =
cppComponentRegistry->getComponentInstance(parentTag);
auto childComponent = cppComponentRegistry->getComponentInstance(
mutation.newChildShadowView.tag);
parentComponent->unmountChildComponent(childComponent, mutation.index);
break;
}
case ShadowViewMutation::Delete: {
cppComponentRegistry->deleteComponentInstance(tag);
break;
}
case ShadowViewMutation::Update: {
auto component = cppComponentRegistry->getComponentInstance(tag);
if (mutation.oldChildShadowView.props !=
mutation.newChildShadowView.props) {
component->updateProps(
mutation.oldChildShadowView.props,
mutation.newChildShadowView.props);
}
break;
}
case ShadowViewMutation::Insert: {
auto parentTag = mutation.parentShadowView.tag;
auto parentComponent =
cppComponentRegistry->getComponentInstance(parentTag);
auto childTag = mutation.newChildShadowView.tag;
auto childComponent =
cppComponentRegistry->getComponentInstance(childTag);
auto oldProps = mutation.oldChildShadowView.props;
auto newProps = mutation.newChildShadowView.props;
childComponent->updateProps(oldProps, newProps);
if (childComponent && parentComponent) {
parentComponent->mountChildComponent(childComponent, mutation.index);
}
break;
}
default: {
break;
}
}
}
}
} // namespace react
} // namespace facebook
@@ -0,0 +1,39 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <react/fabric/CppComponentRegistry.h>
#include <fbjni/fbjni.h>
#include <react/jni/ReadableNativeMap.h>
#include <react/renderer/mounting/ShadowViewMutation.h>
namespace facebook {
namespace react {
class CppViewMutationsWrapper
: public jni::HybridClass<CppViewMutationsWrapper> {
public:
constexpr static const char *const kJavaDescriptor =
"Lcom/facebook/react/fabric/CppViewMutationsWrapper;";
static void registerNatives();
// TODO move this to a constructor or init methods
std::shared_ptr<ShadowViewMutationList> cppViewMutations;
std::shared_ptr<const CppComponentRegistry> cppComponentRegistry;
void runCppViewMutations();
private:
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jclass>);
};
} // namespace react
} // namespace facebook
@@ -10,6 +10,7 @@
#include "Binding.h"
#include "ComponentFactory.h"
#include "CoreComponentsRegistry.h"
#include "CppViewMutationsWrapper.h"
#include "EventBeatManager.h"
#include "EventEmitterWrapper.h"
#include "StateWrapperImpl.h"
@@ -20,6 +21,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
facebook::react::Binding::registerNatives();
facebook::react::EventBeatManager::registerNatives();
facebook::react::EventEmitterWrapper::registerNatives();
facebook::react::CppViewMutationsWrapper::registerNatives();
facebook::react::StateWrapperImpl::registerNatives();
facebook::react::ComponentFactory::registerNatives();
facebook::react::CoreComponentsRegistry::registerNatives();