From b28ddede7b8a962f288d17f2720451fd2a2df12e Mon Sep 17 00:00:00 2001 From: David Vacca Date: Mon, 12 Apr 2021 00:03:16 -0700 Subject: [PATCH] Transfer 'DisplayMode' value from Native -> JS Summary: This diff adds a new variable called "DisplayMode" into SurfaceHandler.cpp and FacebookAppRouteHandler.js. The purpose of DisplayMode is for the native pre-render system to notify React that the a surface is either being "pre-rendered" or "rendered" When the surface is being "pre-rendered" (displayMode == "SUSPENDED"), react will create and commit React Trees, but it will not execute use-effect callbacks When the surface is being "rendered" (displayMode == "VISIBLE"), react will create and commit React Trees and it will not execute all use-effect callbacks that weren't executed during "pre-rendering" By default surfaces are going to be rendered with displayMode == "VISIBLE". This diff should not create any change of behavior for now, this is the infra required to integrate the new offScreen API the react team is working on for pre-rendering system changelog: [internal] internal Reviewed By: yungsters Differential Revision: D27614664 fbshipit-source-id: f1f42fdf174c2ffa74174feb1873f1d5d46e7a95 --- Libraries/ReactNative/AppRegistry.js | 20 ++++++++--- Libraries/ReactNative/DisplayMode.js | 33 +++++++++++++++++++ Libraries/ReactNative/renderApplication.js | 2 ++ .../react/renderer/uimanager/primitives.h | 2 ++ 4 files changed, 52 insertions(+), 5 deletions(-) create mode 100644 Libraries/ReactNative/DisplayMode.js diff --git a/Libraries/ReactNative/AppRegistry.js b/Libraries/ReactNative/AppRegistry.js index 2b37b9a4f73..96edccc1096 100644 --- a/Libraries/ReactNative/AppRegistry.js +++ b/Libraries/ReactNative/AppRegistry.js @@ -18,6 +18,7 @@ const invariant = require('invariant'); const renderApplication = require('./renderApplication'); import type {IPerformanceLogger} from '../Utilities/createPerformanceLogger'; +import {coerceDisplayMode} from './DisplayMode'; import createPerformanceLogger from '../Utilities/createPerformanceLogger'; import NativeHeadlessJsTaskSupport from './NativeHeadlessJsTaskSupport'; import HeadlessJsTaskError from './HeadlessJsTaskError'; @@ -111,7 +112,7 @@ const AppRegistry = { let scopedPerformanceLogger = createPerformanceLogger(); runnables[appKey] = { componentProvider, - run: appParameters => { + run: (appParameters, displayMode) => { renderApplication( componentProviderInstrumentationHook( componentProvider, @@ -125,6 +126,7 @@ const AppRegistry = { scopedPerformanceLogger, appKey === 'LogBox', appKey, + coerceDisplayMode(displayMode), ); }, }; @@ -179,7 +181,11 @@ const AppRegistry = { * * See https://reactnative.dev/docs/appregistry.html#runapplication */ - runApplication(appKey: string, appParameters: any): void { + runApplication( + appKey: string, + appParameters: any, + displayMode?: number, + ): void { if (appKey !== 'LogBox') { const msg = 'Running "' + appKey + '" with ' + JSON.stringify(appParameters); @@ -198,13 +204,17 @@ const AppRegistry = { ); SceneTracker.setActiveScene({name: appKey}); - runnables[appKey].run(appParameters); + runnables[appKey].run(appParameters, displayMode); }, /** * Update initial props for a surface that's already rendered */ - setSurfaceProps(appKey: string, appParameters: any): void { + setSurfaceProps( + appKey: string, + appParameters: any, + displayMode?: number, + ): void { if (appKey !== 'LogBox') { const msg = 'Updating props for Surface "' + @@ -225,7 +235,7 @@ const AppRegistry = { "* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called.", ); - runnables[appKey].run(appParameters); + runnables[appKey].run(appParameters, displayMode); }, /** diff --git a/Libraries/ReactNative/DisplayMode.js b/Libraries/ReactNative/DisplayMode.js new file mode 100644 index 00000000000..30e76fcccd7 --- /dev/null +++ b/Libraries/ReactNative/DisplayMode.js @@ -0,0 +1,33 @@ +/** + * 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. + * + * @flow strict-local + * @format + */ + +export opaque type DisplayModeType = number; + +/** DisplayMode should be in sync with the method displayModeToInt from + * react/renderer/uimanager/primitives.h. */ +const DisplayMode: {[string]: DisplayModeType} = Object.freeze({ + VISIBLE: 1, + SUSPENDED: 2, + HIDDEN: 3, +}); + +export function coerceDisplayMode(value: ?number): DisplayModeType { + if (value == null || value === undefined) { + return DisplayMode.VISIBLE; + } + switch (value) { + case DisplayMode.SUSPENDED: + case DisplayMode.HIDDEN: + return value; + } + return DisplayMode.VISIBLE; +} + +export default DisplayMode; diff --git a/Libraries/ReactNative/renderApplication.js b/Libraries/ReactNative/renderApplication.js index 870b1e28968..8c916978380 100644 --- a/Libraries/ReactNative/renderApplication.js +++ b/Libraries/ReactNative/renderApplication.js @@ -12,6 +12,7 @@ const AppContainer = require('./AppContainer'); import GlobalPerformanceLogger from '../Utilities/GlobalPerformanceLogger'; import type {IPerformanceLogger} from '../Utilities/createPerformanceLogger'; import PerformanceLoggerContext from '../Utilities/PerformanceLoggerContext'; +import type {DisplayModeType} from './DisplayMode'; const React = require('react'); const invariant = require('invariant'); @@ -29,6 +30,7 @@ function renderApplication( scopedPerformanceLogger?: IPerformanceLogger, isLogBox?: boolean, debugName?: string, + displayMode?: ?DisplayModeType, ) { invariant(rootTag, 'Expect to have a valid rootTag, instead got ', rootTag); diff --git a/ReactCommon/react/renderer/uimanager/primitives.h b/ReactCommon/react/renderer/uimanager/primitives.h index 8474a15ae44..749fca7f281 100644 --- a/ReactCommon/react/renderer/uimanager/primitives.h +++ b/ReactCommon/react/renderer/uimanager/primitives.h @@ -125,6 +125,8 @@ inline static SurfaceId surfaceIdFromValue( } inline static int displayModeToInt(DisplayMode const value) { + // the result of this method should be in sync with + // Libraries/ReactNative/DisplayMode.js switch (value) { case DisplayMode::Visible: return 1;