From cac45631c35217e930c38750a0fa1dd20858543c Mon Sep 17 00:00:00 2001 From: Andreas Svensson Date: Thu, 25 Sep 2014 10:46:29 +0200 Subject: [PATCH 001/113] Remove superfluous classID from DOMAttributeNames --- src/browser/ui/dom/HTMLDOMPropertyConfig.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/browser/ui/dom/HTMLDOMPropertyConfig.js b/src/browser/ui/dom/HTMLDOMPropertyConfig.js index 52fbf32ece..76886c7559 100644 --- a/src/browser/ui/dom/HTMLDOMPropertyConfig.js +++ b/src/browser/ui/dom/HTMLDOMPropertyConfig.js @@ -168,7 +168,6 @@ var HTMLDOMPropertyConfig = { property: null // Supports OG in meta tags }, DOMAttributeNames: { - classID: 'classid', className: 'class', htmlFor: 'for', httpEquiv: 'http-equiv' From 3de80ec4ba932a486c1294c539a5da974fc289db Mon Sep 17 00:00:00 2001 From: Andreas Svensson Date: Fri, 26 Sep 2014 16:45:33 +0200 Subject: [PATCH 002/113] Add manifest to HTMLDOMPropertyConfig --- src/browser/ui/dom/HTMLDOMPropertyConfig.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/browser/ui/dom/HTMLDOMPropertyConfig.js b/src/browser/ui/dom/HTMLDOMPropertyConfig.js index 52fbf32ece..d2f1a2b2bf 100644 --- a/src/browser/ui/dom/HTMLDOMPropertyConfig.js +++ b/src/browser/ui/dom/HTMLDOMPropertyConfig.js @@ -108,6 +108,7 @@ var HTMLDOMPropertyConfig = { lang: null, list: null, loop: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, + manifest: MUST_USE_ATTRIBUTE, max: null, maxLength: MUST_USE_ATTRIBUTE, media: MUST_USE_ATTRIBUTE, From a8fff939719886394027d1014cb69596f4bcb96f Mon Sep 17 00:00:00 2001 From: Ben Alpert Date: Mon, 29 Sep 2014 17:37:13 -0700 Subject: [PATCH 003/113] Rename ReactUpdates.setImmediate to 'asap' Per https://github.com/facebook/react/pull/1554#issuecomment-57243842. Test Plan: jest --- .../ui/dom/components/ReactDOMInput.js | 6 ++-- .../ui/dom/components/ReactDOMSelect.js | 2 +- .../ui/dom/components/ReactDOMTextarea.js | 2 +- src/core/ReactUpdates.js | 28 ++++++++-------- src/core/__tests__/ReactUpdates-test.js | 32 +++++++++---------- 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/browser/ui/dom/components/ReactDOMInput.js b/src/browser/ui/dom/components/ReactDOMInput.js index f1718a14c9..221a63d146 100644 --- a/src/browser/ui/dom/components/ReactDOMInput.js +++ b/src/browser/ui/dom/components/ReactDOMInput.js @@ -125,10 +125,10 @@ var ReactDOMInput = ReactCompositeComponent.createClass({ if (onChange) { returnValue = onChange.call(this, event); } - // Here we use setImmediate to wait until all updates have propagated, which + // Here we use asap to wait until all updates have propagated, which // is important when using controlled components within layers: // https://github.com/facebook/react/issues/1698 - ReactUpdates.setImmediate(forceUpdateIfMounted, this); + ReactUpdates.asap(forceUpdateIfMounted, this); var name = this.props.name; if (this.props.type === 'radio' && name != null) { @@ -169,7 +169,7 @@ var ReactDOMInput = ReactCompositeComponent.createClass({ // If this is a controlled radio button group, forcing the input that // was previously checked to update will cause it to be come re-checked // as appropriate. - ReactUpdates.setImmediate(forceUpdateIfMounted, otherInstance); + ReactUpdates.asap(forceUpdateIfMounted, otherInstance); } } diff --git a/src/browser/ui/dom/components/ReactDOMSelect.js b/src/browser/ui/dom/components/ReactDOMSelect.js index cc98e36815..7016e3d295 100644 --- a/src/browser/ui/dom/components/ReactDOMSelect.js +++ b/src/browser/ui/dom/components/ReactDOMSelect.js @@ -180,7 +180,7 @@ var ReactDOMSelect = ReactCompositeComponent.createClass({ } this._pendingValue = selectedValue; - ReactUpdates.setImmediate(updateWithPendingValueIfMounted, this); + ReactUpdates.asap(updateWithPendingValueIfMounted, this); return returnValue; } diff --git a/src/browser/ui/dom/components/ReactDOMTextarea.js b/src/browser/ui/dom/components/ReactDOMTextarea.js index 07b1377c95..895597b157 100644 --- a/src/browser/ui/dom/components/ReactDOMTextarea.js +++ b/src/browser/ui/dom/components/ReactDOMTextarea.js @@ -135,7 +135,7 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({ if (onChange) { returnValue = onChange.call(this, event); } - ReactUpdates.setImmediate(forceUpdateIfMounted, this); + ReactUpdates.asap(forceUpdateIfMounted, this); return returnValue; } diff --git a/src/core/ReactUpdates.js b/src/core/ReactUpdates.js index 8bad4f4309..ad4a3dfdd0 100644 --- a/src/core/ReactUpdates.js +++ b/src/core/ReactUpdates.js @@ -29,8 +29,8 @@ var mixInto = require('mixInto'); var warning = require('warning'); var dirtyComponents = []; -var setImmediateCallbackQueue = CallbackQueue.getPooled(); -var setImmediateEnqueued = false; +var asapCallbackQueue = CallbackQueue.getPooled(); +var asapEnqueued = false; var batchingStrategy = null; @@ -172,18 +172,18 @@ var flushBatchedUpdates = ReactPerf.measure( // ReactUpdatesFlushTransaction's wrappers will clear the dirtyComponents // array and perform any updates enqueued by mount-ready handlers (i.e., // componentDidUpdate) but we need to check here too in order to catch - // updates enqueued by setState callbacks and setImmediate calls. - while (dirtyComponents.length || setImmediateEnqueued) { + // updates enqueued by setState callbacks and asap calls. + while (dirtyComponents.length || asapEnqueued) { if (dirtyComponents.length) { var transaction = ReactUpdatesFlushTransaction.getPooled(); transaction.perform(runBatchedUpdates, null, transaction); ReactUpdatesFlushTransaction.release(transaction); } - if (setImmediateEnqueued) { - setImmediateEnqueued = false; - var queue = setImmediateCallbackQueue; - setImmediateCallbackQueue = CallbackQueue.getPooled(); + if (asapEnqueued) { + asapEnqueued = false; + var queue = asapCallbackQueue; + asapCallbackQueue = CallbackQueue.getPooled(); queue.notifyAll(); CallbackQueue.release(queue); } @@ -237,14 +237,14 @@ function enqueueUpdate(component, callback) { * Enqueue a callback to be run at the end of the current batching cycle. Throws * if no updates are currently being performed. */ -function setImmediate(callback, context) { +function asap(callback, context) { invariant( batchingStrategy.isBatchingUpdates, - 'ReactUpdates.setImmediate: Can\'t enqueue an immediate callback in a ' + - 'context where updates are not being batched.' + 'ReactUpdates.asap: Can\'t enqueue an asap callback in a context where' + + 'updates are not being batched.' ); - setImmediateCallbackQueue.enqueue(callback, context); - setImmediateEnqueued = true; + asapCallbackQueue.enqueue(callback, context); + asapEnqueued = true; } var ReactUpdatesInjection = { @@ -286,7 +286,7 @@ var ReactUpdates = { enqueueUpdate: enqueueUpdate, flushBatchedUpdates: flushBatchedUpdates, injection: ReactUpdatesInjection, - setImmediate: setImmediate + asap: asap }; module.exports = ReactUpdates; diff --git a/src/core/__tests__/ReactUpdates-test.js b/src/core/__tests__/ReactUpdates-test.js index f4093daa58..d748108e68 100644 --- a/src/core/__tests__/ReactUpdates-test.js +++ b/src/core/__tests__/ReactUpdates-test.js @@ -749,7 +749,7 @@ describe('ReactUpdates', function() { expect(callbackCount).toBe(1); }); - it('calls setImmediate callbacks properly', function() { + it('calls asap callbacks properly', function() { var callbackCount = 0; var A = React.createClass({ render: function() { @@ -757,10 +757,10 @@ describe('ReactUpdates', function() { }, componentDidUpdate: function() { var component = this; - ReactUpdates.setImmediate(function() { + ReactUpdates.asap(function() { expect(this).toBe(component); callbackCount++; - ReactUpdates.setImmediate(function() { + ReactUpdates.asap(function() { callbackCount++; }); expect(callbackCount).toBe(1); @@ -775,7 +775,7 @@ describe('ReactUpdates', function() { expect(callbackCount).toBe(2); }); - it('calls setImmediate callbacks with queued updates', function() { + it('calls asap callbacks with queued updates', function() { var log = []; var A = React.createClass({ getInitialState: () => ({updates: 0}), @@ -785,18 +785,18 @@ describe('ReactUpdates', function() { }, componentDidUpdate: function() { if (this.state.updates === 1) { - ReactUpdates.setImmediate(function() { + ReactUpdates.asap(function() { this.setState({updates: 2}, function() { - ReactUpdates.setImmediate(function() { - log.push('setImmediate-1.2'); + ReactUpdates.asap(function() { + log.push('asap-1.2'); }); log.push('setState-cb'); }); - log.push('setImmediate-1.1'); + log.push('asap-1.1'); }, this); } else if (this.state.updates === 2) { - ReactUpdates.setImmediate(function() { - log.push('setImmediate-2'); + ReactUpdates.asap(function() { + log.push('asap-2'); }); } log.push('didUpdate-' + this.state.updates); @@ -811,16 +811,16 @@ describe('ReactUpdates', function() { // We do the first update... 'render-1', 'didUpdate-1', - // ...which calls a setImmediate and enqueues a second update... - 'setImmediate-1.1', - // ...which runs and enqueues the setImmediate-2 log in its didUpdate... + // ...which calls asap and enqueues a second update... + 'asap-1.1', + // ...which runs and enqueues the asap-2 log in its didUpdate... 'render-2', 'didUpdate-2', // ...and runs the setState callback, which enqueues the log for - // setImmediate-1.2. + // asap-1.2. 'setState-cb', - 'setImmediate-2', - 'setImmediate-1.2' + 'asap-2', + 'asap-1.2' ]); }); }); From c4658c1728b39c452a86f371ecb1c51874456107 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 7 Oct 2014 10:44:39 -0700 Subject: [PATCH 004/113] Update React JSX Transforms * Extract JSXDOM into separate transform * Rename lower case variables in JSX to upper case * Drop React.DOM docblock, use string tags instead --- .../transforms/__tests__/react-test.js | 139 +++++------------- vendor/fbtransform/transforms/react.js | 94 ++++-------- 2 files changed, 61 insertions(+), 172 deletions(-) diff --git a/vendor/fbtransform/transforms/__tests__/react-test.js b/vendor/fbtransform/transforms/__tests__/react-test.js index 772acc9706..303f300c72 100644 --- a/vendor/fbtransform/transforms/__tests__/react-test.js +++ b/vendor/fbtransform/transforms/__tests__/react-test.js @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * @emails jeffmo@fb.com + * @emails react-core */ /*jshint evil:true, unused:false*/ @@ -59,34 +59,21 @@ describe('react jsx', function() { }; it('should convert simple tags', function() { - var code = [ - '/**@jsx React.DOM*/', - 'var x =
;' - ].join('\n'); - var result = [ - '/**@jsx React.DOM*/', - 'var x = React.createElement(React.DOM.div, null);' - ].join('\n'); + var code = 'var x =
;'; + var result = 'var x = React.createElement("div", null);'; expect(transform(code).code).toEqual(result); }); it('should convert simple text', function() { - var code = [ - '/**@jsx React.DOM*/\n' + - 'var x =
text
;' - ].join('\n'); - var result = [ - '/**@jsx React.DOM*/', - 'var x = React.createElement(React.DOM.div, null, "text");' - ].join('\n'); + var code = 'var x =
text
;'; + var result = 'var x = React.createElement("div", null, "text");'; expect(transform(code).code).toEqual(result); }); it('should have correct comma in nested children', function() { var code = [ - '/**@jsx React.DOM*/', 'var x =
', '

', ' {foo}
{bar}
', @@ -94,13 +81,12 @@ describe('react jsx', function() { '
;' ].join('\n'); var result = [ - '/**@jsx React.DOM*/', - 'var x = React.createElement(React.DOM.div, null, ', - ' React.createElement(React.DOM.div, null, ' + - 'React.createElement(React.DOM.br, null)), ', + 'var x = React.createElement("div", null, ', + ' React.createElement("div", null, ' + + 'React.createElement("br", null)), ', ' React.createElement(Component, null, foo, ' + - 'React.createElement(React.DOM.br, null), bar), ', - ' React.createElement(React.DOM.br, null)', + 'React.createElement("br", null), bar), ', + ' React.createElement("br", null)', ');' ].join('\n'); @@ -110,14 +96,12 @@ describe('react jsx', function() { it('should avoid wrapping in extra parens if not needed', function() { // Try with a single composite child, wrapped in a div. var code = [ - '/**@jsx React.DOM*/', 'var x =
', ' ', '
;' ].join('\n'); var result = [ - '/**@jsx React.DOM*/', - 'var x = React.createElement(React.DOM.div, null, ', + 'var x = React.createElement("div", null, ', ' React.createElement(Component, null)', ');' ].join('\n'); @@ -126,14 +110,12 @@ describe('react jsx', function() { // Try with a single interpolated child, wrapped in a div. code = [ - '/**@jsx React.DOM*/', 'var x =
', ' {this.props.children}', '
;' ].join('\n'); result = [ - '/**@jsx React.DOM*/', - 'var x = React.createElement(React.DOM.div, null, ', + 'var x = React.createElement("div", null, ', ' this.props.children', ');' ].join('\n'); @@ -141,13 +123,11 @@ describe('react jsx', function() { // Try with a single interpolated child, wrapped in a composite. code = [ - '/**@jsx React.DOM*/', 'var x = ', ' {this.props.children}', ';' ].join('\n'); result = [ - '/**@jsx React.DOM*/', 'var x = React.createElement(Composite, null, ', ' this.props.children', ');' @@ -156,13 +136,11 @@ describe('react jsx', function() { // Try with a single composite child, wrapped in a composite. code = [ - '/**@jsx React.DOM*/', 'var x = ', ' ', ';' ].join('\n'); result = [ - '/**@jsx React.DOM*/', 'var x = React.createElement(Composite, null, ', ' React.createElement(Composite2, null)', ');' @@ -172,7 +150,6 @@ describe('react jsx', function() { it('should insert commas after expressions before whitespace', function() { var code = [ - '/**@jsx React.DOM*/', 'var x =', ' ;' ].join('\n'); var result = [ - '/**@jsx React.DOM*/', 'var x =', - ' React.createElement(React.DOM.div, {', + ' React.createElement("div", {', ' attr1: ', ' "foo" + "bar", ', ' ', @@ -217,9 +193,6 @@ describe('react jsx', function() { it('should properly handle comments adjacent to children', function() { var code = [ - '/**', - ' * @jsx React.DOM', - ' */', 'var x = (', '
', ' {/* A comment at the beginning */}', @@ -235,18 +208,15 @@ describe('react jsx', function() { ');' ].join('\n'); var result = [ - '/**', - ' * @jsx React.DOM', - ' */', 'var x = (', - ' React.createElement(React.DOM.div, null, ', + ' React.createElement("div", null, ', ' /* A comment at the beginning */', ' /* A second comment at the beginning */', - ' React.createElement(React.DOM.span, null', + ' React.createElement("span", null', ' /* A nested comment */', ' ), ', ' /* A sandwiched comment */', - ' React.createElement(React.DOM.br, null)', + ' React.createElement("br", null)', ' /* A comment at the end */', ' /* A second comment at the end */', ' )', @@ -258,9 +228,6 @@ describe('react jsx', function() { it('should properly handle comments between props', function() { var code = [ - '/**', - ' * @jsx React.DOM', - ' */', 'var x = (', '  
;' ].join('\n'); var result = [ - '/**', - ' * @jsx React.DOM', - ' */', - 'React.createElement(React.DOM.div, null, "\u00A0");' + 'React.createElement("div", null, "\u00A0");' ].join('\n'); expect(transform(code).code).toBe(result); @@ -310,16 +268,10 @@ describe('react jsx', function() { it('should not strip   even coupled with other whitespace', function() { var code = [ - '/**', - ' * @jsx React.DOM', - ' */', '
 
;' ].join('\n'); var result = [ - '/**', - ' * @jsx React.DOM', - ' */', - 'React.createElement(React.DOM.div, null, "\u00A0 ");' + 'React.createElement("div", null, "\u00A0 ");' ].join('\n'); expect(transform(code).code).toBe(result); @@ -327,9 +279,13 @@ describe('react jsx', function() { it('should handle hasOwnProperty correctly', function() { var code = 'testing;'; - var result = 'React.createElement(hasOwnProperty, null, "testing");'; + // var result = 'React.createElement("hasOwnProperty", null, "testing");'; - expect(transform(code).code).toBe(result); + // expect(transform(code).code).toBe(result); + + // This is currently not supported, and will generate a string tag in + // a follow up. + expect(() => transform(code)).toThrow(); }); it('should allow constructor as prop', function() { @@ -347,29 +303,15 @@ describe('react jsx', function() { }); it('should allow deeper JS namespacing', function() { - var code = [ - '/**', - ' * @jsx React.DOM', - ' */', - ';' - ].join('\n'); - var result = [ - '/**', - ' * @jsx React.DOM', - ' */', - 'React.createElement(Namespace.DeepNamespace.Component, null);' - ].join('\n'); + var code = ';'; + var result = + 'React.createElement(Namespace.DeepNamespace.Component, null);'; expect(transform(code).code).toBe(result); }); it('should disallow XML namespacing', function() { - var code = [ - '/**', - ' * @jsx React.DOM', - ' */', - ';' - ].join('\n'); + var code = ';'; expect(() => transform(code)).toThrow(); }); @@ -399,18 +341,8 @@ describe('react jsx', function() { }); it('should transform known hyphenated tags', function() { - var code = [ - '/**', - ' * @jsx React.DOM', - ' */', - ';' - ].join('\n'); - var result = [ - '/**', - ' * @jsx React.DOM', - ' */', - 'React.createElement(React.DOM[\'font-face\'], null);' - ].join('\n'); + var code = ';'; + var result = 'React.createElement("font-face", null);'; expect(transform(code).code).toBe(result); }); @@ -422,12 +354,7 @@ describe('react jsx', function() { }); it('should throw for unknown hyphenated tags', function() { - var code = [ - '/**', - ' * @jsx React.DOM', - ' */', - ';' - ].join('\n'); + var code = ';'; expect(() => transform(code)).toThrow(); }); diff --git a/vendor/fbtransform/transforms/react.js b/vendor/fbtransform/transforms/react.js index 11ed7a8f28..8525dcca89 100644 --- a/vendor/fbtransform/transforms/react.js +++ b/vendor/fbtransform/transforms/react.js @@ -28,27 +28,16 @@ var quoteAttrName = require('./xjs').quoteAttrName; var trimLeft = require('./xjs').trimLeft; /** - * Customized desugar processor. + * Customized desugar processor for React JSX. Currently: * - * Currently: (Somewhat tailored to React) - * => X(null, null) - * => X({prop: '1'}, null) - * => X({prop:'2'}, Y(null, null)) - * => X({prop:'2'}, [Y(null, null), Z(null, null)]) - * - * Exceptions to the simple rules above: - * if a property is named "class" it will be changed to "className" in the - * javascript since "class" is not a valid object key in javascript. + * => React.createElement(X, null) + * => React.createElement(X, {prop: '1'}, null) + * => React.createElement(X, {prop:'2'}, + * React.createElement(Y, null) + * ) + *
=> React.createElement("div", null) */ -var JSX_ATTRIBUTE_TRANSFORMS = { - cxName: function(attr) { - throw new Error( - "cxName is no longer supported, use className={cx(...)} instead" - ); - } -}; - /** * Removes all non-whitespace/parenthesis characters */ @@ -57,8 +46,12 @@ function stripNonWhiteParen(value) { return value.replace(reNonWhiteParen, ''); } +var tagConvention = /^[a-z]|\-/; +function isTagName(name) { + return tagConvention.test(name); +} + function visitReactTag(traverse, object, path, state) { - var jsxObjIdent = utils.getDocblock(state).jsx; var openingElement = object.openingElement; var nameObject = openingElement.name; var attributesObject = openingElement.attributes; @@ -69,55 +62,31 @@ function visitReactTag(traverse, object, path, state) { throw new Error('Namespace tags are not supported. ReactJSX is not XML.'); } - var isReact = jsxObjIdent !== 'JSXDOM'; - // We assume that the React runtime is already in scope - if (isReact) { - utils.append('React.createElement(', state); - } + utils.append('React.createElement(', state); - // Only identifiers can be fallback tags or need quoting. We don't need to - // handle quoting for other types. - var didAddTag = false; - - // Only identifiers can be fallback tags. XJSMemberExpressions are not. - if (nameObject.type === Syntax.XJSIdentifier) { - var tagName = nameObject.name; - var quotedTagName = quoteAttrName(tagName); - - if (FALLBACK_TAGS.hasOwnProperty(tagName)) { - // "Properly" handle invalid identifiers, like , which needs to - // be enclosed in quotes. - var predicate = - tagName === quotedTagName ? - ('.' + tagName) : - ('[' + quotedTagName + ']'); - utils.append(jsxObjIdent + predicate, state); - utils.move(nameObject.range[1], state); - didAddTag = true; - } else if (tagName !== quotedTagName) { - // If we're in the case where we need to quote and but don't recognize the - // tag, throw. + // Identifiers with lower case or hypthens are fallback tags (strings). + // XJSMemberExpressions are not. + if (nameObject.type === Syntax.XJSIdentifier && isTagName(nameObject.name)) { + // This is a temporary error message to assist upgrades + if (!FALLBACK_TAGS.hasOwnProperty(nameObject.name)) { throw new Error( - 'Tags must be valid JS identifiers or a recognized special case. `<' + - tagName + '>` is not one of them.' + 'Lower case component names (' + nameObject.name + ') are no longer ' + + 'supported in JSX: See http://fb.me/react-jsx-lower-case' ); } - } - // Use utils.catchup in this case so we can easily handle XJSMemberExpressions - // which look like Foo.Bar.Baz. This also handles unhyphenated XJSIdentifiers - // that aren't fallback tags. - if (!didAddTag) { + utils.append('"' + nameObject.name + '"', state); + utils.move(nameObject.range[1], state); + } else { + // Use utils.catchup in this case so we can easily handle + // XJSMemberExpressions which look like Foo.Bar.Baz. This also handles + // XJSIdentifiers that aren't fallback tags. utils.move(nameObject.range[0], state); utils.catchup(nameObject.range[1], state); } - if (isReact) { - utils.append(', ', state); - } else { - utils.append('(', state); - } + utils.append(', ', state); var hasAttributes = attributesObject.length; @@ -147,7 +116,6 @@ function visitReactTag(traverse, object, path, state) { utils.append('}, ', state); } - // Move to the expression start, ignoring everything except parenthesis // and whitespace. utils.catchup(attr.range[0], state, stripNonWhiteParen); @@ -203,13 +171,7 @@ function visitReactTag(traverse, object, path, state) { utils.move(attr.name.range[1], state); // Use catchupNewlines to skip over the '=' in the attribute utils.catchupNewlines(attr.value.range[0], state); - if (JSX_ATTRIBUTE_TRANSFORMS.hasOwnProperty(attr.name.name)) { - utils.append(JSX_ATTRIBUTE_TRANSFORMS[attr.name.name](attr), state); - utils.move(attr.value.range[1], state); - if (!isLast) { - utils.append(', ', state); - } - } else if (attr.value.type === Syntax.Literal) { + if (attr.value.type === Syntax.Literal) { renderXJSLiteral(attr.value, isLast, state); } else { renderXJSExpressionContainer(traverse, attr.value, isLast, path, state); From b2dbccf9a26e9980369b4666101b817559304c34 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 7 Oct 2014 10:26:14 -0700 Subject: [PATCH 005/113] Rename lower case variables in JSX to upper case We're trying to move to a convention where lower-case variables on JSX are always HTML/SVG tags rather than variables in scope. See: http://fb.me/react-jsx-lower-case Therefore, this diff renames existing uses to upper case variables. This throws an error on all these files, so I manually go rename all the variables. I then run lint to ensure that the rename doesn't leave any undeclared variables. --- src/core/__tests__/ReactCompositeComponent-test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/__tests__/ReactCompositeComponent-test.js b/src/core/__tests__/ReactCompositeComponent-test.js index a21f036d8c..00cdec96f6 100644 --- a/src/core/__tests__/ReactCompositeComponent-test.js +++ b/src/core/__tests__/ReactCompositeComponent-test.js @@ -98,8 +98,8 @@ describe('ReactCompositeComponent', function() { console.log(this.getDOMNode()); }, render: function() { - var component = this.state.component; - return component ? : null; + var Component = this.state.component; + return Component ? : null; } }); From 15a0c8920ecd91a636cd1a7df3a79a42fc21d086 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 7 Oct 2014 10:26:23 -0700 Subject: [PATCH 006/113] Don't use React.DOM I grepped for uses of React.DOM. This is going to be a set of helper functions to generate ReactElements without JSX. They're not classes so they cannot be used where a React class is expected. Since we always use JSX, we should have no internal use for these helpers. We can use strings instead. --- src/addons/transitions/ReactTransitionGroup.js | 4 ++-- src/browser/ui/ReactMount.js | 5 ++++- src/browser/ui/__tests__/ReactMount-test.js | 12 +++++++----- src/core/__tests__/ReactCompositeComponent-test.js | 12 ++++++------ src/core/__tests__/ReactMultiChildText-test.js | 2 +- src/core/__tests__/ReactPropTransferer-test.js | 6 +++--- src/test/reactComponentExpect.js | 5 ++++- 7 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/addons/transitions/ReactTransitionGroup.js b/src/addons/transitions/ReactTransitionGroup.js index 6a9e1888c9..174d389676 100644 --- a/src/addons/transitions/ReactTransitionGroup.js +++ b/src/addons/transitions/ReactTransitionGroup.js @@ -29,13 +29,13 @@ var ReactTransitionGroup = React.createClass({ displayName: 'ReactTransitionGroup', propTypes: { - component: React.PropTypes.func, + component: React.PropTypes.any, childFactory: React.PropTypes.func }, getDefaultProps: function() { return { - component: React.DOM.span, + component: 'span', childFactory: emptyFunction.thatReturnsArgument }; }, diff --git a/src/browser/ui/ReactMount.js b/src/browser/ui/ReactMount.js index 3dc095b6aa..ef11832ca5 100644 --- a/src/browser/ui/ReactMount.js +++ b/src/browser/ui/ReactMount.js @@ -345,9 +345,12 @@ var ReactMount = { ReactDescriptor.isValidDescriptor(nextDescriptor), 'renderComponent(): Invalid component descriptor.%s', ( + typeof nextDescriptor === 'string' ? + ' Instead of passing an element string, make sure to instantiate ' + + 'it by passing it to React.createElement.' : ReactDescriptor.isValidFactory(nextDescriptor) ? ' Instead of passing a component class, make sure to instantiate ' + - 'it first by calling it with props.' : + 'it by passing it to React.createElement.' : // Check if it quacks like a descriptor typeof nextDescriptor.props !== "undefined" ? ' This may be caused by unintentionally loading two independent ' + diff --git a/src/browser/ui/__tests__/ReactMount-test.js b/src/browser/ui/__tests__/ReactMount-test.js index 4dd3448e67..2b5fa5cd09 100644 --- a/src/browser/ui/__tests__/ReactMount-test.js +++ b/src/browser/ui/__tests__/ReactMount-test.js @@ -38,15 +38,17 @@ describe('ReactMount', function() { }); }); - it('throws when given a factory', function() { + it('throws when given a string', function() { expect(function() { - ReactTestUtils.renderIntoDocument(React.DOM.div); + ReactTestUtils.renderIntoDocument('div'); }).toThrow( 'Invariant Violation: renderComponent(): Invalid component descriptor. ' + - 'Instead of passing a component class, make sure to instantiate it ' + - 'first by calling it with props.' + 'Instead of passing an element string, make sure to instantiate it ' + + 'by passing it to React.createElement.' ); + }); + it('throws when given a factory', function() { var Component = React.createClass({ render: function() { return
; @@ -57,7 +59,7 @@ describe('ReactMount', function() { }).toThrow( 'Invariant Violation: renderComponent(): Invalid component descriptor. ' + 'Instead of passing a component class, make sure to instantiate it ' + - 'first by calling it with props.' + 'by passing it to React.createElement.' ); }); diff --git a/src/core/__tests__/ReactCompositeComponent-test.js b/src/core/__tests__/ReactCompositeComponent-test.js index 00cdec96f6..4da64842bc 100644 --- a/src/core/__tests__/ReactCompositeComponent-test.js +++ b/src/core/__tests__/ReactCompositeComponent-test.js @@ -196,11 +196,11 @@ describe('ReactCompositeComponent', function() { var instance1 = ; var instance2 = ; @@ -223,11 +223,11 @@ describe('ReactCompositeComponent', function() { var instance1 = ; var instance2 = ; @@ -264,13 +264,13 @@ describe('ReactCompositeComponent', function() { var instance1 = ; var instance2 = ; expect(function() { diff --git a/src/core/__tests__/ReactMultiChildText-test.js b/src/core/__tests__/ReactMultiChildText-test.js index 01fa1d99e2..4208348a33 100644 --- a/src/core/__tests__/ReactMultiChildText-test.js +++ b/src/core/__tests__/ReactMultiChildText-test.js @@ -94,7 +94,7 @@ var expectChildren = function(d, children) { var elementDOMNode = reactComponentExpect(d) .expectRenderedChildAt(i) - .toBeComponentOfType(React.DOM.div) + .toBeComponentOfType('div') .instance() .getDOMNode(); diff --git a/src/core/__tests__/ReactPropTransferer-test.js b/src/core/__tests__/ReactPropTransferer-test.js index 9373fa0ad2..487c16d630 100644 --- a/src/core/__tests__/ReactPropTransferer-test.js +++ b/src/core/__tests__/ReactPropTransferer-test.js @@ -59,7 +59,7 @@ describe('ReactPropTransferer', function() { reactComponentExpect(instance) .expectRenderedChild() - .toBeComponentOfType(React.DOM.input) + .toBeComponentOfType('input') .scalarPropsEqual({ className: 'textinput', style: {display: 'block', color: 'green'}, @@ -74,7 +74,7 @@ describe('ReactPropTransferer', function() { reactComponentExpect(instance) .expectRenderedChild() - .toBeComponentOfType(React.DOM.input) + .toBeComponentOfType('input') .scalarPropsEqual({placeholder: 'Type here...'}); }); @@ -88,7 +88,7 @@ describe('ReactPropTransferer', function() { reactComponentExpect(instance) .expectRenderedChild() - .toBeComponentOfType(React.DOM.input) + .toBeComponentOfType('input') .scalarPropsEqual({ className: 'textinput hidden_elem', style: { diff --git a/src/test/reactComponentExpect.js b/src/test/reactComponentExpect.js index 56815ecd42..2c39cb4fa3 100644 --- a/src/test/reactComponentExpect.js +++ b/src/test/reactComponentExpect.js @@ -105,8 +105,11 @@ mergeInto(reactComponentExpect.prototype, { // Matchers ------------------------------------------------------------------ toBeComponentOfType: function(convenienceConstructor) { + var type = typeof convenienceConstructor === 'string' ? + convenienceConstructor : + convenienceConstructor.type; expect( - this.instance()._descriptor.type === convenienceConstructor.type + this.instance()._descriptor.type === type ).toBe(true); return this; }, From 7f9b1d18d197d102777f214e782ecc27685cf481 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 7 Oct 2014 10:26:32 -0700 Subject: [PATCH 007/113] Start warning when React.DOM.x is passed into JSX React.DOM is becoming helper factories to generate ReactElements. They're not classes. It will be ok to call them directly as functions, but not to use them where a class is expected. --- src/browser/ReactDOM.js | 4 +- src/browser/__tests__/ReactDOM-test.js | 31 ++++++++++++++- src/browser/ui/React.js | 2 +- src/browser/ui/ReactMount.js | 2 +- src/core/ReactCompositeComponent.js | 2 +- src/core/ReactDescriptor.js | 17 -------- src/core/ReactLegacyDescriptor.js | 54 ++++++++++++++++++++++++-- src/test/ReactTestUtils.js | 3 +- 8 files changed, 86 insertions(+), 29 deletions(-) diff --git a/src/browser/ReactDOM.js b/src/browser/ReactDOM.js index 8d3bc87df8..9d88b7eb62 100644 --- a/src/browser/ReactDOM.js +++ b/src/browser/ReactDOM.js @@ -33,11 +33,11 @@ var mapObject = require('mapObject'); */ function createDOMFactory(tag) { if (__DEV__) { - return ReactLegacyDescriptor.wrapFactory( + return ReactLegacyDescriptor.markNonLegacyFactory( ReactDescriptorValidator.createFactory(tag) ); } - return ReactLegacyDescriptor.wrapFactory( + return ReactLegacyDescriptor.markNonLegacyFactory( ReactDescriptor.createFactory(tag) ); } diff --git a/src/browser/__tests__/ReactDOM-test.js b/src/browser/__tests__/ReactDOM-test.js index aae27e976e..aa3458ef41 100644 --- a/src/browser/__tests__/ReactDOM-test.js +++ b/src/browser/__tests__/ReactDOM-test.js @@ -25,7 +25,7 @@ var React = require('React'); var ReactDOM = require('ReactDOM'); var ReactMount = require('ReactMount'); var ReactTestUtils = require('ReactTestUtils'); -var div = React.createFactory(ReactDOM.div); // TODO: use string +var div = React.createFactory('div'); describe('ReactDOM', function() { // TODO: uncomment this test once we can run in phantom, which @@ -117,6 +117,33 @@ describe('ReactDOM', function() { }); it('should be a valid class', function() { - expect(React.isValidClass(ReactDOM.div)).toBe(true); + expect(React.isValidClass(ReactDOM.div)).toBe(false); + }); + + it('allow React.DOM factories to be called without warnings', function() { + spyOn(console, 'warn'); + var descriptor = React.DOM.div(); + expect(descriptor.type).toBe('div'); + expect(console.warn.argsForCall.length).toBe(0); + }); + + it('warns but allow dom factories to be used in createFactory', function() { + spyOn(console, 'warn'); + var factory = React.createFactory(React.DOM.div); + expect(factory().type).toBe('div'); + expect(console.warn.argsForCall.length).toBe(1); + expect(console.warn.argsForCall[0][0]).toContain( + 'Do not pass React.DOM.div' + ); + }); + + it('warns but allow dom factories to be used in createElement', function() { + spyOn(console, 'warn'); + var descriptor = React.createElement(React.DOM.div); + expect(descriptor.type).toBe('div'); + expect(console.warn.argsForCall.length).toBe(1); + expect(console.warn.argsForCall[0][0]).toContain( + 'Do not pass React.DOM.div' + ); }); }); diff --git a/src/browser/ui/React.js b/src/browser/ui/React.js index 8948fb2577..e0d6c9bad4 100644 --- a/src/browser/ui/React.js +++ b/src/browser/ui/React.js @@ -90,7 +90,7 @@ var React = { renderComponentToStaticMarkup: ReactServerRendering.renderComponentToStaticMarkup, unmountComponentAtNode: ReactMount.unmountComponentAtNode, - isValidClass: ReactDescriptor.isValidFactory, + isValidClass: ReactLegacyDescriptor.isValidFactory, isValidComponent: ReactDescriptor.isValidDescriptor, withContext: ReactContext.withContext, __internals: { diff --git a/src/browser/ui/ReactMount.js b/src/browser/ui/ReactMount.js index ef11832ca5..a5acf90134 100644 --- a/src/browser/ui/ReactMount.js +++ b/src/browser/ui/ReactMount.js @@ -348,7 +348,7 @@ var ReactMount = { typeof nextDescriptor === 'string' ? ' Instead of passing an element string, make sure to instantiate ' + 'it by passing it to React.createElement.' : - ReactDescriptor.isValidFactory(nextDescriptor) ? + ReactLegacyDescriptor.isValidFactory(nextDescriptor) ? ' Instead of passing a component class, make sure to instantiate ' + 'it by passing it to React.createElement.' : // Check if it quacks like a descriptor diff --git a/src/core/ReactCompositeComponent.js b/src/core/ReactCompositeComponent.js index 7d79261952..9d73c79e9d 100644 --- a/src/core/ReactCompositeComponent.js +++ b/src/core/ReactCompositeComponent.js @@ -471,7 +471,7 @@ function mixSpecIntoComponent(Constructor, spec) { } invariant( - !ReactDescriptor.isValidFactory(spec), + !ReactLegacyDescriptor.isValidFactory(spec), 'ReactCompositeComponent: You\'re attempting to ' + 'use a component class as a mixin. Instead, just use a regular object.' ); diff --git a/src/core/ReactDescriptor.js b/src/core/ReactDescriptor.js index 784e32cfad..935057b80a 100644 --- a/src/core/ReactDescriptor.js +++ b/src/core/ReactDescriptor.js @@ -214,23 +214,6 @@ ReactDescriptor.cloneAndReplaceProps = function(oldDescriptor, newProps) { return newDescriptor; }; -/** - * Checks if a value is a valid descriptor constructor. - * - * @param {*} - * @return {boolean} - * @public - */ -ReactDescriptor.isValidFactory = function(factory) { - return typeof factory === 'function' && ( - typeof factory.type === 'string' || ( - typeof factory.type === 'function' && - typeof factory.type.prototype.mountComponent === 'function' && - typeof factory.type.prototype.receiveComponent === 'function' - ) - ); -}; - /** * @param {?object} object * @return {boolean} True if `object` is a valid component. diff --git a/src/core/ReactLegacyDescriptor.js b/src/core/ReactLegacyDescriptor.js index e32bd0053a..245df7c566 100644 --- a/src/core/ReactLegacyDescriptor.js +++ b/src/core/ReactLegacyDescriptor.js @@ -19,7 +19,6 @@ "use strict"; var ReactCurrentOwner = require('ReactCurrentOwner'); -var ReactDescriptor = require('ReactDescriptor'); var invariant = require('invariant'); var monitorCodeUse = require('monitorCodeUse'); @@ -78,6 +77,14 @@ function warnForPlainFunctionType(type) { } } +function warnForNonLegacyFactory(type) { + warning( + false, + 'Do not pass React.DOM.' + type.type + ' to JSX or createFactory. ' + + 'Use the string "' + type + '" instead.' + ); +} + /** * Transfer static properties from the source to the target. Functions are * rebound to have this reflect the original source. @@ -109,6 +116,7 @@ function proxyStaticMethods(target, source) { // We use an object instead of a boolean because booleans are ignored by our // mocking libraries when these factories gets mocked. var LEGACY_MARKER = {}; +var NON_LEGACY_MARKER = {}; var ReactLegacyDescriptorFactory = {}; @@ -119,6 +127,16 @@ ReactLegacyDescriptorFactory.wrapCreateFactory = function(createFactory) { return createFactory(type); } + if (type.isReactNonLegacyFactory) { + // This is probably a factory created by ReactDOM we unwrap it to get to + // the underlying string type. It shouldn't have been passed here so we + // warn. + if (__DEV__) { + warnForNonLegacyFactory(type); + } + return createFactory(type.type); + } + if (type.isReactLegacyFactory) { // This is probably a legacy factory created by ReactCompositeComponent. // We unwrap it to get to the underlying class. @@ -143,6 +161,20 @@ ReactLegacyDescriptorFactory.wrapCreateDescriptor = function(createDescriptor) { return createDescriptor.apply(this, arguments); } + var args; + + if (type.isReactNonLegacyFactory) { + // This is probably a factory created by ReactDOM we unwrap it to get to + // the underlying string type. It shouldn't have been passed here so we + // warn. + if (__DEV__) { + warnForNonLegacyFactory(type); + } + args = Array.prototype.slice.call(arguments, 0); + args[0] = type.type; + return createDescriptor.apply(this, args); + } + if (type.isReactLegacyFactory) { // This is probably a legacy factory created by ReactCompositeComponent. // We unwrap it to get to the underlying class. @@ -152,7 +184,7 @@ ReactLegacyDescriptorFactory.wrapCreateDescriptor = function(createDescriptor) { // future proofs unit testing that assume that these are classes. type.type._mockedReactClassConstructor = type; } - var args = Array.prototype.slice.call(arguments, 0); + args = Array.prototype.slice.call(arguments, 0); args[0] = type.type; return createDescriptor.apply(this, args); } @@ -170,7 +202,7 @@ ReactLegacyDescriptorFactory.wrapCreateDescriptor = function(createDescriptor) { ReactLegacyDescriptorFactory.wrapFactory = function(factory) { invariant( - ReactDescriptor.isValidFactory(factory), + typeof factory === 'function', 'This is suppose to accept a descriptor factory' ); var legacyDescriptorFactory = function(config, children) { @@ -186,6 +218,22 @@ ReactLegacyDescriptorFactory.wrapFactory = function(factory) { return legacyDescriptorFactory; }; +// This is used to mark a factory that will remain. E.g. we're allowed to call +// it as a function. However, you're not suppose to pass it to createElement +// or createFactory, so it will warn you if you do. +ReactLegacyDescriptorFactory.markNonLegacyFactory = function(factory) { + factory.isReactNonLegacyFactory = NON_LEGACY_MARKER; + return factory; +}; + +// Checks if a factory function is actually a legacy factory pretending to +// be a class. +ReactLegacyDescriptorFactory.isValidFactory = function(factory) { + // TODO: This will be removed and moved into a class validator or something. + return typeof factory === 'function' && + factory.isReactLegacyFactory === LEGACY_MARKER; +}; + ReactLegacyDescriptorFactory._isLegacyCallWarningEnabled = true; module.exports = ReactLegacyDescriptorFactory; diff --git a/src/test/ReactTestUtils.js b/src/test/ReactTestUtils.js index ee8ffad184..1a426f1aa8 100644 --- a/src/test/ReactTestUtils.js +++ b/src/test/ReactTestUtils.js @@ -23,7 +23,6 @@ var EventPluginHub = require('EventPluginHub'); var EventPropagators = require('EventPropagators'); var React = require('React'); var ReactDescriptor = require('ReactDescriptor'); -var ReactDOM = require('ReactDOM'); var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter'); var ReactMount = require('ReactMount'); var ReactTextComponent = require('ReactTextComponent'); @@ -242,7 +241,7 @@ var ReactTestUtils = { var ConvenienceConstructor = React.createClass({ render: function() { return React.createElement( - ReactDOM[mockTagName], // TODO: Replace this with just a string + mockTagName, null, this.props.children ); From 8f1657bba618846b7a111a2caee855bf59145c5a Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 7 Oct 2014 13:41:51 -0700 Subject: [PATCH 008/113] Renamed Descriptor -> Element We've decided on a new naming convention for ReactDescriptor. It's now called ReactElement, which is a subset of the ReactNode union type. --- src/browser/ReactDOM.js | 16 +-- src/browser/ReactTextComponent.js | 4 +- src/browser/__tests__/ReactDOM-test.js | 8 +- src/browser/server/ReactServerRendering.js | 6 +- src/browser/ui/React.js | 30 ++-- src/browser/ui/ReactDOMComponent.js | 26 ++-- src/browser/ui/ReactMount.js | 36 ++--- .../ui/__tests__/ReactDOMComponent-test.js | 4 +- src/browser/ui/__tests__/ReactMount-test.js | 4 +- .../ui/dom/components/ReactDOMButton.js | 4 +- src/browser/ui/dom/components/ReactDOMForm.js | 4 +- src/browser/ui/dom/components/ReactDOMImg.js | 4 +- .../ui/dom/components/ReactDOMInput.js | 4 +- .../ui/dom/components/ReactDOMOption.js | 4 +- .../ui/dom/components/ReactDOMSelect.js | 4 +- .../ui/dom/components/ReactDOMTextarea.js | 4 +- .../dom/components/createFullPageComponent.js | 4 +- src/core/ReactComponent.js | 100 ++++++------- src/core/ReactCompositeComponent.js | 100 ++++++------- .../{ReactDescriptor.js => ReactElement.js} | 58 ++++---- ...rValidator.js => ReactElementValidator.js} | 34 ++--- src/core/ReactEmptyComponent.js | 4 +- ...acyDescriptor.js => ReactLegacyElement.js} | 42 +++--- src/core/ReactMultiChild.js | 10 +- src/core/ReactPropTransferer.js | 20 +-- src/core/ReactPropTypes.js | 6 +- src/core/__tests__/ReactComponent-test.js | 4 +- .../__tests__/ReactComponentLifeCycle-test.js | 8 +- .../__tests__/ReactCompositeComponent-test.js | 2 +- src/core/__tests__/ReactDescriptor-test.js | 134 +++++++++--------- src/core/instantiateReactComponent.js | 45 +++--- src/core/shouldUpdateReactComponent.js | 18 +-- src/test/ReactTestUtils.js | 22 +-- src/test/reactComponentExpect.js | 6 +- src/utils/cloneWithProps.js | 6 +- src/utils/onlyChild.js | 4 +- src/utils/traverseAllChildren.js | 4 +- 37 files changed, 396 insertions(+), 397 deletions(-) rename src/core/{ReactDescriptor.js => ReactElement.js} (77%) rename src/core/{ReactDescriptorValidator.js => ReactElementValidator.js} (90%) rename src/core/{ReactLegacyDescriptor.js => ReactLegacyElement.js} (84%) diff --git a/src/browser/ReactDOM.js b/src/browser/ReactDOM.js index 9d88b7eb62..280ad76a75 100644 --- a/src/browser/ReactDOM.js +++ b/src/browser/ReactDOM.js @@ -19,26 +19,26 @@ "use strict"; -var ReactDescriptor = require('ReactDescriptor'); -var ReactDescriptorValidator = require('ReactDescriptorValidator'); -var ReactLegacyDescriptor = require('ReactLegacyDescriptor'); +var ReactElement = require('ReactElement'); +var ReactElementValidator = require('ReactElementValidator'); +var ReactLegacyElement = require('ReactLegacyElement'); var mapObject = require('mapObject'); /** - * Create a factory that creates HTML tag descriptors. + * Create a factory that creates HTML tag elements. * * @param {string} tag Tag name (e.g. `div`). * @private */ function createDOMFactory(tag) { if (__DEV__) { - return ReactLegacyDescriptor.markNonLegacyFactory( - ReactDescriptorValidator.createFactory(tag) + return ReactLegacyElement.markNonLegacyFactory( + ReactElementValidator.createFactory(tag) ); } - return ReactLegacyDescriptor.markNonLegacyFactory( - ReactDescriptor.createFactory(tag) + return ReactLegacyElement.markNonLegacyFactory( + ReactElement.createFactory(tag) ); } diff --git a/src/browser/ReactTextComponent.js b/src/browser/ReactTextComponent.js index ce4222c51f..25cdd6e1bf 100644 --- a/src/browser/ReactTextComponent.js +++ b/src/browser/ReactTextComponent.js @@ -22,7 +22,7 @@ var DOMPropertyOperations = require('DOMPropertyOperations'); var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin'); var ReactComponent = require('ReactComponent'); -var ReactDescriptor = require('ReactDescriptor'); +var ReactElement = require('ReactElement'); var escapeTextForBrowser = require('escapeTextForBrowser'); var mixInto = require('mixInto'); @@ -105,7 +105,7 @@ mixInto(ReactTextComponent, { var ReactTextComponentFactory = function(text) { // Bypass validation and configuration - return new ReactDescriptor(ReactTextComponent, null, null, null, null, text); + return new ReactElement(ReactTextComponent, null, null, null, null, text); }; ReactTextComponentFactory.type = ReactTextComponent; diff --git a/src/browser/__tests__/ReactDOM-test.js b/src/browser/__tests__/ReactDOM-test.js index aa3458ef41..b0cc1e9a52 100644 --- a/src/browser/__tests__/ReactDOM-test.js +++ b/src/browser/__tests__/ReactDOM-test.js @@ -122,8 +122,8 @@ describe('ReactDOM', function() { it('allow React.DOM factories to be called without warnings', function() { spyOn(console, 'warn'); - var descriptor = React.DOM.div(); - expect(descriptor.type).toBe('div'); + var element = React.DOM.div(); + expect(element.type).toBe('div'); expect(console.warn.argsForCall.length).toBe(0); }); @@ -139,8 +139,8 @@ describe('ReactDOM', function() { it('warns but allow dom factories to be used in createElement', function() { spyOn(console, 'warn'); - var descriptor = React.createElement(React.DOM.div); - expect(descriptor.type).toBe('div'); + var element = React.createElement(React.DOM.div); + expect(element.type).toBe('div'); expect(console.warn.argsForCall.length).toBe(1); expect(console.warn.argsForCall[0][0]).toContain( 'Do not pass React.DOM.div' diff --git a/src/browser/server/ReactServerRendering.js b/src/browser/server/ReactServerRendering.js index d0beb51d41..5c07694263 100644 --- a/src/browser/server/ReactServerRendering.js +++ b/src/browser/server/ReactServerRendering.js @@ -18,7 +18,7 @@ */ "use strict"; -var ReactDescriptor = require('ReactDescriptor'); +var ReactElement = require('ReactElement'); var ReactInstanceHandles = require('ReactInstanceHandles'); var ReactMarkupChecksum = require('ReactMarkupChecksum'); var ReactServerRenderingTransaction = @@ -33,7 +33,7 @@ var invariant = require('invariant'); */ function renderComponentToString(component) { invariant( - ReactDescriptor.isValidDescriptor(component), + ReactElement.isValidElement(component), 'renderComponentToString(): You must pass a valid ReactComponent.' ); @@ -65,7 +65,7 @@ function renderComponentToString(component) { */ function renderComponentToStaticMarkup(component) { invariant( - ReactDescriptor.isValidDescriptor(component), + ReactElement.isValidElement(component), 'renderComponentToStaticMarkup(): You must pass a valid ReactComponent.' ); diff --git a/src/browser/ui/React.js b/src/browser/ui/React.js index e0d6c9bad4..bcf2b38f27 100644 --- a/src/browser/ui/React.js +++ b/src/browser/ui/React.js @@ -29,13 +29,13 @@ var ReactComponent = require('ReactComponent'); var ReactCompositeComponent = require('ReactCompositeComponent'); var ReactContext = require('ReactContext'); var ReactCurrentOwner = require('ReactCurrentOwner'); -var ReactDescriptor = require('ReactDescriptor'); -var ReactDescriptorValidator = require('ReactDescriptorValidator'); +var ReactElement = require('ReactElement'); +var ReactElementValidator = require('ReactElementValidator'); var ReactDOM = require('ReactDOM'); var ReactDOMComponent = require('ReactDOMComponent'); var ReactDefaultInjection = require('ReactDefaultInjection'); var ReactInstanceHandles = require('ReactInstanceHandles'); -var ReactLegacyDescriptor = require('ReactLegacyDescriptor'); +var ReactLegacyElement = require('ReactLegacyElement'); var ReactMount = require('ReactMount'); var ReactMultiChild = require('ReactMultiChild'); var ReactPerf = require('ReactPerf'); @@ -47,19 +47,19 @@ var onlyChild = require('onlyChild'); ReactDefaultInjection.inject(); -var createDescriptor = ReactDescriptor.createDescriptor; -var createFactory = ReactDescriptor.createFactory; +var createElement = ReactElement.createElement; +var createFactory = ReactElement.createFactory; if (__DEV__) { - createDescriptor = ReactDescriptorValidator.createDescriptor; - createFactory = ReactDescriptorValidator.createFactory; + createElement = ReactElementValidator.createElement; + createFactory = ReactElementValidator.createFactory; } -// TODO: Drop legacy descriptors once classes no longer export these factories -createDescriptor = ReactLegacyDescriptor.wrapCreateDescriptor( - createDescriptor +// TODO: Drop legacy elements once classes no longer export these factories +createElement = ReactLegacyElement.wrapCreateElement( + createElement ); -createFactory = ReactLegacyDescriptor.wrapCreateFactory( +createFactory = ReactLegacyElement.wrapCreateFactory( createFactory ); @@ -76,8 +76,8 @@ var React = { EventPluginUtils.useTouchEvents = shouldUseTouch; }, createClass: ReactCompositeComponent.createClass, - createDescriptor: createDescriptor, // deprecated, will be removed next week - createElement: createDescriptor, + createDescriptor: createElement, // deprecated, will be removed next week + createElement: createElement, createFactory: createFactory, constructAndRenderComponent: ReactMount.constructAndRenderComponent, constructAndRenderComponentByID: ReactMount.constructAndRenderComponentByID, @@ -90,8 +90,8 @@ var React = { renderComponentToStaticMarkup: ReactServerRendering.renderComponentToStaticMarkup, unmountComponentAtNode: ReactMount.unmountComponentAtNode, - isValidClass: ReactLegacyDescriptor.isValidFactory, - isValidComponent: ReactDescriptor.isValidDescriptor, + isValidClass: ReactLegacyElement.isValidFactory, + isValidComponent: ReactElement.isValidElement, withContext: ReactContext.withContext, __internals: { Component: ReactComponent, diff --git a/src/browser/ui/ReactDOMComponent.js b/src/browser/ui/ReactDOMComponent.js index 3436e4c979..cbbe776d3d 100644 --- a/src/browser/ui/ReactDOMComponent.js +++ b/src/browser/ui/ReactDOMComponent.js @@ -260,22 +260,22 @@ ReactDOMComponent.Mixin = { return ''; }, - receiveComponent: function(nextDescriptor, transaction) { - if (nextDescriptor === this._descriptor && - nextDescriptor._owner != null) { - // Since descriptors are immutable after the owner is rendered, + receiveComponent: function(nextElement, transaction) { + if (nextElement === this._currentElement && + nextElement._owner != null) { + // Since elements are immutable after the owner is rendered, // we can do a cheap identity compare here to determine if this is a // superfluous reconcile. It's possible for state to be mutable but such // change should trigger an update of the owner which would recreate - // the descriptor. We explicitly check for the existence of an owner since - // it's possible for a descriptor created outside a composite to be + // the element. We explicitly check for the existence of an owner since + // it's possible for a element created outside a composite to be // deeply mutated and reused. return; } ReactComponent.Mixin.receiveComponent.call( this, - nextDescriptor, + nextElement, transaction ); }, @@ -285,22 +285,22 @@ ReactDOMComponent.Mixin = { * attached to the DOM. Reconciles the root DOM node, then recurses. * * @param {ReactReconcileTransaction} transaction - * @param {ReactDescriptor} prevDescriptor + * @param {ReactElement} prevElement * @internal * @overridable */ updateComponent: ReactPerf.measure( 'ReactDOMComponent', 'updateComponent', - function(transaction, prevDescriptor) { - assertValidProps(this._descriptor.props); + function(transaction, prevElement) { + assertValidProps(this._currentElement.props); ReactComponent.Mixin.updateComponent.call( this, transaction, - prevDescriptor + prevElement ); - this._updateDOMProperties(prevDescriptor.props, transaction); - this._updateDOMChildren(prevDescriptor.props, transaction); + this._updateDOMProperties(prevElement.props, transaction); + this._updateDOMChildren(prevElement.props, transaction); } ), diff --git a/src/browser/ui/ReactMount.js b/src/browser/ui/ReactMount.js index a5acf90134..a0dc478d12 100644 --- a/src/browser/ui/ReactMount.js +++ b/src/browser/ui/ReactMount.js @@ -21,8 +21,8 @@ var DOMProperty = require('DOMProperty'); var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter'); var ReactCurrentOwner = require('ReactCurrentOwner'); -var ReactDescriptor = require('ReactDescriptor'); -var ReactLegacyDescriptor = require('ReactLegacyDescriptor'); +var ReactElement = require('ReactElement'); +var ReactLegacyElement = require('ReactLegacyElement'); var ReactInstanceHandles = require('ReactInstanceHandles'); var ReactPerf = require('ReactPerf'); @@ -33,8 +33,8 @@ var invariant = require('invariant'); var shouldUpdateReactComponent = require('shouldUpdateReactComponent'); var warning = require('warning'); -var createDescriptor = ReactLegacyDescriptor.wrapCreateDescriptor( - ReactDescriptor.createDescriptor +var createElement = ReactLegacyElement.wrapCreateElement( + ReactElement.createElement ); var SEPARATOR = ReactInstanceHandles.SEPARATOR; @@ -335,24 +335,24 @@ var ReactMount = { * perform an update on it and only mutate the DOM as necessary to reflect the * latest React component. * - * @param {ReactDescriptor} nextDescriptor Component descriptor to render. + * @param {ReactElement} nextElement Component element to render. * @param {DOMElement} container DOM element to render into. * @param {?function} callback function triggered on completion * @return {ReactComponent} Component instance rendered in `container`. */ - renderComponent: function(nextDescriptor, container, callback) { + renderComponent: function(nextElement, container, callback) { invariant( - ReactDescriptor.isValidDescriptor(nextDescriptor), - 'renderComponent(): Invalid component descriptor.%s', + ReactElement.isValidElement(nextElement), + 'renderComponent(): Invalid component element.%s', ( - typeof nextDescriptor === 'string' ? + typeof nextElement === 'string' ? ' Instead of passing an element string, make sure to instantiate ' + 'it by passing it to React.createElement.' : - ReactLegacyDescriptor.isValidFactory(nextDescriptor) ? + ReactLegacyElement.isValidFactory(nextElement) ? ' Instead of passing a component class, make sure to instantiate ' + 'it by passing it to React.createElement.' : - // Check if it quacks like a descriptor - typeof nextDescriptor.props !== "undefined" ? + // Check if it quacks like a element + typeof nextElement.props !== "undefined" ? ' This may be caused by unintentionally loading two independent ' + 'copies of React.' : '' @@ -362,11 +362,11 @@ var ReactMount = { var prevComponent = instancesByReactRootID[getReactRootID(container)]; if (prevComponent) { - var prevDescriptor = prevComponent._descriptor; - if (shouldUpdateReactComponent(prevDescriptor, nextDescriptor)) { + var prevElement = prevComponent._currentElement; + if (shouldUpdateReactComponent(prevElement, nextElement)) { return ReactMount._updateRootComponent( prevComponent, - nextDescriptor, + nextElement, container, callback ); @@ -382,7 +382,7 @@ var ReactMount = { var shouldReuseMarkup = containerHasReactMarkup && !prevComponent; var component = ReactMount._renderNewRootComponent( - nextDescriptor, + nextElement, container, shouldReuseMarkup ); @@ -400,8 +400,8 @@ var ReactMount = { * @return {ReactComponent} Component instance rendered in `container`. */ constructAndRenderComponent: function(constructor, props, container) { - var descriptor = createDescriptor(constructor, props); - return ReactMount.renderComponent(descriptor, container); + var element = createElement(constructor, props); + return ReactMount.renderComponent(element, container); }, /** diff --git a/src/browser/ui/__tests__/ReactDOMComponent-test.js b/src/browser/ui/__tests__/ReactDOMComponent-test.js index 8eb0e105a6..3da6798f7a 100644 --- a/src/browser/ui/__tests__/ReactDOMComponent-test.js +++ b/src/browser/ui/__tests__/ReactDOMComponent-test.js @@ -318,8 +318,8 @@ describe('ReactDOMComponent', function() { var ReactDOMComponent = require('ReactDOMComponent'); var ReactReconcileTransaction = require('ReactReconcileTransaction'); - var StubNativeComponent = function(descriptor) { - ReactComponent.Mixin.construct.call(this, descriptor); + var StubNativeComponent = function(element) { + ReactComponent.Mixin.construct.call(this, element); }; mixInto(StubNativeComponent, ReactComponent.Mixin); mixInto(StubNativeComponent, ReactDOMComponent.Mixin); diff --git a/src/browser/ui/__tests__/ReactMount-test.js b/src/browser/ui/__tests__/ReactMount-test.js index 2b5fa5cd09..473c87672c 100644 --- a/src/browser/ui/__tests__/ReactMount-test.js +++ b/src/browser/ui/__tests__/ReactMount-test.js @@ -42,7 +42,7 @@ describe('ReactMount', function() { expect(function() { ReactTestUtils.renderIntoDocument('div'); }).toThrow( - 'Invariant Violation: renderComponent(): Invalid component descriptor. ' + + 'Invariant Violation: renderComponent(): Invalid component element. ' + 'Instead of passing an element string, make sure to instantiate it ' + 'by passing it to React.createElement.' ); @@ -57,7 +57,7 @@ describe('ReactMount', function() { expect(function() { ReactTestUtils.renderIntoDocument(Component); }).toThrow( - 'Invariant Violation: renderComponent(): Invalid component descriptor. ' + + 'Invariant Violation: renderComponent(): Invalid component element. ' + 'Instead of passing a component class, make sure to instantiate it ' + 'by passing it to React.createElement.' ); diff --git a/src/browser/ui/dom/components/ReactDOMButton.js b/src/browser/ui/dom/components/ReactDOMButton.js index d9c07a78db..bce5ea584b 100644 --- a/src/browser/ui/dom/components/ReactDOMButton.js +++ b/src/browser/ui/dom/components/ReactDOMButton.js @@ -21,13 +21,13 @@ var AutoFocusMixin = require('AutoFocusMixin'); var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin'); var ReactCompositeComponent = require('ReactCompositeComponent'); -var ReactDescriptor = require('ReactDescriptor'); +var ReactElement = require('ReactElement'); var ReactDOM = require('ReactDOM'); var keyMirror = require('keyMirror'); // Store a reference to the