You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This test is namely for signals-based libraries. We need a test that shows that when a custom elements is rendered, none of its life cycle methods (constructor, connectedCallback, adoptedCallback, disconnectedCallback, and attributeChangedCallback) cause an infinite loop when reading the framework's reactive state.
Here's an example (and a good sample test case we can write) in Solid.js where it will infinite-loop and eventually crash by simply reading a signal in a custom element life cycle method:
Besides this, we may want to include more libs, or lib combos, that use signals-and-effects patterns:
Solid.js
Preact with Preact Signals
Lit with its wrapper around Preact Signals, @lit-labs/preact-signals
React + MobX and others
Vue with ref() API and setup mode
Svelte 5 with its new Runes API
etc
The text was updated successfully, but these errors were encountered:
trusktr
changed the title
New test: custom elements should not cause infinite reactivity loops
New test: custom elements should not cause infinite reactivity loops in signals-based libraries
Jan 20, 2024
import{render,signal,effect,untrack,setAttribute,setProperty}from'pota'const[read,write]=signal(true)functionrecurse(name){console.log(name)write(!read())}classCustomElementextendsHTMLElement{staticobservedAttributes=['string-attribute']constructor(){super()recurse('constructor')}connectedCallback(){recurse('Custom element added to page.')}disconnectedCallback(){recurse('Custom element removed from page.')}adoptedCallback(){recurse('Custom element moved to new page.')}attributeChangedCallback(name,oldValue,newValue){recurse('Attribute has changed.')}setboolean(value){recurse('boolean has changed.')}}customElements.define('custom-element',CustomElement)/** Make sure the test is done inside an effect */letdisposeeffect(()=>{// if the reactive lib tracks any custom element callbacks, it will recurse./** * "document.createElement" is not controlled by the reactive libs, so * just untrack it. */constelement=untrack(()=>document.createElement('custom-element'))/** Reactive lib shouldnt cause tracking when setting an attribute */setAttribute(element,'string-attribute','lalala 2')/** Reactive lib shouldnt cause tracking when setting a property */setProperty(element,'boolean',true)/** Reactive lib shouldnt cause tracking when rendering */dispose=render(element)/** Reactive lib shouldnt cause tracking when removed */dispose()})
@titoBouzout Looks good. I'm not sure about set boolean, as making an infinitely-looping property is probably just not wanted no matter what the scenario is. Not sure we can guard against that particular case. But definitely the life cycle methods.
This test is namely for signals-based libraries. We need a test that shows that when a custom elements is rendered, none of its life cycle methods (
constructor
,connectedCallback
,adoptedCallback
,disconnectedCallback
, andattributeChangedCallback
) cause an infinite loop when reading the framework's reactive state.Here's an example (and a good sample test case we can write) in Solid.js where it will infinite-loop and eventually crash by simply reading a signal in a custom element life cycle method:
Besides this, we may want to include more libs, or lib combos, that use signals-and-effects patterns:
@lit-labs/preact-signals
ref()
API andsetup
modeThe text was updated successfully, but these errors were encountered: