* Performs an element update. Note, if an exception is thrown during the * update, `firstUpdated` and `updated` will not be called. * * Call `performUpdate()` to immediately process a pending update. This should * generally not be needed, but it can be done in rare cases when you need to
()
| 1427 | * @category updates |
| 1428 | */ |
| 1429 | protected performUpdate(): void { |
| 1430 | // Abort any update if one is not pending when this is called. |
| 1431 | // This can happen if `performUpdate` is called early to "flush" |
| 1432 | // the update. |
| 1433 | if (!this.isUpdatePending) { |
| 1434 | return; |
| 1435 | } |
| 1436 | debugLogEvent?.({kind: 'update'}); |
| 1437 | if (!this.hasUpdated) { |
| 1438 | // Create renderRoot before first update. This occurs in `connectedCallback` |
| 1439 | // but is done here to support out of tree calls to `enableUpdating`/`performUpdate`. |
| 1440 | (this as Mutable<typeof this, 'renderRoot'>).renderRoot ??= |
| 1441 | this.createRenderRoot(); |
| 1442 | if (DEV_MODE) { |
| 1443 | // Produce warning if any reactive properties on the prototype are |
| 1444 | // shadowed by class fields. Instance fields set before upgrade are |
| 1445 | // deleted by this point, so any own property is caused by class field |
| 1446 | // initialization in the constructor. |
| 1447 | const ctor = this.constructor as typeof ReactiveElement; |
| 1448 | const shadowedProperties = [...ctor.elementProperties.keys()].filter( |
| 1449 | (p) => this.hasOwnProperty(p) && p in getPrototypeOf(this) |
| 1450 | ); |
| 1451 | if (shadowedProperties.length) { |
| 1452 | throw new Error( |
| 1453 | `The following properties on element ${this.localName} will not ` + |
| 1454 | `trigger updates as expected because they are set using class ` + |
| 1455 | `fields: ${shadowedProperties.join(', ')}. ` + |
| 1456 | `Native class fields and some compiled output will overwrite ` + |
| 1457 | `accessors used for detecting changes. See ` + |
| 1458 | `https://lit.dev/msg/class-field-shadowing ` + |
| 1459 | `for more information.` |
| 1460 | ); |
| 1461 | } |
| 1462 | } |
| 1463 | // Mixin instance properties once, if they exist. |
| 1464 | if (this.__instanceProperties) { |
| 1465 | // TODO (justinfagnani): should we use the stored value? Could a new value |
| 1466 | // have been set since we stored the own property value? |
| 1467 | for (const [p, value] of this.__instanceProperties) { |
| 1468 | this[p as keyof this] = value as this[keyof this]; |
| 1469 | } |
| 1470 | this.__instanceProperties = undefined; |
| 1471 | } |
| 1472 | // Trigger initial value reflection and populate the initial |
| 1473 | // `changedProperties` map, but only for the case of properties created |
| 1474 | // via `createProperty` on accessors, which will not have already |
| 1475 | // populated the `changedProperties` map since they are not set. |
| 1476 | // We can't know if these accessors had initializers, so we just set |
| 1477 | // them anyway - a difference from experimental decorators on fields and |
| 1478 | // standard decorators on auto-accessors. |
| 1479 | // For context see: |
| 1480 | // https://github.com/lit/lit/pull/4183#issuecomment-1711959635 |
| 1481 | const elementProperties = (this.constructor as typeof ReactiveElement) |
| 1482 | .elementProperties; |
| 1483 | if (elementProperties.size > 0) { |
| 1484 | for (const [p, options] of elementProperties) { |
| 1485 | const {wrapped} = options; |
| 1486 | const value = this[p as keyof this]; |
nothing calls this directly
no test coverage detected
searching dependent graphs…