React JavaScript source code |
1 | "use strict"; var ReactContext = require('ReactContext'); var ReactCurrentOwner = require('ReactCurrentOwner'); var warning = require('warning'); var RESERVED_PROPS = { key: true, ref: true }; /** * Warn for mutations. * * @internal * @param {object} object * @param {string} key */ function defineWarningProperty(object, key) { Object.defineProperty(object, key, { configurable: false, enumerable: true, get: function() { if (!this._store) { return null; } return this._store[key]; }, set: function(value) { warning( false, 'Don\'t set the ' + key + ' property of the component. ' + 'Mutate the existing props object instead.' ); this._store[key] = value; } }); } /** |
2 | * This is updated to true if the membrane is successfully created. */ var useMutationMembrane = false; /** * Warn for mutations. * * @internal * @param {object} element */ function defineMutationMembrane(prototype) { try { var pseudoFrozenProperties = { props: true }; for (var key in pseudoFrozenProperties) { defineWarningProperty(prototype, key); } useMutationMembrane = true; } catch (x) { // IE will fail on defineProperty } } /** * Base constructor for all React elements. This is only used to make this * work with a dynamic instanceof check. Nothing should live on this prototype. * * @param {*} type * @param {string|object} ref * @param {*} key * @param {*} props * @internal */ var ReactElement = function(type, key, ref, owner, context, props) { // Built-in properties that belong on the element this.type = type; this.key = key; |
3 | this.ref = ref; // Record the component responsible for creating this element. this._owner = owner; // TODO: Deprecate withContext, and then the context becomes accessible // through the owner. this._context = context; 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. this._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. if (useMutationMembrane) { Object.freeze(this); return; } } this.props = props; }; // We intentionally don't expose the function on the constructor property. // ReactElement should be indistinguishable from a plain object. ReactElement.prototype = { _isReactElement: true }; if (__DEV__) { defineMutationMembrane(ReactElement.prototype); } |
4 | ReactElement.createElement = function(type, config, children) { var propName; // Reserved names are extracted var props = {}; var key = null; var ref = null; if (config != null) { ref = config.ref === undefined ? null : config.ref; if (__DEV__) { warning( config.key !== null, 'createElement(...): Encountered component with a `key` of null. In ' + 'a future version, this will be treated as equivalent to the string ' + '\'null\'; instead, provide an explicit key or use undefined.' ); } // TODO: Change this back to `config.key === undefined` key = config.key == null ? null : '' + config.key; // Remaining properties are added to a new props object for (propName in config) { if (config.hasOwnProperty(propName) && !RESERVED_PROPS.hasOwnProperty(propName)) { props[propName] = config[propName]; } } |
5 | } // Children can be more than one argument, and those are transferred onto // the newly allocated props object. var childrenLength = arguments.length - 2; if (childrenLength === 1) { props.children = children; } else if (childrenLength > 1) { var childArray = Array(childrenLength); for (var i = 0; i < childrenLength; i++) { childArray[i] = arguments[i + 2]; } props.children = childArray; } // Resolve default props if (type.defaultProps) { var defaultProps = type.defaultProps; for (propName in defaultProps) { if (typeof props[propName] === 'undefined') { props[propName] = defaultProps[propName]; } |
6 | } } return new ReactElement( type, key, ref, ReactCurrentOwner.current, ReactContext.current, props ); }; ReactElement.createFactory = function(type) { var factory = ReactElement.createElement.bind(null, type); // Expose the type on the factory and the prototype so that it can be // easily accessed on elements. E.g. <Foo />.type === Foo.type. // This should not be named `constructor` since this may not be the function // that created the element, and it may not even be a constructor. // Legacy hook TODO: Warn if this is accessed factory.type = type; return factory; }; ReactElement.cloneAndReplaceProps = function(oldElement, newProps) { var newElement = new ReactElement( oldElement.type, oldElement.key, oldElement.ref, oldElement._owner, oldElement._context, newProps ); |
7 | if (__DEV__) { // If the key on the original is valid, then the clone is valid newElement._store.validated = oldElement._store.validated; } return newElement; }; /** * @param {?object} object * @return {boolean} True if `object` is a valid component. * @final */ ReactElement.isValidElement = function(object) { // ReactTestUtils is often used outside of beforeEach where as React is // within it. This leads to two different instances of React on the same // page. To identify a element from a different React instance we use // a flag instead of an instanceof check. var isElement = !!(object && object._isReactElement); // if (isElement && !(object instanceof ReactElement)) { // This is an indicator that you're using multiple versions of React at the // same time. This will screw with ownership and stuff. Fix it, please. // TODO: We could possibly warn here. // } return isElement; }; module.exports = ReactElement; |
Комментарии