Skip to content

Commit

Permalink
Address ownership issue when rendering using reclaimed DOM. Seems to …
Browse files Browse the repository at this point in the history
…be a fix for #297.
  • Loading branch information
developit committed Sep 23, 2016
1 parent 9cf3137 commit 2743a80
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 33 deletions.
1 change: 1 addition & 0 deletions src/dom/recycler.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ATTR_KEY } from '../constants';
import { toLowerCase } from '../util';
import { ensureNodeData, getRawNodeAttributes, removeNode } from './index';

Expand Down
25 changes: 14 additions & 11 deletions src/vdom/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function setComponentProps(component, props, opts, context, mountAll) {
* @param {boolean} [opts.build=false] If `true`, component will build and store a DOM node if not already associated with one.
* @private
*/
export function renderComponent(component, opts, mountAll) {
export function renderComponent(component, opts, mountAll, isChild) {
if (component._disableRendering) return;

let skip, rendered,
Expand All @@ -72,8 +72,10 @@ export function renderComponent(component, opts, mountAll) {
previousState = component.prevState || state,
previousContext = component.prevContext || context,
isUpdate = component.base,
initialBase = isUpdate || component.nextBase,
initialChildComponent = component._component;
nextBase = component.nextBase,
initialBase = isUpdate || nextBase,
initialChildComponent = component._component,
inst;

// if updating
if (isUpdate) {
Expand Down Expand Up @@ -111,23 +113,25 @@ export function renderComponent(component, opts, mountAll) {
let childComponent = rendered && rendered.nodeName,
toUnmount, base;

if (isFunction(childComponent) && childComponent.prototype.render) {
if (isFunction(childComponent)) {
// set up high order component link

let inst = initialChildComponent,
childProps = getNodeProps(rendered);

inst = initialChildComponent;
let childProps = getNodeProps(rendered);

if (inst && inst.constructor===childComponent) {
setComponentProps(inst, childProps, SYNC_RENDER, context);
}
else {
toUnmount = inst;

inst = createComponent(childComponent, childProps, context);
inst.nextBase = inst.nextBase || mountAll && initialBase;
inst.nextBase = inst.nextBase || nextBase;
inst._parentComponent = component;
component._component = inst;
setComponentProps(inst, childProps, NO_RENDER, context);
renderComponent(inst, SYNC_RENDER);
renderComponent(inst, SYNC_RENDER, mountAll, true);
}

base = inst.base;
Expand All @@ -147,7 +151,7 @@ export function renderComponent(component, opts, mountAll) {
}
}

if (initialBase && base!==initialBase) {
if (initialBase && base!==initialBase && inst!==initialChildComponent) {
let baseParent = initialBase.parentNode;
if (baseParent && base!==baseParent) {
baseParent.replaceChild(base, initialBase);
Expand Down Expand Up @@ -175,7 +179,6 @@ export function renderComponent(component, opts, mountAll) {

if (!isUpdate || mountAll) {
mounts.unshift(component);
if (!diffLevel) flushMounts();
}
else if (!skip && component.componentDidUpdate) {
component.componentDidUpdate(previousProps, previousState, previousContext);
Expand All @@ -184,7 +187,7 @@ export function renderComponent(component, opts, mountAll) {
let cb = component._renderCallbacks, fn;
if (cb) while ( (fn = cb.pop()) ) fn.call(component);

return rendered;
if (!diffLevel && !isChild) flushMounts();
}


Expand Down
31 changes: 9 additions & 22 deletions src/vdom/diff.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,32 +31,23 @@ export function flushMounts() {
* @returns {Element} dom The created/mutated element
* @private
*/
export function diff(dom, vnode, context, mountAll, parent, rootComponent) {
export function diff(dom, vnode, context, mountAll, parent, componentRoot) {
diffLevel++;
let ret = idiff(dom, vnode, context, mountAll, rootComponent);
let ret = idiff(dom, vnode, context, mountAll);
if (parent && ret.parentNode!==parent) parent.appendChild(ret);
if (!--diffLevel) flushMounts();
if (!--diffLevel && !componentRoot) flushMounts();
return ret;
}


function idiff(dom, vnode, context, mountAll, rootComponent) {
function idiff(dom, vnode, context, mountAll) {
let originalAttributes = vnode && vnode.attributes;

while (isFunctionalComponent(vnode)) {
vnode = buildFunctionalComponent(vnode, context);
}

if (empty(vnode)) {
vnode = '';
if (rootComponent) {
if (dom) {
if (dom.nodeType===8) return dom;
recollectNodeTree(dom);
}
return document.createComment(vnode);
}
}
if (empty(vnode)) vnode = '';

if (isString(vnode)) {
if (dom) {
Expand Down Expand Up @@ -179,18 +170,15 @@ function innerDiffNode(dom, vchildren, context, mountAll) {
// morph the matched/found/created DOM child to match vchild (deep)
child = idiff(child, vchild, context, mountAll);

if (child!==originalChildren[i]) {
if (child && child!==dom && child!==originalChildren[i]) {
dom.insertBefore(child, originalChildren[i] || null);
}
}
}


if (keyedLen) {
/*eslint guard-for-in:0*/
for (let i in keyed) if (keyed[i]) {
children[min=childrenLen++] = keyed[i];
}
for (let i in keyed) if (keyed[i]) recollectNodeTree(keyed[i]);
}

// remove orphaned children
Expand All @@ -203,9 +191,8 @@ function innerDiffNode(dom, vchildren, context, mountAll) {
/** Reclaim children that were unreferenced in the desired VTree */
export function removeOrphanedChildren(children, unmountOnly) {
for (let i=children.length; i--; ) {
let child = children[i];
if (child) {
recollectNodeTree(child, unmountOnly);
if (children[i]) {
recollectNodeTree(children[i], unmountOnly);
}
}
}
Expand Down

0 comments on commit 2743a80

Please sign in to comment.