react 0.10.0 → 0.11.0-rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/README.md +3 -0
  2. package/dist/JSXTransformer.js +13445 -0
  3. package/dist/react-with-addons.js +20226 -0
  4. package/dist/react-with-addons.min.js +22 -0
  5. package/dist/react.js +18434 -0
  6. package/dist/react.min.js +21 -0
  7. package/lib/BeforeInputEventPlugin.js +222 -0
  8. package/lib/CSSPropertyOperations.js +3 -3
  9. package/lib/{ReactMountReady.js → CallbackQueue.js} +32 -24
  10. package/lib/ChangeEventPlugin.js +1 -1
  11. package/lib/CompositionEventPlugin.js +5 -1
  12. package/lib/DOMChildrenOperations.js +21 -14
  13. package/lib/DOMProperty.js +45 -17
  14. package/lib/DOMPropertyOperations.js +22 -10
  15. package/lib/DefaultEventPluginOrder.js +1 -0
  16. package/lib/EventConstants.js +1 -0
  17. package/lib/EventListener.js +5 -2
  18. package/lib/EventPluginHub.js +0 -5
  19. package/lib/EventPluginRegistry.js +6 -4
  20. package/lib/EventPluginUtils.js +11 -1
  21. package/lib/ExecutionEnvironment.js +8 -2
  22. package/lib/{DefaultDOMPropertyConfig.js → HTMLDOMPropertyConfig.js} +38 -48
  23. package/lib/LinkedValueUtils.js +21 -22
  24. package/lib/LocalEventTrapMixin.js +52 -0
  25. package/lib/React.js +36 -3
  26. package/lib/ReactBrowserComponentMixin.js +4 -0
  27. package/lib/{ReactEventEmitter.js → ReactBrowserEventEmitter.js} +115 -94
  28. package/lib/ReactCSSTransitionGroup.js +2 -0
  29. package/lib/ReactCSSTransitionGroupChild.js +2 -5
  30. package/lib/ReactChildren.js +31 -10
  31. package/lib/ReactComponent.js +88 -237
  32. package/lib/ReactComponentBrowserEnvironment.js +3 -2
  33. package/lib/ReactComponentWithPureRenderMixin.js +54 -0
  34. package/lib/ReactCompositeComponent.js +213 -383
  35. package/lib/ReactDOM.js +20 -18
  36. package/lib/ReactDOMComponent.js +26 -24
  37. package/lib/ReactDOMForm.js +5 -13
  38. package/lib/ReactDOMIDOperations.js +2 -31
  39. package/lib/ReactDOMImg.js +5 -14
  40. package/lib/ReactDOMSelect.js +16 -15
  41. package/lib/ReactDOMSelection.js +35 -10
  42. package/lib/ReactDOMTextarea.js +2 -4
  43. package/lib/ReactDefaultBatchingStrategy.js +3 -3
  44. package/lib/ReactDefaultInjection.js +18 -15
  45. package/lib/ReactDefaultPerf.js +28 -11
  46. package/lib/ReactDefaultPerfAnalysis.js +4 -0
  47. package/lib/ReactDescriptor.js +243 -0
  48. package/lib/ReactDescriptorValidator.js +283 -0
  49. package/lib/ReactEmptyComponent.js +78 -0
  50. package/lib/ReactEventEmitterMixin.js +1 -3
  51. package/lib/ReactEventListener.js +189 -0
  52. package/lib/ReactInjection.js +4 -2
  53. package/lib/ReactLink.js +24 -0
  54. package/lib/ReactMount.js +51 -19
  55. package/lib/ReactMultiChild.js +9 -11
  56. package/lib/ReactPropTransferer.js +44 -29
  57. package/lib/ReactPropTypes.js +226 -242
  58. package/lib/ReactPutListenerQueue.js +2 -2
  59. package/lib/ReactReconcileTransaction.js +14 -14
  60. package/lib/ReactServerRendering.js +5 -5
  61. package/lib/ReactServerRenderingTransaction.js +4 -5
  62. package/lib/ReactTestUtils.js +39 -21
  63. package/lib/ReactTextComponent.js +8 -22
  64. package/lib/ReactTransitionChildMapping.js +2 -2
  65. package/lib/ReactTransitionEvents.js +19 -0
  66. package/lib/ReactTransitionGroup.js +9 -6
  67. package/lib/ReactUpdates.js +139 -22
  68. package/lib/ReactWithAddons.js +5 -2
  69. package/lib/SVGDOMPropertyConfig.js +97 -0
  70. package/lib/SimpleEventPlugin.js +7 -1
  71. package/lib/SyntheticInputEvent.js +52 -0
  72. package/lib/SyntheticKeyboardEvent.js +33 -4
  73. package/lib/SyntheticMouseEvent.js +3 -0
  74. package/lib/SyntheticTouchEvent.js +4 -1
  75. package/lib/SyntheticUIEvent.js +24 -2
  76. package/lib/Transaction.js +0 -32
  77. package/lib/cloneWithProps.js +3 -1
  78. package/lib/createFullPageComponent.js +1 -1
  79. package/lib/dangerousStyleValue.js +11 -5
  80. package/lib/escapeTextForBrowser.js +2 -3
  81. package/lib/flattenChildren.js +9 -7
  82. package/lib/getEventKey.js +35 -5
  83. package/lib/getEventModifierState.js +52 -0
  84. package/lib/getMarkupWrap.js +2 -0
  85. package/lib/getTextContentAccessor.js +1 -1
  86. package/lib/hyphenate.js +3 -0
  87. package/lib/hyphenateStyleName.js +46 -0
  88. package/lib/instantiateReactComponent.js +13 -21
  89. package/lib/invariant.js +17 -19
  90. package/lib/{objMap.js → mapObject.js} +8 -3
  91. package/lib/mergeHelpers.js +11 -0
  92. package/lib/mergeInto.js +3 -2
  93. package/lib/onlyChild.js +3 -3
  94. package/lib/performance.js +33 -0
  95. package/lib/performanceNow.js +5 -14
  96. package/lib/setInnerHTML.js +77 -0
  97. package/lib/shouldUpdateReactComponent.js +12 -29
  98. package/lib/toArray.js +1 -1
  99. package/lib/traverseAllChildren.js +7 -4
  100. package/lib/update.js +57 -45
  101. package/package.json +4 -3
  102. package/lib/ReactEventTopLevelCallback.js +0 -149
  103. package/lib/createObjectFrom.js +0 -61
  104. package/lib/objMapKeyVal.js +0 -47
@@ -19,7 +19,7 @@
19
19
 
20
20
  "use strict";
21
21
 
22
- var warning = require("./warning");
22
+ var invariant = require("./invariant");
23
23
 
24
24
  /**
25
25
  * Validate a `componentDescriptor`. This should be exposed publicly in a follow
@@ -30,10 +30,10 @@ var warning = require("./warning");
30
30
  */
31
31
  function isValidComponentDescriptor(descriptor) {
32
32
  return (
33
- typeof descriptor.constructor === 'function' &&
34
- typeof descriptor.constructor.prototype.construct === 'function' &&
35
- typeof descriptor.constructor.prototype.mountComponent === 'function' &&
36
- typeof descriptor.constructor.prototype.receiveComponent === 'function'
33
+ descriptor &&
34
+ typeof descriptor.type === 'function' &&
35
+ typeof descriptor.type.prototype.mountComponent === 'function' &&
36
+ typeof descriptor.type.prototype.receiveComponent === 'function'
37
37
  );
38
38
  }
39
39
 
@@ -47,24 +47,16 @@ function isValidComponentDescriptor(descriptor) {
47
47
  * @protected
48
48
  */
49
49
  function instantiateReactComponent(descriptor) {
50
- if ("production" !== process.env.NODE_ENV) {
51
- ("production" !== process.env.NODE_ENV ? warning(
50
+
51
+ // TODO: Make warning
52
+ // if (__DEV__) {
53
+ ("production" !== process.env.NODE_ENV ? invariant(
52
54
  isValidComponentDescriptor(descriptor),
53
55
  'Only React Components are valid for mounting.'
54
- ) : null);
55
- // We use the clone of a composite component instead of the original
56
- // instance. This allows us to warn you if you're are accessing the wrong
57
- // instance.
58
- var instance = descriptor.__realComponentInstance || descriptor;
59
- instance._descriptor = descriptor;
60
- return instance;
61
- }
62
- // In prod we don't clone, we simply use the same instance for unaffected
63
- // behavior. We have to keep the descriptor around for comparison later on.
64
- // This should ideally be accepted in the constructor of the instance but
65
- // since that is currently overloaded, we just manually attach it here.
66
- descriptor._descriptor = descriptor;
67
- return descriptor;
56
+ ) : invariant(isValidComponentDescriptor(descriptor)));
57
+ // }
58
+
59
+ return new descriptor.type(descriptor);
68
60
  }
69
61
 
70
62
  module.exports = instantiateReactComponent;
package/lib/invariant.js CHANGED
@@ -29,34 +29,32 @@
29
29
  * will remain to ensure logic does not differ in production.
30
30
  */
31
31
 
32
- var invariant = function(condition) {
33
- if (!condition) {
34
- var error = new Error(
35
- 'Minified exception occured; use the non-minified dev environment for ' +
36
- 'the full error message and additional helpful warnings.'
37
- );
38
- error.framesToPop = 1;
39
- throw error;
40
- }
41
- };
42
-
43
- if ("production" !== process.env.NODE_ENV) {
44
- invariant = function(condition, format, a, b, c, d, e, f) {
32
+ var invariant = function(condition, format, a, b, c, d, e, f) {
33
+ if ("production" !== process.env.NODE_ENV) {
45
34
  if (format === undefined) {
46
35
  throw new Error('invariant requires an error message argument');
47
36
  }
37
+ }
48
38
 
49
- if (!condition) {
39
+ if (!condition) {
40
+ var error;
41
+ if (format === undefined) {
42
+ error = new Error(
43
+ 'Minified exception occurred; use the non-minified dev environment ' +
44
+ 'for the full error message and additional helpful warnings.'
45
+ );
46
+ } else {
50
47
  var args = [a, b, c, d, e, f];
51
48
  var argIndex = 0;
52
- var error = new Error(
49
+ error = new Error(
53
50
  'Invariant Violation: ' +
54
51
  format.replace(/%s/g, function() { return args[argIndex++]; })
55
52
  );
56
- error.framesToPop = 1; // we don't care about invariant's own frame
57
- throw error;
58
53
  }
59
- };
60
- }
54
+
55
+ error.framesToPop = 1; // we don't care about invariant's own frame
56
+ throw error;
57
+ }
58
+ };
61
59
 
62
60
  module.exports = invariant;
@@ -13,7 +13,7 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  *
16
- * @providesModule objMap
16
+ * @providesModule mapObject
17
17
  */
18
18
 
19
19
  "use strict";
@@ -25,12 +25,17 @@
25
25
  *
26
26
  * func(value, key, iteration)
27
27
  *
28
+ * Grepable names:
29
+ *
30
+ * function objectMap()
31
+ * function objMap()
32
+ *
28
33
  * @param {?object} obj Object to map keys over
29
34
  * @param {function} func Invoked for each key/val pair.
30
35
  * @param {?*} context
31
36
  * @return {?object} Result of mapping or null if obj is falsey
32
37
  */
33
- function objMap(obj, func, context) {
38
+ function mapObject(obj, func, context) {
34
39
  if (!obj) {
35
40
  return null;
36
41
  }
@@ -44,4 +49,4 @@ function objMap(obj, func, context) {
44
49
  return ret;
45
50
  }
46
51
 
47
- module.exports = objMap;
52
+ module.exports = mapObject;
@@ -92,6 +92,17 @@ var mergeHelpers = {
92
92
  ) : invariant(!isTerminal(arg) && !Array.isArray(arg)));
93
93
  },
94
94
 
95
+ /**
96
+ * @param {*} arg
97
+ */
98
+ checkMergeIntoObjectArg: function(arg) {
99
+ ("production" !== process.env.NODE_ENV ? invariant(
100
+ (!isTerminal(arg) || typeof arg === 'function') && !Array.isArray(arg),
101
+ 'Tried to merge into an object, instead got %s.',
102
+ arg
103
+ ) : invariant((!isTerminal(arg) || typeof arg === 'function') && !Array.isArray(arg)));
104
+ },
105
+
95
106
  /**
96
107
  * Checks that a merge was not given a circular object or an object that had
97
108
  * too great of depth.
package/lib/mergeInto.js CHANGED
@@ -22,15 +22,16 @@
22
22
  var mergeHelpers = require("./mergeHelpers");
23
23
 
24
24
  var checkMergeObjectArg = mergeHelpers.checkMergeObjectArg;
25
+ var checkMergeIntoObjectArg = mergeHelpers.checkMergeIntoObjectArg;
25
26
 
26
27
  /**
27
28
  * Shallow merges two structures by mutating the first parameter.
28
29
  *
29
- * @param {object} one Object to be merged into.
30
+ * @param {object|function} one Object to be merged into.
30
31
  * @param {?object} two Optional object with properties to merge from.
31
32
  */
32
33
  function mergeInto(one, two) {
33
- checkMergeObjectArg(one);
34
+ checkMergeIntoObjectArg(one);
34
35
  if (two != null) {
35
36
  checkMergeObjectArg(two);
36
37
  for (var key in two) {
package/lib/onlyChild.js CHANGED
@@ -17,7 +17,7 @@
17
17
  */
18
18
  "use strict";
19
19
 
20
- var ReactComponent = require("./ReactComponent");
20
+ var ReactDescriptor = require("./ReactDescriptor");
21
21
 
22
22
  var invariant = require("./invariant");
23
23
 
@@ -34,9 +34,9 @@ var invariant = require("./invariant");
34
34
  */
35
35
  function onlyChild(children) {
36
36
  ("production" !== process.env.NODE_ENV ? invariant(
37
- ReactComponent.isValidComponent(children),
37
+ ReactDescriptor.isValidDescriptor(children),
38
38
  'onlyChild must be passed a children with exactly one child.'
39
- ) : invariant(ReactComponent.isValidComponent(children)));
39
+ ) : invariant(ReactDescriptor.isValidDescriptor(children)));
40
40
  return children;
41
41
  }
42
42
 
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Copyright 2013-2014 Facebook, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * @providesModule performance
17
+ * @typechecks
18
+ */
19
+
20
+ "use strict";
21
+
22
+ var ExecutionEnvironment = require("./ExecutionEnvironment");
23
+
24
+ var performance;
25
+
26
+ if (ExecutionEnvironment.canUseDOM) {
27
+ performance =
28
+ window.performance ||
29
+ window.msPerformance ||
30
+ window.webkitPerformance;
31
+ }
32
+
33
+ module.exports = performance || {};
@@ -14,25 +14,16 @@
14
14
  * limitations under the License.
15
15
  *
16
16
  * @providesModule performanceNow
17
- * @typechecks static-only
17
+ * @typechecks
18
18
  */
19
19
 
20
- "use strict";
21
-
22
- var ExecutionEnvironment = require("./ExecutionEnvironment");
20
+ var performance = require("./performance");
23
21
 
24
22
  /**
25
- * Detect if we can use window.performance.now() and gracefully
26
- * fallback to Date.now() if it doesn't exist.
27
- * We need to support Firefox < 15 for now due to Facebook's webdriver
28
- * infrastructure.
23
+ * Detect if we can use `window.performance.now()` and gracefully fallback to
24
+ * `Date.now()` if it doesn't exist. We need to support Firefox < 15 for now
25
+ * because of Facebook's testing infrastructure.
29
26
  */
30
- var performance = null;
31
-
32
- if (ExecutionEnvironment.canUseDOM) {
33
- performance = window.performance || window.webkitPerformance;
34
- }
35
-
36
27
  if (!performance || !performance.now) {
37
28
  performance = Date;
38
29
  }
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Copyright 2013-2014 Facebook, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * @providesModule setInnerHTML
17
+ */
18
+
19
+ "use strict";
20
+
21
+ var ExecutionEnvironment = require("./ExecutionEnvironment");
22
+
23
+ /**
24
+ * Set the innerHTML property of a node, ensuring that whitespace is preserved
25
+ * even in IE8.
26
+ *
27
+ * @param {DOMElement} node
28
+ * @param {string} html
29
+ * @internal
30
+ */
31
+ var setInnerHTML = function(node, html) {
32
+ node.innerHTML = html;
33
+ };
34
+
35
+ if (ExecutionEnvironment.canUseDOM) {
36
+ // IE8: When updating a just created node with innerHTML only leading
37
+ // whitespace is removed. When updating an existing node with innerHTML
38
+ // whitespace in root TextNodes is also collapsed.
39
+ // @see quirksmode.org/bugreports/archives/2004/11/innerhtml_and_t.html
40
+
41
+ // Feature detection; only IE8 is known to behave improperly like this.
42
+ var testElement = document.createElement('div');
43
+ testElement.innerHTML = ' ';
44
+ if (testElement.innerHTML === '') {
45
+ setInnerHTML = function(node, html) {
46
+ // Magic theory: IE8 supposedly differentiates between added and updated
47
+ // nodes when processing innerHTML, innerHTML on updated nodes suffers
48
+ // from worse whitespace behavior. Re-adding a node like this triggers
49
+ // the initial and more favorable whitespace behavior.
50
+ // TODO: What to do on a detached node?
51
+ if (node.parentNode) {
52
+ node.parentNode.replaceChild(node, node);
53
+ }
54
+
55
+ // We also implement a workaround for non-visible tags disappearing into
56
+ // thin air on IE8, this only happens if there is no visible text
57
+ // in-front of the non-visible tags. Piggyback on the whitespace fix
58
+ // and simply check if any non-visible tags appear in the source.
59
+ if (html.match(/^[ \r\n\t\f]/) ||
60
+ html[0] === '<' && (
61
+ html.indexOf('<noscript') !== -1 ||
62
+ html.indexOf('<script') !== -1 ||
63
+ html.indexOf('<style') !== -1 ||
64
+ html.indexOf('<meta') !== -1 ||
65
+ html.indexOf('<link') !== -1)) {
66
+ // Recover leading whitespace by temporarily prepending any character.
67
+ // \uFEFF has the potential advantage of being zero-width/invisible.
68
+ node.innerHTML = '\uFEFF' + html;
69
+ node.firstChild.deleteData(0, 1);
70
+ } else {
71
+ node.innerHTML = html;
72
+ }
73
+ };
74
+ }
75
+ }
76
+
77
+ module.exports = setInnerHTML;
@@ -20,40 +20,23 @@
20
20
  "use strict";
21
21
 
22
22
  /**
23
- * Given a `prevComponentInstance` and `nextComponent`, determines if
24
- * `prevComponentInstance` should be updated as opposed to being destroyed or
25
- * replaced by a new instance. The second argument is a descriptor. Future
26
- * versions of the reconciler should only compare descriptors to other
27
- * descriptors.
23
+ * Given a `prevDescriptor` and `nextDescriptor`, determines if the existing
24
+ * instance should be updated as opposed to being destroyed or replaced by a new
25
+ * instance. Both arguments are descriptors. This ensures that this logic can
26
+ * operate on stateless trees without any backing instance.
28
27
  *
29
- * @param {?object} prevComponentInstance
28
+ * @param {?object} prevDescriptor
30
29
  * @param {?object} nextDescriptor
31
- * @return {boolean} True if `prevComponentInstance` should be updated.
30
+ * @return {boolean} True if the existing instance should be updated.
32
31
  * @protected
33
32
  */
34
- function shouldUpdateReactComponent(prevComponentInstance, nextDescriptor) {
35
- // TODO: Remove warning after a release.
36
- if (prevComponentInstance && nextDescriptor &&
37
- prevComponentInstance.constructor === nextDescriptor.constructor && (
38
- (prevComponentInstance.props && prevComponentInstance.props.key) ===
33
+ function shouldUpdateReactComponent(prevDescriptor, nextDescriptor) {
34
+ if (prevDescriptor && nextDescriptor &&
35
+ prevDescriptor.type === nextDescriptor.type && (
36
+ (prevDescriptor.props && prevDescriptor.props.key) ===
39
37
  (nextDescriptor.props && nextDescriptor.props.key)
40
- )) {
41
- if (prevComponentInstance._owner === nextDescriptor._owner) {
42
- return true;
43
- } else {
44
- if ("production" !== process.env.NODE_ENV) {
45
- if (prevComponentInstance.state) {
46
- console.warn(
47
- 'A recent change to React has been found to impact your code. ' +
48
- 'A mounted component will now be unmounted and replaced by a ' +
49
- 'component (of the same class) if their owners are different. ' +
50
- 'Previously, ownership was not considered when updating.',
51
- prevComponentInstance,
52
- nextDescriptor
53
- );
54
- }
55
- }
56
- }
38
+ ) && prevDescriptor._owner === nextDescriptor._owner) {
39
+ return true;
57
40
  }
58
41
  return false;
59
42
  }
package/lib/toArray.js CHANGED
@@ -25,7 +25,7 @@ var invariant = require("./invariant");
25
25
  * This API assumes the caller knows the contents of the data type. For less
26
26
  * well defined inputs use createArrayFrom.
27
27
  *
28
- * @param {object|function} obj
28
+ * @param {object|function|filelist} obj
29
29
  * @return {array}
30
30
  */
31
31
  function toArray(obj) {
@@ -153,11 +153,11 @@ var traverseAllChildrenImpl =
153
153
  }
154
154
  }
155
155
  } else if (type === 'string') {
156
- var normalizedText = new ReactTextComponent(children);
156
+ var normalizedText = ReactTextComponent(children);
157
157
  callback(traverseContext, normalizedText, storageName, indexSoFar);
158
158
  subtreeCount += 1;
159
159
  } else if (type === 'number') {
160
- var normalizedNumber = new ReactTextComponent('' + children);
160
+ var normalizedNumber = ReactTextComponent('' + children);
161
161
  callback(traverseContext, normalizedNumber, storageName, indexSoFar);
162
162
  subtreeCount += 1;
163
163
  }
@@ -180,11 +180,14 @@ var traverseAllChildrenImpl =
180
180
  * @param {?*} children Children tree object.
181
181
  * @param {!function} callback To invoke upon traversing each child.
182
182
  * @param {?*} traverseContext Context for traversal.
183
+ * @return {!number} The number of children in this subtree.
183
184
  */
184
185
  function traverseAllChildren(children, callback, traverseContext) {
185
- if (children !== null && children !== undefined) {
186
- traverseAllChildrenImpl(children, '', 0, callback, traverseContext);
186
+ if (children == null) {
187
+ return 0;
187
188
  }
189
+
190
+ return traverseAllChildrenImpl(children, '', 0, callback, traverseContext);
188
191
  }
189
192
 
190
193
  module.exports = traverseAllChildren;
package/lib/update.js CHANGED
@@ -32,39 +32,41 @@ function shallowCopy(x) {
32
32
  }
33
33
  }
34
34
 
35
- var DIRECTIVE_PUSH = keyOf({$push: null});
36
- var DIRECTIVE_UNSHIFT = keyOf({$unshift: null});
37
- var DIRECTIVE_SPLICE = keyOf({$splice: null});
38
- var DIRECTIVE_SET = keyOf({$set: null});
39
- var DIRECTIVE_MERGE = keyOf({$merge: null});
40
-
41
- var ALL_DIRECTIVES_LIST = [
42
- DIRECTIVE_PUSH,
43
- DIRECTIVE_UNSHIFT,
44
- DIRECTIVE_SPLICE,
45
- DIRECTIVE_SET,
46
- DIRECTIVE_MERGE
35
+ var COMMAND_PUSH = keyOf({$push: null});
36
+ var COMMAND_UNSHIFT = keyOf({$unshift: null});
37
+ var COMMAND_SPLICE = keyOf({$splice: null});
38
+ var COMMAND_SET = keyOf({$set: null});
39
+ var COMMAND_MERGE = keyOf({$merge: null});
40
+ var COMMAND_APPLY = keyOf({$apply: null});
41
+
42
+ var ALL_COMMANDS_LIST = [
43
+ COMMAND_PUSH,
44
+ COMMAND_UNSHIFT,
45
+ COMMAND_SPLICE,
46
+ COMMAND_SET,
47
+ COMMAND_MERGE,
48
+ COMMAND_APPLY
47
49
  ];
48
50
 
49
- var ALL_DIRECTIVES_SET = {};
51
+ var ALL_COMMANDS_SET = {};
50
52
 
51
- ALL_DIRECTIVES_LIST.forEach(function(directive) {
52
- ALL_DIRECTIVES_SET[directive] = true;
53
+ ALL_COMMANDS_LIST.forEach(function(command) {
54
+ ALL_COMMANDS_SET[command] = true;
53
55
  });
54
56
 
55
- function invariantArrayCase(value, spec, directive) {
57
+ function invariantArrayCase(value, spec, command) {
56
58
  ("production" !== process.env.NODE_ENV ? invariant(
57
59
  Array.isArray(value),
58
60
  'update(): expected target of %s to be an array; got %s.',
59
- directive,
61
+ command,
60
62
  value
61
63
  ) : invariant(Array.isArray(value)));
62
- var specValue = spec[directive];
64
+ var specValue = spec[command];
63
65
  ("production" !== process.env.NODE_ENV ? invariant(
64
66
  Array.isArray(specValue),
65
67
  'update(): expected spec of %s to be an array; got %s. ' +
66
68
  'Did you forget to wrap your parameter in an array?',
67
- directive,
69
+ command,
68
70
  specValue
69
71
  ) : invariant(Array.isArray(specValue)));
70
72
  }
@@ -74,81 +76,91 @@ function update(value, spec) {
74
76
  typeof spec === 'object',
75
77
  'update(): You provided a key path to update() that did not contain one ' +
76
78
  'of %s. Did you forget to include {%s: ...}?',
77
- ALL_DIRECTIVES_LIST.join(', '),
78
- DIRECTIVE_SET
79
+ ALL_COMMANDS_LIST.join(', '),
80
+ COMMAND_SET
79
81
  ) : invariant(typeof spec === 'object'));
80
82
 
81
- if (spec.hasOwnProperty(DIRECTIVE_SET)) {
83
+ if (spec.hasOwnProperty(COMMAND_SET)) {
82
84
  ("production" !== process.env.NODE_ENV ? invariant(
83
85
  Object.keys(spec).length === 1,
84
86
  'Cannot have more than one key in an object with %s',
85
- DIRECTIVE_SET
87
+ COMMAND_SET
86
88
  ) : invariant(Object.keys(spec).length === 1));
87
89
 
88
- return spec[DIRECTIVE_SET];
90
+ return spec[COMMAND_SET];
89
91
  }
90
92
 
91
93
  var nextValue = shallowCopy(value);
92
94
 
93
- if (spec.hasOwnProperty(DIRECTIVE_MERGE)) {
94
- var mergeObj = spec[DIRECTIVE_MERGE];
95
+ if (spec.hasOwnProperty(COMMAND_MERGE)) {
96
+ var mergeObj = spec[COMMAND_MERGE];
95
97
  ("production" !== process.env.NODE_ENV ? invariant(
96
98
  mergeObj && typeof mergeObj === 'object',
97
99
  'update(): %s expects a spec of type \'object\'; got %s',
98
- DIRECTIVE_MERGE,
100
+ COMMAND_MERGE,
99
101
  mergeObj
100
102
  ) : invariant(mergeObj && typeof mergeObj === 'object'));
101
103
  ("production" !== process.env.NODE_ENV ? invariant(
102
104
  nextValue && typeof nextValue === 'object',
103
105
  'update(): %s expects a target of type \'object\'; got %s',
104
- DIRECTIVE_MERGE,
106
+ COMMAND_MERGE,
105
107
  nextValue
106
108
  ) : invariant(nextValue && typeof nextValue === 'object'));
107
- copyProperties(nextValue, spec[DIRECTIVE_MERGE]);
109
+ copyProperties(nextValue, spec[COMMAND_MERGE]);
108
110
  }
109
111
 
110
- if (spec.hasOwnProperty(DIRECTIVE_PUSH)) {
111
- invariantArrayCase(value, spec, DIRECTIVE_PUSH);
112
- spec[DIRECTIVE_PUSH].forEach(function(item) {
112
+ if (spec.hasOwnProperty(COMMAND_PUSH)) {
113
+ invariantArrayCase(value, spec, COMMAND_PUSH);
114
+ spec[COMMAND_PUSH].forEach(function(item) {
113
115
  nextValue.push(item);
114
116
  });
115
117
  }
116
118
 
117
- if (spec.hasOwnProperty(DIRECTIVE_UNSHIFT)) {
118
- invariantArrayCase(value, spec, DIRECTIVE_UNSHIFT);
119
- spec[DIRECTIVE_UNSHIFT].forEach(function(item) {
119
+ if (spec.hasOwnProperty(COMMAND_UNSHIFT)) {
120
+ invariantArrayCase(value, spec, COMMAND_UNSHIFT);
121
+ spec[COMMAND_UNSHIFT].forEach(function(item) {
120
122
  nextValue.unshift(item);
121
123
  });
122
124
  }
123
125
 
124
- if (spec.hasOwnProperty(DIRECTIVE_SPLICE)) {
126
+ if (spec.hasOwnProperty(COMMAND_SPLICE)) {
125
127
  ("production" !== process.env.NODE_ENV ? invariant(
126
128
  Array.isArray(value),
127
129
  'Expected %s target to be an array; got %s',
128
- DIRECTIVE_SPLICE,
130
+ COMMAND_SPLICE,
129
131
  value
130
132
  ) : invariant(Array.isArray(value)));
131
133
  ("production" !== process.env.NODE_ENV ? invariant(
132
- Array.isArray(spec[DIRECTIVE_SPLICE]),
134
+ Array.isArray(spec[COMMAND_SPLICE]),
133
135
  'update(): expected spec of %s to be an array of arrays; got %s. ' +
134
136
  'Did you forget to wrap your parameters in an array?',
135
- DIRECTIVE_SPLICE,
136
- spec[DIRECTIVE_SPLICE]
137
- ) : invariant(Array.isArray(spec[DIRECTIVE_SPLICE])));
138
- spec[DIRECTIVE_SPLICE].forEach(function(args) {
137
+ COMMAND_SPLICE,
138
+ spec[COMMAND_SPLICE]
139
+ ) : invariant(Array.isArray(spec[COMMAND_SPLICE])));
140
+ spec[COMMAND_SPLICE].forEach(function(args) {
139
141
  ("production" !== process.env.NODE_ENV ? invariant(
140
142
  Array.isArray(args),
141
143
  'update(): expected spec of %s to be an array of arrays; got %s. ' +
142
144
  'Did you forget to wrap your parameters in an array?',
143
- DIRECTIVE_SPLICE,
144
- spec[DIRECTIVE_SPLICE]
145
+ COMMAND_SPLICE,
146
+ spec[COMMAND_SPLICE]
145
147
  ) : invariant(Array.isArray(args)));
146
148
  nextValue.splice.apply(nextValue, args);
147
149
  });
148
150
  }
149
151
 
152
+ if (spec.hasOwnProperty(COMMAND_APPLY)) {
153
+ ("production" !== process.env.NODE_ENV ? invariant(
154
+ typeof spec[COMMAND_APPLY] === 'function',
155
+ 'update(): expected spec of %s to be a function; got %s.',
156
+ COMMAND_APPLY,
157
+ spec[COMMAND_APPLY]
158
+ ) : invariant(typeof spec[COMMAND_APPLY] === 'function'));
159
+ nextValue = spec[COMMAND_APPLY](nextValue);
160
+ }
161
+
150
162
  for (var k in spec) {
151
- if (!ALL_DIRECTIVES_SET[k]) {
163
+ if (!(ALL_COMMANDS_SET.hasOwnProperty(k) && ALL_COMMANDS_SET[k])) {
152
164
  nextValue[k] = update(value[k], spec[k]);
153
165
  }
154
166
  }