Through manual manipulation via document.createElement — it’s possible to get into a bizarre scenario where computed properties appear to be inexplicably wrong. Take the following:
import XElement from 'https://deno.land/x/element/x-element.js';
class TestElement extends XElement {
static get properties() {
return {
a: { type: Number },
b: { type: Number },
c: { type: Number, internal: true, input: ['a', 'b'], compute: (a, b) => a + b },
};
}
}
customElements.define('test-element', TestElement);
// Hint: This element is constructed, but not initialized.
const element = document.createElement('test-element');
element.setAttribute('a', '1');
element.setAttribute('b', '2');
console.log({ a: element.a, b: element.b, c: element.internal.c });
/*
This is reasonable — it's not expected that attributes sync before DOM connection.
{
a: undefined,
b: undefined,
c: NaN
}
*/
// By attaching it to the DOM, we finally initialize.
document.body.append(element);
console.log({ a: element.a, b: element.b, c: element.internal.c });
/*
This is NOT reasonable — everything should _just work_ after initialization.
{
a: 1,
b: 2,
c: NaN
}
*/
To summarize — this edge case is caused by manual manipulation of attributes and introspection of downstream, internal, computed properties thereof.
In theory, this might even be caused by race conditions due to timing issues between attribute setting, property introspection, and forcible upgrade paths via customElements.upgrade. However, the simple target is to fix the easily-reproducible issue.
Proposal
Explicitly set the memoized compute state to valid = false on initialization. I.e., expect that the element could have been manipulated / interrogated between construction and initialization.
Through manual manipulation via
document.createElement
— it’s possible to get into a bizarre scenario where computed properties appear to be inexplicably wrong. Take the following:To summarize — this edge case is caused by manual manipulation of attributes and introspection of downstream, internal, computed properties thereof.
In theory, this might even be caused by race conditions due to timing issues between attribute setting, property introspection, and forcible upgrade paths via
customElements.upgrade
. However, the simple target is to fix the easily-reproducible issue.Proposal
Explicitly set the memoized compute state to
valid = false
on initialization. I.e., expect that the element could have been manipulated / interrogated between construction and initialization.