diff --git a/src/core/ReactCompositeComponent.js b/src/core/ReactCompositeComponent.js index 9229fe66c7..a419ea8c21 100644 --- a/src/core/ReactCompositeComponent.js +++ b/src/core/ReactCompositeComponent.js @@ -20,6 +20,7 @@ var ReactComponent = require('ReactComponent'); var ReactCurrentOwner = require('ReactCurrentOwner'); +var ReactErrorUtils = require('ReactErrorUtils'); var ReactOwner = require('ReactOwner'); var ReactPerf = require('ReactPerf'); var ReactPropTransferer = require('ReactPropTransferer'); @@ -877,7 +878,10 @@ var ReactCompositeComponentMixin = { continue; } var method = this.__reactAutoBindMap[autoBindKey]; - this[autoBindKey] = this._bindAutoBindMethod(method); + this[autoBindKey] = ReactErrorUtils.guard( + this._bindAutoBindMethod(method), + this.constructor.displayName + '.' + autoBindKey + ); } }, diff --git a/src/core/__tests__/ReactCompositeComponentError-test.js b/src/core/__tests__/ReactCompositeComponentError-test.js new file mode 100644 index 0000000000..11cdd96671 --- /dev/null +++ b/src/core/__tests__/ReactCompositeComponentError-test.js @@ -0,0 +1,46 @@ +/** + * 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. + * + * @jsx React.DOM + * @emails react-core + */ + +"use strict"; + +var React = require('React'); +var ReactTestUtils = require('ReactTestUtils'); +var ReactErrorUtils; + +describe('ReactCompositeComponent-error', function() { + + beforeEach(function() { + ReactErrorUtils = require('ReactErrorUtils'); + }); + + it('should be passed the component and method name', function() { + var Component = React.createClass({ + someHandler: function() {}, + render: function() { + return
; + } + }); + + var instance = ; + ReactTestUtils.renderIntoDocument(instance); + expect(ReactErrorUtils.guard.mock.calls[0][1]) + .toEqual('Component.someHandler'); + }); + +}); diff --git a/src/vendor/stubs/ReactErrorUtils.js b/src/vendor/stubs/ReactErrorUtils.js new file mode 100644 index 0000000000..59c9bb4d97 --- /dev/null +++ b/src/vendor/stubs/ReactErrorUtils.js @@ -0,0 +1,44 @@ +/** + * 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. + * + * @providesModule ReactErrorUtils + * @typechecks + */ + +var ReactErrorUtils = { + /** + * Creates a guarded version of a function. This is supposed to make debugging + * of event handlers easier. This implementation provides only basic error + * logging and re-throws the error. + * + * @param {function} func Function to be executed + * @param {string} name The name of the guard + * @return {function} + */ + guard: function(func, name) { + return function guarded() { + try { + return func.apply(this, arguments); + } catch(ex) { + if (__DEV__) { + console.error(name + ': ' + ex.message); + } + throw ex; + } + }; + } +}; + +module.exports = ReactErrorUtils;