mirror of
https://github.com/facebook/react.git
synced 2026-02-23 20:23:02 +00:00
Validate propTypes, contextTypes, childContextTypes
who watches the watchmen?
This commit is contained in:
committed by
Paul O’Shannessy
parent
fcfe516a2e
commit
351dcfed01
@@ -26,6 +26,7 @@ var ReactOwner = require('ReactOwner');
|
||||
var ReactPerf = require('ReactPerf');
|
||||
var ReactPropTransferer = require('ReactPropTransferer');
|
||||
var ReactPropTypeLocations = require('ReactPropTypeLocations');
|
||||
var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');
|
||||
var ReactUpdates = require('ReactUpdates');
|
||||
|
||||
var invariant = require('invariant');
|
||||
@@ -319,16 +320,46 @@ var RESERVED_SPEC_KEYS = {
|
||||
}
|
||||
},
|
||||
childContextTypes: function(Constructor, childContextTypes) {
|
||||
validateTypeDef(
|
||||
Constructor,
|
||||
childContextTypes,
|
||||
ReactPropTypeLocations.childContext
|
||||
);
|
||||
Constructor.childContextTypes = childContextTypes;
|
||||
},
|
||||
contextTypes: function(Constructor, contextTypes) {
|
||||
validateTypeDef(
|
||||
Constructor,
|
||||
contextTypes,
|
||||
ReactPropTypeLocations.context
|
||||
);
|
||||
Constructor.contextTypes = contextTypes;
|
||||
},
|
||||
propTypes: function(Constructor, propTypes) {
|
||||
validateTypeDef(
|
||||
Constructor,
|
||||
propTypes,
|
||||
ReactPropTypeLocations.prop
|
||||
);
|
||||
Constructor.propTypes = propTypes;
|
||||
}
|
||||
};
|
||||
|
||||
function validateTypeDef(Constructor, typeDef, location) {
|
||||
for (var propName in typeDef) {
|
||||
if (typeDef.hasOwnProperty(propName)) {
|
||||
invariant(
|
||||
typeof typeDef[propName] == 'function',
|
||||
'%s: %s type `%s` is invalid; it must be a function, usually from ' +
|
||||
'React.PropTypes.',
|
||||
Constructor.displayName || 'ReactCompositeComponent',
|
||||
ReactPropTypeLocationNames[location],
|
||||
propName
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateMethodOverride(proto, name) {
|
||||
var specPolicy = ReactCompositeComponentInterface[name];
|
||||
|
||||
@@ -790,9 +821,8 @@ var ReactCompositeComponentMixin = {
|
||||
_checkPropTypes: function(propTypes, props, location) {
|
||||
var componentName = this.constructor.displayName;
|
||||
for (var propName in propTypes) {
|
||||
var checkProp = propTypes[propName];
|
||||
if (checkProp) {
|
||||
checkProp(props, propName, componentName, location);
|
||||
if (propTypes.hasOwnProperty(propName)) {
|
||||
propTypes[propName](props, propName, componentName, location);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
31
src/core/ReactPropTypeLocationNames.js
Normal file
31
src/core/ReactPropTypeLocationNames.js
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 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 ReactPropTypeLocationNames
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
var ReactPropTypeLocationNames = {};
|
||||
|
||||
if (__DEV__) {
|
||||
ReactPropTypeLocationNames = {
|
||||
prop: 'prop',
|
||||
context: 'context',
|
||||
childContext: 'child context'
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = ReactPropTypeLocationNames;
|
||||
@@ -18,19 +18,11 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');
|
||||
|
||||
var createObjectFrom = require('createObjectFrom');
|
||||
var invariant = require('invariant');
|
||||
|
||||
var ReactPropTypeLocationNames = {};
|
||||
|
||||
if (__DEV__) {
|
||||
ReactPropTypeLocationNames = {
|
||||
prop: 'prop',
|
||||
context: 'context',
|
||||
childContext: 'child context'
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Collection of methods that allow declaration and validation of props that are
|
||||
* supplied to React components. Example usage:
|
||||
|
||||
@@ -289,6 +289,57 @@ describe('ReactCompositeComponent', function() {
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it('should throw on invalid prop types', function() {
|
||||
expect(function() {
|
||||
React.createClass({
|
||||
displayName: 'Component',
|
||||
propTypes: {
|
||||
key: null
|
||||
},
|
||||
render: function() {
|
||||
return <span>{this.props.key}</span>;
|
||||
}
|
||||
});
|
||||
}).toThrow(
|
||||
'Invariant Violation: Component: prop type `key` is invalid; ' +
|
||||
'it must be a function, usually from React.PropTypes.'
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw on invalid context types', function() {
|
||||
expect(function() {
|
||||
React.createClass({
|
||||
displayName: 'Component',
|
||||
contextTypes: {
|
||||
key: null
|
||||
},
|
||||
render: function() {
|
||||
return <span>{this.props.key}</span>;
|
||||
}
|
||||
});
|
||||
}).toThrow(
|
||||
'Invariant Violation: Component: context type `key` is invalid; ' +
|
||||
'it must be a function, usually from React.PropTypes.'
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw on invalid child context types', function() {
|
||||
expect(function() {
|
||||
React.createClass({
|
||||
displayName: 'Component',
|
||||
childContextTypes: {
|
||||
key: null
|
||||
},
|
||||
render: function() {
|
||||
return <span>{this.props.key}</span>;
|
||||
}
|
||||
});
|
||||
}).toThrow(
|
||||
'Invariant Violation: Component: child context type `key` is invalid; ' +
|
||||
'it must be a function, usually from React.PropTypes.'
|
||||
);
|
||||
});
|
||||
|
||||
it('should not allow `forceUpdate` on unmounted components', function() {
|
||||
var container = document.createElement('div');
|
||||
document.documentElement.appendChild(container);
|
||||
|
||||
Reference in New Issue
Block a user