Expose instance handles from shadow nodes directly, instead of from event emitters/targets (#37553)

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

## Context

I added some getters in EventTarget/EventEmitter to access the React instance handle for a given shadow node/shadow node family in https://github.com/facebook/react-native/commit/43864a1d6025bfc4483dded115d51f7613018199 (D44022477), so I could implement DOM traversal methods easily.

I wanted to reuse that method to implement `MutationObserver` and `IntersectionObserver`, but unfortunately `EventEmitter`/`EventTarget` only allow access to the instance handle as long as the shadow node is mounted. That makes sense for events, but not for this use case, as with `MutationObserver` we intentionally want to have access to unmounted nodes when creating the list of `addedNodes` and `removedNodes` for the `MutationRecord` (depending on when exactly we generate this list, either `addedNodes` or `removedNodes` wouldn't be mounted).

## Changes

This reverts my original change and adds a new field in `ShadowNodeFamily` to provide access to the `InstanceHandle` at any point (even if the node isn't mounted).

This provides the same guarantees as the original method, keeping weak references to the handles to avoid memory leaks.

Changelog: [internal]

Reviewed By: sammy-SC

Differential Revision: D46149084

fbshipit-source-id: f76abae50134a5d55a98cab42eebeb62084024f9
This commit is contained in:
Rubén Norte
2023-06-08 14:38:00 -07:00
committed by Facebook GitHub Bot
parent a88c0edbd3
commit 325072575a
27 changed files with 195 additions and 148 deletions
@@ -56,8 +56,6 @@ static void testShadowNodeTreeLifeCycleLayoutAnimations(
ViewComponentDescriptor(componentDescriptorParameters);
auto rootComponentDescriptor =
RootComponentDescriptor(componentDescriptorParameters);
auto noopEventEmitter =
std::make_shared<ViewEventEmitter const>(nullptr, -1, eventDispatcher);
PropsParserContext parserContext{-1, *contextContainer};
@@ -95,7 +93,7 @@ static void testShadowNodeTreeLifeCycleLayoutAnimations(
auto surfaceId = SurfaceId(surfaceIdInt);
auto family = rootComponentDescriptor.createFamily(
{Tag(surfaceIdInt), surfaceId, nullptr}, nullptr);
{Tag(surfaceIdInt), surfaceId, nullptr});
// Creating an initial root shadow node.
auto emptyRootNode = std::const_pointer_cast<RootShadowNode>(
@@ -126,12 +126,13 @@ ShadowNode::Shared ComponentDescriptorRegistry::createNode(
std::string const &viewName,
SurfaceId surfaceId,
folly::dynamic const &propsDynamic,
SharedEventTarget const &eventTarget) const {
InstanceHandle::Shared const &instanceHandle) const {
auto unifiedComponentName = componentNameByReactViewName(viewName);
auto const &componentDescriptor = this->at(unifiedComponentName);
auto const fragment = ShadowNodeFamilyFragment{tag, surfaceId, nullptr};
auto family = componentDescriptor.createFamily(fragment, eventTarget);
auto const fragment =
ShadowNodeFamilyFragment{tag, surfaceId, instanceHandle};
auto family = componentDescriptor.createFamily(fragment);
auto const props = componentDescriptor.cloneProps(
PropsParserContext{surfaceId, *contextContainer_.get()},
nullptr,
@@ -14,6 +14,7 @@
#include <react/renderer/componentregistry/ComponentDescriptorProvider.h>
#include <react/renderer/core/ComponentDescriptor.h>
#include <react/renderer/core/InstanceHandle.h>
#include <react/utils/ContextContainer.h>
namespace facebook::react {
@@ -59,7 +60,7 @@ class ComponentDescriptorRegistry {
std::string const &viewName,
SurfaceId surfaceId,
folly::dynamic const &props,
SharedEventTarget const &eventTarget) const;
InstanceHandle::Shared const &instanceHandle) const;
void setFallbackComponentDescriptor(
const SharedComponentDescriptor &descriptor);
@@ -8,6 +8,8 @@
#pragma once
#include <react/renderer/core/EventDispatcher.h>
#include <react/renderer/core/EventEmitter.h>
#include <react/renderer/core/InstanceHandle.h>
#include <react/renderer/core/Props.h>
#include <react/renderer/core/PropsParserContext.h>
#include <react/renderer/core/RawPropsParser.h>
@@ -136,8 +138,13 @@ class ComponentDescriptor {
* Creates a shadow node family for particular node.
*/
virtual ShadowNodeFamily::Shared createFamily(
ShadowNodeFamilyFragment const &fragment,
SharedEventTarget eventTarget) const = 0;
ShadowNodeFamilyFragment const &fragment) const = 0;
/*
* Creates an event emitter for particular node.
*/
virtual SharedEventEmitter createEventEmitter(
InstanceHandle::Shared const &instanceHandle) const = 0;
protected:
EventDispatcher::Weak eventDispatcher_;
@@ -180,17 +180,20 @@ class ConcreteComponentDescriptor : public ComponentDescriptor {
}
ShadowNodeFamily::Shared createFamily(
ShadowNodeFamilyFragment const &fragment,
SharedEventTarget eventTarget) const override {
auto eventEmitter = std::make_shared<ConcreteEventEmitter const>(
std::move(eventTarget), fragment.tag, eventDispatcher_);
ShadowNodeFamilyFragment const &fragment) const override {
return std::make_shared<ShadowNodeFamily>(
ShadowNodeFamilyFragment{
fragment.tag, fragment.surfaceId, eventEmitter},
fragment.tag, fragment.surfaceId, fragment.instanceHandle},
eventDispatcher_,
*this);
}
SharedEventEmitter createEventEmitter(
InstanceHandle::Shared const &instanceHandle) const override {
return std::make_shared<ConcreteEventEmitter const>(
std::make_shared<EventTarget>(instanceHandle), eventDispatcher_);
}
protected:
/*
* Called immediately after `ShadowNode` is created or cloned.
@@ -43,7 +43,6 @@ ValueFactory EventEmitter::defaultPayloadFactory() {
EventEmitter::EventEmitter(
SharedEventTarget eventTarget,
Tag /*tag*/,
EventDispatcher::Weak eventDispatcher)
: eventTarget_(std::move(eventTarget)),
eventDispatcher_(std::move(eventDispatcher)) {}
@@ -131,8 +130,4 @@ void EventEmitter::setEnabled(bool enabled) const {
}
}
const SharedEventTarget &EventEmitter::getEventTarget() const {
return eventTarget_;
}
} // namespace facebook::react
@@ -38,7 +38,6 @@ class EventEmitter {
EventEmitter(
SharedEventTarget eventTarget,
Tag tag,
EventDispatcher::Weak eventDispatcher);
virtual ~EventEmitter() = default;
@@ -55,8 +54,6 @@ class EventEmitter {
*/
void setEnabled(bool enabled) const;
SharedEventTarget const &getEventTarget() const;
protected:
#ifdef ANDROID
// We need this temporarily due to lack of Java-counterparts for particular
@@ -13,14 +13,9 @@ namespace facebook::react {
using Tag = EventTarget::Tag;
EventTarget::EventTarget(
jsi::Runtime &runtime,
jsi::Value const &instanceHandle,
Tag tag)
: weakInstanceHandle_(
jsi::WeakObject(runtime, instanceHandle.asObject(runtime))),
strongInstanceHandle_(jsi::Value::null()),
tag_(tag) {}
EventTarget::EventTarget(InstanceHandle::Shared instanceHandle)
: instanceHandle_(std::move(instanceHandle)),
strongInstanceHandle_(jsi::Value::null()) {}
void EventTarget::setEnabled(bool enabled) const {
enabled_ = enabled;
@@ -31,7 +26,7 @@ void EventTarget::retain(jsi::Runtime &runtime) const {
return;
}
strongInstanceHandle_ = weakInstanceHandle_.lock(runtime);
strongInstanceHandle_ = instanceHandle_->getInstanceHandle(runtime);
// Having a `null` or `undefined` object here indicates that
// `weakInstanceHandle_` was already deallocated. This should *not* happen by
@@ -62,7 +57,7 @@ jsi::Value EventTarget::getInstanceHandle(jsi::Runtime &runtime) const {
}
Tag EventTarget::getTag() const {
return tag_;
return instanceHandle_->getTag();
}
} // namespace facebook::react
@@ -7,9 +7,9 @@
#pragma once
#include <memory>
#include <jsi/jsi.h>
#include <react/renderer/core/InstanceHandle.h>
#include <memory>
namespace facebook::react {
@@ -34,7 +34,7 @@ class EventTarget {
/*
* Constructs an EventTarget from a weak instance handler and a tag.
*/
EventTarget(jsi::Runtime &runtime, jsi::Value const &instanceHandle, Tag tag);
explicit EventTarget(InstanceHandle::Shared instanceHandle);
/*
* Sets the `enabled` flag that allows creating a strong instance handle from
@@ -65,10 +65,9 @@ class EventTarget {
Tag getTag() const;
private:
const InstanceHandle::Shared instanceHandle_;
mutable bool enabled_{false}; // Protected by `EventEmitter::DispatchMutex()`.
mutable jsi::WeakObject weakInstanceHandle_; // Protected by `jsi::Runtime &`.
mutable jsi::Value strongInstanceHandle_; // Protected by `jsi::Runtime &`.
Tag tag_;
};
using SharedEventTarget = std::shared_ptr<const EventTarget>;
@@ -0,0 +1,28 @@
/*
* 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 "InstanceHandle.h"
namespace facebook::react {
InstanceHandle::InstanceHandle(
jsi::Runtime &runtime,
jsi::Value const &instanceHandle,
Tag tag)
: weakInstanceHandle_(
jsi::WeakObject(runtime, instanceHandle.asObject(runtime))),
tag_(tag) {}
jsi::Value InstanceHandle::getInstanceHandle(jsi::Runtime &runtime) const {
return weakInstanceHandle_.lock(runtime);
}
Tag InstanceHandle::getTag() const {
return tag_;
}
} // namespace facebook::react
@@ -0,0 +1,41 @@
/*
* 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 <jsi/jsi.h>
#include <react/renderer/core/ReactPrimitives.h>
#include <memory>
namespace facebook::react {
class InstanceHandle {
public:
using Shared = std::shared_ptr<const InstanceHandle>;
InstanceHandle(
jsi::Runtime &runtime,
jsi::Value const &instanceHandle,
Tag tag);
/*
* Creates and returns the `instanceHandle`.
* Returns `null` if the `instanceHandle` is not retained at this moment.
*/
jsi::Value getInstanceHandle(jsi::Runtime &runtime) const;
/*
* Deprecated. Do not use.
*/
Tag getTag() const;
private:
const jsi::WeakObject weakInstanceHandle_; // Protected by `jsi::Runtime &`.
const Tag tag_;
};
} // namespace facebook::react
@@ -17,8 +17,6 @@ namespace facebook::react {
* `Tag` and `InstanceHandle` are used to address React Native components.
*/
using Tag = int32_t;
using InstanceHandle = struct InstanceHandleDummyStruct {
} *;
/*
* An id of a running Surface instance that is used to refer to the instance.
@@ -174,6 +174,15 @@ const SharedEventEmitter &ShadowNode::getEventEmitter() const {
return family_->eventEmitter_;
}
jsi::Value ShadowNode::getInstanceHandle(jsi::Runtime &runtime) const {
auto instanceHandle = family_->instanceHandle_;
if (instanceHandle == nullptr) {
return jsi::Value::null();
}
return instanceHandle->getInstanceHandle(runtime);
}
Tag ShadowNode::getTag() const {
return family_->tag_;
}
@@ -123,6 +123,7 @@ class ShadowNode : public Sealable,
Props::Shared const &getProps() const;
ListOfShared const &getChildren() const;
SharedEventEmitter const &getEventEmitter() const;
jsi::Value getInstanceHandle(jsi::Runtime &runtime) const;
Tag getTag() const;
SurfaceId getSurfaceId() const;
@@ -25,7 +25,9 @@ ShadowNodeFamily::ShadowNodeFamily(
: eventDispatcher_(std::move(eventDispatcher)),
tag_(fragment.tag),
surfaceId_(fragment.surfaceId),
eventEmitter_(fragment.eventEmitter),
instanceHandle_(fragment.instanceHandle),
eventEmitter_(
componentDescriptor.createEventEmitter(fragment.instanceHandle)),
componentDescriptor_(componentDescriptor),
componentHandle_(componentDescriptor.getComponentHandle()),
componentName_(componentDescriptor.getComponentName()) {}
@@ -13,6 +13,7 @@
#include <butter/small_vector.h>
#include <react/renderer/core/EventEmitter.h>
#include <react/renderer/core/InstanceHandle.h>
#include <react/renderer/core/ReactPrimitives.h>
namespace facebook::react {
@@ -36,7 +37,7 @@ class State;
struct ShadowNodeFamilyFragment {
Tag const tag;
SurfaceId const surfaceId;
EventEmitter::Shared const &eventEmitter;
InstanceHandle::Shared const &instanceHandle;
};
/*
@@ -137,6 +138,11 @@ class ShadowNodeFamily final {
*/
SurfaceId const surfaceId_;
/*
* Weak reference to the React instance handle
*/
InstanceHandle::Shared const instanceHandle_;
/*
* `EventEmitter` associated with all nodes of the family.
*/
@@ -29,13 +29,11 @@ TEST(ComponentDescriptorTest, createShadowNode) {
const auto &raw = RawProps(folly::dynamic::object("nativeID", "abc"));
Props::Shared props = descriptor->cloneProps(parserContext, nullptr, raw);
auto family = descriptor->createFamily(
ShadowNodeFamilyFragment{
/* .tag = */ 9,
/* .surfaceId = */ 1,
/* .eventEmitter = */ nullptr,
},
nullptr);
auto family = descriptor->createFamily(ShadowNodeFamilyFragment{
/* .tag = */ 9,
/* .surfaceId = */ 1,
/* .instanceHandle = */ nullptr,
});
ShadowNode::Shared node = descriptor->createShadowNode(
ShadowNodeFragment{
@@ -62,13 +60,11 @@ TEST(ComponentDescriptorTest, cloneShadowNode) {
const auto &raw = RawProps(folly::dynamic::object("nativeID", "abc"));
Props::Shared props = descriptor->cloneProps(parserContext, nullptr, raw);
auto family = descriptor->createFamily(
ShadowNodeFamilyFragment{
/* .tag = */ 9,
/* .surfaceId = */ 1,
/* .eventEmitter = */ nullptr,
},
nullptr);
auto family = descriptor->createFamily(ShadowNodeFamilyFragment{
/* .tag = */ 9,
/* .surfaceId = */ 1,
/* .instanceHandle = */ nullptr,
});
ShadowNode::Shared node = descriptor->createShadowNode(
ShadowNodeFragment{
/* .props = */ props,
@@ -97,37 +93,31 @@ TEST(ComponentDescriptorTest, appendChild) {
const auto &raw = RawProps(folly::dynamic::object("nativeID", "abc"));
Props::Shared props = descriptor->cloneProps(parserContext, nullptr, raw);
auto family1 = descriptor->createFamily(
ShadowNodeFamilyFragment{
/* .tag = */ 1,
/* .surfaceId = */ 1,
/* .eventEmitter = */ nullptr,
},
nullptr);
auto family1 = descriptor->createFamily(ShadowNodeFamilyFragment{
/* .tag = */ 1,
/* .surfaceId = */ 1,
/* .instanceHandle = */ nullptr,
});
ShadowNode::Shared node1 = descriptor->createShadowNode(
ShadowNodeFragment{
/* .props = */ props,
},
family1);
auto family2 = descriptor->createFamily(
ShadowNodeFamilyFragment{
/* .tag = */ 2,
/* .surfaceId = */ 1,
/* .eventEmitter = */ nullptr,
},
nullptr);
auto family2 = descriptor->createFamily(ShadowNodeFamilyFragment{
/* .tag = */ 2,
/* .surfaceId = */ 1,
/* .instanceHandle = */ nullptr,
});
ShadowNode::Shared node2 = descriptor->createShadowNode(
ShadowNodeFragment{
/* .props = */ props,
},
family2);
auto family3 = descriptor->createFamily(
ShadowNodeFamilyFragment{
/* .tag = */ 3,
/* .surfaceId = */ 1,
/* .eventEmitter = */ nullptr,
},
nullptr);
auto family3 = descriptor->createFamily(ShadowNodeFamilyFragment{
/* .tag = */ 3,
/* .surfaceId = */ 1,
/* .instanceHandle = */ nullptr,
});
ShadowNode::Shared node3 = descriptor->createShadowNode(
ShadowNodeFragment{
/* .props = */ props,
@@ -41,7 +41,7 @@ class ShadowNodeTest : public ::testing::Test {
ShadowNodeFamilyFragment{
/* .tag = */ 11,
/* .surfaceId = */ surfaceId_,
/* .eventEmitter = */ nullptr,
/* .instanceHandle = */ nullptr,
},
eventDispatcher_,
componentDescriptor_);
@@ -57,7 +57,7 @@ class ShadowNodeTest : public ::testing::Test {
ShadowNodeFamilyFragment{
/* .tag = */ 12,
/* .surfaceId = */ surfaceId_,
/* .eventEmitter = */ nullptr,
/* .instanceHandle = */ nullptr,
},
eventDispatcher_,
componentDescriptor_);
@@ -73,7 +73,7 @@ class ShadowNodeTest : public ::testing::Test {
ShadowNodeFamilyFragment{
/* .tag = */ 13,
/* .surfaceId = */ surfaceId_,
/* .eventEmitter = */ nullptr,
/* .instanceHandle = */ nullptr,
},
eventDispatcher_,
componentDescriptor_);
@@ -92,7 +92,7 @@ class ShadowNodeTest : public ::testing::Test {
ShadowNodeFamilyFragment{
/* .tag = */ 15,
/* .surfaceId = */ surfaceId_,
/* .eventEmitter = */ nullptr,
/* .instanceHandle = */ nullptr,
},
eventDispatcher_,
componentDescriptor_);
@@ -108,7 +108,7 @@ class ShadowNodeTest : public ::testing::Test {
ShadowNodeFamilyFragment{
/* .tag = */ 16,
/* .surfaceId = */ surfaceId_,
/* .eventEmitter = */ nullptr,
/* .instanceHandle = */ nullptr,
},
eventDispatcher_,
componentDescriptor_);
@@ -127,7 +127,7 @@ class ShadowNodeTest : public ::testing::Test {
ShadowNodeFamilyFragment{
/* .tag = */ 17,
/* .surfaceId = */ surfaceId_,
/* .eventEmitter = */ nullptr,
/* .instanceHandle = */ nullptr,
},
eventDispatcher_,
componentDescriptor_);
@@ -143,7 +143,7 @@ class ShadowNodeTest : public ::testing::Test {
ShadowNodeFamilyFragment{
/* .tag = */ 18,
/* .surfaceId = */ surfaceId_,
/* .eventEmitter = */ nullptr,
/* .instanceHandle = */ nullptr,
},
eventDispatcher_,
componentDescriptor_);
@@ -174,7 +174,7 @@ TEST_F(ShadowNodeTest, handleShadowNodeCreation) {
EXPECT_STREQ(nodeZ_->getComponentName(), "Test");
EXPECT_EQ(nodeZ_->getTag(), 18);
EXPECT_EQ(nodeZ_->getSurfaceId(), surfaceId_);
EXPECT_EQ(nodeZ_->getEventEmitter(), nullptr);
EXPECT_NE(nodeZ_->getEventEmitter(), nullptr);
EXPECT_EQ(nodeZ_->getChildren().size(), 0);
}
@@ -238,7 +238,7 @@ TEST_F(ShadowNodeTest, handleState) {
ShadowNodeFamilyFragment{
/* .tag = */ 9,
/* .surfaceId = */ surfaceId_,
/* .eventEmitter = */ nullptr,
/* .instanceHandle = */ nullptr,
},
eventDispatcher_,
componentDescriptor_);
@@ -26,10 +26,8 @@ ShadowNode::Unshared ComponentBuilder::build(
children.push_back(build(childFragment));
}
auto family = componentDescriptor.createFamily(
ShadowNodeFamilyFragment{
elementFragment.tag, elementFragment.surfaceId, nullptr},
nullptr);
auto family = componentDescriptor.createFamily(ShadowNodeFamilyFragment{
elementFragment.tag, elementFragment.surfaceId, nullptr});
auto initialState =
componentDescriptor.createInitialState(elementFragment.props, family);
@@ -225,9 +225,6 @@ ShadowTree::ShadowTree(
ShadowTreeDelegate const &delegate,
ContextContainer const &contextContainer)
: surfaceId_(surfaceId), delegate_(delegate) {
const auto noopEventEmitter = std::make_shared<const ViewEventEmitter>(
nullptr, -1, std::shared_ptr<const EventDispatcher>());
static auto globalRootComponentDescriptor =
std::make_unique<RootComponentDescriptor const>(
ComponentDescriptorParameters{
@@ -239,9 +236,8 @@ ShadowTree::ShadowTree(
layoutConstraints,
layoutContext);
auto const fragment =
ShadowNodeFamilyFragment{surfaceId, surfaceId, noopEventEmitter};
auto family = globalRootComponentDescriptor->createFamily(fragment, nullptr);
auto const fragment = ShadowNodeFamilyFragment{surfaceId, surfaceId, nullptr};
auto family = globalRootComponentDescriptor->createFamily(fragment);
auto rootShadowNode = std::static_pointer_cast<const RootShadowNode>(
globalRootComponentDescriptor->createShadowNode(
@@ -53,7 +53,7 @@ static ShadowNode::Shared makeNode(
return componentDescriptor.createShadowNode(
ShadowNodeFragment{
props, std::make_shared<ShadowNode::ListOfShared>(children)},
componentDescriptor.createFamily({tag, SurfaceId(1), nullptr}, nullptr));
componentDescriptor.createFamily({tag, SurfaceId(1), nullptr}));
}
/**
@@ -79,8 +79,8 @@ TEST(MountingTest, testReorderingInstructionGeneration) {
auto rootComponentDescriptor =
RootComponentDescriptor(componentDescriptorParameters);
auto rootFamily = rootComponentDescriptor.createFamily(
{Tag(1), SurfaceId(1), nullptr}, nullptr);
auto rootFamily =
rootComponentDescriptor.createFamily({Tag(1), SurfaceId(1), nullptr});
// Creating an initial root shadow node.
auto emptyRootNode = std::const_pointer_cast<RootShadowNode>(
@@ -110,8 +110,8 @@ TEST(MountingTest, testReorderingInstructionGeneration) {
auto childJ = makeNode(viewComponentDescriptor, 109, {});
auto childK = makeNode(viewComponentDescriptor, 110, {});
auto family = viewComponentDescriptor.createFamily(
{10, SurfaceId(1), nullptr}, nullptr);
auto family =
viewComponentDescriptor.createFamily({10, SurfaceId(1), nullptr});
// Construct "identical" shadow nodes: they differ only in children.
auto shadowNodeV1 = viewComponentDescriptor.createShadowNode(
@@ -390,8 +390,8 @@ TEST(MountingTest, testViewReparentingInstructionGeneration) {
auto rootComponentDescriptor =
RootComponentDescriptor(componentDescriptorParameters);
auto rootFamily = rootComponentDescriptor.createFamily(
{Tag(1), SurfaceId(1), nullptr}, nullptr);
auto rootFamily =
rootComponentDescriptor.createFamily({Tag(1), SurfaceId(1), nullptr});
// Creating an initial root shadow node.
auto emptyRootNode = std::const_pointer_cast<RootShadowNode>(
@@ -422,8 +422,8 @@ TEST(MountingTest, testViewReparentingInstructionGeneration) {
auto childJ = makeNode(viewComponentDescriptor, 109, {});
auto childK = makeNode(viewComponentDescriptor, 110, {});
auto family = viewComponentDescriptor.createFamily(
{10, SurfaceId(1), nullptr}, nullptr);
auto family =
viewComponentDescriptor.createFamily({10, SurfaceId(1), nullptr});
auto reparentedViewA = makeNode(
viewComponentDescriptor,
@@ -42,8 +42,6 @@ static void testShadowNodeTreeLifeCycle(
ViewComponentDescriptor(componentDescriptorParameters);
auto rootComponentDescriptor =
RootComponentDescriptor(componentDescriptorParameters);
auto noopEventEmitter =
std::make_shared<ViewEventEmitter const>(nullptr, -1, eventDispatcher);
PropsParserContext parserContext{-1, *contextContainer};
@@ -52,8 +50,8 @@ static void testShadowNodeTreeLifeCycle(
for (int i = 0; i < repeats; i++) {
allNodes.clear();
auto family = rootComponentDescriptor.createFamily(
{Tag(1), SurfaceId(1), nullptr}, nullptr);
auto family =
rootComponentDescriptor.createFamily({Tag(1), SurfaceId(1), nullptr});
// Creating an initial root shadow node.
auto emptyRootNode = std::const_pointer_cast<RootShadowNode>(
@@ -195,8 +193,6 @@ static void testShadowNodeTreeLifeCycleExtensiveFlatteningUnflattening(
ViewComponentDescriptor(componentDescriptorParameters);
auto rootComponentDescriptor =
RootComponentDescriptor(componentDescriptorParameters);
auto noopEventEmitter =
std::make_shared<ViewEventEmitter const>(nullptr, -1, eventDispatcher);
PropsParserContext parserContext{-1, *contextContainer};
@@ -205,8 +201,8 @@ static void testShadowNodeTreeLifeCycleExtensiveFlatteningUnflattening(
for (int i = 0; i < repeats; i++) {
allNodes.clear();
auto family = rootComponentDescriptor.createFamily(
{Tag(1), SurfaceId(1), nullptr}, nullptr);
auto family =
rootComponentDescriptor.createFamily({Tag(1), SurfaceId(1), nullptr});
// Creating an initial root shadow node.
auto emptyRootNode = std::const_pointer_cast<RootShadowNode>(
@@ -68,7 +68,7 @@ ShadowNode::Shared UIManager::createNode(
std::string const &name,
SurfaceId surfaceId,
const RawProps &rawProps,
SharedEventTarget eventTarget) const {
const InstanceHandle::Shared &instanceHandle) const {
SystraceSection s("UIManager::createNode");
auto &componentDescriptor = componentDescriptorRegistry_->at(name);
@@ -77,9 +77,9 @@ ShadowNode::Shared UIManager::createNode(
PropsParserContext propsParserContext{surfaceId, *contextContainer_.get()};
auto const fragment = ShadowNodeFamilyFragment{tag, surfaceId, nullptr};
auto family =
componentDescriptor.createFamily(fragment, std::move(eventTarget));
auto const fragment =
ShadowNodeFamilyFragment{tag, surfaceId, instanceHandle};
auto family = componentDescriptor.createFamily(fragment);
auto const props =
componentDescriptor.cloneProps(propsParserContext, nullptr, rawProps);
auto const state = componentDescriptor.createInitialState(props, family);
@@ -14,6 +14,7 @@
#include <shared_mutex>
#include <react/renderer/componentregistry/ComponentDescriptorRegistry.h>
#include <react/renderer/core/InstanceHandle.h>
#include <react/renderer/core/RawValue.h>
#include <react/renderer/core/ShadowNode.h>
#include <react/renderer/core/StateData.h>
@@ -134,7 +135,7 @@ class UIManager final : public ShadowTreeDelegate {
std::string const &componentName,
SurfaceId surfaceId,
const RawProps &props,
SharedEventTarget eventTarget) const;
const InstanceHandle::Shared &instanceHandle) const;
ShadowNode::Shared cloneNode(
ShadowNode const &shadowNode,
@@ -186,12 +186,13 @@ jsi::Value UIManagerBinding::get(
jsi::Value const & /*thisValue*/,
jsi::Value const *arguments,
size_t /*count*/) noexcept -> jsi::Value {
auto eventTarget =
eventTargetFromValue(runtime, arguments[4], arguments[0]);
if (!eventTarget) {
auto instanceHandle =
instanceHandleFromValue(runtime, arguments[4], arguments[0]);
if (!instanceHandle) {
react_native_assert(false);
return jsi::Value::undefined();
}
return valueFromShadowNode(
runtime,
uiManager->createNode(
@@ -199,7 +200,7 @@ jsi::Value UIManagerBinding::get(
stringFromValue(runtime, arguments[1]),
surfaceIdFromValue(runtime, arguments[2]),
RawProps(runtime, arguments[3]),
eventTarget));
instanceHandle));
});
}
@@ -798,7 +799,7 @@ jsi::Value UIManagerBinding::get(
return jsi::Value::null();
}
return getInstanceHandleFromShadowNode(parentShadowNode, runtime);
return (*parentShadowNode).getInstanceHandle(runtime);
});
}
@@ -1006,8 +1007,7 @@ jsi::Value UIManagerBinding::get(
return jsi::Array::createWithElements(
runtime,
getInstanceHandleFromShadowNode(
newestParentOfShadowNode, runtime),
(*newestParentOfShadowNode).getInstanceHandle(runtime),
jsi::Value{runtime, (double)offsetTop},
jsi::Value{runtime, (double)offsetLeft});
});
@@ -142,16 +142,16 @@ inline static Tag tagFromValue(jsi::Value const &value) {
return (Tag)value.getNumber();
}
inline static SharedEventTarget eventTargetFromValue(
inline static InstanceHandle::Shared instanceHandleFromValue(
jsi::Runtime &runtime,
jsi::Value const &eventTargetValue,
jsi::Value const &instanceHandleValue,
jsi::Value const &tagValue) {
react_native_assert(!eventTargetValue.isNull());
if (eventTargetValue.isNull()) {
react_native_assert(!instanceHandleValue.isNull());
if (instanceHandleValue.isNull()) {
return nullptr;
}
return std::make_shared<EventTarget>(
runtime, eventTargetValue, tagFromValue(tagValue));
return std::make_shared<InstanceHandle>(
runtime, instanceHandleValue, tagFromValue(tagValue));
}
inline static SurfaceId surfaceIdFromValue(
@@ -185,21 +185,6 @@ inline static folly::dynamic commandArgsFromValue(
return jsi::dynamicFromValue(runtime, value);
}
inline static jsi::Value getInstanceHandleFromShadowNode(
ShadowNode::Shared shadowNode,
jsi::Runtime &runtime) {
auto eventTarget = shadowNode->getEventEmitter()->getEventTarget();
// shadowNode is probably a RootShadowNode and they don't have
// event targets.
if (eventTarget == nullptr) {
return jsi::Value::null();
}
eventTarget->retain(runtime);
auto instanceHandle = eventTarget->getInstanceHandle(runtime);
eventTarget->release(runtime);
return instanceHandle;
}
inline static jsi::Value getArrayOfInstanceHandlesFromShadowNodes(
ShadowNode::ListOfShared const &nodes,
jsi::Runtime &runtime) {
@@ -209,7 +194,7 @@ inline static jsi::Value getArrayOfInstanceHandlesFromShadowNodes(
std::vector<jsi::Value> nonNullInstanceHandles;
nonNullInstanceHandles.reserve(nodes.size());
for (auto const &shadowNode : nodes) {
auto instanceHandle = getInstanceHandleFromShadowNode(shadowNode, runtime);
auto instanceHandle = (*shadowNode).getInstanceHandle(runtime);
if (!instanceHandle.isNull()) {
nonNullInstanceHandles.push_back(std::move(instanceHandle));
}
@@ -290,7 +290,7 @@ static inline ShadowNode::Shared generateShadowNodeTree(
int deviation = 3) {
if (size <= 1) {
auto family = componentDescriptor.createFamily(
{generateReactTag(), SurfaceId(1), nullptr}, nullptr);
{generateReactTag(), SurfaceId(1), nullptr});
return componentDescriptor.createShadowNode(
ShadowNodeFragment{generateDefaultProps(componentDescriptor)}, family);
}
@@ -306,7 +306,7 @@ static inline ShadowNode::Shared generateShadowNodeTree(
}
auto family = componentDescriptor.createFamily(
{generateReactTag(), SurfaceId(1), nullptr}, nullptr);
{generateReactTag(), SurfaceId(1), nullptr});
return componentDescriptor.createShadowNode(
ShadowNodeFragment{
generateDefaultProps(componentDescriptor),