From 1e567b4e2f1ef953743a0d1372c251078660d89b Mon Sep 17 00:00:00 2001 From: Steven Orvell Date: Fri, 28 Feb 2020 17:25:36 -0800 Subject: [PATCH 01/12] Adds `forceUpdate()` Allows users to force elements to update synchronously. --- src/lib/updating-element.ts | 13 +++++++++++++ src/test/lib/updating-element_test.ts | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/lib/updating-element.ts b/src/lib/updating-element.ts index a672baea..12d827fd 100644 --- a/src/lib/updating-element.ts +++ b/src/lib/updating-element.ts @@ -679,6 +679,9 @@ export abstract class UpdatingElement extends HTMLElement { * ``` */ protected performUpdate(): void|Promise { + if (!this._hasRequestedUpdate) { + return; + } // Mixin instance properties once, if they exist. if (this._instanceProperties) { this._applyInstanceProperties(); @@ -709,6 +712,16 @@ export abstract class UpdatingElement extends HTMLElement { } } + /** + * Forces a synchronous update. + */ + forceUpdate(name?: PropertyKey, oldValue?: unknown) { + if (name || !this._hasRequestedUpdate) { + this.requestUpdateInternal(name, oldValue); + } + this.performUpdate(); + } + private _markUpdated() { this._changedProperties = new Map(); this._updateState = this._updateState & ~STATE_UPDATE_REQUESTED; diff --git a/src/test/lib/updating-element_test.ts b/src/test/lib/updating-element_test.ts index 8421eec9..b152cccb 100644 --- a/src/test/lib/updating-element_test.ts +++ b/src/test/lib/updating-element_test.ts @@ -75,6 +75,28 @@ suite('UpdatingElement', () => { assert.equal(el.updateCount, 2); }); + test('Can call `forceUpdate()` to make update synchronous', async () => { + class E extends UpdatingElement { + updateCount = 0; + updated() { + this.updateCount++; + } + } + customElements.define(generateElementName(), E); + const el = new E(); + container.appendChild(el); + el.forceUpdate(); + assert.equal(el.updateCount, 1); + el.forceUpdate(); + assert.equal(el.updateCount, 2); + el.requestUpdate(); + el.forceUpdate(); + assert.equal(el.updateCount, 3); + el.forceUpdate(); + await el.updateComplete; + assert.equal(el.updateCount, 4); + }); + test('`shouldUpdate` controls update', async () => { class E extends UpdatingElement { needsUpdate = true; From c08979d4324228266fe649cbd46e921508c7cd37 Mon Sep 17 00:00:00 2001 From: Steven Orvell Date: Wed, 4 Mar 2020 18:37:22 -0800 Subject: [PATCH 02/12] Test: can make property accessor perform sync update. Removes `forceUpdate` in favor of calling `performUpdate` in an accessor. --- src/lib/updating-element.ts | 10 --- src/test/lib/updating-element_test.ts | 89 ++++++++++++++++++++------- 2 files changed, 67 insertions(+), 32 deletions(-) diff --git a/src/lib/updating-element.ts b/src/lib/updating-element.ts index 89874599..3f7423ab 100644 --- a/src/lib/updating-element.ts +++ b/src/lib/updating-element.ts @@ -726,16 +726,6 @@ export abstract class UpdatingElement extends HTMLElement { } } - /** - * Forces a synchronous update. - */ - forceUpdate(name?: PropertyKey, oldValue?: unknown) { - if (name || !this._hasRequestedUpdate) { - this.requestUpdateInternal(name, oldValue); - } - this.performUpdate(); - } - private _markUpdated() { this._changedProperties = new Map(); this._updateState = this._updateState & ~STATE_UPDATE_REQUESTED; diff --git a/src/test/lib/updating-element_test.ts b/src/test/lib/updating-element_test.ts index 8210c705..ebc53d68 100644 --- a/src/test/lib/updating-element_test.ts +++ b/src/test/lib/updating-element_test.ts @@ -75,28 +75,6 @@ suite('UpdatingElement', () => { assert.equal(el.updateCount, 2); }); - test('Can call `forceUpdate()` to make update synchronous', async () => { - class E extends UpdatingElement { - updateCount = 0; - updated() { - this.updateCount++; - } - } - customElements.define(generateElementName(), E); - const el = new E(); - container.appendChild(el); - el.forceUpdate(); - assert.equal(el.updateCount, 1); - el.forceUpdate(); - assert.equal(el.updateCount, 2); - el.requestUpdate(); - el.forceUpdate(); - assert.equal(el.updateCount, 3); - el.forceUpdate(); - await el.updateComplete; - assert.equal(el.updateCount, 4); - }); - test('`shouldUpdate` controls update', async () => { class E extends UpdatingElement { needsUpdate = true; @@ -1934,6 +1912,73 @@ suite('UpdatingElement', () => { assert.equal(el.foo, 0); }); + test.only('can make properties sync by createProperty', async () => { + + interface MyPropertyDeclaration extends PropertyDeclaration { + sync: boolean + } + + @customElement(generateElementName()) + class E extends UpdatingElement { + + static createProperty( + name: PropertyKey, + options: MyPropertyDeclaration) { + this.setOptionsForProperty(name, options); + if (options.noAccessor || this.prototype.hasOwnProperty(name)) { + return; + } + const key = typeof name === 'symbol' ? Symbol() : `__${name}`; + Object.defineProperty(this.prototype, name, { + // tslint:disable-next-line:no-any no symbol in index + get(): any { + return (this as {[key: string]: unknown})[key as string]; + }, + set(this: E, value: unknown) { + const oldValue = + (this as {} as {[key: string]: unknown})[name as string]; + (this as {} as {[key: string]: unknown})[key as string] = value; + (this as unknown as E).requestUpdateInternal(name, oldValue); + if (options.sync && this.hasUpdated) { + (this as unknown as E).performUpdate(); + } + }, + configurable: true, + enumerable: true + }); + } + + updateCount = 0; + + updated() { + this.updateCount++; + } + + @property({type: Number, sync: true, reflect: true}) + foo = 5; + + @property({}) + bar = 'bar'; + + } + + const el = new E(); + container.appendChild(el); + await el.updateComplete; + el.foo = 10; + assert.equal(el.updateCount, 2); + el.foo = 1; + el.foo = 2; + assert.equal(el.updateCount, 4); + el.foo = 3; + await el.updateComplete; + assert.equal(el.updateCount, 5); + el.bar = 'bar2'; + assert.equal(el.updateCount, 5); + await el.updateComplete; + assert.equal(el.updateCount, 6); + }); + test('attribute-based property storage', async () => { class E extends UpdatingElement { _updateCount = 0; From d121098815038cd0b9e2d72ade7bc0d7cb2e141b Mon Sep 17 00:00:00 2001 From: Steven Orvell Date: Thu, 5 Mar 2020 13:52:58 -0800 Subject: [PATCH 03/12] Update test --- src/test/lib/updating-element_test.ts | 38 +++++++++++---------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/src/test/lib/updating-element_test.ts b/src/test/lib/updating-element_test.ts index 098f1c63..49eabad7 100644 --- a/src/test/lib/updating-element_test.ts +++ b/src/test/lib/updating-element_test.ts @@ -1905,7 +1905,7 @@ suite('UpdatingElement', () => { assert.equal(el.foo, 0); }); - test.only('can make properties sync by createProperty', async () => { + test('can make properties sync by createProperty', async () => { interface MyPropertyDeclaration extends PropertyDeclaration { sync: boolean @@ -1916,29 +1916,21 @@ suite('UpdatingElement', () => { static createProperty( name: PropertyKey, - options: MyPropertyDeclaration) { - this.setOptionsForProperty(name, options); - if (options.noAccessor || this.prototype.hasOwnProperty(name)) { - return; - } - const key = typeof name === 'symbol' ? Symbol() : `__${name}`; - Object.defineProperty(this.prototype, name, { - // tslint:disable-next-line:no-any no symbol in index - get(): any { - return (this as {[key: string]: unknown})[key as string]; - }, - set(this: E, value: unknown) { - const oldValue = - (this as {} as {[key: string]: unknown})[name as string]; - (this as {} as {[key: string]: unknown})[key as string] = value; - (this as unknown as E).requestUpdateInternal(name, oldValue); - if (options.sync && this.hasUpdated) { - (this as unknown as E).performUpdate(); + options: PropertyDeclaration, + descriptorFactory: PropertyDescriptorFactory) { + + descriptorFactory = (options: PropertyDeclaration, _key: symbol|string, descriptor: PropertyDescriptor) => { + const setter = descriptor.set!; + return Object.assign(descriptor, { + set(this: E, value: unknown) { + setter.call(this, value); + if ((options as MyPropertyDeclaration).sync && this.hasUpdated) { + (this as unknown as E).performUpdate(); + } } - }, - configurable: true, - enumerable: true - }); + }); + }; + super.createProperty(name, options, descriptorFactory); } updateCount = 0; From 2bb927723b658e01f85b8b7ecd6b7760b2f55052 Mon Sep 17 00:00:00 2001 From: Steven Orvell Date: Thu, 5 Mar 2020 13:58:01 -0800 Subject: [PATCH 04/12] Change argument order --- src/test/lib/updating-element_test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/lib/updating-element_test.ts b/src/test/lib/updating-element_test.ts index f25f65eb..c95b1502 100644 --- a/src/test/lib/updating-element_test.ts +++ b/src/test/lib/updating-element_test.ts @@ -1919,7 +1919,7 @@ suite('UpdatingElement', () => { options: PropertyDeclaration, descriptorFactory: PropertyDescriptorFactory) { - descriptorFactory = (options: PropertyDeclaration, _key: symbol|string, descriptor: PropertyDescriptor) => { + descriptorFactory = (options: PropertyDeclaration, descriptor: PropertyDescriptor) => { const setter = descriptor.set!; return Object.assign(descriptor, { set(this: E, value: unknown) { From 27cb2f122160f940c9f3113c01d883d7bc286805 Mon Sep 17 00:00:00 2001 From: Steven Orvell Date: Mon, 9 Mar 2020 15:33:29 -0700 Subject: [PATCH 05/12] Update to use `createPropertyDescriptor` --- src/test/lib/updating-element_test.ts | 29 ++++++++++++--------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/src/test/lib/updating-element_test.ts b/src/test/lib/updating-element_test.ts index 19c9e1ce..5bfec073 100644 --- a/src/test/lib/updating-element_test.ts +++ b/src/test/lib/updating-element_test.ts @@ -1930,7 +1930,7 @@ suite('UpdatingElement', () => { assert.deepEqual(el._observedZot, {value: 'zot', oldValue: ''}); }); - test('can make properties sync by createProperty', async () => { + test('can customize properties to update synchronously', async () => { interface MyPropertyDeclaration extends PropertyDeclaration { sync: boolean @@ -1939,23 +1939,20 @@ suite('UpdatingElement', () => { @customElement(generateElementName()) class E extends UpdatingElement { - static createProperty( + static createPropertyDescriptor( name: PropertyKey, - options: PropertyDeclaration, - descriptorFactory: PropertyDescriptorFactory) { - - descriptorFactory = (options: PropertyDeclaration, descriptor: PropertyDescriptor) => { - const setter = descriptor.set!; - return Object.assign(descriptor, { - set(this: E, value: unknown) { - setter.call(this, value); - if ((options as MyPropertyDeclaration).sync && this.hasUpdated) { - (this as unknown as E).performUpdate(); - } + key: string|symbol, + options: MyPropertyDeclaration) { + const defaultDescriptor = super.createPropertyDescriptor(name, key, options); + const setter = defaultDescriptor.set; + return Object.assign(defaultDescriptor, { + set(this: E, value: unknown) { + setter.call(this, value); + if (options.sync && this.hasUpdated) { + (this as unknown as E).performUpdate(); } - }); - }; - super.createProperty(name, options, descriptorFactory); + } + }); } updateCount = 0; From 270f44c97e415d6b4a1abade2f9ee2ca65214841 Mon Sep 17 00:00:00 2001 From: Steven Orvell Date: Mon, 13 Apr 2020 09:22:43 -0700 Subject: [PATCH 06/12] Update test slightly --- src/lib/updating-element.ts | 3 +++ src/test/lib/updating-element_test.ts | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lib/updating-element.ts b/src/lib/updating-element.ts index 28eed8cb..98185af8 100644 --- a/src/lib/updating-element.ts +++ b/src/lib/updating-element.ts @@ -751,6 +751,9 @@ export abstract class UpdatingElement extends HTMLElement { * ``` */ protected performUpdate(): void|Promise { + // Abort any update if one is not pending when this is called. + // This can happen if `performUpdate` as called early to "flush" + // the update. if (!this._hasRequestedUpdate) { return; } diff --git a/src/test/lib/updating-element_test.ts b/src/test/lib/updating-element_test.ts index 5151dce7..f1650908 100644 --- a/src/test/lib/updating-element_test.ts +++ b/src/test/lib/updating-element_test.ts @@ -1978,17 +1978,17 @@ suite('UpdatingElement', () => { test('can customize properties to update synchronously', async () => { interface MyPropertyDeclaration extends PropertyDeclaration { - sync: boolean + sync: boolean; } @customElement(generateElementName()) class E extends UpdatingElement { - static createPropertyDescriptor( + static getPropertyDescriptor( name: PropertyKey, key: string|symbol, options: MyPropertyDeclaration) { - const defaultDescriptor = super.createPropertyDescriptor(name, key, options); + const defaultDescriptor = super.getPropertyDescriptor(name, key, options); const setter = defaultDescriptor.set; return Object.assign(defaultDescriptor, { set(this: E, value: unknown) { @@ -2006,7 +2006,7 @@ suite('UpdatingElement', () => { this.updateCount++; } - @property({type: Number, sync: true, reflect: true}) + @property({type: Number, sync: true, reflect: true} as PropertyDeclaration) foo = 5; @property({}) From 2ef5f99ad85c4313f16a119106266afde3867300 Mon Sep 17 00:00:00 2001 From: Steven Orvell Date: Mon, 13 Apr 2020 09:28:11 -0700 Subject: [PATCH 07/12] Update chancelog.md --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 597c043c..ccc5cbb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). +### Added +* The protected `performUpdate()` method may not be called, for example via a +property setter, to syncronously "flush" a pending update. Note, this updates +only the element and not any potentially pending descendants in the element's +local DOM ([#959](https://github.com/Polymer/lit-element/issues/959)). + +* Constructible stylesheets may not be provided directly as styles, in addition to using the `css` tagged template function ([#853](https://github.com/Polymer/lit-element/issues/853)). + ## [2.3.1] - 2020-03-19 ### Fixed From a05ae081b3ffdc3e4716749405435792556809bb Mon Sep 17 00:00:00 2001 From: Steven Orvell Date: Mon, 13 Apr 2020 09:30:30 -0700 Subject: [PATCH 08/12] Fix typos --- CHANGELOG.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccc5cbb0..56126096 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,12 +18,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added -* The protected `performUpdate()` method may not be called, for example via a -property setter, to syncronously "flush" a pending update. Note, this updates -only the element and not any potentially pending descendants in the element's -local DOM ([#959](https://github.com/Polymer/lit-element/issues/959)). +* The protected `performUpdate()` method may now be called to syncronously "flush" a pending update, for example via a property setter. Note, this updates only the element and not any potentially pending descendants in the element's local DOM ([#959](https://github.com/Polymer/lit-element/issues/959)). -* Constructible stylesheets may not be provided directly as styles, in addition to using the `css` tagged template function ([#853](https://github.com/Polymer/lit-element/issues/853)). +* Constructible stylesheets may now be provided directly as styles, in addition to using the `css` tagged template function ([#853](https://github.com/Polymer/lit-element/issues/853)). ## [2.3.1] - 2020-03-19 From 30af837ae16763ef186c04db8292953959f68aa1 Mon Sep 17 00:00:00 2001 From: Steven Orvell Date: Mon, 13 Apr 2020 10:05:07 -0700 Subject: [PATCH 09/12] Exposes protected `isUpdatePending` property This can be useful to check, for example in a custom property setter. --- CHANGELOG.md | 2 +- src/lib/updating-element.ts | 8 ++++---- src/test/lib/updating-element_test.ts | 11 ++++++++++- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56126096..834f418a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added -* The protected `performUpdate()` method may now be called to syncronously "flush" a pending update, for example via a property setter. Note, this updates only the element and not any potentially pending descendants in the element's local DOM ([#959](https://github.com/Polymer/lit-element/issues/959)). +* The protected `performUpdate()` method may now be called to syncronously "flush" a pending update, for example via a property setter. Also adds a protected `isUpdatePending` property which can be checked to see if an update is currently scheduled. Note, performing a synchronous update only updates the element and not any potentially pending descendants in the element's local DOM ([#959](https://github.com/Polymer/lit-element/issues/959)). * Constructible stylesheets may now be provided directly as styles, in addition to using the `css` tagged template function ([#853](https://github.com/Polymer/lit-element/issues/853)). diff --git a/src/lib/updating-element.ts b/src/lib/updating-element.ts index 98185af8..ddc5e444 100644 --- a/src/lib/updating-element.ts +++ b/src/lib/updating-element.ts @@ -680,7 +680,7 @@ export abstract class UpdatingElement extends HTMLElement { shouldRequestUpdate = false; } } - if (!this._hasRequestedUpdate && shouldRequestUpdate) { + if (!this.isUpdatePending && shouldRequestUpdate) { this._updatePromise = this._enqueueUpdate(); } } @@ -723,10 +723,10 @@ export abstract class UpdatingElement extends HTMLElement { if (result != null) { await result; } - return !this._hasRequestedUpdate; + return !this.isUpdatePending; } - private get _hasRequestedUpdate() { + protected get isUpdatePending() { return (this._updateState & STATE_UPDATE_REQUESTED); } @@ -754,7 +754,7 @@ export abstract class UpdatingElement extends HTMLElement { // Abort any update if one is not pending when this is called. // This can happen if `performUpdate` as called early to "flush" // the update. - if (!this._hasRequestedUpdate) { + if (!this.isUpdatePending) { return; } // Mixin instance properties once, if they exist. diff --git a/src/test/lib/updating-element_test.ts b/src/test/lib/updating-element_test.ts index f1650908..9843ecc6 100644 --- a/src/test/lib/updating-element_test.ts +++ b/src/test/lib/updating-element_test.ts @@ -1992,8 +1992,9 @@ suite('UpdatingElement', () => { const setter = defaultDescriptor.set; return Object.assign(defaultDescriptor, { set(this: E, value: unknown) { + const isUpdatePending = this.isUpdatePending; setter.call(this, value); - if (options.sync && this.hasUpdated) { + if (options.sync && this.hasUpdated && !isUpdatePending) { (this as unknown as E).performUpdate(); } } @@ -2002,6 +2003,11 @@ suite('UpdatingElement', () => { updateCount = 0; + update(changedProperties: PropertyValues) { + this.zug = this.foo + 1; + super.update(changedProperties); + } + updated() { this.updateCount++; } @@ -2009,6 +2015,9 @@ suite('UpdatingElement', () => { @property({type: Number, sync: true, reflect: true} as PropertyDeclaration) foo = 5; + @property({type: Number, sync: true} as PropertyDeclaration) + zug = this.foo; + @property({}) bar = 'bar'; From a142648c68dc0780a155fd0398fdff36964c189a Mon Sep 17 00:00:00 2001 From: Steve Orvell Date: Tue, 14 Apr 2020 14:15:56 -0700 Subject: [PATCH 10/12] Update src/lib/updating-element.ts Co-Authored-By: Kevin Schaaf --- src/lib/updating-element.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/updating-element.ts b/src/lib/updating-element.ts index ddc5e444..6a9ca8ca 100644 --- a/src/lib/updating-element.ts +++ b/src/lib/updating-element.ts @@ -752,7 +752,7 @@ export abstract class UpdatingElement extends HTMLElement { */ protected performUpdate(): void|Promise { // Abort any update if one is not pending when this is called. - // This can happen if `performUpdate` as called early to "flush" + // This can happen if `performUpdate` is called early to "flush" // the update. if (!this.isUpdatePending) { return; From 3ebdae01369a3231d446751b17d70bfc21b838ba Mon Sep 17 00:00:00 2001 From: Steven Orvell Date: Tue, 14 Apr 2020 14:35:49 -0700 Subject: [PATCH 11/12] Reverts adding `isUpdatePending` as there was no clear use case --- CHANGELOG.md | 2 +- src/lib/updating-element.ts | 8 ++++---- src/test/lib/updating-element_test.ts | 11 +++++++++-- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 834f418a..9709e527 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added -* The protected `performUpdate()` method may now be called to syncronously "flush" a pending update, for example via a property setter. Also adds a protected `isUpdatePending` property which can be checked to see if an update is currently scheduled. Note, performing a synchronous update only updates the element and not any potentially pending descendants in the element's local DOM ([#959](https://github.com/Polymer/lit-element/issues/959)). +* The protected `performUpdate()` method may now be called to syncronously "flush" a pending update, for example via a property setter. Note, performing a synchronous update only updates the element and not any potentially pending descendants in the element's local DOM ([#959](https://github.com/Polymer/lit-element/issues/959)). * Constructible stylesheets may now be provided directly as styles, in addition to using the `css` tagged template function ([#853](https://github.com/Polymer/lit-element/issues/853)). diff --git a/src/lib/updating-element.ts b/src/lib/updating-element.ts index ddc5e444..98185af8 100644 --- a/src/lib/updating-element.ts +++ b/src/lib/updating-element.ts @@ -680,7 +680,7 @@ export abstract class UpdatingElement extends HTMLElement { shouldRequestUpdate = false; } } - if (!this.isUpdatePending && shouldRequestUpdate) { + if (!this._hasRequestedUpdate && shouldRequestUpdate) { this._updatePromise = this._enqueueUpdate(); } } @@ -723,10 +723,10 @@ export abstract class UpdatingElement extends HTMLElement { if (result != null) { await result; } - return !this.isUpdatePending; + return !this._hasRequestedUpdate; } - protected get isUpdatePending() { + private get _hasRequestedUpdate() { return (this._updateState & STATE_UPDATE_REQUESTED); } @@ -754,7 +754,7 @@ export abstract class UpdatingElement extends HTMLElement { // Abort any update if one is not pending when this is called. // This can happen if `performUpdate` as called early to "flush" // the update. - if (!this.isUpdatePending) { + if (!this._hasRequestedUpdate) { return; } // Mixin instance properties once, if they exist. diff --git a/src/test/lib/updating-element_test.ts b/src/test/lib/updating-element_test.ts index 9843ecc6..60571649 100644 --- a/src/test/lib/updating-element_test.ts +++ b/src/test/lib/updating-element_test.ts @@ -1992,20 +1992,23 @@ suite('UpdatingElement', () => { const setter = defaultDescriptor.set; return Object.assign(defaultDescriptor, { set(this: E, value: unknown) { - const isUpdatePending = this.isUpdatePending; setter.call(this, value); - if (options.sync && this.hasUpdated && !isUpdatePending) { + if (options.sync && this.hasUpdated && !this.isUpdating) { (this as unknown as E).performUpdate(); } } }); } + isUpdating = false; + updateCount = 0; update(changedProperties: PropertyValues) { + this.isUpdating = true; this.zug = this.foo + 1; super.update(changedProperties); + this.isUpdating = false; } updated() { @@ -2038,6 +2041,10 @@ suite('UpdatingElement', () => { assert.equal(el.updateCount, 5); await el.updateComplete; assert.equal(el.updateCount, 6); + el.foo = 5; + assert.equal(el.updateCount, 7); + el.zug = 60; + assert.equal(el.updateCount, 8); }); test('attribute-based property storage', async () => { From 8e64370c7860be4e8073c4932c1bee8489249e2d Mon Sep 17 00:00:00 2001 From: Steven Orvell Date: Tue, 14 Apr 2020 14:48:50 -0700 Subject: [PATCH 12/12] Tweak test --- src/test/lib/updating-element_test.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/test/lib/updating-element_test.ts b/src/test/lib/updating-element_test.ts index 60571649..f6346c6a 100644 --- a/src/test/lib/updating-element_test.ts +++ b/src/test/lib/updating-element_test.ts @@ -2004,11 +2004,17 @@ suite('UpdatingElement', () => { updateCount = 0; - update(changedProperties: PropertyValues) { + performUpdate() { + // While it's dubious to have a computed property that's + // also settable but this just demonstrates it's possible. this.isUpdating = true; + super.performUpdate(); + this.isUpdating = false; + } + + update(changedProperties: PropertyValues) { this.zug = this.foo + 1; super.update(changedProperties); - this.isUpdating = false; } updated() {