Fixes #2692. Ensures that custom-style properties are applied async but before next render so that all properties are defined before any are consumed by custom-styles. Also refines dom-module's early upgrade code so that it does not affect other elements (corrects for example, custom-styles upgrading before expected).

This commit is contained in:
Steven Orvell 2015-11-12 15:09:48 -08:00
parent cb68ce54eb
commit b829f2a3aa
7 changed files with 123 additions and 28 deletions

View File

@ -142,7 +142,11 @@ Note, all features of `custom-style` are available when defining styles as part
styleUtil.forEachStyleRule(styleUtil.rulesForStyle(e), function(rule) {
styleTransformer.documentRule(rule);
});
this._applyCustomProperties(e);
// Allow all custom-styles defined in this turn to register
// before applying any properties. This helps ensure that all properties
// are defined before any are consumed.
Polymer.RenderStatus.beforeNextRender(this,
this._applyCustomProperties, [e]);
}
},

View File

@ -72,8 +72,8 @@
if (!m) {
// If polyfilling, a script can run before a dom-module element
// is upgraded. We force the containing document to upgrade
// and try again to workaround this polyfill limitation.
forceDocumentUpgrade();
// dom-modules and try again to workaround this polyfill limitation.
forceDomModulesUpgrade();
m = findModule(id);
}
if (m && selector) {
@ -97,12 +97,20 @@
var cePolyfill = window.CustomElements && !CustomElements.useNative;
document.registerElement('dom-module', DomModule);
function forceDocumentUpgrade() {
function forceDomModulesUpgrade() {
if (cePolyfill) {
var script = document._currentScript || document.currentScript;
var doc = script && script.ownerDocument || document;
if (doc) {
CustomElements.upgradeAll(doc);
// find all dom-modules
var modules = doc.querySelectorAll('dom-module');
// minimize work by going backwards and stopping if we find an
// upgraded module.
for (var i= modules.length-1, m; (i >=0) && (m=modules[i]); i--) {
if (m.__upgraded__) {
return;
} else {
CustomElements.upgrade(m);
}
}
}
}

View File

@ -50,33 +50,51 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
_afterNextRenderQueue: [],
_beforeNextRenderQueue: [],
_waitingNextRender: false,
afterNextRender: function(element, fn, args) {
if (!this._waitingNextRender) {
this._waitingNextRender = true;
this.whenReady(this._flushAfterNextRender);
}
this._watchNextRender();
this._afterNextRenderQueue.push([element, fn, args]);
},
_flushAfterNextRender: function() {
// we want to defer flush until just after the next paint.
requestAnimationFrame(function() {
setTimeout(Polymer.RenderStatus.__flushAfterNextRender);
beforeNextRender: function(element, fn, args) {
this._watchNextRender();
this._beforeNextRenderQueue.push([element, fn, args]);
},
_watchNextRender: function() {
if (!this._waitingNextRender) {
this._waitingNextRender = true;
var fn = function() {
Polymer.RenderStatus._flushNextRender();
}
if (!this._ready) {
this.whenReady(fn);
} else {
requestAnimationFrame(fn);
}
}
},
_flushNextRender: function() {
this._waitingNextRender = false;
this._flushRenderCallbacks(this._beforeNextRenderQueue);
this._beforeNextRenderQueue = [];
var self = this;
// we want to defer after render until just after the paint.
setTimeout(function() {
self._flushRenderCallbacks(self._afterNextRenderQueue);
self._afterNextRenderQueue = [];
});
},
__flushAfterNextRender: function() {
// called without context so force here.
var self = Polymer.RenderStatus;
self._waitingNextRender = false;
for (var i=0, h; i < self._afterNextRenderQueue.length; i++) {
h = self._afterNextRenderQueue[i];
_flushRenderCallbacks: function(callbacks) {
for (var i=0, h; i < callbacks.length; i++) {
h = callbacks[i];
h[1].apply(h[0], h[2] || Polymer.nar);
};
self._afterNextRenderQueue = [];
}
};

View File

@ -61,6 +61,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
// 'unit/styling-cross-scope-apply.html?dom=shadow',
'unit/styling-cross-scope-unknown-host.html',
'unit/custom-style.html',
'unit/custom-style-late.html',
'unit/dynamic-import.html',
'unit/templatizer.html',
'unit/dom-repeat.html',

View File

@ -0,0 +1,19 @@
<script>
Polymer({
is: 'x-input',
extends : 'input'
});
</script>
<style is="custom-style">
input[is=x-input] {
border : 4px solid red;
@apply (--cs-blue);
}
</style>
<style is="custom-style">
:root {
--cs-blue: {
border : 8px solid blue;
};
}
</style>

View File

@ -0,0 +1,42 @@
<!doctype html>
<!--
@license
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
<meta charset="utf-8">
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
<script src="../../../web-component-tester/browser.js"></script>
<link rel="import" href="../../polymer.html">
<link rel="import" href="custom-style-late-import.html">
</head>
<body>
<input id="input" is="x-input">
<script>
suite('custom-style late property definition', function() {
test('late defined properties applied to custom-style', function() {
assertComputed(input, '8px');
});
});
function assertComputed(element, value, property, pseudo) {
var computed = getComputedStyle(element, pseudo);
property = property || 'border-top-width';
assert.equal(computed[property], value, 'computed style incorrect for ' + property);
}
</script>
</body>
</html>

View File

@ -365,11 +365,11 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
var ds = document.createElement('style', 'custom-style');
ds.textContent = ':root { --dynamic: 11px solid orange; }';
document.head.appendChild(ds);
setTimeout(function() {
Polymer.updateStyles();
Polymer.updateStyles();
Polymer.RenderStatus.afterNextRender(null, function() {
assertComputed(dynamic, '11px');
done();
}, 0);
});
});
test('custom-styles apply normal and property values to elements and cannot be late bound via inheritance', function() {
@ -409,7 +409,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
document.body.removeChild(style);
});
test('imperative custom style with include', function() {
test('imperative custom style with include', function(done) {
var style = document.createElement('style', 'custom-style');
style.include = 'shared-style2';
var d = document.createElement('div');
@ -417,9 +417,12 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
document.body.appendChild(d);
document.body.appendChild(style);
CustomElements.takeRecords();
assertComputed(d, '16px');
document.body.removeChild(d);
document.body.removeChild(style);
Polymer.RenderStatus.afterNextRender(null, function() {
assertComputed(d, '16px');
document.body.removeChild(d);
document.body.removeChild(style);
done();
});
});
test('imperative custom style with non-existent include', function() {