Skip to content
Permalink
Browse files

Attempt to exclusively use the 'content' distribution code path for a…

…ppending dom to elements (sip)
  • Loading branch information
sorvell committed Dec 13, 2014
1 parent 26472ce commit 67eaf0e864119fb6bbd068e13f80bc1086dce92d
Showing with 100 additions and 44 deletions.
  1. +1 −1 polymer-core.html
  2. +45 −6 src/features/content.html
  3. +20 −7 src/features/ready.html
  4. +7 −12 src/module.html
  5. +16 −16 test/unit/content.html
  6. +7 −0 test/unit/ready-elements.html
  7. +4 −2 test/unit/ready.html
@@ -45,7 +45,7 @@

defaultFeatures: function() {
if (this._useContent) {
this.poolContent();
this.prepareContent();
}
if (this._template) {
this.stampTemplate();
@@ -24,12 +24,13 @@
isHost: true,

register: function(prototype) {
var t = prototype._template;
prototype._useContent = prototype._useContent ||
Boolean(t && t.content.querySelector('content'));
// var t = prototype._template;
// prototype._useContent = prototype._useContent ||
// Boolean(t && t.content.querySelector('content'));
prototype._useContent = true;
},

poolContent: function() {
prepareContent: function() {
// capture lightChildren to help reify dom scoping
saveLightChildrenIfNeeded(this);
// create our lite ShadowRoot document fragment
@@ -49,7 +50,7 @@
distributeContent: function() {
// sanity check to guard against uninitialized state
if (!this.contentRoot) {
throw Error('poolContent() must be called before distributeContent()');
throw Error('prepareContent() must be called before distributeContent()');
}
// NOTE: `contentRoot` is populated only for the first
// distribution. After that dom should be in the composed tree and
@@ -138,7 +139,7 @@
var content = node;
var anyDistributed = false;
for (var i = 0; i < pool.length; i++) {
var node = pool[i];
node = pool[i];
// skip nodes that were already used
if (!node) {
continue;
@@ -200,6 +201,7 @@
return children;
},

/*
_updateChildNodes: function(node, children) {
// Add the children that need to be added. Walk the list backwards so we can
// use insertBefore easily.
@@ -221,6 +223,33 @@
child = nextNode;
}
},
*/

// TODO(sorvell): experimental attempt to distribute left-to-right to
// maintain the same attach order as the platform.
_updateChildNodes: function(node, children) {
// Add the children that need to be added.
for (var i=0, l=children.length, c, b; (i<l) && (c=children[i]); i++) {
b = children[i-1] || null;
if (c.parentNode != node || c.previousSibling != b) {
insertBefore(node, c, b && b.nextSibling)
}
}
// We just added nodes in order, starting from an unknown point;
// therefore delete everything before and after the expected children.
var last = children[children.length-1];
var lastChild = node.lastChild;
while (lastChild && lastChild != last) {
node.removeChild(lastChild);
lastChild = node.lastChild;
}
var first = children[0];
var firstChild = node.firstChild;
while (firstChild && firstChild != first) {
node.removeChild(firstChild);
firstChild = node.firstChild;
}
},

_matchesContentSelect: function(node, contentElement) {
var select = contentElement.getAttribute('select');
@@ -294,6 +323,16 @@
parentNode.insertBefore(newChild, refChild);
}

function appendChild(parentNode, newChild) {
// remove child from its old parent first
remove(newChild);
// make sure we never lose logical DOM information:
// if the parentNode doesn't have lightChildren, save that information now.
saveLightChildrenIfNeeded(parentNode);
// insert it into the real DOM
parentNode.appendChild(newChild);
}

function remove(node) {
var parentNode = node.parentNode;
if (!parentNode) return;
@@ -65,25 +65,38 @@
},

_notifyReady: function() {
//console.group('[' + this.name + '#' + this.id + ']', 'ready');
this._ready();
this._broadcast('_beforeReady');
this._broadcast('_ready', true);
this._readied = true;
},

_broadcast: function(method, cleanup) {
var moniker = '[' + this.tag + (this.id ? '#' + this.id : '') +
']: ' + method;
console.group(moniker);
this[method]();
var n$ = this._readyListeners;
if (n$) {
for (var i=0, l=n$.length, n; (i<l) && (n=n$[i]); i++) {
n._notifyReady();
n._broadcast(method, cleanup);
}
}
this._readyListeners = null;
//console.groupEnd('[' + this.name + '#' + this.id + ']', 'ready');
if (cleanup) {
this._readyListeners = null;
}
console.groupEnd(moniker);
},

_ready: function() {
this._readied = true;
_beforeReady: function() {
this.takeAttributes();
// TODO(jmesserly): this is a hook to allow content.html to be called
// before "ready". This needs to be factored better.
if (this._useContent) {
this.distributeContent();
}
},

_ready: function() {
this.ready();
},

@@ -33,25 +33,20 @@
break;
}
modules[name] = module;
};
}

function marshal(name) {
return modules[name];
}

var modules = {};

if (window.HTMLImports) {
var using = function(depends, task) {
HTMLImports.whenImportsReady(function() {
withDependencies(task, depends);
});
};
} else {
var using = function(depends, task) {
withDependencies(task, depends);
};
}
// NOTE: when used in conjunction with the imports polyfill,
// if a module is defined in an import, `using` is not available
// in the main document until `HTMLImports.whenReady`.
var using = function(depends, task) {
withDependencies(task, depends);
};

// exports

@@ -37,7 +37,7 @@
var host = document.createElement('x-content-test');
// Populate the initial pool of light DOM children.
host.innerHTML = hostInnerHtml;
host.poolContent();
host.prepareContent();
// Pretend we're stamping the template contents.
setInnerHTML(host.root, shadowRootHtml);
// Invoke distribution and verify the resulting tree.
@@ -84,7 +84,7 @@
var host = document.createElement('x-content-test');
host.innerHTML = '<a></a>';
var a = host.firstChild;
host.poolContent();
host.prepareContent();
setInnerHTML(host.root, '<x-content-test id="p">' +
'<b></b><content></content></x-content-test>');

@@ -95,7 +95,7 @@
// force upgrade on polyfilled browsers
CustomElements.upgrade(p);

p.poolContent();
p.prepareContent();
setInnerHTML(p.root,
'a: <content select=a></content>b: <content select=b></content>');
var textNodeA = p.root.firstChild;
@@ -132,7 +132,7 @@
var host = document.createElement('x-content-test');
host.innerHTML = '<a>Hello</a>';

host.poolContent();
host.prepareContent();
setInnerHTML(host.root, '<content>fallback</content>');
host.distributeContent();
assert.strictEqual(host.innerHTML, '<a>Hello</a>');
@@ -151,7 +151,7 @@
var host = document.createElement('x-content-test');
host.innerHTML = '<a>Hello</a>';

host.poolContent();
host.prepareContent();
setInnerHTML(host.root, '<content></content><b>after</b>');
host.distributeContent();
assert.strictEqual(host.innerHTML, '<a>Hello</a><b>after</b>');
@@ -169,7 +169,7 @@
var host = document.createElement('x-content-test');
host.innerHTML = '<a>Hello</a>';

host.poolContent();
host.prepareContent();
setInnerHTML(host.root, '<content select="xxx"><b>fallback</b></content>');
var b = host.root.firstChild.firstChild;
host.distributeContent();
@@ -192,7 +192,7 @@
var host = document.createElement('x-content-test');
host.innerHTML = '<a>Hello</a>';

host.poolContent();
host.prepareContent();
setInnerHTML(host.root, '<content>fallback</content>');
host.distributeContent();
assert.strictEqual(host.innerHTML, '<a>Hello</a>');
@@ -212,7 +212,7 @@
var a = host.firstChild;
var b = a.nextSibling;

host.poolContent();
host.prepareContent();
setInnerHTML(host.root, '<content>fallback</content>');
host.distributeContent();
assert.strictEqual(host.innerHTML, '<a></a><b></b>');
@@ -228,7 +228,7 @@
var host = document.createElement('x-content-test');
host.innerHTML = '<a>Hello</a>';

host.poolContent();
host.prepareContent();
setInnerHTML(host.root, '<content></content><b>after</b>');
var b = host.root.lastChild;
host.distributeContent();
@@ -252,7 +252,7 @@
var host = document.createElement('x-content-test');
host.innerHTML = '<a>Hello</a><b>World</b>';

host.poolContent();
host.prepareContent();
setInnerHTML(host.root, '<content select="b">fallback b</content>' +
'<content select="a">fallback a</content>');
host.distributeContent();
@@ -271,7 +271,7 @@
var host = document.createElement('x-content-test');
host.innerHTML = '<a>Hello</a>';

host.poolContent();
host.prepareContent();
setInnerHTML(host.root, '<content></content>');
host.distributeContent();
assert.strictEqual(host.innerHTML, '<a>Hello</a>');
@@ -285,7 +285,7 @@
var host = document.createElement('x-content-test');
host.innerHTML = '<a>Hello</a>';

host.poolContent();
host.prepareContent();
setInnerHTML(host.root, '<content></content>');
host.distributeContent();
assert.strictEqual(host.innerHTML, '<a>Hello</a>');
@@ -301,7 +301,7 @@
host.innerHTML = '<a>Hello</a>';
var a = host.firstChild;

host.poolContent();
host.prepareContent();
setInnerHTML(host.root, '<content></content>');
host.distributeContent();
assert.strictEqual(host.innerHTML, '<a>Hello</a>');
@@ -315,7 +315,7 @@
var host = document.createElement('x-content-test');
host.innerHTML = '<a>Hello</a>';

host.poolContent();
host.prepareContent();
setInnerHTML(host.root, '<content></content>');
var content = host.root.firstChild;
host.distributeContent();
@@ -332,7 +332,7 @@
host.innerHTML = '<a>Hello</a>';
var a = host.firstChild;

host.poolContent();
host.prepareContent();
setInnerHTML(host.root, '<content></content>');
host.distributeContent();
assert.strictEqual(host.innerHTML, '<a>Hello</a>');
@@ -347,7 +347,7 @@
var host = document.createElement('x-content-test');
host.innerHTML = '<a>Hello</a>';

host.poolContent();
host.prepareContent();
setInnerHTML(host.root, '<content></content>');
var content = host.root.firstChild;
host.distributeContent();
@@ -9,7 +9,14 @@
moniker: function() {
return this.tag + (this.id ? '#' + this.id : '')
},
created: function() {
console.log('created', this.moniker());
},
attached: function() {
console.log('attached', this.moniker());
},
ready: function() {
console.log('ready', this.moniker());
readyList.push(this.moniker());
}
};
@@ -24,15 +24,17 @@

suite('ready', function() {

var correct = ['x-ready', 'x-zot#a', 'x-zot#b', 'x-zot#c', 'x-zot#d', 'x-foo', 'x-bar', 'x-zot', 'x-bar', 'x-zot'];

test('element create in dom calls ready', function() {
assert.deepEqual(readyList, ['x-ready', 'x-zot#a', 'x-zot#b', 'x-zot#c', 'x-zot#d', 'x-foo', 'x-bar', 'x-zot', 'x-bar', 'x-zot']);
assert.deepEqual(readyList, correct);
});

test('element create + attach calls ready', function() {
clearReadyList();
document.body.appendChild(document.createElement('x-ready'));
CustomElements.takeRecords(document);
assert.deepEqual(readyList, ['x-ready', 'x-zot#a', 'x-zot#b', 'x-zot#c', 'x-zot#d', 'x-foo', 'x-bar', 'x-zot', 'x-bar', 'x-zot']);
assert.deepEqual(readyList, correct);
});

});

0 comments on commit 67eaf0e

Please sign in to comment.
You can’t perform that action at this time.