@samitouri / QOS-React-2 / commits / a61f4df0b9
Fork 0

The library for web and native user interfaces.

Fix a bunch of problems with implicit autobinding

CommitSyncScript committed Jun 24, 2013 at 16:09 UTC a61f4df0b9b23250a5a59285aad82cf7d82a19b8
2 files changed +23 -27
src/core/ReactCompositeComponent.js
+23 -18
@@ -28,16 +28,18 @@ var keyMirror = require('keyMirror');
28 var merge = require('merge');
29 var mixInto = require('mixInto');
30
31 -var invokedBeforeMount = function() {
32 - invariant(
33 - false,
34 - 'You have invoked a method that is automatically bound, before the ' +
35 - 'instance has been mounted. There is nothing conceptually wrong with ' +
36 - 'this, but since this method will be replaced with a new version once ' +
37 - 'the component is mounted - you should be aware of the fact that this ' +
38 - 'method will soon be replaced.'
39 - );
40 -};
31 +function invokeWithWarning(func) {
32 + return function() {
33 + console && console.warn && console.warn(
34 + 'You have invoked a method that is automatically bound, before the ' +
35 + 'instance has been mounted. There is nothing conceptually wrong with ' +
36 + 'this, but since this method will be replaced with a new version once' +
37 + ' the component is mounted - you should be aware of the fact that ' +
38 + 'this method will soon be replaced.'
39 + );
40 + return func.apply(this, arguments);
41 + };
42 +}
43
44 /**
45 * Policies that describe methods in `ReactCompositeComponentInterface`.
@@ -370,7 +372,10 @@ function mixSpecIntoComponent(Constructor, spec) {
372 proto.__reactAutoBindMap = {};
373 }
374 proto.__reactAutoBindMap[name] = property;
373 - proto[name] = invokedBeforeMount;
375 + proto[name] = property;
376 + if (__DEV__) {
377 + proto[name] = invokeWithWarning(property);
378 + }
379 } else {
380 if (isInherited) {
381 // For methods which are defined more than once, call the existing
@@ -393,13 +398,13 @@ function mixSpecIntoComponent(Constructor, spec) {
398 * @private
399 */
400 function createChainedFunction(one, two) {
396 - return function chainedFunction(a, b, c, d, e, tooMany) {
401 + return function chainedFunction(a, b, c, d, e, f, g, tooMany) {
402 invariant(
403 typeof tooMany === 'undefined',
399 - 'Chained function can only take a maximum of 5 arguments.'
404 + 'Chained function can only take a maximum of 7 arguments.'
405 );
401 - one.call(this, a, b, c, d, e);
402 - two.call(this, a, b, c, d, e);
406 + one.call(this, a, b, c, d, e, f, g);
407 + two.call(this, a, b, c, d, e, f, g);
408 };
409 }
410
@@ -814,12 +819,12 @@ var ReactCompositeComponentMixin = {
819 */
820 _bindAutoBindMethod: function(method) {
821 var component = this;
817 - function autoBound(a, b, c, d, e, tooMany) {
822 + function autoBound(a, b, c, d, e, f, g, tooMany) {
823 invariant(
824 typeof tooMany === 'undefined',
820 - 'React.autoBind(...): Methods can only take a maximum of 5 arguments.'
825 + 'React.autoBind(...): Methods can only take a maximum of 7 arguments.'
826 );
822 - return method.call(component, a, b, c, d, e);
827 + return method.call(component, a, b, c, d, e, f, g);
828 }
829 return autoBound;
830 }
src/core/__tests__/ReactCompositeComponent-test.js
-9
@@ -188,15 +188,6 @@ describe('ReactCompositeComponent', function() {
188 });
189 var instance = <ComponentClass />;
190
191 - // Autobound methods will throw before mounting.
192 - // TODO: We should actually allow component instance methods to be invoked
193 - // before mounting for read-only operations. We would then update this test.
194 - expect(function() {
195 - instance.methodToBeExplicitlyBound.bind(instance)();
196 - }).toThrow();
197 - expect(function() {
198 - instance.methodAutoBound();
199 - }).toThrow();
191 expect(function() {
192 instance.methodExplicitlyNotBound();
193 }).not.toThrow();