react 0.9.0 → 0.10.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 (44) hide show
  1. package/lib/AutoFocusMixin.js +3 -1
  2. package/lib/DOMChildrenOperations.js +12 -6
  3. package/lib/DOMProperty.js +6 -4
  4. package/lib/DOMPropertyOperations.js +6 -6
  5. package/lib/DefaultDOMPropertyConfig.js +5 -12
  6. package/lib/EventPluginHub.js +2 -0
  7. package/lib/LinkedValueUtils.js +22 -23
  8. package/lib/React.js +3 -1
  9. package/lib/ReactBrowserComponentMixin.js +42 -0
  10. package/lib/ReactCSSTransitionGroup.js +10 -10
  11. package/lib/ReactComponent.js +76 -31
  12. package/lib/ReactComponentBrowserEnvironment.js +1 -35
  13. package/lib/ReactCompositeComponent.js +199 -67
  14. package/lib/ReactDOM.js +5 -5
  15. package/lib/ReactDOMButton.js +2 -1
  16. package/lib/ReactDOMComponent.js +22 -5
  17. package/lib/ReactDOMForm.js +3 -0
  18. package/lib/ReactDOMImg.js +3 -0
  19. package/lib/ReactDOMInput.js +2 -1
  20. package/lib/ReactDOMOption.js +11 -7
  21. package/lib/ReactDOMSelect.js +2 -1
  22. package/lib/ReactDOMTextarea.js +7 -3
  23. package/lib/ReactDefaultInjection.js +10 -0
  24. package/lib/ReactInjection.js +4 -0
  25. package/lib/ReactInputSelection.js +2 -1
  26. package/lib/ReactMount.js +13 -5
  27. package/lib/ReactMultiChild.js +10 -3
  28. package/lib/ReactOwner.js +6 -1
  29. package/lib/ReactPropTransferer.js +1 -1
  30. package/lib/ReactReconcileTransaction.js +7 -6
  31. package/lib/ReactServerRendering.js +38 -8
  32. package/lib/ReactServerRenderingTransaction.js +116 -0
  33. package/lib/ReactTextComponent.js +24 -2
  34. package/lib/ReactWithAddons.js +3 -1
  35. package/lib/cloneWithProps.js +7 -7
  36. package/lib/{ReactComponentEnvironment.js → emptyObject.js} +6 -5
  37. package/lib/focusNode.js +33 -0
  38. package/lib/instantiateReactComponent.js +70 -0
  39. package/lib/isNode.js +1 -1
  40. package/lib/monitorCodeUse.js +37 -0
  41. package/lib/shouldUpdateReactComponent.js +17 -14
  42. package/lib/traverseAllChildren.js +2 -1
  43. package/lib/update.js +159 -0
  44. package/package.json +1 -1
@@ -95,7 +95,7 @@ var ReactPropTransferer = {
95
95
 
96
96
  var transferStrategy = TransferStrategies[thisKey];
97
97
 
98
- if (transferStrategy) {
98
+ if (transferStrategy && TransferStrategies.hasOwnProperty(thisKey)) {
99
99
  transferStrategy(props, thisKey, newProps[thisKey]);
100
100
  } else if (!props.hasOwnProperty(thisKey)) {
101
101
  props[thisKey] = newProps[thisKey];
@@ -19,7 +19,6 @@
19
19
 
20
20
  "use strict";
21
21
 
22
- var ExecutionEnvironment = require("./ExecutionEnvironment");
23
22
  var PooledClass = require("./PooledClass");
24
23
  var ReactEventEmitter = require("./ReactEventEmitter");
25
24
  var ReactInputSelection = require("./ReactInputSelection");
@@ -127,6 +126,12 @@ var TRANSACTION_WRAPPERS = [
127
126
  */
128
127
  function ReactReconcileTransaction() {
129
128
  this.reinitializeTransaction();
129
+ // Only server-side rendering really needs this option (see
130
+ // `ReactServerRendering`), but server-side uses
131
+ // `ReactServerRenderingTransaction` instead. This option is here so that it's
132
+ // accessible and defaults to false when `ReactDOMComponent` and
133
+ // `ReactTextComponent` checks it in `mountComponent`.`
134
+ this.renderToStaticMarkup = false;
130
135
  this.reactMountReady = ReactMountReady.getPooled(null);
131
136
  this.putListenerQueue = ReactPutListenerQueue.getPooled();
132
137
  }
@@ -140,11 +145,7 @@ var Mixin = {
140
145
  * TODO: convert to array<TransactionWrapper>
141
146
  */
142
147
  getTransactionWrappers: function() {
143
- if (ExecutionEnvironment.canUseDOM) {
144
- return TRANSACTION_WRAPPERS;
145
- } else {
146
- return [];
147
- }
148
+ return TRANSACTION_WRAPPERS;
148
149
  },
149
150
 
150
151
  /**
@@ -21,13 +21,15 @@
21
21
  var ReactComponent = require("./ReactComponent");
22
22
  var ReactInstanceHandles = require("./ReactInstanceHandles");
23
23
  var ReactMarkupChecksum = require("./ReactMarkupChecksum");
24
- var ReactReconcileTransaction = require("./ReactReconcileTransaction");
24
+ var ReactServerRenderingTransaction =
25
+ require("./ReactServerRenderingTransaction");
25
26
 
27
+ var instantiateReactComponent = require("./instantiateReactComponent");
26
28
  var invariant = require("./invariant");
27
29
 
28
30
  /**
29
31
  * @param {ReactComponent} component
30
- * @return {string} the markup
32
+ * @return {string} the HTML markup
31
33
  */
32
34
  function renderComponentToString(component) {
33
35
  ("production" !== process.env.NODE_ENV ? invariant(
@@ -41,19 +43,47 @@ function renderComponentToString(component) {
41
43
  'returns the generated markup. Please remove the second parameter.'
42
44
  ) : invariant(!(arguments.length === 2 && typeof arguments[1] === 'function')));
43
45
 
44
- var id = ReactInstanceHandles.createReactRootID();
45
- var transaction = ReactReconcileTransaction.getPooled();
46
- transaction.reinitializeTransaction();
46
+ var transaction;
47
47
  try {
48
+ var id = ReactInstanceHandles.createReactRootID();
49
+ transaction = ReactServerRenderingTransaction.getPooled(false);
50
+
48
51
  return transaction.perform(function() {
49
- var markup = component.mountComponent(id, transaction, 0);
52
+ var componentInstance = instantiateReactComponent(component);
53
+ var markup = componentInstance.mountComponent(id, transaction, 0);
50
54
  return ReactMarkupChecksum.addChecksumToMarkup(markup);
51
55
  }, null);
52
56
  } finally {
53
- ReactReconcileTransaction.release(transaction);
57
+ ReactServerRenderingTransaction.release(transaction);
58
+ }
59
+ }
60
+
61
+ /**
62
+ * @param {ReactComponent} component
63
+ * @return {string} the HTML markup, without the extra React ID and checksum
64
+ * (for generating static pages)
65
+ */
66
+ function renderComponentToStaticMarkup(component) {
67
+ ("production" !== process.env.NODE_ENV ? invariant(
68
+ ReactComponent.isValidComponent(component),
69
+ 'renderComponentToStaticMarkup(): You must pass a valid ReactComponent.'
70
+ ) : invariant(ReactComponent.isValidComponent(component)));
71
+
72
+ var transaction;
73
+ try {
74
+ var id = ReactInstanceHandles.createReactRootID();
75
+ transaction = ReactServerRenderingTransaction.getPooled(true);
76
+
77
+ return transaction.perform(function() {
78
+ var componentInstance = instantiateReactComponent(component);
79
+ return componentInstance.mountComponent(id, transaction, 0);
80
+ }, null);
81
+ } finally {
82
+ ReactServerRenderingTransaction.release(transaction);
54
83
  }
55
84
  }
56
85
 
57
86
  module.exports = {
58
- renderComponentToString: renderComponentToString
87
+ renderComponentToString: renderComponentToString,
88
+ renderComponentToStaticMarkup: renderComponentToStaticMarkup
59
89
  };
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Copyright 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 ReactServerRenderingTransaction
17
+ * @typechecks
18
+ */
19
+
20
+ "use strict";
21
+
22
+ var PooledClass = require("./PooledClass");
23
+ var ReactMountReady = require("./ReactMountReady");
24
+ var ReactPutListenerQueue = require("./ReactPutListenerQueue");
25
+ var Transaction = require("./Transaction");
26
+
27
+ var emptyFunction = require("./emptyFunction");
28
+ var mixInto = require("./mixInto");
29
+
30
+ /**
31
+ * Provides a `ReactMountReady` queue for collecting `onDOMReady` callbacks
32
+ * during the performing of the transaction.
33
+ */
34
+ var ON_DOM_READY_QUEUEING = {
35
+ /**
36
+ * Initializes the internal `onDOMReady` queue.
37
+ */
38
+ initialize: function() {
39
+ this.reactMountReady.reset();
40
+ },
41
+
42
+ close: emptyFunction
43
+ };
44
+
45
+ var PUT_LISTENER_QUEUEING = {
46
+ initialize: function() {
47
+ this.putListenerQueue.reset();
48
+ },
49
+
50
+ close: emptyFunction
51
+ };
52
+
53
+ /**
54
+ * Executed within the scope of the `Transaction` instance. Consider these as
55
+ * being member methods, but with an implied ordering while being isolated from
56
+ * each other.
57
+ */
58
+ var TRANSACTION_WRAPPERS = [
59
+ PUT_LISTENER_QUEUEING,
60
+ ON_DOM_READY_QUEUEING
61
+ ];
62
+
63
+ /**
64
+ * @class ReactServerRenderingTransaction
65
+ * @param {boolean} renderToStaticMarkup
66
+ */
67
+ function ReactServerRenderingTransaction(renderToStaticMarkup) {
68
+ this.reinitializeTransaction();
69
+ this.renderToStaticMarkup = renderToStaticMarkup;
70
+ this.reactMountReady = ReactMountReady.getPooled(null);
71
+ this.putListenerQueue = ReactPutListenerQueue.getPooled();
72
+ }
73
+
74
+ var Mixin = {
75
+ /**
76
+ * @see Transaction
77
+ * @abstract
78
+ * @final
79
+ * @return {array} Empty list of operation wrap proceedures.
80
+ */
81
+ getTransactionWrappers: function() {
82
+ return TRANSACTION_WRAPPERS;
83
+ },
84
+
85
+ /**
86
+ * @return {object} The queue to collect `onDOMReady` callbacks with.
87
+ * TODO: convert to ReactMountReady
88
+ */
89
+ getReactMountReady: function() {
90
+ return this.reactMountReady;
91
+ },
92
+
93
+ getPutListenerQueue: function() {
94
+ return this.putListenerQueue;
95
+ },
96
+
97
+ /**
98
+ * `PooledClass` looks for this, and will invoke this before allowing this
99
+ * instance to be resused.
100
+ */
101
+ destructor: function() {
102
+ ReactMountReady.release(this.reactMountReady);
103
+ this.reactMountReady = null;
104
+
105
+ ReactPutListenerQueue.release(this.putListenerQueue);
106
+ this.putListenerQueue = null;
107
+ }
108
+ };
109
+
110
+
111
+ mixInto(ReactServerRenderingTransaction, Transaction.Mixin);
112
+ mixInto(ReactServerRenderingTransaction, Mixin);
113
+
114
+ PooledClass.addPoolingTo(ReactServerRenderingTransaction);
115
+
116
+ module.exports = ReactServerRenderingTransaction;
@@ -20,6 +20,7 @@
20
20
  "use strict";
21
21
 
22
22
  var DOMPropertyOperations = require("./DOMPropertyOperations");
23
+ var ReactBrowserComponentMixin = require("./ReactBrowserComponentMixin");
23
24
  var ReactComponent = require("./ReactComponent");
24
25
 
25
26
  var escapeTextForBrowser = require("./escapeTextForBrowser");
@@ -44,7 +45,18 @@ var ReactTextComponent = function(initialText) {
44
45
  this.construct({text: initialText});
45
46
  };
46
47
 
48
+ /**
49
+ * Used to clone the text descriptor object before it's mounted.
50
+ *
51
+ * @param {object} props
52
+ * @return {object} A new ReactTextComponent instance
53
+ */
54
+ ReactTextComponent.ConvenienceConstructor = function(props) {
55
+ return new ReactTextComponent(props.text);
56
+ };
57
+
47
58
  mixInto(ReactTextComponent, ReactComponent.Mixin);
59
+ mixInto(ReactTextComponent, ReactBrowserComponentMixin);
48
60
  mixInto(ReactTextComponent, {
49
61
 
50
62
  /**
@@ -52,7 +64,7 @@ mixInto(ReactTextComponent, {
52
64
  * any features besides containing text content.
53
65
  *
54
66
  * @param {string} rootID DOM ID of the root node.
55
- * @param {ReactReconcileTransaction} transaction
67
+ * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
56
68
  * @param {number} mountDepth number of components in the owner hierarchy
57
69
  * @return {string} Markup for this text node.
58
70
  * @internal
@@ -64,9 +76,19 @@ mixInto(ReactTextComponent, {
64
76
  transaction,
65
77
  mountDepth
66
78
  );
79
+
80
+ var escapedText = escapeTextForBrowser(this.props.text);
81
+
82
+ if (transaction.renderToStaticMarkup) {
83
+ // Normally we'd wrap this in a `span` for the reasons stated above, but
84
+ // since this is a situation where React won't take over (static pages),
85
+ // we can simply return the text as it is.
86
+ return escapedText;
87
+ }
88
+
67
89
  return (
68
90
  '<span ' + DOMPropertyOperations.createMarkupForID(rootID) + '>' +
69
- escapeTextForBrowser(this.props.text) +
91
+ escapedText +
70
92
  '</span>'
71
93
  );
72
94
  },
@@ -33,6 +33,7 @@ var ReactCSSTransitionGroup = require("./ReactCSSTransitionGroup");
33
33
 
34
34
  var cx = require("./cx");
35
35
  var cloneWithProps = require("./cloneWithProps");
36
+ var update = require("./update");
36
37
 
37
38
  React.addons = {
38
39
  LinkedStateMixin: LinkedStateMixin,
@@ -40,7 +41,8 @@ React.addons = {
40
41
  TransitionGroup: ReactTransitionGroup,
41
42
 
42
43
  classSet: cx,
43
- cloneWithProps: cloneWithProps
44
+ cloneWithProps: cloneWithProps,
45
+ update: update
44
46
  };
45
47
 
46
48
  if ("production" !== process.env.NODE_ENV) {
@@ -22,6 +22,7 @@
22
22
  var ReactPropTransferer = require("./ReactPropTransferer");
23
23
 
24
24
  var keyOf = require("./keyOf");
25
+ var warning = require("./warning");
25
26
 
26
27
  var CHILDREN_PROP = keyOf({children: null});
27
28
 
@@ -36,13 +37,12 @@ var CHILDREN_PROP = keyOf({children: null});
36
37
  */
37
38
  function cloneWithProps(child, props) {
38
39
  if ("production" !== process.env.NODE_ENV) {
39
- if (child.props.ref) {
40
- console.warn(
41
- 'You are calling cloneWithProps() on a child with a ref. This is ' +
42
- 'dangerous because you\'re creating a new child which will not be ' +
43
- 'added as a ref to its parent.'
44
- );
45
- }
40
+ ("production" !== process.env.NODE_ENV ? warning(
41
+ !child.props.ref,
42
+ 'You are calling cloneWithProps() on a child with a ref. This is ' +
43
+ 'dangerous because you\'re creating a new child which will not be ' +
44
+ 'added as a ref to its parent.'
45
+ ) : null);
46
46
  }
47
47
 
48
48
  var newProps = ReactPropTransferer.mergeProps(props, child.props);
@@ -13,14 +13,15 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  *
16
- * @providesModule ReactComponentEnvironment
16
+ * @providesModule emptyObject
17
17
  */
18
18
 
19
19
  "use strict";
20
20
 
21
- var ReactComponentBrowserEnvironment =
22
- require("./ReactComponentBrowserEnvironment");
21
+ var emptyObject = {};
23
22
 
24
- var ReactComponentEnvironment = ReactComponentBrowserEnvironment;
23
+ if ("production" !== process.env.NODE_ENV) {
24
+ Object.freeze(emptyObject);
25
+ }
25
26
 
26
- module.exports = ReactComponentEnvironment;
27
+ module.exports = emptyObject;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Copyright 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 focusNode
17
+ */
18
+
19
+ "use strict";
20
+
21
+ /**
22
+ * IE8 throws if an input/textarea is disabled and we try to focus it.
23
+ * Focus only when necessary.
24
+ *
25
+ * @param {DOMElement} node input/textarea to focus
26
+ */
27
+ function focusNode(node) {
28
+ if (!node.disabled) {
29
+ node.focus();
30
+ }
31
+ }
32
+
33
+ module.exports = focusNode;
@@ -0,0 +1,70 @@
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 instantiateReactComponent
17
+ * @typechecks static-only
18
+ */
19
+
20
+ "use strict";
21
+
22
+ var warning = require("./warning");
23
+
24
+ /**
25
+ * Validate a `componentDescriptor`. This should be exposed publicly in a follow
26
+ * up diff.
27
+ *
28
+ * @param {object} descriptor
29
+ * @return {boolean} Returns true if this is a valid descriptor of a Component.
30
+ */
31
+ function isValidComponentDescriptor(descriptor) {
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'
37
+ );
38
+ }
39
+
40
+ /**
41
+ * Given a `componentDescriptor` create an instance that will actually be
42
+ * mounted. Currently it just extracts an existing clone from composite
43
+ * components but this is an implementation detail which will change.
44
+ *
45
+ * @param {object} descriptor
46
+ * @return {object} A new instance of componentDescriptor's constructor.
47
+ * @protected
48
+ */
49
+ function instantiateReactComponent(descriptor) {
50
+ if ("production" !== process.env.NODE_ENV) {
51
+ ("production" !== process.env.NODE_ENV ? warning(
52
+ isValidComponentDescriptor(descriptor),
53
+ '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;
68
+ }
69
+
70
+ module.exports = instantiateReactComponent;