Skip to content

Commit

Permalink
Avoid saving logical info on parent when a content is added inside a …
Browse files Browse the repository at this point in the history
…fragment + slight factoring.
  • Loading branch information
Steven Orvell committed Aug 18, 2015
1 parent ee61627 commit 36072be
Showing 1 changed file with 65 additions and 58 deletions.
123 changes: 65 additions & 58 deletions src/lib/dom-api.html
Original file line number Diff line number Diff line change
Expand Up @@ -57,62 +57,59 @@
}
},

// cases in which we may not be able to just do standard appendChild
appendChild: function(node) {
return this._addNode(node);
},

insertBefore: function(node, ref_node) {
return this._addNode(node, ref_node);
},

// cases in which we may not be able to just do standard native call
// 1. container has a shadyRoot (needsDistribution IFF the shadyRoot
// has an insertion point)
// 2. container is a shadyRoot (don't distribute, instead set
// container to container.host.
// 3. node is <content> (host of container needs distribution)
appendChild: function(node) {
this._removeNodeFromHost(node, true);
// if a <content> is added, make sure it's parent has logical info.
if (this.getOwnerRoot()) {
this._ensureContentLogicalInfo(node);
}
if (this._nodeIsInLogicalTree(this.node)) {
this._addLogicalInfo(node, this.node);
}
this._addNodeToHost(node);
// if not distributing and not adding to host, do a fast path addition
if (!this._maybeDistribute(node, this.node) &&
!this._tryRemoveUndistributedNode(node)) {
// if adding to a shadyRoot, add to host instead
var container = this.node._isShadyRoot ? this.node.host : this.node;
addToComposedParent(container, node);
nativeAppendChild.call(container, node);
}
return node;
},

insertBefore: function(node, ref_node) {
if (!ref_node) {
return this.appendChild(node);
}
_addNode: function(node, ref_node) {
this._removeNodeFromHost(node, true);
var addedInsertionPoint;
var root = this.getOwnerRoot();
// if a <content> is added, make sure it's parent has logical info.
if (this.getOwnerRoot()) {
this._ensureContentLogicalInfo(node);
}
if (this._nodeIsInLogicalTree(this.node)) {
var children = this.childNodes;
var index = children.indexOf(ref_node);
if (index < 0) {
throw Error('The ref_node to be inserted before is not a child ' +
'of this node');
if (root) {
addedInsertionPoint = this._maybeAddInsertionPoint(node, this.node);
}
if (this._nodeHasLogicalChildren(this.node)) {
if (ref_node) {
var children = this.childNodes;
var index = children.indexOf(ref_node);
if (index < 0) {
throw Error('The ref_node to be inserted before is not a child ' +
'of this node');
}
}
this._addLogicalInfo(node, this.node, index);
}
this._addNodeToHost(node);
// if not distributing and not adding to host, do a fast path addition
if (!this._maybeDistribute(node, this.node) &&
!this._tryRemoveUndistributedNode(node)) {
// if ref_node is <content> replace with first distributed node
ref_node = ref_node.localName === CONTENT ?
this._firstComposedNode(ref_node) : ref_node;
if (ref_node) {
// if ref_node is <content> replace with first distributed node
ref_node = ref_node.localName === CONTENT ?
this._firstComposedNode(ref_node) : ref_node;
}
// if adding to a shadyRoot, add to host instead
var container = this.node._isShadyRoot ? this.node.host : this.node;
addToComposedParent(container, node, ref_node);
nativeInsertBefore.call(container, node, ref_node);
if (ref_node) {
nativeInsertBefore.call(container, node, ref_node);
} else {
nativeAppendChild.call(container, node);
}
}
if (addedInsertionPoint) {
this._updateInsertionPoints(root.host);
}
return node;
},
Expand Down Expand Up @@ -198,7 +195,8 @@
var root = this._ownerShadyRootForNode(parent);
if (root) {
var host = root.host;
this._updateInsertionPoints(host);
// note, insertion point list update is handled after node
// mutations are complete
this._lazyDistribute(host);
}
}
Expand All @@ -214,6 +212,30 @@
return parentNeedsDist || (hasContent && !wrappedContent);
},

/* note: parent argument is required since node may have an out
of date parent at this point; returns true if a <content> is being added */
_maybeAddInsertionPoint: function(node, parent) {
var added;
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE &&
!node.__noContent) {
var c$ = factory(node).querySelectorAll(CONTENT);
for (var i=0, n, np, na; (i<c$.length) && (n=c$[i]); i++) {
np = factory(n).parentNode;
// don't allow node's parent to be fragment itself
if (np === node) {
np = parent;
}
na = this._maybeAddInsertionPoint(n, np);
added = added || na;
}
} else if (node.localName === CONTENT) {
saveLightChildrenIfNeeded(parent);
saveLightChildrenIfNeeded(node);
added = true;
}
return added;
},

_tryRemoveUndistributedNode: function(node) {
if (this.node.shadyRoot) {
if (node._composedParent) {
Expand All @@ -234,24 +256,9 @@
}
},

// a node has logical info associated with it
_nodeIsInLogicalTree: function(node) {
return Boolean(node._lightParent !== undefined ||
node._lightChildren !== undefined);
},

_ensureContentLogicalInfo: function(node) {
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE &&
!node.__noContent) {
var c$ = factory(node).querySelectorAll(CONTENT);
for (var i=0, n; (i<c$.length) && (n=c$[i]); i++) {
this._ensureContentLogicalInfo(n);
}
} else if (node.localName === CONTENT) {
// should be parent not this.node, but this is before parent is set.
saveLightChildrenIfNeeded(this.node);
saveLightChildrenIfNeeded(node);
}
// a node has logical children
_nodeHasLogicalChildren: function(node) {
return Boolean(node._lightChildren !== undefined);
},

_parentNeedsDistribution: function(parent) {
Expand Down

0 comments on commit 36072be

Please sign in to comment.