/**1* Copyright 2013-2015, Facebook, Inc.2* All rights reserved.3*4* This source code is licensed under the BSD-style license found in the5* LICENSE file in the root directory of this source tree. An additional grant6* of patent rights can be found in the PATENTS file in the same directory.7*8* @providesModule ReactClass9*/1011'use strict';1213var ReactComponent = require("./ReactComponent");14var ReactCurrentOwner = require("./ReactCurrentOwner");15var ReactElement = require("./ReactElement");16var ReactErrorUtils = require("./ReactErrorUtils");17var ReactInstanceMap = require("./ReactInstanceMap");18var ReactLifeCycle = require("./ReactLifeCycle");19var ReactPropTypeLocations = require("./ReactPropTypeLocations");20var ReactPropTypeLocationNames = require("./ReactPropTypeLocationNames");21var ReactUpdateQueue = require("./ReactUpdateQueue");2223var assign = require("./Object.assign");24var invariant = require("./invariant");25var keyMirror = require("./keyMirror");26var keyOf = require("./keyOf");27var warning = require("./warning");2829var MIXINS_KEY = keyOf({mixins: null});3031/**32* Policies that describe methods in `ReactClassInterface`.33*/34var SpecPolicy = keyMirror({35/**36* These methods may be defined only once by the class specification or mixin.37*/38DEFINE_ONCE: null,39/**40* These methods may be defined by both the class specification and mixins.41* Subsequent definitions will be chained. These methods must return void.42*/43DEFINE_MANY: null,44/**45* These methods are overriding the base class.46*/47OVERRIDE_BASE: null,48/**49* These methods are similar to DEFINE_MANY, except we assume they return50* objects. We try to merge the keys of the return values of all the mixed in51* functions. If there is a key conflict we throw.52*/53DEFINE_MANY_MERGED: null54});555657var injectedMixins = [];5859/**60* Composite components are higher-level components that compose other composite61* or native components.62*63* To create a new type of `ReactClass`, pass a specification of64* your new class to `React.createClass`. The only requirement of your class65* specification is that you implement a `render` method.66*67* var MyComponent = React.createClass({68* render: function() {69* return <div>Hello World</div>;70* }71* });72*73* The class specification supports a specific protocol of methods that have74* special meaning (e.g. `render`). See `ReactClassInterface` for75* more the comprehensive protocol. Any other properties and methods in the76* class specification will available on the prototype.77*78* @interface ReactClassInterface79* @internal80*/81var ReactClassInterface = {8283/**84* An array of Mixin objects to include when defining your component.85*86* @type {array}87* @optional88*/89mixins: SpecPolicy.DEFINE_MANY,9091/**92* An object containing properties and methods that should be defined on93* the component's constructor instead of its prototype (static methods).94*95* @type {object}96* @optional97*/98statics: SpecPolicy.DEFINE_MANY,99100/**101* Definition of prop types for this component.102*103* @type {object}104* @optional105*/106propTypes: SpecPolicy.DEFINE_MANY,107108/**109* Definition of context types for this component.110*111* @type {object}112* @optional113*/114contextTypes: SpecPolicy.DEFINE_MANY,115116/**117* Definition of context types this component sets for its children.118*119* @type {object}120* @optional121*/122childContextTypes: SpecPolicy.DEFINE_MANY,123124// ==== Definition methods ====125126/**127* Invoked when the component is mounted. Values in the mapping will be set on128* `this.props` if that prop is not specified (i.e. using an `in` check).129*130* This method is invoked before `getInitialState` and therefore cannot rely131* on `this.state` or use `this.setState`.132*133* @return {object}134* @optional135*/136getDefaultProps: SpecPolicy.DEFINE_MANY_MERGED,137138/**139* Invoked once before the component is mounted. The return value will be used140* as the initial value of `this.state`.141*142* getInitialState: function() {143* return {144* isOn: false,145* fooBaz: new BazFoo()146* }147* }148*149* @return {object}150* @optional151*/152getInitialState: SpecPolicy.DEFINE_MANY_MERGED,153154/**155* @return {object}156* @optional157*/158getChildContext: SpecPolicy.DEFINE_MANY_MERGED,159160/**161* Uses props from `this.props` and state from `this.state` to render the162* structure of the component.163*164* No guarantees are made about when or how often this method is invoked, so165* it must not have side effects.166*167* render: function() {168* var name = this.props.name;169* return <div>Hello, {name}!</div>;170* }171*172* @return {ReactComponent}173* @nosideeffects174* @required175*/176render: SpecPolicy.DEFINE_ONCE,177178179180// ==== Delegate methods ====181182/**183* Invoked when the component is initially created and about to be mounted.184* This may have side effects, but any external subscriptions or data created185* by this method must be cleaned up in `componentWillUnmount`.186*187* @optional188*/189componentWillMount: SpecPolicy.DEFINE_MANY,190191/**192* Invoked when the component has been mounted and has a DOM representation.193* However, there is no guarantee that the DOM node is in the document.194*195* Use this as an opportunity to operate on the DOM when the component has196* been mounted (initialized and rendered) for the first time.197*198* @param {DOMElement} rootNode DOM element representing the component.199* @optional200*/201componentDidMount: SpecPolicy.DEFINE_MANY,202203/**204* Invoked before the component receives new props.205*206* Use this as an opportunity to react to a prop transition by updating the207* state using `this.setState`. Current props are accessed via `this.props`.208*209* componentWillReceiveProps: function(nextProps, nextContext) {210* this.setState({211* likesIncreasing: nextProps.likeCount > this.props.likeCount212* });213* }214*215* NOTE: There is no equivalent `componentWillReceiveState`. An incoming prop216* transition may cause a state change, but the opposite is not true. If you217* need it, you are probably looking for `componentWillUpdate`.218*219* @param {object} nextProps220* @optional221*/222componentWillReceiveProps: SpecPolicy.DEFINE_MANY,223224/**225* Invoked while deciding if the component should be updated as a result of226* receiving new props, state and/or context.227*228* Use this as an opportunity to `return false` when you're certain that the229* transition to the new props/state/context will not require a component230* update.231*232* shouldComponentUpdate: function(nextProps, nextState, nextContext) {233* return !equal(nextProps, this.props) ||234* !equal(nextState, this.state) ||235* !equal(nextContext, this.context);236* }237*238* @param {object} nextProps239* @param {?object} nextState240* @param {?object} nextContext241* @return {boolean} True if the component should update.242* @optional243*/244shouldComponentUpdate: SpecPolicy.DEFINE_ONCE,245246/**247* Invoked when the component is about to update due to a transition from248* `this.props`, `this.state` and `this.context` to `nextProps`, `nextState`249* and `nextContext`.250*251* Use this as an opportunity to perform preparation before an update occurs.252*253* NOTE: You **cannot** use `this.setState()` in this method.254*255* @param {object} nextProps256* @param {?object} nextState257* @param {?object} nextContext258* @param {ReactReconcileTransaction} transaction259* @optional260*/261componentWillUpdate: SpecPolicy.DEFINE_MANY,262263/**264* Invoked when the component's DOM representation has been updated.265*266* Use this as an opportunity to operate on the DOM when the component has267* been updated.268*269* @param {object} prevProps270* @param {?object} prevState271* @param {?object} prevContext272* @param {DOMElement} rootNode DOM element representing the component.273* @optional274*/275componentDidUpdate: SpecPolicy.DEFINE_MANY,276277/**278* Invoked when the component is about to be removed from its parent and have279* its DOM representation destroyed.280*281* Use this as an opportunity to deallocate any external resources.282*283* NOTE: There is no `componentDidUnmount` since your component will have been284* destroyed by that point.285*286* @optional287*/288componentWillUnmount: SpecPolicy.DEFINE_MANY,289290291292// ==== Advanced methods ====293294/**295* Updates the component's currently mounted DOM representation.296*297* By default, this implements React's rendering and reconciliation algorithm.298* Sophisticated clients may wish to override this.299*300* @param {ReactReconcileTransaction} transaction301* @internal302* @overridable303*/304updateComponent: SpecPolicy.OVERRIDE_BASE305306};307308/**309* Mapping from class specification keys to special processing functions.310*311* Although these are declared like instance properties in the specification312* when defining classes using `React.createClass`, they are actually static313* and are accessible on the constructor instead of the prototype. Despite314* being static, they must be defined outside of the "statics" key under315* which all other static methods are defined.316*/317var RESERVED_SPEC_KEYS = {318displayName: function(Constructor, displayName) {319Constructor.displayName = displayName;320},321mixins: function(Constructor, mixins) {322if (mixins) {323for (var i = 0; i < mixins.length; i++) {324mixSpecIntoComponent(Constructor, mixins[i]);325}326}327},328childContextTypes: function(Constructor, childContextTypes) {329if ("production" !== process.env.NODE_ENV) {330validateTypeDef(331Constructor,332childContextTypes,333ReactPropTypeLocations.childContext334);335}336Constructor.childContextTypes = assign(337{},338Constructor.childContextTypes,339childContextTypes340);341},342contextTypes: function(Constructor, contextTypes) {343if ("production" !== process.env.NODE_ENV) {344validateTypeDef(345Constructor,346contextTypes,347ReactPropTypeLocations.context348);349}350Constructor.contextTypes = assign(351{},352Constructor.contextTypes,353contextTypes354);355},356/**357* Special case getDefaultProps which should move into statics but requires358* automatic merging.359*/360getDefaultProps: function(Constructor, getDefaultProps) {361if (Constructor.getDefaultProps) {362Constructor.getDefaultProps = createMergedResultFunction(363Constructor.getDefaultProps,364getDefaultProps365);366} else {367Constructor.getDefaultProps = getDefaultProps;368}369},370propTypes: function(Constructor, propTypes) {371if ("production" !== process.env.NODE_ENV) {372validateTypeDef(373Constructor,374propTypes,375ReactPropTypeLocations.prop376);377}378Constructor.propTypes = assign(379{},380Constructor.propTypes,381propTypes382);383},384statics: function(Constructor, statics) {385mixStaticSpecIntoComponent(Constructor, statics);386}387};388389function validateTypeDef(Constructor, typeDef, location) {390for (var propName in typeDef) {391if (typeDef.hasOwnProperty(propName)) {392// use a warning instead of an invariant so components393// don't show up in prod but not in __DEV__394("production" !== process.env.NODE_ENV ? warning(395typeof typeDef[propName] === 'function',396'%s: %s type `%s` is invalid; it must be a function, usually from ' +397'React.PropTypes.',398Constructor.displayName || 'ReactClass',399ReactPropTypeLocationNames[location],400propName401) : null);402}403}404}405406function validateMethodOverride(proto, name) {407var specPolicy = ReactClassInterface.hasOwnProperty(name) ?408ReactClassInterface[name] :409null;410411// Disallow overriding of base class methods unless explicitly allowed.412if (ReactClassMixin.hasOwnProperty(name)) {413("production" !== process.env.NODE_ENV ? invariant(414specPolicy === SpecPolicy.OVERRIDE_BASE,415'ReactClassInterface: You are attempting to override ' +416'`%s` from your class specification. Ensure that your method names ' +417'do not overlap with React methods.',418name419) : invariant(specPolicy === SpecPolicy.OVERRIDE_BASE));420}421422// Disallow defining methods more than once unless explicitly allowed.423if (proto.hasOwnProperty(name)) {424("production" !== process.env.NODE_ENV ? invariant(425specPolicy === SpecPolicy.DEFINE_MANY ||426specPolicy === SpecPolicy.DEFINE_MANY_MERGED,427'ReactClassInterface: You are attempting to define ' +428'`%s` on your component more than once. This conflict may be due ' +429'to a mixin.',430name431) : invariant(specPolicy === SpecPolicy.DEFINE_MANY ||432specPolicy === SpecPolicy.DEFINE_MANY_MERGED));433}434}435436/**437* Mixin helper which handles policy validation and reserved438* specification keys when building React classses.439*/440function mixSpecIntoComponent(Constructor, spec) {441if (!spec) {442return;443}444445("production" !== process.env.NODE_ENV ? invariant(446typeof spec !== 'function',447'ReactClass: You\'re attempting to ' +448'use a component class as a mixin. Instead, just use a regular object.'449) : invariant(typeof spec !== 'function'));450("production" !== process.env.NODE_ENV ? invariant(451!ReactElement.isValidElement(spec),452'ReactClass: You\'re attempting to ' +453'use a component as a mixin. Instead, just use a regular object.'454) : invariant(!ReactElement.isValidElement(spec)));455456var proto = Constructor.prototype;457458// By handling mixins before any other properties, we ensure the same459// chaining order is applied to methods with DEFINE_MANY policy, whether460// mixins are listed before or after these methods in the spec.461if (spec.hasOwnProperty(MIXINS_KEY)) {462RESERVED_SPEC_KEYS.mixins(Constructor, spec.mixins);463}464465for (var name in spec) {466if (!spec.hasOwnProperty(name)) {467continue;468}469470if (name === MIXINS_KEY) {471// We have already handled mixins in a special case above472continue;473}474475var property = spec[name];476validateMethodOverride(proto, name);477478if (RESERVED_SPEC_KEYS.hasOwnProperty(name)) {479RESERVED_SPEC_KEYS[name](Constructor, property);480} else {481// Setup methods on prototype:482// The following member methods should not be automatically bound:483// 1. Expected ReactClass methods (in the "interface").484// 2. Overridden methods (that were mixed in).485var isReactClassMethod =486ReactClassInterface.hasOwnProperty(name);487var isAlreadyDefined = proto.hasOwnProperty(name);488var markedDontBind = property && property.__reactDontBind;489var isFunction = typeof property === 'function';490var shouldAutoBind =491isFunction &&492!isReactClassMethod &&493!isAlreadyDefined &&494!markedDontBind;495496if (shouldAutoBind) {497if (!proto.__reactAutoBindMap) {498proto.__reactAutoBindMap = {};499}500proto.__reactAutoBindMap[name] = property;501proto[name] = property;502} else {503if (isAlreadyDefined) {504var specPolicy = ReactClassInterface[name];505506// These cases should already be caught by validateMethodOverride507("production" !== process.env.NODE_ENV ? invariant(508isReactClassMethod && (509(specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY)510),511'ReactClass: Unexpected spec policy %s for key %s ' +512'when mixing in component specs.',513specPolicy,514name515) : invariant(isReactClassMethod && (516(specPolicy === SpecPolicy.DEFINE_MANY_MERGED || specPolicy === SpecPolicy.DEFINE_MANY)517)));518519// For methods which are defined more than once, call the existing520// methods before calling the new property, merging if appropriate.521if (specPolicy === SpecPolicy.DEFINE_MANY_MERGED) {522proto[name] = createMergedResultFunction(proto[name], property);523} else if (specPolicy === SpecPolicy.DEFINE_MANY) {524proto[name] = createChainedFunction(proto[name], property);525}526} else {527proto[name] = property;528if ("production" !== process.env.NODE_ENV) {529// Add verbose displayName to the function, which helps when looking530// at profiling tools.531if (typeof property === 'function' && spec.displayName) {532proto[name].displayName = spec.displayName + '_' + name;533}534}535}536}537}538}539}540541function mixStaticSpecIntoComponent(Constructor, statics) {542if (!statics) {543return;544}545for (var name in statics) {546var property = statics[name];547if (!statics.hasOwnProperty(name)) {548continue;549}550551var isReserved = name in RESERVED_SPEC_KEYS;552("production" !== process.env.NODE_ENV ? invariant(553!isReserved,554'ReactClass: You are attempting to define a reserved ' +555'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' +556'as an instance property instead; it will still be accessible on the ' +557'constructor.',558name559) : invariant(!isReserved));560561var isInherited = name in Constructor;562("production" !== process.env.NODE_ENV ? invariant(563!isInherited,564'ReactClass: You are attempting to define ' +565'`%s` on your component more than once. This conflict may be ' +566'due to a mixin.',567name568) : invariant(!isInherited));569Constructor[name] = property;570}571}572573/**574* Merge two objects, but throw if both contain the same key.575*576* @param {object} one The first object, which is mutated.577* @param {object} two The second object578* @return {object} one after it has been mutated to contain everything in two.579*/580function mergeIntoWithNoDuplicateKeys(one, two) {581("production" !== process.env.NODE_ENV ? invariant(582one && two && typeof one === 'object' && typeof two === 'object',583'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.'584) : invariant(one && two && typeof one === 'object' && typeof two === 'object'));585586for (var key in two) {587if (two.hasOwnProperty(key)) {588("production" !== process.env.NODE_ENV ? invariant(589one[key] === undefined,590'mergeIntoWithNoDuplicateKeys(): ' +591'Tried to merge two objects with the same key: `%s`. This conflict ' +592'may be due to a mixin; in particular, this may be caused by two ' +593'getInitialState() or getDefaultProps() methods returning objects ' +594'with clashing keys.',595key596) : invariant(one[key] === undefined));597one[key] = two[key];598}599}600return one;601}602603/**604* Creates a function that invokes two functions and merges their return values.605*606* @param {function} one Function to invoke first.607* @param {function} two Function to invoke second.608* @return {function} Function that invokes the two argument functions.609* @private610*/611function createMergedResultFunction(one, two) {612return function mergedResult() {613var a = one.apply(this, arguments);614var b = two.apply(this, arguments);615if (a == null) {616return b;617} else if (b == null) {618return a;619}620var c = {};621mergeIntoWithNoDuplicateKeys(c, a);622mergeIntoWithNoDuplicateKeys(c, b);623return c;624};625}626627/**628* Creates a function that invokes two functions and ignores their return vales.629*630* @param {function} one Function to invoke first.631* @param {function} two Function to invoke second.632* @return {function} Function that invokes the two argument functions.633* @private634*/635function createChainedFunction(one, two) {636return function chainedFunction() {637one.apply(this, arguments);638two.apply(this, arguments);639};640}641642/**643* Binds a method to the component.644*645* @param {object} component Component whose method is going to be bound.646* @param {function} method Method to be bound.647* @return {function} The bound method.648*/649function bindAutoBindMethod(component, method) {650var boundMethod = method.bind(component);651if ("production" !== process.env.NODE_ENV) {652boundMethod.__reactBoundContext = component;653boundMethod.__reactBoundMethod = method;654boundMethod.__reactBoundArguments = null;655var componentName = component.constructor.displayName;656var _bind = boundMethod.bind;657/* eslint-disable block-scoped-var, no-undef */658boundMethod.bind = function(newThis ) {for (var args=[],$__0=1,$__1=arguments.length;$__0<$__1;$__0++) args.push(arguments[$__0]);659// User is trying to bind() an autobound method; we effectively will660// ignore the value of "this" that the user is trying to use, so661// let's warn.662if (newThis !== component && newThis !== null) {663("production" !== process.env.NODE_ENV ? warning(664false,665'bind(): React component methods may only be bound to the ' +666'component instance. See %s',667componentName668) : null);669} else if (!args.length) {670("production" !== process.env.NODE_ENV ? warning(671false,672'bind(): You are binding a component method to the component. ' +673'React does this for you automatically in a high-performance ' +674'way, so you can safely remove this call. See %s',675componentName676) : null);677return boundMethod;678}679var reboundMethod = _bind.apply(boundMethod, arguments);680reboundMethod.__reactBoundContext = component;681reboundMethod.__reactBoundMethod = method;682reboundMethod.__reactBoundArguments = args;683return reboundMethod;684/* eslint-enable */685};686}687return boundMethod;688}689690/**691* Binds all auto-bound methods in a component.692*693* @param {object} component Component whose method is going to be bound.694*/695function bindAutoBindMethods(component) {696for (var autoBindKey in component.__reactAutoBindMap) {697if (component.__reactAutoBindMap.hasOwnProperty(autoBindKey)) {698var method = component.__reactAutoBindMap[autoBindKey];699component[autoBindKey] = bindAutoBindMethod(700component,701ReactErrorUtils.guard(702method,703component.constructor.displayName + '.' + autoBindKey704)705);706}707}708}709710var typeDeprecationDescriptor = {711enumerable: false,712get: function() {713var displayName = this.displayName || this.name || 'Component';714("production" !== process.env.NODE_ENV ? warning(715false,716'%s.type is deprecated. Use %s directly to access the class.',717displayName,718displayName719) : null);720Object.defineProperty(this, 'type', {721value: this722});723return this;724}725};726727/**728* Add more to the ReactClass base class. These are all legacy features and729* therefore not already part of the modern ReactComponent.730*/731var ReactClassMixin = {732733/**734* TODO: This will be deprecated because state should always keep a consistent735* type signature and the only use case for this, is to avoid that.736*/737replaceState: function(newState, callback) {738ReactUpdateQueue.enqueueReplaceState(this, newState);739if (callback) {740ReactUpdateQueue.enqueueCallback(this, callback);741}742},743744/**745* Checks whether or not this composite component is mounted.746* @return {boolean} True if mounted, false otherwise.747* @protected748* @final749*/750isMounted: function() {751if ("production" !== process.env.NODE_ENV) {752var owner = ReactCurrentOwner.current;753if (owner !== null) {754("production" !== process.env.NODE_ENV ? warning(755owner._warnedAboutRefsInRender,756'%s is accessing isMounted inside its render() function. ' +757'render() should be a pure function of props and state. It should ' +758'never access something that requires stale data from the previous ' +759'render, such as refs. Move this logic to componentDidMount and ' +760'componentDidUpdate instead.',761owner.getName() || 'A component'762) : null);763owner._warnedAboutRefsInRender = true;764}765}766var internalInstance = ReactInstanceMap.get(this);767return (768internalInstance &&769internalInstance !== ReactLifeCycle.currentlyMountingInstance770);771},772773/**774* Sets a subset of the props.775*776* @param {object} partialProps Subset of the next props.777* @param {?function} callback Called after props are updated.778* @final779* @public780* @deprecated781*/782setProps: function(partialProps, callback) {783ReactUpdateQueue.enqueueSetProps(this, partialProps);784if (callback) {785ReactUpdateQueue.enqueueCallback(this, callback);786}787},788789/**790* Replace all the props.791*792* @param {object} newProps Subset of the next props.793* @param {?function} callback Called after props are updated.794* @final795* @public796* @deprecated797*/798replaceProps: function(newProps, callback) {799ReactUpdateQueue.enqueueReplaceProps(this, newProps);800if (callback) {801ReactUpdateQueue.enqueueCallback(this, callback);802}803}804};805806var ReactClassComponent = function() {};807assign(808ReactClassComponent.prototype,809ReactComponent.prototype,810ReactClassMixin811);812813/**814* Module for creating composite components.815*816* @class ReactClass817*/818var ReactClass = {819820/**821* Creates a composite component class given a class specification.822*823* @param {object} spec Class specification (which must define `render`).824* @return {function} Component constructor function.825* @public826*/827createClass: function(spec) {828var Constructor = function(props, context) {829// This constructor is overridden by mocks. The argument is used830// by mocks to assert on what gets mounted.831832if ("production" !== process.env.NODE_ENV) {833("production" !== process.env.NODE_ENV ? warning(834this instanceof Constructor,835'Something is calling a React component directly. Use a factory or ' +836'JSX instead. See: https://fb.me/react-legacyfactory'837) : null);838}839840// Wire up auto-binding841if (this.__reactAutoBindMap) {842bindAutoBindMethods(this);843}844845this.props = props;846this.context = context;847this.state = null;848849// ReactClasses doesn't have constructors. Instead, they use the850// getInitialState and componentWillMount methods for initialization.851852var initialState = this.getInitialState ? this.getInitialState() : null;853if ("production" !== process.env.NODE_ENV) {854// We allow auto-mocks to proceed as if they're returning null.855if (typeof initialState === 'undefined' &&856this.getInitialState._isMockFunction) {857// This is probably bad practice. Consider warning here and858// deprecating this convenience.859initialState = null;860}861}862("production" !== process.env.NODE_ENV ? invariant(863typeof initialState === 'object' && !Array.isArray(initialState),864'%s.getInitialState(): must return an object or null',865Constructor.displayName || 'ReactCompositeComponent'866) : invariant(typeof initialState === 'object' && !Array.isArray(initialState)));867868this.state = initialState;869};870Constructor.prototype = new ReactClassComponent();871Constructor.prototype.constructor = Constructor;872873injectedMixins.forEach(874mixSpecIntoComponent.bind(null, Constructor)875);876877mixSpecIntoComponent(Constructor, spec);878879// Initialize the defaultProps property after all mixins have been merged880if (Constructor.getDefaultProps) {881Constructor.defaultProps = Constructor.getDefaultProps();882}883884if ("production" !== process.env.NODE_ENV) {885// This is a tag to indicate that the use of these method names is ok,886// since it's used with createClass. If it's not, then it's likely a887// mistake so we'll warn you to use the static property, property888// initializer or constructor respectively.889if (Constructor.getDefaultProps) {890Constructor.getDefaultProps.isReactClassApproved = {};891}892if (Constructor.prototype.getInitialState) {893Constructor.prototype.getInitialState.isReactClassApproved = {};894}895}896897("production" !== process.env.NODE_ENV ? invariant(898Constructor.prototype.render,899'createClass(...): Class specification must implement a `render` method.'900) : invariant(Constructor.prototype.render));901902if ("production" !== process.env.NODE_ENV) {903("production" !== process.env.NODE_ENV ? warning(904!Constructor.prototype.componentShouldUpdate,905'%s has a method called ' +906'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +907'The name is phrased as a question because the function is ' +908'expected to return a value.',909spec.displayName || 'A component'910) : null);911}912913// Reduce time spent doing lookups by setting these on the prototype.914for (var methodName in ReactClassInterface) {915if (!Constructor.prototype[methodName]) {916Constructor.prototype[methodName] = null;917}918}919920// Legacy hook921Constructor.type = Constructor;922if ("production" !== process.env.NODE_ENV) {923try {924Object.defineProperty(Constructor, 'type', typeDeprecationDescriptor);925} catch (x) {926// IE will fail on defineProperty (es5-shim/sham too)927}928}929930return Constructor;931},932933injection: {934injectMixin: function(mixin) {935injectedMixins.push(mixin);936}937}938939};940941module.exports = ReactClass;942943944