From 5195083f9ae422b21a7fc11bc5e332d27d2605a5 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Wed, 8 Nov 2017 11:31:20 -0800 Subject: [PATCH] Introduce "hydratable instance" type The Flow error here highlighted a quirk in our typing of hydration. React only really knows about a subset of all possible nodes that can exist in a hydrated tree. Currently we assume that the host renderer filters them out to be either Instance or TextInstance. We also assume that those are different things which they might not be. E.g. it could be fine for a renderer to render "text" as the same type as one of the instances, with some default props. We don't really know what it will be narrowed down to until we call canHydrateInstance or canHydrateTextInstance. That's when the type is truly refined. So to solve this I use a different type for hydratable instance that is used in that temporary stage between us reading it from the DOM and until it gets refined by canHydrate(Text)Instance. --- .../src/ReactFiberBeginWork.js | 4 ++-- .../src/ReactFiberCommitWork.js | 4 ++-- .../src/ReactFiberCompleteWork.js | 4 ++-- .../src/ReactFiberHostContext.js | 4 ++-- .../src/ReactFiberHydrationContext.js | 6 +++--- .../src/ReactFiberReconciler.js | 18 +++++++++--------- .../src/ReactFiberScheduler.js | 4 ++-- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js index efeb2a29f28011..22612a32a07a84 100644 --- a/packages/react-reconciler/src/ReactFiberBeginWork.js +++ b/packages/react-reconciler/src/ReactFiberBeginWork.js @@ -67,8 +67,8 @@ if (__DEV__) { var warnedAboutStatelessRefs = {}; } -module.exports = function( - config: HostConfig, +module.exports = function( + config: HostConfig, hostContext: HostContext, hydrationContext: HydrationContext, scheduleWork: (fiber: Fiber, expirationTime: ExpirationTime) => void, diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.js b/packages/react-reconciler/src/ReactFiberCommitWork.js index bae7e7dece8c6f..6a12a5668539f6 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.js @@ -37,8 +37,8 @@ if (__DEV__) { var {startPhaseTimer, stopPhaseTimer} = require('./ReactDebugFiberPerf'); } -module.exports = function( - config: HostConfig, +module.exports = function( + config: HostConfig, captureError: (failedFiber: Fiber, error: mixed) => Fiber | null, ) { const {getPublicInstance, mutation, persistence} = config; diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.js b/packages/react-reconciler/src/ReactFiberCompleteWork.js index e1635828335b4c..60837f968f090b 100644 --- a/packages/react-reconciler/src/ReactFiberCompleteWork.js +++ b/packages/react-reconciler/src/ReactFiberCompleteWork.js @@ -41,8 +41,8 @@ var { } = require('./ReactFiberContext'); var {Never} = require('./ReactFiberExpirationTime'); -module.exports = function( - config: HostConfig, +module.exports = function( + config: HostConfig, hostContext: HostContext, hydrationContext: HydrationContext, ) { diff --git a/packages/react-reconciler/src/ReactFiberHostContext.js b/packages/react-reconciler/src/ReactFiberHostContext.js index c0503256554aaa..bd5ee701cb6fc2 100644 --- a/packages/react-reconciler/src/ReactFiberHostContext.js +++ b/packages/react-reconciler/src/ReactFiberHostContext.js @@ -30,8 +30,8 @@ export type HostContext = { resetHostContainer(): void, }; -module.exports = function( - config: HostConfig, +module.exports = function( + config: HostConfig, ): HostContext { const {getChildHostContext, getRootHostContext} = config; diff --git a/packages/react-reconciler/src/ReactFiberHydrationContext.js b/packages/react-reconciler/src/ReactFiberHydrationContext.js index 6b575b2e8456e8..32ba3339e6b8e5 100644 --- a/packages/react-reconciler/src/ReactFiberHydrationContext.js +++ b/packages/react-reconciler/src/ReactFiberHydrationContext.js @@ -31,8 +31,8 @@ export type HydrationContext = { popHydrationState(fiber: Fiber): boolean, }; -module.exports = function( - config: HostConfig, +module.exports = function( + config: HostConfig, ): HydrationContext { const {shouldSetTextContent, hydration} = config; @@ -84,7 +84,7 @@ module.exports = function( // The deepest Fiber on the stack involved in a hydration context. // This may have been an insertion or a hydration. let hydrationParentFiber: null | Fiber = null; - let nextHydratableInstance: null | I | TI = null; + let nextHydratableInstance: null | HI = null; let isHydrating: boolean = false; function enterHydrationState(fiber: Fiber) { diff --git a/packages/react-reconciler/src/ReactFiberReconciler.js b/packages/react-reconciler/src/ReactFiberReconciler.js index bfe8bfcf684214..5c232bdd9dcf7b 100644 --- a/packages/react-reconciler/src/ReactFiberReconciler.js +++ b/packages/react-reconciler/src/ReactFiberReconciler.js @@ -49,7 +49,7 @@ export type Deadline = { type OpaqueHandle = Fiber; type OpaqueRoot = FiberRoot; -export type HostConfig = { +export type HostConfig = { getRootHostContext(rootContainerInstance: C): CX, getChildHostContext(parentHostContext: CX, type: T, instance: C): CX, getPublicInstance(instance: I | TI): PI, @@ -99,7 +99,7 @@ export type HostConfig = { useSyncScheduling?: boolean, - +hydration?: HydrationHostConfig, + +hydration?: HydrationHostConfig, +mutation?: MutableUpdatesHostConfig, +persistence?: PersistentUpdatesHostConfig, @@ -154,12 +154,12 @@ type PersistentUpdatesHostConfig = { replaceContainerChildren(container: C, newChildren: CC): void, }; -type HydrationHostConfig = { +type HydrationHostConfig = { // Optional hydration - canHydrateInstance(instance: I | TI, type: T, props: P): boolean, - canHydrateTextInstance(instance: I | TI, text: string): boolean, - getNextHydratableSibling(instance: I | TI): null | I | TI, - getFirstHydratableChild(parentInstance: I | C): null | I | TI, + canHydrateInstance(instance: HI, type: T, props: P): boolean, + canHydrateTextInstance(instance: HI, text: string): boolean, + getNextHydratableSibling(instance: I | TI | HI): null | HI, + getFirstHydratableChild(parentInstance: I | C): null | HI, hydrateInstance( instance: I, type: T, @@ -255,8 +255,8 @@ function getContextForSubtree( : parentContext; } -module.exports = function( - config: HostConfig, +module.exports = function( + config: HostConfig, ): Reconciler { var {getPublicInstance} = config; diff --git a/packages/react-reconciler/src/ReactFiberScheduler.js b/packages/react-reconciler/src/ReactFiberScheduler.js index 67a87c9a4a3f83..d99e64d37cc4d3 100644 --- a/packages/react-reconciler/src/ReactFiberScheduler.js +++ b/packages/react-reconciler/src/ReactFiberScheduler.js @@ -141,8 +141,8 @@ if (__DEV__) { }; } -module.exports = function( - config: HostConfig, +module.exports = function( + config: HostConfig, ) { const hostContext = ReactFiberHostContext(config); const hydrationContext: HydrationContext = ReactFiberHydrationContext(