mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Fabric: Asserting if the RuntimeExecutor callback in RCTRuntimeExecutorFromBridge is not called
Summary: The implementation of RuntimeExecutor must execute all provided callbacks. However, the implementation of RCTRuntimeExecutorFromBridge cannot guarantee it because it relies on Bridge to make the call. In this diff, we wrap the callback into a callable that asserts if it's not being called before destruction. Changelog: [Internal] Fabric-specific internal change. Reviewed By: mdvacca Differential Revision: D22810439 fbshipit-source-id: f11932019ab6ccbab7e65db5919e0c64dcaf37ed
This commit is contained in:
committed by
Facebook GitHub Bot
parent
f838c7e5c3
commit
a1b6f7bd9e
@@ -18,6 +18,7 @@
|
||||
#import <React/RCTSurfacePresenterStub.h>
|
||||
|
||||
#import <ReactCommon/RuntimeExecutor.h>
|
||||
#import <react/utils/CalledOnceMovableOnlyFunction.h>
|
||||
#import <react/utils/ContextContainer.h>
|
||||
#import <react/utils/ManagedObjectWrapper.h>
|
||||
|
||||
@@ -48,7 +49,20 @@ static RuntimeExecutor RCTRuntimeExecutorFromBridge(RCTBridge *bridge)
|
||||
auto bridgeWeakWrapper = wrapManagedObjectWeakly([bridge batchedBridge] ?: bridge);
|
||||
|
||||
RuntimeExecutor runtimeExecutor = [bridgeWeakWrapper](
|
||||
std::function<void(facebook::jsi::Runtime & runtime)> &&callback) {
|
||||
std::function<void(facebook::jsi::Runtime &)> &&callbackArgument) {
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Here we wrap callback into a callable that will assert if the `callback` is not called before deallocation
|
||||
// or called more than once.
|
||||
// It's useful to see at which exact point in time those assumptions were violated.
|
||||
auto sharedCallback = std::make_shared<CalledOnceMovableOnlyFunction<void, facebook::jsi::Runtime &>>(
|
||||
[callback = std::move(callbackArgument)](facebook::jsi::Runtime &runtime) { callback(runtime); });
|
||||
auto callback = std::function<void(facebook::jsi::Runtime &)>(
|
||||
[sharedCallback](facebook::jsi::Runtime &runtime) { (*sharedCallback)(runtime); });
|
||||
#else
|
||||
auto callback = std::move(callbackArgument);
|
||||
#endif
|
||||
|
||||
RCTBridge *bridge = unwrapManagedObjectWeakly(bridgeWeakWrapper);
|
||||
|
||||
RCTAssert(bridge, @"RCTRuntimeExecutorFromBridge: Bridge must not be nil at the moment of scheduling a call.");
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* Implements a moveable-only function that asserts if called more than once
|
||||
* or destroyed before calling.
|
||||
* Useful for use in debug mode to ensure such guarantees.
|
||||
*/
|
||||
template <typename ReturnT = void, typename... ArgumentT>
|
||||
class CalledOnceMovableOnlyFunction {
|
||||
using T = ReturnT(ArgumentT...);
|
||||
|
||||
std::function<T> function_;
|
||||
bool wasCalled_;
|
||||
bool wasMovedFrom_;
|
||||
|
||||
public:
|
||||
CalledOnceMovableOnlyFunction(std::function<T> &&function)
|
||||
: function_(std::move(function)) {
|
||||
wasCalled_ = false;
|
||||
wasMovedFrom_ = false;
|
||||
}
|
||||
|
||||
~CalledOnceMovableOnlyFunction() {
|
||||
assert(
|
||||
(wasCalled_ || wasMovedFrom_) &&
|
||||
"`CalledOnceMovableOnlyFunction` is destroyed before being called.");
|
||||
}
|
||||
|
||||
/*
|
||||
* Not copyable.
|
||||
*/
|
||||
CalledOnceMovableOnlyFunction(CalledOnceMovableOnlyFunction const &other) =
|
||||
delete;
|
||||
CalledOnceMovableOnlyFunction &operator=(
|
||||
CalledOnceMovableOnlyFunction const &other) = delete;
|
||||
|
||||
/*
|
||||
* Movable.
|
||||
*/
|
||||
CalledOnceMovableOnlyFunction(
|
||||
CalledOnceMovableOnlyFunction &&other) noexcept {
|
||||
wasCalled_ = false;
|
||||
wasMovedFrom_ = false;
|
||||
other.wasMovedFrom_ = true;
|
||||
function_ = std::move(other.function_);
|
||||
};
|
||||
|
||||
CalledOnceMovableOnlyFunction &operator=(
|
||||
CalledOnceMovableOnlyFunction &&other) noexcept {
|
||||
assert(
|
||||
(wasCalled_ || wasMovedFrom_) &&
|
||||
"`CalledOnceMovableOnlyFunction` is re-assigned before being called.");
|
||||
wasCalled_ = false;
|
||||
wasMovedFrom_ = false;
|
||||
other.wasMovedFrom_ = true;
|
||||
function_ = std::move(other.function_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callable.
|
||||
*/
|
||||
ReturnT operator()(ArgumentT... args) {
|
||||
assert(
|
||||
!wasMovedFrom_ &&
|
||||
"`CalledOnceMovableOnlyFunction` is called after being moved from.");
|
||||
assert(
|
||||
!wasCalled_ &&
|
||||
"`CalledOnceMovableOnlyFunction` is called more than once.");
|
||||
|
||||
wasCalled_ = true;
|
||||
return function_(args...);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
Reference in New Issue
Block a user