implements disable-upgrade attribute which prevents readying an element until the attribute is removed.

This commit is contained in:
Steven Orvell
2017-03-08 16:46:35 -08:00
parent 4ae65ba26f
commit a222078e82
8 changed files with 421 additions and 17 deletions

View File

@@ -57,6 +57,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
constructor() {
super();
this.root = this;
this.created();
}

View File

@@ -119,6 +119,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
let caseMap = Polymer.CaseMap;
const DISABLED = 'disable-upgrade';
/**
* Returns the `properties` object specifically on `klass`. Use for:
* (1) super chain mixes togther to make `propertiesForClass` which is
@@ -437,7 +439,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
*/
static get observedAttributes() {
if (!this.hasOwnProperty(goog.reflect.objectProperty('__observedAttributes', this))) {
let list = [];
let list = [DISABLED];
let properties = propertiesForClass(this);
for (let prop in properties) {
list.push(Polymer.CaseMap.camelToDashCase(prop));
@@ -533,17 +535,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return this._importPath;
}
constructor() {
super();
Polymer.telemetry.instanceCount++;
// Stamp template
if (this._template) {
this.root = this._stampTemplate(this._template);
} else {
this.root = this;
}
}
/**
* Overrides the default `Polymer.PropertyAccessors` to ensure class
* metaprogramming related to property accessors and effects has
@@ -555,6 +546,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
* @override
*/
_initializeProperties() {
Polymer.telemetry.instanceCount++;
this.__upgradeFlush = null;
this.constructor.finalize();
const importPath = this.constructor.importPath;
// note: finalize template when we have access to `localName` to
@@ -615,6 +608,18 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
*/
disconnectedCallback() {}
/**
* Stamps the element template.
*
* @override
*/
ready() {
if (this._template) {
this.root = this._stampTemplate(this._template);
}
super.ready();
}
/**
* Implements `PropertyEffects`'s `_readyClients` call. Attaches
* element dom by calling `_attachDom` with the dom stamped from the
@@ -673,7 +678,18 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
* @override
*/
attributeChangedCallback(name, old, value) {
if (old !== value) {
// process `disable-upgrade` specially
if (name === DISABLED) {
const disabled = value !== null;
if (this.__upgradeFlush && !disabled) {
this._flushProperties = this.__upgradeFlush;
this.__upgradeFlush = null;
this._flushProperties();
} else if (disabled) {
this.__upgradeFlush = this._flushProperties;
this._flushProperties = function() {};
}
} else if (old !== value) {
let property = caseMap.dashToCamelCase(name);
let type = propertiesForClass(this.constructor)[property].type;
if (!this._hasReadOnlyEffect(property)) {

View File

@@ -454,8 +454,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return class TemplateStamp extends superClass {
constructor() {
super();
_initializeProperties() {
super._initializeProperties();
this.$ = null;
this.__templateNodes = null;
this.__templateNotes = null;

View File

@@ -32,7 +32,10 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
}
function flushQueue(queue) {
while (queue.length) {
const max = queue.length;
let i=0;
while (queue.length && i < max) {
i++;
const q = queue.shift();
const context = q[0];
const callback = q[1];

View File

@@ -68,7 +68,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
'unit/logging.html',
'unit/mixin-utils.html',
'unit/mixin-behaviors.html',
'unit/render-status.html'
'unit/render-status.html',
'unit/disable-upgrade.html'
];
// http://eddmann.com/posts/cartesian-product-in-javascript/

View File

@@ -0,0 +1,98 @@
<!--
@license
Copyright (c) 2017 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
-->
<!DOCTYPE html>
<html>
<head>
<script src="../../../webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="../../polymer.html">
</head>
<body>
<dom-module id="x-child">
<template>
<style>
:host {
display: block;
border: 2px solid lightgreen;
margin: 2px;
padding: 2px;
};
</style>
<div>I'm a child, yo!</div>
</template>
<script>
HTMLImports.whenReady(function() {
class XChild extends Polymer.Element {
static get is() { return 'x-child'}
static get properties() {
return {
prop: { value: 'hi'}
}
}
}
customElements.define(XChild.is, XChild);
});
</script>
</dom-module>
<dom-module id="x-test">
<template>
<style>
:host {
display: block;
border: 2px solid orange;
padding: 2px;
};
</style>
<div>element says: {{prop}}</div>
<x-child id="child" disable-upgrade$="[[disabled]]"></x-child>
</template>
<script>
HTMLImports.whenReady(function() {
class XTest extends Polymer.Element {
static get is() { return 'x-test'}
static get properties() {
return {
prop: { value: 'hi'},
disabled: {value: true}
}
}
ready() {
super.ready();
setTimeout(() => {
// this.$.child.removeAttribute('disable-upgrade');
this.disabled = false;
}, 1000)
}
}
customElements.define(XTest.is, XTest);
});
</script>
</dom-module>
<h2>Enabled</h2>
<x-test></x-test>
<x-test></x-test>
<h2>Disabled</h2>
<script>
function go() {
Array.from(document.querySelectorAll('[disable-upgrade]'))
.forEach((e) => e.removeAttribute('disable-upgrade'));
}
</script>
<button onclick="go()">Go</button>
<x-test id="one" disable-upgrade></x-test>
<x-test id="two" disable-upgrade></x-test>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,158 @@
<!doctype html>
<!--
@license
Copyright (c) 2017 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
-->
<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">
<dom-module id="x-lazy">
<template>
<style>
:host {
display: block;
}
</style>
<div id="child">Live!</div>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-lazy'
});
});
</script>
</dom-module>
<test-fixture id="simple">
<template>
<x-lazy disable-upgrade></x-lazy>
</template>
</test-fixture>
<dom-module id="x-complicated-child">
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-complicated-child',
properties: {
a: {
observer: 'aChanged'
},
c: {
observer: 'cChanged'
},
aRan: {
value: false
},
cRan: {
value: false
}
},
aChanged: function() {
this.aRan = true;
},
cChanged: function() {
this.cRan = true;
}
});
})
</script>
</dom-module>
<dom-module id="x-complicated-lazy">
<template>
<x-complicated-child id="child" a="{{a}}" disable-upgrade$="{{b}}" c="{{c}}"></x-complicated-child>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-complicated-lazy',
properties: {
a: {value: true},
b: {value: true},
c: {value: true}
}
});
});
</script>
</dom-module>
<test-fixture id="databind-lazy">
<template>
<x-complicated-lazy></x-complicated-lazy>
</template>
</test-fixture>
<dom-module id="x-complicated-not-lazy">
<template>
<!-- the <x-non-lazy> element here ensures there are other elements on -->
<!-- the host-stack to trigger "configuration", to ensure the disabled -->
<!-- element handles that code path correctly -->
<x-non-lazy></x-non-lazy>
<x-complicated-child id="child" a="{{a}}" disable-upgrade$="{{b}}" c="{{c}}"></x-complicated-child>
</template>
<script>
HTMLImports.whenReady(function() {
Polymer({
is: 'x-non-lazy'
});
Polymer({
is: 'x-complicated-not-lazy',
properties: {
a: {value: true},
b: {value: false},
c: {value: true}
}
});
});
</script>
</dom-module>
<test-fixture id="databind-not-lazy">
<template>
<x-complicated-not-lazy></x-complicated-not-lazy>
</template>
</test-fixture>
<script>
suite('Element disableUpgrade', function() {
suite('disable-upgrade', function() {
var el;
setup(function() {
el = fixture('simple');
});
test('does not stamp when lazy', function() {
assert.equal(el.hasAttribute('disable-upgrade'), true);
assert.notOk(el.shadowRoot);
assert.notOk(el.$);
});
test('stamps when disableUpgrade is removed', function() {
el.removeAttribute('disable-upgrade');
assert.ok(el.root);
assert.ok(el.$.child);
});
});
suite('disableUpgrade and Databinding', function() {
test('binding to disable-upgrade with true', function() {
var el = fixture('databind-lazy');
assert.equal(el.$.child.hasAttribute('disable-upgrade'), true);
assert.equal(el.$.child.aRan, false);
assert.equal(el.$.child.cRan, false);
});
test('bindings to disable-upgrade with false', function () {
var el = fixture('databind-not-lazy');
assert.notOk(el.$.child.hasAttribute('disable-upgrade'));
assert.equal(el.$.child.aRan, true);
assert.equal(el.$.child.cRan, true);
})
})
});
</script>