Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/legacy-undefined-noBatch' into 5…
Browse files Browse the repository at this point in the history
…143-ordered-computed-3.x
  • Loading branch information
kevinpschaaf committed Mar 8, 2019
2 parents ef0efa6 + d936ee9 commit 810a70f
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 66 deletions.
28 changes: 17 additions & 11 deletions lib/elements/array-selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ let ArraySelectorMixin = dedupingMixin(superClass => {

__updateSelection(multi, itemsInfo) {
let path = itemsInfo.path;
if (path == 'items') {
if (path == JSCompiler_renameProperty('items', this)) {
// Case 1 - items array changed, so diff against previous array and
// deselect any removed items and adjust selected indices
let newItems = itemsInfo.base || [];
Expand All @@ -122,14 +122,14 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
}
this.__lastItems = newItems;
this.__lastMulti = multi;
} else if (itemsInfo.path == 'items.splices') {
} else if (itemsInfo.path == `${JSCompiler_renameProperty('items', this)}.splices`) {
// Case 2 - got specific splice information describing the array mutation:
// deselect any removed items and adjust selected indices
this.__applySplices(itemsInfo.value.indexSplices);
} else {
// Case 3 - an array element was changed, so deselect the previous
// item for that index if it was previously selected
let part = path.slice('items.'.length);
let part = path.slice(`${JSCompiler_renameProperty('items', this)}.`.length);
let idx = parseInt(part, 10);
if ((part.indexOf('.') < 0) && part == idx) {
this.__deselectChangedIdx(idx);
Expand Down Expand Up @@ -167,7 +167,7 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
selected.forEach((idx, item) => {
if (idx < 0) {
if (this.multi) {
this.splice('selected', sidx, 1);
this.splice(JSCompiler_renameProperty('selected', this), sidx, 1);
} else {
this.selected = this.selectedItem = null;
}
Expand All @@ -184,13 +184,19 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
let sidx = 0;
this.__selectedMap.forEach(idx => {
if (idx >= 0) {
this.linkPaths('items.' + idx, 'selected.' + sidx++);
this.linkPaths(
`${JSCompiler_renameProperty('items', this)}.${idx}`,
`${JSCompiler_renameProperty('selected', this)}.${sidx++}`);
}
});
} else {
this.__selectedMap.forEach(idx => {
this.linkPaths('selected', 'items.' + idx);
this.linkPaths('selectedItem', 'items.' + idx);
this.linkPaths(
JSCompiler_renameProperty('selected', this),
`${JSCompiler_renameProperty('items', this)}.${idx}`);
this.linkPaths(
JSCompiler_renameProperty('selectedItem', this),
`${JSCompiler_renameProperty('items', this)}.${idx}`);
});
}
}
Expand Down Expand Up @@ -248,9 +254,9 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
}

__selectedIndexForItemIndex(idx) {
let selected = this.__dataLinkedPaths['items.' + idx];
let selected = this.__dataLinkedPaths[`${JSCompiler_renameProperty('items', this)}.${idx}`];
if (selected) {
return parseInt(selected.slice('selected.'.length), 10);
return parseInt(selected.slice(`${JSCompiler_renameProperty('selected', this)}.`.length), 10);
}
}

Expand All @@ -271,7 +277,7 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
}
this.__updateLinks();
if (this.multi) {
this.splice('selected', sidx, 1);
this.splice(JSCompiler_renameProperty('selected', this), sidx, 1);
} else {
this.selected = this.selectedItem = null;
}
Expand Down Expand Up @@ -318,7 +324,7 @@ let ArraySelectorMixin = dedupingMixin(superClass => {
this.__selectedMap.set(item, idx);
this.__updateLinks();
if (this.multi) {
this.push('selected', item);
this.push(JSCompiler_renameProperty('selected', this), item);
} else {
this.selected = this.selectedItem = item;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/elements/dom-repeat.js
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ export class DomRepeat extends domRepeatBase {
if (prop == this.as) {
this.items[idx] = value;
}
let path = translate(this.as, 'items.' + idx, prop);
let path = translate(this.as, `${JSCompiler_renameProperty('items', this)}.${idx}`, prop);
this.notifyPath(path, value);
}
}
Expand Down
24 changes: 22 additions & 2 deletions lib/legacy/class.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,26 @@ function flattenBehaviors(behaviors, list, exclude) {
return list;
}

/**
* Copies property descriptors from source to target, overwriting all fields
* of any previous descriptor for a property *except* for `value`, which is
* merged in from the target if it does not exist on the source.
*
* @param {*} target Target properties object
* @param {*} source Source properties object
*/
function mergeProperties(target, source) {
for (const p in source) {
const targetInfo = target[p];
const sourceInfo = source[p];
if (!('value' in sourceInfo) && targetInfo && ('value' in targetInfo)) {
target[p] = Object.assign({value: targetInfo.value}, sourceInfo);
} else {
target[p] = sourceInfo;
}
}
}

/* Note about construction and extension of legacy classes.
[Changed in Q4 2018 to optimize performance.]
Expand Down Expand Up @@ -227,10 +247,10 @@ function GenerateClassFromInfo(info, Base, behaviors) {
const properties = {};
if (behaviorList) {
for (let i=0; i < behaviorList.length; i++) {
Object.assign(properties, behaviorList[i].properties);
mergeProperties(properties, behaviorList[i].properties);
}
}
Object.assign(properties, info.properties);
mergeProperties(properties, info.properties);
return properties;
}

Expand Down
8 changes: 5 additions & 3 deletions lib/utils/debounce.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ export class Debouncer {
cancel() {
if (this.isActive()) {
this._cancelAsync();
this._timer = null;
// Canceling a debouncer removes its spot from the flush queue,
// so if a debouncer is manually canceled and re-debounced, it
// will reset its flush order (this is a very minor difference from 1.x)
Expand All @@ -61,7 +60,10 @@ export class Debouncer {
* @return {void}
*/
_cancelAsync() {
this._asyncModule.cancel(/** @type {number} */(this._timer));
if (this.isActive()) {
this._asyncModule.cancel(/** @type {number} */(this._timer));
this._timer = null;
}
}
/**
* Flushes an active debouncer and returns a reference to itself.
Expand Down Expand Up @@ -144,7 +146,7 @@ export const enqueueDebouncer = function(debouncer) {
/**
* Flushes any enqueued debouncers
*
* @return {void}
* @return {boolean} Returns whether any debouncers were flushed
*/
export const flushDebouncers = function() {
const didFlush = Boolean(debouncerQueue.size);
Expand Down
9 changes: 5 additions & 4 deletions lib/utils/gestures.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,10 @@ let mouseCanceller = function(mouseEvent) {
for (let i = 0; i < path.length; i++) {
if (path[i].nodeType === Node.ELEMENT_NODE) {
if (path[i].localName === 'label') {
clickedLabels.push(path[i]);
} else if (canBeLabelled(path[i])) {
let ownerLabels = matchingLabels(path[i]);
clickedLabels.push(/** @type {!HTMLLabelElement} */ (path[i]));
} else if (canBeLabelled(/** @type {!HTMLElement} */ (path[i]))) {
let ownerLabels =
matchingLabels(/** @type {!HTMLElement} */ (path[i]));
// check if one of the clicked labels is labelling this element
for (let j = 0; j < ownerLabels.length; j++) {
clickFromLabel = clickFromLabel || clickedLabels.indexOf(ownerLabels[j]) > -1;
Expand Down Expand Up @@ -386,7 +387,7 @@ export function deepTargetFind(x, y) {
* @return {EventTarget} Returns the event target.
*/
function _findOriginalTarget(ev) {
const path = getComposedPath(ev);
const path = getComposedPath(/** @type {?Event} */ (ev));
// It shouldn't be, but sometimes path is empty (window on Safari).
return path.length > 0 ? path[0] : ev.target;
}
Expand Down
20 changes: 12 additions & 8 deletions test/unit/behaviors.html
Original file line number Diff line number Diff line change
Expand Up @@ -402,23 +402,26 @@
behaviors: [
{
properties: {
foo: { value: true },
bar: { value: true}
foo: { value: 'a' },
bar: { value: 'a' },
ziz: { value: 'a' }
}
},
{
properties: {
foo: { value: true },
foo: { value: 'b' },
bar: String,
zot: {value: true}
zot: { value: 'b' },
ziz: { value: 'b' }
}
},

],

properties: {
foo: String,
zot: String
zot: String,
ziz: { value: 'c' }
}
});

Expand Down Expand Up @@ -587,9 +590,10 @@

test('behavior default values can be overridden', function() {
const el = fixture('override-default-value');
assert.notOk(el.foo);
assert.notOk(el.bar);
assert.notOk(el.zot);
assert.equal(el.foo, 'b');
assert.equal(el.bar, 'a');
assert.equal(el.zot, 'b');
assert.equal(el.ziz, 'c');
});

test('readOnly not applied when property was previously observed', function() {
Expand Down
92 changes: 55 additions & 37 deletions test/unit/debounce.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,61 @@
import { enqueueDebouncer, flush } from '../../lib/utils/flush.js';
Polymer({is: 'x-basic'});

suite('enqueueDebouncer & flush', function() {

// NOTE: This is a regression test; the bug it fixed only occured if the
// debouncer was flushed before any microtasks run, hence it should be
// first in this file
test('re-enqueue canceled debouncer', function() {
const cb = sinon.spy();
let db;
db = Debouncer.debounce(null, microTask, cb);
enqueueDebouncer(db);
db.cancel();
assert.equal(db.isActive(), false);
assert.equal(cb.callCount, 0);
db = Debouncer.debounce(db, microTask, cb);
enqueueDebouncer(db);
flush();
assert.isTrue(cb.calledOnce);
});

const testEnqueue = (shouldFlush, done) => {
const actualOrder = [];
const enqueue = (type, {db, cb} = {}) => {
cb = cb || (() => actualOrder.push(cb));
db = Debouncer.debounce(db, type, cb);
enqueueDebouncer(db);
return {db, cb};
};
const db1 = enqueue(microTask);
const db2 = enqueue(microTask);
const db3 = enqueue(timeOut);
const db4 = enqueue(microTask);
enqueue(microTask, db2);
enqueue(microTask, db1);
if (shouldFlush) {
flush();
assert.deepEqual(actualOrder, [db1.cb, db2.cb, db3.cb, db4.cb]);
done();
} else {
timeOut.run(() => {
assert.deepEqual(actualOrder, [db4.cb, db2.cb, db1.cb, db3.cb]);
done();
});
}
};

test('non-flushed', function(done) {
testEnqueue(false, done);
});

test('flushed', function(done) {
testEnqueue(true, done);
});

});

suite('debounce', function() {
var element;

Expand Down Expand Up @@ -211,43 +266,6 @@

});

suite('enqueueDebouncer & flush', function() {

const testEnqueue = (shouldFlush, done) => {
const actualOrder = [];
const enqueue = (type, {db, cb} = {}) => {
cb = cb || (() => actualOrder.push(cb));
db = Debouncer.debounce(db, type, cb);
enqueueDebouncer(db);
return {db, cb};
};
const db1 = enqueue(microTask);
const db2 = enqueue(microTask);
const db3 = enqueue(timeOut);
const db4 = enqueue(microTask);
enqueue(microTask, db2);
enqueue(microTask, db1);
if (shouldFlush) {
flush();
assert.deepEqual(actualOrder, [db1.cb, db2.cb, db3.cb, db4.cb]);
done();
} else {
timeOut.run(() => {
assert.deepEqual(actualOrder, [db4.cb, db2.cb, db1.cb, db3.cb]);
done();
});
}
};

test('non-flushed', function(done) {
testEnqueue(false, done);
});

test('flushed', function(done) {
testEnqueue(true, done);
});

});
});
</script>
</body>
Expand Down

0 comments on commit 810a70f

Please sign in to comment.