sprae 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/readme.md +2 -2
- package/sprae.js +17 -16
- package/sprae.min.js +1 -1
- package/src/core.js +3 -7
- package/src/state.js +13 -10
- package/test/dom.js +67 -11
- package/test/state.js +33 -12
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -254,11 +254,11 @@ Expose element to data scope with the `id`:
|
|
|
254
254
|
|
|
255
255
|
## Sandbox
|
|
256
256
|
|
|
257
|
-
Expressions are sandboxed, ie. have no access to global or window.
|
|
257
|
+
Expressions are sandboxed, ie. have no access to global or window (since sprae can be run in server environment).
|
|
258
258
|
|
|
259
259
|
Default sandbox provides: _Array_, _Object_, _Number_, _String_, _Boolean_, _Date_, _console_.
|
|
260
260
|
|
|
261
|
-
Sandbox can be extended via `Object.assign(sprae.
|
|
261
|
+
Sandbox can be extended via `Object.assign(sprae.globals, { BigInt, window, document })` etc.
|
|
262
262
|
|
|
263
263
|
## Examples
|
|
264
264
|
|
package/sprae.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/state.js
|
|
2
2
|
var currentFx;
|
|
3
|
-
var
|
|
3
|
+
var batch = /* @__PURE__ */ new Set();
|
|
4
|
+
var pendingUpdate;
|
|
4
5
|
var targetFxs = /* @__PURE__ */ new WeakMap();
|
|
5
6
|
var targetProxy = /* @__PURE__ */ new WeakMap();
|
|
6
7
|
var proxyTarget = /* @__PURE__ */ new WeakMap();
|
|
@@ -55,7 +56,8 @@ var handler = {
|
|
|
55
56
|
let propFxs = targetFxs.get(target)?.[prop];
|
|
56
57
|
if (propFxs)
|
|
57
58
|
for (let fx2 of propFxs)
|
|
58
|
-
|
|
59
|
+
batch.add(fx2);
|
|
60
|
+
planUpdate();
|
|
59
61
|
return true;
|
|
60
62
|
},
|
|
61
63
|
deleteProperty(target, prop) {
|
|
@@ -85,14 +87,16 @@ var fx = (fn) => {
|
|
|
85
87
|
call();
|
|
86
88
|
return call;
|
|
87
89
|
};
|
|
88
|
-
var
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
var planUpdate = () => {
|
|
91
|
+
if (!pendingUpdate) {
|
|
92
|
+
pendingUpdate = true;
|
|
93
|
+
queueMicrotask(() => {
|
|
94
|
+
for (let fx2 of batch)
|
|
95
|
+
fx2.call();
|
|
96
|
+
batch.clear();
|
|
97
|
+
pendingUpdate = false;
|
|
98
|
+
});
|
|
99
|
+
}
|
|
96
100
|
};
|
|
97
101
|
|
|
98
102
|
// src/domdiff.js
|
|
@@ -564,16 +568,13 @@ function dashcase(str) {
|
|
|
564
568
|
}
|
|
565
569
|
|
|
566
570
|
// src/core.js
|
|
567
|
-
sprae.
|
|
571
|
+
sprae.globals = sandbox;
|
|
568
572
|
var memo = /* @__PURE__ */ new WeakMap();
|
|
569
573
|
function sprae(container, values) {
|
|
570
574
|
if (!container.children)
|
|
571
575
|
return;
|
|
572
|
-
if (memo.has(container))
|
|
573
|
-
|
|
574
|
-
batch(() => Object.assign(state3, values));
|
|
575
|
-
return state3;
|
|
576
|
-
}
|
|
576
|
+
if (memo.has(container))
|
|
577
|
+
return Object.assign(memo.get(container), values);
|
|
577
578
|
const state2 = state(values || {});
|
|
578
579
|
const updates = [];
|
|
579
580
|
const init = (el, parent = el.parentNode) => {
|
package/sprae.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e,t,r=new
|
|
1
|
+
var e,t,r=new Set,n=new WeakMap,l=new WeakMap,s=new WeakMap,a=Symbol("parent"),i={Array:Array,Object:Object,Number:Number,String:String,Boolean:Boolean,Date:Date,console:console},o={has:()=>!0,get(t,r){if("symbol"==typeof r)return t[r];if(!(r in t))return t[a]?.[r];if(Array.isArray(t)&&r in Array.prototype)return t[r];let s=t[r];if(e){let l=n.get(t);l||n.set(t,l={}),l[r]?l[r].includes(e)||l[r].push(e):l[r]=[e]}if(s&&s.constructor===Object||Array.isArray(s)){let e=l.get(s);return e||l.set(s,e=new Proxy(s,o)),e}return s},set(e,t,l){if(!(t in e)&&e[a]&&t in e[a])return e[a][t]=l;if(Array.isArray(e)&&t in Array.prototype)return e[t]=l;const s=e[t];if(Object.is(s,l))return!0;e[t]=l;let i=n.get(e)?.[t];if(i)for(let e of i)r.add(e);return f(),!0},deleteProperty:(e,t)=>(e[t]=void 0,delete e[t],!0)},u=(e,t)=>{if(l.has(e))return l.get(e);if(s.has(e))return e;let r=new Proxy(e,o);return l.set(e,r),s.set(r,e),e[a]=t?u(t):i,r},c=t=>{const r=()=>{let n=e;e=r,t(),e=n};return r(),r},f=()=>{t||(t=!0,queueMicrotask((()=>{for(let e of r)e.call();r.clear(),t=!1})))},p=new WeakMap,y=class extends Map{#e=new FinalizationRegistry((e=>super.delete(e)));get size(){return[...this].length}constructor(e=[]){super();for(const[t,r]of e)this.set(t,r)}get(e){return super.get(e)?.deref()}set(e,t){let r=super.get(e);return r&&this.#e.unregister(r),r=(e=>p.get(e)||(e=>{const t=new WeakRef(e);return p.set(e,t),t})(e))(t),this.#e.register(t,e,r),super.set(e,r)}},h={},g={};h.if=(e,t)=>{let r=document.createTextNode(""),n=[N(e,t,":if")],l=[e],s=e;for(;(s=e.nextElementSibling)&&s.hasAttribute(":else");)s.removeAttribute(":else"),(t=s.getAttribute(":if"))?(s.removeAttribute(":if"),s.remove(),l.push(s),n.push(N(e,t,":else :if"))):(s.remove(),l.push(s),n.push((()=>1)));return e.replaceWith(s=r),e=>{let t=n.findIndex((t=>t(e)));l[t]!=s&&((s[d]||s).replaceWith(s=l[t]||r),M(s,e))}},h.with=(e,t,r)=>{const n=N(e,t,"with")(r);M(e,u(n,r))};var d=Symbol(":each");h.each=(e,t)=>{let r=function(e){let t=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,r=e.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!r)return;let n=r[2].trim(),l=r[1].replace(/^\s*\(|\)\s*$/g,"").trim(),s=l.match(t);return s?[l.replace(t,"").trim(),s[1].trim(),n]:[l,"",n]}(t);if(!r)return S(new Error,e,t);const n=e[d]=document.createTextNode("");e.replaceWith(n);const l=N(e,r[2],":each"),s=e.getAttribute(":key"),a=s?N(null,s):null;e.removeAttribute(":key");const i=e.getAttribute(":ref"),o=new y,c=new y;let f=[];return s=>{let p=l(s);p?"number"==typeof p?p=Array.from({length:p},((e,t)=>[t,t+1])):Array.isArray(p)?p=p.map(((e,t)=>[t+1,e])):"object"==typeof p?p=Object.entries(p):S(Error("Bad list value"),e,t,":each"):p=[];let y=[],h=[];for(let[t,n]of p){let l,f,p=a?.({[r[0]]:n,[r[1]]:t});null==p?l=e.cloneNode(!0):(l=c.get(p))||c.set(p,l=e.cloneNode(!0)),y.push(l),null!=p&&(f=o.get(p))?f[r[0]]=n:(f=u({[r[0]]:n,[i||""]:null,[r[1]]:t},s),null!=p&&o.set(p,f)),h.push(f)}!function(e,t,r,n){const l=new Map,s=new Map;let a,i;for(a=0;a<t.length;a++)l.set(t[a],a);for(a=0;a<r.length;a++)s.set(r[a],a);for(a=i=0;a!==t.length||i!==r.length;){var o=t[a],u=r[i];if(null===o)a++;else if(r.length<=i)e.removeChild(t[a]),a++;else if(t.length<=a)e.insertBefore(u,t[a]||n),i++;else if(o===u)a++,i++;else{var c=s.get(o),f=l.get(u);void 0===c?(e.removeChild(t[a]),a++):void 0===f?(e.insertBefore(u,t[a]||n),i++):(e.insertBefore(t[f],t[a]||n),t[f]=null,f>a+1&&a++,i++)}}}(n.parentNode,f,y,n),f=y;for(let e=0;e<y.length;e++)M(y[e],h[e])}},g.ref=(e,t,r)=>{r[t]=e},g.id=(e,t)=>{let r=N(e,t,":id");return t=>{return n=r(t),e.id=n||0===n?n:"";var n}},g.class=(e,t)=>{let r=N(e,t,":class"),n=e.className;return t=>{let l=r(t),s="string"==typeof l?l:(Array.isArray(l)?l:Object.entries(l).map((([e,t])=>t?e:""))).filter(Boolean).join(" ");e.className=[n,s].filter(Boolean).join(" ")}},g.style=(e,t)=>{let r=N(e,t,":style"),n=e.getAttribute("style")||"";return n.endsWith(";")||(n+="; "),t=>{let l=r(t);if("string"==typeof l)e.setAttribute("style",n+l);else{e.setAttribute("style",n);for(let t in l)e.style.setProperty(t,l[t])}}},g.text=(e,t)=>{let r=N(e,t,":text");return t=>{let n=r(t);e.textContent=null==n?"":n}},g.data=(e,t)=>{let r=N(e,t,":data");return t=>{let n=r(t);for(let t in n)e.dataset[t]=n[t]}},g.aria=(e,t)=>{let r=N(e,t,":aria");return t=>(t=>{for(let r in t)W(e,"aria-"+j(r),null==t[r]?null:t[r]+"")})(r(t))},g[""]=(e,t)=>{let r=N(e,t,":");if(r)return t=>{let n=r(t);for(let t in n)W(e,j(t),n[t])}},g.value=(e,t)=>{let r,n,l=N(e,t,":value"),s="text"===e.type||""===e.type?t=>e.setAttribute("value",e.value=null==t?"":t):"TEXTAREA"===e.tagName||"text"===e.type||""===e.type?t=>(r=e.selectionStart,n=e.selectionEnd,e.setAttribute("value",e.value=null==t?"":t),r&&e.setSelectionRange(r,n)):"checkbox"===e.type?t=>(e.value=t?"on":"",W(e,"checked",t)):"select-one"===e.type?t=>{for(let t in e.options)t.removeAttribute("selected");e.value=t,e.selectedOptions[0]?.setAttribute("selected","")}:t=>e.value=t;return e=>s(l(e))},g.on=(e,t)=>{let r=N(e,t,":on");return t=>{let n=r(t),l=[];for(let t in n)l.push(b(e,t,n[t]));return()=>{for(let e of l)e()}}};var m=(e,t,r,n)=>{let l=n.startsWith("on")&&n.slice(2),s=N(e,t,":"+n);if(s)return l?t=>{let r=s(t)||(()=>{});return b(e,l,r)}:t=>W(e,n,s(t))},b=(e,t,r)=>{if(!r)return;let n=t.split("..").map((t=>{let r={evt:"",target:e,test:()=>!0};return r.evt=(t.startsWith("on")?t.slice(2):t).replace(/\.(\w+)?-?([-\w]+)?/g,((e,t,n="")=>(r.test=v[t]?.(r,...n.split("-"))||r.test,""))),r}));if(1==n.length)return a(r,n[0]);const l=(t,r=0)=>{let s;return s=a((a=>{r&&s();let i=t.call(e,a);"function"!=typeof i&&(i=()=>{}),r+1<n.length&&l(i,r?r+1:1)}),n[r])};let s=l(r);return()=>s();function a(e,{evt:t,target:r,test:n,defer:l,stop:s,prevent:a,...i}){l&&(e=l(e));let o=t=>n(t)&&(s&&t.stopPropagation(),a&&t.preventDefault(),e.call(r,t));return r.addEventListener(t,o,i),()=>r.removeEventListener(t,o,i)}},v={prevent(e){e.prevent=!0},stop(e){e.stop=!0},once(e){e.once=!0},passive(e){e.passive=!0},capture(e){e.capture=!0},window(e){e.target=window},document(e){e.target=document},toggle(e){e.defer=(t,r)=>n=>r?(r.call?.(e.target,n),r=null):r=t()},throttle(e,t){e.defer=e=>k(e,t?Number(t)||0:108)},debounce(e,t){e.defer=e=>w(e,t?Number(t)||0:108)},outside:e=>t=>{let r=e.target;return!(r.contains(t.target)||!1===t.target.isConnected||r.offsetWidth<1&&r.offsetHeight<1)},self:e=>t=>t.target===e.target,ctrl:(e,...t)=>e=>A.ctrl(e)&&t.every((t=>A[t]?A[t](e):e.key===t)),shift:(e,...t)=>e=>A.shift(e)&&t.every((t=>A[t]?A[t](e):e.key===t)),alt:(e,...t)=>e=>A.alt(e)&&t.every((t=>A[t]?A[t](e):e.key===t)),meta:(e,...t)=>e=>A.meta(e)&&t.every((t=>A[t]?A[t](e):e.key===t)),arrow:e=>A.arrow,enter:e=>A.enter,escape:e=>A.escape,tab:e=>A.tab,space:e=>A.space,backspace:e=>A.backspace,delete:e=>A.delete,digit:e=>A.digit,letter:e=>A.letter,character:e=>A.character},A={ctrl:e=>e.ctrlKey||"Control"===e.key||"Ctrl"===e.key,shift:e=>e.shiftKey||"Shift"===e.key,alt:e=>e.altKey||"Alt"===e.key,meta:e=>e.metaKey||"Meta"===e.key||"Command"===e.key,arrow:e=>e.key.startsWith("Arrow"),enter:e=>"Enter"===e.key,escape:e=>e.key.startsWith("Esc"),tab:e=>"Tab"===e.key,space:e=>" "===e.key||"Space"===e.key||" "===e.key,backspace:e=>"Backspace"===e.key,delete:e=>"Delete"===e.key,digit:e=>/^\d$/.test(e.key),letter:e=>/^[a-zA-Z]$/.test(e.key),character:e=>/^\S$/.test(e.key)},k=(e,t)=>{let r,n,l=s=>{r=!0,setTimeout((()=>{if(r=!1,n)return n=!1,l(s),e(s)}),t)};return t=>r?n=!0:(l(t),e(t))},w=(e,t)=>{let r;return n=>{clearTimeout(r),r=setTimeout((()=>{r=null,e(n)}),t)}},W=(e,t,r)=>{null==r||!1===r?e.removeAttribute(t):e.setAttribute(t,!0===r?"":"number"==typeof r||"string"==typeof r?r:"")},x={};function N(e,t,r){let n=x[t];if(!n){let l=/^[\n\s]*if.*\(.*\)/.test(t)||/\b(let|const)\s/.test(t)&&!r.startsWith(":on")?`(() => {${t}})()`:t;try{n=x[t]=new Function("__scope",`with (__scope) { return ${l.trim()} };`)}catch(n){return S(n,e,t,r)}}return l=>{let s;try{s=n.call(e,l)}catch(n){return S(n,e,t,r)}return s}}function S(e,t,r,n){Object.assign(e,{element:t,expression:r}),console.warn(`∴ ${e.message}\n\n${n}=${r?`"${r}"\n\n`:""}`,t),queueMicrotask((()=>{throw e}),0)}function j(e){return e.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase()))}M.globals=i;var E=new WeakMap;function M(e,t){if(!e.children)return;if(E.has(e))return Object.assign(E.get(e),t);const r=u(t||{}),n=[],l=(e,t=e.parentNode)=>{for(let l in h){let s=":"+l;if(e.hasAttribute?.(s)){let a=e.getAttribute(s);if(e.removeAttribute(s),n.push(h[l](e,a,r,l)),E.has(e)||e.parentNode!==t)return!1}}if(e.attributes)for(let l=0;l<e.attributes.length;){let s=e.attributes[l];if(":"!==s.name[0]){l++;continue}e.removeAttribute(s.name);let a=s.value,i=s.name.slice(1).split(":");for(let l of i){let s=g[l]||m;if(n.push(s(e,a,r,l)),E.has(e)||e.parentNode!==t)return!1}}for(let t,r=0;t=e.children[r];r++)!1===l(t,e)&&r--};l(e);for(let e of n)if(e){let t;c((()=>{"function"==typeof t&&t(),t=e(r)}))}return E.set(e,r),r}var $=M;export{$ as default};
|
package/src/core.js
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
|
-
import { state as createState, fx,
|
|
1
|
+
import { state as createState, fx, sandbox } from './state.js';
|
|
2
2
|
import defaultDirective, { primary, secondary } from './directives.js';
|
|
3
3
|
|
|
4
|
-
sprae.
|
|
4
|
+
sprae.globals=sandbox
|
|
5
5
|
|
|
6
6
|
// sprae element: apply directives
|
|
7
7
|
const memo = new WeakMap
|
|
8
8
|
export default function sprae(container, values) {
|
|
9
9
|
if (!container.children) return
|
|
10
|
-
if (memo.has(container))
|
|
11
|
-
let state = memo.get(container)
|
|
12
|
-
batch(() => Object.assign(state, values))
|
|
13
|
-
return state
|
|
14
|
-
}
|
|
10
|
+
if (memo.has(container)) return Object.assign( memo.get(container), values)
|
|
15
11
|
|
|
16
12
|
// subscribe to reactives
|
|
17
13
|
// for (let prop in values) {
|
package/src/state.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// currentFx stack of listeners
|
|
2
|
-
let currentFx,
|
|
2
|
+
let currentFx, batch = new Set, pendingUpdate
|
|
3
3
|
|
|
4
4
|
const targetFxs = new WeakMap
|
|
5
5
|
const targetProxy = new WeakMap
|
|
@@ -60,7 +60,8 @@ const handler = {
|
|
|
60
60
|
// whenever target prop is set, call all dependent fxs
|
|
61
61
|
let propFxs = targetFxs.get(target)?.[prop]
|
|
62
62
|
|
|
63
|
-
if (propFxs) for (let fx of propFxs)
|
|
63
|
+
if (propFxs) for (let fx of propFxs) batch.add(fx)
|
|
64
|
+
planUpdate()
|
|
64
65
|
|
|
65
66
|
// FIXME: unsubscribe / delete effects by setting null/undefined
|
|
66
67
|
// if (value == null) targetFxs.delete(prev)
|
|
@@ -103,11 +104,13 @@ export const fx = (fn) => {
|
|
|
103
104
|
return call
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
export const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
107
|
+
export const planUpdate = () => {
|
|
108
|
+
if (!pendingUpdate) {
|
|
109
|
+
pendingUpdate = true
|
|
110
|
+
queueMicrotask(() => {
|
|
111
|
+
for (let fx of batch) fx.call()
|
|
112
|
+
batch.clear()
|
|
113
|
+
pendingUpdate = false
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
}
|
package/test/dom.js
CHANGED
|
@@ -25,6 +25,7 @@ test('hidden: core', async () => {
|
|
|
25
25
|
let params = sprae(el, {hidden:true})
|
|
26
26
|
is(el.outerHTML, `<div hidden=""></div>`)
|
|
27
27
|
params.hidden = false
|
|
28
|
+
await tick()
|
|
28
29
|
is(el.outerHTML, `<div></div>`)
|
|
29
30
|
})
|
|
30
31
|
|
|
@@ -42,6 +43,7 @@ test('common: reactive', async () => {
|
|
|
42
43
|
let params = sprae(el, {name:'text', url:'//google.com'})
|
|
43
44
|
is(el.outerHTML, `<label for="text">text</label><input id="text" name="text" type="text"><a href="//google.com"></a><img src="//google.com">`)
|
|
44
45
|
params.name = 'email'
|
|
46
|
+
await tick()
|
|
45
47
|
is(el.outerHTML, `<label for="email">email</label><input id="email" name="email" type="email"><a href="//google.com"></a><img src="//google.com">`)
|
|
46
48
|
})
|
|
47
49
|
|
|
@@ -76,17 +78,22 @@ test('style', async () => {
|
|
|
76
78
|
let el = h`<x style="left: 1px" :style="style"></x>`
|
|
77
79
|
let params = sprae(el, {style: "top: 1px"})
|
|
78
80
|
is(el.outerHTML, `<x style="left: 1px; top: 1px"></x>`)
|
|
81
|
+
|
|
79
82
|
params.style = {top: '2px'}
|
|
83
|
+
await tick()
|
|
80
84
|
is(el.outerHTML, `<x style="left: 1px; top: 2px;"></x>`)
|
|
81
85
|
|
|
82
86
|
params.style = {'--x': 123}
|
|
87
|
+
await tick()
|
|
83
88
|
is(el.style.getPropertyValue('--x'), '123')
|
|
84
89
|
|
|
85
90
|
params.style = {top:'1px', bottom:'2px'}
|
|
91
|
+
await tick()
|
|
86
92
|
is(el.outerHTML, `<x style="left: 1px; top: 1px; bottom: 2px;"></x>`)
|
|
87
93
|
|
|
88
94
|
params.style = {top:'2px', bottom: null}
|
|
89
95
|
// FIXME
|
|
96
|
+
await tick()
|
|
90
97
|
is(el.outerHTML, `<x style="left: 1px; top: 2px;"></x>`)
|
|
91
98
|
})
|
|
92
99
|
|
|
@@ -96,6 +103,7 @@ test('class', async () => {
|
|
|
96
103
|
let params = sprae(el, {a:'x', b:'y', c, d:false});
|
|
97
104
|
is(el.outerHTML, `<x class="base x"></x><y class="y z"></y><z class="b"></z>`);
|
|
98
105
|
params.d = true;
|
|
106
|
+
await tick()
|
|
99
107
|
is(el.outerHTML, `<x class="base x"></x><y class="y z"></y><z class="b c"></z>`);
|
|
100
108
|
// c.value = 'w'
|
|
101
109
|
// is(el.outerHTML, `<x class="base x"></x><y class="y w"></y><z class="b c"></z>`);
|
|
@@ -126,6 +134,7 @@ test('props: calculation', async () => {
|
|
|
126
134
|
let state = sprae(el, {x:3});
|
|
127
135
|
is(el.outerHTML, `<x x="012"></x>`)
|
|
128
136
|
state.x = 4
|
|
137
|
+
await tick()
|
|
129
138
|
is(el.outerHTML, `<x x="0123"></x>`)
|
|
130
139
|
})
|
|
131
140
|
|
|
@@ -156,6 +165,7 @@ test('value: direct', async () => {
|
|
|
156
165
|
is(el.value, '1')
|
|
157
166
|
is(el.outerHTML, `<input value="1">`)
|
|
158
167
|
state.a = 2
|
|
168
|
+
await tick()
|
|
159
169
|
is(el.value, '2')
|
|
160
170
|
is(el.outerHTML, `<input value="2">`)
|
|
161
171
|
|
|
@@ -182,6 +192,7 @@ test('text: core', async () => {
|
|
|
182
192
|
let params = sprae(el, {text:'abc'})
|
|
183
193
|
is(el.outerHTML, `<div>abc</div>`)
|
|
184
194
|
params.text = null
|
|
195
|
+
await tick()
|
|
185
196
|
is(el.outerHTML, `<div></div>`)
|
|
186
197
|
})
|
|
187
198
|
|
|
@@ -196,10 +207,13 @@ test('if: base', async () => {
|
|
|
196
207
|
|
|
197
208
|
is(el.innerHTML, '<span>a</span>')
|
|
198
209
|
params.a = 2
|
|
210
|
+
await tick()
|
|
199
211
|
is(el.innerHTML, '<span>b</span>')
|
|
200
212
|
params.a = 3
|
|
213
|
+
await tick()
|
|
201
214
|
is(el.innerHTML, '<span>c</span>')
|
|
202
215
|
params.a = null
|
|
216
|
+
await tick()
|
|
203
217
|
is(el.innerHTML, '<span>c</span>')
|
|
204
218
|
})
|
|
205
219
|
|
|
@@ -214,15 +228,20 @@ test('if: short with insertions', async () => {
|
|
|
214
228
|
|
|
215
229
|
is(el.innerHTML, '<span>1:1</span>')
|
|
216
230
|
params.a = 2
|
|
231
|
+
await tick()
|
|
217
232
|
is(el.innerHTML, '<span>2:2</span>')
|
|
218
233
|
params.a = 3
|
|
234
|
+
await tick()
|
|
219
235
|
is(el.innerHTML, '<span>3</span>')
|
|
220
236
|
params.a = 4
|
|
237
|
+
await tick()
|
|
221
238
|
is(el.innerHTML, '<span>4</span>')
|
|
222
239
|
|
|
223
240
|
params.a = 1
|
|
241
|
+
await tick()
|
|
224
242
|
is(el.innerHTML, '<span>1:1</span>')
|
|
225
243
|
params.a = 4
|
|
244
|
+
await tick()
|
|
226
245
|
is(el.innerHTML, '<span>4</span>')
|
|
227
246
|
|
|
228
247
|
params.a = null
|
|
@@ -258,11 +277,12 @@ test('if: (#3) subsequent content is not abandoned', async () => {
|
|
|
258
277
|
is(x.outerHTML, `<x><z>123</z></x>`)
|
|
259
278
|
})
|
|
260
279
|
|
|
261
|
-
test('if: + :with doesnt prevent secondary effects from happening', () => {
|
|
280
|
+
test('if: + :with doesnt prevent secondary effects from happening', async () => {
|
|
262
281
|
let el = h`<div><x :if="x" :with="{}" :text="x"></x></div>`
|
|
263
282
|
let state = sprae(el, {x:''})
|
|
264
283
|
is(el.innerHTML, ``)
|
|
265
284
|
state.x = '123'
|
|
285
|
+
await tick()
|
|
266
286
|
is(el.innerHTML, `<x>123</x>`)
|
|
267
287
|
|
|
268
288
|
// NOTE: we ignore this case
|
|
@@ -284,10 +304,13 @@ test('each: array', async () => {
|
|
|
284
304
|
is(el.innerHTML, '')
|
|
285
305
|
console.log('set 1,2')
|
|
286
306
|
params.b = [1,2]
|
|
307
|
+
await tick()
|
|
287
308
|
is(el.innerHTML, '<span>1</span><span>2</span>')
|
|
288
309
|
params.b = []
|
|
310
|
+
await tick()
|
|
289
311
|
is(el.innerHTML, '')
|
|
290
312
|
params.b = null
|
|
313
|
+
await tick()
|
|
291
314
|
is(el.innerHTML, '')
|
|
292
315
|
})
|
|
293
316
|
|
|
@@ -302,10 +325,13 @@ test('each: object', async () => {
|
|
|
302
325
|
is(el.innerHTML, '')
|
|
303
326
|
console.log('set 1,2')
|
|
304
327
|
params.b = { x:1, y:2 }
|
|
328
|
+
await tick()
|
|
305
329
|
is(el.innerHTML, '<span>x,1</span><span>y,2</span>')
|
|
306
330
|
params.b = []
|
|
331
|
+
await tick()
|
|
307
332
|
is(el.innerHTML, '')
|
|
308
333
|
params.b = null
|
|
334
|
+
await tick()
|
|
309
335
|
is(el.innerHTML, '')
|
|
310
336
|
})
|
|
311
337
|
|
|
@@ -318,12 +344,15 @@ test('each: loop within loop', async () => {
|
|
|
318
344
|
|
|
319
345
|
is(el.innerHTML, '<x><y>1</y><y>2</y></x><x><y>3</y><y>4</y></x>')
|
|
320
346
|
params.c = [[5,6], [3,4]]
|
|
347
|
+
await tick()
|
|
321
348
|
is(el.innerHTML, '<x><y>5</y><y>6</y></x><x><y>3</y><y>4</y></x>')
|
|
322
349
|
// params.c[1] = [7,8]
|
|
323
350
|
params.c = [params.c[0], [7,8]]
|
|
351
|
+
await tick()
|
|
324
352
|
is(el.innerHTML, '<x><y>5</y><y>6</y></x><x><y>7</y><y>8</y></x>')
|
|
325
353
|
// is(el.innerHTML, '<span>1</span><span>2</span>')
|
|
326
354
|
params.c = []
|
|
355
|
+
await tick()
|
|
327
356
|
is(el.innerHTML, '')
|
|
328
357
|
// params.b = null
|
|
329
358
|
// is(el.innerHTML, '')
|
|
@@ -358,10 +387,13 @@ test('each: loop with condition', async () => {
|
|
|
358
387
|
|
|
359
388
|
is(el.innerHTML, '')
|
|
360
389
|
params.c = true
|
|
390
|
+
await tick()
|
|
361
391
|
is(el.innerHTML, '<span>1</span><span>2</span>')
|
|
362
392
|
params.b = [1]
|
|
393
|
+
await tick()
|
|
363
394
|
is(el.innerHTML, '<span>1</span>')
|
|
364
395
|
params.b = null
|
|
396
|
+
await tick()
|
|
365
397
|
is(el.innerHTML, '')
|
|
366
398
|
})
|
|
367
399
|
|
|
@@ -375,13 +407,17 @@ test('each: condition with loop', async () => {
|
|
|
375
407
|
|
|
376
408
|
is(el.innerHTML, '<span>false</span>')
|
|
377
409
|
params.c = true
|
|
410
|
+
await tick()
|
|
378
411
|
is(el.innerHTML, '<span>1</span><span>2</span>')
|
|
379
412
|
params.b = [1]
|
|
413
|
+
await tick()
|
|
380
414
|
is(el.innerHTML, '<span>1</span>')
|
|
381
415
|
params.b = null
|
|
416
|
+
await tick()
|
|
382
417
|
is(el.innerHTML, '')
|
|
383
418
|
console.log('c=false')
|
|
384
419
|
params.c = false
|
|
420
|
+
await tick()
|
|
385
421
|
is(el.innerHTML, '<span>false</span>')
|
|
386
422
|
})
|
|
387
423
|
|
|
@@ -395,8 +431,10 @@ test('each: loop within condition', async () => {
|
|
|
395
431
|
|
|
396
432
|
is(el.innerHTML, '<x><y>1</y></x>')
|
|
397
433
|
params.a = 2
|
|
434
|
+
await tick()
|
|
398
435
|
is(el.innerHTML, '<x><y>-1</y><y>-2</y></x>')
|
|
399
436
|
params.a = 0
|
|
437
|
+
await tick()
|
|
400
438
|
is(el.innerHTML, '')
|
|
401
439
|
})
|
|
402
440
|
|
|
@@ -413,8 +451,10 @@ test('each: condition within loop', async () => {
|
|
|
413
451
|
|
|
414
452
|
is(el.innerHTML, '<x><y>1:1</y></x><x><y>2:2</y></x><x><y>3</y></x>')
|
|
415
453
|
params.b = [2]
|
|
454
|
+
await tick()
|
|
416
455
|
is(el.innerHTML, '<x><y>2:2</y></x>')
|
|
417
456
|
params.b = null
|
|
457
|
+
await tick()
|
|
418
458
|
is(el.innerHTML, '')
|
|
419
459
|
})
|
|
420
460
|
|
|
@@ -433,9 +473,11 @@ test('each: unkeyed', async () => {
|
|
|
433
473
|
is(el.textContent, '123')
|
|
434
474
|
// let first = el.firstChild
|
|
435
475
|
state.xs = [1,3,2]
|
|
476
|
+
await tick()
|
|
436
477
|
// is(el.firstChild, first)
|
|
437
478
|
is(el.textContent, '132')
|
|
438
479
|
state.xs = [3,3,3]
|
|
480
|
+
await tick()
|
|
439
481
|
is(el.textContent, '333')
|
|
440
482
|
// is(el.firstChild, first)
|
|
441
483
|
})
|
|
@@ -448,9 +490,11 @@ test('each: keyed', async () => {
|
|
|
448
490
|
is(el.textContent, '123')
|
|
449
491
|
let first = el.firstChild
|
|
450
492
|
state.xs = [1,3,2]
|
|
493
|
+
await tick()
|
|
451
494
|
is(el.firstChild, first)
|
|
452
495
|
is(el.textContent, '132')
|
|
453
496
|
state.xs = [3,3,3]
|
|
497
|
+
await tick()
|
|
454
498
|
is(el.textContent, '3')
|
|
455
499
|
// is(el.firstChild, first)
|
|
456
500
|
})
|
|
@@ -465,18 +509,21 @@ test('each: unmounted elements remove listeners', async () => {
|
|
|
465
509
|
// let's hope they get removed without memory leaks :')
|
|
466
510
|
})
|
|
467
511
|
|
|
468
|
-
test('each: internal children get updated by state update, also: update by running again', () => {
|
|
512
|
+
test('each: internal children get updated by state update, also: update by running again', async () => {
|
|
469
513
|
let el = h`<><x :each="item, idx in items" :text="item" :key="idx"></x></>`
|
|
470
514
|
let state = sprae(el, { items: [1,2,3] })
|
|
471
515
|
is(el.textContent, '123')
|
|
472
516
|
state.items = [2, 2, 3]
|
|
517
|
+
await tick()
|
|
473
518
|
is(el.textContent, '223')
|
|
474
519
|
state = sprae(el, { items: [0,2,3] })
|
|
520
|
+
await tick()
|
|
475
521
|
is(el.textContent, '023')
|
|
476
522
|
// NOTE: this doesn't update items, since they're new array
|
|
477
523
|
console.log('set items')
|
|
478
524
|
state.items[0] = 1
|
|
479
|
-
state.items = [...state.items]
|
|
525
|
+
// state.items = [...state.items]
|
|
526
|
+
await tick()
|
|
480
527
|
is(el.textContent, '123')
|
|
481
528
|
})
|
|
482
529
|
|
|
@@ -499,7 +546,7 @@ test('each: key-based caching is in-sync with direct elements', () => {
|
|
|
499
546
|
is(el.outerHTML, el2.outerHTML)
|
|
500
547
|
})
|
|
501
548
|
|
|
502
|
-
test('on: base', () => {
|
|
549
|
+
test('on: base', async () => {
|
|
503
550
|
let el = h`<div :on="{click(e){log.push('click')}, x}"></div>`
|
|
504
551
|
let log = []
|
|
505
552
|
let params = sprae(el, {x(){log.push('x')}, log})
|
|
@@ -511,11 +558,13 @@ test('on: base', () => {
|
|
|
511
558
|
is(log, ['click','x'])
|
|
512
559
|
|
|
513
560
|
params.x = function(){log.push('xx')}
|
|
561
|
+
await tick()
|
|
514
562
|
el.dispatchEvent(new window.Event('x'));
|
|
515
563
|
is(log, ['click','x','xx']);
|
|
516
564
|
|
|
517
565
|
console.log('make null')
|
|
518
566
|
params.x = null;
|
|
567
|
+
await tick()
|
|
519
568
|
el.dispatchEvent(new window.Event('x'));
|
|
520
569
|
is(log, ['click','x','xx']);
|
|
521
570
|
})
|
|
@@ -632,7 +681,7 @@ test('on: parallel chains', e => {
|
|
|
632
681
|
is(state.log, ['x','x','y','y','z','z','x']);
|
|
633
682
|
})
|
|
634
683
|
|
|
635
|
-
test('on: state changes between chain of events', e => {
|
|
684
|
+
test('on: state changes between chain of events', async e => {
|
|
636
685
|
let el = h`<x :on="{'x..y':fn}"></x>`
|
|
637
686
|
let log = []
|
|
638
687
|
let state = sprae(el, {log, fn: () => (log.push('x1'), ()=>log.push('y1'))})
|
|
@@ -641,6 +690,7 @@ test('on: state changes between chain of events', e => {
|
|
|
641
690
|
is(log, ['x1'])
|
|
642
691
|
console.log('update fn')
|
|
643
692
|
state.fn = () => (log.push('x2'), () => log.push('y2'))
|
|
693
|
+
await tick()
|
|
644
694
|
is(log, ['x1'])
|
|
645
695
|
// console.log('xx')
|
|
646
696
|
// NOTE: state update registers new chain listener before finishing prev chain
|
|
@@ -808,12 +858,13 @@ test('on: modifiers chain', async e => {
|
|
|
808
858
|
is(state.log,['x', 'x'])
|
|
809
859
|
})
|
|
810
860
|
|
|
811
|
-
test('with: inline', () => {
|
|
861
|
+
test('with: inline', async () => {
|
|
812
862
|
let el = h`<x :with="{foo:'bar'}"><y :text="foo + baz"></y></x>`
|
|
813
863
|
let state = sprae(el, {baz: 'qux'})
|
|
814
864
|
// FIXME: this doesn't inherit root scope baz property and instead uses hard-initialized one
|
|
815
865
|
is(el.innerHTML, `<y>barqux</y>`)
|
|
816
866
|
state.baz = 'quux'
|
|
867
|
+
await tick()
|
|
817
868
|
is(el.innerHTML, `<y>barquux</y>`)
|
|
818
869
|
})
|
|
819
870
|
test.skip('with: inline reactive', () => {
|
|
@@ -825,22 +876,24 @@ test.skip('with: inline reactive', () => {
|
|
|
825
876
|
baz.value = 'quux'
|
|
826
877
|
is(el.innerHTML, `<y>barquux</y>`)
|
|
827
878
|
})
|
|
828
|
-
test('with: data', () => {
|
|
879
|
+
test('with: data', async () => {
|
|
829
880
|
let el = h`<x :with="x"><y :text="foo"></y></x>`
|
|
830
881
|
let state = sprae(el, {x: {foo:'bar'}})
|
|
831
882
|
is(el.innerHTML, `<y>bar</y>`)
|
|
832
883
|
console.log('update', state.x)
|
|
833
884
|
state.x.foo = 'baz'
|
|
885
|
+
await tick()
|
|
834
886
|
// Object.assign(state, {x:{foo:'baz'}})
|
|
835
887
|
is(el.innerHTML, `<y>baz</y>`)
|
|
836
888
|
})
|
|
837
|
-
test('with: transparency', () => {
|
|
889
|
+
test('with: transparency', async () => {
|
|
838
890
|
// NOTE: y:text initializes through directive, not through parent
|
|
839
891
|
// therefore by default :text uses parent's state, not defined by element itself
|
|
840
892
|
let el = h`<x :with="{foo:'foo'}"><y :with="b" :text="foo+bar"></y></x>`
|
|
841
893
|
let params = sprae(el, {b:{bar:'bar'}})
|
|
842
894
|
is(el.innerHTML, `<y>foobar</y>`)
|
|
843
895
|
params.b.bar = 'baz'
|
|
896
|
+
await tick()
|
|
844
897
|
is(el.innerHTML, `<y>foobaz</y>`)
|
|
845
898
|
})
|
|
846
899
|
test.skip('with: reactive transparency', () => {
|
|
@@ -851,22 +904,25 @@ test.skip('with: reactive transparency', () => {
|
|
|
851
904
|
bar.value = '3'
|
|
852
905
|
is(el.innerHTML, `<y>13</y>`)
|
|
853
906
|
})
|
|
854
|
-
test('with: writes to state', () => {
|
|
907
|
+
test('with: writes to state', async () => {
|
|
855
908
|
let a = h`<x :with="{a:1}"><y :on="{x(){a++}}" :text="a"></y></x>`
|
|
856
909
|
sprae(a)
|
|
857
910
|
is(a.innerHTML, `<y>1</y>`)
|
|
858
911
|
a.firstChild.dispatchEvent(new window.Event('x'))
|
|
912
|
+
await tick()
|
|
859
913
|
is(a.innerHTML, `<y>2</y>`)
|
|
860
914
|
a.firstChild.dispatchEvent(new window.Event('x'))
|
|
915
|
+
await tick()
|
|
861
916
|
is(a.innerHTML, `<y>3</y>`)
|
|
862
917
|
})
|
|
863
918
|
|
|
864
|
-
test('ref: base', () => {
|
|
919
|
+
test('ref: base', async () => {
|
|
865
920
|
let a = h`<a :ref="a" :init="log.push(a), null" :text="b"></a>`
|
|
866
921
|
let state = sprae(a, {log:[], b:1})
|
|
867
922
|
is(state.log[0], a)
|
|
868
923
|
is(a.outerHTML, `<a>1</a>`)
|
|
869
924
|
state.b = 2
|
|
925
|
+
await tick()
|
|
870
926
|
is(a.outerHTML, `<a>2</a>`)
|
|
871
927
|
is(state.a, a, 'Exposes to the state');
|
|
872
928
|
})
|
|
@@ -929,7 +985,7 @@ test('sandbox', async () => {
|
|
|
929
985
|
is(log, ['undefined', 'object', 'undefined', 'undefined'])
|
|
930
986
|
|
|
931
987
|
log.splice(0)
|
|
932
|
-
Object.assign(sprae.
|
|
988
|
+
Object.assign(sprae.globals, { window })
|
|
933
989
|
sprae(el.cloneNode(), {log})
|
|
934
990
|
is(log, ['object', 'object', 'undefined', 'undefined'])
|
|
935
991
|
})
|
package/test/state.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {state, fx
|
|
1
|
+
import {state, fx} from '../src/state.js'
|
|
2
2
|
import t, {is, ok} from 'tst'
|
|
3
3
|
import signalStruct from 'signal-struct'
|
|
4
4
|
import { effect } from '@preact/signals-core'
|
|
5
|
+
import {tick} from 'wait-please'
|
|
5
6
|
|
|
6
|
-
t('state: basic', t => {
|
|
7
|
+
t('state: basic', async t => {
|
|
7
8
|
let s = state({x:0, y:1})
|
|
8
9
|
|
|
9
10
|
let xy; fx(() => xy = s.x + s.y)
|
|
@@ -12,12 +13,14 @@ t('state: basic', t => {
|
|
|
12
13
|
s.x = 2
|
|
13
14
|
console.log('set 3')
|
|
14
15
|
s.y = 3
|
|
16
|
+
await tick()
|
|
15
17
|
is(xy, 5, 'Eq')
|
|
16
18
|
s.y = 4
|
|
19
|
+
await tick()
|
|
17
20
|
is(xy, 6, 'Eq')
|
|
18
21
|
})
|
|
19
22
|
|
|
20
|
-
t('state: signal-struct basics', t => {
|
|
23
|
+
t('state: signal-struct basics', async t => {
|
|
21
24
|
let s = state({
|
|
22
25
|
x: 0,
|
|
23
26
|
y: 1,
|
|
@@ -39,8 +42,10 @@ t('state: signal-struct basics', t => {
|
|
|
39
42
|
is(xy, 1)
|
|
40
43
|
s.x = 2
|
|
41
44
|
s.y = 3
|
|
45
|
+
await tick()
|
|
42
46
|
is(xy, 5)
|
|
43
47
|
s.y = 4
|
|
48
|
+
await tick()
|
|
44
49
|
is(xy, 6)
|
|
45
50
|
|
|
46
51
|
// getters are computed
|
|
@@ -51,7 +56,7 @@ t('state: signal-struct basics', t => {
|
|
|
51
56
|
is(s.xy, 6)
|
|
52
57
|
})
|
|
53
58
|
|
|
54
|
-
t('state: deep props', () => {
|
|
59
|
+
t('state: deep props', async () => {
|
|
55
60
|
let s = state({
|
|
56
61
|
z: { r: 2, i: 3 }
|
|
57
62
|
})
|
|
@@ -60,17 +65,20 @@ t('state: deep props', () => {
|
|
|
60
65
|
let len; fx(() => (len = (s.z.r**2 + s.z.i**2)**0.5))
|
|
61
66
|
s.z.r = 3
|
|
62
67
|
s.z.i = 4
|
|
68
|
+
await tick()
|
|
63
69
|
is(len, 5)
|
|
64
70
|
s.z.r = 4
|
|
65
71
|
s.z.i = 3
|
|
72
|
+
await tick()
|
|
66
73
|
is(len, 5)
|
|
67
74
|
|
|
68
75
|
// updating internal objects/arrays turns them into signals too
|
|
69
76
|
s.z = { r: 5, i: 12}
|
|
77
|
+
await tick()
|
|
70
78
|
is(len, 13)
|
|
71
79
|
})
|
|
72
80
|
|
|
73
|
-
t('state: array', () => {
|
|
81
|
+
t('state: array', async () => {
|
|
74
82
|
let s = state({
|
|
75
83
|
w: [1,2]
|
|
76
84
|
})
|
|
@@ -79,23 +87,27 @@ t('state: array', () => {
|
|
|
79
87
|
let mult; fx(() => mult = s.w?.[0] * s.w?.[1] || 0)
|
|
80
88
|
is(mult, 2)
|
|
81
89
|
s.w = [3,4]
|
|
90
|
+
await tick()
|
|
82
91
|
is(mult,12)
|
|
83
92
|
|
|
84
93
|
// nullifying is fine
|
|
85
94
|
s.w = null
|
|
95
|
+
await tick()
|
|
86
96
|
is(mult, 0)
|
|
87
97
|
|
|
88
98
|
// delete is fine
|
|
89
99
|
delete s.w
|
|
90
100
|
|
|
101
|
+
await tick()
|
|
91
102
|
is(mult, 0)
|
|
92
103
|
|
|
93
104
|
console.log('set w')
|
|
94
105
|
s.w = [1,2]
|
|
106
|
+
await tick()
|
|
95
107
|
is(mult, 2)
|
|
96
108
|
})
|
|
97
109
|
|
|
98
|
-
t('state: bulk-update', () => {
|
|
110
|
+
t('state: bulk-update', async () => {
|
|
99
111
|
let s = state({
|
|
100
112
|
x: 0,
|
|
101
113
|
y: 1,
|
|
@@ -114,6 +126,7 @@ t('state: bulk-update', () => {
|
|
|
114
126
|
// let [signals, update] = s
|
|
115
127
|
// update({ x: 1, y: 1, z: { r: 3, i: 4 } })
|
|
116
128
|
Object.assign(s, { x: 1, y: 1, z: { r: 3, i: 4 } })
|
|
129
|
+
await tick()
|
|
117
130
|
is(xy, 2)
|
|
118
131
|
is(len, 5, 'len after update')
|
|
119
132
|
})
|
|
@@ -178,31 +191,37 @@ t('state: inheritance', () => {
|
|
|
178
191
|
// })
|
|
179
192
|
})
|
|
180
193
|
|
|
181
|
-
t('state: inheritance: updating values in chain', () => {
|
|
194
|
+
t('state: inheritance: updating values in chain', async () => {
|
|
182
195
|
let s1 = {x:1}
|
|
183
196
|
let s = state(s1, {y:2})
|
|
184
|
-
console.group('fx')
|
|
197
|
+
// console.group('fx')
|
|
185
198
|
let xy = 0; fx(() => xy = s.x + s.y);
|
|
186
|
-
console.groupEnd('fx')
|
|
199
|
+
// console.groupEnd('fx')
|
|
200
|
+
await tick()
|
|
187
201
|
is(xy, 3)
|
|
188
202
|
s.x++
|
|
203
|
+
await tick()
|
|
189
204
|
is(xy, 4)
|
|
190
205
|
console.log('y++')
|
|
191
206
|
s.y++
|
|
207
|
+
await tick()
|
|
192
208
|
is(xy, 5)
|
|
193
209
|
})
|
|
194
210
|
|
|
195
|
-
t('state: array items', () => {
|
|
211
|
+
t('state: array items', async () => {
|
|
196
212
|
// arrays get each item converted to signal struct
|
|
197
213
|
let s5 = state({list: [{x:1}, {x:2}]})
|
|
198
214
|
let sum; fx(()=> sum = s5.list.reduce((sum, item)=>item.x + sum, 0))
|
|
199
215
|
is(sum, 3)
|
|
200
216
|
s5.list[0].x = 2
|
|
217
|
+
await tick()
|
|
201
218
|
is(sum, 4)
|
|
202
219
|
console.log('set array value')
|
|
203
220
|
s5.list = [{x:3}, {x:3}]
|
|
221
|
+
await tick()
|
|
204
222
|
is(sum, 6)
|
|
205
223
|
s5.list = [{x:3}, {x:3}, {x:4}]
|
|
224
|
+
await tick()
|
|
206
225
|
is(sum, 10)
|
|
207
226
|
})
|
|
208
227
|
|
|
@@ -214,14 +233,16 @@ t('state: arrays retain reference', () => {
|
|
|
214
233
|
is(list,[1,4,3])
|
|
215
234
|
})
|
|
216
235
|
|
|
217
|
-
t('state: direct list', () => {
|
|
236
|
+
t('state: direct list', async () => {
|
|
218
237
|
// works with arrays as well
|
|
219
238
|
let list = state([{x:1}, {x:2}])
|
|
220
239
|
let sum; fx(()=> sum = list.reduce((sum, item)=>item.x + sum, 0))
|
|
221
240
|
is(sum, 3)
|
|
222
241
|
list[0].x = 2
|
|
242
|
+
await tick()
|
|
223
243
|
is(sum, 4)
|
|
224
244
|
list.splice(0, 2, {x:3}, {x:3})
|
|
245
|
+
await tick()
|
|
225
246
|
console.log(list)
|
|
226
247
|
is(sum, 6)
|
|
227
248
|
})
|
|
@@ -240,7 +261,7 @@ t('state: circular?', () => {
|
|
|
240
261
|
is (a, [1, 2])
|
|
241
262
|
})
|
|
242
263
|
|
|
243
|
-
t('state: batch', () => {
|
|
264
|
+
t.skip('state: batch', () => {
|
|
244
265
|
let s = state({x:1, y:2})
|
|
245
266
|
let log = []; fx(() => log.push(s.x + s.y))
|
|
246
267
|
is(log, [3])
|