Merge pull request #575 from spicyj/owner

Move __owner__ off of props
This commit is contained in:
Pete Hunt
2013-11-21 17:44:48 -08:00
6 changed files with 58 additions and 22 deletions
+22 -14
View File
@@ -81,8 +81,8 @@ function validateExplicitKey(component) {
if (!component.isOwnedBy(ReactCurrentOwner.current)) {
// Name of the component that originally created this child.
var childOwnerName =
component.props.__owner__ &&
component.props.__owner__.constructor.displayName;
component._owner &&
component._owner.constructor.displayName;
// Usually the current owner is the offender, but if it accepts
// children as a property, it may be the creator of the child that's
@@ -260,7 +260,7 @@ var ReactComponent = {
*/
replaceProps: function(props, callback) {
invariant(
!this.props.__owner__,
!this._owner,
'replaceProps(...): You called `setProps` or `replaceProps` on a ' +
'component with an owner. This is an anti-pattern since props will ' +
'get reactively updated when rendered. Instead, change the owner\'s ' +
@@ -288,13 +288,19 @@ var ReactComponent = {
construct: function(initialProps, children) {
this.props = initialProps || {};
// Record the component responsible for creating this component.
this.props.__owner__ = ReactCurrentOwner.current;
this._owner = ReactCurrentOwner.current;
// All components start unmounted.
this._lifeCycleState = ComponentLifeCycle.UNMOUNTED;
this._pendingProps = null;
this._pendingCallbacks = null;
// Unlike _pendingProps and _pendingCallbacks, we won't use null to
// indicate that nothing is pending because it's possible for a component
// to have a null owner. Instead, an owner change is pending when
// this._owner !== this._pendingOwner.
this._pendingOwner = this._owner;
// Children can be more than one argument
var childrenLength = arguments.length - 1;
if (childrenLength === 1) {
@@ -336,7 +342,7 @@ var ReactComponent = {
);
var props = this.props;
if (props.ref != null) {
ReactOwner.addComponentAsRefTo(this, props.ref, props.__owner__);
ReactOwner.addComponentAsRefTo(this, props.ref, this._owner);
}
this._rootNodeID = rootID;
this._lifeCycleState = ComponentLifeCycle.MOUNTED;
@@ -361,7 +367,7 @@ var ReactComponent = {
);
var props = this.props;
if (props.ref != null) {
ReactOwner.removeComponentAsRefFrom(this, props.ref, props.__owner__);
ReactOwner.removeComponentAsRefFrom(this, props.ref, this._owner);
}
ReactComponent.unmountIDFromEnvironment(this._rootNodeID);
this._rootNodeID = null;
@@ -384,6 +390,7 @@ var ReactComponent = {
this.isMounted(),
'receiveComponent(...): Can only update a mounted component.'
);
this._pendingOwner = nextComponent._owner;
this._pendingProps = nextComponent.props;
this._performUpdateIfNecessary(transaction);
},
@@ -411,9 +418,11 @@ var ReactComponent = {
return;
}
var prevProps = this.props;
var prevOwner = this._owner;
this.props = this._pendingProps;
this._owner = this._pendingOwner;
this._pendingProps = null;
this.updateComponent(transaction, prevProps);
this.updateComponent(transaction, prevProps, prevOwner);
},
/**
@@ -423,21 +432,20 @@ var ReactComponent = {
* @param {object} prevProps
* @internal
*/
updateComponent: function(transaction, prevProps) {
updateComponent: function(transaction, prevProps, prevOwner) {
var props = this.props;
// 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`.
if (props.__owner__ !== prevProps.__owner__ ||
props.ref !== prevProps.ref) {
if (this._owner !== prevOwner || props.ref !== prevProps.ref) {
if (prevProps.ref != null) {
ReactOwner.removeComponentAsRefFrom(
this, prevProps.ref, prevProps.__owner__
this, prevProps.ref, prevOwner
);
}
// Correct, even if the owner is the same, and only the ref has changed.
if (props.ref != null) {
ReactOwner.addComponentAsRefTo(this, props.ref, props.__owner__);
ReactOwner.addComponentAsRefTo(this, props.ref, this._owner);
}
}
},
@@ -491,7 +499,7 @@ var ReactComponent = {
* @internal
*/
isOwnedBy: function(owner) {
return this.props.__owner__ === owner;
return this._owner === owner;
},
/**
@@ -503,7 +511,7 @@ var ReactComponent = {
* @internal
*/
getSiblingByRef: function(ref) {
var owner = this.props.__owner__;
var owner = this._owner;
if (!owner || !owner.refs) {
return null;
}
+27 -3
View File
@@ -841,6 +841,12 @@ var ReactCompositeComponentMixin = {
this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_STATE;
// Unlike props, state, and context, we specifically don't want to set
// _pendingOwner to null here because it's possible for a component to have
// a null owner, so we instead make `this._owner === this._pendingOwner`
// mean that there's no owner change pending.
var nextOwner = this._pendingOwner;
var nextState = this._pendingState || this.state;
this._pendingState = null;
@@ -851,6 +857,7 @@ var ReactCompositeComponentMixin = {
// Will set `this.props`, `this.state` and `this.context`.
this._performComponentUpdate(
nextProps,
nextOwner,
nextState,
nextFullContext,
nextContext,
@@ -860,6 +867,7 @@ var ReactCompositeComponentMixin = {
// If it's determined that a component should not update, we still want
// to set props and state.
this.props = nextProps;
this._owner = nextOwner;
this.state = nextState;
this._currentContext = nextFullContext;
this.context = nextContext;
@@ -873,6 +881,7 @@ var ReactCompositeComponentMixin = {
* performs update.
*
* @param {object} nextProps Next object to set as properties.
* @param {?ReactComponent} nextOwner Next component to set as owner
* @param {?object} nextState Next object to set as state.
* @param {?object} nextFullContext Next object to set as _currentContext.
* @param {?object} nextContext Next object to set as context.
@@ -881,12 +890,14 @@ var ReactCompositeComponentMixin = {
*/
_performComponentUpdate: function(
nextProps,
nextOwner,
nextState,
nextFullContext,
nextContext,
transaction
) {
var prevProps = this.props;
var prevOwner = this._owner;
var prevState = this.state;
var prevContext = this.context;
@@ -895,11 +906,18 @@ var ReactCompositeComponentMixin = {
}
this.props = nextProps;
this._owner = nextOwner;
this.state = nextState;
this._currentContext = nextFullContext;
this.context = nextContext;
this.updateComponent(transaction, prevProps, prevState, prevContext);
this.updateComponent(
transaction,
prevProps,
prevOwner,
prevState,
prevContext
);
if (this.componentDidUpdate) {
transaction.getReactMountReady().enqueue(
@@ -926,6 +944,7 @@ var ReactCompositeComponentMixin = {
*
* @param {ReactReconcileTransaction} transaction
* @param {object} prevProps
* @param {?ReactComponent} prevOwner
* @param {?object} prevState
* @param {?object} prevContext
* @internal
@@ -934,8 +953,13 @@ var ReactCompositeComponentMixin = {
updateComponent: ReactPerf.measure(
'ReactCompositeComponent',
'updateComponent',
function(transaction, prevProps, prevState, prevContext) {
ReactComponent.Mixin.updateComponent.call(this, transaction, prevProps);
function(transaction, prevProps, prevOwner, prevState, prevContext) {
ReactComponent.Mixin.updateComponent.call(
this,
transaction,
prevProps,
prevOwner
);
var prevComponent = this._renderedComponent;
var nextComponent = this._renderValidatedComponent();
if (shouldUpdateReactComponent(prevComponent, nextComponent)) {
+7 -2
View File
@@ -200,8 +200,13 @@ ReactDOMComponent.Mixin = {
updateComponent: ReactPerf.measure(
'ReactDOMComponent',
'updateComponent',
function(transaction, prevProps) {
ReactComponent.Mixin.updateComponent.call(this, transaction, prevProps);
function(transaction, prevProps, prevOwner) {
ReactComponent.Mixin.updateComponent.call(
this,
transaction,
prevProps,
prevOwner
);
this._updateDOMProperties(prevProps);
this._updateDOMChildren(prevProps, transaction);
}
+1 -1
View File
@@ -92,7 +92,7 @@ var ReactPropTransferer = {
*/
transferPropsTo: function(component) {
invariant(
component.props.__owner__ === this,
component._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.',
+1 -1
View File
@@ -32,7 +32,7 @@ function shouldUpdateReactComponent(prevComponent, nextComponent) {
// TODO: Remove warning after a release.
if (prevComponent && nextComponent &&
prevComponent.constructor === nextComponent.constructor) {
if (prevComponent.props.__owner__ === nextComponent.props.__owner__) {
if (prevComponent._owner === nextComponent._owner) {
return true;
} else {
if (__DEV__) {
-1
View File
@@ -30,7 +30,6 @@ var processAttributeNameAndPrefix = memoizeStringOnly(function(name) {
if (__DEV__) {
var reactProps = {
__owner__: true,
children: true,
dangerouslySetInnerHTML: true,
key: true,