Skip to content

Commit

Permalink
Merge pull request facebook#2550 from sebmarkbage/cleanupinternals
Browse files Browse the repository at this point in the history
Move ComponentEnvironment out of ReactComponent
  • Loading branch information
sebmarkbage committed Nov 18, 2014
2 parents ef3b348 + 5951a13 commit e3e0bf5
Show file tree
Hide file tree
Showing 10 changed files with 105 additions and 49 deletions.
13 changes: 8 additions & 5 deletions src/browser/ui/ReactComponentBrowserEnvironment.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,19 @@

var ReactDOMIDOperations = require('ReactDOMIDOperations');
var ReactMount = require('ReactMount');
var ReactReconcileTransaction = require('ReactReconcileTransaction');

/**
* Abstracts away all functionality of `ReactComponent` requires knowledge of
* the browser context.
* Abstracts away all functionality of the reconciler that requires knowledge of
* the browser context. TODO: These callers should be refactored to avoid the
* need for this injection.
*/
var ReactComponentBrowserEnvironment = {
ReactReconcileTransaction: ReactReconcileTransaction,

BackendIDOperations: ReactDOMIDOperations,
processChildrenUpdates:
ReactDOMIDOperations.dangerouslyProcessChildrenUpdates,

replaceNodeWithMarkupByID:
ReactDOMIDOperations.dangerouslyReplaceNodeWithMarkupByID,

/**
* If a particular environment requires that some resources be cleaned up,
Expand Down
24 changes: 19 additions & 5 deletions src/browser/ui/ReactDOMComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ var STYLE = keyOf({style: null});

var ELEMENT_NODE_TYPE = 1;

/**
* Optionally injectable operations for mutating the DOM
*/
var BackendIDOperations = null;

/**
* @param {?object} props
*/
Expand Down Expand Up @@ -149,6 +154,7 @@ function ReactDOMComponent(tag) {
this._tag = tag;
this._renderedChildren = null;
this._previousStyleCopy = null;
this._rootNodeID = null;
}

ReactDOMComponent.displayName = 'ReactDOMComponent';
Expand Down Expand Up @@ -177,7 +183,7 @@ ReactDOMComponent.Mixin = {
mountDepth,
context
);
this._previousStyleCopy = null;
this._rootNodeID = rootID;
assertValidProps(this._currentElement.props);
var closeTag = omittedCloseTags[this._tag] ? '' : '</' + this._tag + '>';
return (
Expand Down Expand Up @@ -370,7 +376,7 @@ ReactDOMComponent.Mixin = {
} else if (
DOMProperty.isStandardName[propKey] ||
DOMProperty.isCustomAttribute(propKey)) {
ReactComponent.BackendIDOperations.deletePropertyByID(
BackendIDOperations.deletePropertyByID(
this._rootNodeID,
propKey
);
Expand Down Expand Up @@ -414,15 +420,15 @@ ReactDOMComponent.Mixin = {
} else if (
DOMProperty.isStandardName[propKey] ||
DOMProperty.isCustomAttribute(propKey)) {
ReactComponent.BackendIDOperations.updatePropertyByID(
BackendIDOperations.updatePropertyByID(
this._rootNodeID,
propKey,
nextProp
);
}
}
if (styleUpdates) {
ReactComponent.BackendIDOperations.updateStylesByID(
BackendIDOperations.updateStylesByID(
this._rootNodeID,
styleUpdates
);
Expand Down Expand Up @@ -472,7 +478,7 @@ ReactDOMComponent.Mixin = {
}
} else if (nextHtml != null) {
if (lastHtml !== nextHtml) {
ReactComponent.BackendIDOperations.updateInnerHTMLByID(
BackendIDOperations.updateInnerHTMLByID(
this._rootNodeID,
nextHtml
);
Expand All @@ -492,6 +498,8 @@ ReactDOMComponent.Mixin = {
this.unmountChildren();
ReactBrowserEventEmitter.deleteAllListeners(this._rootNodeID);
ReactComponent.Mixin.unmountComponent.call(this);
ReactMount.purgeID(this._rootNodeID);
this._rootNodeID = null;
}

};
Expand All @@ -503,4 +511,10 @@ assign(
ReactMultiChild.Mixin
);

ReactDOMComponent.injection = {
injectIDOperations: function(IDOperations) {
ReactDOMComponent.BackendIDOperations = BackendIDOperations = IDOperations;
}
};

module.exports = ReactDOMComponent;
2 changes: 1 addition & 1 deletion src/browser/ui/ReactDOMIDOperations.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ var INVALID_PROPERTY_ERRORS = {

/**
* Operations used to process updates to DOM nodes. This is made injectable via
* `ReactComponent.BackendIDOperations`.
* `ReactDOMComponent.BackendIDOperations`.
*/
var ReactDOMIDOperations = {

Expand Down
4 changes: 2 additions & 2 deletions src/browser/ui/ReactDOMTextComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
"use strict";

var DOMPropertyOperations = require('DOMPropertyOperations');
var ReactComponent = require('ReactComponent');
var ReactComponentBrowserEnvironment =
require('ReactComponentBrowserEnvironment');
var ReactDOMComponent = require('ReactDOMComponent');

var assign = require('Object.assign');
var escapeTextForBrowser = require('escapeTextForBrowser');
Expand Down Expand Up @@ -100,7 +100,7 @@ assign(ReactDOMTextComponent.prototype, {
// and/or updateComponent to do the actual update for consistency with
// other component types?
this._stringText = nextStringText;
ReactComponent.BackendIDOperations.updateTextContentByID(
ReactDOMComponent.BackendIDOperations.updateTextContentByID(
this._rootNodeID,
nextStringText
);
Expand Down
5 changes: 4 additions & 1 deletion src/browser/ui/ReactDefaultInjection.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var ReactDOMComponent = require('ReactDOMComponent');
var ReactDOMButton = require('ReactDOMButton');
var ReactDOMForm = require('ReactDOMForm');
var ReactDOMImg = require('ReactDOMImg');
var ReactDOMIDOperations = require('ReactDOMIDOperations');
var ReactDOMInput = require('ReactDOMInput');
var ReactDOMOption = require('ReactDOMOption');
var ReactDOMSelect = require('ReactDOMSelect');
Expand All @@ -37,6 +38,7 @@ var ReactEventListener = require('ReactEventListener');
var ReactInjection = require('ReactInjection');
var ReactInstanceHandles = require('ReactInstanceHandles');
var ReactMount = require('ReactMount');
var ReactReconcileTransaction = require('ReactReconcileTransaction');
var SelectEventPlugin = require('SelectEventPlugin');
var ServerReactRootIndex = require('ServerReactRootIndex');
var SimpleEventPlugin = require('SimpleEventPlugin');
Expand Down Expand Up @@ -102,7 +104,7 @@ function inject() {
ReactInjection.EmptyComponent.injectEmptyComponent('noscript');

ReactInjection.Updates.injectReconcileTransaction(
ReactComponentBrowserEnvironment.ReactReconcileTransaction
ReactReconcileTransaction
);
ReactInjection.Updates.injectBatchingStrategy(
ReactDefaultBatchingStrategy
Expand All @@ -115,6 +117,7 @@ function inject() {
);

ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment);
ReactInjection.DOMComponent.injectIDOperations(ReactDOMIDOperations);

if (__DEV__) {
var url = (ExecutionEnvironment.canUseDOM && window.location.href) || '';
Expand Down
6 changes: 4 additions & 2 deletions src/browser/ui/ReactInjection.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,20 @@

var DOMProperty = require('DOMProperty');
var EventPluginHub = require('EventPluginHub');
var ReactComponent = require('ReactComponent');
var ReactComponentEnvironment = require('ReactComponentEnvironment');
var ReactClass = require('ReactClass');
var ReactEmptyComponent = require('ReactEmptyComponent');
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
var ReactNativeComponent = require('ReactNativeComponent');
var ReactDOMComponent = require('ReactDOMComponent');
var ReactPerf = require('ReactPerf');
var ReactRootIndex = require('ReactRootIndex');
var ReactUpdates = require('ReactUpdates');

var ReactInjection = {
Component: ReactComponent.injection,
Component: ReactComponentEnvironment.injection,
Class: ReactClass.injection,
DOMComponent: ReactDOMComponent.injection,
DOMProperty: DOMProperty.injection,
EmptyComponent: ReactEmptyComponent.injection,
EventPluginHub: EventPluginHub.injection,
Expand Down
30 changes: 0 additions & 30 deletions src/core/ReactComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,6 @@ var ReactRef = require('ReactRef');

var invariant = require('invariant');

var injected = false;

/**
* Optionally injectable environment dependent cleanup hook. (server vs.
* browser etc). Example: A browser system caches DOM nodes based on component
* ID and must remove that cache entry when this instance is unmounted.
*
* @private
*/
var unmountIDFromEnvironment = null;

function attachRef(ref, component, owner) {
if (ref instanceof ReactRef) {
ReactRef.attachRef(ref, component);
Expand Down Expand Up @@ -70,20 +59,6 @@ function detachRef(ref, component, owner) {
*/
var ReactComponent = {

injection: {
injectEnvironment: function(ReactComponentEnvironment) {
invariant(
!injected,
'ReactComponent: injectEnvironment() can only be called once.'
);
unmountIDFromEnvironment =
ReactComponentEnvironment.unmountIDFromEnvironment;
ReactComponent.BackendIDOperations =
ReactComponentEnvironment.BackendIDOperations;
injected = true;
}
},

/**
* Injected module that provides ability to mutate individual properties.
* Injected into the base class because many different subclasses need access
Expand Down Expand Up @@ -114,7 +89,6 @@ var ReactComponent = {
// We keep the old element and a reference to the pending element
// to track updates.
this._currentElement = element;
this._rootNodeID = null;
this._mountIndex = 0;
this._mountDepth = 0;
},
Expand All @@ -140,7 +114,6 @@ var ReactComponent = {
var owner = this._currentElement._owner;
attachRef(ref, this, owner);
}
this._rootNodeID = rootID;
this._mountDepth = mountDepth;
// Effectively: return '';
},
Expand All @@ -160,9 +133,6 @@ var ReactComponent = {
if (ref != null) {
detachRef(ref, this, this._currentElement._owner);
}
unmountIDFromEnvironment(this._rootNodeID);
// Reset all fields
this._rootNodeID = null;
},

/**
Expand Down
57 changes: 57 additions & 0 deletions src/core/ReactComponentEnvironment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* Copyright 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactComponentEnvironment
*/

"use strict";

var invariant = require('invariant');

var injected = false;

var ReactComponentEnvironment = {

/**
* Optionally injectable environment dependent cleanup hook. (server vs.
* browser etc). Example: A browser system caches DOM nodes based on component
* ID and must remove that cache entry when this instance is unmounted.
*/
unmountIDFromEnvironment: null,

/**
* Optionally injectable hook for swapping out mount images in the middle of
* the tree.
*/
replaceNodeWithMarkupByID: null,

/**
* Optionally injectable hook for processing a queue of child updates. Will
* later move into MultiChildComponents.
*/
processChildrenUpdates: null,

injection: {
injectEnvironment: function(environment) {
invariant(
!injected,
'ReactCompositeComponent: injectEnvironment() can only be called once.'
);
ReactComponentEnvironment.unmountIDFromEnvironment =
environment.unmountIDFromEnvironment;
ReactComponentEnvironment.replaceNodeWithMarkupByID =
environment.replaceNodeWithMarkupByID;
ReactComponentEnvironment.processChildrenUpdates =
environment.processChildrenUpdates;
injected = true;
}
},

};

module.exports = ReactComponentEnvironment;
9 changes: 8 additions & 1 deletion src/core/ReactCompositeComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"use strict";

var ReactComponent = require('ReactComponent');
var ReactComponentEnvironment = require('ReactComponentEnvironment');
var ReactContext = require('ReactContext');
var ReactCurrentOwner = require('ReactCurrentOwner');
var ReactElement = require('ReactElement');
Expand Down Expand Up @@ -112,6 +113,8 @@ var ReactCompositeComponentMixin = assign({},
* @internal
*/
construct: function(element) {
this._rootNodeID = null;

this._instance.props = element.props;
this._instance.state = null;
this._instance.context = null;
Expand Down Expand Up @@ -168,6 +171,7 @@ var ReactCompositeComponentMixin = assign({},
);

this._context = context;
this._rootNodeID = rootID;

var inst = this._instance;

Expand Down Expand Up @@ -259,7 +263,10 @@ var ReactCompositeComponentMixin = assign({},

ReactComponent.Mixin.unmountComponent.call(this);

ReactComponentEnvironment.unmountIDFromEnvironment(this._rootNodeID);

this._context = null;
this._rootNodeID = null;

// Delete the reference from the instance to this internal representation
// which allow the internals to be properly cleaned up even if the user
Expand Down Expand Up @@ -780,7 +787,7 @@ var ReactCompositeComponentMixin = assign({},
this._mountDepth + 1,
context
);
ReactComponent.BackendIDOperations.dangerouslyReplaceNodeWithMarkupByID(
ReactComponentEnvironment.replaceNodeWithMarkupByID(
prevComponentID,
nextMarkup
);
Expand Down
4 changes: 2 additions & 2 deletions src/core/ReactMultiChild.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

"use strict";

var ReactComponent = require('ReactComponent');
var ReactComponentEnvironment = require('ReactComponentEnvironment');
var ReactMultiChildUpdateTypes = require('ReactMultiChildUpdateTypes');

var flattenChildren = require('flattenChildren');
Expand Down Expand Up @@ -136,7 +136,7 @@ function enqueueTextContent(parentID, textContent) {
*/
function processQueue() {
if (updateQueue.length) {
ReactComponent.BackendIDOperations.dangerouslyProcessChildrenUpdates(
ReactComponentEnvironment.processChildrenUpdates(
updateQueue,
markupQueue
);
Expand Down

0 comments on commit e3e0bf5

Please sign in to comment.