Reviewed By: priteshrnandgaonkar

Differential Revision: D7339832

fbshipit-source-id: 2de6f47ae7601ac083d3b9fbe10ffaf6307ae760
This commit is contained in:
David Vacca 2018-04-01 18:27:04 -07:00 коммит произвёл Facebook Github Bot
Родитель d58ba8242b
Коммит aff5a75d8e
10 изменённых файлов: 94 добавлений и 58 удалений

Просмотреть файл

@ -10,6 +10,7 @@ import static java.lang.System.arraycopy;
import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.Assertions;
import com.facebook.react.uimanager.annotations.ReactPropertyHolder; import com.facebook.react.uimanager.annotations.ReactPropertyHolder;
import com.facebook.yoga.YogaNodeCloneFunction;
import com.facebook.yoga.YogaAlign; import com.facebook.yoga.YogaAlign;
import com.facebook.yoga.YogaBaselineFunction; import com.facebook.yoga.YogaBaselineFunction;
import com.facebook.yoga.YogaConfig; import com.facebook.yoga.YogaConfig;
@ -21,7 +22,6 @@ import com.facebook.yoga.YogaFlexDirection;
import com.facebook.yoga.YogaJustify; import com.facebook.yoga.YogaJustify;
import com.facebook.yoga.YogaMeasureFunction; import com.facebook.yoga.YogaMeasureFunction;
import com.facebook.yoga.YogaNode; import com.facebook.yoga.YogaNode;
import com.facebook.yoga.YogaNodeClonedFunction;
import com.facebook.yoga.YogaOverflow; import com.facebook.yoga.YogaOverflow;
import com.facebook.yoga.YogaPositionType; import com.facebook.yoga.YogaPositionType;
import com.facebook.yoga.YogaValue; import com.facebook.yoga.YogaValue;
@ -61,17 +61,19 @@ public class ReactShadowNodeImpl implements ReactShadowNode<ReactShadowNodeImpl>
private static final YogaConfig sYogaConfig; private static final YogaConfig sYogaConfig;
static { static {
sYogaConfig = ReactYogaConfigProvider.get(); sYogaConfig = ReactYogaConfigProvider.get();
sYogaConfig.setOnNodeCloned(new YogaNodeClonedFunction() { sYogaConfig.setOnCloneNode(new YogaNodeCloneFunction() {
@Override @Override
public void onNodeCloned(YogaNode oldYogaNode, public YogaNode cloneNode(YogaNode oldYogaNode,
YogaNode newYogaNode,
YogaNode parent, YogaNode parent,
int childIndex) { int childIndex) {
ReactShadowNode parentReactShadowNode = (ReactShadowNode) parent.getData(); ReactShadowNodeImpl parentReactShadowNode = (ReactShadowNodeImpl) parent.getData();
Assertions.assertNotNull(parentReactShadowNode); Assertions.assertNotNull(parentReactShadowNode);
ReactShadowNodeImpl newReactShadowNode = (ReactShadowNodeImpl) oldYogaNode.getData();
ReactShadowNode newReactShadowNode = (ReactShadowNode) newYogaNode.getData();
Assertions.assertNotNull(newReactShadowNode); Assertions.assertNotNull(newReactShadowNode);
ReactShadowNodeImpl newNode = newReactShadowNode.mutableCopy();
parentReactShadowNode.replaceChild(newNode, childIndex);
return newNode.mYogaNode;
} }
}); });
} }
@ -133,6 +135,11 @@ public class ReactShadowNodeImpl implements ReactShadowNode<ReactShadowNodeImpl>
mOriginalReactShadowNode = original; mOriginalReactShadowNode = original;
} }
private void replaceChild(ReactShadowNodeImpl newNode, int childIndex) {
mChildren.remove(childIndex);
mChildren.add(childIndex, newNode);
}
/** /**
* @return a copy of this object (no including copy of its children or the underlying yogaNode). * @return a copy of this object (no including copy of its children or the underlying yogaNode).
*/ */
@ -145,7 +152,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode<ReactShadowNodeImpl>
ReactShadowNodeImpl copy = copy(); ReactShadowNodeImpl copy = copy();
copy.mYogaNode = mYogaNode; copy.mYogaNode = mYogaNode;
// TODO: T26729293 clone YogaNode instead of reusing the same instance // TODO: T26729293 clone YogaNode instead of reusing the same instance
//mYogaNode = original.mYogaNode.clone(); //copy.mYogaNode = mYogaNode.clone();
copy.mNativeChildren = mNativeChildren == null ? null : new ArrayList<>(mNativeChildren); copy.mNativeChildren = mNativeChildren == null ? null : new ArrayList<>(mNativeChildren);
copy.mTotalNativeChildren = mTotalNativeChildren; copy.mTotalNativeChildren = mTotalNativeChildren;
copy.mChildren = mChildren == null ? null : new ArrayList<>(mChildren); copy.mChildren = mChildren == null ? null : new ArrayList<>(mChildren);
@ -165,7 +172,7 @@ public class ReactShadowNodeImpl implements ReactShadowNode<ReactShadowNodeImpl>
ReactShadowNodeImpl copy = copy(); ReactShadowNodeImpl copy = copy();
copy.mYogaNode = mYogaNode; copy.mYogaNode = mYogaNode;
// TODO: T26729293 clone YogaNode instead of reusing the same instance // TODO: T26729293 clone YogaNode instead of reusing the same instance
//mYogaNode = original.mYogaNode.cloneWithNewChildren(); //copy.mYogaNode = mYogaNode.clone();
copy.mNativeChildren = null; copy.mNativeChildren = null;
copy.mChildren = null; copy.mChildren = null;
copy.mTotalNativeChildren = 0; copy.mTotalNativeChildren = 0;

Просмотреть файл

@ -25,7 +25,7 @@ public class YogaConfig {
long mNativePointer; long mNativePointer;
private YogaLogger mLogger; private YogaLogger mLogger;
private YogaNodeClonedFunction mNodeClonedFunction; private YogaNodeCloneFunction mYogaNodeCloneFunction;
private native long jni_YGConfigNew(); private native long jni_YGConfigNew();
public YogaConfig() { public YogaConfig() {
@ -97,16 +97,15 @@ public class YogaConfig {
return mLogger; return mLogger;
} }
private native void jni_YGConfigSetHasNodeClonedFunc(long nativePointer, boolean hasClonedFunc); private native void jni_YGConfigSetHasCloneNodeFunc(long nativePointer, boolean hasClonedFunc);
public void setOnNodeCloned(YogaNodeClonedFunction nodeClonedFunction) { public void setOnCloneNode(YogaNodeCloneFunction cloneYogaNodeFunction) {
mNodeClonedFunction = nodeClonedFunction; mYogaNodeCloneFunction = cloneYogaNodeFunction;
jni_YGConfigSetHasNodeClonedFunc(mNativePointer, nodeClonedFunction != null); jni_YGConfigSetHasCloneNodeFunc(mNativePointer, cloneYogaNodeFunction != null);
} }
@DoNotStrip @DoNotStrip
public final void onNodeCloned( private final YogaNode cloneNode(YogaNode oldNode, YogaNode parent, int childIndex) {
YogaNode oldNode, YogaNode newNode, YogaNode parent, int childIndex) { return mYogaNodeCloneFunction.cloneNode(oldNode, parent, childIndex);
mNodeClonedFunction.onNodeCloned(oldNode, newNode, parent, childIndex);
} }
} }

Просмотреть файл

@ -697,4 +697,18 @@ public class YogaNode implements Cloneable {
public void print() { public void print() {
jni_YGNodePrint(mNativePointer); jni_YGNodePrint(mNativePointer);
} }
/**
* This method replaces the child at childIndex position with the newNode received by parameter.
* This is different than calling removeChildAt and addChildAt because this method ONLY replaces
* the child in the mChildren datastructure. @DoNotStrip: called from JNI
*
* @return the nativePointer of the newNode {@linl YogaNode}
*/
@DoNotStrip
private final long replaceChild(YogaNode newNode, int childIndex) {
mChildren.remove(childIndex);
mChildren.add(childIndex, newNode);
return newNode.mNativePointer;
}
} }

Просмотреть файл

@ -10,8 +10,8 @@ package com.facebook.yoga;
import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.proguard.annotations.DoNotStrip;
@DoNotStrip @DoNotStrip
public interface YogaNodeClonedFunction { public interface YogaNodeCloneFunction {
@DoNotStrip @DoNotStrip
void onNodeCloned(YogaNode oldNode, YogaNode newNode, YogaNode parent, int childIndex); YogaNode cloneNode(YogaNode oldNode, YogaNode parent, int childIndex);
} }

Просмотреть файл

@ -142,31 +142,49 @@ static float YGJNIBaselineFunc(YGNodeRef node, float width, float height) {
} }
} }
static void YGJNIOnNodeClonedFunc( static inline YGNodeRef _jlong2YGNodeRef(jlong addr) {
return reinterpret_cast<YGNodeRef>(static_cast<intptr_t>(addr));
}
static inline YGConfigRef _jlong2YGConfigRef(jlong addr) {
return reinterpret_cast<YGConfigRef>(static_cast<intptr_t>(addr));
}
static YGNodeRef YGJNIOnNodeClonedFunc(
YGNodeRef oldNode, YGNodeRef oldNode,
YGNodeRef newNode,
YGNodeRef parent, YGNodeRef parent,
int childIndex) { int childIndex) {
auto config = oldNode->getConfig(); auto config = oldNode->getConfig();
if (!config) { if (!config) {
return; return nullptr;
} }
static auto onNodeClonedFunc = findClassStatic("com/facebook/yoga/YogaConfig") static auto onNodeClonedFunc = findClassStatic("com/facebook/yoga/YogaConfig")
->getMethod<void( ->getMethod<alias_ref<JYogaNode>(
local_ref<JYogaNode>, local_ref<JYogaNode>,
local_ref<JYogaNode>, local_ref<JYogaNode>,
local_ref<JYogaNode>, jint)>("cloneNode");
jint)>("onNodeCloned");
auto context = reinterpret_cast<YGConfigContext*>(YGConfigGetContext(config)); auto context = reinterpret_cast<YGConfigContext*>(YGConfigGetContext(config));
auto javaConfig = context->config; auto javaConfig = context->config;
onNodeClonedFunc( auto newNode = onNodeClonedFunc(
javaConfig->get(), javaConfig->get(),
YGNodeJobject(oldNode)->lockLocal(), YGNodeJobject(oldNode)->lockLocal(),
YGNodeJobject(newNode)->lockLocal(),
YGNodeJobject(parent)->lockLocal(), YGNodeJobject(parent)->lockLocal(),
childIndex); childIndex);
static auto replaceChild = findClassStatic("com/facebook/yoga/YogaNode")
->getMethod<jlong(
local_ref<JYogaNode>,
jint)>("replaceChild");
jlong newNodeNativePointer = replaceChild(
YGNodeJobject(parent)->lockLocal(),
newNode,
childIndex);
return _jlong2YGNodeRef(newNodeNativePointer);
} }
static YGSize YGJNIMeasureFunc( static YGSize YGJNIMeasureFunc(
@ -234,14 +252,6 @@ static int YGJNILogFunc(const YGConfigRef config,
return result; return result;
} }
static inline YGNodeRef _jlong2YGNodeRef(jlong addr) {
return reinterpret_cast<YGNodeRef>(static_cast<intptr_t>(addr));
}
static inline YGConfigRef _jlong2YGConfigRef(jlong addr) {
return reinterpret_cast<YGConfigRef>(static_cast<intptr_t>(addr));
}
jlong jni_YGNodeNew(alias_ref<jobject> thiz) { jlong jni_YGNodeNew(alias_ref<jobject> thiz) {
const YGNodeRef node = YGNodeNew(); const YGNodeRef node = YGNodeNew();
node->setContext(new weak_ref<jobject>(make_weak(thiz))); node->setContext(new weak_ref<jobject>(make_weak(thiz)));
@ -506,10 +516,10 @@ void jni_YGConfigSetUseLegacyStretchBehaviour(alias_ref<jobject>,
YGConfigSetUseLegacyStretchBehaviour(config, useLegacyStretchBehaviour); YGConfigSetUseLegacyStretchBehaviour(config, useLegacyStretchBehaviour);
} }
void jni_YGConfigSetHasNodeClonedFunc( void jni_YGConfigSetHasCloneNodeFunc(
alias_ref<jobject> thiz, alias_ref<jobject> thiz,
jlong nativePointer, jlong nativePointer,
jboolean hasNodeClonedFunc) { jboolean hasCloneNodeFunc) {
const YGConfigRef config = _jlong2YGConfigRef(nativePointer); const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
auto context = reinterpret_cast<YGConfigContext*>(YGConfigGetContext(config)); auto context = reinterpret_cast<YGConfigContext*>(YGConfigGetContext(config));
if (context && context->config) { if (context && context->config) {
@ -517,15 +527,15 @@ void jni_YGConfigSetHasNodeClonedFunc(
context->config = nullptr; context->config = nullptr;
} }
if (hasNodeClonedFunc) { if (hasCloneNodeFunc) {
if (!context) { if (!context) {
context = new YGConfigContext(); context = new YGConfigContext();
YGConfigSetContext(config, context); YGConfigSetContext(config, context);
} }
context->config = new global_ref<jobject>(make_global(thiz)); context->config = new global_ref<jobject>(make_global(thiz));
YGConfigSetNodeClonedFunc(config, YGJNIOnNodeClonedFunc); YGConfigSetCloneNodeFunc(config, YGJNIOnNodeClonedFunc);
} else { } else {
YGConfigSetNodeClonedFunc(config, nullptr); YGConfigSetCloneNodeFunc(config, nullptr);
} }
} }
@ -652,7 +662,7 @@ jint JNI_OnLoad(JavaVM *vm, void *) {
YGMakeNativeMethod(jni_YGConfigSetPointScaleFactor), YGMakeNativeMethod(jni_YGConfigSetPointScaleFactor),
YGMakeNativeMethod(jni_YGConfigSetUseLegacyStretchBehaviour), YGMakeNativeMethod(jni_YGConfigSetUseLegacyStretchBehaviour),
YGMakeNativeMethod(jni_YGConfigSetLogger), YGMakeNativeMethod(jni_YGConfigSetLogger),
YGMakeNativeMethod(jni_YGConfigSetHasNodeClonedFunc), YGMakeNativeMethod(jni_YGConfigSetHasCloneNodeFunc),
YGMakeNativeMethod( YGMakeNativeMethod(
jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour), jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour),
}); });

Просмотреть файл

@ -24,7 +24,7 @@ SharedYogaConfig YogaLayoutableShadowNode::suitableYogaConfig() {
if (!sharedYogaConfig) { if (!sharedYogaConfig) {
sharedYogaConfig = std::make_shared<YGConfig>(YGConfig({ sharedYogaConfig = std::make_shared<YGConfig>(YGConfig({
.cloneNodeCallback = YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector // .cloneNodeCallback = YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector
})); }));
} }

Просмотреть файл

@ -558,15 +558,18 @@ void YGNode::cloneChildrenIfNeeded() {
return; return;
} }
const YGNodeClonedFunc cloneNodeCallback = config_->cloneNodeCallback; const YGCloneNodeFunc cloneNodeCallback = config_->cloneNodeCallback;
for (uint32_t i = 0; i < childCount; ++i) { for (uint32_t i = 0; i < childCount; ++i) {
const YGNodeRef oldChild = children_[i]; const YGNodeRef oldChild = children_[i];
const YGNodeRef newChild = YGNodeClone(oldChild); YGNodeRef newChild = nullptr;
if (cloneNodeCallback) {
newChild = cloneNodeCallback(oldChild, this, i);
}
if (newChild == nullptr) {
newChild = YGNodeClone(oldChild);
}
replaceChild(newChild, i); replaceChild(newChild, i);
newChild->setParent(this); newChild->setParent(this);
if (cloneNodeCallback) {
cloneNodeCallback(oldChild, newChild, this, i);
}
} }
} }

Просмотреть файл

@ -94,7 +94,7 @@ struct YGConfig {
bool shouldDiffLayoutWithoutLegacyStretchBehaviour; bool shouldDiffLayoutWithoutLegacyStretchBehaviour;
float pointScaleFactor; float pointScaleFactor;
YGLogger logger; YGLogger logger;
YGNodeClonedFunc cloneNodeCallback; YGCloneNodeFunc cloneNodeCallback;
void* context; void* context;
}; };

Просмотреть файл

@ -428,7 +428,7 @@ void YGNodeRemoveChild(const YGNodeRef parent, const YGNodeRef excludedChild) {
// Otherwise we have to clone the node list except for the child we're trying to delete. // Otherwise we have to clone the node list except for the child we're trying to delete.
// We don't want to simply clone all children, because then the host will need to free // We don't want to simply clone all children, because then the host will need to free
// the clone of the child that was just deleted. // the clone of the child that was just deleted.
const YGNodeClonedFunc cloneNodeCallback = const YGCloneNodeFunc cloneNodeCallback =
parent->getConfig()->cloneNodeCallback; parent->getConfig()->cloneNodeCallback;
uint32_t nextInsertIndex = 0; uint32_t nextInsertIndex = 0;
for (uint32_t i = 0; i < childCount; i++) { for (uint32_t i = 0; i < childCount; i++) {
@ -440,12 +440,16 @@ void YGNodeRemoveChild(const YGNodeRef parent, const YGNodeRef excludedChild) {
parent->markDirtyAndPropogate(); parent->markDirtyAndPropogate();
continue; continue;
} }
const YGNodeRef newChild = YGNodeClone(oldChild); YGNodeRef newChild = nullptr;
if (cloneNodeCallback) {
newChild = cloneNodeCallback(oldChild, parent, nextInsertIndex);
}
if (newChild == nullptr) {
newChild = YGNodeClone(oldChild);
}
parent->replaceChild(newChild, nextInsertIndex); parent->replaceChild(newChild, nextInsertIndex);
newChild->setParent(parent); newChild->setParent(parent);
if (cloneNodeCallback) {
cloneNodeCallback(oldChild, newChild, parent, nextInsertIndex);
}
nextInsertIndex++; nextInsertIndex++;
} }
while (nextInsertIndex < childCount) { while (nextInsertIndex < childCount) {
@ -3964,7 +3968,7 @@ void *YGConfigGetContext(const YGConfigRef config) {
return config->context; return config->context;
} }
void YGConfigSetNodeClonedFunc(const YGConfigRef config, const YGNodeClonedFunc callback) { void YGConfigSetCloneNodeFunc(const YGConfigRef config, const YGCloneNodeFunc callback) {
config->cloneNodeCallback = callback; config->cloneNodeCallback = callback;
} }

Просмотреть файл

@ -62,8 +62,7 @@ typedef int (*YGLogger)(const YGConfigRef config,
YGLogLevel level, YGLogLevel level,
const char *format, const char *format,
va_list args); va_list args);
typedef void (*YGNodeClonedFunc)(YGNodeRef oldNode, typedef YGNodeRef (*YGCloneNodeFunc)(YGNodeRef oldNode,
YGNodeRef newNode,
YGNodeRef parent, YGNodeRef parent,
int childIndex); int childIndex);
@ -283,8 +282,8 @@ WIN_EXPORT bool YGConfigIsExperimentalFeatureEnabled(const YGConfigRef config,
WIN_EXPORT void YGConfigSetUseWebDefaults(const YGConfigRef config, const bool enabled); WIN_EXPORT void YGConfigSetUseWebDefaults(const YGConfigRef config, const bool enabled);
WIN_EXPORT bool YGConfigGetUseWebDefaults(const YGConfigRef config); WIN_EXPORT bool YGConfigGetUseWebDefaults(const YGConfigRef config);
WIN_EXPORT void YGConfigSetNodeClonedFunc(const YGConfigRef config, WIN_EXPORT void YGConfigSetCloneNodeFunc(const YGConfigRef config,
const YGNodeClonedFunc callback); const YGCloneNodeFunc callback);
// Export only for C# // Export only for C#
WIN_EXPORT YGConfigRef YGConfigGetDefault(void); WIN_EXPORT YGConfigRef YGConfigGetDefault(void);