From 88c94683d687e28429d08d2aa046755f67e2d70b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Tue, 6 May 2014 09:09:51 -0700 Subject: [PATCH] Revert "Move defaultProps resolution and type validation to the descriptor" This reverts commit ff52e3df00ab7ed1375f46d81c122a614e202bb9. Too many things broke with transferPropsTo --- src/browser/ReactDOM.js | 7 - src/core/ReactCompositeComponent.js | 82 +++---- src/core/ReactDescriptor.js | 215 ++++++++++++---- src/core/ReactDescriptorValidator.js | 283 ---------------------- src/core/__tests__/ReactPropTypes-test.js | 4 +- 5 files changed, 205 insertions(+), 386 deletions(-) delete mode 100644 src/core/ReactDescriptorValidator.js diff --git a/src/browser/ReactDOM.js b/src/browser/ReactDOM.js index 4906cc47d8..32bb9e3b60 100644 --- a/src/browser/ReactDOM.js +++ b/src/browser/ReactDOM.js @@ -20,7 +20,6 @@ "use strict"; var ReactDescriptor = require('ReactDescriptor'); -var ReactDescriptorValidator = require('ReactDescriptorValidator'); var ReactDOMComponent = require('ReactDOMComponent'); var mergeInto = require('mergeInto'); @@ -51,12 +50,6 @@ function createDOMComponentClass(omitClose, tag) { var ConvenienceConstructor = ReactDescriptor.createFactory(Constructor); - if (__DEV__) { - return ReactDescriptorValidator.createFactory( - ConvenienceConstructor - ); - } - return ConvenienceConstructor; } diff --git a/src/core/ReactCompositeComponent.js b/src/core/ReactCompositeComponent.js index 4622314281..372126221c 100644 --- a/src/core/ReactCompositeComponent.js +++ b/src/core/ReactCompositeComponent.js @@ -22,7 +22,6 @@ var ReactComponent = require('ReactComponent'); var ReactContext = require('ReactContext'); var ReactCurrentOwner = require('ReactCurrentOwner'); var ReactDescriptor = require('ReactDescriptor'); -var ReactDescriptorValidator = require('ReactDescriptorValidator'); var ReactEmptyComponent = require('ReactEmptyComponent'); var ReactErrorUtils = require('ReactErrorUtils'); var ReactOwner = require('ReactOwner'); @@ -329,17 +328,18 @@ var ReactCompositeComponentInterface = { * which all other static methods are defined. */ var RESERVED_SPEC_KEYS = { - displayName: function(Constructor, displayName) { - Constructor.displayName = displayName; + displayName: function(ConvenienceConstructor, displayName) { + ConvenienceConstructor.type.displayName = displayName; }, - mixins: function(Constructor, mixins) { + mixins: function(ConvenienceConstructor, mixins) { if (mixins) { for (var i = 0; i < mixins.length; i++) { - mixSpecIntoComponent(Constructor, mixins[i]); + mixSpecIntoComponent(ConvenienceConstructor, mixins[i]); } } }, - childContextTypes: function(Constructor, childContextTypes) { + childContextTypes: function(ConvenienceConstructor, childContextTypes) { + var Constructor = ConvenienceConstructor.type; validateTypeDef( Constructor, childContextTypes, @@ -350,7 +350,8 @@ var RESERVED_SPEC_KEYS = { childContextTypes ); }, - contextTypes: function(Constructor, contextTypes) { + contextTypes: function(ConvenienceConstructor, contextTypes) { + var Constructor = ConvenienceConstructor.type; validateTypeDef( Constructor, contextTypes, @@ -358,21 +359,8 @@ var RESERVED_SPEC_KEYS = { ); Constructor.contextTypes = merge(Constructor.contextTypes, contextTypes); }, - /** - * Special case getDefaultProps which should move into statics but requires - * automatic merging. - */ - getDefaultProps: function(Constructor, getDefaultProps) { - if (Constructor.getDefaultProps) { - Constructor.getDefaultProps = createMergedResultFunction( - Constructor.getDefaultProps, - getDefaultProps - ); - } else { - Constructor.getDefaultProps = getDefaultProps; - } - }, - propTypes: function(Constructor, propTypes) { + propTypes: function(ConvenienceConstructor, propTypes) { + var Constructor = ConvenienceConstructor.type; validateTypeDef( Constructor, propTypes, @@ -380,8 +368,8 @@ var RESERVED_SPEC_KEYS = { ); Constructor.propTypes = merge(Constructor.propTypes, propTypes); }, - statics: function(Constructor, statics) { - mixStaticSpecIntoComponent(Constructor, statics); + statics: function(ConvenienceConstructor, statics) { + mixStaticSpecIntoComponent(ConvenienceConstructor, statics); } }; @@ -449,7 +437,7 @@ function validateLifeCycleOnReplaceState(instance) { * Custom version of `mixInto` which handles policy validation and reserved * specification keys when building `ReactCompositeComponent` classses. */ -function mixSpecIntoComponent(Constructor, spec) { +function mixSpecIntoComponent(ConvenienceConstructor, spec) { invariant( !ReactDescriptor.isValidFactory(spec), 'ReactCompositeComponent: You\'re attempting to ' + @@ -461,6 +449,7 @@ function mixSpecIntoComponent(Constructor, spec) { 'use a component as a mixin. Instead, just use a regular object.' ); + var Constructor = ConvenienceConstructor.type; var proto = Constructor.prototype; for (var name in spec) { var property = spec[name]; @@ -471,7 +460,7 @@ function mixSpecIntoComponent(Constructor, spec) { validateMethodOverride(proto, name); if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) { - RESERVED_SPEC_KEYS[name](Constructor, property); + RESERVED_SPEC_KEYS[name](ConvenienceConstructor, property); } else { // Setup methods on prototype: // The following member methods should not be automatically bound: @@ -532,7 +521,7 @@ function mixSpecIntoComponent(Constructor, spec) { } } -function mixStaticSpecIntoComponent(Constructor, statics) { +function mixStaticSpecIntoComponent(ConvenienceConstructor, statics) { if (!statics) { return; } @@ -542,10 +531,10 @@ function mixStaticSpecIntoComponent(Constructor, statics) { continue; } - var isInherited = name in Constructor; + var isInherited = name in ConvenienceConstructor; var result = property; if (isInherited) { - var existingProperty = Constructor[name]; + var existingProperty = ConvenienceConstructor[name]; var existingType = typeof existingProperty; var propertyType = typeof property; invariant( @@ -558,7 +547,8 @@ function mixStaticSpecIntoComponent(Constructor, statics) { ); result = createChainedFunction(existingProperty, property); } - Constructor[name] = result; + ConvenienceConstructor[name] = result; + ConvenienceConstructor.type[name] = result; } } @@ -733,6 +723,7 @@ var ReactCompositeComponentMixin = { this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING; this.context = this._processContext(this._descriptor._context); + this._defaultProps = this.getDefaultProps ? this.getDefaultProps() : null; this.props = this._processProps(this.props); if (this.__reactAutoBindMap) { @@ -790,6 +781,8 @@ var ReactCompositeComponentMixin = { } this._compositeLifeCycleState = null; + this._defaultProps = null; + this._renderedComponent.unmountComponent(); this._renderedComponent = null; @@ -928,6 +921,12 @@ var ReactCompositeComponentMixin = { */ _processProps: function(newProps) { var props = merge(newProps); + var defaultProps = this._defaultProps; + for (var propName in defaultProps) { + if (typeof props[propName] === 'undefined') { + props[propName] = defaultProps[propName]; + } + } if (__DEV__) { var propTypes = this.constructor.propTypes; if (propTypes) { @@ -946,8 +945,6 @@ var ReactCompositeComponentMixin = { * @private */ _checkPropTypes: function(propTypes, props, location) { - // TODO: Stop validating prop types here and only use the descriptor - // validation. var componentName = this.constructor.displayName; for (var propName in propTypes) { if (propTypes.hasOwnProperty(propName)) { @@ -1313,11 +1310,16 @@ var ReactCompositeComponent = { Constructor.prototype = new ReactCompositeComponentBase(); Constructor.prototype.constructor = Constructor; + var ConvenienceConstructor = ReactDescriptor.createFactory(Constructor); + + // TODO: Move statics off of the convenience constructor. That way the + // factory can be created independently from the main class. + injectedMixins.forEach( - mixSpecIntoComponent.bind(null, Constructor) + mixSpecIntoComponent.bind(null, ConvenienceConstructor) ); - mixSpecIntoComponent(Constructor, spec); + mixSpecIntoComponent(ConvenienceConstructor, spec); invariant( Constructor.prototype.render, @@ -1346,17 +1348,7 @@ var ReactCompositeComponent = { } } - var descriptorFactory = ReactDescriptor.createFactory(Constructor); - - if (__DEV__) { - return ReactDescriptorValidator.createFactory( - descriptorFactory, - Constructor.propTypes, - Constructor.contextTypes - ); - } - - return descriptorFactory; + return ConvenienceConstructor; }, injection: { diff --git a/src/core/ReactDescriptor.js b/src/core/ReactDescriptor.js index cdcaf6930c..0c3cdbf617 100644 --- a/src/core/ReactDescriptor.js +++ b/src/core/ReactDescriptor.js @@ -21,9 +21,165 @@ var ReactContext = require('ReactContext'); var ReactCurrentOwner = require('ReactCurrentOwner'); -var merge = require('merge'); +var monitorCodeUse = require('monitorCodeUse'); var warning = require('warning'); +/** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ +var ownerHasKeyUseWarning = { + 'react_key_warning': {}, + 'react_numeric_key_warning': {} +}; +var ownerHasMonitoredObjectMap = {}; + +var NUMERIC_PROPERTY_REGEX = /^\d+$/; + +/** + * Gets the current owner's displayName for use in warnings. + * + * @internal + * @return {?string} Display name or undefined + */ +function getCurrentOwnerDisplayName() { + var current = ReactCurrentOwner.current; + return current && current.constructor.displayName || undefined; +} + +/** + * Warn if the component doesn't have an explicit key assigned to it. + * This component is in an array. The array could grow and shrink or be + * reordered. All children that haven't already been validated are required to + * have a "key" property assigned to it. + * + * @internal + * @param {ReactComponent} component Component that requires a key. + * @param {*} parentType component's parent's type. + */ +function validateExplicitKey(component, parentType) { + if (component._store.validated || component.props.key != null) { + return; + } + component._store.validated = true; + + warnAndMonitorForKeyUse( + 'react_key_warning', + 'Each child in an array should have a unique "key" prop.', + component, + parentType + ); +} + +/** + * Warn if the key is being defined as an object property but has an incorrect + * value. + * + * @internal + * @param {string} name Property name of the key. + * @param {ReactComponent} component Component that requires a key. + * @param {*} parentType component's parent's type. + */ +function validatePropertyKey(name, component, parentType) { + if (!NUMERIC_PROPERTY_REGEX.test(name)) { + return; + } + warnAndMonitorForKeyUse( + 'react_numeric_key_warning', + 'Child objects should have non-numeric keys so ordering is preserved.', + component, + parentType + ); +} + +/** + * Shared warning and monitoring code for the key warnings. + * + * @internal + * @param {string} warningID The id used when logging. + * @param {string} message The base warning that gets output. + * @param {ReactComponent} component Component that requires a key. + * @param {*} parentType component's parent's type. + */ +function warnAndMonitorForKeyUse(warningID, message, component, parentType) { + var ownerName = getCurrentOwnerDisplayName(); + var parentName = parentType.displayName; + + var useName = ownerName || parentName; + var memoizer = ownerHasKeyUseWarning[warningID]; + if (memoizer.hasOwnProperty(useName)) { + return; + } + memoizer[useName] = true; + + message += ownerName ? + ` Check the render method of ${ownerName}.` : + ` Check the renderComponent call using <${parentName}>.`; + + // Usually the current owner is the offender, but if it accepts children as a + // property, it may be the creator of the child that's responsible for + // assigning it a key. + var childOwnerName = null; + if (component._owner && component._owner !== ReactCurrentOwner.current) { + // Name of the component that originally created this child. + childOwnerName = component._owner.constructor.displayName; + + message += ` It was passed a child from ${childOwnerName}.`; + } + + message += ' See http://fb.me/react-warning-keys for more information.'; + monitorCodeUse(warningID, { + component: useName, + componentOwner: childOwnerName + }); + console.warn(message); +} + +/** + * Log that we're using an object map. We're considering deprecating this + * feature and replace it with proper Map and ImmutableMap data structures. + * + * @internal + */ +function monitorUseOfObjectMap() { + var currentName = getCurrentOwnerDisplayName() || ''; + if (ownerHasMonitoredObjectMap.hasOwnProperty(currentName)) { + return; + } + ownerHasMonitoredObjectMap[currentName] = true; + monitorCodeUse('react_object_map_children'); +} + +/** + * Ensure that every component either is passed in a static location, in an + * array with an explicit keys property defined, or in an object literal + * with valid key property. + * + * @internal + * @param {*} component Statically passed child of any type. + * @param {*} parentType component's parent's type. + * @return {boolean} + */ +function validateChildKeys(component, parentType) { + if (Array.isArray(component)) { + for (var i = 0; i < component.length; i++) { + var child = component[i]; + if (ReactDescriptor.isValidDescriptor(child)) { + validateExplicitKey(child, parentType); + } + } + } else if (ReactDescriptor.isValidDescriptor(component)) { + // This component was passed in a valid location. + component._store.validated = true; + } else if (component && typeof component === 'object') { + monitorUseOfObjectMap(); + for (var name in component) { + validatePropertyKey(name, component[name], parentType); + } + } +} + /** * Warn for mutations. * @@ -81,26 +237,6 @@ function defineMutationMembrane(prototype) { } } -/** - * Transfer static properties from the source to the target. Functions are - * rebound to have this reflect the original source. - */ -function proxyStaticMethods(target, source) { - if (typeof source !== 'function') { - return; - } - for (var key in source) { - if (source.hasOwnProperty(key)) { - var value = source[key]; - if (typeof value === 'function') { - target[key] = value.bind(source); - } else { - target[key] = value; - } - } - } -} - /** * Base constructor for all React descriptors. This is only used to make this * work with a dynamic instanceof check. Nothing should live on this prototype. @@ -118,44 +254,29 @@ ReactDescriptor.createFactory = function(type) { var descriptorPrototype = Object.create(ReactDescriptor.prototype); - var defaultProps = type.getDefaultProps && type.getDefaultProps(); - var factory = function(props, children) { - // For consistency we currently allocate a new object for every descriptor. - // This protects the descriptor from being mutated by the original props - // object being mutated. It also protects the original props object from - // being mutated by children arguments and default props. This behavior - // comes with a performance cost and could be deprecated in the future. - // It could also be optimized with a smarter JSX transform. if (props == null) { props = {}; - } else if (typeof props === 'object') { - props = merge(props); } - // Children can be more than one argument, and those are transferred onto - // the newly allocated props object. + // Children can be more than one argument var childrenLength = arguments.length - 1; if (childrenLength === 1) { + if (__DEV__) { + validateChildKeys(children, type); + } props.children = children; } else if (childrenLength > 1) { var childArray = Array(childrenLength); for (var i = 0; i < childrenLength; i++) { + if (__DEV__) { + validateChildKeys(arguments[i + 1], type); + } childArray[i] = arguments[i + 1]; } props.children = childArray; } - // Resolve default props - if (defaultProps) { - for (var propName in defaultProps) { - if (typeof props[propName] === 'undefined') { - props[propName] = defaultProps[propName]; - } - } - } - - // Initialize the descriptor object var descriptor = Object.create(descriptorPrototype); // Record the component responsible for creating this descriptor. @@ -168,13 +289,10 @@ ReactDescriptor.createFactory = function(type) { if (__DEV__) { // The validation flag and props are currently mutative. We put them on // an external backing store so that we can freeze the whole object. - // This can be replaced with a WeakMap once they are implemented in - // commonly used development environments. descriptor._store = { validated: false, props: props }; // We're not allowed to set props directly on the object so we early - // return and rely on the prototype membrane to forward to the backing - // store. + // return and rely on the prototype membrane toward to the backing store. if (useMutationMembrane) { Object.freeze(descriptor); return descriptor; @@ -183,6 +301,7 @@ ReactDescriptor.createFactory = function(type) { descriptor.props = props; return descriptor; + }; // Currently we expose the prototype of the descriptor so that @@ -197,8 +316,6 @@ ReactDescriptor.createFactory = function(type) { factory.type = type; descriptorPrototype.type = type; - proxyStaticMethods(factory, type); - // Expose a unique constructor on the prototype is that this works with type // systems that compare constructor properties: .constructor === Foo // This may be controversial since it requires a known factory function. diff --git a/src/core/ReactDescriptorValidator.js b/src/core/ReactDescriptorValidator.js deleted file mode 100644 index e6e23966aa..0000000000 --- a/src/core/ReactDescriptorValidator.js +++ /dev/null @@ -1,283 +0,0 @@ -/** - * Copyright 2014 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 ReactDescriptorValidator - */ - -/** - * ReactDescriptorValidator provides a wrapper around a descriptor factory - * which validates the props passed to the descriptor. This is intended to be - * used only in DEV and could be replaced by a static type checker for languages - * that support it. - */ - -"use strict"; - -var ReactDescriptor = require('ReactDescriptor'); -var ReactPropTypeLocations = require('ReactPropTypeLocations'); -var ReactCurrentOwner = require('ReactCurrentOwner'); - -var monitorCodeUse = require('monitorCodeUse'); - -/** - * Warn if there's no key explicitly set on dynamic arrays of children or - * object keys are not valid. This allows us to keep track of children between - * updates. - */ -var ownerHasKeyUseWarning = { - 'react_key_warning': {}, - 'react_numeric_key_warning': {} -}; -var ownerHasMonitoredObjectMap = {}; - -var loggedTypeFailures = {}; - -var NUMERIC_PROPERTY_REGEX = /^\d+$/; - -/** - * Gets the current owner's displayName for use in warnings. - * - * @internal - * @return {?string} Display name or undefined - */ -function getCurrentOwnerDisplayName() { - var current = ReactCurrentOwner.current; - return current && current.constructor.displayName || undefined; -} - -/** - * Warn if the component doesn't have an explicit key assigned to it. - * This component is in an array. The array could grow and shrink or be - * reordered. All children that haven't already been validated are required to - * have a "key" property assigned to it. - * - * @internal - * @param {ReactComponent} component Component that requires a key. - * @param {*} parentType component's parent's type. - */ -function validateExplicitKey(component, parentType) { - if (component._store.validated || component.props.key != null) { - return; - } - component._store.validated = true; - - warnAndMonitorForKeyUse( - 'react_key_warning', - 'Each child in an array should have a unique "key" prop.', - component, - parentType - ); -} - -/** - * Warn if the key is being defined as an object property but has an incorrect - * value. - * - * @internal - * @param {string} name Property name of the key. - * @param {ReactComponent} component Component that requires a key. - * @param {*} parentType component's parent's type. - */ -function validatePropertyKey(name, component, parentType) { - if (!NUMERIC_PROPERTY_REGEX.test(name)) { - return; - } - warnAndMonitorForKeyUse( - 'react_numeric_key_warning', - 'Child objects should have non-numeric keys so ordering is preserved.', - component, - parentType - ); -} - -/** - * Shared warning and monitoring code for the key warnings. - * - * @internal - * @param {string} warningID The id used when logging. - * @param {string} message The base warning that gets output. - * @param {ReactComponent} component Component that requires a key. - * @param {*} parentType component's parent's type. - */ -function warnAndMonitorForKeyUse(warningID, message, component, parentType) { - var ownerName = getCurrentOwnerDisplayName(); - var parentName = parentType.displayName; - - var useName = ownerName || parentName; - var memoizer = ownerHasKeyUseWarning[warningID]; - if (memoizer.hasOwnProperty(useName)) { - return; - } - memoizer[useName] = true; - - message += ownerName ? - ` Check the render method of ${ownerName}.` : - ` Check the renderComponent call using <${parentName}>.`; - - // Usually the current owner is the offender, but if it accepts children as a - // property, it may be the creator of the child that's responsible for - // assigning it a key. - var childOwnerName = null; - if (component._owner && component._owner !== ReactCurrentOwner.current) { - // Name of the component that originally created this child. - childOwnerName = component._owner.constructor.displayName; - - message += ` It was passed a child from ${childOwnerName}.`; - } - - message += ' See http://fb.me/react-warning-keys for more information.'; - monitorCodeUse(warningID, { - component: useName, - componentOwner: childOwnerName - }); - console.warn(message); -} - -/** - * Log that we're using an object map. We're considering deprecating this - * feature and replace it with proper Map and ImmutableMap data structures. - * - * @internal - */ -function monitorUseOfObjectMap() { - var currentName = getCurrentOwnerDisplayName() || ''; - if (ownerHasMonitoredObjectMap.hasOwnProperty(currentName)) { - return; - } - ownerHasMonitoredObjectMap[currentName] = true; - monitorCodeUse('react_object_map_children'); -} - -/** - * Ensure that every component either is passed in a static location, in an - * array with an explicit keys property defined, or in an object literal - * with valid key property. - * - * @internal - * @param {*} component Statically passed child of any type. - * @param {*} parentType component's parent's type. - * @return {boolean} - */ -function validateChildKeys(component, parentType) { - if (Array.isArray(component)) { - for (var i = 0; i < component.length; i++) { - var child = component[i]; - if (ReactDescriptor.isValidDescriptor(child)) { - validateExplicitKey(child, parentType); - } - } - } else if (ReactDescriptor.isValidDescriptor(component)) { - // This component was passed in a valid location. - component._store.validated = true; - } else if (component && typeof component === 'object') { - monitorUseOfObjectMap(); - for (var name in component) { - validatePropertyKey(name, component[name], parentType); - } - } -} - -/** - * Assert that the props are valid - * - * @param {string} componentName Name of the component for error messages. - * @param {object} propTypes Map of prop name to a ReactPropType - * @param {object} props - * @param {string} location e.g. "prop", "context", "child context" - * @private - */ -function checkPropTypes(componentName, propTypes, props, location) { - for (var propName in propTypes) { - if (propTypes.hasOwnProperty(propName)) { - var error; - // Prop type validation may throw. In case they do, we don't want to - // fail the render phase where it didn't fail before. So we log it. - // After these have been cleaned up, we'll let them throw. - try { - error = propTypes[propName](props, propName, componentName, location); - } catch (ex) { - error = ex; - } - if (error instanceof Error && !(error.message in loggedTypeFailures)) { - // Only monitor this failure once because there tends to be a lot of the - // same error. - loggedTypeFailures[error.message] = true; - // This will soon use the warning module - monitorCodeUse( - 'react_failed_descriptor_type_check', - { message: error.message } - ); - } - } - } -} - -var ReactDescriptorValidator = { - - /** - * Wraps a descriptor factory function in another function which validates - * the props and context of the descriptor and warns about any failed type - * checks. - * - * @param {function} factory The original descriptor factory - * @param {object?} propTypes A prop type definition set - * @param {object?} contextTypes A context type definition set - * @return {object} The component descriptor, which may be invalid. - * @private - */ - createFactory: function(factory, propTypes, contextTypes) { - var validatedFactory = function(props, children) { - var descriptor = factory.apply(this, arguments); - - for (var i = 1; i < arguments.length; i++) { - validateChildKeys(arguments[i], descriptor.type); - } - - var name = descriptor.type.displayName; - if (propTypes) { - checkPropTypes( - name, - propTypes, - descriptor.props, - ReactPropTypeLocations.prop - ); - } - if (contextTypes) { - checkPropTypes( - name, - contextTypes, - descriptor._context, - ReactPropTypeLocations.context - ); - } - return descriptor; - }; - - validatedFactory.prototype = factory.prototype; - validatedFactory.type = factory.type; - - // Copy static properties - for (var key in factory) { - if (factory.hasOwnProperty(key)) { - validatedFactory[key] = factory[key]; - } - } - - return validatedFactory; - } - -}; - -module.exports = ReactDescriptorValidator; diff --git a/src/core/__tests__/ReactPropTypes-test.js b/src/core/__tests__/ReactPropTypes-test.js index 1316231945..7177c17f16 100644 --- a/src/core/__tests__/ReactPropTypes-test.js +++ b/src/core/__tests__/ReactPropTypes-test.js @@ -614,7 +614,7 @@ describe('Custom validator', function() { var instance = ; instance = ReactTestUtils.renderIntoDocument(instance); - expect(spy.argsForCall.length).toBe(2); // temp double validation + expect(spy.argsForCall.length).toBe(1); expect(spy.argsForCall[0][1]).toBe('num'); expect(spy.argsForCall[0][2]).toBe('Component'); }); @@ -632,7 +632,7 @@ describe('Custom validator', function() { var instance = ; instance = ReactTestUtils.renderIntoDocument(instance); - expect(spy.argsForCall.length).toBe(2); // temp double validation + expect(spy.argsForCall.length).toBe(1); }); it('should have received the validator\'s return value', function() {