Skip to content

Commit 707a376

Browse files
author
Steven Orvell
committed
Merge branch 'master' into shadydom-upgrade
2 parents 1aeaa80 + b7c73bd commit 707a376

17 files changed

+489
-72
lines changed

CONTRIBUTING.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ Beyond GitHub, we try to have a variety of different lines of communication open
1010

1111
* [Blog](https://blog.polymer-project.org/)
1212
* [Twitter](https://twitter.com/polymer)
13-
* [Google+ Community](https://plus.sandbox.google.com/u/0/communities/115626364525706131031?cfem=1)
1413
* [Mailing list](https://groups.google.com/forum/#!forum/polymer-dev)
1514
* [Slack channel](https://bit.ly/polymerslack)
1615

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,6 @@ Beyond GitHub, we try to have a variety of different lines of communication avai
135135

136136
* [Blog](https://blog.polymer-project.org/)
137137
* [Twitter](https://twitter.com/polymer)
138-
* [Google+ community](https://plus.google.com/communities/115626364525706131031)
139138
* [Mailing list](https://groups.google.com/forum/#!forum/polymer-dev)
140139
* [Slack channel](https://bit.ly/polymerslack)
141140

lib/elements/array-selector.js

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
107107

108108
__updateSelection(multi, itemsInfo) {
109109
let path = itemsInfo.path;
110-
if (path == 'items') {
110+
if (path == JSCompiler_renameProperty('items', this)) {
111111
// Case 1 - items array changed, so diff against previous array and
112112
// deselect any removed items and adjust selected indices
113113
let newItems = itemsInfo.base || [];
@@ -122,14 +122,14 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
122122
}
123123
this.__lastItems = newItems;
124124
this.__lastMulti = multi;
125-
} else if (itemsInfo.path == 'items.splices') {
125+
} else if (itemsInfo.path == `${JSCompiler_renameProperty('items', this)}.splices`) {
126126
// Case 2 - got specific splice information describing the array mutation:
127127
// deselect any removed items and adjust selected indices
128128
this.__applySplices(itemsInfo.value.indexSplices);
129129
} else {
130130
// Case 3 - an array element was changed, so deselect the previous
131131
// item for that index if it was previously selected
132-
let part = path.slice('items.'.length);
132+
let part = path.slice(`${JSCompiler_renameProperty('items', this)}.`.length);
133133
let idx = parseInt(part, 10);
134134
if ((part.indexOf('.') < 0) && part == idx) {
135135
this.__deselectChangedIdx(idx);
@@ -167,7 +167,7 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
167167
selected.forEach((idx, item) => {
168168
if (idx < 0) {
169169
if (this.multi) {
170-
this.splice('selected', sidx, 1);
170+
this.splice(JSCompiler_renameProperty('selected', this), sidx, 1);
171171
} else {
172172
this.selected = this.selectedItem = null;
173173
}
@@ -184,13 +184,19 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
184184
let sidx = 0;
185185
this.__selectedMap.forEach(idx => {
186186
if (idx >= 0) {
187-
this.linkPaths('items.' + idx, 'selected.' + sidx++);
187+
this.linkPaths(
188+
`${JSCompiler_renameProperty('items', this)}.${idx}`,
189+
`${JSCompiler_renameProperty('selected', this)}.${sidx++}`);
188190
}
189191
});
190192
} else {
191193
this.__selectedMap.forEach(idx => {
192-
this.linkPaths('selected', 'items.' + idx);
193-
this.linkPaths('selectedItem', 'items.' + idx);
194+
this.linkPaths(
195+
JSCompiler_renameProperty('selected', this),
196+
`${JSCompiler_renameProperty('items', this)}.${idx}`);
197+
this.linkPaths(
198+
JSCompiler_renameProperty('selectedItem', this),
199+
`${JSCompiler_renameProperty('items', this)}.${idx}`);
194200
});
195201
}
196202
}
@@ -248,9 +254,9 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
248254
}
249255

250256
__selectedIndexForItemIndex(idx) {
251-
let selected = this.__dataLinkedPaths['items.' + idx];
257+
let selected = this.__dataLinkedPaths[`${JSCompiler_renameProperty('items', this)}.${idx}`];
252258
if (selected) {
253-
return parseInt(selected.slice('selected.'.length), 10);
259+
return parseInt(selected.slice(`${JSCompiler_renameProperty('selected', this)}.`.length), 10);
254260
}
255261
}
256262

@@ -271,7 +277,7 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
271277
}
272278
this.__updateLinks();
273279
if (this.multi) {
274-
this.splice('selected', sidx, 1);
280+
this.splice(JSCompiler_renameProperty('selected', this), sidx, 1);
275281
} else {
276282
this.selected = this.selectedItem = null;
277283
}
@@ -318,7 +324,7 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
318324
this.__selectedMap.set(item, idx);
319325
this.__updateLinks();
320326
if (this.multi) {
321-
this.push('selected', item);
327+
this.push(JSCompiler_renameProperty('selected', this), item);
322328
} else {
323329
this.selected = this.selectedItem = item;
324330
}

lib/elements/dom-repeat.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ export class DomRepeat extends domRepeatBase {
382382
if (prop == this.as) {
383383
this.items[idx] = value;
384384
}
385-
let path = translate(this.as, 'items.' + idx, prop);
385+
let path = translate(this.as, `${JSCompiler_renameProperty('items', this)}.${idx}`, prop);
386386
this.notifyPath(path, value);
387387
}
388388
}

lib/legacy/class.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,26 @@ function flattenBehaviors(behaviors, list, exclude) {
155155
return list;
156156
}
157157

158+
/**
159+
* Copies property descriptors from source to target, overwriting all fields
160+
* of any previous descriptor for a property *except* for `value`, which is
161+
* merged in from the target if it does not exist on the source.
162+
*
163+
* @param {*} target Target properties object
164+
* @param {*} source Source properties object
165+
*/
166+
function mergeProperties(target, source) {
167+
for (const p in source) {
168+
const targetInfo = target[p];
169+
const sourceInfo = source[p];
170+
if (!('value' in sourceInfo) && targetInfo && ('value' in targetInfo)) {
171+
target[p] = Object.assign({value: targetInfo.value}, sourceInfo);
172+
} else {
173+
target[p] = sourceInfo;
174+
}
175+
}
176+
}
177+
158178
/* Note about construction and extension of legacy classes.
159179
[Changed in Q4 2018 to optimize performance.]
160180
@@ -227,10 +247,10 @@ function GenerateClassFromInfo(info, Base, behaviors) {
227247
const properties = {};
228248
if (behaviorList) {
229249
for (let i=0; i < behaviorList.length; i++) {
230-
Object.assign(properties, behaviorList[i].properties);
250+
mergeProperties(properties, behaviorList[i].properties);
231251
}
232252
}
233-
Object.assign(properties, info.properties);
253+
mergeProperties(properties, info.properties);
234254
return properties;
235255
}
236256

lib/legacy/polymer.dom.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,12 @@ if (window['ShadyDOM'] && window['ShadyDOM']['inUse'] && window['ShadyDOM']['noP
395395
}
396396
});
397397

398+
// Note, `classList` is here only for legacy compatibility since it does not
399+
// trigger distribution in v1 Shadow DOM.
400+
forwardReadOnlyProperties(Wrapper.prototype, [
401+
'classList'
402+
]);
403+
398404
DomApiImpl = Wrapper;
399405

400406
Object.defineProperties(EventApi.prototype, {
@@ -416,12 +422,17 @@ if (window['ShadyDOM'] && window['ShadyDOM']['inUse'] && window['ShadyDOM']['noP
416422

417423
} else {
418424

425+
// Methods that can provoke distribution or must return the logical, not
426+
// composed tree.
419427
forwardMethods(DomApiNative.prototype, [
420428
'cloneNode', 'appendChild', 'insertBefore', 'removeChild',
421429
'replaceChild', 'setAttribute', 'removeAttribute',
422430
'querySelector', 'querySelectorAll'
423431
]);
424432

433+
// Properties that should return the logical, not composed tree. Note, `classList`
434+
// is here only for legacy compatibility since it does not trigger distribution
435+
// in v1 Shadow DOM.
425436
forwardReadOnlyProperties(DomApiNative.prototype, [
426437
'parentNode', 'firstChild', 'lastChild',
427438
'nextSibling', 'previousSibling', 'firstElementChild',

lib/mixins/element-mixin.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { wrap } from '../utils/wrap.js';
2424
* Current Polymer version in Semver notation.
2525
* @type {string} Semver notation of the current version of Polymer.
2626
*/
27-
export const version = '3.0.5';
27+
export const version = '3.2.0';
2828

2929
const builtCSS = window.ShadyCSS && window.ShadyCSS['cssBuild'];
3030

lib/mixins/template-stamp.js

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ import '../utils/boot.js';
1111

1212
import { dedupingMixin } from '../utils/mixin.js';
1313

14-
const walker = document.createTreeWalker(document, NodeFilter.SHOW_ALL,
15-
null, false);
16-
1714
// 1.x backwards-compatible auto-wrapper for template type extensions
1815
// This is a clear layering violation and gives favored-nation status to
1916
// dom-if and dom-repeat templates. This is a conceit we're choosing to keep
@@ -48,8 +45,7 @@ function findTemplateNode(root, nodeInfo) {
4845
if (parent) {
4946
// note: marginally faster than indexing via childNodes
5047
// (http://jsperf.com/childnodes-lookup)
51-
walker.currentNode = parent;
52-
for (let n=walker.firstChild(), i=0; n; n=walker.nextSibling()) {
48+
for (let n=parent.firstChild, i=0; n; n=n.nextSibling) {
5349
if (nodeInfo.parentIndex === i++) {
5450
return n;
5551
}
@@ -238,8 +234,7 @@ export const TemplateStamp = dedupingMixin(
238234
// For ShadyDom optimization, indicating there is an insertion point
239235
templateInfo.hasInsertionPoint = true;
240236
}
241-
walker.currentNode = element;
242-
if (walker.firstChild()) {
237+
if (element.firstChild) {
243238
noted = this._parseTemplateChildNodes(element, templateInfo, nodeInfo) || noted;
244239
}
245240
if (element.hasAttributes && element.hasAttributes()) {
@@ -265,8 +260,7 @@ export const TemplateStamp = dedupingMixin(
265260
if (root.localName === 'script' || root.localName === 'style') {
266261
return;
267262
}
268-
walker.currentNode = root;
269-
for (let node=walker.firstChild(), parentIndex=0, next; node; node=next) {
263+
for (let node=root.firstChild, parentIndex=0, next; node; node=next) {
270264
// Wrap templates
271265
if (node.localName == 'template') {
272266
node = wrapTemplateExtension(node);
@@ -275,13 +269,12 @@ export const TemplateStamp = dedupingMixin(
275269
// text nodes to be inexplicably split =(
276270
// note that root.normalize() should work but does not so we do this
277271
// manually.
278-
walker.currentNode = node;
279-
next = walker.nextSibling();
272+
next = node.nextSibling;
280273
if (node.nodeType === Node.TEXT_NODE) {
281274
let /** Node */ n = next;
282275
while (n && (n.nodeType === Node.TEXT_NODE)) {
283276
node.textContent += n.textContent;
284-
next = walker.nextSibling();
277+
next = n.nextSibling;
285278
root.removeChild(n);
286279
n = next;
287280
}
@@ -296,8 +289,7 @@ export const TemplateStamp = dedupingMixin(
296289
childInfo.infoIndex = templateInfo.nodeInfoList.push(/** @type {!NodeInfo} */(childInfo)) - 1;
297290
}
298291
// Increment if not removed
299-
walker.currentNode = node;
300-
if (walker.parentNode()) {
292+
if (node.parentNode) {
301293
parentIndex++;
302294
}
303295
}

lib/utils/debounce.js

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export class Debouncer {
3535
this._callback = callback;
3636
this._timer = this._asyncModule.run(() => {
3737
this._timer = null;
38+
debouncerQueue.delete(this);
3839
this._callback();
3940
});
4041
}
@@ -44,6 +45,21 @@ export class Debouncer {
4445
* @return {void}
4546
*/
4647
cancel() {
48+
if (this.isActive()) {
49+
this._cancelAsync();
50+
// Canceling a debouncer removes its spot from the flush queue,
51+
// so if a debouncer is manually canceled and re-debounced, it
52+
// will reset its flush order (this is a very minor difference from 1.x)
53+
// Re-debouncing via the `debounce` API retains the 1.x FIFO flush order
54+
debouncerQueue.delete(this);
55+
}
56+
}
57+
/**
58+
* Cancels a debouncer's async callback.
59+
*
60+
* @return {void}
61+
*/
62+
_cancelAsync() {
4763
if (this.isActive()) {
4864
this._asyncModule.cancel(/** @type {number} */(this._timer));
4965
this._timer = null;
@@ -104,11 +120,46 @@ export class Debouncer {
104120
*/
105121
static debounce(debouncer, asyncModule, callback) {
106122
if (debouncer instanceof Debouncer) {
107-
debouncer.cancel();
123+
// Cancel the async callback, but leave in debouncerQueue if it was
124+
// enqueued, to maintain 1.x flush order
125+
debouncer._cancelAsync();
108126
} else {
109127
debouncer = new Debouncer();
110128
}
111129
debouncer.setConfig(asyncModule, callback);
112130
return debouncer;
113131
}
114132
}
133+
134+
let debouncerQueue = new Set();
135+
136+
/**
137+
* Adds a `Debouncer` to a list of globally flushable tasks.
138+
*
139+
* @param {!Debouncer} debouncer Debouncer to enqueue
140+
* @return {void}
141+
*/
142+
export const enqueueDebouncer = function(debouncer) {
143+
debouncerQueue.add(debouncer);
144+
};
145+
146+
/**
147+
* Flushes any enqueued debouncers
148+
*
149+
* @return {boolean} Returns whether any debouncers were flushed
150+
*/
151+
export const flushDebouncers = function() {
152+
const didFlush = Boolean(debouncerQueue.size);
153+
// If new debouncers are added while flushing, Set.forEach will ensure
154+
// newly added ones are also flushed
155+
debouncerQueue.forEach(debouncer => {
156+
try {
157+
debouncer.flush();
158+
} catch(e) {
159+
setTimeout(() => {
160+
throw e;
161+
});
162+
}
163+
});
164+
return didFlush;
165+
};

lib/utils/flush.js

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,8 @@ import './boot.js';
1111
/* eslint-disable no-unused-vars */
1212
import { Debouncer } from '../utils/debounce.js'; // used in type annotations
1313
/* eslint-enable no-unused-vars */
14-
15-
let debouncerQueue = [];
16-
17-
/**
18-
* Adds a `Debouncer` to a list of globally flushable tasks.
19-
*
20-
* @param {!Debouncer} debouncer Debouncer to enqueue
21-
* @return {void}
22-
*/
23-
export const enqueueDebouncer = function(debouncer) {
24-
debouncerQueue.push(debouncer);
25-
};
26-
27-
function flushDebouncers() {
28-
const didFlush = Boolean(debouncerQueue.length);
29-
while (debouncerQueue.length) {
30-
try {
31-
debouncerQueue.shift().flush();
32-
} catch(e) {
33-
setTimeout(() => {
34-
throw e;
35-
});
36-
}
37-
}
38-
return didFlush;
39-
}
14+
import { flushDebouncers } from '../utils/debounce.js'; // used in type annotations
15+
export { enqueueDebouncer } from '../utils/debounce.js'; // used in type annotations
4016

4117
/**
4218
* Forces several classes of asynchronously queued tasks to flush:

0 commit comments

Comments
 (0)