Refactor: ReactHost: Delete old task creation methods (#42168)

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

Changelog: [Internal]

Reviewed By: mdvacca

Differential Revision: D52495533

fbshipit-source-id: 787919fa68a0308d5e5bc803c7f5f1221675cd09
This commit is contained in:
Ramanpreet Nara
2024-01-09 19:07:01 -08:00
committed by Facebook GitHub Bot
parent 2e6afdc550
commit af004ce4e6
@@ -67,7 +67,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
@@ -201,12 +200,7 @@ public class ReactHostImpl implements ReactHost {
*/
@Override
public TaskInterface<Void> start() {
if (ReactFeatureFlags.enableBridgelessArchitectureNewCreateReloadDestroy) {
return Task.call(this::newGetOrCreateStartTask, mBGExecutor)
.continueWithTask(Task::getResult);
}
return Task.call(this::oldGetOrCreateStartTask, mBGExecutor).continueWithTask(Task::getResult);
return Task.call(this::newGetOrCreateStartTask, mBGExecutor).continueWithTask(Task::getResult);
}
/** Initialize and run a React Native surface in a background without mounting real views. */
@@ -441,36 +435,32 @@ public class ReactHostImpl implements ReactHost {
@Override
public TaskInterface<Void> reload(String reason) {
final String method = "reload()";
if (ReactFeatureFlags.enableBridgelessArchitectureNewCreateReloadDestroy) {
return Task.call(
() -> {
Task<Void> reloadTask = null;
if (mDestroyTask != null) {
log(method, "Waiting for destroy to finish, before reloading React Native.");
reloadTask =
mDestroyTask
.continueWithTask(task -> newGetOrCreateReloadTask(reason), mBGExecutor)
.makeVoid();
} else {
reloadTask = newGetOrCreateReloadTask(reason).makeVoid();
}
return Task.call(
() -> {
Task<Void> reloadTask = null;
if (mDestroyTask != null) {
log(method, "Waiting for destroy to finish, before reloading React Native.");
reloadTask =
mDestroyTask
.continueWithTask(task -> newGetOrCreateReloadTask(reason), mBGExecutor)
.makeVoid();
} else {
reloadTask = newGetOrCreateReloadTask(reason).makeVoid();
}
return reloadTask.continueWithTask(
task -> {
if (task.isFaulted()) {
mReactHostDelegate.handleInstanceException(task.getError());
return newGetOrCreateDestroyTask("Reload failed", task.getError());
}
return reloadTask.continueWithTask(
task -> {
if (task.isFaulted()) {
mReactHostDelegate.handleInstanceException(task.getError());
return newGetOrCreateDestroyTask("Reload failed", task.getError());
}
return task;
},
mBGExecutor);
},
mBGExecutor)
.continueWithTask(Task::getResult);
}
return oldReload(reason);
return task;
},
mBGExecutor);
},
mBGExecutor)
.continueWithTask(Task::getResult);
}
/**
@@ -486,24 +476,19 @@ public class ReactHostImpl implements ReactHost {
@Override
public TaskInterface<Void> destroy(String reason, @Nullable Exception ex) {
final String method = "destroy()";
if (ReactFeatureFlags.enableBridgelessArchitectureNewCreateReloadDestroy) {
return Task.call(
() -> {
if (mReloadTask != null) {
log(
method,
"Reloading React Native. Waiting for reload to finish before destroying React Native.");
return mReloadTask.continueWithTask(
task -> newGetOrCreateDestroyTask(reason, ex), mBGExecutor);
}
return newGetOrCreateDestroyTask(reason, ex);
},
mBGExecutor)
.continueWithTask(Task::getResult);
}
oldDestroy(reason, ex);
return Task.forResult(nullsafeFIXME(null, "Empty Destroy Task"));
return Task.call(
() -> {
if (mReloadTask != null) {
log(
method,
"Reloading React Native. Waiting for reload to finish before destroying React Native.");
return mReloadTask.continueWithTask(
task -> newGetOrCreateDestroyTask(reason, ex), mBGExecutor);
}
return newGetOrCreateDestroyTask(reason, ex);
},
mBGExecutor)
.continueWithTask(Task::getResult);
}
private MemoryPressureListener createMemoryPressureListener(ReactInstance reactInstance) {
@@ -720,30 +705,6 @@ public class ReactHostImpl implements ReactHost {
@ThreadConfined("ReactHost")
private @Nullable Task<Void> mStartTask = null;
@ThreadConfined("ReactHost")
private Task<Void> oldGetOrCreateStartTask() {
if (mStartTask == null) {
final String method = "oldGetOrCreateStartTask()";
log(method, "Schedule");
mStartTask =
getOrCreateReactInstance()
.continueWithTask(
task -> {
if (task.isFaulted()) {
destroy(
"oldGetOrCreateStartTask() failure: " + task.getError().getMessage(),
task.getError());
mReactHostDelegate.handleInstanceException(task.getError());
}
return task;
},
mBGExecutor)
.makeVoid();
}
return mStartTask;
}
@ThreadConfined("ReactHost")
private Task<Void> newGetOrCreateStartTask() {
if (mStartTask == null) {
@@ -857,12 +818,8 @@ public class ReactHostImpl implements ReactHost {
* destroying, will wait until destroy is finished, before creating.
*/
private Task<ReactInstance> getOrCreateReactInstance() {
if (ReactFeatureFlags.enableBridgelessArchitectureNewCreateReloadDestroy) {
return Task.call(this::waitThenCallNewGetOrCreateReactInstanceTask, mBGExecutor)
.continueWithTask(Task::getResult);
}
return oldGetOrCreateReactInstanceTask();
return Task.call(this::waitThenCallNewGetOrCreateReactInstanceTask, mBGExecutor)
.continueWithTask(Task::getResult);
}
@ThreadConfined("ReactHost")
@@ -1021,87 +978,6 @@ public class ReactHostImpl implements ReactHost {
});
}
private Task<ReactInstance> oldGetOrCreateReactInstanceTask() {
final String method = "oldGetOrCreateReactInstanceTask()";
log(method);
return mReactInstanceTaskRef.getOrCreate(
() -> {
log(method, "Start");
ReactMarker.logMarker(
ReactMarkerConstants.REACT_BRIDGELESS_LOADING_START, BRIDGELESS_MARKER_INSTANCE_KEY);
final BridgelessReactContext reactContext = getOrCreateReactContext();
final DevSupportManager devSupportManager = getDevSupportManager();
reactContext.setJSExceptionHandler(devSupportManager);
return getJsBundleLoader()
.onSuccess(
task -> {
final JSBundleLoader bundleLoader = task.getResult();
log(method, "Creating ReactInstance");
final ReactInstance instance =
new ReactInstance(
reactContext,
mReactHostDelegate,
mComponentFactory,
devSupportManager,
mQueueThreadExceptionHandler,
mReactJsExceptionHandler,
mUseDevSupport);
if (ReactFeatureFlags
.unstable_bridgelessArchitectureMemoryPressureHackyBoltsFix) {
mMemoryPressureListener = createMemoryPressureListener(instance);
}
mMemoryPressureRouter.addMemoryPressureListener(mMemoryPressureListener);
log(method, "Loading JS Bundle");
instance.loadJSBundle(bundleLoader);
log(
method,
"Calling DevSupportManagerBase.onNewReactContextCreated(reactContext)");
devSupportManager.onNewReactContextCreated(reactContext);
reactContext.runOnJSQueueThread(
() -> {
// Executing on the JS thread to ensurethat we're done
// loading the JS bundle.
// TODO T76081936 Move this if we switchto a sync RTE
ReactMarker.logMarker(
ReactMarkerConstants.REACT_BRIDGELESS_LOADING_END,
BRIDGELESS_MARKER_INSTANCE_KEY);
});
return instance;
},
mBGExecutor)
.onSuccess(
task -> {
/*
Call ReactContext.onHostResume() only when already in the resumed state which
aligns with the bridge https://fburl.com/diffusion/2qhxmudv.
*/
mReactLifecycleStateManager.resumeReactContextIfHostResumed(
reactContext, getCurrentActivity());
ReactInstanceEventListener[] listeners =
new ReactInstanceEventListener[mReactInstanceEventListeners.size()];
final ReactInstanceEventListener[] finalListeners =
mReactInstanceEventListeners.toArray(listeners);
log(method, "Executing ReactInstanceEventListeners");
for (ReactInstanceEventListener listener : finalListeners) {
if (listener != null) {
listener.onReactContextInitialized(reactContext);
}
}
return task.getResult();
},
mUIExecutor);
});
}
private Task<JSBundleLoader> getJsBundleLoader() {
final String method = "getJSBundleLoader()";
log(method);
@@ -1604,141 +1480,6 @@ public class ReactHostImpl implements ReactHost {
return mDestroyTask;
}
/** Destroy and recreate the ReactInstance and context. */
private Task<Void> oldReload(String reason) {
final String method = "oldReload()";
log(method);
// Log how React Native is destroyed
// TODO(T136397487): Remove after Venice is shipped to 100%
raiseSoftException(method, reason);
synchronized (mReactInstanceTaskRef) {
mMemoryPressureRouter.removeMemoryPressureListener(mMemoryPressureListener);
oldDestroyReactInstanceAndContext(method, reason);
return callAfterGetOrCreateReactInstance(
method,
reactInstance -> {
// Restart any attached surfaces
log(method, "Restarting Surfaces");
synchronized (mAttachedSurfaces) {
for (ReactSurfaceImpl surface : mAttachedSurfaces) {
reactInstance.startSurface(surface);
}
}
});
}
}
/** Destroy the specified instance and context. */
private void oldDestroy(String reason, @Nullable Exception ex) {
final String method = "oldDestroy()";
log(method);
// Log how React Native is destroyed
// TODO(T136397487): Remove after Venice is shipped to 100%
raiseSoftException(method, reason, ex);
synchronized (mReactInstanceTaskRef) {
// Prevent re-destroy when ReactInstance has been reset already, which could happen when
// calling destroy multiple times on the same thread
ReactInstance reactInstance = mReactInstanceTaskRef.get().getResult();
if (reactInstance == null) {
return;
}
// Retain a reference to current ReactContext before de-referenced by mReactContextRef
final ReactContext reactContext = getCurrentReactContext();
if (reactContext != null) {
mMemoryPressureRouter.destroy(reactContext);
}
oldDestroyReactInstanceAndContext(method, reason);
// Remove all attached surfaces
log(method, "Clearing attached surfaces");
synchronized (mAttachedSurfaces) {
mAttachedSurfaces.clear();
}
Task.call(
(Callable<Void>)
() -> {
moveToHostDestroy(reactContext);
return null;
},
mUIExecutor);
}
}
private void oldDestroyReactInstanceAndContext(final String callingMethod, final String reason) {
final String method = "oldDestroyReactInstanceAndContext(" + callingMethod + ")";
log(method);
synchronized (mReactInstanceTaskRef) {
Task<ReactInstance> task = mReactInstanceTaskRef.getAndReset();
if (!task.isFaulted() && !task.isCancelled()) {
final ReactInstance instance = task.getResult();
// Noop on redundant calls to destroyReactInstance()
if (instance == null) {
log(method, "ReactInstance is null");
return;
}
/*
* The surfaces should be stopped before the instance destroy.
* Calling stop directly on instance ensures we keep the list of attached surfaces for restart.
*/
log(method, "Stopping surfaces");
synchronized (mAttachedSurfaces) {
for (ReactSurfaceImpl surface : mAttachedSurfaces) {
instance.stopSurface(surface);
surface.clear();
}
}
ReactContext reactContext = getCurrentReactContext();
// Reset the ReactContext inside the DevSupportManager
if (reactContext != null) {
log(method, "DevSupportManager.onReactInstanceDestroyed()");
getDevSupportManager().onReactInstanceDestroyed(reactContext);
log(method, "Destroy ReactContext");
mBridgelessReactContextRef.reset();
}
mBGExecutor.execute(
() -> {
// instance.destroy() is time consuming and is confined to ReactHost thread.
log(method, "Destroy ReactInstance");
instance.destroy();
// Re-enable preloads
log(method, "Resetting Preload task ref");
mStartTask = null;
});
} else {
raiseSoftException(
method,
("Not cleaning up ReactInstance: task.isFaulted() = "
+ task.isFaulted()
+ ", task.isCancelled() = "
+ task.isCancelled())
+ ". Reason: "
+ reason);
mBGExecutor.execute(
() -> {
log(method, "Resetting Preload task ref");
mStartTask = null;
});
}
}
}
@Nullable
@Override
public JSEngineResolutionAlgorithm getJsEngineResolutionAlgorithm() {