Skip to content
This repository has been archived by the owner on Mar 13, 2018. It is now read-only.

Commit

Permalink
Micro optimize rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
arv committed Sep 6, 2013
1 parent 0d9408d commit cf62307
Showing 1 changed file with 35 additions and 43 deletions.
78 changes: 35 additions & 43 deletions src/ShadowRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
(function(scope) {
'use strict';

var Element = scope.wrappers.Element;
var HTMLContentElement = scope.wrappers.HTMLContentElement;
var HTMLShadowElement = scope.wrappers.HTMLShadowElement;
var Node = scope.wrappers.Node;
Expand Down Expand Up @@ -137,9 +138,7 @@
*/
function visit(tree, predicate, visitor) {
// This operates on logical DOM.
var nodes = getChildNodesSnapshot(tree);
for (var i = 0; i < nodes.length; i++) {
var node = nodes[i];
for (var node = tree.firstChild; node; node = node.nextSibling) {
if (predicate(node)) {
if (visitor(node) === false)
return;
Expand Down Expand Up @@ -190,14 +189,14 @@
if (!select)
return true;

if (node.nodeType !== Node.ELEMENT_NODE)
if (!(node instanceof Element))
return false;

// TODO(arv): This does not seem right. Need to check for a simple selector.
if (!selectorMatchRegExp.test(select))
return false;

if (select[0] === ':' &&!allowedPseudoRegExp.test(select))
if (select[0] === ':' && !allowedPseudoRegExp.test(select))
return false;

try {
Expand All @@ -219,9 +218,9 @@
var renderTimer;

function renderAllPending() {
pendingDirtyRenderers.forEach(function(owner) {
owner.render();
});
for (var i = 0; i < pendingDirtyRenderers.length; i++) {
pendingDirtyRenderers[i].render();
}
pendingDirtyRenderers = [];
}

Expand Down Expand Up @@ -351,10 +350,9 @@
var topMostRenderer = !renderNode;
var renderNode = opt_renderNode || new RenderNode(host);

var shadowDOMChildNodes = getChildNodesSnapshot(shadowRoot);
shadowDOMChildNodes.forEach(function(node) {
for (var node = shadowRoot.firstChild; node; node = node.nextSibling) {
this.renderNode(shadowRoot, renderNode, node, false);
}, this);
}

if (topMostRenderer)
renderNode.sync();
Expand Down Expand Up @@ -394,15 +392,14 @@
var renderer = getRendererForHost(node);
renderer.render(renderNode);
} else {
var parent = node;
var logicalChildNodes = getChildNodesSnapshot(parent);
// We associate the parent of a content/shadow with the renderer
// because we may need to remove stale childNodes.
if (shadowDOMRendererTable.get(parent))
this.associateNode(parent);
logicalChildNodes.forEach(function(node) {
this.renderNode(shadowRoot, renderNode, node, isNested);
}, this);
if (shadowDOMRendererTable.get(node))
this.associateNode(node);

for (var child = parent.firstChild; child; child = child.nextSibling) {
this.renderNode(shadowRoot, renderNode, child, isNested);
}
}
},

Expand All @@ -412,12 +409,13 @@
if (distributedChildNodes.length) {
this.associateNode(insertionPoint);

distributedChildNodes.forEach(function(child) {
for (var i = 0; i < distributedChildNodes.length; i++) {
var child = distributedChildNodes[i];
if (isInsertionPoint(child) && isNested)
this.renderInsertionPoint(shadowRoot, renderNode, child, isNested);
else
this.renderAsAnyDomTree(shadowRoot, renderNode, child, isNested);
}, this);
}
} else {
this.renderFallbackContent(shadowRoot, renderNode, insertionPoint);
}
Expand All @@ -430,23 +428,24 @@
if (nextOlderTree) {
assignToInsertionPoint(nextOlderTree, shadowInsertionPoint);
this.associateNode(shadowInsertionPoint.parentNode);
var shadowDOMChildNodes = getChildNodesSnapshot(nextOlderTree);
shadowDOMChildNodes.forEach(function(node) {
for (var node = nextOlderTree.firstChild;
node;
node = node.nextSibling) {
this.renderNode(nextOlderTree, renderNode, node, true);
}, this);
}
} else {
this.renderFallbackContent(shadowRoot, renderNode,
shadowInsertionPoint);
}
},

renderFallbackContent: function(shadowRoot, renderNode, fallbackHost) {
var logicalChildNodes = getChildNodesSnapshot(fallbackHost);
this.associateNode(fallbackHost);
this.associateNode(fallbackHost.parentNode);
logicalChildNodes.forEach(function(node) {

for (var node = fallbackHost.firstChild; node; node = node.nextSibling) {
this.renderAsAnyDomTree(shadowRoot, renderNode, node, false);
}, this);
}
},

/**
Expand Down Expand Up @@ -489,7 +488,6 @@

// http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-distribution-algorithm
distribute: function(tree, pool) {
var anyRemoved = false;
var self = this;

visit(tree, isActiveInsertionPoint,
Expand All @@ -505,26 +503,20 @@
if (matchesCriteria(node, insertionPoint)) { // 1.2.2
distributeChildToInsertionPoint(node, insertionPoint); // 1.2.2.1
pool[i] = undefined; // 1.2.2.2
anyRemoved = true;
}
}
});

if (!anyRemoved)
return pool;

return pool.filter(function(item) {
return item !== undefined;
});
},

// http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-tree-composition
treeComposition: function () {
var shadowHost = this.host;
var tree = shadowHost.shadowRoot; // 1.
var pool = []; // 2.
var shadowHostChildNodes = getChildNodesSnapshot(shadowHost);
shadowHostChildNodes.forEach(function(child) { // 3.

for (var child = shadowHost.firstChild;
child;
child = child.nextSibling) { // 3.
if (isInsertionPoint(child)) { // 3.2.
var reprojected = getDistributedChildNodes(child); // 3.2.1.
// if reprojected is undef... reset it?
Expand All @@ -534,7 +526,7 @@
} else {
pool.push(child); // 3.3.
}
});
}

var shadowInsertionPoint, point;
while (tree) { // 4.
Expand All @@ -546,7 +538,7 @@
});
point = shadowInsertionPoint;

pool = this.distribute(tree, pool); // 4.2.
this.distribute(tree, pool); // 4.2.
if (point) { // 4.3.
var nextOlderTree = tree.olderShadowRoot; // 4.3.1.
if (!nextOlderTree) {
Expand All @@ -569,21 +561,21 @@

function isInsertionPoint(node) {
// Should this include <shadow>?
return node.localName === 'content';
return node instanceof HTMLContentElement;
}

function isActiveInsertionPoint(node) {
// <content> inside another <content> or <shadow> is considered inactive.
return node.localName === 'content';
return node instanceof HTMLContentElement;
}

function isShadowInsertionPoint(node) {
return node.localName === 'shadow';
return node instanceof HTMLShadowElement;
}

function isActiveShadowInsertionPoint(node) {
// <shadow> inside another <content> or <shadow> is considered inactive.
return node.localName === 'shadow';
return node instanceof HTMLShadowElement;
}

function isShadowHost(shadowHost) {
Expand Down

0 comments on commit cf62307

Please sign in to comment.