From 52e622f1db79d2c871101af58f744e58f435d4ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Wed, 17 Jul 2013 16:45:38 -0700 Subject: [PATCH 01/35] Version bump for 0.5.0 development --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 24c779d48d..58cf9b810e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-tools", - "version": "0.4.0", + "version": "0.5.0-alpha", "keywords": [ "react", "jsx", From fd2125ee94f5bf30f7b5488cededbb0d1170574f Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 17 Jul 2013 18:32:23 -0400 Subject: [PATCH 02/35] Use getAttribute instead of getAttributeNode in ReactID.rawGetID. Also known as internalGetID, internally. --- src/core/ReactID.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/core/ReactID.js b/src/core/ReactID.js index f658241146..d3a6cfad2b 100644 --- a/src/core/ReactID.js +++ b/src/core/ReactID.js @@ -57,13 +57,7 @@ function getID(node) { } function internalGetID(node) { - if (node && node.getAttributeNode) { - var attributeNode = node.getAttributeNode(ATTR_NAME); - if (attributeNode) { - return attributeNode.value || ''; - } - } - return ''; + return node && node.getAttribute && node.getAttribute(ATTR_NAME) || ''; } /** From 75ce576d3daec14fd0214e33904a288fa319426c Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Wed, 17 Jul 2013 19:56:47 -0700 Subject: [PATCH 03/35] Avoid some innocuous test warnings. This reduces some console.warning spew from `grunt test` output. --- src/core/__tests__/ReactCompositeComponent-test.js | 4 ++++ src/core/__tests__/ReactInstanceHandles-test.js | 5 +++++ src/core/__tests__/refs-test.js | 6 +++++- src/dom/components/__tests__/ReactDOMTextarea-test.js | 11 +++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/core/__tests__/ReactCompositeComponent-test.js b/src/core/__tests__/ReactCompositeComponent-test.js index 28356063ef..b79b06c524 100644 --- a/src/core/__tests__/ReactCompositeComponent-test.js +++ b/src/core/__tests__/ReactCompositeComponent-test.js @@ -134,6 +134,8 @@ describe('ReactCompositeComponent', function() { }); it('should auto bind methods and values correctly', function() { + spyOn(console, 'warn'); + var ComponentClass = React.createClass({ getInitialState: function() { return {valueToReturn: 'hi'}; @@ -168,7 +170,9 @@ describe('ReactCompositeComponent', function() { // Next, prove that once mounted, the scope is bound correctly to the actual // component. ReactTestUtils.renderIntoDocument(instance); + expect(console.warn.argsForCall.length).toBe(0); var explicitlyBound = instance.methodToBeExplicitlyBound.bind(instance); + expect(console.warn.argsForCall.length).toBe(1); var autoBound = instance.methodAutoBound; var explicitlyNotBound = instance.methodExplicitlyNotBound; diff --git a/src/core/__tests__/ReactInstanceHandles-test.js b/src/core/__tests__/ReactInstanceHandles-test.js index b5161547c7..093ae845a5 100644 --- a/src/core/__tests__/ReactInstanceHandles-test.js +++ b/src/core/__tests__/ReactInstanceHandles-test.js @@ -138,6 +138,9 @@ describe('ReactInstanceHandles', function() { ReactID.getID(childNodeB) )).toBe(childNodeB); + spyOn(console, 'error'); + expect(console.error.argsForCall.length).toBe(0); + expect(function() { ReactInstanceHandles.findComponentRoot( parentNode, @@ -148,6 +151,8 @@ describe('ReactInstanceHandles', function() { 'Unable to find element. This probably means the DOM was ' + 'unexpectedly mutated (e.g. by the browser).' ); + + expect(console.error.argsForCall.length).toBe(1); }); }); diff --git a/src/core/__tests__/refs-test.js b/src/core/__tests__/refs-test.js index 193c9554ac..4880c31a4d 100644 --- a/src/core/__tests__/refs-test.js +++ b/src/core/__tests__/refs-test.js @@ -44,7 +44,11 @@ var ClickCounter = React.createClass({ var i; for (i=0; i < this.state.count; i++) { children.push( -
+
); } return ( diff --git a/src/dom/components/__tests__/ReactDOMTextarea-test.js b/src/dom/components/__tests__/ReactDOMTextarea-test.js index 5fbb36a7c6..456a8e63c1 100644 --- a/src/dom/components/__tests__/ReactDOMTextarea-test.js +++ b/src/dom/components/__tests__/ReactDOMTextarea-test.js @@ -62,9 +62,12 @@ describe('ReactDOMTextarea', function() { }); it('should treat children like `defaultValue`', function() { + spyOn(console, 'warn'); + var stub = ; var node = renderTextarea(stub); + expect(console.warn.argsForCall.length).toBe(1); expect(node.value).toBe('giraffe'); // Changing children should do nothing, it functions like `defaultValue`. @@ -73,21 +76,29 @@ describe('ReactDOMTextarea', function() { }); it('should allow numbers as children', function() { + spyOn(console, 'warn'); var node = renderTextarea(); + expect(console.warn.argsForCall.length).toBe(1); expect(node.value).toBe('17'); }); it("should throw with multiple or invalid children", function() { + spyOn(console, 'warn'); + expect(function() { ReactTestUtils.renderIntoDocument( ); }).toThrow(); + expect(console.warn.argsForCall.length).toBe(1); + expect(function() { ReactTestUtils.renderIntoDocument( ); }).toThrow(); + + expect(console.warn.argsForCall.length).toBe(2); }); }); From e6812d7e36c70c430dc6e9198a0fa7549f144f1c Mon Sep 17 00:00:00 2001 From: Pete Hunt Date: Wed, 17 Jul 2013 19:57:00 -0700 Subject: [PATCH 04/35] Add iframe attributes to React These are pretty useful for building apps and stuff. --- src/dom/DefaultDOMPropertyConfig.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dom/DefaultDOMPropertyConfig.js b/src/dom/DefaultDOMPropertyConfig.js index 0ab0a05071..045aad5edc 100644 --- a/src/dom/DefaultDOMPropertyConfig.js +++ b/src/dom/DefaultDOMPropertyConfig.js @@ -38,6 +38,7 @@ var DefaultDOMPropertyConfig = { action: null, ajaxify: MUST_USE_ATTRIBUTE, allowFullScreen: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, + allowTransparency: MUST_USE_ATTRIBUTE, alt: null, autoComplete: null, autoFocus: HAS_BOOLEAN_VALUE, @@ -56,6 +57,7 @@ var DefaultDOMPropertyConfig = { disabled: MUST_USE_PROPERTY | HAS_BOOLEAN_VALUE, draggable: null, encType: null, + frameBorder: MUST_USE_ATTRIBUTE, height: MUST_USE_ATTRIBUTE, hidden: MUST_USE_ATTRIBUTE | HAS_BOOLEAN_VALUE, href: null, From 7ef5172d807de6d461090a563a43428544a11ed0 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 19 Jul 2013 10:58:11 -0400 Subject: [PATCH 05/35] Don't call require("mock-modules").register("test/all", ...). The "test/all" module will never be mocked, nor should it ever need to be reset by `dumpCache`. --- bin/jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/jsx b/bin/jsx index 5e269cda97..aa6ae90ab8 100755 --- a/bin/jsx +++ b/bin/jsx @@ -41,6 +41,7 @@ require("commoner").resolve(function(id) { return context.getProvidedP().then(function(idToPath) { if (id !== "mock-modules" && id !== "mocks" && + id !== "test/all" && idToPath.hasOwnProperty("mock-modules")) { return source + '\nrequire("mock-modules").register(' + JSON.stringify(id) + ', module);\n'; From 5beb48114567988b7abcedc74ddfaa7d718761d7 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 19 Jul 2013 10:40:43 -0400 Subject: [PATCH 06/35] Abandon '; - }).join("") + inner + ""; + /^(\s*)ENABLE_TESTS_HERE/m, + function(placeholder, leadingSpace) { + return leadingSpace + tests.map(function(testID) { + return "harness.enableTest(" + JSON.stringify(testID) + ");"; + }).join("\n" + leadingSpace); } ); @@ -63,9 +62,6 @@ server.listen(port, function(req, res) { file = "../build/" + file; break; - case "frame.html": - break; - case "": default: file = "index.html"; From 507e58ed9661bbfd7e89ad19460d3c80a6cf572e Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 19 Jul 2013 11:02:32 -0400 Subject: [PATCH 07/35] Pull in my rewritten Function.prototype.bind polyfill from upstream. We don't sync upstream polyfills (because we don't have a story for how they would be used), so this needs to be updated manually. Sacrificed some negligible performance optimizations to reduce the number of different cases from four to one. It's important to test this implementation in PhantomJS, since that's the only browser that I know of where built-in functions sometimes do not have a `.prototype`. --- src/test/all.js | 46 +++++++++++++++------------------------------- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/src/test/all.js b/src/test/all.js index a94a58062d..a5c58f4bab 100644 --- a/src/test/all.js +++ b/src/test/all.js @@ -12,40 +12,24 @@ if (!Fp.bind) { Fp.bind = function(context) { var func = this; var args = slice.call(arguments, 1); - var bound; - if (func.prototype) { - if (args.length > 0) { - bound = function() { - return func.apply( - !(this instanceof func) && context || this, - args.concat(slice.call(arguments)) - ); - }; - } else { - bound = function() { - return func.apply( - !(this instanceof func) && context || this, - arguments - ); - }; - } - - bound.prototype = Object.create(func.prototype); - - } else if (args.length > 0) { - bound = function() { - return func.apply( - context || this, - args.concat(slice.call(arguments)) - ); - }; - } else { - bound = function() { - return func.apply(context || this, arguments); - }; + function bound() { + var invokedAsConstructor = func.prototype && (this instanceof func); + return func.apply( + // Ignore the context parameter when invoking the bound function + // as a constructor. Note that this includes not only constructor + // invocations using the new keyword but also calls to base class + // constructors such as BaseClass.call(this, ...) or super(...). + !invokedAsConstructor && context || this, + args.concat(slice.call(arguments)) + ); } + // The bound function must share the .prototype of the unbound + // function so that any object created by one constructor will count + // as an instance of both constructors. + bound.prototype = func.prototype; + return bound; }; } From bf275a909748a1e64ff06934ce0b6f8f285b86f7 Mon Sep 17 00:00:00 2001 From: Jamie Wong Date: Fri, 19 Jul 2013 12:33:54 -0400 Subject: [PATCH 08/35] Docs Typo Fix: s/distinciton/distinction --- docs/docs/04-multiple-components.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/04-multiple-components.md b/docs/docs/04-multiple-components.md index 82e8b73ec1..ecc7c9baab 100644 --- a/docs/docs/04-multiple-components.md +++ b/docs/docs/04-multiple-components.md @@ -62,7 +62,7 @@ React.renderComponent( In the above example, instances of `Avatar` *own* instances of `ProfilePic` and `ProfileLink`. In React, **an owner is the component that sets the `props` of other components**. More formally, if a component `X` is created in component `Y`'s `render()` method, it is said that `X` is *owned by* `Y`. As discussed earlier, a component cannot mutate its `props` — they are always consistent with what its owner sets them to. This key property leads to UIs that are guaranteed to be consistent. -It's important to draw a distinciton between the owner-ownee relationship and the parent-child relationship. The owner-ownee relationship is specific to React, while the parent-child relationship is simply the one you know and love from the DOM. In the example above, `Avatar` owns the `div`, `ProfilePic` and `ProfileLink` instances, and `div` is the **parent** (but not owner) of the `ProfilePic` and `ProfileLink` instances. +It's important to draw a distinction between the owner-ownee relationship and the parent-child relationship. The owner-ownee relationship is specific to React, while the parent-child relationship is simply the one you know and love from the DOM. In the example above, `Avatar` owns the `div`, `ProfilePic` and `ProfileLink` instances, and `div` is the **parent** (but not owner) of the `ProfilePic` and `ProfileLink` instances. ## Children From 36fbd8d9412c599608888e18b104c820ffaefea4 Mon Sep 17 00:00:00 2001 From: Ben Newman Date: Fri, 19 Jul 2013 13:53:15 -0400 Subject: [PATCH 09/35] After each test, remove any stray nodes added to the document. This was not necessary when we were running each test in its own ` + + +## React Presentation + +[Tom Occhino](http://tomocchino.com/) and [Jordan Walke](https://github.com/jordwalke), React developers, did a presentation of React at Facebook Seattle's office. Check out the first 25 minutes for the presentation and the remaining 45 for a Q&A. I highly recommend you watching this video. + +
+ + +## Docs + +[Pete Hunt](http://www.petehunt.net/) rewrote the entirety of the docs for v0.4. The goal was to add more explanation about why we built React and what the best practices are. + +> Guides +> +> * [Why React?](/react/docs/why-react.html) +> * [Displaying Data](/react/docs/displaying-data.html) +> * [JSX in Depth](/react/docs/jsx-in-depth.html) +> * [JSX Gotchas](/react/docs/jsx-gotchas.html) +> * [Interactivity and Dynamic UIs](/react/docs/interactivity-and-dynamic-uis.html) +> * [Multiple Components](/react/docs/multiple-components.html) +> * [Reusable Components](/react/docs/reusable-components.html) +> * [Forms](/react/docs/forms.html) +> * [Working With the Browser](/react/docs/working-with-the-browser.html) +> * [More About Refs](/react/docs/more-about-refs.html) +> * [Tooling integration](/react/docs/tooling-integration.html) +> * [Reference](/react/docs/reference.html) From d1c5cda93f9b912777a7c45ecd071f14aef947e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Tue, 23 Jul 2013 10:55:04 -0700 Subject: [PATCH 25/35] Use the right home page for react-source gem --- react-source.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react-source.gemspec b/react-source.gemspec index 0e1b619df4..ead889f5bb 100644 --- a/react-source.gemspec +++ b/react-source.gemspec @@ -8,7 +8,7 @@ gemspec = Gem::Specification.new do |s| s.version = package['version'] s.license = 'Apache-2.0' - s.homepage = 'https://github.com/facebook/react.js' + s.homepage = 'https://github.com/facebook/react' s.summary = 'Ruby bridge to JSX & the React JavaScript library.' s.authors = ['Paul O’Shannessy'] From 7f8b2885d9f9feb396896f7d9d6086ac7731cf36 Mon Sep 17 00:00:00 2001 From: Cheng Lou Date: Tue, 23 Jul 2013 11:42:54 -0400 Subject: [PATCH 26/35] fix jquery-bootstrap example bugs Old one had some bugs: - 'x' on modal wasn't showing. - trying to close modal in unmount, but modal had a closing animation. --- examples/jquery-bootstrap/js/app.js | 84 ++++++++++++++--------------- 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/examples/jquery-bootstrap/js/app.js b/examples/jquery-bootstrap/js/app.js index 754eed05fc..b522605705 100644 --- a/examples/jquery-bootstrap/js/app.js +++ b/examples/jquery-bootstrap/js/app.js @@ -7,7 +7,7 @@ var BootstrapButton = React.createClass({ // transferPropsTo() is smart enough to merge classes provided // to this component. return this.transferPropsTo( - + {this.props.children} ); @@ -19,12 +19,18 @@ var BootstrapModal = React.createClass({ // integrate with Bootstrap or jQuery! componentDidMount: function() { // When the component is added, turn it into a modal - $(this.getDOMNode()).modal({backdrop: 'static', keyboard: false}); + $(this.getDOMNode()) + .modal({backdrop: 'static', keyboard: false, show: false}) }, componentWillUnmount: function() { - // And when it's destroyed, hide it. + $(this.getDOMNode()).off('hidden', this.handleHidden); + }, + close: function() { $(this.getDOMNode()).modal('hide'); }, + open: function() { + $(this.getDOMNode()).modal('show'); + }, render: function() { var confirmButton = null; var cancelButton = null; @@ -32,92 +38,84 @@ var BootstrapModal = React.createClass({ if (this.props.confirm) { confirmButton = ( + onClick={this.handleConfirm} + className="btn-primary"> {this.props.confirm} ); } if (this.props.cancel) { cancelButton = ( - + {this.props.cancel} ); } return ( -