Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include <jsinspector-modern/tracing/PerformanceTracerSection.h>
#include <react/debug/react_native_assert.h>
#include <react/renderer/components/root/RootComponentDescriptor.h>
#include <react/renderer/components/view/ViewShadowNode.h>
#include <react/renderer/core/LayoutContext.h>
#include <react/renderer/core/LayoutPrimitives.h>
#include <react/renderer/mounting/ShadowTreeRevision.h>
Expand Down Expand Up @@ -463,7 +462,8 @@ CommitStatus ShadowTree::tryCommit(
}
}

emitLayoutEvents(affectedLayoutableNodes);
delegate_.shadowTreeDidCommit(
*this, newRevision.rootShadowNode, affectedLayoutableNodes);

if (isReactBranch) {
scheduleReactRevisionPromotion();
Expand Down Expand Up @@ -634,25 +634,6 @@ void ShadowTree::commitEmptyTree() const {
{/* default commit options */});
}

void ShadowTree::emitLayoutEvents(
std::vector<const LayoutableShadowNode*>& affectedLayoutableNodes) const {
TraceSection s(
"ShadowTree::emitLayoutEvents",
"affectedLayoutableNodes",
affectedLayoutableNodes.size());

for (const auto* layoutableNode : affectedLayoutableNodes) {
if (auto viewProps =
dynamic_cast<const ViewProps*>(layoutableNode->getProps().get())) {
if (viewProps->onLayout) {
static_cast<const BaseViewEventEmitter&>(
*layoutableNode->getEventEmitter())
.onLayout(layoutableNode->getLayoutMetrics());
}
}
}
}

void ShadowTree::notifyDelegatesOfUpdates() const {
delegate_.shadowTreeDidFinishTransaction(mountingCoordinator_, true);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,6 @@ class ShadowTree final {

void mount(ShadowTreeRevision revision, bool mountSynchronously) const;

void emitLayoutEvents(std::vector<const LayoutableShadowNode *> &affectedLayoutableNodes) const;

void scheduleReactRevisionPromotion() const;

const SurfaceId surfaceId_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace facebook::react {

class LayoutableShadowNode;
class ShadowTree;
struct ShadowTreeCommitOptions;

Expand Down Expand Up @@ -49,6 +50,16 @@ class ShadowTreeDelegate {
*/
virtual void shadowTreeDidPromoteReactRevision(const ShadowTree &shadowTree) const = 0;

/*
* Called right after a Shadow Tree commits a new tree, reporting the nodes
* whose layout changed in this commit.
*/
virtual void shadowTreeDidCommit(
const ShadowTree& shadowTree,
const RootShadowNode::Shared& rootShadowNode,
const std::vector<const LayoutableShadowNode*>& affectedLayoutableNodes)
const noexcept {}

virtual ~ShadowTreeDelegate() noexcept = default;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <react/renderer/mounting/MountingOverrideDelegate.h>
#include <react/renderer/mounting/ShadowViewMutation.h>
#include <react/renderer/runtimescheduler/RuntimeScheduler.h>
#include <react/renderer/uimanager/LayoutEventEmitter.h>
#include <react/renderer/uimanager/UIManager.h>
#include <react/renderer/uimanager/UIManagerBinding.h>
#include <mutex>
Expand Down Expand Up @@ -148,6 +149,11 @@ Scheduler::Scheduler(

delegate_ = delegate;
commitHooks_ = schedulerToolbox.commitHooks;

// Layout events (`onLayout`) are emitted as a standalone consumer of the
// `shadowTreeDidCommit` commit hook.
commitHooks_.push_back(std::make_shared<LayoutEventEmitter>());

uiManager_ = uiManager;

for (auto& commitHook : commitHooks_) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 "LayoutEventEmitter.h"

#include <cxxreact/TraceSection.h>
#include <react/renderer/components/view/ViewShadowNode.h>
#include <react/renderer/core/LayoutableShadowNode.h>

namespace facebook::react {

void LayoutEventEmitter::shadowTreeDidCommit(
const ShadowTree& /*shadowTree*/,
const RootShadowNode::Shared& /*rootShadowNode*/,
const std::vector<const LayoutableShadowNode*>&
affectedLayoutableNodes) noexcept {
TraceSection s(
"LayoutEventEmitter::shadowTreeDidCommit",
"affectedLayoutableNodes",
affectedLayoutableNodes.size());

for (const auto* layoutableNode : affectedLayoutableNodes) {
if (auto viewProps =
dynamic_cast<const ViewProps*>(layoutableNode->getProps().get())) {
if (viewProps->onLayout) {
static_cast<const BaseViewEventEmitter&>(
*layoutableNode->getEventEmitter())
.onLayout(layoutableNode->getLayoutMetrics());
}
}
}
}

} // namespace facebook::react
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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/renderer/uimanager/UIManagerCommitHook.h>

namespace facebook::react {

/*
* Emits layout events (`onLayout`) for the nodes whose layout changed in
* each commit, using the `shadowTreeDidCommit` commit hook as the source of
* layout changes (this logic used to be implemented directly in
* `ShadowTree`).
*/
class LayoutEventEmitter final : public UIManagerCommitHook {
public:
void commitHookWasRegistered(const UIManager& uiManager) noexcept override {}
void commitHookWasUnregistered(const UIManager& uiManager) noexcept override {}

void shadowTreeDidCommit(
const ShadowTree& shadowTree,
const RootShadowNode::Shared& rootShadowNode,
const std::vector<const LayoutableShadowNode*>&
affectedLayoutableNodes) noexcept override;
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,21 @@ void UIManager::shadowTreeDidPromoteReactRevision(
}
}

void UIManager::shadowTreeDidCommit(
const ShadowTree& shadowTree,
const RootShadowNode::Shared& rootShadowNode,
const std::vector<const LayoutableShadowNode*>& affectedLayoutableNodes)
const noexcept {
TraceSection s("UIManager::shadowTreeDidCommit");

std::shared_lock lock(commitHookMutex_);

for (auto* commitHook : commitHooks_) {
commitHook->shadowTreeDidCommit(
shadowTree, rootShadowNode, affectedLayoutableNodes);
}
}

void UIManager::reportMount(SurfaceId surfaceId) const {
TraceSection s("UIManager::reportMount");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,12 @@ class UIManager final : public ShadowTreeDelegate {

void shadowTreeDidPromoteReactRevision(const ShadowTree &shadowTree) const override;

void shadowTreeDidCommit(
const ShadowTree& shadowTree,
const RootShadowNode::Shared& rootShadowNode,
const std::vector<const LayoutableShadowNode*>& affectedLayoutableNodes)
const noexcept override;

std::shared_ptr<ShadowNode> createNode(
Tag tag,
const std::string &componentName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace facebook::react {

class LayoutableShadowNode;
class ShadowTree;
struct ShadowTreeCommitOptions;
class UIManager;
Expand Down Expand Up @@ -54,6 +55,16 @@ class UIManagerCommitHook {
return newRootShadowNode;
}

/*
* Called right after a `ShadowTree` commits a new tree.
* The semantic of the method corresponds to a method of the same name
* from `ShadowTreeDelegate`.
*/
virtual void shadowTreeDidCommit(
const ShadowTree& /*shadowTree*/,
const RootShadowNode::Shared& /*rootShadowNode*/,
const std::vector<const LayoutableShadowNode*>& /*affectedLayoutableNodes*/) noexcept {}

virtual ~UIManagerCommitHook() noexcept = default;
};

Expand Down
9 changes: 9 additions & 0 deletions scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api
Original file line number Diff line number Diff line change
Expand Up @@ -3165,6 +3165,12 @@ class facebook::react::LayoutAnimationStatusDelegate {
class facebook::react::LayoutConformanceShadowNode : public facebook::react::ConcreteShadowNode<facebook::react::LayoutConformanceShadowNodeComponentName, facebook::react::YogaLayoutableShadowNode, facebook::react::LayoutConformanceProps> {
}

class facebook::react::LayoutEventEmitter : public facebook::react::UIManagerCommitHook {
public virtual void commitHookWasRegistered(const facebook::react::UIManager& uiManager) noexcept override;
public virtual void commitHookWasUnregistered(const facebook::react::UIManager& uiManager) noexcept override;
public virtual void shadowTreeDidCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& rootShadowNode, const std::vector<const facebook::react::LayoutableShadowNode*>& affectedLayoutableNodes) noexcept override;
}

class facebook::react::LayoutableShadowNode : public facebook::react::ShadowNode {
public LayoutableShadowNode(const facebook::react::ShadowNode& sourceShadowNode, const facebook::react::ShadowNodeFragment& fragment);
public LayoutableShadowNode(const facebook::react::ShadowNodeFragment& fragment, const facebook::react::ShadowNodeFamily::Shared& family, facebook::react::ShadowNodeTraits traits);
Expand Down Expand Up @@ -4751,6 +4757,7 @@ class facebook::react::ShadowTree {

class facebook::react::ShadowTreeDelegate {
public virtual facebook::react::RootShadowNode::Unshared shadowTreeWillCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& oldRootShadowNode, const facebook::react::RootShadowNode::Unshared& newRootShadowNode, const facebook::react::ShadowTreeCommitOptions& commitOptions) const = 0;
public virtual void shadowTreeDidCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& rootShadowNode, const std::vector<const facebook::react::LayoutableShadowNode*>& affectedLayoutableNodes) const noexcept;
public virtual void shadowTreeDidFinishReactCommit(const facebook::react::ShadowTree& shadowTree) const = 0;
public virtual void shadowTreeDidFinishTransaction(std::shared_ptr<const facebook::react::MountingCoordinator> mountingCoordinator, bool mountSynchronously) const = 0;
public virtual void shadowTreeDidPromoteReactRevision(const facebook::react::ShadowTree& shadowTree) const = 0;
Expand Down Expand Up @@ -5260,6 +5267,7 @@ class facebook::react::UIManager : public facebook::react::ShadowTreeDelegate {
public std::shared_ptr<facebook::react::ShadowNode> cloneNode(const facebook::react::ShadowNode& shadowNode, const std::shared_ptr<const std::vector<std::shared_ptr<const facebook::react::ShadowNode>>>& children, facebook::react::RawProps rawProps) const;
public std::shared_ptr<facebook::react::ShadowNode> createNode(facebook::react::Tag tag, const std::string& componentName, facebook::react::SurfaceId surfaceId, facebook::react::RawProps props, facebook::react::InstanceHandle::Shared instanceHandle) const;
public virtual facebook::react::RootShadowNode::Unshared shadowTreeWillCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& oldRootShadowNode, const facebook::react::RootShadowNode::Unshared& newRootShadowNode, const facebook::react::ShadowTree::CommitOptions& commitOptions) const override;
public virtual void shadowTreeDidCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& rootShadowNode, const std::vector<const facebook::react::LayoutableShadowNode*>& affectedLayoutableNodes) const noexcept override;
public virtual void shadowTreeDidFinishReactCommit(const facebook::react::ShadowTree& shadowTree) const override;
public virtual void shadowTreeDidFinishTransaction(std::shared_ptr<const facebook::react::MountingCoordinator> mountingCoordinator, bool mountSynchronously) const override;
public virtual void shadowTreeDidPromoteReactRevision(const facebook::react::ShadowTree& shadowTree) const override;
Expand Down Expand Up @@ -5331,6 +5339,7 @@ class facebook::react::UIManagerCommitHook {
public virtual facebook::react::RootShadowNode::Unshared shadowTreeWillCommit(const facebook::react::ShadowTree&, const facebook::react::RootShadowNode::Shared&, const facebook::react::RootShadowNode::Unshared& newRootShadowNode) noexcept;
public virtual void commitHookWasRegistered(const facebook::react::UIManager& uiManager) noexcept = 0;
public virtual void commitHookWasUnregistered(const facebook::react::UIManager& uiManager) noexcept = 0;
public virtual void shadowTreeDidCommit(const facebook::react::ShadowTree&, const facebook::react::RootShadowNode::Shared&, const std::vector<const facebook::react::LayoutableShadowNode*>&) noexcept;
public virtual ~UIManagerCommitHook() noexcept = default;
}

Expand Down
9 changes: 9 additions & 0 deletions scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api
Original file line number Diff line number Diff line change
Expand Up @@ -3074,6 +3074,12 @@ class facebook::react::LayoutAnimationStatusDelegate {
class facebook::react::LayoutConformanceShadowNode : public facebook::react::ConcreteShadowNode<facebook::react::LayoutConformanceShadowNodeComponentName, facebook::react::YogaLayoutableShadowNode, facebook::react::LayoutConformanceProps> {
}

class facebook::react::LayoutEventEmitter : public facebook::react::UIManagerCommitHook {
public virtual void commitHookWasRegistered(const facebook::react::UIManager& uiManager) noexcept override;
public virtual void commitHookWasUnregistered(const facebook::react::UIManager& uiManager) noexcept override;
public virtual void shadowTreeDidCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& rootShadowNode, const std::vector<const facebook::react::LayoutableShadowNode*>& affectedLayoutableNodes) noexcept override;
}

class facebook::react::LayoutableShadowNode : public facebook::react::ShadowNode {
public LayoutableShadowNode(const facebook::react::ShadowNode& sourceShadowNode, const facebook::react::ShadowNodeFragment& fragment);
public LayoutableShadowNode(const facebook::react::ShadowNodeFragment& fragment, const facebook::react::ShadowNodeFamily::Shared& family, facebook::react::ShadowNodeTraits traits);
Expand Down Expand Up @@ -4562,6 +4568,7 @@ class facebook::react::ShadowTree {

class facebook::react::ShadowTreeDelegate {
public virtual facebook::react::RootShadowNode::Unshared shadowTreeWillCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& oldRootShadowNode, const facebook::react::RootShadowNode::Unshared& newRootShadowNode, const facebook::react::ShadowTreeCommitOptions& commitOptions) const = 0;
public virtual void shadowTreeDidCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& rootShadowNode, const std::vector<const facebook::react::LayoutableShadowNode*>& affectedLayoutableNodes) const noexcept;
public virtual void shadowTreeDidFinishReactCommit(const facebook::react::ShadowTree& shadowTree) const = 0;
public virtual void shadowTreeDidFinishTransaction(std::shared_ptr<const facebook::react::MountingCoordinator> mountingCoordinator, bool mountSynchronously) const = 0;
public virtual void shadowTreeDidPromoteReactRevision(const facebook::react::ShadowTree& shadowTree) const = 0;
Expand Down Expand Up @@ -5071,6 +5078,7 @@ class facebook::react::UIManager : public facebook::react::ShadowTreeDelegate {
public std::shared_ptr<facebook::react::ShadowNode> cloneNode(const facebook::react::ShadowNode& shadowNode, const std::shared_ptr<const std::vector<std::shared_ptr<const facebook::react::ShadowNode>>>& children, facebook::react::RawProps rawProps) const;
public std::shared_ptr<facebook::react::ShadowNode> createNode(facebook::react::Tag tag, const std::string& componentName, facebook::react::SurfaceId surfaceId, facebook::react::RawProps props, facebook::react::InstanceHandle::Shared instanceHandle) const;
public virtual facebook::react::RootShadowNode::Unshared shadowTreeWillCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& oldRootShadowNode, const facebook::react::RootShadowNode::Unshared& newRootShadowNode, const facebook::react::ShadowTree::CommitOptions& commitOptions) const override;
public virtual void shadowTreeDidCommit(const facebook::react::ShadowTree& shadowTree, const facebook::react::RootShadowNode::Shared& rootShadowNode, const std::vector<const facebook::react::LayoutableShadowNode*>& affectedLayoutableNodes) const noexcept override;
public virtual void shadowTreeDidFinishReactCommit(const facebook::react::ShadowTree& shadowTree) const override;
public virtual void shadowTreeDidFinishTransaction(std::shared_ptr<const facebook::react::MountingCoordinator> mountingCoordinator, bool mountSynchronously) const override;
public virtual void shadowTreeDidPromoteReactRevision(const facebook::react::ShadowTree& shadowTree) const override;
Expand Down Expand Up @@ -5142,6 +5150,7 @@ class facebook::react::UIManagerCommitHook {
public virtual facebook::react::RootShadowNode::Unshared shadowTreeWillCommit(const facebook::react::ShadowTree&, const facebook::react::RootShadowNode::Shared&, const facebook::react::RootShadowNode::Unshared& newRootShadowNode) noexcept;
public virtual void commitHookWasRegistered(const facebook::react::UIManager& uiManager) noexcept = 0;
public virtual void commitHookWasUnregistered(const facebook::react::UIManager& uiManager) noexcept = 0;
public virtual void shadowTreeDidCommit(const facebook::react::ShadowTree&, const facebook::react::RootShadowNode::Shared&, const std::vector<const facebook::react::LayoutableShadowNode*>&) noexcept;
public virtual ~UIManagerCommitHook() noexcept = default;
}

Expand Down
Loading
Loading