Skip to content

Commit

Permalink
Ensure computation on initialization.
Browse files Browse the repository at this point in the history
This handles a nuanced edge case where internal, computed properties
can be incorrect if they were interrogated between host construction and
initialization.

For example:

```javascript
// This will trigger construction (assuming the element is defined).
const element = document.createElement('my-element');

// Do things after construction, before initialization.

// This will trigger initialization (again, assuming definition).
document.body.append(element);

// Do things after initialization while connected.
```

This change set should guarantee that after initialization, during
connection — things will be correct. We cannot make such guarantees when
not connected due to lack of eventing around attribute callbacks.

Closes #143.
  • Loading branch information
theengineear committed May 24, 2023
1 parent 3c73774 commit 97df916
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 1 deletion.
13 changes: 13 additions & 0 deletions test/test-computed-properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,19 @@ it('does correct NaN checking', () => {
assert(el.count === count);
});

it('resets compute validity on initialization to catch upgrade edge cases with internal, computed properties', () => {
const el = document.createElement('test-element');
el.setAttribute('a', '1');
el.setAttribute('b', '2');
assert(el.a === undefined);
assert(el.b === undefined);
assert(Number.isNaN(el.internal.c));
document.body.append(el);
assert(el.a === 1);
assert(el.b === 2);
assert(el.internal.c === 3);
});

it('cannot be written to from host', () => {
const el = document.createElement('test-element');
document.body.append(el);
Expand Down
5 changes: 4 additions & 1 deletion x-element.js
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ export default class XElement extends HTMLElement {

static #initializeHost(host) {
const hostInfo = XElement.#hosts.get(host);
const { initialized, invalidProperties } = hostInfo;
const { computeMap, initialized, invalidProperties } = hostInfo;
if (initialized === false) {
XElement.#upgradeOwnProperties(host);
// Only reflect attributes when the element is connected.
Expand All @@ -661,6 +661,9 @@ export default class XElement extends HTMLElement {
XElement.#setPropertyValue(host, property, property.default(host, property.initial()));
}
invalidProperties.add(property);
if (property.compute) {
computeMap.get(property).valid = false;
}
}
hostInfo.initialized = true;
return true;
Expand Down

0 comments on commit 97df916

Please sign in to comment.