react / react-0.13.3 / examples / basic-commonjs / node_modules / reactify / node_modules / react-tools / src / core / ReactElement.js
81152 views/**1* Copyright 2014, 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 ReactElement9*/1011"use strict";1213var ReactContext = require('ReactContext');14var ReactCurrentOwner = require('ReactCurrentOwner');1516var warning = require('warning');1718var RESERVED_PROPS = {19key: true,20ref: true21};2223/**24* Warn for mutations.25*26* @internal27* @param {object} object28* @param {string} key29*/30function defineWarningProperty(object, key) {31Object.defineProperty(object, key, {3233configurable: false,34enumerable: true,3536get: function() {37if (!this._store) {38return null;39}40return this._store[key];41},4243set: function(value) {44warning(45false,46'Don\'t set the ' + key + ' property of the component. ' +47'Mutate the existing props object instead.'48);49this._store[key] = value;50}5152});53}5455/**56* This is updated to true if the membrane is successfully created.57*/58var useMutationMembrane = false;5960/**61* Warn for mutations.62*63* @internal64* @param {object} element65*/66function defineMutationMembrane(prototype) {67try {68var pseudoFrozenProperties = {69props: true70};71for (var key in pseudoFrozenProperties) {72defineWarningProperty(prototype, key);73}74useMutationMembrane = true;75} catch (x) {76// IE will fail on defineProperty77}78}7980/**81* Base constructor for all React elements. This is only used to make this82* work with a dynamic instanceof check. Nothing should live on this prototype.83*84* @param {*} type85* @param {string|object} ref86* @param {*} key87* @param {*} props88* @internal89*/90var ReactElement = function(type, key, ref, owner, context, props) {91// Built-in properties that belong on the element92this.type = type;93this.key = key;94this.ref = ref;9596// Record the component responsible for creating this element.97this._owner = owner;9899// TODO: Deprecate withContext, and then the context becomes accessible100// through the owner.101this._context = context;102103if (__DEV__) {104// The validation flag and props are currently mutative. We put them on105// an external backing store so that we can freeze the whole object.106// This can be replaced with a WeakMap once they are implemented in107// commonly used development environments.108this._store = { validated: false, props: props };109110// We're not allowed to set props directly on the object so we early111// return and rely on the prototype membrane to forward to the backing112// store.113if (useMutationMembrane) {114Object.freeze(this);115return;116}117}118119this.props = props;120};121122// We intentionally don't expose the function on the constructor property.123// ReactElement should be indistinguishable from a plain object.124ReactElement.prototype = {125_isReactElement: true126};127128if (__DEV__) {129defineMutationMembrane(ReactElement.prototype);130}131132ReactElement.createElement = function(type, config, children) {133var propName;134135// Reserved names are extracted136var props = {};137138var key = null;139var ref = null;140141if (config != null) {142ref = config.ref === undefined ? null : config.ref;143if (__DEV__) {144warning(145config.key !== null,146'createElement(...): Encountered component with a `key` of null. In ' +147'a future version, this will be treated as equivalent to the string ' +148'\'null\'; instead, provide an explicit key or use undefined.'149);150}151// TODO: Change this back to `config.key === undefined`152key = config.key == null ? null : '' + config.key;153// Remaining properties are added to a new props object154for (propName in config) {155if (config.hasOwnProperty(propName) &&156!RESERVED_PROPS.hasOwnProperty(propName)) {157props[propName] = config[propName];158}159}160}161162// Children can be more than one argument, and those are transferred onto163// the newly allocated props object.164var childrenLength = arguments.length - 2;165if (childrenLength === 1) {166props.children = children;167} else if (childrenLength > 1) {168var childArray = Array(childrenLength);169for (var i = 0; i < childrenLength; i++) {170childArray[i] = arguments[i + 2];171}172props.children = childArray;173}174175// Resolve default props176if (type && type.defaultProps) {177var defaultProps = type.defaultProps;178for (propName in defaultProps) {179if (typeof props[propName] === 'undefined') {180props[propName] = defaultProps[propName];181}182}183}184185return new ReactElement(186type,187key,188ref,189ReactCurrentOwner.current,190ReactContext.current,191props192);193};194195ReactElement.createFactory = function(type) {196var factory = ReactElement.createElement.bind(null, type);197// Expose the type on the factory and the prototype so that it can be198// easily accessed on elements. E.g. <Foo />.type === Foo.type.199// This should not be named `constructor` since this may not be the function200// that created the element, and it may not even be a constructor.201factory.type = type;202return factory;203};204205ReactElement.cloneAndReplaceProps = function(oldElement, newProps) {206var newElement = new ReactElement(207oldElement.type,208oldElement.key,209oldElement.ref,210oldElement._owner,211oldElement._context,212newProps213);214215if (__DEV__) {216// If the key on the original is valid, then the clone is valid217newElement._store.validated = oldElement._store.validated;218}219return newElement;220};221222/**223* @param {?object} object224* @return {boolean} True if `object` is a valid component.225* @final226*/227ReactElement.isValidElement = function(object) {228// ReactTestUtils is often used outside of beforeEach where as React is229// within it. This leads to two different instances of React on the same230// page. To identify a element from a different React instance we use231// a flag instead of an instanceof check.232var isElement = !!(object && object._isReactElement);233// if (isElement && !(object instanceof ReactElement)) {234// This is an indicator that you're using multiple versions of React at the235// same time. This will screw with ownership and stuff. Fix it, please.236// TODO: We could possibly warn here.237// }238return isElement;239};240241module.exports = ReactElement;242243244