diff --git a/packages/react-native/React/Fabric/AppleEventBeat.cpp b/packages/react-native/React/Fabric/AppleEventBeat.cpp deleted file mode 100644 index 4a3d533a0cd9..000000000000 --- a/packages/react-native/React/Fabric/AppleEventBeat.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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 "AppleEventBeat.h" - -#include - -namespace facebook::react { - -AppleEventBeat::AppleEventBeat( - std::shared_ptr ownerBox, - std::unique_ptr uiRunLoopObserver, - RuntimeScheduler& runtimeScheduler) - : EventBeat(std::move(ownerBox), runtimeScheduler), - uiRunLoopObserver_(std::move(uiRunLoopObserver)) { - uiRunLoopObserver_->setDelegate(this); - uiRunLoopObserver_->enable(); -} - -void AppleEventBeat::activityDidChange( - const RunLoopObserver::Delegate* delegate, - RunLoopObserver::Activity /*activity*/) const noexcept { - react_native_assert(delegate == this); - induce(); -} - -} // namespace facebook::react diff --git a/packages/react-native/React/Fabric/AppleEventBeat.h b/packages/react-native/React/Fabric/AppleEventBeat.h index 256e0f0983ad..528145e23797 100644 --- a/packages/react-native/React/Fabric/AppleEventBeat.h +++ b/packages/react-native/React/Fabric/AppleEventBeat.h @@ -7,6 +7,8 @@ #pragma once +#include + #include #include #include @@ -19,6 +21,11 @@ class RuntimeScheduler; * Event beat associated with JavaScript runtime. * The beat is called on `RuntimeExecutor`'s thread induced by the UI thread * event loop. + * + * A synchronous request made while Core Animation is laying out the current + * frame (the run loop observer that induces the beat has already run at that + * point) is additionally induced from the display phase of the same commit + * cycle, so that its effects are mounted before the frame is presented. */ class AppleEventBeat : public EventBeat, public RunLoopObserver::Delegate { public: @@ -27,13 +34,20 @@ class AppleEventBeat : public EventBeat, public RunLoopObserver::Delegate { std::unique_ptr uiRunLoopObserver, RuntimeScheduler &RuntimeScheduler); + ~AppleEventBeat() override; + + void requestSynchronous() const override; + #pragma mark - RunLoopObserver::Delegate void activityDidChange(const RunLoopObserver::Delegate *delegate, RunLoopObserver::Activity activity) const noexcept override; private: + class DisplayPhaseFlusher; + std::unique_ptr uiRunLoopObserver_; + std::unique_ptr displayPhaseFlusher_; }; } // namespace facebook::react diff --git a/packages/react-native/React/Fabric/AppleEventBeat.mm b/packages/react-native/React/Fabric/AppleEventBeat.mm new file mode 100644 index 000000000000..b91adb43c2d6 --- /dev/null +++ b/packages/react-native/React/Fabric/AppleEventBeat.mm @@ -0,0 +1,182 @@ +/* + * 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 "AppleEventBeat.h" + +#import +#import + +#include + +/* + * A zero-sized layer whose only purpose is to run a callback during the + * display phase of a Core Animation commit. Core Animation processes a commit + * as layout → display → (repeat until stable) → commit, so a layer marked as + * needing display during the layout phase has its `display` called after the + * whole layout pass but before the transaction is committed. + */ +@interface RCTEventBeatFlusherLayer : CALayer +@property (nonatomic, copy, nullable) void (^onDisplay)(void); +@end + +@implementation RCTEventBeatFlusherLayer + +- (void)display +{ + if (self.onDisplay != nil) { + self.onDisplay(); + } +} + +// The layer is not a visual element; never participate in animations. +- (id)actionForKey:(NSString *)event +{ + return nil; +} + +@end + +/* + * The windows that can commit a Core Animation transaction: the visible ones + * of every foreground scene. + */ +static NSArray *RCTFlushableWindows(void) +{ + NSMutableArray *windows = [NSMutableArray new]; + for (UIScene *scene in RCTSharedApplication().connectedScenes) { + if (![scene isKindOfClass:[UIWindowScene class]]) { + continue; + } + if (scene.activationState != UISceneActivationStateForegroundActive && + scene.activationState != UISceneActivationStateForegroundInactive) { + continue; + } + for (UIWindow *window in ((UIWindowScene *)scene).windows) { + if (!window.hidden) { + [windows addObject:window]; + } + } + } + if (windows.count == 0) { + // Apps on the legacy UIApplicationDelegate lifecycle own their window + // outside of any scene, so the enumeration above finds nothing. + UIWindow *keyWindow = RCTKeyWindow(); + if (keyWindow != nil) { + [windows addObject:keyWindow]; + } + } + return windows; +} + +namespace facebook::react { + +/* + * Owns the flusher layers and keeps one attached to every window's layer so + * that whichever layer tree is being committed contains one of them. + */ +class AppleEventBeat::DisplayPhaseFlusher { + public: + DisplayPhaseFlusher(std::function callback, std::weak_ptr weakOwner) + { + // Weak keys: a window that goes away takes its own layer with it. + layers_ = [NSMapTable weakToStrongObjectsMapTable]; + auto sharedCallback = std::make_shared>(std::move(callback)); + onDisplay_ = ^{ + // The owner (indirectly) retains the event beat; if it is gone, so is + // the beat the callback points into. + auto owner = weakOwner.lock(); + if (!owner) { + return; + } + (*sharedCallback)(); + }; + } + + ~DisplayPhaseFlusher() + { + // The beat can be destroyed on any thread; layer mutations belong on the + // main thread. The block only retains the layers, and a display happening + // before this executes is made safe by the owner check above. + NSMapTable *layers = layers_; + RCTExecuteOnMainQueue(^{ + for (RCTEventBeatFlusherLayer *layer in layers.objectEnumerator) { + layer.onDisplay = nil; + [layer removeFromSuperlayer]; + } + [layers removeAllObjects]; + }); + } + + /* + * Schedules the callback to run in the display phase of the current (or + * next) Core Animation commit cycle. Main thread only. + * + * Every window gets a layer rather than only the key window: the request can + * come from any of them — a modal and the LogBox are windows of their own — + * and only a layer in a tree that is committed is displayed in this cycle. + * The induce the display triggers is coalescing, so the extra layers cost a + * dirty zero-sized layer each, not extra beats. + */ + void schedule() const + { + for (UIWindow *window in RCTFlushableWindows()) { + RCTEventBeatFlusherLayer *layer = [layers_ objectForKey:window]; + if (layer == nil) { + layer = [RCTEventBeatFlusherLayer new]; + layer.frame = CGRectZero; + layer.onDisplay = onDisplay_; + [layers_ setObject:layer forKey:window]; + } + if (layer.superlayer != window.layer) { + [window.layer addSublayer:layer]; + } + [layer setNeedsDisplay]; + } + } + + private: + NSMapTable *layers_; + void (^onDisplay_)(void); +}; + +AppleEventBeat::AppleEventBeat(std::shared_ptr ownerBox, + std::unique_ptr uiRunLoopObserver, + RuntimeScheduler &runtimeScheduler) + : EventBeat(std::move(ownerBox), runtimeScheduler), + uiRunLoopObserver_(std::move(uiRunLoopObserver)), + displayPhaseFlusher_(std::make_unique([this]() { induce(); }, ownerBox_->owner)) +{ + uiRunLoopObserver_->setDelegate(this); + uiRunLoopObserver_->enable(); +} + +AppleEventBeat::~AppleEventBeat() = default; + +void AppleEventBeat::requestSynchronous() const +{ + EventBeat::requestSynchronous(); + + // The run loop observer that ordinarily induces the beat runs before Core + // Animation commits the frame. A synchronous request made while Core + // Animation is already laying out (e.g. an event emitted from + // `layoutSubviews`) would therefore only be processed on the next frame. + // Scheduling an induce in the display phase of the current commit cycle + // processes it before this frame is presented. Multiple requests within one + // cycle coalesce into a single induce. + if (RCTIsMainQueue()) { + displayPhaseFlusher_->schedule(); + } +} + +void AppleEventBeat::activityDidChange(const RunLoopObserver::Delegate *delegate, + RunLoopObserver::Activity /*activity*/) const noexcept +{ + react_native_assert(delegate == this); + induce(); +} + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventBeat.cpp b/packages/react-native/ReactCommon/react/renderer/core/EventBeat.cpp index cdb05f4719fd..839e2f19f90b 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventBeat.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/EventBeat.cpp @@ -53,7 +53,14 @@ void EventBeat::induce() const { isEventBeatRequested_ = false; if (isBeatCallbackScheduled_) { - return; + // An asynchronous beat is already scheduled but has not run yet. A + // synchronous request must not be stranded behind it (it would silently + // lose its this-frame guarantee, and the leftover flag would make an + // unrelated later beat blocking), so it proceeds and processes the queue + // now; the already scheduled beat will simply find an empty queue. + if (!isSynchronousRequested_) { + return; + } } isBeatCallbackScheduled_ = true; diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventBeat.h b/packages/react-native/ReactCommon/react/renderer/core/EventBeat.h index 3740b457e785..b8da33cc9ac2 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventBeat.h +++ b/packages/react-native/ReactCommon/react/renderer/core/EventBeat.h @@ -111,6 +111,16 @@ class EventBeat { */ virtual void requestSynchronous() const; + /* + * Induces the next beat to happen as soon as possible. + * Receiver might ignore the call if a beat was not requested. + * + * Ordinarily called by the platform once per frame; also callable by a + * consumer right after `requestSynchronous` to process the queue immediately + * at the call site instead of at the next frame boundary. + */ + void induce() const; + /* * The callback will be executed once a consumer (for example EventQueue) * calls either `EventBeat::request` or `EventBeat::requestSynchronous`. The @@ -128,12 +138,6 @@ class EventBeat { void unstable_setInduceCallback(std::function callback); protected: - /* - * Induces the next beat to happen as soon as possible. - * Receiver might ignore the call if a beat was not requested. - */ - void induce() const; - BeatCallback beatCallback_; std::function induceCallback_; std::shared_ptr ownerBox_; diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/EventBeatTest.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/EventBeatTest.cpp new file mode 100644 index 000000000000..1dda2fd47fd6 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/EventBeatTest.cpp @@ -0,0 +1,168 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "StubQueue.h" + +namespace facebook::react { + +class EventBeatTestFeatureFlags : public ReactNativeFeatureFlagsDefaults { + public: + bool enableBridgelessArchitecture() override { + return true; + } +}; + +class EventBeatTest : public testing::Test { + protected: + void SetUp() override { + ReactNativeFeatureFlags::dangerouslyReset(); + ReactNativeFeatureFlags::override( + std::make_unique()); + + runtime_ = facebook::hermes::makeHermesRuntime( + ::hermes::vm::RuntimeConfig::Builder().build()); + stubQueue_ = std::make_unique(); + + RuntimeExecutor runtimeExecutor = + [this]( + std::function&& callback) { + stubQueue_->runOnQueue([this, callback = std::move(callback)]() { + callback(*runtime_); + }); + }; + + runtimeScheduler_ = std::make_unique(runtimeExecutor); + + ownerBox_ = std::make_shared(); + owner_ = std::make_shared(0); + ownerBox_->owner = owner_; + eventBeat_ = std::make_unique(ownerBox_, *runtimeScheduler_); + } + + void TearDown() override { + ReactNativeFeatureFlags::dangerouslyReset(); + } + + std::unique_ptr runtime_; + std::unique_ptr stubQueue_; + std::unique_ptr runtimeScheduler_; + std::shared_ptr ownerBox_; + std::shared_ptr owner_; + std::unique_ptr eventBeat_; +}; + +TEST_F(EventBeatTest, induceWithoutRequestIsNoop) { + int beatCount = 0; + eventBeat_->setBeatCallback([&beatCount](jsi::Runtime& /*runtime*/) { + beatCount++; + }); + + eventBeat_->induce(); + + EXPECT_EQ(beatCount, 0); + EXPECT_EQ(stubQueue_->size(), 0); +} + +TEST_F(EventBeatTest, synchronousRequestIsProcessedAtInduce) { + int beatCount = 0; + eventBeat_->setBeatCallback([&beatCount](jsi::Runtime& /*runtime*/) { + beatCount++; + }); + + eventBeat_->requestSynchronous(); + EXPECT_EQ(beatCount, 0); + + // Platform implementations induce the beat at a point where the effects of + // synchronous events can still make the current frame (the display phase on + // Apple, before the draw on Android). The beat callback runs synchronously + // before `induce` returns, with both threads blocked. + std::thread driver([this]() { + stubQueue_->waitForTask(); + stubQueue_->tick(); + }); + eventBeat_->induce(); + driver.join(); + + EXPECT_EQ(beatCount, 1); + + // The request was consumed: another induce does nothing. + eventBeat_->induce(); + EXPECT_EQ(beatCount, 1); + EXPECT_EQ(stubQueue_->size(), 0); +} + +TEST_F(EventBeatTest, requestMadeDuringBeatIsProcessedByASubsequentInduce) { + int beatCount = 0; + eventBeat_->setBeatCallback([&](jsi::Runtime& /*runtime*/) { + beatCount++; + if (beatCount == 1) { + // A synchronous request made from within the beat (e.g. an event whose + // handler causes another synchronous event). Platform implementations + // defer the induce for it (the display phase flusher on Apple, the next + // pre-draw on Android) rather than inducing from within the beat. + eventBeat_->requestSynchronous(); + } + }); + + eventBeat_->requestSynchronous(); + std::thread driver([this]() { + stubQueue_->waitForTask(); + stubQueue_->tick(); + }); + eventBeat_->induce(); + driver.join(); + + EXPECT_EQ(beatCount, 1); + + // The request made during the beat is not lost: the next induce processes + // it. + std::thread driver2([this]() { + stubQueue_->waitForTask(); + stubQueue_->tick(); + }); + eventBeat_->induce(); + driver2.join(); + + EXPECT_EQ(beatCount, 2); +} + +TEST_F(EventBeatTest, synchronousRequestIsNotStrandedBehindScheduledBeat) { + int beatCount = 0; + eventBeat_->setBeatCallback([&beatCount](jsi::Runtime& /*runtime*/) { + beatCount++; + }); + + // An asynchronous beat is scheduled but has not run yet. + eventBeat_->request(); + eventBeat_->induce(); + EXPECT_EQ(beatCount, 0); + + // A synchronous request arriving now must still be processed by its induce + // instead of being silently deferred behind the scheduled beat. + eventBeat_->requestSynchronous(); + std::thread driver([this]() { + stubQueue_->waitForTask(); + stubQueue_->tick(); + stubQueue_->waitForTask(); + stubQueue_->tick(); + }); + eventBeat_->induce(); + driver.join(); + + EXPECT_EQ(beatCount, 2); +} + +} // namespace facebook::react diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api index 2e6dc7e0b4e2..2531a123e50e 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api @@ -2218,7 +2218,6 @@ class facebook::react::EventBeat { protected mutable std::atomic isEventBeatRequested_; protected std::function induceCallback_; protected std::shared_ptr ownerBox_; - protected void induce() const; public EventBeat(const facebook::react::EventBeat& other) = delete; public EventBeat(std::shared_ptr ownerBox, facebook::react::RuntimeScheduler& runtimeScheduler); public facebook::react::EventBeat& operator=(const facebook::react::EventBeat& other) = delete; @@ -2227,6 +2226,7 @@ class facebook::react::EventBeat { public virtual void request() const; public virtual void requestSynchronous() const; public virtual ~EventBeat() = default; + public void induce() const; public void setBeatCallback(facebook::react::EventBeat::BeatCallback beatCallback); } diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api index 7ec351405ee3..3d346ac488cf 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api @@ -2201,7 +2201,6 @@ class facebook::react::EventBeat { protected mutable std::atomic isEventBeatRequested_; protected std::function induceCallback_; protected std::shared_ptr ownerBox_; - protected void induce() const; public EventBeat(const facebook::react::EventBeat& other) = delete; public EventBeat(std::shared_ptr ownerBox, facebook::react::RuntimeScheduler& runtimeScheduler); public facebook::react::EventBeat& operator=(const facebook::react::EventBeat& other) = delete; @@ -2210,6 +2209,7 @@ class facebook::react::EventBeat { public virtual void request() const; public virtual void requestSynchronous() const; public virtual ~EventBeat() = default; + public void induce() const; public void setBeatCallback(facebook::react::EventBeat::BeatCallback beatCallback); } diff --git a/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api index 6843410835c3..130a86d9588b 100644 --- a/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api @@ -2216,7 +2216,6 @@ class facebook::react::EventBeat { protected mutable std::atomic isEventBeatRequested_; protected std::function induceCallback_; protected std::shared_ptr ownerBox_; - protected void induce() const; public EventBeat(const facebook::react::EventBeat& other) = delete; public EventBeat(std::shared_ptr ownerBox, facebook::react::RuntimeScheduler& runtimeScheduler); public facebook::react::EventBeat& operator=(const facebook::react::EventBeat& other) = delete; @@ -2225,6 +2224,7 @@ class facebook::react::EventBeat { public virtual void request() const; public virtual void requestSynchronous() const; public virtual ~EventBeat() = default; + public void induce() const; public void setBeatCallback(facebook::react::EventBeat::BeatCallback beatCallback); } diff --git a/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api index d6dc3f80a6ad..90f9105cb7e4 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api @@ -4245,6 +4245,8 @@ class facebook::react::AppRegistryBinding { class facebook::react::AppleEventBeat : public facebook::react::EventBeat, public facebook::react::RunLoopObserver::Delegate { public AppleEventBeat(std::shared_ptr ownerBox, std::unique_ptr uiRunLoopObserver, facebook::react::RuntimeScheduler& RuntimeScheduler); public virtual void activityDidChange(const facebook::react::RunLoopObserver::Delegate* delegate, facebook::react::RunLoopObserver::Activity activity) const noexcept override; + public virtual void requestSynchronous() const override; + public ~AppleEventBeat() override; } class facebook::react::AsyncArrayBuffer { @@ -4745,7 +4747,6 @@ class facebook::react::EventBeat { protected mutable std::atomic isEventBeatRequested_; protected std::function induceCallback_; protected std::shared_ptr ownerBox_; - protected void induce() const; public EventBeat(const facebook::react::EventBeat& other) = delete; public EventBeat(std::shared_ptr ownerBox, facebook::react::RuntimeScheduler& runtimeScheduler); public facebook::react::EventBeat& operator=(const facebook::react::EventBeat& other) = delete; @@ -4754,6 +4755,7 @@ class facebook::react::EventBeat { public virtual void request() const; public virtual void requestSynchronous() const; public virtual ~EventBeat() = default; + public void induce() const; public void setBeatCallback(facebook::react::EventBeat::BeatCallback beatCallback); } diff --git a/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api index da7a542fd69f..49dcfe05d451 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleNewarchCxx.api @@ -4232,6 +4232,8 @@ class facebook::react::AppRegistryBinding { class facebook::react::AppleEventBeat : public facebook::react::EventBeat, public facebook::react::RunLoopObserver::Delegate { public AppleEventBeat(std::shared_ptr ownerBox, std::unique_ptr uiRunLoopObserver, facebook::react::RuntimeScheduler& RuntimeScheduler); public virtual void activityDidChange(const facebook::react::RunLoopObserver::Delegate* delegate, facebook::react::RunLoopObserver::Activity activity) const noexcept override; + public virtual void requestSynchronous() const override; + public ~AppleEventBeat() override; } class facebook::react::AsyncArrayBuffer { @@ -4721,7 +4723,6 @@ class facebook::react::EventBeat { protected mutable std::atomic isEventBeatRequested_; protected std::function induceCallback_; protected std::shared_ptr ownerBox_; - protected void induce() const; public EventBeat(const facebook::react::EventBeat& other) = delete; public EventBeat(std::shared_ptr ownerBox, facebook::react::RuntimeScheduler& runtimeScheduler); public facebook::react::EventBeat& operator=(const facebook::react::EventBeat& other) = delete; @@ -4730,6 +4731,7 @@ class facebook::react::EventBeat { public virtual void request() const; public virtual void requestSynchronous() const; public virtual ~EventBeat() = default; + public void induce() const; public void setBeatCallback(facebook::react::EventBeat::BeatCallback beatCallback); } diff --git a/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api index a92742d8c14e..0059a9259d0f 100644 --- a/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api @@ -4243,6 +4243,8 @@ class facebook::react::AppRegistryBinding { class facebook::react::AppleEventBeat : public facebook::react::EventBeat, public facebook::react::RunLoopObserver::Delegate { public AppleEventBeat(std::shared_ptr ownerBox, std::unique_ptr uiRunLoopObserver, facebook::react::RuntimeScheduler& RuntimeScheduler); public virtual void activityDidChange(const facebook::react::RunLoopObserver::Delegate* delegate, facebook::react::RunLoopObserver::Activity activity) const noexcept override; + public virtual void requestSynchronous() const override; + public ~AppleEventBeat() override; } class facebook::react::AsyncArrayBuffer { @@ -4743,7 +4745,6 @@ class facebook::react::EventBeat { protected mutable std::atomic isEventBeatRequested_; protected std::function induceCallback_; protected std::shared_ptr ownerBox_; - protected void induce() const; public EventBeat(const facebook::react::EventBeat& other) = delete; public EventBeat(std::shared_ptr ownerBox, facebook::react::RuntimeScheduler& runtimeScheduler); public facebook::react::EventBeat& operator=(const facebook::react::EventBeat& other) = delete; @@ -4752,6 +4753,7 @@ class facebook::react::EventBeat { public virtual void request() const; public virtual void requestSynchronous() const; public virtual ~EventBeat() = default; + public void induce() const; public void setBeatCallback(facebook::react::EventBeat::BeatCallback beatCallback); } diff --git a/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api index 763c902b2e27..9d716ed5a43e 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api @@ -1460,7 +1460,6 @@ class facebook::react::EventBeat { protected mutable std::atomic isEventBeatRequested_; protected std::function induceCallback_; protected std::shared_ptr ownerBox_; - protected void induce() const; public EventBeat(const facebook::react::EventBeat& other) = delete; public EventBeat(std::shared_ptr ownerBox, facebook::react::RuntimeScheduler& runtimeScheduler); public facebook::react::EventBeat& operator=(const facebook::react::EventBeat& other) = delete; @@ -1469,6 +1468,7 @@ class facebook::react::EventBeat { public virtual void request() const; public virtual void requestSynchronous() const; public virtual ~EventBeat() = default; + public void induce() const; public void setBeatCallback(facebook::react::EventBeat::BeatCallback beatCallback); } diff --git a/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api index abad9815f5c4..dcd3dcec5dde 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonNewarchCxx.api @@ -1444,7 +1444,6 @@ class facebook::react::EventBeat { protected mutable std::atomic isEventBeatRequested_; protected std::function induceCallback_; protected std::shared_ptr ownerBox_; - protected void induce() const; public EventBeat(const facebook::react::EventBeat& other) = delete; public EventBeat(std::shared_ptr ownerBox, facebook::react::RuntimeScheduler& runtimeScheduler); public facebook::react::EventBeat& operator=(const facebook::react::EventBeat& other) = delete; @@ -1453,6 +1452,7 @@ class facebook::react::EventBeat { public virtual void request() const; public virtual void requestSynchronous() const; public virtual ~EventBeat() = default; + public void induce() const; public void setBeatCallback(facebook::react::EventBeat::BeatCallback beatCallback); } diff --git a/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api b/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api index 0c58351b5c06..65b495bc9243 100644 --- a/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api +++ b/scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api @@ -1458,7 +1458,6 @@ class facebook::react::EventBeat { protected mutable std::atomic isEventBeatRequested_; protected std::function induceCallback_; protected std::shared_ptr ownerBox_; - protected void induce() const; public EventBeat(const facebook::react::EventBeat& other) = delete; public EventBeat(std::shared_ptr ownerBox, facebook::react::RuntimeScheduler& runtimeScheduler); public facebook::react::EventBeat& operator=(const facebook::react::EventBeat& other) = delete; @@ -1467,6 +1466,7 @@ class facebook::react::EventBeat { public virtual void request() const; public virtual void requestSynchronous() const; public virtual ~EventBeat() = default; + public void induce() const; public void setBeatCallback(facebook::react::EventBeat::BeatCallback beatCallback); }