Skip to content

Commit

Permalink
Always pass props and state to Create mount item
Browse files Browse the repository at this point in the history
Summary: For Litho interop and to resolve T47926405, always pass props and state to Create mount item so that any ViewManager can create view instances with knowledge of initial props and state.

Reviewed By: mdvacca

Differential Revision: D16554082

fbshipit-source-id: 3b19a43347b0fa201a054eec60e82fb77cad3625
  • Loading branch information
JoshuaGross authored and facebook-github-bot committed Jul 30, 2019
1 parent f22a7c6 commit bf5e73e
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ private void preallocateView(
int reactTag,
final String componentName,
@Nullable ReadableMap props,
Object stateWrapper,
@Nullable Object stateWrapper,
boolean isLayoutable) {
ThemedReactContext context = mReactContextForRootTag.get(rootTag);
String component = getFabricComponentName(componentName);
Expand All @@ -239,13 +239,25 @@ private void preallocateView(
@DoNotStrip
@SuppressWarnings("unused")
private MountItem createMountItem(
String componentName, int reactRootTag, int reactTag, boolean isLayoutable) {
String componentName,
@Nullable ReadableMap props,
@Nullable Object stateWrapper,
int reactRootTag,
int reactTag,
boolean isLayoutable) {
String component = getFabricComponentName(componentName);
ThemedReactContext reactContext = mReactContextForRootTag.get(reactRootTag);
if (reactContext == null) {
throw new IllegalArgumentException("Unable to find ReactContext for root: " + reactRootTag);
}
return new CreateMountItem(reactContext, reactRootTag, reactTag, component, isLayoutable);
return new CreateMountItem(
reactContext,
reactRootTag,
reactTag,
component,
props,
(StateWrapper) stateWrapper,
isLayoutable);
}

@DoNotStrip
Expand Down Expand Up @@ -449,6 +461,9 @@ private void dispatchMountItems() {

long batchedExecutionStartTime = SystemClock.uptimeMillis();
for (MountItem mountItem : mountItemsToDispatch) {
if (DEBUG) {
FLog.d(TAG, "dispatchMountItems: Executing mountItem: " + mountItem);
}
mountItem.execute(mMountingManager);
}
mBatchedExecutionTime = SystemClock.uptimeMillis() - batchedExecutionStartTime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -427,13 +427,15 @@ local_ref<JMountItem::javaobject> createDeleteMountItem(
return deleteInstruction(javaUIManager, mutation.oldChildShadowView.tag);
}

// TODO T48019320: because we pass initial props and state to the Create (and preallocate) mount instruction,
// we technically don't need to pass the first Update to any components. Dedupe?
local_ref<JMountItem::javaobject> createCreateMountItem(
const jni::global_ref<jobject> &javaUIManager,
const ShadowViewMutation &mutation,
const Tag surfaceId) {
static auto createJavaInstruction =
jni::findClassStatic(UIManagerJavaDescriptor)
->getMethod<alias_ref<JMountItem>(jstring, jint, jint, jboolean)>(
->getMethod<alias_ref<JMountItem>(jstring, ReadableMap::javaobject, jobject, jint, jint, jboolean)>(
"createMountItem");

auto newChildShadowView = mutation.newChildShadowView;
Expand All @@ -444,9 +446,24 @@ local_ref<JMountItem::javaobject> createCreateMountItem(
jboolean isLayoutable =
newChildShadowView.layoutMetrics != EmptyLayoutMetrics;

local_ref<ReadableMap::javaobject> props = castReadableMap(
ReadableNativeMap::newObjectCxxArgs(newChildShadowView.props->rawProps));

// Do not hold onto Java object from C
// We DO want to hold onto C object from Java, since we don't know the
// lifetime of the Java object
local_ref<StateWrapperImpl::JavaPart> javaStateWrapper = nullptr;
if (newChildShadowView.state != nullptr) {
javaStateWrapper = StateWrapperImpl::newObjectJavaArgs();
StateWrapperImpl *cStateWrapper = cthis(javaStateWrapper);
cStateWrapper->state_ = newChildShadowView.state;
}

return createJavaInstruction(
javaUIManager,
componentName.get(),
props.get(),
(javaStateWrapper != nullptr ? javaStateWrapper.get() : nullptr),
surfaceId,
newChildShadowView.tag,
isLayoutable);
Expand Down Expand Up @@ -514,7 +531,7 @@ void Binding::schedulerDidFinishTransaction(
}
case ShadowViewMutation::Delete: {
mountItems[position++] =
createDeleteMountItem(localJavaUIManager, mutation);
createDeleteMountItem(localJavaUIManager, mutation);

deletedViewTags.insert(mutation.oldChildShadowView.tag);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,11 @@ public void createView(

if (isLayoutable) {
viewManager = mViewManagerRegistry.get(componentName);
// View Managers are responsible for dealing with initial state and props.
view =
mViewFactory.getOrCreateView(
componentName, propsDiffMap, stateWrapper, themedReactContext);
view.setId(reactTag);
if (stateWrapper != null) {
viewManager.updateState(view, propsDiffMap, stateWrapper);
}
}

ViewState viewState = new ViewState(reactTag, view, viewManager);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
*/
package com.facebook.react.fabric.mounting.mountitems;

import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.fabric.mounting.MountingManager;
import com.facebook.react.uimanager.StateWrapper;
import com.facebook.react.uimanager.ThemedReactContext;

public class CreateMountItem implements MountItem {
Expand All @@ -15,24 +18,31 @@ public class CreateMountItem implements MountItem {
private final int mRootTag;
private final int mReactTag;
private final ThemedReactContext mContext;
private final @Nullable ReadableMap mProps;
private final @Nullable StateWrapper mStateWrapper;
private final boolean mIsLayoutable;

public CreateMountItem(
ThemedReactContext context,
int rootTag,
int reactTag,
String component,
@Nullable ReadableMap props,
StateWrapper stateWrapper,
boolean isLayoutable) {
mContext = context;
mComponent = component;
mRootTag = rootTag;
mReactTag = reactTag;
mProps = props;
mStateWrapper = stateWrapper;
mIsLayoutable = isLayoutable;
}

@Override
public void execute(MountingManager mountingManager) {
mountingManager.createView(mContext, mComponent, mReactTag, null, null, mIsLayoutable);
mountingManager.createView(
mContext, mComponent, mReactTag, mProps, mStateWrapper, mIsLayoutable);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ public C createShadowNodeInstance() {
if (initialProps != null) {
updateProperties(view, initialProps);
}
if (stateWrapper != null) {
Object extraData = updateState(view, initialProps, stateWrapper);
if (extraData != null) {
updateExtraData(view, extraData);
}
}
return view;
}

Expand Down Expand Up @@ -150,7 +156,7 @@ protected void onAfterUpdateTransaction(@NonNull T view) {}
* x/y/width/height this is the recommended and thread-safe way of passing extra data from css
* node to the native view counterpart.
*
* <p>TODO(7247021): Replace updateExtraData with generic update props mechanism after D2086999
* <p>TODO T7247021: Replace updateExtraData with generic update props mechanism after D2086999
*/
public abstract void updateExtraData(@NonNull T root, Object extraData);

Expand Down

0 comments on commit bf5e73e

Please sign in to comment.