1export const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); 2export const forever = () => new Promise(() => {}); 3 4export const animready = async () => { 5 for (let i = 0; i < 4; i++) await delay(0); 6}; 7 8//// RVAR //// 9//let current_func = null; 10const current_funcs = []; 11let rvar_list = []; 12 13export class Store { 14 15 constructor(value) { 16 this.value = value; 17 this.listeners = []; 18 19 // convenience function for setting this value from an onInput/onChange event: 20 this.bind = (e) => this.set(e.currentTarget.value); 21 } 22 23 untrack(func) { 24 this.listeners = this.listeners.filter(l => l !== func); 25 } 26 27 track() { 28 // I think it will only subscribe to the inner autorun. 29 // However, I think maybe this pattern should not be allowed. 30 // autorun(() => { 31 // autorun(() => { 32 // console.log(store.get()); 33 // }); 34 // }); 35 //if (typeof current_func === "function") { 36 if (current_funcs.length) { 37 //this.listeners.push(current_func); 38 this.listeners.push(current_funcs.at(-1)); 39 rvar_list.push(this); 40 } 41 } 42 43 /// return the wrapped value and subscribe to whichever autorun you're in 44 get() { 45 // NOTE - test the case where an autorun is within another autorun. How should this behave? 46 this.track(); 47 return this.value; 48 } 49 50 /// change wrapped data and trigger listeners 51 set(value) { 52 const oldval = this.value; 53 this.value = value; 54 this.trigger(); 55 return value; 56 } 57 58 /// trigger listeners without changing the data 59 trigger() { 60 for (const listener of this.listeners) { 61 if (current_funcs.includes(listener)) { 62 console.warn("Store debugging: reason = autorun listener is setting its own value"); 63 console.warn("Store debugging: previous value = " + oldval); 64 console.warn("Store debugging: previous value = " + this.value); 65 console.warn("Store debugging: listener = " + listener); 66 throw new Error("Infinite loop - setting an Store within its own listener will cause the listener to run forever and brick your computer. Use .value instead of .get(). See stack trace."); 67 } else { 68 listener(); 69 } 70 } 71 } 72 73 valueOf() { 74 return this.get(); 75 } 76 77 toString() { 78 return this.get(); 79 } 80} 81 82export function autorun(func) { 83 //const last_func = current_func; 84 // ^ no translation 85 const last_rvar_list = rvar_list; 86 87 //current_func = func; 88 current_funcs.push(func); 89 rvar_list = []; 90 func(); 91 92 const cancel = ((rvar_list) => () => { 93 for (const rvar of rvar_list) { 94 rvar.untrack(func); 95 } 96 })(rvar_list); 97 98 //current_func = last_func; 99 current_funcs.pop(); 100 rvar_list = last_rvar_list; 101 102 return cancel; 103} 104 105// note - preprocess html `` template literals 106// filter through all the variables and if any are instanceof Store, then sync them to that function. 107//// RVAR ////
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.