You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
4.6 KiB
149 lines
4.6 KiB
/** |
|
* Copyright 2013-2015, Facebook, Inc. |
|
* All rights reserved. |
|
* |
|
* This source code is licensed under the BSD-style license found in the |
|
* LICENSE file in the root directory of this source tree. An additional grant |
|
* of patent rights can be found in the PATENTS file in the same directory. |
|
* |
|
* @providesModule ReactChildren |
|
*/ |
|
|
|
'use strict'; |
|
|
|
var PooledClass = require("./PooledClass"); |
|
var ReactFragment = require("./ReactFragment"); |
|
|
|
var traverseAllChildren = require("./traverseAllChildren"); |
|
var warning = require("./warning"); |
|
|
|
var twoArgumentPooler = PooledClass.twoArgumentPooler; |
|
var threeArgumentPooler = PooledClass.threeArgumentPooler; |
|
|
|
/** |
|
* PooledClass representing the bookkeeping associated with performing a child |
|
* traversal. Allows avoiding binding callbacks. |
|
* |
|
* @constructor ForEachBookKeeping |
|
* @param {!function} forEachFunction Function to perform traversal with. |
|
* @param {?*} forEachContext Context to perform context with. |
|
*/ |
|
function ForEachBookKeeping(forEachFunction, forEachContext) { |
|
this.forEachFunction = forEachFunction; |
|
this.forEachContext = forEachContext; |
|
} |
|
PooledClass.addPoolingTo(ForEachBookKeeping, twoArgumentPooler); |
|
|
|
function forEachSingleChild(traverseContext, child, name, i) { |
|
var forEachBookKeeping = traverseContext; |
|
forEachBookKeeping.forEachFunction.call( |
|
forEachBookKeeping.forEachContext, child, i); |
|
} |
|
|
|
/** |
|
* Iterates through children that are typically specified as `props.children`. |
|
* |
|
* The provided forEachFunc(child, index) will be called for each |
|
* leaf child. |
|
* |
|
* @param {?*} children Children tree container. |
|
* @param {function(*, int)} forEachFunc. |
|
* @param {*} forEachContext Context for forEachContext. |
|
*/ |
|
function forEachChildren(children, forEachFunc, forEachContext) { |
|
if (children == null) { |
|
return children; |
|
} |
|
|
|
var traverseContext = |
|
ForEachBookKeeping.getPooled(forEachFunc, forEachContext); |
|
traverseAllChildren(children, forEachSingleChild, traverseContext); |
|
ForEachBookKeeping.release(traverseContext); |
|
} |
|
|
|
/** |
|
* PooledClass representing the bookkeeping associated with performing a child |
|
* mapping. Allows avoiding binding callbacks. |
|
* |
|
* @constructor MapBookKeeping |
|
* @param {!*} mapResult Object containing the ordered map of results. |
|
* @param {!function} mapFunction Function to perform mapping with. |
|
* @param {?*} mapContext Context to perform mapping with. |
|
*/ |
|
function MapBookKeeping(mapResult, mapFunction, mapContext) { |
|
this.mapResult = mapResult; |
|
this.mapFunction = mapFunction; |
|
this.mapContext = mapContext; |
|
} |
|
PooledClass.addPoolingTo(MapBookKeeping, threeArgumentPooler); |
|
|
|
function mapSingleChildIntoContext(traverseContext, child, name, i) { |
|
var mapBookKeeping = traverseContext; |
|
var mapResult = mapBookKeeping.mapResult; |
|
|
|
var keyUnique = !mapResult.hasOwnProperty(name); |
|
if ("production" !== process.env.NODE_ENV) { |
|
("production" !== process.env.NODE_ENV ? warning( |
|
keyUnique, |
|
'ReactChildren.map(...): Encountered two children with the same key, ' + |
|
'`%s`. Child keys must be unique; when two children share a key, only ' + |
|
'the first child will be used.', |
|
name |
|
) : null); |
|
} |
|
|
|
if (keyUnique) { |
|
var mappedChild = |
|
mapBookKeeping.mapFunction.call(mapBookKeeping.mapContext, child, i); |
|
mapResult[name] = mappedChild; |
|
} |
|
} |
|
|
|
/** |
|
* Maps children that are typically specified as `props.children`. |
|
* |
|
* The provided mapFunction(child, key, index) will be called for each |
|
* leaf child. |
|
* |
|
* TODO: This may likely break any calls to `ReactChildren.map` that were |
|
* previously relying on the fact that we guarded against null children. |
|
* |
|
* @param {?*} children Children tree container. |
|
* @param {function(*, int)} mapFunction. |
|
* @param {*} mapContext Context for mapFunction. |
|
* @return {object} Object containing the ordered map of results. |
|
*/ |
|
function mapChildren(children, func, context) { |
|
if (children == null) { |
|
return children; |
|
} |
|
|
|
var mapResult = {}; |
|
var traverseContext = MapBookKeeping.getPooled(mapResult, func, context); |
|
traverseAllChildren(children, mapSingleChildIntoContext, traverseContext); |
|
MapBookKeeping.release(traverseContext); |
|
return ReactFragment.create(mapResult); |
|
} |
|
|
|
function forEachSingleChildDummy(traverseContext, child, name, i) { |
|
return null; |
|
} |
|
|
|
/** |
|
* Count the number of children that are typically specified as |
|
* `props.children`. |
|
* |
|
* @param {?*} children Children tree container. |
|
* @return {number} The number of children. |
|
*/ |
|
function countChildren(children, context) { |
|
return traverseAllChildren(children, forEachSingleChildDummy, null); |
|
} |
|
|
|
var ReactChildren = { |
|
forEach: forEachChildren, |
|
map: mapChildren, |
|
count: countChildren |
|
}; |
|
|
|
module.exports = ReactChildren;
|
|
|