mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Renamed Descriptor -> Element
We've decided on a new naming convention for ReactDescriptor. It's now called ReactElement, which is a subset of the ReactNode union type.
This commit is contained in:
@@ -19,26 +19,26 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactDescriptorValidator = require('ReactDescriptorValidator');
|
||||
var ReactLegacyDescriptor = require('ReactLegacyDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactElementValidator = require('ReactElementValidator');
|
||||
var ReactLegacyElement = require('ReactLegacyElement');
|
||||
|
||||
var mapObject = require('mapObject');
|
||||
|
||||
/**
|
||||
* Create a factory that creates HTML tag descriptors.
|
||||
* Create a factory that creates HTML tag elements.
|
||||
*
|
||||
* @param {string} tag Tag name (e.g. `div`).
|
||||
* @private
|
||||
*/
|
||||
function createDOMFactory(tag) {
|
||||
if (__DEV__) {
|
||||
return ReactLegacyDescriptor.markNonLegacyFactory(
|
||||
ReactDescriptorValidator.createFactory(tag)
|
||||
return ReactLegacyElement.markNonLegacyFactory(
|
||||
ReactElementValidator.createFactory(tag)
|
||||
);
|
||||
}
|
||||
return ReactLegacyDescriptor.markNonLegacyFactory(
|
||||
ReactDescriptor.createFactory(tag)
|
||||
return ReactLegacyElement.markNonLegacyFactory(
|
||||
ReactElement.createFactory(tag)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
var DOMPropertyOperations = require('DOMPropertyOperations');
|
||||
var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin');
|
||||
var ReactComponent = require('ReactComponent');
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
|
||||
var escapeTextForBrowser = require('escapeTextForBrowser');
|
||||
var mixInto = require('mixInto');
|
||||
@@ -105,7 +105,7 @@ mixInto(ReactTextComponent, {
|
||||
|
||||
var ReactTextComponentFactory = function(text) {
|
||||
// Bypass validation and configuration
|
||||
return new ReactDescriptor(ReactTextComponent, null, null, null, null, text);
|
||||
return new ReactElement(ReactTextComponent, null, null, null, null, text);
|
||||
};
|
||||
|
||||
ReactTextComponentFactory.type = ReactTextComponent;
|
||||
|
||||
@@ -122,8 +122,8 @@ describe('ReactDOM', function() {
|
||||
|
||||
it('allow React.DOM factories to be called without warnings', function() {
|
||||
spyOn(console, 'warn');
|
||||
var descriptor = React.DOM.div();
|
||||
expect(descriptor.type).toBe('div');
|
||||
var element = React.DOM.div();
|
||||
expect(element.type).toBe('div');
|
||||
expect(console.warn.argsForCall.length).toBe(0);
|
||||
});
|
||||
|
||||
@@ -139,8 +139,8 @@ describe('ReactDOM', function() {
|
||||
|
||||
it('warns but allow dom factories to be used in createElement', function() {
|
||||
spyOn(console, 'warn');
|
||||
var descriptor = React.createElement(React.DOM.div);
|
||||
expect(descriptor.type).toBe('div');
|
||||
var element = React.createElement(React.DOM.div);
|
||||
expect(element.type).toBe('div');
|
||||
expect(console.warn.argsForCall.length).toBe(1);
|
||||
expect(console.warn.argsForCall[0][0]).toContain(
|
||||
'Do not pass React.DOM.div'
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactInstanceHandles = require('ReactInstanceHandles');
|
||||
var ReactMarkupChecksum = require('ReactMarkupChecksum');
|
||||
var ReactServerRenderingTransaction =
|
||||
@@ -33,7 +33,7 @@ var invariant = require('invariant');
|
||||
*/
|
||||
function renderComponentToString(component) {
|
||||
invariant(
|
||||
ReactDescriptor.isValidDescriptor(component),
|
||||
ReactElement.isValidElement(component),
|
||||
'renderComponentToString(): You must pass a valid ReactComponent.'
|
||||
);
|
||||
|
||||
@@ -65,7 +65,7 @@ function renderComponentToString(component) {
|
||||
*/
|
||||
function renderComponentToStaticMarkup(component) {
|
||||
invariant(
|
||||
ReactDescriptor.isValidDescriptor(component),
|
||||
ReactElement.isValidElement(component),
|
||||
'renderComponentToStaticMarkup(): You must pass a valid ReactComponent.'
|
||||
);
|
||||
|
||||
|
||||
+15
-15
@@ -29,13 +29,13 @@ var ReactComponent = require('ReactComponent');
|
||||
var ReactCompositeComponent = require('ReactCompositeComponent');
|
||||
var ReactContext = require('ReactContext');
|
||||
var ReactCurrentOwner = require('ReactCurrentOwner');
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactDescriptorValidator = require('ReactDescriptorValidator');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactElementValidator = require('ReactElementValidator');
|
||||
var ReactDOM = require('ReactDOM');
|
||||
var ReactDOMComponent = require('ReactDOMComponent');
|
||||
var ReactDefaultInjection = require('ReactDefaultInjection');
|
||||
var ReactInstanceHandles = require('ReactInstanceHandles');
|
||||
var ReactLegacyDescriptor = require('ReactLegacyDescriptor');
|
||||
var ReactLegacyElement = require('ReactLegacyElement');
|
||||
var ReactMount = require('ReactMount');
|
||||
var ReactMultiChild = require('ReactMultiChild');
|
||||
var ReactPerf = require('ReactPerf');
|
||||
@@ -47,19 +47,19 @@ var onlyChild = require('onlyChild');
|
||||
|
||||
ReactDefaultInjection.inject();
|
||||
|
||||
var createDescriptor = ReactDescriptor.createDescriptor;
|
||||
var createFactory = ReactDescriptor.createFactory;
|
||||
var createElement = ReactElement.createElement;
|
||||
var createFactory = ReactElement.createFactory;
|
||||
|
||||
if (__DEV__) {
|
||||
createDescriptor = ReactDescriptorValidator.createDescriptor;
|
||||
createFactory = ReactDescriptorValidator.createFactory;
|
||||
createElement = ReactElementValidator.createElement;
|
||||
createFactory = ReactElementValidator.createFactory;
|
||||
}
|
||||
|
||||
// TODO: Drop legacy descriptors once classes no longer export these factories
|
||||
createDescriptor = ReactLegacyDescriptor.wrapCreateDescriptor(
|
||||
createDescriptor
|
||||
// TODO: Drop legacy elements once classes no longer export these factories
|
||||
createElement = ReactLegacyElement.wrapCreateElement(
|
||||
createElement
|
||||
);
|
||||
createFactory = ReactLegacyDescriptor.wrapCreateFactory(
|
||||
createFactory = ReactLegacyElement.wrapCreateFactory(
|
||||
createFactory
|
||||
);
|
||||
|
||||
@@ -76,8 +76,8 @@ var React = {
|
||||
EventPluginUtils.useTouchEvents = shouldUseTouch;
|
||||
},
|
||||
createClass: ReactCompositeComponent.createClass,
|
||||
createDescriptor: createDescriptor, // deprecated, will be removed next week
|
||||
createElement: createDescriptor,
|
||||
createDescriptor: createElement, // deprecated, will be removed next week
|
||||
createElement: createElement,
|
||||
createFactory: createFactory,
|
||||
constructAndRenderComponent: ReactMount.constructAndRenderComponent,
|
||||
constructAndRenderComponentByID: ReactMount.constructAndRenderComponentByID,
|
||||
@@ -90,8 +90,8 @@ var React = {
|
||||
renderComponentToStaticMarkup:
|
||||
ReactServerRendering.renderComponentToStaticMarkup,
|
||||
unmountComponentAtNode: ReactMount.unmountComponentAtNode,
|
||||
isValidClass: ReactLegacyDescriptor.isValidFactory,
|
||||
isValidComponent: ReactDescriptor.isValidDescriptor,
|
||||
isValidClass: ReactLegacyElement.isValidFactory,
|
||||
isValidComponent: ReactElement.isValidElement,
|
||||
withContext: ReactContext.withContext,
|
||||
__internals: {
|
||||
Component: ReactComponent,
|
||||
|
||||
@@ -260,22 +260,22 @@ ReactDOMComponent.Mixin = {
|
||||
return '';
|
||||
},
|
||||
|
||||
receiveComponent: function(nextDescriptor, transaction) {
|
||||
if (nextDescriptor === this._descriptor &&
|
||||
nextDescriptor._owner != null) {
|
||||
// Since descriptors are immutable after the owner is rendered,
|
||||
receiveComponent: function(nextElement, transaction) {
|
||||
if (nextElement === this._currentElement &&
|
||||
nextElement._owner != null) {
|
||||
// Since elements are immutable after the owner is rendered,
|
||||
// we can do a cheap identity compare here to determine if this is a
|
||||
// superfluous reconcile. It's possible for state to be mutable but such
|
||||
// change should trigger an update of the owner which would recreate
|
||||
// the descriptor. We explicitly check for the existence of an owner since
|
||||
// it's possible for a descriptor created outside a composite to be
|
||||
// the element. We explicitly check for the existence of an owner since
|
||||
// it's possible for a element created outside a composite to be
|
||||
// deeply mutated and reused.
|
||||
return;
|
||||
}
|
||||
|
||||
ReactComponent.Mixin.receiveComponent.call(
|
||||
this,
|
||||
nextDescriptor,
|
||||
nextElement,
|
||||
transaction
|
||||
);
|
||||
},
|
||||
@@ -285,22 +285,22 @@ ReactDOMComponent.Mixin = {
|
||||
* attached to the DOM. Reconciles the root DOM node, then recurses.
|
||||
*
|
||||
* @param {ReactReconcileTransaction} transaction
|
||||
* @param {ReactDescriptor} prevDescriptor
|
||||
* @param {ReactElement} prevElement
|
||||
* @internal
|
||||
* @overridable
|
||||
*/
|
||||
updateComponent: ReactPerf.measure(
|
||||
'ReactDOMComponent',
|
||||
'updateComponent',
|
||||
function(transaction, prevDescriptor) {
|
||||
assertValidProps(this._descriptor.props);
|
||||
function(transaction, prevElement) {
|
||||
assertValidProps(this._currentElement.props);
|
||||
ReactComponent.Mixin.updateComponent.call(
|
||||
this,
|
||||
transaction,
|
||||
prevDescriptor
|
||||
prevElement
|
||||
);
|
||||
this._updateDOMProperties(prevDescriptor.props, transaction);
|
||||
this._updateDOMChildren(prevDescriptor.props, transaction);
|
||||
this._updateDOMProperties(prevElement.props, transaction);
|
||||
this._updateDOMChildren(prevElement.props, transaction);
|
||||
}
|
||||
),
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
var DOMProperty = require('DOMProperty');
|
||||
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
|
||||
var ReactCurrentOwner = require('ReactCurrentOwner');
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactLegacyDescriptor = require('ReactLegacyDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactLegacyElement = require('ReactLegacyElement');
|
||||
var ReactInstanceHandles = require('ReactInstanceHandles');
|
||||
var ReactPerf = require('ReactPerf');
|
||||
|
||||
@@ -33,8 +33,8 @@ var invariant = require('invariant');
|
||||
var shouldUpdateReactComponent = require('shouldUpdateReactComponent');
|
||||
var warning = require('warning');
|
||||
|
||||
var createDescriptor = ReactLegacyDescriptor.wrapCreateDescriptor(
|
||||
ReactDescriptor.createDescriptor
|
||||
var createElement = ReactLegacyElement.wrapCreateElement(
|
||||
ReactElement.createElement
|
||||
);
|
||||
|
||||
var SEPARATOR = ReactInstanceHandles.SEPARATOR;
|
||||
@@ -335,24 +335,24 @@ var ReactMount = {
|
||||
* perform an update on it and only mutate the DOM as necessary to reflect the
|
||||
* latest React component.
|
||||
*
|
||||
* @param {ReactDescriptor} nextDescriptor Component descriptor to render.
|
||||
* @param {ReactElement} nextElement Component element to render.
|
||||
* @param {DOMElement} container DOM element to render into.
|
||||
* @param {?function} callback function triggered on completion
|
||||
* @return {ReactComponent} Component instance rendered in `container`.
|
||||
*/
|
||||
renderComponent: function(nextDescriptor, container, callback) {
|
||||
renderComponent: function(nextElement, container, callback) {
|
||||
invariant(
|
||||
ReactDescriptor.isValidDescriptor(nextDescriptor),
|
||||
'renderComponent(): Invalid component descriptor.%s',
|
||||
ReactElement.isValidElement(nextElement),
|
||||
'renderComponent(): Invalid component element.%s',
|
||||
(
|
||||
typeof nextDescriptor === 'string' ?
|
||||
typeof nextElement === 'string' ?
|
||||
' Instead of passing an element string, make sure to instantiate ' +
|
||||
'it by passing it to React.createElement.' :
|
||||
ReactLegacyDescriptor.isValidFactory(nextDescriptor) ?
|
||||
ReactLegacyElement.isValidFactory(nextElement) ?
|
||||
' Instead of passing a component class, make sure to instantiate ' +
|
||||
'it by passing it to React.createElement.' :
|
||||
// Check if it quacks like a descriptor
|
||||
typeof nextDescriptor.props !== "undefined" ?
|
||||
// Check if it quacks like a element
|
||||
typeof nextElement.props !== "undefined" ?
|
||||
' This may be caused by unintentionally loading two independent ' +
|
||||
'copies of React.' :
|
||||
''
|
||||
@@ -362,11 +362,11 @@ var ReactMount = {
|
||||
var prevComponent = instancesByReactRootID[getReactRootID(container)];
|
||||
|
||||
if (prevComponent) {
|
||||
var prevDescriptor = prevComponent._descriptor;
|
||||
if (shouldUpdateReactComponent(prevDescriptor, nextDescriptor)) {
|
||||
var prevElement = prevComponent._currentElement;
|
||||
if (shouldUpdateReactComponent(prevElement, nextElement)) {
|
||||
return ReactMount._updateRootComponent(
|
||||
prevComponent,
|
||||
nextDescriptor,
|
||||
nextElement,
|
||||
container,
|
||||
callback
|
||||
);
|
||||
@@ -382,7 +382,7 @@ var ReactMount = {
|
||||
var shouldReuseMarkup = containerHasReactMarkup && !prevComponent;
|
||||
|
||||
var component = ReactMount._renderNewRootComponent(
|
||||
nextDescriptor,
|
||||
nextElement,
|
||||
container,
|
||||
shouldReuseMarkup
|
||||
);
|
||||
@@ -400,8 +400,8 @@ var ReactMount = {
|
||||
* @return {ReactComponent} Component instance rendered in `container`.
|
||||
*/
|
||||
constructAndRenderComponent: function(constructor, props, container) {
|
||||
var descriptor = createDescriptor(constructor, props);
|
||||
return ReactMount.renderComponent(descriptor, container);
|
||||
var element = createElement(constructor, props);
|
||||
return ReactMount.renderComponent(element, container);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -318,8 +318,8 @@ describe('ReactDOMComponent', function() {
|
||||
var ReactDOMComponent = require('ReactDOMComponent');
|
||||
var ReactReconcileTransaction = require('ReactReconcileTransaction');
|
||||
|
||||
var StubNativeComponent = function(descriptor) {
|
||||
ReactComponent.Mixin.construct.call(this, descriptor);
|
||||
var StubNativeComponent = function(element) {
|
||||
ReactComponent.Mixin.construct.call(this, element);
|
||||
};
|
||||
mixInto(StubNativeComponent, ReactComponent.Mixin);
|
||||
mixInto(StubNativeComponent, ReactDOMComponent.Mixin);
|
||||
|
||||
@@ -42,7 +42,7 @@ describe('ReactMount', function() {
|
||||
expect(function() {
|
||||
ReactTestUtils.renderIntoDocument('div');
|
||||
}).toThrow(
|
||||
'Invariant Violation: renderComponent(): Invalid component descriptor. ' +
|
||||
'Invariant Violation: renderComponent(): Invalid component element. ' +
|
||||
'Instead of passing an element string, make sure to instantiate it ' +
|
||||
'by passing it to React.createElement.'
|
||||
);
|
||||
@@ -57,7 +57,7 @@ describe('ReactMount', function() {
|
||||
expect(function() {
|
||||
ReactTestUtils.renderIntoDocument(Component);
|
||||
}).toThrow(
|
||||
'Invariant Violation: renderComponent(): Invalid component descriptor. ' +
|
||||
'Invariant Violation: renderComponent(): Invalid component element. ' +
|
||||
'Instead of passing a component class, make sure to instantiate it ' +
|
||||
'by passing it to React.createElement.'
|
||||
);
|
||||
|
||||
@@ -21,13 +21,13 @@
|
||||
var AutoFocusMixin = require('AutoFocusMixin');
|
||||
var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin');
|
||||
var ReactCompositeComponent = require('ReactCompositeComponent');
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactDOM = require('ReactDOM');
|
||||
|
||||
var keyMirror = require('keyMirror');
|
||||
|
||||
// Store a reference to the <button> `ReactDOMComponent`. TODO: use string
|
||||
var button = ReactDescriptor.createFactory(ReactDOM.button.type);
|
||||
var button = ReactElement.createFactory(ReactDOM.button.type);
|
||||
|
||||
var mouseListenerNames = keyMirror({
|
||||
onClick: true,
|
||||
|
||||
@@ -22,11 +22,11 @@ var EventConstants = require('EventConstants');
|
||||
var LocalEventTrapMixin = require('LocalEventTrapMixin');
|
||||
var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin');
|
||||
var ReactCompositeComponent = require('ReactCompositeComponent');
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactDOM = require('ReactDOM');
|
||||
|
||||
// Store a reference to the <form> `ReactDOMComponent`. TODO: use string
|
||||
var form = ReactDescriptor.createFactory(ReactDOM.form.type);
|
||||
var form = ReactElement.createFactory(ReactDOM.form.type);
|
||||
|
||||
/**
|
||||
* Since onSubmit doesn't bubble OR capture on the top level in IE8, we need
|
||||
|
||||
@@ -22,11 +22,11 @@ var EventConstants = require('EventConstants');
|
||||
var LocalEventTrapMixin = require('LocalEventTrapMixin');
|
||||
var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin');
|
||||
var ReactCompositeComponent = require('ReactCompositeComponent');
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactDOM = require('ReactDOM');
|
||||
|
||||
// Store a reference to the <img> `ReactDOMComponent`. TODO: use string
|
||||
var img = ReactDescriptor.createFactory(ReactDOM.img.type);
|
||||
var img = ReactElement.createFactory(ReactDOM.img.type);
|
||||
|
||||
/**
|
||||
* Since onLoad doesn't bubble OR capture on the top level in IE8, we need to
|
||||
|
||||
@@ -23,7 +23,7 @@ var DOMPropertyOperations = require('DOMPropertyOperations');
|
||||
var LinkedValueUtils = require('LinkedValueUtils');
|
||||
var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin');
|
||||
var ReactCompositeComponent = require('ReactCompositeComponent');
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactDOM = require('ReactDOM');
|
||||
var ReactMount = require('ReactMount');
|
||||
var ReactUpdates = require('ReactUpdates');
|
||||
@@ -32,7 +32,7 @@ var invariant = require('invariant');
|
||||
var merge = require('merge');
|
||||
|
||||
// Store a reference to the <input> `ReactDOMComponent`. TODO: use string
|
||||
var input = ReactDescriptor.createFactory(ReactDOM.input.type);
|
||||
var input = ReactElement.createFactory(ReactDOM.input.type);
|
||||
|
||||
var instancesByReactID = {};
|
||||
|
||||
|
||||
@@ -20,13 +20,13 @@
|
||||
|
||||
var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin');
|
||||
var ReactCompositeComponent = require('ReactCompositeComponent');
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactDOM = require('ReactDOM');
|
||||
|
||||
var warning = require('warning');
|
||||
|
||||
// Store a reference to the <option> `ReactDOMComponent`. TODO: use string
|
||||
var option = ReactDescriptor.createFactory(ReactDOM.option.type);
|
||||
var option = ReactElement.createFactory(ReactDOM.option.type);
|
||||
|
||||
/**
|
||||
* Implements an <option> native component that warns when `selected` is set.
|
||||
|
||||
@@ -22,14 +22,14 @@ var AutoFocusMixin = require('AutoFocusMixin');
|
||||
var LinkedValueUtils = require('LinkedValueUtils');
|
||||
var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin');
|
||||
var ReactCompositeComponent = require('ReactCompositeComponent');
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactDOM = require('ReactDOM');
|
||||
var ReactUpdates = require('ReactUpdates');
|
||||
|
||||
var merge = require('merge');
|
||||
|
||||
// Store a reference to the <select> `ReactDOMComponent`. TODO: use string
|
||||
var select = ReactDescriptor.createFactory(ReactDOM.select.type);
|
||||
var select = ReactElement.createFactory(ReactDOM.select.type);
|
||||
|
||||
function updateWithPendingValueIfMounted() {
|
||||
/*jshint validthis:true */
|
||||
|
||||
@@ -23,7 +23,7 @@ var DOMPropertyOperations = require('DOMPropertyOperations');
|
||||
var LinkedValueUtils = require('LinkedValueUtils');
|
||||
var ReactBrowserComponentMixin = require('ReactBrowserComponentMixin');
|
||||
var ReactCompositeComponent = require('ReactCompositeComponent');
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactDOM = require('ReactDOM');
|
||||
var ReactUpdates = require('ReactUpdates');
|
||||
|
||||
@@ -33,7 +33,7 @@ var merge = require('merge');
|
||||
var warning = require('warning');
|
||||
|
||||
// Store a reference to the <textarea> `ReactDOMComponent`. TODO: use string
|
||||
var textarea = ReactDescriptor.createFactory(ReactDOM.textarea.type);
|
||||
var textarea = ReactElement.createFactory(ReactDOM.textarea.type);
|
||||
|
||||
function forceUpdateIfMounted() {
|
||||
/*jshint validthis:true */
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
// Defeat circular references by requiring this directly.
|
||||
var ReactCompositeComponent = require('ReactCompositeComponent');
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
|
||||
var invariant = require('invariant');
|
||||
|
||||
@@ -37,7 +37,7 @@ var invariant = require('invariant');
|
||||
* @return {function} convenience constructor of new component
|
||||
*/
|
||||
function createFullPageComponent(tag) {
|
||||
var elementFactory = ReactDescriptor.createFactory(tag);
|
||||
var elementFactory = ReactElement.createFactory(tag);
|
||||
|
||||
var FullPageComponent = ReactCompositeComponent.createClass({
|
||||
displayName: 'ReactFullPageComponent' + tag,
|
||||
|
||||
+50
-50
@@ -18,7 +18,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactOwner = require('ReactOwner');
|
||||
var ReactUpdates = require('ReactUpdates');
|
||||
|
||||
@@ -147,11 +147,11 @@ var ReactComponent = {
|
||||
* @public
|
||||
*/
|
||||
setProps: function(partialProps, callback) {
|
||||
// Merge with the pending descriptor if it exists, otherwise with existing
|
||||
// descriptor props.
|
||||
var descriptor = this._pendingDescriptor || this._descriptor;
|
||||
// Merge with the pending element if it exists, otherwise with existing
|
||||
// element props.
|
||||
var element = this._pendingElement || this._currentElement;
|
||||
this.replaceProps(
|
||||
merge(descriptor.props, partialProps),
|
||||
merge(element.props, partialProps),
|
||||
callback
|
||||
);
|
||||
},
|
||||
@@ -177,10 +177,10 @@ var ReactComponent = {
|
||||
'`render` method to pass the correct value as props to the component ' +
|
||||
'where it is created.'
|
||||
);
|
||||
// This is a deoptimized path. We optimize for always having a descriptor.
|
||||
// This creates an extra internal descriptor.
|
||||
this._pendingDescriptor = ReactDescriptor.cloneAndReplaceProps(
|
||||
this._pendingDescriptor || this._descriptor,
|
||||
// This is a deoptimized path. We optimize for always having a element.
|
||||
// This creates an extra internal element.
|
||||
this._pendingElement = ReactElement.cloneAndReplaceProps(
|
||||
this._pendingElement || this._currentElement,
|
||||
props
|
||||
);
|
||||
ReactUpdates.enqueueUpdate(this, callback);
|
||||
@@ -195,12 +195,12 @@ var ReactComponent = {
|
||||
* @internal
|
||||
*/
|
||||
_setPropsInternal: function(partialProps, callback) {
|
||||
// This is a deoptimized path. We optimize for always having a descriptor.
|
||||
// This creates an extra internal descriptor.
|
||||
var descriptor = this._pendingDescriptor || this._descriptor;
|
||||
this._pendingDescriptor = ReactDescriptor.cloneAndReplaceProps(
|
||||
descriptor,
|
||||
merge(descriptor.props, partialProps)
|
||||
// This is a deoptimized path. We optimize for always having a element.
|
||||
// This creates an extra internal element.
|
||||
var element = this._pendingElement || this._currentElement;
|
||||
this._pendingElement = ReactElement.cloneAndReplaceProps(
|
||||
element,
|
||||
merge(element.props, partialProps)
|
||||
);
|
||||
ReactUpdates.enqueueUpdate(this, callback);
|
||||
},
|
||||
@@ -211,19 +211,19 @@ var ReactComponent = {
|
||||
* Subclasses that override this method should make sure to invoke
|
||||
* `ReactComponent.Mixin.construct.call(this, ...)`.
|
||||
*
|
||||
* @param {ReactDescriptor} descriptor
|
||||
* @param {ReactElement} element
|
||||
* @internal
|
||||
*/
|
||||
construct: function(descriptor) {
|
||||
construct: function(element) {
|
||||
// This is the public exposed props object after it has been processed
|
||||
// with default props. The descriptor's props represents the true internal
|
||||
// with default props. The element's props represents the true internal
|
||||
// state of the props.
|
||||
this.props = descriptor.props;
|
||||
this.props = element.props;
|
||||
// Record the component responsible for creating this component.
|
||||
// This is accessible through the descriptor but we maintain an extra
|
||||
// This is accessible through the element but we maintain an extra
|
||||
// field for compatibility with devtools and as a way to make an
|
||||
// incremental update. TODO: Consider deprecating this field.
|
||||
this._owner = descriptor._owner;
|
||||
this._owner = element._owner;
|
||||
|
||||
// All components start unmounted.
|
||||
this._lifeCycleState = ComponentLifeCycle.UNMOUNTED;
|
||||
@@ -231,10 +231,10 @@ var ReactComponent = {
|
||||
// See ReactUpdates.
|
||||
this._pendingCallbacks = null;
|
||||
|
||||
// We keep the old descriptor and a reference to the pending descriptor
|
||||
// We keep the old element and a reference to the pending element
|
||||
// to track updates.
|
||||
this._descriptor = descriptor;
|
||||
this._pendingDescriptor = null;
|
||||
this._currentElement = element;
|
||||
this._pendingElement = null;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -259,9 +259,9 @@ var ReactComponent = {
|
||||
'single component instance in multiple places.',
|
||||
rootID
|
||||
);
|
||||
var ref = this._descriptor.ref;
|
||||
var ref = this._currentElement.ref;
|
||||
if (ref != null) {
|
||||
var owner = this._descriptor._owner;
|
||||
var owner = this._currentElement._owner;
|
||||
ReactOwner.addComponentAsRefTo(this, ref, owner);
|
||||
}
|
||||
this._rootNodeID = rootID;
|
||||
@@ -285,7 +285,7 @@ var ReactComponent = {
|
||||
this.isMounted(),
|
||||
'unmountComponent(): Can only unmount a mounted component.'
|
||||
);
|
||||
var ref = this._descriptor.ref;
|
||||
var ref = this._currentElement.ref;
|
||||
if (ref != null) {
|
||||
ReactOwner.removeComponentAsRefFrom(this, ref, this._owner);
|
||||
}
|
||||
@@ -305,49 +305,49 @@ var ReactComponent = {
|
||||
* @param {ReactReconcileTransaction} transaction
|
||||
* @internal
|
||||
*/
|
||||
receiveComponent: function(nextDescriptor, transaction) {
|
||||
receiveComponent: function(nextElement, transaction) {
|
||||
invariant(
|
||||
this.isMounted(),
|
||||
'receiveComponent(...): Can only update a mounted component.'
|
||||
);
|
||||
this._pendingDescriptor = nextDescriptor;
|
||||
this._pendingElement = nextElement;
|
||||
this.performUpdateIfNecessary(transaction);
|
||||
},
|
||||
|
||||
/**
|
||||
* If `_pendingDescriptor` is set, update the component.
|
||||
* If `_pendingElement` is set, update the component.
|
||||
*
|
||||
* @param {ReactReconcileTransaction} transaction
|
||||
* @internal
|
||||
*/
|
||||
performUpdateIfNecessary: function(transaction) {
|
||||
if (this._pendingDescriptor == null) {
|
||||
if (this._pendingElement == null) {
|
||||
return;
|
||||
}
|
||||
var prevDescriptor = this._descriptor;
|
||||
var nextDescriptor = this._pendingDescriptor;
|
||||
this._descriptor = nextDescriptor;
|
||||
this.props = nextDescriptor.props;
|
||||
this._owner = nextDescriptor._owner;
|
||||
this._pendingDescriptor = null;
|
||||
this.updateComponent(transaction, prevDescriptor);
|
||||
var prevElement = this._currentElement;
|
||||
var nextElement = this._pendingElement;
|
||||
this._currentElement = nextElement;
|
||||
this.props = nextElement.props;
|
||||
this._owner = nextElement._owner;
|
||||
this._pendingElement = null;
|
||||
this.updateComponent(transaction, prevElement);
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the component's currently mounted representation.
|
||||
*
|
||||
* @param {ReactReconcileTransaction} transaction
|
||||
* @param {object} prevDescriptor
|
||||
* @param {object} prevElement
|
||||
* @internal
|
||||
*/
|
||||
updateComponent: function(transaction, prevDescriptor) {
|
||||
var nextDescriptor = this._descriptor;
|
||||
updateComponent: function(transaction, prevElement) {
|
||||
var nextElement = this._currentElement;
|
||||
|
||||
// If either the owner or a `ref` has changed, make sure the newest owner
|
||||
// has stored a reference to `this`, and the previous owner (if different)
|
||||
// has forgotten the reference to `this`. We use the descriptor instead
|
||||
// has forgotten the reference to `this`. We use the element instead
|
||||
// of the public this.props because the post processing cannot determine
|
||||
// a ref. The ref conceptually lives on the descriptor.
|
||||
// a ref. The ref conceptually lives on the element.
|
||||
|
||||
// TODO: Should this even be possible? The owner cannot change because
|
||||
// it's forbidden by shouldUpdateReactComponent. The ref can change
|
||||
@@ -355,19 +355,19 @@ var ReactComponent = {
|
||||
// is made. It probably belongs where the key checking and
|
||||
// instantiateReactComponent is done.
|
||||
|
||||
if (nextDescriptor._owner !== prevDescriptor._owner ||
|
||||
nextDescriptor.ref !== prevDescriptor.ref) {
|
||||
if (prevDescriptor.ref != null) {
|
||||
if (nextElement._owner !== prevElement._owner ||
|
||||
nextElement.ref !== prevElement.ref) {
|
||||
if (prevElement.ref != null) {
|
||||
ReactOwner.removeComponentAsRefFrom(
|
||||
this, prevDescriptor.ref, prevDescriptor._owner
|
||||
this, prevElement.ref, prevElement._owner
|
||||
);
|
||||
}
|
||||
// Correct, even if the owner is the same, and only the ref has changed.
|
||||
if (nextDescriptor.ref != null) {
|
||||
if (nextElement.ref != null) {
|
||||
ReactOwner.addComponentAsRefTo(
|
||||
this,
|
||||
nextDescriptor.ref,
|
||||
nextDescriptor._owner
|
||||
nextElement.ref,
|
||||
nextElement._owner
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
var ReactComponent = require('ReactComponent');
|
||||
var ReactContext = require('ReactContext');
|
||||
var ReactCurrentOwner = require('ReactCurrentOwner');
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactDescriptorValidator = require('ReactDescriptorValidator');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactElementValidator = require('ReactElementValidator');
|
||||
var ReactEmptyComponent = require('ReactEmptyComponent');
|
||||
var ReactErrorUtils = require('ReactErrorUtils');
|
||||
var ReactLegacyDescriptor = require('ReactLegacyDescriptor');
|
||||
var ReactLegacyElement = require('ReactLegacyElement');
|
||||
var ReactOwner = require('ReactOwner');
|
||||
var ReactPerf = require('ReactPerf');
|
||||
var ReactPropTransferer = require('ReactPropTransferer');
|
||||
@@ -471,12 +471,12 @@ function mixSpecIntoComponent(Constructor, spec) {
|
||||
}
|
||||
|
||||
invariant(
|
||||
!ReactLegacyDescriptor.isValidFactory(spec),
|
||||
!ReactLegacyElement.isValidFactory(spec),
|
||||
'ReactCompositeComponent: You\'re attempting to ' +
|
||||
'use a component class as a mixin. Instead, just use a regular object.'
|
||||
);
|
||||
invariant(
|
||||
!ReactDescriptor.isValidDescriptor(spec),
|
||||
!ReactElement.isValidElement(spec),
|
||||
'ReactCompositeComponent: You\'re attempting to ' +
|
||||
'use a component as a mixin. Instead, just use a regular object.'
|
||||
);
|
||||
@@ -713,11 +713,11 @@ var ReactCompositeComponentMixin = {
|
||||
/**
|
||||
* Base constructor for all composite component.
|
||||
*
|
||||
* @param {ReactDescriptor} descriptor
|
||||
* @param {ReactElement} element
|
||||
* @final
|
||||
* @internal
|
||||
*/
|
||||
construct: function(descriptor) {
|
||||
construct: function(element) {
|
||||
// Children can be either an array or more than one argument
|
||||
ReactComponent.Mixin.construct.apply(this, arguments);
|
||||
ReactOwner.Mixin.construct.apply(this, arguments);
|
||||
@@ -726,7 +726,7 @@ var ReactCompositeComponentMixin = {
|
||||
this._pendingState = null;
|
||||
|
||||
// This is the public post-processed context. The real context and pending
|
||||
// context lives on the descriptor.
|
||||
// context lives on the element.
|
||||
this.context = null;
|
||||
|
||||
this._compositeLifeCycleState = null;
|
||||
@@ -769,7 +769,7 @@ var ReactCompositeComponentMixin = {
|
||||
this._bindAutoBindMethods();
|
||||
}
|
||||
|
||||
this.context = this._processContext(this._descriptor._context);
|
||||
this.context = this._processContext(this._currentElement._context);
|
||||
this.props = this._processProps(this.props);
|
||||
|
||||
this.state = this.getInitialState ? this.getInitialState() : null;
|
||||
@@ -794,7 +794,7 @@ var ReactCompositeComponentMixin = {
|
||||
|
||||
this._renderedComponent = instantiateReactComponent(
|
||||
this._renderValidatedComponent(),
|
||||
this._descriptor.type // The wrapping type
|
||||
this._currentElement.type // The wrapping type
|
||||
);
|
||||
|
||||
// Done with mounting, `setState` will now trigger UI changes.
|
||||
@@ -987,7 +987,7 @@ var ReactCompositeComponentMixin = {
|
||||
* @private
|
||||
*/
|
||||
_checkPropTypes: function(propTypes, props, location) {
|
||||
// TODO: Stop validating prop types here and only use the descriptor
|
||||
// TODO: Stop validating prop types here and only use the element
|
||||
// validation.
|
||||
var componentName = this.constructor.displayName;
|
||||
for (var propName in propTypes) {
|
||||
@@ -1006,7 +1006,7 @@ var ReactCompositeComponentMixin = {
|
||||
},
|
||||
|
||||
/**
|
||||
* If any of `_pendingDescriptor`, `_pendingState`, or `_pendingForceUpdate`
|
||||
* If any of `_pendingElement`, `_pendingState`, or `_pendingForceUpdate`
|
||||
* is set, update the component.
|
||||
*
|
||||
* @param {ReactReconcileTransaction} transaction
|
||||
@@ -1021,7 +1021,7 @@ var ReactCompositeComponentMixin = {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._pendingDescriptor == null &&
|
||||
if (this._pendingElement == null &&
|
||||
this._pendingState == null &&
|
||||
!this._pendingForceUpdate) {
|
||||
return;
|
||||
@@ -1029,12 +1029,12 @@ var ReactCompositeComponentMixin = {
|
||||
|
||||
var nextContext = this.context;
|
||||
var nextProps = this.props;
|
||||
var nextDescriptor = this._descriptor;
|
||||
if (this._pendingDescriptor != null) {
|
||||
nextDescriptor = this._pendingDescriptor;
|
||||
nextContext = this._processContext(nextDescriptor._context);
|
||||
nextProps = this._processProps(nextDescriptor.props);
|
||||
this._pendingDescriptor = null;
|
||||
var nextElement = this._currentElement;
|
||||
if (this._pendingElement != null) {
|
||||
nextElement = this._pendingElement;
|
||||
nextContext = this._processContext(nextElement._context);
|
||||
nextProps = this._processProps(nextElement.props);
|
||||
this._pendingElement = null;
|
||||
|
||||
this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
|
||||
if (this.componentWillReceiveProps) {
|
||||
@@ -1066,7 +1066,7 @@ var ReactCompositeComponentMixin = {
|
||||
this._pendingForceUpdate = false;
|
||||
// Will set `this.props`, `this.state` and `this.context`.
|
||||
this._performComponentUpdate(
|
||||
nextDescriptor,
|
||||
nextElement,
|
||||
nextProps,
|
||||
nextState,
|
||||
nextContext,
|
||||
@@ -1075,14 +1075,14 @@ var ReactCompositeComponentMixin = {
|
||||
} else {
|
||||
// If it's determined that a component should not update, we still want
|
||||
// to set props and state.
|
||||
this._descriptor = nextDescriptor;
|
||||
this._currentElement = nextElement;
|
||||
this.props = nextProps;
|
||||
this.state = nextState;
|
||||
this.context = nextContext;
|
||||
|
||||
// Owner cannot change because shouldUpdateReactComponent doesn't allow
|
||||
// it. TODO: Remove this._owner completely.
|
||||
this._owner = nextDescriptor._owner;
|
||||
this._owner = nextElement._owner;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1090,7 +1090,7 @@ var ReactCompositeComponentMixin = {
|
||||
* Merges new props and state, notifies delegate methods of update and
|
||||
* performs update.
|
||||
*
|
||||
* @param {ReactDescriptor} nextDescriptor Next descriptor
|
||||
* @param {ReactElement} nextElement Next element
|
||||
* @param {object} nextProps Next public object to set as properties.
|
||||
* @param {?object} nextState Next object to set as state.
|
||||
* @param {?object} nextContext Next public object to set as context.
|
||||
@@ -1098,13 +1098,13 @@ var ReactCompositeComponentMixin = {
|
||||
* @private
|
||||
*/
|
||||
_performComponentUpdate: function(
|
||||
nextDescriptor,
|
||||
nextElement,
|
||||
nextProps,
|
||||
nextState,
|
||||
nextContext,
|
||||
transaction
|
||||
) {
|
||||
var prevDescriptor = this._descriptor;
|
||||
var prevElement = this._currentElement;
|
||||
var prevProps = this.props;
|
||||
var prevState = this.state;
|
||||
var prevContext = this.context;
|
||||
@@ -1113,18 +1113,18 @@ var ReactCompositeComponentMixin = {
|
||||
this.componentWillUpdate(nextProps, nextState, nextContext);
|
||||
}
|
||||
|
||||
this._descriptor = nextDescriptor;
|
||||
this._currentElement = nextElement;
|
||||
this.props = nextProps;
|
||||
this.state = nextState;
|
||||
this.context = nextContext;
|
||||
|
||||
// Owner cannot change because shouldUpdateReactComponent doesn't allow
|
||||
// it. TODO: Remove this._owner completely.
|
||||
this._owner = nextDescriptor._owner;
|
||||
this._owner = nextElement._owner;
|
||||
|
||||
this.updateComponent(
|
||||
transaction,
|
||||
prevDescriptor
|
||||
prevElement
|
||||
);
|
||||
|
||||
if (this.componentDidUpdate) {
|
||||
@@ -1135,22 +1135,22 @@ var ReactCompositeComponentMixin = {
|
||||
}
|
||||
},
|
||||
|
||||
receiveComponent: function(nextDescriptor, transaction) {
|
||||
if (nextDescriptor === this._descriptor &&
|
||||
nextDescriptor._owner != null) {
|
||||
// Since descriptors are immutable after the owner is rendered,
|
||||
receiveComponent: function(nextElement, transaction) {
|
||||
if (nextElement === this._currentElement &&
|
||||
nextElement._owner != null) {
|
||||
// Since elements are immutable after the owner is rendered,
|
||||
// we can do a cheap identity compare here to determine if this is a
|
||||
// superfluous reconcile. It's possible for state to be mutable but such
|
||||
// change should trigger an update of the owner which would recreate
|
||||
// the descriptor. We explicitly check for the existence of an owner since
|
||||
// it's possible for a descriptor created outside a composite to be
|
||||
// the element. We explicitly check for the existence of an owner since
|
||||
// it's possible for a element created outside a composite to be
|
||||
// deeply mutated and reused.
|
||||
return;
|
||||
}
|
||||
|
||||
ReactComponent.Mixin.receiveComponent.call(
|
||||
this,
|
||||
nextDescriptor,
|
||||
nextElement,
|
||||
transaction
|
||||
);
|
||||
},
|
||||
@@ -1162,33 +1162,33 @@ var ReactCompositeComponentMixin = {
|
||||
* Sophisticated clients may wish to override this.
|
||||
*
|
||||
* @param {ReactReconcileTransaction} transaction
|
||||
* @param {ReactDescriptor} prevDescriptor
|
||||
* @param {ReactElement} prevElement
|
||||
* @internal
|
||||
* @overridable
|
||||
*/
|
||||
updateComponent: ReactPerf.measure(
|
||||
'ReactCompositeComponent',
|
||||
'updateComponent',
|
||||
function(transaction, prevParentDescriptor) {
|
||||
function(transaction, prevParentElement) {
|
||||
ReactComponent.Mixin.updateComponent.call(
|
||||
this,
|
||||
transaction,
|
||||
prevParentDescriptor
|
||||
prevParentElement
|
||||
);
|
||||
|
||||
var prevComponentInstance = this._renderedComponent;
|
||||
var prevDescriptor = prevComponentInstance._descriptor;
|
||||
var nextDescriptor = this._renderValidatedComponent();
|
||||
if (shouldUpdateReactComponent(prevDescriptor, nextDescriptor)) {
|
||||
prevComponentInstance.receiveComponent(nextDescriptor, transaction);
|
||||
var prevElement = prevComponentInstance._currentElement;
|
||||
var nextElement = this._renderValidatedComponent();
|
||||
if (shouldUpdateReactComponent(prevElement, nextElement)) {
|
||||
prevComponentInstance.receiveComponent(nextElement, transaction);
|
||||
} else {
|
||||
// These two IDs are actually the same! But nothing should rely on that.
|
||||
var thisID = this._rootNodeID;
|
||||
var prevComponentID = prevComponentInstance._rootNodeID;
|
||||
prevComponentInstance.unmountComponent();
|
||||
this._renderedComponent = instantiateReactComponent(
|
||||
nextDescriptor,
|
||||
this._descriptor.type
|
||||
nextElement,
|
||||
this._currentElement.type
|
||||
);
|
||||
var nextMarkup = this._renderedComponent.mountComponent(
|
||||
thisID,
|
||||
@@ -1245,7 +1245,7 @@ var ReactCompositeComponentMixin = {
|
||||
var renderedComponent;
|
||||
var previousContext = ReactContext.current;
|
||||
ReactContext.current = this._processChildContext(
|
||||
this._descriptor._context
|
||||
this._currentElement._context
|
||||
);
|
||||
ReactCurrentOwner.current = this;
|
||||
try {
|
||||
@@ -1261,7 +1261,7 @@ var ReactCompositeComponentMixin = {
|
||||
ReactCurrentOwner.current = null;
|
||||
}
|
||||
invariant(
|
||||
ReactDescriptor.isValidDescriptor(renderedComponent),
|
||||
ReactElement.isValidElement(renderedComponent),
|
||||
'%s.render(): A valid ReactComponent must be returned. You may have ' +
|
||||
'returned undefined, an array or some other invalid object.',
|
||||
this.constructor.displayName || 'ReactCompositeComponent'
|
||||
@@ -1406,12 +1406,12 @@ var ReactCompositeComponent = {
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
return ReactLegacyDescriptor.wrapFactory(
|
||||
ReactDescriptorValidator.createFactory(Constructor)
|
||||
return ReactLegacyElement.wrapFactory(
|
||||
ReactElementValidator.createFactory(Constructor)
|
||||
);
|
||||
}
|
||||
return ReactLegacyDescriptor.wrapFactory(
|
||||
ReactDescriptor.createFactory(Constructor)
|
||||
return ReactLegacyElement.wrapFactory(
|
||||
ReactElement.createFactory(Constructor)
|
||||
);
|
||||
},
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @providesModule ReactDescriptor
|
||||
* @providesModule ReactElement
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
@@ -69,7 +69,7 @@ var useMutationMembrane = false;
|
||||
* Warn for mutations.
|
||||
*
|
||||
* @internal
|
||||
* @param {object} descriptor
|
||||
* @param {object} element
|
||||
*/
|
||||
function defineMutationMembrane(prototype) {
|
||||
try {
|
||||
@@ -86,7 +86,7 @@ function defineMutationMembrane(prototype) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Base constructor for all React descriptors. This is only used to make this
|
||||
* 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
|
||||
@@ -95,13 +95,13 @@ function defineMutationMembrane(prototype) {
|
||||
* @params {*} props
|
||||
* @internal
|
||||
*/
|
||||
var ReactDescriptor = function(type, key, ref, owner, context, props) {
|
||||
// Built-in properties that belong on the descriptor
|
||||
var ReactElement = function(type, key, ref, owner, context, props) {
|
||||
// Built-in properties that belong on the element
|
||||
this.type = type;
|
||||
this.key = key;
|
||||
this.ref = ref;
|
||||
|
||||
// Record the component responsible for creating this descriptor.
|
||||
// Record the component responsible for creating this element.
|
||||
this._owner = owner;
|
||||
|
||||
// TODO: Deprecate withContext, and then the context becomes accessible
|
||||
@@ -128,12 +128,12 @@ var ReactDescriptor = function(type, key, ref, owner, context, props) {
|
||||
};
|
||||
|
||||
if (__DEV__) {
|
||||
defineMutationMembrane(ReactDescriptor.prototype);
|
||||
defineMutationMembrane(ReactElement.prototype);
|
||||
}
|
||||
|
||||
ReactDescriptor.prototype._isReactDescriptor = true;
|
||||
ReactElement.prototype._isReactElement = true;
|
||||
|
||||
ReactDescriptor.createDescriptor = function(type, config, children) {
|
||||
ReactElement.createElement = function(type, config, children) {
|
||||
var propName;
|
||||
|
||||
// Reserved names are extracted
|
||||
@@ -177,7 +177,7 @@ ReactDescriptor.createDescriptor = function(type, config, children) {
|
||||
}
|
||||
}
|
||||
|
||||
return new ReactDescriptor(
|
||||
return new ReactElement(
|
||||
type,
|
||||
key,
|
||||
ref,
|
||||
@@ -187,31 +187,31 @@ ReactDescriptor.createDescriptor = function(type, config, children) {
|
||||
);
|
||||
};
|
||||
|
||||
ReactDescriptor.createFactory = function(type) {
|
||||
var factory = ReactDescriptor.createDescriptor.bind(null, type);
|
||||
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 descriptors. E.g. <Foo />.type === Foo.type.
|
||||
// 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 descriptor, and it may not even be a constructor.
|
||||
// that created the element, and it may not even be a constructor.
|
||||
factory.type = type;
|
||||
return factory;
|
||||
};
|
||||
|
||||
ReactDescriptor.cloneAndReplaceProps = function(oldDescriptor, newProps) {
|
||||
var newDescriptor = new ReactDescriptor(
|
||||
oldDescriptor.type,
|
||||
oldDescriptor.key,
|
||||
oldDescriptor.ref,
|
||||
oldDescriptor._owner,
|
||||
oldDescriptor._context,
|
||||
ReactElement.cloneAndReplaceProps = function(oldElement, newProps) {
|
||||
var newElement = new ReactElement(
|
||||
oldElement.type,
|
||||
oldElement.key,
|
||||
oldElement.ref,
|
||||
oldElement._owner,
|
||||
oldElement._context,
|
||||
newProps
|
||||
);
|
||||
|
||||
if (__DEV__) {
|
||||
// If the key on the original is valid, then the clone is valid
|
||||
newDescriptor._store.validated = oldDescriptor._store.validated;
|
||||
newElement._store.validated = oldElement._store.validated;
|
||||
}
|
||||
return newDescriptor;
|
||||
return newElement;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -219,18 +219,18 @@ ReactDescriptor.cloneAndReplaceProps = function(oldDescriptor, newProps) {
|
||||
* @return {boolean} True if `object` is a valid component.
|
||||
* @final
|
||||
*/
|
||||
ReactDescriptor.isValidDescriptor = function(object) {
|
||||
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 descriptor from a different React instance we use
|
||||
// page. To identify a element from a different React instance we use
|
||||
// a flag instead of an instanceof check.
|
||||
var isDescriptor = !!(object && object._isReactDescriptor);
|
||||
// if (isDescriptor && !(object instanceof ReactDescriptor)) {
|
||||
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 isDescriptor;
|
||||
return isElement;
|
||||
};
|
||||
|
||||
module.exports = ReactDescriptor;
|
||||
module.exports = ReactElement;
|
||||
@@ -13,19 +13,19 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @providesModule ReactDescriptorValidator
|
||||
* @providesModule ReactElementValidator
|
||||
*/
|
||||
|
||||
/**
|
||||
* ReactDescriptorValidator provides a wrapper around a descriptor factory
|
||||
* which validates the props passed to the descriptor. This is intended to be
|
||||
* ReactElementValidator provides a wrapper around a element factory
|
||||
* which validates the props passed to the element. 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 ReactElement = require('ReactElement');
|
||||
var ReactPropTypeLocations = require('ReactPropTypeLocations');
|
||||
var ReactCurrentOwner = require('ReactCurrentOwner');
|
||||
|
||||
@@ -174,11 +174,11 @@ function validateChildKeys(component, parentType) {
|
||||
if (Array.isArray(component)) {
|
||||
for (var i = 0; i < component.length; i++) {
|
||||
var child = component[i];
|
||||
if (ReactDescriptor.isValidDescriptor(child)) {
|
||||
if (ReactElement.isValidElement(child)) {
|
||||
validateExplicitKey(child, parentType);
|
||||
}
|
||||
}
|
||||
} else if (ReactDescriptor.isValidDescriptor(component)) {
|
||||
} else if (ReactElement.isValidElement(component)) {
|
||||
// This component was passed in a valid location.
|
||||
component._store.validated = true;
|
||||
} else if (component && typeof component === 'object') {
|
||||
@@ -216,7 +216,7 @@ function checkPropTypes(componentName, propTypes, props, location) {
|
||||
loggedTypeFailures[error.message] = true;
|
||||
// This will soon use the warning module
|
||||
monitorCodeUse(
|
||||
'react_failed_descriptor_type_check',
|
||||
'react_failed_element_type_check',
|
||||
{ message: error.message }
|
||||
);
|
||||
}
|
||||
@@ -224,15 +224,15 @@ function checkPropTypes(componentName, propTypes, props, location) {
|
||||
}
|
||||
}
|
||||
|
||||
var ReactDescriptorValidator = {
|
||||
var ReactElementValidator = {
|
||||
|
||||
createDescriptor: function(type, props, children) {
|
||||
var descriptor = ReactDescriptor.createDescriptor.apply(this, arguments);
|
||||
createElement: function(type, props, children) {
|
||||
var element = ReactElement.createElement.apply(this, arguments);
|
||||
|
||||
// The result can be nullish if a mock or a custom function is used.
|
||||
// TODO: Drop this when these are no longer allowed as the type argument.
|
||||
if (descriptor == null) {
|
||||
return descriptor;
|
||||
if (element == null) {
|
||||
return element;
|
||||
}
|
||||
|
||||
for (var i = 2; i < arguments.length; i++) {
|
||||
@@ -244,7 +244,7 @@ var ReactDescriptorValidator = {
|
||||
checkPropTypes(
|
||||
name,
|
||||
type.propTypes,
|
||||
descriptor.props,
|
||||
element.props,
|
||||
ReactPropTypeLocations.prop
|
||||
);
|
||||
}
|
||||
@@ -252,15 +252,15 @@ var ReactDescriptorValidator = {
|
||||
checkPropTypes(
|
||||
name,
|
||||
type.contextTypes,
|
||||
descriptor._context,
|
||||
element._context,
|
||||
ReactPropTypeLocations.context
|
||||
);
|
||||
}
|
||||
return descriptor;
|
||||
return element;
|
||||
},
|
||||
|
||||
createFactory: function(type) {
|
||||
var validatedFactory = ReactDescriptorValidator.createDescriptor.bind(
|
||||
var validatedFactory = ReactElementValidator.createElement.bind(
|
||||
null,
|
||||
type
|
||||
);
|
||||
@@ -270,4 +270,4 @@ var ReactDescriptorValidator = {
|
||||
|
||||
};
|
||||
|
||||
module.exports = ReactDescriptorValidator;
|
||||
module.exports = ReactElementValidator;
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
|
||||
var invariant = require('invariant');
|
||||
|
||||
@@ -29,7 +29,7 @@ var nullComponentIdsRegistry = {};
|
||||
|
||||
var ReactEmptyComponentInjection = {
|
||||
injectEmptyComponent: function(emptyComponent) {
|
||||
component = ReactDescriptor.createFactory(emptyComponent);
|
||||
component = ReactElement.createFactory(emptyComponent);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* @providesModule ReactLegacyDescriptor
|
||||
* @providesModule ReactLegacyElement
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
@@ -26,7 +26,7 @@ var warning = require('warning');
|
||||
|
||||
var legacyFactoryLogs = {};
|
||||
function warnForLegacyFactoryCall() {
|
||||
if (!ReactLegacyDescriptorFactory._isLegacyCallWarningEnabled) {
|
||||
if (!ReactLegacyElementFactory._isLegacyCallWarningEnabled) {
|
||||
return;
|
||||
}
|
||||
var owner = ReactCurrentOwner.current;
|
||||
@@ -118,9 +118,9 @@ function proxyStaticMethods(target, source) {
|
||||
var LEGACY_MARKER = {};
|
||||
var NON_LEGACY_MARKER = {};
|
||||
|
||||
var ReactLegacyDescriptorFactory = {};
|
||||
var ReactLegacyElementFactory = {};
|
||||
|
||||
ReactLegacyDescriptorFactory.wrapCreateFactory = function(createFactory) {
|
||||
ReactLegacyElementFactory.wrapCreateFactory = function(createFactory) {
|
||||
var legacyCreateFactory = function(type) {
|
||||
if (typeof type !== 'function') {
|
||||
// Non-function types cannot be legacy factories
|
||||
@@ -154,11 +154,11 @@ ReactLegacyDescriptorFactory.wrapCreateFactory = function(createFactory) {
|
||||
return legacyCreateFactory;
|
||||
};
|
||||
|
||||
ReactLegacyDescriptorFactory.wrapCreateDescriptor = function(createDescriptor) {
|
||||
var legacyCreateDescriptor = function(type, props, children) {
|
||||
ReactLegacyElementFactory.wrapCreateElement = function(createElement) {
|
||||
var legacyCreateElement = function(type, props, children) {
|
||||
if (typeof type !== 'function') {
|
||||
// Non-function types cannot be legacy factories
|
||||
return createDescriptor.apply(this, arguments);
|
||||
return createElement.apply(this, arguments);
|
||||
}
|
||||
|
||||
var args;
|
||||
@@ -172,7 +172,7 @@ ReactLegacyDescriptorFactory.wrapCreateDescriptor = function(createDescriptor) {
|
||||
}
|
||||
args = Array.prototype.slice.call(arguments, 0);
|
||||
args[0] = type.type;
|
||||
return createDescriptor.apply(this, args);
|
||||
return createElement.apply(this, args);
|
||||
}
|
||||
|
||||
if (type.isReactLegacyFactory) {
|
||||
@@ -186,7 +186,7 @@ ReactLegacyDescriptorFactory.wrapCreateDescriptor = function(createDescriptor) {
|
||||
}
|
||||
args = Array.prototype.slice.call(arguments, 0);
|
||||
args[0] = type.type;
|
||||
return createDescriptor.apply(this, args);
|
||||
return createElement.apply(this, args);
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
@@ -197,43 +197,43 @@ ReactLegacyDescriptorFactory.wrapCreateDescriptor = function(createDescriptor) {
|
||||
// immediately as if this was used with legacy JSX.
|
||||
return type.apply(null, Array.prototype.slice.call(arguments, 1));
|
||||
};
|
||||
return legacyCreateDescriptor;
|
||||
return legacyCreateElement;
|
||||
};
|
||||
|
||||
ReactLegacyDescriptorFactory.wrapFactory = function(factory) {
|
||||
ReactLegacyElementFactory.wrapFactory = function(factory) {
|
||||
invariant(
|
||||
typeof factory === 'function',
|
||||
'This is suppose to accept a descriptor factory'
|
||||
'This is suppose to accept a element factory'
|
||||
);
|
||||
var legacyDescriptorFactory = function(config, children) {
|
||||
var legacyElementFactory = function(config, children) {
|
||||
// This factory should not be called when JSX is used. Use JSX instead.
|
||||
if (__DEV__) {
|
||||
warnForLegacyFactoryCall();
|
||||
}
|
||||
return factory.apply(this, arguments);
|
||||
};
|
||||
proxyStaticMethods(legacyDescriptorFactory, factory.type);
|
||||
legacyDescriptorFactory.isReactLegacyFactory = LEGACY_MARKER;
|
||||
legacyDescriptorFactory.type = factory.type;
|
||||
return legacyDescriptorFactory;
|
||||
proxyStaticMethods(legacyElementFactory, factory.type);
|
||||
legacyElementFactory.isReactLegacyFactory = LEGACY_MARKER;
|
||||
legacyElementFactory.type = factory.type;
|
||||
return legacyElementFactory;
|
||||
};
|
||||
|
||||
// This is used to mark a factory that will remain. E.g. we're allowed to call
|
||||
// it as a function. However, you're not suppose to pass it to createElement
|
||||
// or createFactory, so it will warn you if you do.
|
||||
ReactLegacyDescriptorFactory.markNonLegacyFactory = function(factory) {
|
||||
ReactLegacyElementFactory.markNonLegacyFactory = function(factory) {
|
||||
factory.isReactNonLegacyFactory = NON_LEGACY_MARKER;
|
||||
return factory;
|
||||
};
|
||||
|
||||
// Checks if a factory function is actually a legacy factory pretending to
|
||||
// be a class.
|
||||
ReactLegacyDescriptorFactory.isValidFactory = function(factory) {
|
||||
ReactLegacyElementFactory.isValidFactory = function(factory) {
|
||||
// TODO: This will be removed and moved into a class validator or something.
|
||||
return typeof factory === 'function' &&
|
||||
factory.isReactLegacyFactory === LEGACY_MARKER;
|
||||
};
|
||||
|
||||
ReactLegacyDescriptorFactory._isLegacyCallWarningEnabled = true;
|
||||
ReactLegacyElementFactory._isLegacyCallWarningEnabled = true;
|
||||
|
||||
module.exports = ReactLegacyDescriptorFactory;
|
||||
module.exports = ReactLegacyElementFactory;
|
||||
@@ -286,12 +286,12 @@ var ReactMultiChild = {
|
||||
continue;
|
||||
}
|
||||
var prevChild = prevChildren && prevChildren[name];
|
||||
var prevDescriptor = prevChild && prevChild._descriptor;
|
||||
var nextDescriptor = nextChildren[name];
|
||||
if (shouldUpdateReactComponent(prevDescriptor, nextDescriptor)) {
|
||||
var prevElement = prevChild && prevChild._currentElement;
|
||||
var nextElement = nextChildren[name];
|
||||
if (shouldUpdateReactComponent(prevElement, nextElement)) {
|
||||
this.moveChild(prevChild, nextIndex, lastIndex);
|
||||
lastIndex = Math.max(prevChild._mountIndex, lastIndex);
|
||||
prevChild.receiveComponent(nextDescriptor, transaction);
|
||||
prevChild.receiveComponent(nextElement, transaction);
|
||||
prevChild._mountIndex = nextIndex;
|
||||
} else {
|
||||
if (prevChild) {
|
||||
@@ -301,7 +301,7 @@ var ReactMultiChild = {
|
||||
}
|
||||
// The child must be instantiated before it's mounted.
|
||||
var nextChildInstance = instantiateReactComponent(
|
||||
nextDescriptor,
|
||||
nextElement,
|
||||
null
|
||||
);
|
||||
this._mountChildByNameAtIndex(
|
||||
|
||||
@@ -129,21 +129,21 @@ var ReactPropTransferer = {
|
||||
*
|
||||
* This is usually used to pass down props to a returned root component.
|
||||
*
|
||||
* @param {ReactDescriptor} descriptor Component receiving the properties.
|
||||
* @return {ReactDescriptor} The supplied `component`.
|
||||
* @param {ReactElement} element Component receiving the properties.
|
||||
* @return {ReactElement} The supplied `component`.
|
||||
* @final
|
||||
* @protected
|
||||
*/
|
||||
transferPropsTo: function(descriptor) {
|
||||
transferPropsTo: function(element) {
|
||||
invariant(
|
||||
descriptor._owner === this,
|
||||
element._owner === this,
|
||||
'%s: You can\'t call transferPropsTo() on a component that you ' +
|
||||
'don\'t own, %s. This usually means you are calling ' +
|
||||
'transferPropsTo() on a component passed in as props or children.',
|
||||
this.constructor.displayName,
|
||||
typeof descriptor.type === 'string' ?
|
||||
descriptor.type :
|
||||
descriptor.type.displayName
|
||||
typeof element.type === 'string' ?
|
||||
element.type :
|
||||
element.type.displayName
|
||||
);
|
||||
|
||||
if (__DEV__) {
|
||||
@@ -157,11 +157,11 @@ var ReactPropTransferer = {
|
||||
}
|
||||
}
|
||||
|
||||
// Because descriptors are immutable we have to merge into the existing
|
||||
// Because elements are immutable we have to merge into the existing
|
||||
// props object rather than clone it.
|
||||
transferInto(descriptor.props, this.props);
|
||||
transferInto(element.props, this.props);
|
||||
|
||||
return descriptor;
|
||||
return element;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');
|
||||
|
||||
var emptyFunction = require('emptyFunction');
|
||||
@@ -160,7 +160,7 @@ function createArrayOfTypeChecker(typeChecker) {
|
||||
|
||||
function createComponentTypeChecker() {
|
||||
function validate(props, propName, componentName, location) {
|
||||
if (!ReactDescriptor.isValidDescriptor(props[propName])) {
|
||||
if (!ReactElement.isValidElement(props[propName])) {
|
||||
var locationName = ReactPropTypeLocationNames[location];
|
||||
return new Error(
|
||||
`Invalid ${locationName} \`${propName}\` supplied to ` +
|
||||
@@ -297,7 +297,7 @@ function isRenderable(propValue) {
|
||||
if (Array.isArray(propValue)) {
|
||||
return propValue.every(isRenderable);
|
||||
}
|
||||
if (ReactDescriptor.isValidDescriptor(propValue)) {
|
||||
if (ReactElement.isValidElement(propValue)) {
|
||||
return true;
|
||||
}
|
||||
for (var k in propValue) {
|
||||
|
||||
@@ -139,9 +139,9 @@ describe('ReactComponent', function() {
|
||||
}
|
||||
});
|
||||
|
||||
var descriptor = <Component />;
|
||||
var element = <Component />;
|
||||
|
||||
var instance = ReactTestUtils.renderIntoDocument(descriptor);
|
||||
var instance = ReactTestUtils.renderIntoDocument(element);
|
||||
expect(instance.isMounted()).toBeTruthy();
|
||||
});
|
||||
|
||||
|
||||
@@ -103,10 +103,10 @@ describe('ReactComponentLifeCycle', function() {
|
||||
);
|
||||
}
|
||||
});
|
||||
var descriptor = <StatefulComponent />;
|
||||
var firstInstance = React.renderComponent(descriptor, container);
|
||||
var element = <StatefulComponent />;
|
||||
var firstInstance = React.renderComponent(element, container);
|
||||
React.unmountComponentAtNode(container);
|
||||
var secondInstance = React.renderComponent(descriptor, container);
|
||||
var secondInstance = React.renderComponent(element, container);
|
||||
expect(firstInstance).not.toBe(secondInstance);
|
||||
});
|
||||
|
||||
@@ -425,7 +425,7 @@ describe('ReactComponentLifeCycle', function() {
|
||||
instance.setProps({text: "dos", tooltipText: "two"});
|
||||
});
|
||||
|
||||
it('should not allow setProps() called on an unmounted descriptor',
|
||||
it('should not allow setProps() called on an unmounted element',
|
||||
function() {
|
||||
var PropsToUpdate = React.createClass({
|
||||
render: function() {
|
||||
|
||||
@@ -114,7 +114,7 @@ describe('ReactCompositeComponent', function() {
|
||||
it('should give context for PropType errors in nested components.', () => {
|
||||
// In this test, we're making sure that if a proptype error is found in a
|
||||
// component, we give a small hint as to which parent instantiated that
|
||||
// component as per warnings about key usage in ReactDescriptorValidator.
|
||||
// component as per warnings about key usage in ReactElementValidator.
|
||||
spyOn(console, 'warn');
|
||||
var MyComp = React.createClass({
|
||||
propTypes: {
|
||||
|
||||
@@ -20,16 +20,16 @@
|
||||
"use strict";
|
||||
|
||||
var React;
|
||||
var ReactDescriptor;
|
||||
var ReactElement;
|
||||
var ReactTestUtils;
|
||||
|
||||
describe('ReactDescriptor', function() {
|
||||
describe('ReactElement', function() {
|
||||
var ComponentFactory;
|
||||
var ComponentClass;
|
||||
|
||||
beforeEach(function() {
|
||||
React = require('React');
|
||||
ReactDescriptor = require('ReactDescriptor');
|
||||
ReactElement = require('ReactElement');
|
||||
ReactTestUtils = require('ReactTestUtils');
|
||||
ComponentFactory = React.createClass({
|
||||
render: function() { return <div />; }
|
||||
@@ -37,61 +37,61 @@ describe('ReactDescriptor', function() {
|
||||
ComponentClass = ComponentFactory.type;
|
||||
});
|
||||
|
||||
it('returns a complete descriptor according to spec', function() {
|
||||
var descriptor = React.createFactory(ComponentFactory)();
|
||||
expect(descriptor.type).toBe(ComponentClass);
|
||||
expect(descriptor.key).toBe(null);
|
||||
expect(descriptor.ref).toBe(null);
|
||||
expect(descriptor.props).toEqual({});
|
||||
it('returns a complete element according to spec', function() {
|
||||
var element = React.createFactory(ComponentFactory)();
|
||||
expect(element.type).toBe(ComponentClass);
|
||||
expect(element.key).toBe(null);
|
||||
expect(element.ref).toBe(null);
|
||||
expect(element.props).toEqual({});
|
||||
});
|
||||
|
||||
it('allows a string to be passed as the type', function() {
|
||||
var descriptor = React.createFactory('div')();
|
||||
expect(descriptor.type).toBe('div');
|
||||
expect(descriptor.key).toBe(null);
|
||||
expect(descriptor.ref).toBe(null);
|
||||
expect(descriptor.props).toEqual({});
|
||||
var element = React.createFactory('div')();
|
||||
expect(element.type).toBe('div');
|
||||
expect(element.key).toBe(null);
|
||||
expect(element.ref).toBe(null);
|
||||
expect(element.props).toEqual({});
|
||||
});
|
||||
|
||||
it('returns an immutable descriptor', function() {
|
||||
var descriptor = React.createFactory(ComponentFactory)();
|
||||
expect(() => descriptor.type = 'div').toThrow();
|
||||
it('returns an immutable element', function() {
|
||||
var element = React.createFactory(ComponentFactory)();
|
||||
expect(() => element.type = 'div').toThrow();
|
||||
});
|
||||
|
||||
it('does not reuse the original config object', function() {
|
||||
var config = { foo: 1 };
|
||||
var descriptor = React.createFactory(ComponentFactory)(config);
|
||||
expect(descriptor.props.foo).toBe(1);
|
||||
var element = React.createFactory(ComponentFactory)(config);
|
||||
expect(element.props.foo).toBe(1);
|
||||
config.foo = 2;
|
||||
expect(descriptor.props.foo).toBe(1);
|
||||
expect(element.props.foo).toBe(1);
|
||||
});
|
||||
|
||||
it('extracts key and ref from the config', function() {
|
||||
var descriptor = React.createFactory(ComponentFactory)({
|
||||
var element = React.createFactory(ComponentFactory)({
|
||||
key: '12',
|
||||
ref: '34',
|
||||
foo: '56'
|
||||
});
|
||||
expect(descriptor.type).toBe(ComponentClass);
|
||||
expect(descriptor.key).toBe('12');
|
||||
expect(descriptor.ref).toBe('34');
|
||||
expect(descriptor.props).toEqual({foo:'56'});
|
||||
expect(element.type).toBe(ComponentClass);
|
||||
expect(element.key).toBe('12');
|
||||
expect(element.ref).toBe('34');
|
||||
expect(element.props).toEqual({foo:'56'});
|
||||
});
|
||||
|
||||
it('coerces the key to a string', function() {
|
||||
var descriptor = React.createFactory(ComponentFactory)({
|
||||
var element = React.createFactory(ComponentFactory)({
|
||||
key: 12,
|
||||
foo: '56'
|
||||
});
|
||||
expect(descriptor.type).toBe(ComponentClass);
|
||||
expect(descriptor.key).toBe('12');
|
||||
expect(descriptor.ref).toBe(null);
|
||||
expect(descriptor.props).toEqual({foo:'56'});
|
||||
expect(element.type).toBe(ComponentClass);
|
||||
expect(element.key).toBe('12');
|
||||
expect(element.ref).toBe(null);
|
||||
expect(element.props).toEqual({foo:'56'});
|
||||
});
|
||||
|
||||
it('preserves the context on the descriptor', function() {
|
||||
it('preserves the context on the element', function() {
|
||||
var Component = React.createFactory(ComponentFactory);
|
||||
var descriptor;
|
||||
var element;
|
||||
|
||||
var Wrapper = React.createClass({
|
||||
childContextTypes: {
|
||||
@@ -101,19 +101,19 @@ describe('ReactDescriptor', function() {
|
||||
return { foo: 'bar' };
|
||||
},
|
||||
render: function() {
|
||||
descriptor = Component();
|
||||
return descriptor;
|
||||
element = Component();
|
||||
return element;
|
||||
}
|
||||
});
|
||||
|
||||
ReactTestUtils.renderIntoDocument(<Wrapper />);
|
||||
|
||||
expect(descriptor._context).toEqual({ foo: 'bar' });
|
||||
expect(element._context).toEqual({ foo: 'bar' });
|
||||
});
|
||||
|
||||
it('preserves the owner on the descriptor', function() {
|
||||
it('preserves the owner on the element', function() {
|
||||
var Component = React.createFactory(ComponentFactory);
|
||||
var descriptor;
|
||||
var element;
|
||||
|
||||
var Wrapper = React.createClass({
|
||||
childContextTypes: {
|
||||
@@ -123,53 +123,53 @@ describe('ReactDescriptor', function() {
|
||||
return { foo: 'bar' };
|
||||
},
|
||||
render: function() {
|
||||
descriptor = Component();
|
||||
return descriptor;
|
||||
element = Component();
|
||||
return element;
|
||||
}
|
||||
});
|
||||
|
||||
var instance = ReactTestUtils.renderIntoDocument(<Wrapper />);
|
||||
|
||||
expect(descriptor._owner).toBe(instance);
|
||||
expect(element._owner).toBe(instance);
|
||||
});
|
||||
|
||||
it('merges an additional argument onto the children prop', function() {
|
||||
spyOn(console, 'warn');
|
||||
var a = 1;
|
||||
var descriptor = React.createFactory(ComponentFactory)({
|
||||
var element = React.createFactory(ComponentFactory)({
|
||||
children: 'text'
|
||||
}, a);
|
||||
expect(descriptor.props.children).toBe(a);
|
||||
expect(element.props.children).toBe(a);
|
||||
expect(console.warn.argsForCall.length).toBe(0);
|
||||
});
|
||||
|
||||
it('does not override children if no rest args are provided', function() {
|
||||
spyOn(console, 'warn');
|
||||
var descriptor = React.createFactory(ComponentFactory)({
|
||||
var element = React.createFactory(ComponentFactory)({
|
||||
children: 'text'
|
||||
});
|
||||
expect(descriptor.props.children).toBe('text');
|
||||
expect(element.props.children).toBe('text');
|
||||
expect(console.warn.argsForCall.length).toBe(0);
|
||||
});
|
||||
|
||||
it('overrides children if null is provided as an argument', function() {
|
||||
spyOn(console, 'warn');
|
||||
var descriptor = React.createFactory(ComponentFactory)({
|
||||
var element = React.createFactory(ComponentFactory)({
|
||||
children: 'text'
|
||||
}, null);
|
||||
expect(descriptor.props.children).toBe(null);
|
||||
expect(element.props.children).toBe(null);
|
||||
expect(console.warn.argsForCall.length).toBe(0);
|
||||
});
|
||||
|
||||
it('merges rest arguments onto the children prop in an array', function() {
|
||||
spyOn(console, 'warn');
|
||||
var a = 1, b = 2, c = 3;
|
||||
var descriptor = React.createFactory(ComponentFactory)(null, a, b, c);
|
||||
expect(descriptor.props.children).toEqual([1, 2, 3]);
|
||||
var element = React.createFactory(ComponentFactory)(null, a, b, c);
|
||||
expect(element.props.children).toEqual([1, 2, 3]);
|
||||
expect(console.warn.argsForCall.length).toBe(0);
|
||||
});
|
||||
|
||||
it('warns for keys for arrays of descriptors in rest args', function() {
|
||||
it('warns for keys for arrays of elements in rest args', function() {
|
||||
spyOn(console, 'warn');
|
||||
var Component = React.createFactory(ComponentFactory);
|
||||
|
||||
@@ -181,7 +181,7 @@ describe('ReactDescriptor', function() {
|
||||
);
|
||||
});
|
||||
|
||||
it('does not warn when the descriptor is directly in rest args', function() {
|
||||
it('does not warn when the element is directly in rest args', function() {
|
||||
spyOn(console, 'warn');
|
||||
var Component = React.createFactory(ComponentFactory);
|
||||
|
||||
@@ -190,7 +190,7 @@ describe('ReactDescriptor', function() {
|
||||
expect(console.warn.argsForCall.length).toBe(0);
|
||||
});
|
||||
|
||||
it('does not warn when the array contains a non-descriptor', function() {
|
||||
it('does not warn when the array contains a non-element', function() {
|
||||
spyOn(console, 'warn');
|
||||
var Component = React.createFactory(ComponentFactory);
|
||||
|
||||
@@ -216,27 +216,27 @@ describe('ReactDescriptor', function() {
|
||||
}
|
||||
});
|
||||
|
||||
var descriptor = <ComponentClass />;
|
||||
expect(descriptor.type.someStaticMethod()).toBe('someReturnValue');
|
||||
var element = <ComponentClass />;
|
||||
expect(element.type.someStaticMethod()).toBe('someReturnValue');
|
||||
expect(console.warn.argsForCall.length).toBe(0);
|
||||
});
|
||||
|
||||
it('identifies valid descriptors', function() {
|
||||
it('identifies valid elements', function() {
|
||||
var Component = React.createClass({
|
||||
render: function() {
|
||||
return <div />;
|
||||
}
|
||||
});
|
||||
|
||||
expect(ReactDescriptor.isValidDescriptor(<div />)).toEqual(true);
|
||||
expect(ReactDescriptor.isValidDescriptor(<Component />)).toEqual(true);
|
||||
expect(ReactElement.isValidElement(<div />)).toEqual(true);
|
||||
expect(ReactElement.isValidElement(<Component />)).toEqual(true);
|
||||
|
||||
expect(ReactDescriptor.isValidDescriptor(null)).toEqual(false);
|
||||
expect(ReactDescriptor.isValidDescriptor(true)).toEqual(false);
|
||||
expect(ReactDescriptor.isValidDescriptor({})).toEqual(false);
|
||||
expect(ReactDescriptor.isValidDescriptor("string")).toEqual(false);
|
||||
expect(ReactDescriptor.isValidDescriptor(React.DOM.div)).toEqual(false);
|
||||
expect(ReactDescriptor.isValidDescriptor(Component)).toEqual(false);
|
||||
expect(ReactElement.isValidElement(null)).toEqual(false);
|
||||
expect(ReactElement.isValidElement(true)).toEqual(false);
|
||||
expect(ReactElement.isValidElement({})).toEqual(false);
|
||||
expect(ReactElement.isValidElement("string")).toEqual(false);
|
||||
expect(ReactElement.isValidElement(React.DOM.div)).toEqual(false);
|
||||
expect(ReactElement.isValidElement(Component)).toEqual(false);
|
||||
});
|
||||
|
||||
it('warns but allow a plain function in a factory to be invoked', function() {
|
||||
@@ -256,7 +256,7 @@ describe('ReactDescriptor', function() {
|
||||
|
||||
it('warns but allow a plain function to be immediately invoked', function() {
|
||||
spyOn(console, 'warn');
|
||||
var result = React.createDescriptor(function (x, y) {
|
||||
var result = React.createElement(function (x, y) {
|
||||
return 21 + x + y;
|
||||
}, 11, 10);
|
||||
expect(result).toBe(42);
|
||||
@@ -269,7 +269,7 @@ describe('ReactDescriptor', function() {
|
||||
it('warns but does not fail on undefined results', function() {
|
||||
spyOn(console, 'warn');
|
||||
var fn = function () { };
|
||||
var result = React.createDescriptor(fn, 1, 2, null);
|
||||
var result = React.createElement(fn, 1, 2, null);
|
||||
expect(result).toBe(undefined);
|
||||
expect(console.warn.argsForCall.length).toBe(1);
|
||||
expect(console.warn.argsForCall[0][0]).toContain(
|
||||
@@ -297,9 +297,9 @@ describe('ReactDescriptor', function() {
|
||||
expect(typeof Component.specialType.isRequired).toBe("function");
|
||||
});
|
||||
|
||||
it('allows a DOM descriptor to be used with a string', function() {
|
||||
var descriptor = React.createDescriptor('div', { className: 'foo' });
|
||||
var instance = ReactTestUtils.renderIntoDocument(descriptor);
|
||||
it('allows a DOM element to be used with a string', function() {
|
||||
var element = React.createElement('div', { className: 'foo' });
|
||||
var instance = ReactTestUtils.renderIntoDocument(element);
|
||||
expect(instance.getDOMNode().tagName).toBe('DIV');
|
||||
});
|
||||
|
||||
|
||||
@@ -21,48 +21,47 @@
|
||||
|
||||
var warning = require('warning');
|
||||
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactLegacyDescriptor = require('ReactLegacyDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactLegacyElement = require('ReactLegacyElement');
|
||||
var ReactNativeComponent = require('ReactNativeComponent');
|
||||
var ReactEmptyComponent = require('ReactEmptyComponent');
|
||||
|
||||
/**
|
||||
* Given a `componentDescriptor` create an instance that will actually be
|
||||
* mounted.
|
||||
* Given an `element` create an instance that will actually be mounted.
|
||||
*
|
||||
* @param {object} descriptor
|
||||
* @param {object} element
|
||||
* @param {*} parentCompositeType The composite type that resolved this.
|
||||
* @return {object} A new instance of the descriptor's constructor.
|
||||
* @return {object} A new instance of the element's constructor.
|
||||
* @protected
|
||||
*/
|
||||
function instantiateReactComponent(descriptor, parentCompositeType) {
|
||||
function instantiateReactComponent(element, parentCompositeType) {
|
||||
var instance;
|
||||
|
||||
if (__DEV__) {
|
||||
warning(
|
||||
descriptor && (typeof descriptor.type === 'function' ||
|
||||
typeof descriptor.type === 'string'),
|
||||
element && (typeof element.type === 'function' ||
|
||||
typeof element.type === 'string'),
|
||||
'Only functions or strings can be mounted as React components.'
|
||||
);
|
||||
|
||||
// Resolve mock instances
|
||||
if (descriptor.type._mockedReactClassConstructor) {
|
||||
if (element.type._mockedReactClassConstructor) {
|
||||
// If this is a mocked class, we treat the legacy factory as if it was the
|
||||
// class constructor for future proofing unit tests. Because this might
|
||||
// be mocked as a legacy factory, we ignore any warnings triggerd by
|
||||
// this temporary hack.
|
||||
ReactLegacyDescriptor._isLegacyCallWarningEnabled = false;
|
||||
ReactLegacyElement._isLegacyCallWarningEnabled = false;
|
||||
try {
|
||||
instance = new descriptor.type._mockedReactClassConstructor(
|
||||
descriptor.props
|
||||
instance = new element.type._mockedReactClassConstructor(
|
||||
element.props
|
||||
);
|
||||
} finally {
|
||||
ReactLegacyDescriptor._isLegacyCallWarningEnabled = true;
|
||||
ReactLegacyElement._isLegacyCallWarningEnabled = true;
|
||||
}
|
||||
|
||||
// If the mock implementation was a legacy factory, then it returns a
|
||||
// descriptor. We need to turn this into a real component instance.
|
||||
if (ReactDescriptor.isValidDescriptor(instance)) {
|
||||
// element. We need to turn this into a real component instance.
|
||||
if (ReactElement.isValidElement(instance)) {
|
||||
instance = new instance.type(instance.props);
|
||||
}
|
||||
|
||||
@@ -71,7 +70,7 @@ function instantiateReactComponent(descriptor, parentCompositeType) {
|
||||
// For auto-mocked factories, the prototype isn't shimmed and therefore
|
||||
// there is no render function on the instance. We replace the whole
|
||||
// component with an empty component instance instead.
|
||||
descriptor = ReactEmptyComponent.getEmptyComponent();
|
||||
element = ReactEmptyComponent.getEmptyComponent();
|
||||
} else {
|
||||
if (render._isMockFunction && !render._getMockImplementation()) {
|
||||
// Auto-mocked components may have a prototype with a mocked render
|
||||
@@ -81,22 +80,22 @@ function instantiateReactComponent(descriptor, parentCompositeType) {
|
||||
ReactEmptyComponent.getEmptyComponent
|
||||
);
|
||||
}
|
||||
instance.construct(descriptor);
|
||||
instance.construct(element);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Special case string values
|
||||
if (typeof descriptor.type === 'string') {
|
||||
if (typeof element.type === 'string') {
|
||||
instance = ReactNativeComponent.createInstanceForTag(
|
||||
descriptor.type,
|
||||
descriptor.props,
|
||||
element.type,
|
||||
element.props,
|
||||
parentCompositeType
|
||||
);
|
||||
} else {
|
||||
// Normal case for non-mocks and non-strings
|
||||
instance = new descriptor.type(descriptor.props);
|
||||
instance = new element.type(element.props);
|
||||
}
|
||||
|
||||
if (__DEV__) {
|
||||
@@ -110,7 +109,7 @@ function instantiateReactComponent(descriptor, parentCompositeType) {
|
||||
|
||||
// This actually sets up the internal instance. This will become decoupled
|
||||
// from the public instance in a future diff.
|
||||
instance.construct(descriptor);
|
||||
instance.construct(element);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -20,21 +20,21 @@
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Given a `prevDescriptor` and `nextDescriptor`, determines if the existing
|
||||
* Given a `prevElement` and `nextElement`, determines if the existing
|
||||
* instance should be updated as opposed to being destroyed or replaced by a new
|
||||
* instance. Both arguments are descriptors. This ensures that this logic can
|
||||
* instance. Both arguments are elements. This ensures that this logic can
|
||||
* operate on stateless trees without any backing instance.
|
||||
*
|
||||
* @param {?object} prevDescriptor
|
||||
* @param {?object} nextDescriptor
|
||||
* @param {?object} prevElement
|
||||
* @param {?object} nextElement
|
||||
* @return {boolean} True if the existing instance should be updated.
|
||||
* @protected
|
||||
*/
|
||||
function shouldUpdateReactComponent(prevDescriptor, nextDescriptor) {
|
||||
if (prevDescriptor && nextDescriptor &&
|
||||
prevDescriptor.type === nextDescriptor.type &&
|
||||
prevDescriptor.key === nextDescriptor.key &&
|
||||
prevDescriptor._owner === nextDescriptor._owner) {
|
||||
function shouldUpdateReactComponent(prevElement, nextElement) {
|
||||
if (prevElement && nextElement &&
|
||||
prevElement.type === nextElement.type &&
|
||||
prevElement.key === nextElement.key &&
|
||||
prevElement._owner === nextElement._owner) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
+11
-11
@@ -22,7 +22,7 @@ var EventConstants = require('EventConstants');
|
||||
var EventPluginHub = require('EventPluginHub');
|
||||
var EventPropagators = require('EventPropagators');
|
||||
var React = require('React');
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
|
||||
var ReactMount = require('ReactMount');
|
||||
var ReactTextComponent = require('ReactTextComponent');
|
||||
@@ -55,13 +55,13 @@ var ReactTestUtils = {
|
||||
return React.renderComponent(instance, div);
|
||||
},
|
||||
|
||||
isDescriptor: function(descriptor) {
|
||||
return ReactDescriptor.isValidDescriptor(descriptor);
|
||||
isElement: function(element) {
|
||||
return ReactElement.isValidElement(element);
|
||||
},
|
||||
|
||||
isDescriptorOfType: function(inst, convenienceConstructor) {
|
||||
isElementOfType: function(inst, convenienceConstructor) {
|
||||
return (
|
||||
ReactDescriptor.isValidDescriptor(inst) &&
|
||||
ReactElement.isValidElement(inst) &&
|
||||
inst.type === convenienceConstructor.type
|
||||
);
|
||||
},
|
||||
@@ -70,9 +70,9 @@ var ReactTestUtils = {
|
||||
return !!(inst && inst.mountComponent && inst.tagName);
|
||||
},
|
||||
|
||||
isDOMComponentDescriptor: function(inst) {
|
||||
isDOMComponentElement: function(inst) {
|
||||
return !!(inst &&
|
||||
ReactDescriptor.isValidDescriptor(inst) &&
|
||||
ReactElement.isValidElement(inst) &&
|
||||
!!inst.tagName);
|
||||
},
|
||||
|
||||
@@ -86,8 +86,8 @@ var ReactTestUtils = {
|
||||
(inst.constructor === type.type));
|
||||
},
|
||||
|
||||
isCompositeComponentDescriptor: function(inst) {
|
||||
if (!ReactDescriptor.isValidDescriptor(inst)) {
|
||||
isCompositeComponentElement: function(inst) {
|
||||
if (!ReactElement.isValidElement(inst)) {
|
||||
return false;
|
||||
}
|
||||
// We check the prototype of the type that will get mounted, not the
|
||||
@@ -99,8 +99,8 @@ var ReactTestUtils = {
|
||||
);
|
||||
},
|
||||
|
||||
isCompositeComponentDescriptorWithType: function(inst, type) {
|
||||
return !!(ReactTestUtils.isCompositeComponentDescriptor(inst) &&
|
||||
isCompositeComponentElementWithType: function(inst, type) {
|
||||
return !!(ReactTestUtils.isCompositeComponentElement(inst) &&
|
||||
(inst.constructor === type));
|
||||
},
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ function reactComponentExpect(instance) {
|
||||
this._instance = instance;
|
||||
expect(typeof instance).toBe('object');
|
||||
expect(typeof instance.constructor).toBe('function');
|
||||
expect(ReactTestUtils.isDescriptor(instance)).toBe(false);
|
||||
expect(ReactTestUtils.isElement(instance)).toBe(false);
|
||||
}
|
||||
|
||||
mergeInto(reactComponentExpect.prototype, {
|
||||
@@ -109,7 +109,7 @@ mergeInto(reactComponentExpect.prototype, {
|
||||
convenienceConstructor :
|
||||
convenienceConstructor.type;
|
||||
expect(
|
||||
this.instance()._descriptor.type === type
|
||||
this.instance()._currentElement.type === type
|
||||
).toBe(true);
|
||||
return this;
|
||||
},
|
||||
@@ -129,7 +129,7 @@ mergeInto(reactComponentExpect.prototype, {
|
||||
toBeCompositeComponentWithType: function(convenienceConstructor) {
|
||||
this.toBeCompositeComponent();
|
||||
expect(
|
||||
this.instance()._descriptor.type === convenienceConstructor.type
|
||||
this.instance()._currentElement.type === convenienceConstructor.type
|
||||
).toBe(true);
|
||||
return this;
|
||||
},
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactPropTransferer = require('ReactPropTransferer');
|
||||
|
||||
var keyOf = require('keyOf');
|
||||
@@ -55,8 +55,8 @@ function cloneWithProps(child, props) {
|
||||
}
|
||||
|
||||
// The current API doesn't retain _owner and _context, which is why this
|
||||
// doesn't use ReactDescriptor.cloneAndReplaceProps.
|
||||
return ReactDescriptor.createDescriptor(child.type, newProps);
|
||||
// doesn't use ReactElement.cloneAndReplaceProps.
|
||||
return ReactElement.createElement(child.type, newProps);
|
||||
}
|
||||
|
||||
module.exports = cloneWithProps;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
|
||||
var invariant = require('invariant');
|
||||
|
||||
@@ -34,7 +34,7 @@ var invariant = require('invariant');
|
||||
*/
|
||||
function onlyChild(children) {
|
||||
invariant(
|
||||
ReactDescriptor.isValidDescriptor(children),
|
||||
ReactElement.isValidElement(children),
|
||||
'onlyChild must be passed a children with exactly one child.'
|
||||
);
|
||||
return children;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var ReactDescriptor = require('ReactDescriptor');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactInstanceHandles = require('ReactInstanceHandles');
|
||||
|
||||
var invariant = require('invariant');
|
||||
@@ -128,7 +128,7 @@ var traverseAllChildrenImpl =
|
||||
callback(traverseContext, null, storageName, indexSoFar);
|
||||
subtreeCount = 1;
|
||||
} else if (type === 'string' || type === 'number' ||
|
||||
ReactDescriptor.isValidDescriptor(children)) {
|
||||
ReactElement.isValidElement(children)) {
|
||||
callback(traverseContext, children, storageName, indexSoFar);
|
||||
subtreeCount = 1;
|
||||
} else if (type === 'object') {
|
||||
|
||||
Reference in New Issue
Block a user