react 0.14.0-beta3 → 0.14.2

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 (89) hide show
  1. package/README.md +4 -4
  2. package/addons.js +2 -0
  3. package/dist/react-with-addons.js +1941 -1364
  4. package/dist/react-with-addons.min.js +6 -6
  5. package/dist/react.js +1704 -1242
  6. package/dist/react.min.js +6 -6
  7. package/lib/CSSProperty.js +15 -3
  8. package/lib/CSSPropertyOperations.js +15 -2
  9. package/lib/ChangeEventPlugin.js +5 -2
  10. package/lib/DOMChildrenOperations.js +12 -1
  11. package/lib/DOMPropertyOperations.js +14 -1
  12. package/lib/Danger.js +9 -4
  13. package/lib/EnterLeaveEventPlugin.js +13 -5
  14. package/lib/EventConstants.js +1 -1
  15. package/lib/EventPluginHub.js +18 -10
  16. package/lib/EventPluginUtils.js +23 -27
  17. package/lib/EventPropagators.js +1 -1
  18. package/lib/FallbackCompositionState.js +6 -0
  19. package/lib/HTMLDOMPropertyConfig.js +26 -2
  20. package/lib/PooledClass.js +1 -3
  21. package/lib/React.js +14 -3
  22. package/lib/ReactBrowserComponentMixin.js +1 -1
  23. package/lib/ReactBrowserEventEmitter.js +9 -3
  24. package/lib/ReactCSSTransitionGroup.js +33 -18
  25. package/lib/ReactCSSTransitionGroupChild.js +42 -25
  26. package/lib/ReactChildReconciler.js +3 -5
  27. package/lib/ReactChildren.js +70 -30
  28. package/lib/ReactClass.js +6 -6
  29. package/lib/ReactComponent.js +7 -6
  30. package/lib/ReactCompositeComponent.js +58 -7
  31. package/lib/ReactDOM.js +7 -5
  32. package/lib/ReactDOMComponent.js +146 -46
  33. package/lib/ReactDOMFeatureFlags.js +18 -0
  34. package/lib/ReactDOMIDOperations.js +1 -60
  35. package/lib/ReactDOMInput.js +10 -1
  36. package/lib/ReactDOMSelect.js +1 -1
  37. package/lib/ReactDOMSelection.js +16 -0
  38. package/lib/ReactDOMServer.js +3 -1
  39. package/lib/ReactDOMTextComponent.js +23 -10
  40. package/lib/ReactDOMTextarea.js +3 -1
  41. package/lib/ReactDefaultInjection.js +0 -2
  42. package/lib/ReactDefaultPerf.js +10 -4
  43. package/lib/ReactDefaultPerfAnalysis.js +7 -3
  44. package/lib/ReactElement.js +72 -35
  45. package/lib/ReactElementValidator.js +31 -75
  46. package/lib/ReactEmptyComponent.js +25 -61
  47. package/lib/ReactEmptyComponentRegistry.js +48 -0
  48. package/lib/ReactErrorUtils.js +56 -9
  49. package/lib/ReactEventEmitterMixin.js +1 -1
  50. package/lib/ReactEventListener.js +16 -9
  51. package/lib/ReactFragment.js +25 -116
  52. package/lib/ReactInjection.js +0 -2
  53. package/lib/ReactIsomorphic.js +4 -0
  54. package/lib/ReactLink.js +1 -1
  55. package/lib/ReactMount.js +127 -41
  56. package/lib/ReactMultiChild.js +37 -4
  57. package/lib/ReactOwner.js +2 -2
  58. package/lib/ReactPropTransferer.js +1 -1
  59. package/lib/ReactPropTypes.js +11 -8
  60. package/lib/ReactReconcileTransaction.js +4 -2
  61. package/lib/ReactReconciler.js +16 -17
  62. package/lib/ReactRef.js +13 -1
  63. package/lib/ReactServerRenderingTransaction.js +1 -0
  64. package/lib/ReactTestUtils.js +27 -15
  65. package/lib/ReactTransitionChildMapping.js +3 -6
  66. package/lib/ReactUpdateQueue.js +4 -4
  67. package/lib/ReactUpdates.js +1 -1
  68. package/lib/ReactVersion.js +14 -0
  69. package/lib/ReactWithAddons.js +10 -1
  70. package/lib/ResponderEventPlugin.js +1 -1
  71. package/lib/SelectEventPlugin.js +11 -1
  72. package/lib/SimpleEventPlugin.js +2 -23
  73. package/lib/SyntheticEvent.js +15 -1
  74. package/lib/Transaction.js +1 -1
  75. package/lib/canDefineProperty.js +24 -0
  76. package/lib/createHierarchyRenderer.js +1 -1
  77. package/lib/deprecated.js +3 -2
  78. package/lib/findDOMNode.js +1 -1
  79. package/lib/getTestDocument.js +4 -11
  80. package/lib/instantiateReactComponent.js +3 -5
  81. package/lib/reactComponentExpect.js +6 -0
  82. package/lib/shouldUpdateReactComponent.js +12 -8
  83. package/lib/sliceChildren.js +3 -20
  84. package/lib/traverseAllChildren.js +15 -9
  85. package/package.json +2 -2
  86. package/react.js +1 -51
  87. package/dist/JSXTransformer.js +0 -17949
  88. package/lib/joinClasses.js +0 -39
  89. package/lib/memoizeStringOnly.js +0 -31
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Copyright 2013-2015, Facebook, Inc.
3
+ * All rights reserved.
4
+ *
5
+ * This source code is licensed under the BSD-style license found in the
6
+ * LICENSE file in the root directory of this source tree. An additional grant
7
+ * of patent rights can be found in the PATENTS file in the same directory.
8
+ *
9
+ * @providesModule ReactDOMFeatureFlags
10
+ */
11
+
12
+ 'use strict';
13
+
14
+ var ReactDOMFeatureFlags = {
15
+ useCreateElement: false
16
+ };
17
+
18
+ module.exports = ReactDOMFeatureFlags;
@@ -12,7 +12,6 @@
12
12
 
13
13
  'use strict';
14
14
 
15
- var CSSPropertyOperations = require('./CSSPropertyOperations');
16
15
  var DOMChildrenOperations = require('./DOMChildrenOperations');
17
16
  var DOMPropertyOperations = require('./DOMPropertyOperations');
18
17
  var ReactMount = require('./ReactMount');
@@ -32,8 +31,7 @@ var INVALID_PROPERTY_ERRORS = {
32
31
  };
33
32
 
34
33
  /**
35
- * Operations used to process updates to DOM nodes. This is made injectable via
36
- * `ReactDOMComponent.BackendIDOperations`.
34
+ * Operations used to process updates to DOM nodes.
37
35
  */
38
36
  var ReactDOMIDOperations = {
39
37
 
@@ -60,59 +58,6 @@ var ReactDOMIDOperations = {
60
58
  }
61
59
  },
62
60
 
63
- /**
64
- * Updates a DOM node with new property values.
65
- *
66
- * @param {string} id ID of the node to update.
67
- * @param {string} name A valid property name.
68
- * @param {*} value New value of the property.
69
- * @internal
70
- */
71
- updateAttributeByID: function (id, name, value) {
72
- var node = ReactMount.getNode(id);
73
- !!INVALID_PROPERTY_ERRORS.hasOwnProperty(name) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'updatePropertyByID(...): %s', INVALID_PROPERTY_ERRORS[name]) : invariant(false) : undefined;
74
- DOMPropertyOperations.setValueForAttribute(node, name, value);
75
- },
76
-
77
- /**
78
- * Updates a DOM node to remove a property. This should only be used to remove
79
- * DOM properties in `DOMProperty`.
80
- *
81
- * @param {string} id ID of the node to update.
82
- * @param {string} name A property name to remove, see `DOMProperty`.
83
- * @internal
84
- */
85
- deletePropertyByID: function (id, name, value) {
86
- var node = ReactMount.getNode(id);
87
- !!INVALID_PROPERTY_ERRORS.hasOwnProperty(name) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'updatePropertyByID(...): %s', INVALID_PROPERTY_ERRORS[name]) : invariant(false) : undefined;
88
- DOMPropertyOperations.deleteValueForProperty(node, name, value);
89
- },
90
-
91
- /**
92
- * Updates a DOM node with new style values. If a value is specified as '',
93
- * the corresponding style property will be unset.
94
- *
95
- * @param {string} id ID of the node to update.
96
- * @param {object} styles Mapping from styles to values.
97
- * @internal
98
- */
99
- updateStylesByID: function (id, styles) {
100
- var node = ReactMount.getNode(id);
101
- CSSPropertyOperations.setValueForStyles(node, styles);
102
- },
103
-
104
- /**
105
- * Updates a DOM node's text content set by `props.content`.
106
- *
107
- * @param {string} id ID of the node to update.
108
- * @param {string} content Text content.
109
- * @internal
110
- */
111
- updateTextContentByID: function (id, content) {
112
- var node = ReactMount.getNode(id);
113
- DOMChildrenOperations.updateTextContent(node, content);
114
- },
115
-
116
61
  /**
117
62
  * Replaces a DOM node that exists in the document with markup.
118
63
  *
@@ -142,10 +87,6 @@ var ReactDOMIDOperations = {
142
87
  };
143
88
 
144
89
  ReactPerf.measureMethods(ReactDOMIDOperations, 'ReactDOMIDOperations', {
145
- updatePropertyByID: 'updatePropertyByID',
146
- deletePropertyByID: 'deletePropertyByID',
147
- updateStylesByID: 'updateStylesByID',
148
- updateTextContentByID: 'updateTextContentByID',
149
90
  dangerouslyReplaceNodeWithMarkupByID: 'dangerouslyReplaceNodeWithMarkupByID',
150
91
  dangerouslyProcessChildrenUpdates: 'dangerouslyProcessChildrenUpdates'
151
92
  });
@@ -61,7 +61,9 @@ var ReactDOMInput = {
61
61
  },
62
62
 
63
63
  mountWrapper: function (inst, props) {
64
- LinkedValueUtils.checkPropTypes('input', props, inst._currentElement._owner);
64
+ if (process.env.NODE_ENV !== 'production') {
65
+ LinkedValueUtils.checkPropTypes('input', props, inst._currentElement._owner);
66
+ }
65
67
 
66
68
  var defaultValue = props.defaultValue;
67
69
  inst._wrapperState = {
@@ -69,7 +71,10 @@ var ReactDOMInput = {
69
71
  initialValue: defaultValue != null ? defaultValue : null,
70
72
  onChange: _handleChange.bind(inst)
71
73
  };
74
+ },
72
75
 
76
+ mountReadyWrapper: function (inst) {
77
+ // Can't be in mountWrapper or else server rendering leaks.
73
78
  instancesByReactID[inst._rootNodeID] = inst;
74
79
  },
75
80
 
@@ -127,6 +132,10 @@ function _handleChange(event) {
127
132
  if (otherNode === rootNode || otherNode.form !== rootNode.form) {
128
133
  continue;
129
134
  }
135
+ // This will throw if radio buttons rendered by different copies of React
136
+ // and the same name are rendered into the same form (same as #1939).
137
+ // That's probably okay; we don't support it just as we don't support
138
+ // mixing React with non-React.
130
139
  var otherID = ReactMount.getID(otherNode);
131
140
  !otherID ? process.env.NODE_ENV !== 'production' ? invariant(false, 'ReactDOMInput: Mixing React and non-React radio inputs with the ' + 'same `name` is not supported.') : invariant(false) : undefined;
132
141
  var otherInstance = instancesByReactID[otherID];
@@ -21,7 +21,7 @@ var warning = require('fbjs/lib/warning');
21
21
  var valueContextKey = '__ReactDOMSelect_value$' + Math.random().toString(36).slice(2);
22
22
 
23
23
  function updateOptionsIfPendingUpdateAndMounted() {
24
- if (this._wrapperState.pendingUpdate && this._rootNodeID) {
24
+ if (this._rootNodeID && this._wrapperState.pendingUpdate) {
25
25
  this._wrapperState.pendingUpdate = false;
26
26
 
27
27
  var props = this._currentElement.props;
@@ -76,6 +76,22 @@ function getModernOffsets(node) {
76
76
 
77
77
  var currentRange = selection.getRangeAt(0);
78
78
 
79
+ // In Firefox, range.startContainer and range.endContainer can be "anonymous
80
+ // divs", e.g. the up/down buttons on an <input type="number">. Anonymous
81
+ // divs do not seem to expose properties, triggering a "Permission denied
82
+ // error" if any of its properties are accessed. The only seemingly possible
83
+ // way to avoid erroring is to access a property that typically works for
84
+ // non-anonymous divs and catch any error that may otherwise arise. See
85
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=208427
86
+ try {
87
+ /* eslint-disable no-unused-expressions */
88
+ currentRange.startContainer.nodeType;
89
+ currentRange.endContainer.nodeType;
90
+ /* eslint-enable no-unused-expressions */
91
+ } catch (e) {
92
+ return null;
93
+ }
94
+
79
95
  // If the node and offset values are the same, the selection is collapsed.
80
96
  // `Selection.isCollapsed` is available natively, but IE sometimes gets
81
97
  // this value wrong.
@@ -13,12 +13,14 @@
13
13
 
14
14
  var ReactDefaultInjection = require('./ReactDefaultInjection');
15
15
  var ReactServerRendering = require('./ReactServerRendering');
16
+ var ReactVersion = require('./ReactVersion');
16
17
 
17
18
  ReactDefaultInjection.inject();
18
19
 
19
20
  var ReactDOMServer = {
20
21
  renderToString: ReactServerRendering.renderToString,
21
- renderToStaticMarkup: ReactServerRendering.renderToStaticMarkup
22
+ renderToStaticMarkup: ReactServerRendering.renderToStaticMarkup,
23
+ version: ReactVersion
22
24
  };
23
25
 
24
26
  module.exports = ReactDOMServer;
@@ -12,12 +12,14 @@
12
12
 
13
13
  'use strict';
14
14
 
15
+ var DOMChildrenOperations = require('./DOMChildrenOperations');
15
16
  var DOMPropertyOperations = require('./DOMPropertyOperations');
16
17
  var ReactComponentBrowserEnvironment = require('./ReactComponentBrowserEnvironment');
17
- var ReactDOMComponent = require('./ReactDOMComponent');
18
+ var ReactMount = require('./ReactMount');
18
19
 
19
20
  var assign = require('./Object.assign');
20
21
  var escapeTextContentForBrowser = require('./escapeTextContentForBrowser');
22
+ var setTextContent = require('./setTextContent');
21
23
  var validateDOMNesting = require('./validateDOMNesting');
22
24
 
23
25
  /**
@@ -72,16 +74,26 @@ assign(ReactDOMTextComponent.prototype, {
72
74
  }
73
75
 
74
76
  this._rootNodeID = rootID;
75
- var escapedText = escapeTextContentForBrowser(this._stringText);
77
+ if (transaction.useCreateElement) {
78
+ var ownerDocument = context[ReactMount.ownerDocumentContextKey];
79
+ var el = ownerDocument.createElement('span');
80
+ DOMPropertyOperations.setAttributeForID(el, rootID);
81
+ // Populate node cache
82
+ ReactMount.getID(el);
83
+ setTextContent(el, this._stringText);
84
+ return el;
85
+ } else {
86
+ var escapedText = escapeTextContentForBrowser(this._stringText);
76
87
 
77
- if (transaction.renderToStaticMarkup) {
78
- // Normally we'd wrap this in a `span` for the reasons stated above, but
79
- // since this is a situation where React won't take over (static pages),
80
- // we can simply return the text as it is.
81
- return escapedText;
82
- }
88
+ if (transaction.renderToStaticMarkup) {
89
+ // Normally we'd wrap this in a `span` for the reasons stated above, but
90
+ // since this is a situation where React won't take over (static pages),
91
+ // we can simply return the text as it is.
92
+ return escapedText;
93
+ }
83
94
 
84
- return '<span ' + DOMPropertyOperations.createMarkupForID(rootID) + '>' + escapedText + '</span>';
95
+ return '<span ' + DOMPropertyOperations.createMarkupForID(rootID) + '>' + escapedText + '</span>';
96
+ }
85
97
  },
86
98
 
87
99
  /**
@@ -100,7 +112,8 @@ assign(ReactDOMTextComponent.prototype, {
100
112
  // and/or updateComponent to do the actual update for consistency with
101
113
  // other component types?
102
114
  this._stringText = nextStringText;
103
- ReactDOMComponent.BackendIDOperations.updateTextContentByID(this._rootNodeID, nextStringText);
115
+ var node = ReactMount.getNode(this._rootNodeID);
116
+ DOMChildrenOperations.updateTextContent(node, nextStringText);
104
117
  }
105
118
  }
106
119
  },
@@ -58,7 +58,9 @@ var ReactDOMTextarea = {
58
58
  },
59
59
 
60
60
  mountWrapper: function (inst, props) {
61
- LinkedValueUtils.checkPropTypes('textarea', props, inst._currentElement._owner);
61
+ if (process.env.NODE_ENV !== 'production') {
62
+ LinkedValueUtils.checkPropTypes('textarea', props, inst._currentElement._owner);
63
+ }
62
64
 
63
65
  var defaultValue = props.defaultValue;
64
66
  // TODO (yungsters): Remove support for children content in <textarea>.
@@ -22,7 +22,6 @@ var ReactBrowserComponentMixin = require('./ReactBrowserComponentMixin');
22
22
  var ReactComponentBrowserEnvironment = require('./ReactComponentBrowserEnvironment');
23
23
  var ReactDefaultBatchingStrategy = require('./ReactDefaultBatchingStrategy');
24
24
  var ReactDOMComponent = require('./ReactDOMComponent');
25
- var ReactDOMIDOperations = require('./ReactDOMIDOperations');
26
25
  var ReactDOMTextComponent = require('./ReactDOMTextComponent');
27
26
  var ReactEventListener = require('./ReactEventListener');
28
27
  var ReactInjection = require('./ReactInjection');
@@ -83,7 +82,6 @@ function inject() {
83
82
  ReactInjection.RootIndex.injectCreateReactRootIndex(ExecutionEnvironment.canUseDOM ? ClientReactRootIndex.createReactRootIndex : ServerReactRootIndex.createReactRootIndex);
84
83
 
85
84
  ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment);
86
- ReactInjection.DOMComponent.injectIDOperations(ReactDOMIDOperations);
87
85
 
88
86
  if (process.env.NODE_ENV !== 'production') {
89
87
  var url = ExecutionEnvironment.canUseDOM && window.location.href || '';
@@ -143,13 +143,14 @@ var ReactDefaultPerf = {
143
143
  counts: {},
144
144
  writes: {},
145
145
  displayNames: {},
146
- totalTime: 0
146
+ totalTime: 0,
147
+ created: {}
147
148
  });
148
149
  start = performanceNow();
149
150
  rv = func.apply(this, args);
150
151
  ReactDefaultPerf._allMeasurements[ReactDefaultPerf._allMeasurements.length - 1].totalTime = performanceNow() - start;
151
152
  return rv;
152
- } else if (fnName === '_mountImageIntoNode' || moduleName === 'ReactDOMIDOperations') {
153
+ } else if (fnName === '_mountImageIntoNode' || moduleName === 'ReactBrowserEventEmitter' || moduleName === 'ReactDOMIDOperations' || moduleName === 'CSSPropertyOperations' || moduleName === 'DOMChildrenOperations' || moduleName === 'DOMPropertyOperations') {
153
154
  start = performanceNow();
154
155
  rv = func.apply(this, args);
155
156
  totalTime = performanceNow() - start;
@@ -177,13 +178,17 @@ var ReactDefaultPerf = {
177
178
  });
178
179
  } else {
179
180
  // basic format
180
- ReactDefaultPerf._recordWrite(args[0], fnName, totalTime, Array.prototype.slice.call(args, 1));
181
+ var id = args[0];
182
+ if (typeof id === 'object') {
183
+ id = ReactMount.getID(args[0]);
184
+ }
185
+ ReactDefaultPerf._recordWrite(id, fnName, totalTime, Array.prototype.slice.call(args, 1));
181
186
  }
182
187
  return rv;
183
188
  } else if (moduleName === 'ReactCompositeComponent' && (fnName === 'mountComponent' || fnName === 'updateComponent' || // TODO: receiveComponent()?
184
189
  fnName === '_renderValidatedComponent')) {
185
190
 
186
- if (typeof this._currentElement.type === 'string') {
191
+ if (this._currentElement.type === ReactMount.TopLevelWrapper) {
187
192
  return func.apply(this, args);
188
193
  }
189
194
 
@@ -197,6 +202,7 @@ var ReactDefaultPerf = {
197
202
  if (isRender) {
198
203
  addValue(entry.counts, rootNodeID, 1);
199
204
  } else if (isMount) {
205
+ entry.created[rootNodeID] = true;
200
206
  mountStack.push(0);
201
207
  }
202
208
 
@@ -22,9 +22,9 @@ var DOM_OPERATION_TYPES = {
22
22
  REMOVE_NODE: 'remove',
23
23
  SET_MARKUP: 'set innerHTML',
24
24
  TEXT_CONTENT: 'set textContent',
25
- 'updatePropertyByID': 'update attribute',
26
- 'deletePropertyByID': 'delete attribute',
27
- 'updateStylesByID': 'update styles',
25
+ 'setValueForProperty': 'update attribute',
26
+ 'setValueForAttribute': 'update attribute',
27
+ 'deleteValueForProperty': 'remove attribute',
28
28
  'dangerouslyReplaceNodeWithMarkupByID': 'replace'
29
29
  };
30
30
 
@@ -178,6 +178,10 @@ function getUnchangedComponents(measurement) {
178
178
  break;
179
179
  }
180
180
  }
181
+ // check if component newly created
182
+ if (measurement.created[id]) {
183
+ isDirty = true;
184
+ }
181
185
  if (!isDirty && measurement.counts[id] > 0) {
182
186
  cleanComponents[id] = true;
183
187
  }
@@ -14,10 +14,17 @@
14
14
  var ReactCurrentOwner = require('./ReactCurrentOwner');
15
15
 
16
16
  var assign = require('./Object.assign');
17
+ var canDefineProperty = require('./canDefineProperty');
18
+
19
+ // The Symbol used to tag the ReactElement type. If there is no native Symbol
20
+ // nor polyfill, then a plain number is used for performance.
21
+ var REACT_ELEMENT_TYPE = typeof Symbol === 'function' && Symbol['for'] && Symbol['for']('react.element') || 0xeac7;
17
22
 
18
23
  var RESERVED_PROPS = {
19
24
  key: true,
20
- ref: true
25
+ ref: true,
26
+ __self: true,
27
+ __source: true
21
28
  };
22
29
 
23
30
  /**
@@ -27,51 +34,75 @@ var RESERVED_PROPS = {
27
34
  * @param {*} type
28
35
  * @param {*} key
29
36
  * @param {string|object} ref
37
+ * @param {*} self A *temporary* helper to detect places where `this` is
38
+ * different from the `owner` when React.createElement is called, so that we
39
+ * can warn. We want to get rid of owner and replace string `ref`s with arrow
40
+ * functions, and as long as `this` and owner are the same, there will be no
41
+ * change in behavior.
42
+ * @param {*} source An annotation object (added by a transpiler or otherwise)
43
+ * indicating filename, line number, and/or other information.
30
44
  * @param {*} owner
31
45
  * @param {*} props
32
46
  * @internal
33
47
  */
34
- var ReactElement = function (type, key, ref, owner, props) {
35
- // Built-in properties that belong on the element
36
- this.type = type;
37
- this.key = key;
38
- this.ref = ref;
48
+ var ReactElement = function (type, key, ref, self, source, owner, props) {
49
+ var element = {
50
+ // This tag allow us to uniquely identify this as a React Element
51
+ $$typeof: REACT_ELEMENT_TYPE,
39
52
 
40
- // Record the component responsible for creating this element.
41
- this._owner = owner;
53
+ // Built-in properties that belong on the element
54
+ type: type,
55
+ key: key,
56
+ ref: ref,
57
+ props: props,
42
58
 
43
- this.props = props;
59
+ // Record the component responsible for creating this element.
60
+ _owner: owner
61
+ };
44
62
 
45
63
  if (process.env.NODE_ENV !== 'production') {
46
64
  // The validation flag is currently mutative. We put it on
47
65
  // an external backing store so that we can freeze the whole object.
48
66
  // This can be replaced with a WeakMap once they are implemented in
49
67
  // commonly used development environments.
50
- this._store = {};
68
+ element._store = {};
51
69
 
52
70
  // To make comparing ReactElements easier for testing purposes, we make
53
71
  // the validation flag non-enumerable (where possible, which should
54
72
  // include every environment we run tests in), so the test framework
55
73
  // ignores it.
56
- try {
57
- Object.defineProperty(this._store, 'validated', {
74
+ if (canDefineProperty) {
75
+ Object.defineProperty(element._store, 'validated', {
58
76
  configurable: false,
59
77
  enumerable: false,
60
78
  writable: true,
61
79
  value: false
62
80
  });
63
- } catch (x) {
64
- this._store.validated = false;
81
+ // self and source are DEV only properties.
82
+ Object.defineProperty(element, '_self', {
83
+ configurable: false,
84
+ enumerable: false,
85
+ writable: false,
86
+ value: self
87
+ });
88
+ // Two elements created in two different places should be considered
89
+ // equal for testing purposes and therefore we hide it from enumeration.
90
+ Object.defineProperty(element, '_source', {
91
+ configurable: false,
92
+ enumerable: false,
93
+ writable: false,
94
+ value: source
95
+ });
96
+ } else {
97
+ element._store.validated = false;
98
+ element._self = self;
99
+ element._source = source;
65
100
  }
66
- Object.freeze(this.props);
67
- Object.freeze(this);
101
+ Object.freeze(element.props);
102
+ Object.freeze(element);
68
103
  }
69
- };
70
104
 
71
- // We intentionally don't expose the function on the constructor property.
72
- // ReactElement should be indistinguishable from a plain object.
73
- ReactElement.prototype = {
74
- _isReactElement: true
105
+ return element;
75
106
  };
76
107
 
77
108
  ReactElement.createElement = function (type, config, children) {
@@ -82,10 +113,14 @@ ReactElement.createElement = function (type, config, children) {
82
113
 
83
114
  var key = null;
84
115
  var ref = null;
116
+ var self = null;
117
+ var source = null;
85
118
 
86
119
  if (config != null) {
87
120
  ref = config.ref === undefined ? null : config.ref;
88
121
  key = config.key === undefined ? null : '' + config.key;
122
+ self = config.__self === undefined ? null : config.__self;
123
+ source = config.__source === undefined ? null : config.__source;
89
124
  // Remaining properties are added to a new props object
90
125
  for (propName in config) {
91
126
  if (config.hasOwnProperty(propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {
@@ -117,7 +152,7 @@ ReactElement.createElement = function (type, config, children) {
117
152
  }
118
153
  }
119
154
 
120
- return new ReactElement(type, key, ref, ReactCurrentOwner.current, props);
155
+ return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);
121
156
  };
122
157
 
123
158
  ReactElement.createFactory = function (type) {
@@ -131,8 +166,14 @@ ReactElement.createFactory = function (type) {
131
166
  return factory;
132
167
  };
133
168
 
169
+ ReactElement.cloneAndReplaceKey = function (oldElement, newKey) {
170
+ var newElement = ReactElement(oldElement.type, newKey, oldElement.ref, oldElement._self, oldElement._source, oldElement._owner, oldElement.props);
171
+
172
+ return newElement;
173
+ };
174
+
134
175
  ReactElement.cloneAndReplaceProps = function (oldElement, newProps) {
135
- var newElement = new ReactElement(oldElement.type, oldElement.key, oldElement.ref, oldElement._owner, newProps);
176
+ var newElement = ReactElement(oldElement.type, oldElement.key, oldElement.ref, oldElement._self, oldElement._source, oldElement._owner, newProps);
136
177
 
137
178
  if (process.env.NODE_ENV !== 'production') {
138
179
  // If the key on the original is valid, then the clone is valid
@@ -151,6 +192,12 @@ ReactElement.cloneElement = function (element, config, children) {
151
192
  // Reserved names are extracted
152
193
  var key = element.key;
153
194
  var ref = element.ref;
195
+ // Self is preserved since the owner is preserved.
196
+ var self = element._self;
197
+ // Source is preserved since cloneElement is unlikely to be targeted by a
198
+ // transpiler, and the original source is probably a better indicator of the
199
+ // true owner.
200
+ var source = element._source;
154
201
 
155
202
  // Owner will be preserved, unless ref is overridden
156
203
  var owner = element._owner;
@@ -185,7 +232,7 @@ ReactElement.cloneElement = function (element, config, children) {
185
232
  props.children = childArray;
186
233
  }
187
234
 
188
- return new ReactElement(element.type, key, ref, owner, props);
235
+ return ReactElement(element.type, key, ref, self, source, owner, props);
189
236
  };
190
237
 
191
238
  /**
@@ -194,17 +241,7 @@ ReactElement.cloneElement = function (element, config, children) {
194
241
  * @final
195
242
  */
196
243
  ReactElement.isValidElement = function (object) {
197
- // ReactTestUtils is often used outside of beforeEach where as React is
198
- // within it. This leads to two different instances of React on the same
199
- // page. To identify a element from a different React instance we use
200
- // a flag instead of an instanceof check.
201
- var isElement = !!(object && object._isReactElement);
202
- // if (isElement && !(object instanceof ReactElement)) {
203
- // This is an indicator that you're using multiple versions of React at the
204
- // same time. This will screw with ownership and stuff. Fix it, please.
205
- // TODO: We could possibly warn here.
206
- // }
207
- return isElement;
244
+ return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
208
245
  };
209
246
 
210
247
  module.exports = ReactElement;