Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Move child recursion to ReactReconciler #6011

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/renderers/dom/client/utils/DOMLazyTree.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ var enableLazy = (
/\bEdge\/\d/.test(navigator.userAgent)
);

var TREE_TYPE = 'dom';

function insertTreeChildren(tree) {
if (!enableLazy) {
return;
Expand Down Expand Up @@ -86,13 +88,15 @@ function queueText(tree, text) {

function DOMLazyTree(node) {
return {
lazy: TREE_TYPE,
node: node,
children: [],
html: null,
text: null,
};
}

DOMLazyTree.treeType = TREE_TYPE;
DOMLazyTree.insertTreeBefore = insertTreeBefore;
DOMLazyTree.replaceChildWithTree = replaceChildWithTree;
DOMLazyTree.queueChild = queueChild;
Expand Down
4 changes: 3 additions & 1 deletion src/renderers/dom/server/ReactServerRendering.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
'use strict';

var ReactDOMContainerInfo = require('ReactDOMContainerInfo');
var ReactReconciler = require('ReactReconciler');
var ReactDefaultBatchingStrategy = require('ReactDefaultBatchingStrategy');
var ReactElement = require('ReactElement');
var ReactMarkupChecksum = require('ReactMarkupChecksum');
Expand Down Expand Up @@ -41,7 +42,8 @@ function renderToStringImpl(element, makeStaticMarkup) {

return transaction.perform(function() {
var componentInstance = instantiateReactComponent(element);
var markup = componentInstance.mountComponent(
var markup = ReactReconciler.mountComponent(
componentInstance,
transaction,
null,
ReactDOMContainerInfo(),
Expand Down
20 changes: 11 additions & 9 deletions src/renderers/dom/shared/ReactDOMComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -571,10 +571,15 @@ ReactDOMComponent.Mixin = {
mountImage = tagOpen + '/>';
} else {
mountImage =
tagOpen + '>' + tagContent + '</' + this._currentElement.type + '>';
[tagOpen + '>'].concat(tagContent, '</' + this._currentElement.type + '>');
}
}

return mountImage;
},

postMount: function(transaction) {
var props = this._currentElement.props;
switch (this._tag) {
case 'button':
case 'input':
Expand All @@ -588,8 +593,6 @@ ReactDOMComponent.Mixin = {
}
break;
}

return mountImage;
},

/**
Expand Down Expand Up @@ -691,7 +694,7 @@ ReactDOMComponent.Mixin = {
transaction,
context
);
ret = mountImages.join('');
ret = mountImages;
}
}
if (newlineEatingTags[this._tag] && ret.charAt(0) === '\n') {
Expand All @@ -716,24 +719,23 @@ ReactDOMComponent.Mixin = {
var innerHTML = props.dangerouslySetInnerHTML;
if (innerHTML != null) {
if (innerHTML.__html != null) {
DOMLazyTree.queueHTML(lazyTree, innerHTML.__html);
lazyTree.html = innerHTML.__html;
}
} else {
var contentToUse =
CONTENT_TYPES[typeof props.children] ? props.children : null;
var childrenToUse = contentToUse != null ? null : props.children;
if (contentToUse != null) {
// TODO: Validate that text is allowed as a child of this node
DOMLazyTree.queueText(lazyTree, contentToUse);
lazyTree.text = contentToUse;
} else if (childrenToUse != null) {
var mountImages = this.mountChildren(
childrenToUse,
transaction,
context
);
for (var i = 0; i < mountImages.length; i++) {
DOMLazyTree.queueChild(lazyTree, mountImages[i]);
}
lazyTree.children = mountImages;
return mountImages;
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion src/renderers/dom/shared/ReactDOMTextComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ assign(ReactDOMTextComponent.prototype, {
var el = ownerDocument.createElement('span');
ReactDOMComponentTree.precacheNode(this, el);
var lazyTree = DOMLazyTree(el);
DOMLazyTree.queueText(lazyTree, this._stringText);
lazyTree.text = this._stringText;
return lazyTree;
} else {
var escapedText = escapeTextContentForBrowser(this._stringText);
Expand Down
4 changes: 4 additions & 0 deletions src/renderers/dom/shared/ReactDefaultInjection.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ var ReactReconcileTransaction = require('ReactReconcileTransaction');
var SVGDOMPropertyConfig = require('SVGDOMPropertyConfig');
var SelectEventPlugin = require('SelectEventPlugin');
var SimpleEventPlugin = require('SimpleEventPlugin');
var DOMLazyTree = require('DOMLazyTree');


var alreadyInjected = false;

Expand Down Expand Up @@ -92,6 +94,8 @@ function inject() {

ReactInjection.Component.injectEnvironment(ReactComponentBrowserEnvironment);

ReactInjection.ReactReconciler.injectLazyTreeImpl(DOMLazyTree);

if (__DEV__) {
var url = (ExecutionEnvironment.canUseDOM && window.location.href) || '';
if ((/[?&]react_perf\b/).test(url)) {
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/dom/shared/ReactInjection.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var ReactEmptyComponent = require('ReactEmptyComponent');
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');
var ReactNativeComponent = require('ReactNativeComponent');
var ReactPerf = require('ReactPerf');
var ReactReconciler = require('ReactReconciler');
var ReactUpdates = require('ReactUpdates');

var ReactInjection = {
Expand All @@ -32,6 +33,7 @@ var ReactInjection = {
EventEmitter: ReactBrowserEventEmitter.injection,
NativeComponent: ReactNativeComponent.injection,
Perf: ReactPerf.injection,
ReactReconciler: ReactReconciler.injection,
Updates: ReactUpdates.injection,
};

Expand Down
26 changes: 13 additions & 13 deletions src/renderers/shared/reconciler/ReactCompositeComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,10 +289,6 @@ var ReactCompositeComponentMixin = {
markup = this.performInitialMount(renderedElement, nativeParent, nativeContainerInfo, transaction, context);
}

if (inst.componentDidMount) {
transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
}

return markup;
},

Expand Down Expand Up @@ -347,21 +343,25 @@ var ReactCompositeComponentMixin = {
renderedElement
);

var markup = ReactReconciler.mountComponent(
this._renderedComponent,
transaction,
nativeParent,
nativeContainerInfo,
this._processChildContext(context)
);

return markup;
return this._renderedComponent;
},

getNativeNode: function() {
return ReactReconciler.getNativeNode(this._renderedComponent);
},

/**
* Called after recursion of children has completed
* @final
* @internal
*/
postMount: function(transaction) {
var inst = this._instance;
if (inst.componentDidMount) {
transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
}
},

/**
* Releases any resources allocated by `mountComponent`.
*
Expand Down
9 changes: 1 addition & 8 deletions src/renderers/shared/reconciler/ReactMultiChild.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,15 +219,8 @@ var ReactMultiChild = {
for (var name in children) {
if (children.hasOwnProperty(name)) {
var child = children[name];
var mountImage = ReactReconciler.mountComponent(
child,
transaction,
this,
this._nativeContainerInfo,
context
);
child._mountIndex = index++;
mountImages.push(mountImage);
mountImages.push(child);
}
}
return mountImages;
Expand Down
90 changes: 88 additions & 2 deletions src/renderers/shared/reconciler/ReactReconciler.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ function attachRefs() {
ReactRef.attachRefs(this, this._currentElement);
}

var lazyTreeImpls = {};

var ReactReconciler = {

/**
Expand All @@ -41,17 +43,95 @@ var ReactReconciler = {
nativeContainerInfo,
context
) {
var markup = internalInstance.mountComponent(
var child = internalInstance.mountComponent(
transaction,
nativeParent,
nativeContainerInfo,
context
);

if (internalInstance._currentElement &&
internalInstance._currentElement.ref != null) {
transaction.getReactMountReady().enqueue(attachRefs, internalInstance);
}
return markup;

var join = true;
if (!Array.isArray(child)) {
child = [child];
join = false;
}
var processedChildren = child.map(function processChild(childOfChild) {
return ReactReconciler.processChild(
childOfChild,
internalInstance,
transaction,
nativeParent,
nativeContainerInfo,
context
);
});

return join ? processedChildren.join('') : processedChildren[0];
},

processChild: function(
child,
internalInstance,
transaction,
nativeParent,
nativeContainerInfo,
context
) {
if ('string' === typeof child || 'number' === typeof child) {
return child;
} else if (child.lazy) {
var lazyImpl = lazyTreeImpls[child.lazy];
// DOMLazyTree
if (child.html) {
// dangerouslySetInnerHTML
lazyImpl.queueHTML(child, child.html);
} else if (child.text) {
// ReactTextComponent
lazyImpl.queueText(child, child.text);
} else if (child.children) {
// ReactDOMComponent
for (var i=0; i<child.children.length; ++i) {
var childOfChild = child.children[i];
var childMountImage = ReactReconciler.mountComponent(
childOfChild,
transaction,
internalInstance,
internalInstance._nativeContainerInfo,
internalInstance._processChildContext ?
internalInstance._processChildContext(context) : context,
);
lazyImpl.queueChild(child, childMountImage);

if (internalInstance.postMount) {
internalInstance.postMount(transaction);
}
}
} else {
throw new Error('Unknown child type');
}
return child;
} else {
// ReactCompositeComponent
var mountImage = ReactReconciler.mountComponent(
child,
transaction,
nativeParent,
internalInstance._nativeContainerInfo,
internalInstance._processChildContext ?
internalInstance._processChildContext(context) : context,
);

if (internalInstance.postMount) {
internalInstance.postMount(transaction);
}

return mountImage;
}
},

/**
Expand Down Expand Up @@ -135,6 +215,12 @@ var ReactReconciler = {
internalInstance.performUpdateIfNecessary(transaction);
},

injection: {
injectLazyTreeImpl: function(lazyTreeImpl) {
lazyTreeImpls[lazyTreeImpl.treeType] = lazyTreeImpl;
},
},

};

module.exports = ReactReconciler;
8 changes: 1 addition & 7 deletions src/renderers/shared/reconciler/ReactSimpleEmptyComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,7 @@ assign(ReactSimpleEmptyComponent.prototype, {
nativeContainerInfo,
context
) {
return ReactReconciler.mountComponent(
this._renderedComponent,
transaction,
nativeParent,
nativeContainerInfo,
context
);
return this._renderedComponent;
},
receiveComponent: function() {
},
Expand Down