Support passing in children directly when cloning nodes (#39817)

Summary:
Update the UIManagerBinding interface to support the upcoming API changes in https://github.com/facebook/react/pull/27458

Changelog: [Internal]

Pull Request resolved: https://github.com/facebook/react-native/pull/39817

Reviewed By: rubennorte, sammy-SC

Differential Revision: D49912532

fbshipit-source-id: 436a3488ad4059467070f4ce41ae2b04dda19019
This commit is contained in:
Pieter De Baets
2023-10-06 08:09:07 -07:00
committed by Facebook GitHub Bot
parent 1719a072fd
commit 239079e457
2 changed files with 57 additions and 29 deletions
@@ -327,25 +327,28 @@ jsi::Value UIManagerBinding::get(
});
}
// Semantic: Clones the node with *same* props and *empty* children.
// Semantic: Clones the node with *same* props and *given* children.
if (methodName == "cloneNodeWithNewChildren") {
auto paramCount = 1;
auto paramCount = 2;
return jsi::Function::createFromHostFunction(
runtime,
name,
paramCount,
[uiManager, methodName, paramCount](
[uiManager, methodName](
jsi::Runtime& runtime,
const jsi::Value& /*thisValue*/,
const jsi::Value* arguments,
size_t count) -> jsi::Value {
validateArgumentCount(runtime, methodName, paramCount, count);
// TODO: re-enable when passChildrenWhenCloningPersistedNodes is
// rolled out
// validateArgumentCount(runtime, methodName, paramCount, count);
return valueFromShadowNode(
runtime,
uiManager->cloneNode(
*shadowNodeFromValue(runtime, arguments[0]),
ShadowNode::emptySharedShadowNodeSharedList()));
count > 1 ? shadowNodeListFromValue(runtime, arguments[1])
: ShadowNode::emptySharedShadowNodeSharedList()));
});
}
@@ -363,7 +366,7 @@ jsi::Value UIManagerBinding::get(
size_t count) -> jsi::Value {
validateArgumentCount(runtime, methodName, paramCount, count);
const auto& rawProps = RawProps(runtime, arguments[1]);
RawProps rawProps(runtime, arguments[1]);
return valueFromShadowNode(
runtime,
uiManager->cloneNode(
@@ -373,26 +376,31 @@ jsi::Value UIManagerBinding::get(
});
}
// Semantic: Clones the node with *given* props and *empty* children.
// Semantic: Clones the node with *given* props and *given* children.
if (methodName == "cloneNodeWithNewChildrenAndProps") {
auto paramCount = 2;
auto paramCount = 3;
return jsi::Function::createFromHostFunction(
runtime,
name,
paramCount,
[uiManager, methodName, paramCount](
[uiManager, methodName](
jsi::Runtime& runtime,
const jsi::Value& /*thisValue*/,
const jsi::Value* arguments,
size_t count) -> jsi::Value {
validateArgumentCount(runtime, methodName, paramCount, count);
// TODO: re-enable when passChildrenWhenCloningPersistedNodes is
// rolled out
// validateArgumentCount(runtime, methodName, paramCount, count);
const auto& rawProps = RawProps(runtime, arguments[1]);
bool hasChildrenArg = count == 3;
RawProps rawProps(runtime, arguments[hasChildrenArg ? 2 : 1]);
return valueFromShadowNode(
runtime,
uiManager->cloneNode(
*shadowNodeFromValue(runtime, arguments[0]),
ShadowNode::emptySharedShadowNodeSharedList(),
hasChildrenArg
? shadowNodeListFromValue(runtime, arguments[1])
: ShadowNode::emptySharedShadowNodeSharedList(),
&rawProps));
});
}
@@ -417,6 +425,7 @@ jsi::Value UIManagerBinding::get(
});
}
// TODO: remove when passChildrenWhenCloningPersistedNodes is rolled out
if (methodName == "createChildSet") {
return jsi::Function::createFromHostFunction(
runtime,
@@ -432,6 +441,7 @@ jsi::Value UIManagerBinding::get(
});
}
// TODO: remove when passChildrenWhenCloningPersistedNodes is rolled out
if (methodName == "appendChildToSet") {
auto paramCount = 2;
return jsi::Function::createFromHostFunction(
@@ -475,17 +485,13 @@ jsi::Value UIManagerBinding::get(
if (!uiManager->backgroundExecutor_ ||
(runtimeSchedulerBinding &&
runtimeSchedulerBinding->getIsSynchronous())) {
auto weakShadowNodeList =
weakShadowNodeListFromValue(runtime, arguments[1]);
auto shadowNodeList =
shadowNodeListFromWeakList(weakShadowNodeList);
if (shadowNodeList) {
uiManager->completeSurface(
surfaceId,
shadowNodeList,
{/* .enableStateReconciliation = */ true,
/* .mountSynchronously = */ false});
}
shadowNodeListFromValue(runtime, arguments[1]);
uiManager->completeSurface(
surfaceId,
shadowNodeList,
{/* .enableStateReconciliation = */ true,
/* .mountSynchronously = */ false});
} else {
auto weakShadowNodeList =
weakShadowNodeListFromValue(runtime, arguments[1]);
@@ -86,17 +86,39 @@ inline static jsi::Value valueFromShadowNode(
}
}
// TODO: once we no longer need to mutate the return value (appendChildToSet)
// make this a SharedListOfShared
inline static ShadowNode::UnsharedListOfShared shadowNodeListFromValue(
jsi::Runtime& runtime,
const jsi::Value& value) {
if (CoreFeatures::useNativeState) {
return value.getObject(runtime)
.getNativeState<ShadowNodeListWrapper>(runtime)
->shadowNodeList;
// TODO: cleanup when passChildrenWhenCloningPersistedNodes is rolled out
jsi::Object object = value.asObject(runtime);
if (object.isArray(runtime)) {
auto jsArray = std::move(object).asArray(runtime);
size_t jsArrayLen = jsArray.length(runtime);
if (jsArrayLen > 0) {
auto shadowNodeArray = std::make_shared<ShadowNode::ListOfShared>();
shadowNodeArray->reserve(jsArrayLen);
for (size_t i = 0; i < jsArrayLen; i++) {
shadowNodeArray->push_back(
shadowNodeFromValue(runtime, jsArray.getValueAtIndex(runtime, i)));
}
return shadowNodeArray;
} else {
// TODO: return ShadowNode::emptySharedShadowNodeSharedList()
return std::make_shared<ShadowNode::ListOfShared>(
ShadowNode::ListOfShared({}));
;
}
} else {
return value.getObject(runtime)
.getHostObject<ShadowNodeListWrapper>(runtime)
->shadowNodeList;
if (CoreFeatures::useNativeState) {
return object.getNativeState<ShadowNodeListWrapper>(runtime)
->shadowNodeList;
} else {
return object.getHostObject<ShadowNodeListWrapper>(runtime)
->shadowNodeList;
}
}
}