/**1* Copyright 2014-2015, Facebook, Inc.2* All rights reserved.3*4* This source code is licensed under the BSD-style license found in the5* LICENSE file in the root directory of this source tree. An additional grant6* of patent rights can be found in the PATENTS file in the same directory.7*8* @providesModule ReactChildReconciler9* @typechecks static-only10*/1112'use strict';1314var ReactReconciler = require("./ReactReconciler");1516var flattenChildren = require("./flattenChildren");17var instantiateReactComponent = require("./instantiateReactComponent");18var shouldUpdateReactComponent = require("./shouldUpdateReactComponent");1920/**21* ReactChildReconciler provides helpers for initializing or updating a set of22* children. Its output is suitable for passing it onto ReactMultiChild which23* does diffed reordering and insertion.24*/25var ReactChildReconciler = {2627/**28* Generates a "mount image" for each of the supplied children. In the case29* of `ReactDOMComponent`, a mount image is a string of markup.30*31* @param {?object} nestedChildNodes Nested child maps.32* @return {?object} A set of child instances.33* @internal34*/35instantiateChildren: function(nestedChildNodes, transaction, context) {36var children = flattenChildren(nestedChildNodes);37for (var name in children) {38if (children.hasOwnProperty(name)) {39var child = children[name];40// The rendered children must be turned into instances as they're41// mounted.42var childInstance = instantiateReactComponent(child, null);43children[name] = childInstance;44}45}46return children;47},4849/**50* Updates the rendered children and returns a new set of children.51*52* @param {?object} prevChildren Previously initialized set of children.53* @param {?object} nextNestedChildNodes Nested child maps.54* @param {ReactReconcileTransaction} transaction55* @param {object} context56* @return {?object} A new set of child instances.57* @internal58*/59updateChildren: function(60prevChildren,61nextNestedChildNodes,62transaction,63context) {64// We currently don't have a way to track moves here but if we use iterators65// instead of for..in we can zip the iterators and check if an item has66// moved.67// TODO: If nothing has changed, return the prevChildren object so that we68// can quickly bailout if nothing has changed.69var nextChildren = flattenChildren(nextNestedChildNodes);70if (!nextChildren && !prevChildren) {71return null;72}73var name;74for (name in nextChildren) {75if (!nextChildren.hasOwnProperty(name)) {76continue;77}78var prevChild = prevChildren && prevChildren[name];79var prevElement = prevChild && prevChild._currentElement;80var nextElement = nextChildren[name];81if (shouldUpdateReactComponent(prevElement, nextElement)) {82ReactReconciler.receiveComponent(83prevChild, nextElement, transaction, context84);85nextChildren[name] = prevChild;86} else {87if (prevChild) {88ReactReconciler.unmountComponent(prevChild, name);89}90// The child must be instantiated before it's mounted.91var nextChildInstance = instantiateReactComponent(92nextElement,93null94);95nextChildren[name] = nextChildInstance;96}97}98// Unmount children that are no longer present.99for (name in prevChildren) {100if (prevChildren.hasOwnProperty(name) &&101!(nextChildren && nextChildren.hasOwnProperty(name))) {102ReactReconciler.unmountComponent(prevChildren[name]);103}104}105return nextChildren;106},107108/**109* Unmounts all rendered children. This should be used to clean up children110* when this component is unmounted.111*112* @param {?object} renderedChildren Previously initialized set of children.113* @internal114*/115unmountChildren: function(renderedChildren) {116for (var name in renderedChildren) {117var renderedChild = renderedChildren[name];118ReactReconciler.unmountComponent(renderedChild);119}120}121122};123124module.exports = ReactChildReconciler;125126127