diff --git a/src/core/ReactDOM.js b/src/core/ReactDOM.js
index 412a6f4704..c1de36d9ab 100644
--- a/src/core/ReactDOM.js
+++ b/src/core/ReactDOM.js
@@ -50,6 +50,8 @@ function createDOMComponentClass(tag, omitClose) {
instance.construct.apply(instance, arguments);
return instance;
};
+
+ Constructor.ConvenienceConstructor = ConvenienceConstructor;
ConvenienceConstructor.componentConstructor = Constructor;
return ConvenienceConstructor;
}
diff --git a/src/core/ReactPropTransferer.js b/src/core/ReactPropTransferer.js
index 1242887d5d..ed721a3c9b 100644
--- a/src/core/ReactPropTransferer.js
+++ b/src/core/ReactPropTransferer.js
@@ -76,6 +76,33 @@ var ReactPropTransferer = {
TransferStrategies: TransferStrategies,
+ /**
+ * Merge two props objects using TransferStrategies.
+ *
+ * @param {object} oldProps original props (they take precedence)
+ * @param {object} newProps new props to merge in
+ * @return {object} a new object containing both sets of props merged.
+ */
+ mergeProps: function(oldProps, newProps) {
+ var props = merge(oldProps);
+
+ for (var thisKey in newProps) {
+ if (!newProps.hasOwnProperty(thisKey)) {
+ continue;
+ }
+
+ var transferStrategy = TransferStrategies[thisKey];
+
+ if (transferStrategy) {
+ transferStrategy(props, thisKey, newProps[thisKey]);
+ } else if (!props.hasOwnProperty(thisKey)) {
+ props[thisKey] = newProps[thisKey];
+ }
+ }
+
+ return props;
+ },
+
/**
* @lends {ReactPropTransferer.prototype}
*/
@@ -104,29 +131,15 @@ var ReactPropTransferer = {
component.constructor.displayName
);
- var props = {};
- for (var thatKey in component.props) {
- if (component.props.hasOwnProperty(thatKey)) {
- props[thatKey] = component.props[thatKey];
- }
- }
- for (var thisKey in this.props) {
- if (!this.props.hasOwnProperty(thisKey)) {
- continue;
- }
- var transferStrategy = TransferStrategies[thisKey];
- if (transferStrategy) {
- transferStrategy(props, thisKey, this.props[thisKey]);
- } else if (!props.hasOwnProperty(thisKey)) {
- props[thisKey] = this.props[thisKey];
- }
- }
- component.props = props;
+ component.props = ReactPropTransferer.mergeProps(
+ component.props,
+ this.props
+ );
+
return component;
}
}
-
};
module.exports = ReactPropTransferer;
diff --git a/src/utils/__tests__/cloneWithProps-test.js b/src/utils/__tests__/cloneWithProps-test.js
new file mode 100644
index 0000000000..2e96bdcdda
--- /dev/null
+++ b/src/utils/__tests__/cloneWithProps-test.js
@@ -0,0 +1,89 @@
+/**
+ * Copyright 2013 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * @emails react-core
+ * @jsx React.DOM
+ */
+
+"use strict";
+
+require('mock-modules').dontMock('cloneWithProps');
+
+var mocks = require('mocks');
+
+var cloneWithProps = require('cloneWithProps');
+
+var React;
+var ReactTestUtils;
+
+var onlyChild;
+
+describe('cloneWithProps', function() {
+
+ beforeEach(function() {
+ React = require('React');
+ ReactTestUtils = require('ReactTestUtils');
+ onlyChild = require('onlyChild');
+ });
+
+ it('should clone an object with new props', function() {
+ var Grandparent = React.createClass({
+ render: function() {
+ return