diff --git a/src/renderers/noop/ReactNoop.js b/src/renderers/noop/ReactNoop.js index 9214a1865b..4ffa0b6582 100644 --- a/src/renderers/noop/ReactNoop.js +++ b/src/renderers/noop/ReactNoop.js @@ -20,20 +20,44 @@ 'use strict'; import type { Fiber } from 'ReactFiber'; +import type { HostChildren } from 'ReactFiberReconciler'; var ReactFiberReconciler = require('ReactFiberReconciler'); var scheduledHighPriCallback = null; var scheduledLowPriCallback = null; +type Props = { }; +type Instance = { id: number }; + +var instanceCounter = 0; + var NoopRenderer = ReactFiberReconciler({ - createHostInstance() { - + createInstance(type : string, props : Props, children : HostChildren) : Instance { + console.log('Create instance #' + instanceCounter); + return { + id: instanceCounter++ + }; }, + + prepareUpdate(instance : Instance, oldProps : Props, newProps : Props, children : HostChildren) : boolean { + console.log('Prepare for update on #' + instance.id); + return true; + }, + + commitUpdate(instance : Instance, oldProps : Props, newProps : Props, children : HostChildren) : void { + console.log('Commit update on #' + instance.id); + }, + + deleteInstance(instance : Instance) : void { + console.log('Delete #' + instance.id); + }, + scheduleHighPriCallback(callback) { scheduledHighPriCallback = callback; }, + scheduleLowPriCallback(callback) { scheduledLowPriCallback = callback; }, diff --git a/src/renderers/shared/fiber/ReactFiber.js b/src/renderers/shared/fiber/ReactFiber.js index b4dbb18880..39683f001e 100644 --- a/src/renderers/shared/fiber/ReactFiber.js +++ b/src/renderers/shared/fiber/ReactFiber.js @@ -48,7 +48,7 @@ type Instance = { type: any, // The local state associated with this fiber. - stateNode: ?Object, + stateNode: any, // Conceptual aliases // parent : Instance -> return The parent happens to be the same as the diff --git a/src/renderers/shared/fiber/ReactFiberCommitWork.js b/src/renderers/shared/fiber/ReactFiberCommitWork.js index 161c2b3c8d..1f3e5e5a22 100644 --- a/src/renderers/shared/fiber/ReactFiberCommitWork.js +++ b/src/renderers/shared/fiber/ReactFiberCommitWork.js @@ -24,6 +24,8 @@ var { module.exports = function(config : HostConfig) { + const commitUpdate = config.commitUpdate; + function commitWork(finishedWork : Fiber) : void { switch (finishedWork.tag) { case ClassComponent: @@ -33,7 +35,17 @@ module.exports = function(config : HostConfig) { // TODO: Attach children to root container. return; case HostComponent: - console.log('commit updates to host component', finishedWork.type); + if (finishedWork.stateNode == null || !finishedWork.alternate) { + throw new Error('This should only be done during updates.'); + } + const children = finishedWork.output; + const newProps = finishedWork.memoizedProps; + // If we have an alternate, that means this is an update and we need to + // schedule a side-effect to do the updates. + const current = finishedWork.alternate; + const oldProps = current.memoizedProps; + const instance : I = finishedWork.stateNode; + commitUpdate(instance, oldProps, newProps, children); return; default: throw new Error('This unit of work tag should not have side-effects.'); diff --git a/src/renderers/shared/fiber/ReactFiberCompleteWork.js b/src/renderers/shared/fiber/ReactFiberCompleteWork.js index 50c6e6895f..6f4752ccc0 100644 --- a/src/renderers/shared/fiber/ReactFiberCompleteWork.js +++ b/src/renderers/shared/fiber/ReactFiberCompleteWork.js @@ -15,7 +15,6 @@ import type { ReactCoroutine } from 'ReactCoroutine'; import type { Fiber } from 'ReactFiber'; import type { HostConfig } from 'ReactFiberReconciler'; - import type { ReifiedYield } from 'ReactReifiedYield'; var ReactChildFiber = require('ReactChildFiber'); @@ -33,6 +32,9 @@ var { module.exports = function(config : HostConfig) { + const createInstance = config.createInstance; + const prepareUpdate = config.prepareUpdate; + function markForPostEffect(workInProgress : Fiber) { // Schedule a side-effect on this fiber, after the children's side-effects. if (workInProgress.lastEffect) { @@ -120,13 +122,24 @@ module.exports = function(config : HostConfig) { case HostContainer: return null; case HostComponent: + console.log('/host component', workInProgress.type); transferOutput(workInProgress.child, workInProgress); - if (workInProgress.alternate) { + const children = workInProgress.output; + const newProps = workInProgress.memoizedProps; + if (workInProgress.alternate && workInProgress.stateNode != null) { // If we have an alternate, that means this is an update and we need to // schedule a side-effect to do the updates. - markForPostEffect(workInProgress); + const current = workInProgress.alternate; + const oldProps = current.memoizedProps; + const instance : I = workInProgress.stateNode; + if (prepareUpdate(instance, oldProps, newProps, children)) { + // This returns true if there was something to update. + markForPostEffect(workInProgress); + } + } else { + const instance = createInstance(workInProgress.type, newProps, children); + workInProgress.stateNode = instance; } - console.log('/host component', workInProgress.type); return null; case CoroutineComponent: console.log('/coroutine component', workInProgress.pendingProps.handler.name); diff --git a/src/renderers/shared/fiber/ReactFiberReconciler.js b/src/renderers/shared/fiber/ReactFiberReconciler.js index 3fde615cf0..28421314ab 100644 --- a/src/renderers/shared/fiber/ReactFiberReconciler.js +++ b/src/renderers/shared/fiber/ReactFiberReconciler.js @@ -22,18 +22,21 @@ var { LowPriority, } = require('ReactPriorityLevel'); -type ReactHostElement = { - type: T, - props: P -}; - type Deadline = { timeRemaining : () => number }; +type HostChildNode = { output: HostChildren, sibling: ?HostChildNode }; + +export type HostChildren = null | void | I | HostChildNode; + export type HostConfig = { - createHostInstance(element : ReactHostElement) : I, + createInstance(type : T, props : P, children : HostChildren) : I, + prepareUpdate(instance : I, oldProps : P, newProps : P, children : HostChildren) : bool, + commitUpdate(instance : I, oldProps : P, newProps : P, children : HostChildren) : void, + deleteInstance(instance : I) : void, + scheduleHighPriCallback(callback : () => void) : void, scheduleLowPriCallback(callback : (deadline : Deadline) => void) : void