Skip to content

Commit

Permalink
Introduce "hydratable instance" type
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sebmarkbage committed Nov 8, 2017
1 parent 7de3b44 commit 5195083
Show file tree
Hide file tree
Showing 7 changed files with 22 additions and 22 deletions.
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiberBeginWork.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ if (__DEV__) {
var warnedAboutStatelessRefs = {};
}

module.exports = function<T, P, I, TI, PI, C, CC, CX, PL>(
config: HostConfig<T, P, I, TI, PI, C, CC, CX, PL>,
module.exports = function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
config: HostConfig<T, P, I, TI, HI, PI, C, CC, CX, PL>,
hostContext: HostContext<C, CX>,
hydrationContext: HydrationContext<C, CX>,
scheduleWork: (fiber: Fiber, expirationTime: ExpirationTime) => void,
Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiberCommitWork.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ if (__DEV__) {
var {startPhaseTimer, stopPhaseTimer} = require('./ReactDebugFiberPerf');
}

module.exports = function<T, P, I, TI, PI, C, CC, CX, PL>(
config: HostConfig<T, P, I, TI, PI, C, CC, CX, PL>,
module.exports = function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
config: HostConfig<T, P, I, TI, HI, PI, C, CC, CX, PL>,
captureError: (failedFiber: Fiber, error: mixed) => Fiber | null,
) {
const {getPublicInstance, mutation, persistence} = config;
Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiberCompleteWork.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ var {
} = require('./ReactFiberContext');
var {Never} = require('./ReactFiberExpirationTime');

module.exports = function<T, P, I, TI, PI, C, CC, CX, PL>(
config: HostConfig<T, P, I, TI, PI, C, CC, CX, PL>,
module.exports = function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
config: HostConfig<T, P, I, TI, HI, PI, C, CC, CX, PL>,
hostContext: HostContext<C, CX>,
hydrationContext: HydrationContext<C, CX>,
) {
Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiberHostContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ export type HostContext<C, CX> = {
resetHostContainer(): void,
};

module.exports = function<T, P, I, TI, PI, C, CC, CX, PL>(
config: HostConfig<T, P, I, TI, PI, C, CC, CX, PL>,
module.exports = function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
config: HostConfig<T, P, I, TI, HI, PI, C, CC, CX, PL>,
): HostContext<C, CX> {
const {getChildHostContext, getRootHostContext} = config;

Expand Down
6 changes: 3 additions & 3 deletions packages/react-reconciler/src/ReactFiberHydrationContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ export type HydrationContext<C, CX> = {
popHydrationState(fiber: Fiber): boolean,
};

module.exports = function<T, P, I, TI, PI, C, CC, CX, PL>(
config: HostConfig<T, P, I, TI, PI, C, CC, CX, PL>,
module.exports = function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
config: HostConfig<T, P, I, TI, HI, PI, C, CC, CX, PL>,
): HydrationContext<C, CX> {
const {shouldSetTextContent, hydration} = config;

Expand Down Expand Up @@ -84,7 +84,7 @@ module.exports = function<T, P, I, TI, PI, C, CC, CX, PL>(
// 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) {
Expand Down
18 changes: 9 additions & 9 deletions packages/react-reconciler/src/ReactFiberReconciler.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export type Deadline = {
type OpaqueHandle = Fiber;
type OpaqueRoot = FiberRoot;

export type HostConfig<T, P, I, TI, PI, C, CC, CX, PL> = {
export type HostConfig<T, P, I, TI, HI, PI, C, CC, CX, PL> = {
getRootHostContext(rootContainerInstance: C): CX,
getChildHostContext(parentHostContext: CX, type: T, instance: C): CX,
getPublicInstance(instance: I | TI): PI,
Expand Down Expand Up @@ -99,7 +99,7 @@ export type HostConfig<T, P, I, TI, PI, C, CC, CX, PL> = {

useSyncScheduling?: boolean,

+hydration?: HydrationHostConfig<T, P, I, TI, C, CX, PL>,
+hydration?: HydrationHostConfig<T, P, I, TI, HI, C, CX, PL>,

+mutation?: MutableUpdatesHostConfig<T, P, I, TI, C, PL>,
+persistence?: PersistentUpdatesHostConfig<T, P, I, TI, C, CC, PL>,
Expand Down Expand Up @@ -154,12 +154,12 @@ type PersistentUpdatesHostConfig<T, P, I, TI, C, CC, PL> = {
replaceContainerChildren(container: C, newChildren: CC): void,
};

type HydrationHostConfig<T, P, I, TI, C, CX, PL> = {
type HydrationHostConfig<T, P, I, TI, HI, C, CX, PL> = {
// 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,
Expand Down Expand Up @@ -255,8 +255,8 @@ function getContextForSubtree(
: parentContext;
}

module.exports = function<T, P, I, TI, PI, C, CC, CX, PL>(
config: HostConfig<T, P, I, TI, PI, C, CC, CX, PL>,
module.exports = function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
config: HostConfig<T, P, I, TI, HI, PI, C, CC, CX, PL>,
): Reconciler<C, I, TI> {
var {getPublicInstance} = config;

Expand Down
4 changes: 2 additions & 2 deletions packages/react-reconciler/src/ReactFiberScheduler.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ if (__DEV__) {
};
}

module.exports = function<T, P, I, TI, PI, C, CC, CX, PL>(
config: HostConfig<T, P, I, TI, PI, C, CC, CX, PL>,
module.exports = function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
config: HostConfig<T, P, I, TI, HI, PI, C, CC, CX, PL>,
) {
const hostContext = ReactFiberHostContext(config);
const hydrationContext: HydrationContext<C, CX> = ReactFiberHydrationContext(
Expand Down

0 comments on commit 5195083

Please sign in to comment.