The library for web and native user interfaces.
Use `invariant` in `react/utils`
Just some therapeutic cleanup.
Tim Yung committed
Jul 24, 2013 at 17:19 UTC
bdf2a9bb124b8fc34120949b322202497741f239
10 files changed
+147
-221
src/utils/OrderedMap.js
-2
@@ -85,8 +85,6 @@ function OrderedMapImpl(normalizedObj, computedLength) {
85
* Validates a "public" key - that is, one that the public facing API supplies.
86
* The key is then normalized for internal storage. In order to be considered
87
* valid, all keys must be non-empty, defined, non-null strings or numbers.
88
- * Since this already costs a function invocation, will avoid additional call to
89
- * `throwIf`.
88
*
89
* @param {string?} key Validates that the key is suitable for use in a
90
* `OrderedMap`.
src/utils/Transaction.js
+37
-38
@@ -18,23 +18,7 @@
18
19
"use strict";
20
21
-var throwIf = require('throwIf');
22
-
23
-var DUAL_TRANSACTION = 'DUAL_TRANSACTION';
24
-var MISSING_TRANSACTION = 'MISSING_TRANSACTION';
25
-if (__DEV__) {
26
- DUAL_TRANSACTION =
27
- 'Cannot initialize transaction when there is already an outstanding ' +
28
- 'transaction. Common causes of this are trying to render a component ' +
29
- 'when you are already rendering a component or attempting a state ' +
30
- 'transition while in a render function. Another possibility is that ' +
31
- 'you are rendering new content (or state transitioning) in a ' +
32
- 'componentDidRender callback. If this is not the case, please report the ' +
33
- 'issue immediately.';
34
-
35
- MISSING_TRANSACTION =
36
- 'Cannot close transaction when there is none open.';
37
-}
21
+var invariant = require('invariant');
22
23
/**
24
* `Transaction` creates a black box that is able to wrap any method such that
@@ -156,26 +140,33 @@ var Mixin = {
140
* @return Return value from `method`.
141
*/
142
perform: function(method, scope, a, b, c, d, e, f) {
159
- throwIf(this.isInTransaction(), DUAL_TRANSACTION);
143
+ invariant(
144
+ !this.isInTransaction(),
145
+ 'Transaction.perform(...): Cannot initialize a transaction when there ' +
146
+ 'is already an outstanding transaction.'
147
+ );
148
var memberStart = Date.now();
161
- var err = null;
149
+ var errorToThrow = null;
150
var ret;
151
try {
152
this.initializeAll();
153
ret = method.call(scope, a, b, c, d, e, f);
166
- } catch (ie_requires_catch) {
167
- err = ie_requires_catch;
154
+ } catch (error) {
155
+ // IE8 requires `catch` in order to use `finally`.
156
+ errorToThrow = error;
157
} finally {
158
var memberEnd = Date.now();
159
this.methodInvocationTime += (memberEnd - memberStart);
160
try {
161
this.closeAll();
173
- } catch (closeAllErr) {
174
- err = err || closeAllErr;
162
+ } catch (closeError) {
163
+ // If `method` throws, prefer to show that stack trace over any thrown
164
+ // by invoking `closeAll`.
165
+ errorToThrow = errorToThrow || closeError;
166
}
167
}
177
- if (err) {
178
- throw err;
168
+ if (errorToThrow) {
169
+ throw errorToThrow;
170
}
171
return ret;
172
},
@@ -184,15 +175,17 @@ var Mixin = {
175
this._isInTransaction = true;
176
var transactionWrappers = this.transactionWrappers;
177
var wrapperInitTimes = this.timingMetrics.wrapperInitTimes;
187
- var err = null;
178
+ var errorToThrow = null;
179
for (var i = 0; i < transactionWrappers.length; i++) {
180
var initStart = Date.now();
181
var wrapper = transactionWrappers[i];
182
try {
192
- this.wrapperInitData[i] =
193
- wrapper.initialize ? wrapper.initialize.call(this) : null;
194
- } catch (initErr) {
195
- err = err || initErr; // Remember the first error.
183
+ this.wrapperInitData[i] = wrapper.initialize ?
184
+ wrapper.initialize.call(this) :
185
+ null;
186
+ } catch (initError) {
187
+ // Prefer to show the stack trace of the first error.
188
+ errorToThrow = errorToThrow || initError;
189
this.wrapperInitData[i] = Transaction.OBSERVED_ERROR;
190
} finally {
191
var curInitTime = wrapperInitTimes[i];
@@ -200,8 +193,8 @@ var Mixin = {
193
wrapperInitTimes[i] = (curInitTime || 0) + (initEnd - initStart);
194
}
195
}
203
- if (err) {
204
- throw err;
196
+ if (errorToThrow) {
197
+ throw errorToThrow;
198
}
199
},
200
@@ -212,10 +205,13 @@ var Mixin = {
205
* invoked).
206
*/
207
closeAll: function() {
215
- throwIf(!this.isInTransaction(), MISSING_TRANSACTION);
208
+ invariant(
209
+ this.isInTransaction(),
210
+ 'Transaction.closeAll(): Cannot close transaction when none are open.'
211
+ );
212
var transactionWrappers = this.transactionWrappers;
213
var wrapperCloseTimes = this.timingMetrics.wrapperCloseTimes;
218
- var err = null;
214
+ var errorToThrow = null;
215
for (var i = 0; i < transactionWrappers.length; i++) {
216
var wrapper = transactionWrappers[i];
217
var closeStart = Date.now();
@@ -224,8 +220,9 @@ var Mixin = {
220
if (initData !== Transaction.OBSERVED_ERROR) {
221
wrapper.close && wrapper.close.call(this, initData);
222
}
227
- } catch (closeErr) {
228
- err = err || closeErr; // Remember the first error.
223
+ } catch (closeError) {
224
+ // Prefer to show the stack trace of the first error.
225
+ errorToThrow = errorToThrow || closeError;
226
} finally {
227
var closeEnd = Date.now();
228
var curCloseTime = wrapperCloseTimes[i];
@@ -234,14 +231,16 @@ var Mixin = {
231
}
232
this.wrapperInitData.length = 0;
233
this._isInTransaction = false;
237
- if (err) {
238
- throw err;
234
+ if (errorToThrow) {
235
+ throw errorToThrow;
236
}
237
}
238
};
239
240
var Transaction = {
241
+
242
Mixin: Mixin,
243
+
244
/**
245
* Token to look for to determine if an error occured.
246
*/
src/utils/accumulate.js
+22
-38
@@ -18,50 +18,34 @@
18
19
"use strict";
20
21
-var throwIf = require('throwIf');
22
-
23
-var INVALID_ARGS = 'INVALID_ACCUM_ARGS';
24
-
25
-if (__DEV__) {
26
- INVALID_ARGS =
27
- 'accumulate requires non empty (non-null, defined) next ' +
28
- 'values. All arrays accumulated must not contain any empty items.';
29
-}
21
+var invariant = require('invariant');
22
23
/**
32
- * Accumulates items that must never be empty, into a result in a manner that
33
- * conserves memory - avoiding allocation of arrays until they are needed. The
34
- * accumulation may start and/or end up being a single element or an array
35
- * depending on the total count (if greater than one, an array is allocated).
36
- * Handles most common case first (starting with an empty current value and
37
- * acquiring one).
38
- * @return {Accumulation} An accumulation which is either a single item or an
39
- * Array of items.
24
+ * Accumulates items that must not be null or undefined.
25
+ *
26
+ * This is used to conserve memory by avoiding array allocations.
27
+ *
28
+ * @return {*|array<*>} An accumulation of items.
29
*/
41
-function accumulate(cur, next) {
42
- var curValIsEmpty = cur == null; // Will test for emptiness (null/undef)
43
- var nextValIsEmpty = next === null;
44
- if (__DEV__) {
45
- throwIf(nextValIsEmpty, INVALID_ARGS);
46
- }
47
- if (nextValIsEmpty) {
48
- return cur;
30
+function accumulate(current, next) {
31
+ invariant(
32
+ next != null,
33
+ 'accumulate(...): Accumulated items must be not be null or undefined.'
34
+ );
35
+ if (current == null) {
36
+ return next;
37
} else {
50
- if (curValIsEmpty) {
51
- return next;
38
+ // Both are not empty. Warning: Never call x.concat(y) when you are not
39
+ // certain that x is an Array (x could be a string with concat method).
40
+ var currentIsArray = Array.isArray(current);
41
+ var nextIsArray = Array.isArray(next);
42
+ if (currentIsArray) {
43
+ return current.concat(next);
44
} else {
53
- // Both are not empty. Warning: Never call x.concat(y) when you are not
54
- // certain that x is an Array (x could be a string with concat method).
55
- var curIsArray = Array.isArray(cur);
56
- var nextIsArray = Array.isArray(next);
57
- if (curIsArray) {
58
- return cur.concat(next);
45
+ if (nextIsArray) {
46
+ return [current].concat(next);
47
} else {
60
- if (nextIsArray) {
61
- return [cur].concat(next);
62
- } else {
63
- return [cur, next];
64
- }
48
+ return [current, next];
49
}
50
}
51
}
src/utils/escapeTextForBrowser.js
+15
-16
@@ -14,19 +14,12 @@
14
* limitations under the License.
15
*
16
* @providesModule escapeTextForBrowser
17
+ * @typechecks static-only
18
*/
19
20
"use strict";
21
21
-var throwIf = require('throwIf');
22
-
23
-var ESCAPE_TYPE_ERR;
24
-
25
-if (__DEV__) {
26
- ESCAPE_TYPE_ERR =
27
- 'The React core has attempted to escape content that is of a ' +
28
- 'mysterious type (object etc) Escaping only works on numbers and strings';
29
-}
22
+var invariant = require('invariant');
23
24
var ESCAPE_LOOKUP = {
25
"&": "&",
@@ -41,13 +34,19 @@ function escaper(match) {
34
return ESCAPE_LOOKUP[match];
35
}
36
44
-var escapeTextForBrowser = function (text) {
37
+/**
38
+ * Escapes text to prevent scripting attacks.
39
+ *
40
+ * @param {number|string} text Text value to escape.
41
+ * @return {string} An escaped string.
42
+ */
43
+function escapeTextForBrowser(text) {
44
var type = typeof text;
46
- var invalid = type === 'object';
47
- if (__DEV__) {
48
- throwIf(invalid, ESCAPE_TYPE_ERR);
49
- }
50
- if (text === '' || invalid) {
45
+ invariant(
46
+ type !== 'object',
47
+ 'escapeTextForBrowser(...): Attempted to escape an object.'
48
+ );
49
+ if (text === '') {
50
return '';
51
} else {
52
if (type === 'string') {
@@ -56,6 +55,6 @@ var escapeTextForBrowser = function (text) {
55
return (''+text).replace(/[&><"'\/]/g, escaper);
56
}
57
}
59
-};
58
+}
59
60
module.exports = escapeTextForBrowser;
src/utils/flattenChildren.js
+9
-9
@@ -18,7 +18,7 @@
18
19
"use strict";
20
21
-var throwIf = require('throwIf');
21
+var invariant = require('invariant');
22
var traverseAllChildren = require('traverseAllChildren');
23
24
/**
@@ -27,14 +27,14 @@ var traverseAllChildren = require('traverseAllChildren');
27
* @param {!string} name String name of key path to child.
28
*/
29
function flattenSingleChildIntoContext(traverseContext, child, name) {
30
- // We found a component instance
30
+ // We found a component instance.
31
var result = traverseContext;
32
- if (__DEV__) {
33
- throwIf(
34
- result.hasOwnProperty(name),
35
- traverseAllChildren.DUPLICATE_KEY_ERROR
36
- );
37
- }
32
+ invariant(
33
+ !result.hasOwnProperty(name),
34
+ 'flattenChildren(...): Encountered two children with the same key, `%s`. ' +
35
+ 'Children keys must be unique.',
36
+ name
37
+ );
38
result[name] = child;
39
}
40
@@ -43,7 +43,7 @@ function flattenSingleChildIntoContext(traverseContext, child, name) {
43
* @return {!object} flattened children keyed by name.
44
*/
45
function flattenChildren(children) {
46
- if (children === null || children === undefined) {
46
+ if (children == null) {
47
return children;
48
}
49
var result = {};
src/utils/keyMirror.js
+20
-18
@@ -14,36 +14,38 @@
14
* limitations under the License.
15
*
16
* @providesModule keyMirror
17
+ * @typechecks static-only
18
*/
19
20
"use strict";
21
21
-var throwIf = require('throwIf');
22
-
23
-var NOT_OBJECT_ERROR = 'NOT_OBJECT_ERROR';
24
-if (__DEV__) {
25
- NOT_OBJECT_ERROR = 'keyMirror only works on objects';
26
-}
22
+var invariant = require('invariant');
23
24
/**
29
- * Utility for constructing enums with keys being equal to the associated
30
- * values, even when using advanced key crushing. This is useful for debugging,
31
- * but also for using the values themselves as lookups into the enum.
32
- * Example:
33
- * var COLORS = keyMirror({blue: null, red: null});
34
- * var myColor = COLORS.blue;
35
- * var isColorValid = !!COLORS[myColor]
25
+ * Constructs an enumeration with keys equal to their value.
26
+ *
27
+ * For example:
28
+ *
29
+ * var COLORS = keyMirror({blue: null, red: null});
30
+ * var myColor = COLORS.blue;
31
+ * var isColorValid = !!COLORS[myColor];
32
+ *
33
* The last line could not be performed if the values of the generated enum were
34
* not equal to their keys.
38
- * Input: {key1: val1, key2: val2}
39
- * Output: {key1: key1, key2: key2}
35
+ *
36
+ * Input: {key1: val1, key2: val2}
37
+ * Output: {key1: key1, key2: key2}
38
+ *
39
+ * @param {object} obj
40
+ * @return {object}
41
*/
42
var keyMirror = function(obj) {
43
var ret = {};
44
var key;
44
-
45
- throwIf(!(obj instanceof Object) || Array.isArray(obj), NOT_OBJECT_ERROR);
46
-
45
+ invariant(
46
+ obj instanceof Object && !Array.isArray(obj),
47
+ 'keyMirror(...): Argument must be an object.'
48
+ );
49
for (key in obj) {
50
if (!obj.hasOwnProperty(key)) {
51
continue;
src/utils/mapAllChildren.js
+8
-8
@@ -20,7 +20,7 @@
20
21
var PooledClass = require('PooledClass');
22
23
-var throwIf = require('throwIf');
23
+var invariant = require('invariant');
24
var traverseAllChildren = require('traverseAllChildren');
25
26
var threeArgumentPooler = PooledClass.threeArgumentPooler;
@@ -50,13 +50,13 @@ function mapSingleChildIntoContext(traverseContext, child, name, i) {
50
var mapFunction = mapBookKeeping.mapFunction;
51
var mapContext = mapBookKeeping.mapContext;
52
var mappedChild = mapFunction.call(mapContext, child, name, i);
53
- // We found a component instance
54
- if (__DEV__) {
55
- throwIf(
56
- mapResult.hasOwnProperty(name),
57
- traverseAllChildren.DUPLICATE_KEY_ERROR
58
- );
59
- }
53
+ // We found a component instance.
54
+ invariant(
55
+ !mapResult.hasOwnProperty(name),
56
+ 'mapAllChildren(...): Encountered two children with the same key, `%s`. ' +
57
+ 'Children keys must be unique.',
58
+ name
59
+ );
60
mapResult[name] = mappedChild;
61
}
62
src/utils/mergeDeepInto.js
+6
-20
@@ -21,9 +21,8 @@
21
22
"use strict";
23
24
-var keyMirror = require('keyMirror');
24
+var invariant = require('invariant');
25
var mergeHelpers = require('mergeHelpers');
26
-var throwIf = require('throwIf');
26
27
var ArrayStrategies = mergeHelpers.ArrayStrategies;
28
var checkArrayStrategy = mergeHelpers.checkArrayStrategy;
@@ -33,20 +32,6 @@ var checkMergeObjectArgs = mergeHelpers.checkMergeObjectArgs;
32
var isTerminal = mergeHelpers.isTerminal;
33
var normalizeMergeArg = mergeHelpers.normalizeMergeArg;
34
36
-var ERRORS = keyMirror({
37
- RUN_TIME_ARRAY_MERGE_FAIL: null
38
-});
39
-
40
-if (__DEV__) {
41
- ERRORS = {
42
- RUN_TIME_ARRAY_MERGE_FAIL:
43
- "The caller has not supplied an ArrayStrategy. This is supported as " +
44
- "long as the data structures being merged do not contain two Arrays " +
45
- "that must be merged together, which is exactly what has just " +
46
- "happened. Change the call site to supply an Array merge resolver."
47
- };
48
-}
49
-
35
/**
36
* Every deep merge function must handle merging in each of the following cases
37
* at every level. We may refer to letters below in implementations. For each
@@ -161,9 +146,10 @@ var mergeSingleFieldDeep = function(one, two, key, arrayStrategy, level) {
146
if (twoValIsTerminal) { // [E]
147
one[key] = twoVal;
148
} else if (twoValIsArray) { // [F]
164
- throwIf(
165
- !ArrayStrategies[arrayStrategy],
166
- ERRORS.RUN_TIME_ARRAY_MERGE_FAIL
149
+ invariant(
150
+ ArrayStrategies[arrayStrategy],
151
+ 'mergeDeepInto(...): Attempted to merge two arrays, but a valid ' +
152
+ 'ArrayStrategy was not specified.'
153
);
154
// Else: At this point, the only other valid option is `IndexByIndex`
155
if (arrayStrategy === ArrayStrategies.Clobber) {
@@ -234,7 +220,7 @@ var mergeSingleFieldDeep = function(one, two, key, arrayStrategy, level) {
220
*/
221
var mergeDeepInto = function(one, twoParam, arrayStrategy) {
222
var two = normalizeMergeArg(twoParam);
237
- checkArrayStrategy(arrayStrategy); // Will be checked twice, for now
223
+ checkArrayStrategy(arrayStrategy); // Will be checked twice, for now.
224
mergeDeepIntoObjects(one, two, arrayStrategy, 0);
225
};
226
src/utils/mergeHelpers.js
+24
-49
@@ -20,8 +20,8 @@
20
21
"use strict";
22
23
+var invariant = require('invariant');
24
var keyMirror = require('keyMirror');
24
-var throwIf = require('throwIf');
25
26
/**
27
* Maximum number of levels to traverse. Will catch circular structures.
@@ -29,41 +29,6 @@ var throwIf = require('throwIf');
29
*/
30
var MAX_MERGE_DEPTH = 36;
31
32
-var ERRORS = keyMirror({
33
- MERGE_ARRAY_FAIL: null,
34
- MERGE_CORE_FAILURE: null,
35
- MERGE_TYPE_USAGE_FAILURE: null,
36
- MERGE_DEEP_MAX_LEVELS: null,
37
- MERGE_DEEP_NO_ARR_STRATEGY: null
38
-});
39
-
40
-if (__DEV__) {
41
- ERRORS = {
42
- MERGE_ARRAY_FAIL:
43
- 'Unsupported type passed to a merge function. You may have passed a ' +
44
- 'structure that contains an array and the merge function does not know ' +
45
- 'how to merge arrays. ',
46
-
47
- MERGE_CORE_FAILURE:
48
- 'Critical assumptions about the merge functions have been violated. ' +
49
- 'This is the fault of the merge functions themselves, not necessarily ' +
50
- 'the callers.',
51
-
52
- MERGE_TYPE_USAGE_FAILURE:
53
- 'Calling merge function with invalid types. You may call merge ' +
54
- 'functions (non-array non-terminal) OR (null/undefined) arguments. ' +
55
- 'mergeInto functions have the same requirements but with an added ' +
56
- 'restriction that the first parameter must not be null/undefined.',
57
-
58
- MERGE_DEEP_MAX_LEVELS:
59
- 'Maximum deep merge depth exceeded. You may attempting to merge ' +
60
- 'circular structures in an unsupported way.',
61
- MERGE_DEEP_NO_ARR_STRATEGY:
62
- 'You must provide an array strategy to deep merge functions to ' +
63
- 'instruct the deep merge how to resolve merging two arrays.'
64
- };
65
-}
66
-
32
/**
33
* We won't worry about edge cases like new String('x') or new Boolean(true).
34
* Functions are considered terminals, and arrays are not.
@@ -99,9 +64,11 @@ var mergeHelpers = {
64
* @param {*} two Array to merge from.
65
*/
66
checkMergeArrayArgs: function(one, two) {
102
- throwIf(
103
- !Array.isArray(one) || !Array.isArray(two),
104
- ERRORS.MERGE_CORE_FAILURE
67
+ invariant(
68
+ Array.isArray(one) && Array.isArray(two),
69
+ 'Critical assumptions about the merge functions have been violated. ' +
70
+ 'This is the fault of the merge functions themselves, not necessarily ' +
71
+ 'the callers.'
72
);
73
},
74
@@ -118,7 +85,12 @@ var mergeHelpers = {
85
* @param {*} arg
86
*/
87
checkMergeObjectArg: function(arg) {
121
- throwIf(isTerminal(arg) || Array.isArray(arg), ERRORS.MERGE_CORE_FAILURE);
88
+ invariant(
89
+ !isTerminal(arg) && !Array.isArray(arg),
90
+ 'Critical assumptions about the merge functions have been violated. ' +
91
+ 'This is the fault of the merge functions themselves, not necessarily ' +
92
+ 'the callers.'
93
+ );
94
},
95
96
/**
@@ -128,19 +100,23 @@ var mergeHelpers = {
100
* @param {number} Level of recursion to validate against maximum.
101
*/
102
checkMergeLevel: function(level) {
131
- throwIf(level >= MAX_MERGE_DEPTH, ERRORS.MERGE_DEEP_MAX_LEVELS);
103
+ invariant(
104
+ level < MAX_MERGE_DEPTH,
105
+ 'Maximum deep merge depth exceeded. You may be attempting to merge ' +
106
+ 'circular structures in an unsupported way.'
107
+ );
108
},
109
110
/**
135
- * Checks that a merge was not given a circular object or an object that had
136
- * too great of depth.
111
+ * Checks that the supplied merge strategy is valid.
112
*
138
- * @param {number} Level of recursion to validate against maximum.
113
+ * @param {string} Array merge strategy.
114
*/
115
checkArrayStrategy: function(strategy) {
141
- throwIf(
142
- strategy !== undefined && !(strategy in mergeHelpers.ArrayStrategies),
143
- ERRORS.MERGE_DEEP_NO_ARR_STRATEGY
116
+ invariant(
117
+ strategy === undefined || strategy in mergeHelpers.ArrayStrategies,
118
+ 'You must provide an array strategy to deep merge functions to ' +
119
+ 'instruct the deep merge how to resolve merging two arrays.'
120
);
121
},
122
@@ -154,9 +130,8 @@ var mergeHelpers = {
130
ArrayStrategies: keyMirror({
131
Clobber: true,
132
IndexByIndex: true
157
- }),
133
+ })
134
159
- ERRORS: ERRORS
135
};
136
137
module.exports = mergeHelpers;
src/utils/traverseAllChildren.js
+6
-23
@@ -21,22 +21,7 @@
21
var ReactComponent = require('ReactComponent');
22
var ReactTextComponent = require('ReactTextComponent');
23
24
-var throwIf = require('throwIf');
25
-
26
-/**
27
- * @polyFill Array.isArray
28
- */
29
-var DUPLICATE_KEY_ERROR = 'DUPLICATE_KEY_ERROR';
30
-var INVALID_CHILD = 'INVALID_CHILD';
31
-if (__DEV__) {
32
- INVALID_CHILD =
33
- 'You may not pass a child of that type to a React component. It ' +
34
- 'is a common mistake to try to pass a standard browser DOM element ' +
35
- 'as a child of a React component.';
36
- DUPLICATE_KEY_ERROR =
37
- 'You have two children with identical keys. Make sure that you set the ' +
38
- '"key" property to a unique value such as a row ID.';
39
-}
24
+var invariant = require('invariant');
25
26
/**
27
* TODO: Test that:
@@ -88,7 +73,11 @@ var traverseAllChildrenImpl =
73
subtreeCount = 1;
74
} else {
75
if (type === 'object') {
91
- throwIf(children && children.nodeType === 1, INVALID_CHILD);
76
+ invariant(
77
+ children || children.nodeType !== 1,
78
+ 'traverseAllChildren(...): Encountered an invalid child; DOM ' +
79
+ 'elements are not valid children of React components.'
80
+ );
81
for (var key in children) {
82
if (children.hasOwnProperty(key)) {
83
subtreeCount += traverseAllChildrenImpl(
@@ -135,10 +124,4 @@ function traverseAllChildren(children, callback, traverseContext) {
124
}
125
}
126
138
-/**
139
- * Export the error code for use in other walking/mapping code.
140
- */
141
-traverseAllChildren.DUPLICATE_KEY_ERROR = DUPLICATE_KEY_ERROR;
142
-
143
-
127
module.exports = traverseAllChildren;