From f6684558aaab7f530113b8efff6c1cddeee08873 Mon Sep 17 00:00:00 2001 From: enzoaicardi Date: Tue, 23 Jul 2024 16:55:50 +0200 Subject: [PATCH] [dev] fix signal setter infinite loop --- dist/cjs/vif.cjs | 2 +- dist/esm/vif.js | 2 +- dist/iife/vif.js | 2 +- dist/umd/vif.js | 2 +- src/reactivity/signal.js | 12 +++- tests/benchmarks/vs-lit.js | 4 -- tests/data-test.js | 18 ++++++ tests/garbage/lit.js | 104 --------------------------------- tests/garbage/vif.js | 92 ----------------------------- tests/{garbage => }/index.html | 11 ++-- 10 files changed, 36 insertions(+), 213 deletions(-) delete mode 100644 tests/benchmarks/vs-lit.js create mode 100644 tests/data-test.js delete mode 100644 tests/garbage/lit.js delete mode 100644 tests/garbage/vif.js rename tests/{garbage => }/index.html (65%) diff --git a/dist/cjs/vif.cjs b/dist/cjs/vif.cjs index 1633e07..6024f0f 100644 --- a/dist/cjs/vif.cjs +++ b/dist/cjs/vif.cjs @@ -1 +1 @@ -"use strict";const t=(t,n,s,o)=>{const r=n.handler||(n.handler=new e);r[o]=s(t.t),n.addEventListener(o,r)};class e{handleEvent(t){this[t.type](t)}}let n={},s=null;const o=t=>{n[t]&&(n[t](),n[t]=!1)},r=document,c=t=>r.createElement(t),l=(t,e)=>t.cloneNode(e),i=t=>t.children,f=t=>t.content,u=t=>t.nextSibling,a=t=>t.o||t.children,p=(t,e)=>t.name.substring(e),x=t=>0===t.name.indexOf("x-"),h=t=>0===t.tagName.indexOf("X-"),d=t=>"TEMPLATE"===t.tagName,m=t=>!!et[t.tagName]||d(t),w={l(t){let e=this;e.t||(e.t=t||{}),e.i||(e.i=new Set)},u(){this.p()},h(t,e,n){let o=this,r=e.length-1,c=n;for(;r>=0;){const l=e[r],i=t[l.m];if(l.v&&(i.$=l.S,(n||o.i).add(i),s&&s(i.tagName)),!n)for(const[t,e]of l.L){const n=e.M(o,i,e.j,t);n&&o.i.add(n)}if(l.S){(!l.v||(c=!m(i)&&(i.i=new Set)))&&o.h(a(i),l.S,c)}r--}},p(){for(const t of this.i)t.u&&t.u();this.i.clear()}};function y(t){this.l(t)}y.prototype=w;let E=null;const v=t=>{const e=t=>{if(void 0!==t){e.value=t;for(const t of e.k)t()}else E&&(e.k.add(E),E.C.add(e.k));return e.value};return e.value=t,e.O=!0,e.k=new Set,e},b=t=>{const e=E;return E=t,E.C=new Set,E.u=(t=>()=>{for(const e of t.C)e.delete(t)})(E),t(),E=e,t};let g=r.createComment(""),$=c("template"),S=r.createDocumentFragment();const L=t=>{let e=f(t).firstChild;for(;e;){const t=u(e);1!==e.nodeType&&e.remove(),e=t}},M=()=>{},j=(t,...e)=>t.reduce(((n,s,o)=>n+(s+(o===t.length-1?"":e[o]))),""),k=c("style"),C="css-x";let O=1;const R=(t,e)=>"$"+(e||O)+t,T=(t,...e)=>{if("string"==typeof t)return`${C}="${R(t,O)}"`;{const n=j(t,e);k.textContent+=n,k.parentElement||r.head.appendChild(k)}},V=(t,e,n)=>{const s=n,o=t.R;e.setAttribute(C,R(s,o))},H=(t,e,n)=>{const s=n,o=t.useRef(s);let r=!0;return b((()=>{const t=o();if(r){for(const n of t)n(e);r=!1}else t[t.length-1](e)}))},U=(t,e,n)=>{const s=e.style.display;return b((()=>{n(t.t)?s?e.style.display=s:e.style.removeProperty("display"):e.style.display="none"}))},X=(t,e,n)=>b((()=>e.textContent=n(t.t))),A=(t,e,n,s)=>b((()=>e.setAttribute(s,n(t.t)))),P=t=>"x-text"===t?X:"x-show"===t?U:"x-ref"===t?H:"x-css"===t?V:A,q=(t,e,n,s)=>{e.t||(e.t={});let o=null;const r={T:(t,e)=>o={V:t,H:e}},c=b((()=>{const o=e.t[s],c=n(t.t);o&&o.O?r.T(o,c):e.t[s]=c}));return o&&o.V(o.H),r.T=(t,e)=>t(e),c},z={},B=t=>{if(z[t])return z[t];let e=Object.getPrototypeOf((function(){})).constructor,n=/^[\n\s]*if.*\(.*\)/.test(t.trim())||/^(let|const)\s/.test(t.trim())?`(()=>{ ${t} })()`:t;let s=(()=>{try{let s=new e(["scope"],`with(scope){return ${n}};`);return Object.defineProperty(s,"name",{value:`VifExp "${t}"`}),s}catch(e){return console.error("VifExp error : "+t,e),!1}})();return z[t]=s,s},D=(t,e,n)=>{Z(e);let s=[];const o="item",r=e.getAttribute(o)||o;return b((()=>{const o=n(t.t);((t,e,n,s,o)=>{let r=0;const c=n.length,l=s.length;let i=l-c;for(;r0;)Q(e,t,r,o,s[r]),i--,r++;i<0&&Y(e,r,r-i)})(t.t,e,s,o,r),s=o.slice()}))},F=(t,e,n)=>{Z(e);let s=!1;return b((()=>{const o=!!n(t.t);o!==s&&(s=o,o?Q(e,t.t,0):Y(e,0))}))};let G=location;const I=()=>G.pathname+G.search,J=v(I());addEventListener("popstate",(()=>{G=location,J(I())}));const K=t=>{if("string"==typeof t){const e=new URL(t,G);if(G.href!==e.href)return G=e,history.pushState({},"",G),J(I())}else{t.preventDefault();const e=t.currentTarget.href;if(e)return K(e)}};K.route=J;const N=(t,e,n)=>{Z(e);const s=new RegExp(n||"."),o="params",r=e.getAttribute(o)||o;let c=null;return b((()=>{const n=J().match(s)||null;n!==c&&(n&&c?W(e,0,n):n?Q(e,t.t,0,r,n):Y(e,0)),c=n}))},Q=(t,e,n,s,o)=>{const r=t.U;let c=r[n+1];const a=l(f(t),!0);c?c.V&&c.V(o):c=r[n+1]=((t,e,n,s)=>{const o=n&&v(s);return o&&(o.index=e),{X:new y(n?{...t,[n]:o}:t),V:o}})(e,n,s,o),c.A=a.lastChild,t.$&&c.X.h(i(a),t.$);const p=r[n].A;p.parentNode.insertBefore(a,u(p))},W=(t,e,n)=>{t.U[e+1].V(n)},Y=(t,e,n)=>{const s=t.U,o=s[e].A;for(;e++{L(t);const e=t.U=[{A:l(g)}];f(t).append(l(g)),t.u=()=>{for(let t=1;t{const n=[];for(let o=0;o0&&n};class tt extends HTMLElement{constructor(){super(),this.l(),this.P={}}onMount(){}connectedCallback(){let t=this,e=t.t;for(const n of t.attributes)if(x(n)){const t=p(n,2);e[t]=v(e[t])}else e[n.name]=n.value||!0;t.onMount({props:e}),t.q()}onUnmount(){}u(){let t=this;t.onUnmount({props:t.t}),t.p()}q(){let t=this;const e=t.B;let n=e.D,s=e.S,o=e.R;const r=n?M:j,c=o?M:T,u=e.F,a={html:r,css:c,props:t.t},p=u.call(t,a);if("string"==typeof p?(n=e.D=(t=>{let e=l($);return e.innerHTML=t,L(e),f(e)})(p),s=e.S=_(i(n))):n||(n=p&&p!==t?(t=>{let e=l(S);return e.append(...t),e})(p):t,s=t.$||_(t.o||i(n))),t.R=e.R=o||O++,e.D&&(n=l(n,!0)),s&&t.h(t.o||i(n),s),n!==t){const e=t.parentNode;e.o||(e.o=[].slice.call(i(e))),t.replaceWith(n)}}useEffect(t){this.i.add(b(t))}useRef(t,e,n){const s=this.P,o=s[t]||(s[t]=v([]));if(!e)return o;{const t=o.value;n?t[(t.length||1)-1]=e:t.push(e),o(t)}}}Object.assign(tt.prototype,w);const et={},nt=v(localStorage.getItem("locale")||navigator.language),st=(t,e)=>t[e]||t[t.default],ot=t=>{const e=v();let n=[];return e.onload=t=>{e()?t():n.push(t)},b((()=>{const[s,o]=nt().split("-"),r=st(st(t,s),o);r&&r().then((t=>{e(t.default),n&&(n=n.forEach((t=>t())))}))})),e};ot.locale=nt,exports.useDefine=(t,e)=>{const n="X-"+t.toUpperCase();return et[n]=class extends tt{constructor(){super()}},et[n].F=e,et[n].prototype.B=et[n],customElements.define(`x-${t}`,et[n]),et[n]},exports.useEffect=b,exports.useI18n=ot,exports.useNavigate=K,exports.useObserve=t=>{n={...t,...n},s=o},exports.useSignal=v; +"use strict";const t=(t,n,s,o)=>{const r=n.handler||(n.handler=new e);r[o]=s(t.t),n.addEventListener(o,r)};class e{handleEvent(t){this[t.type](t)}}let n={},s=null;const o=t=>{n[t]&&(n[t](),n[t]=!1)},r=document,c=t=>r.createElement(t),l=(t,e)=>t.cloneNode(e),i=t=>t.children,u=t=>t.content,f=t=>t.nextSibling,a=t=>t.o||t.children,p=(t,e)=>t.name.substring(e),x=t=>0===t.name.indexOf("x-"),h=t=>0===t.tagName.indexOf("X-"),d=t=>"TEMPLATE"===t.tagName,m=t=>!!et[t.tagName]||d(t),w={l(t){let e=this;e.t||(e.t=t||{}),e.i||(e.i=new Set)},u(){this.p()},h(t,e,n){let o=this,r=e.length-1,c=n;for(;r>=0;){const l=e[r],i=t[l.m];if(l.v&&(i.$=l.S,(n||o.i).add(i),s&&s(i.tagName)),!n)for(const[t,e]of l.L){const n=e.M(o,i,e.j,t);n&&o.i.add(n)}if(l.S){(!l.v||(c=!m(i)&&(i.i=new Set)))&&o.h(a(i),l.S,c)}r--}},p(){for(const t of this.i)t.u&&t.u();this.i.clear()}};function y(t){this.l(t)}y.prototype=w;let E=null;const v=t=>{const e=t=>{if(void 0!==t){const n=E;E=null,e.value=t;for(const t of e.k)t();E=n}else E&&(e.k.add(E),E.C.add(e.k));return e.value};return e.value=t,e.O=!0,e.k=new Set,e},b=t=>{const e=E;return E=t,E.C=new Set,E.u=(t=>()=>{for(const e of t.C)e.delete(t)})(E),t(),E=e,t};let g=r.createComment(""),$=c("template"),S=r.createDocumentFragment();const L=t=>{let e=u(t).firstChild;for(;e;){const t=f(e);1!==e.nodeType&&e.remove(),e=t}},M=()=>{},j=(t,...e)=>t.reduce(((n,s,o)=>n+(s+(o===t.length-1?"":e[o]))),""),k=c("style"),C="css-x";let O=1;const R=(t,e)=>"$"+(e||O)+t,T=(t,...e)=>{if("string"==typeof t)return`${C}="${R(t,O)}"`;{const n=j(t,e);k.textContent+=n,k.parentElement||r.head.appendChild(k)}},V=(t,e,n)=>{const s=n,o=t.R;e.setAttribute(C,R(s,o))},H=(t,e,n)=>{const s=n,o=t.useRef(s);let r=!0;return b((()=>{const t=o();if(r){for(const n of t)n(e);r=!1}else t[t.length-1](e)}))},U=(t,e,n)=>{const s=e.style.display;return b((()=>{n(t.t)?s?e.style.display=s:e.style.removeProperty("display"):e.style.display="none"}))},X=(t,e,n)=>b((()=>e.textContent=n(t.t))),A=(t,e,n,s)=>b((()=>e.setAttribute(s,n(t.t)))),P=t=>"x-text"===t?X:"x-show"===t?U:"x-ref"===t?H:"x-css"===t?V:A,q=(t,e,n,s)=>{e.t||(e.t={});let o=null;const r={T:(t,e)=>o={V:t,H:e}},c=b((()=>{const o=e.t[s],c=n(t.t);o&&o.O?r.T(o,c):e.t[s]=c}));return o&&o.V(o.H),r.T=(t,e)=>t(e),c},z={},B=t=>{if(z[t])return z[t];let e=Object.getPrototypeOf((function(){})).constructor,n=/^[\n\s]*if.*\(.*\)/.test(t.trim())||/^(let|const)\s/.test(t.trim())?`(()=>{ ${t} })()`:t;let s=(()=>{try{let s=new e(["scope"],`with(scope){return ${n}};`);return Object.defineProperty(s,"name",{value:`VifExp "${t}"`}),s}catch(e){return console.error("VifExp error : "+t,e),!1}})();return z[t]=s,s},D=(t,e,n)=>{Z(e);let s=[];const o="item",r=e.getAttribute(o)||o;return b((()=>{const o=n(t.t);((t,e,n,s,o)=>{let r=0;const c=n.length,l=s.length;let i=l-c;for(;r0;)Q(e,t,r,o,s[r]),i--,r++;i<0&&Y(e,r,r-i)})(t.t,e,s,o,r),s=o.slice()}))},F=(t,e,n)=>{Z(e);let s=!1;return b((()=>{const o=!!n(t.t);o!==s&&(s=o,o?Q(e,t.t,0):Y(e,0))}))};let G=location;const I=()=>G.pathname+G.search,J=v(I());addEventListener("popstate",(()=>{G=location,J(I())}));const K=t=>{if("string"==typeof t){const e=new URL(t,G);if(G.href!==e.href)return G=e,history.pushState({},"",G),J(I())}else{t.preventDefault();const e=t.currentTarget.href;if(e)return K(e)}};K.route=J;const N=(t,e,n)=>{Z(e);const s=new RegExp(n||"."),o="params",r=e.getAttribute(o)||o;let c=null;return b((()=>{const n=J().match(s)||null;n!==c&&(n&&c?W(e,0,n):n?Q(e,t.t,0,r,n):Y(e,0)),c=n}))},Q=(t,e,n,s,o)=>{const r=t.U;let c=r[n+1];const a=l(u(t),!0);c?c.V&&c.V(o):c=r[n+1]=((t,e,n,s)=>{const o=n&&v(s);return o&&(o.index=e),{X:new y(n?{...t,[n]:o}:t),V:o}})(e,n,s,o),c.A=a.lastChild,t.$&&c.X.h(i(a),t.$);const p=r[n].A;p.parentNode.insertBefore(a,f(p))},W=(t,e,n)=>{t.U[e+1].V(n)},Y=(t,e,n)=>{const s=t.U,o=s[e].A;for(;e++{L(t);const e=t.U=[{A:l(g)}];u(t).append(l(g)),t.u=()=>{for(let t=1;t{const n=[];for(let o=0;o0&&n};class tt extends HTMLElement{constructor(){super(),this.l(),this.P={}}onMount(){}connectedCallback(){let t=this,e=t.t;for(const n of t.attributes)if(x(n)){const t=p(n,2);e[t]=v(e[t])}else e[n.name]=n.value||!0;t.onMount({props:e}),t.q()}onUnmount(){}u(){let t=this;t.onUnmount({props:t.t}),t.p()}q(){let t=this;const e=t.B;let n=e.D,s=e.S,o=e.R;const r=n?M:j,c=o?M:T,f=e.F,a={html:r,css:c,props:t.t},p=f.call(t,a);if("string"==typeof p?(n=e.D=(t=>{let e=l($);return e.innerHTML=t,L(e),u(e)})(p),s=e.S=_(i(n))):n||(n=p&&p!==t?(t=>{let e=l(S);return e.append(...t),e})(p):t,s=t.$||_(t.o||i(n))),t.R=e.R=o||O++,e.D&&(n=l(n,!0)),s&&t.h(t.o||i(n),s),n!==t){const e=t.parentNode;e.o||(e.o=[].slice.call(i(e))),t.replaceWith(n)}}useEffect(t){this.i.add(b(t))}useRef(t,e,n){const s=this.P,o=s[t]||(s[t]=v([]));if(!e)return o;{const t=o.value;n?t[(t.length||1)-1]=e:t.push(e),o(t)}}}Object.assign(tt.prototype,w);const et={},nt=v(localStorage.getItem("locale")||navigator.language),st=(t,e)=>t[e]||t[t.default],ot=t=>{const e=v();let n=[];return e.onload=t=>{e()?t():n.push(t)},b((()=>{const[s,o]=nt().split("-"),r=st(st(t,s),o);r&&r().then((t=>{e(t.default),n&&(n=n.forEach((t=>t())))}))})),e};ot.locale=nt,exports.useDefine=(t,e)=>{const n="X-"+t.toUpperCase();return et[n]=class extends tt{constructor(){super()}},et[n].F=e,et[n].prototype.B=et[n],customElements.define(`x-${t}`,et[n]),et[n]},exports.useEffect=b,exports.useI18n=ot,exports.useNavigate=K,exports.useObserve=t=>{n={...t,...n},s=o},exports.useSignal=v; diff --git a/dist/esm/vif.js b/dist/esm/vif.js index 6cb19db..47aee22 100644 --- a/dist/esm/vif.js +++ b/dist/esm/vif.js @@ -1 +1 @@ -const t=(t,n,s,o)=>{const r=n.handler||(n.handler=new e);r[o]=s(t.t),n.addEventListener(o,r)};class e{handleEvent(t){this[t.type](t)}}let n={},s=null;const o=t=>{n[t]&&(n[t](),n[t]=!1)},r=t=>{n={...t,...n},s=o},c=document,l=t=>c.createElement(t),i=(t,e)=>t.cloneNode(e),u=t=>t.children,f=t=>t.content,a=t=>t.nextSibling,p=t=>t.o||t.children,h=(t,e)=>t.name.substring(e),x=t=>0===t.name.indexOf("x-"),d=t=>0===t.tagName.indexOf("X-"),m=t=>"TEMPLATE"===t.tagName,w=t=>!!nt[t.tagName]||m(t),E={l(t){let e=this;e.t||(e.t=t||{}),e.i||(e.i=new Set)},u(){this.p()},h(t,e,n){let o=this,r=e.length-1,c=n;for(;r>=0;){const l=e[r],i=t[l.m];if(l.v&&(i.S=l.$,(n||o.i).add(i),s&&s(i.tagName)),!n)for(const[t,e]of l.L){const n=e.M(o,i,e.O,t);n&&o.i.add(n)}if(l.$){(!l.v||(c=!w(i)&&(i.i=new Set)))&&o.h(p(i),l.$,c)}r--}},p(){for(const t of this.i)t.u&&t.u();this.i.clear()}};function v(t){this.l(t)}v.prototype=E;let y=null;const g=t=>{const e=t=>{if(void 0!==t){e.value=t;for(const t of e.j)t()}else y&&(e.j.add(y),y.k.add(e.j));return e.value};return e.value=t,e.C=!0,e.j=new Set,e},b=t=>{const e=y;return y=t,y.k=new Set,y.u=(t=>()=>{for(const e of t.k)e.delete(t)})(y),t(),y=e,t};let S=c.createComment(""),$=l("template"),L=c.createDocumentFragment();const M=t=>{let e=f(t).firstChild;for(;e;){const t=a(e);1!==e.nodeType&&e.remove(),e=t}},O=()=>{},j=(t,...e)=>t.reduce(((n,s,o)=>n+(s+(o===t.length-1?"":e[o]))),""),k=l("style"),C="css-x";let R=1;const T=(t,e)=>"$"+(e||R)+t,V=(t,...e)=>{if("string"==typeof t)return`${C}="${T(t,R)}"`;{const n=j(t,e);k.textContent+=n,k.parentElement||c.head.appendChild(k)}},H=(t,e,n)=>{const s=n,o=t.R;e.setAttribute(C,T(s,o))},U=(t,e,n)=>{const s=n,o=t.useRef(s);let r=!0;return b((()=>{const t=o();if(r){for(const n of t)n(e);r=!1}else t[t.length-1](e)}))},X=(t,e,n)=>{const s=e.style.display;return b((()=>{n(t.t)?s?e.style.display=s:e.style.removeProperty("display"):e.style.display="none"}))},A=(t,e,n)=>b((()=>e.textContent=n(t.t))),D=(t,e,n,s)=>b((()=>e.setAttribute(s,n(t.t)))),I=t=>"x-text"===t?A:"x-show"===t?X:"x-ref"===t?U:"x-css"===t?H:D,N=(t,e,n,s)=>{e.t||(e.t={});let o=null;const r={T:(t,e)=>o={V:t,H:e}},c=b((()=>{const o=e.t[s],c=n(t.t);o&&o.C?r.T(o,c):e.t[s]=c}));return o&&o.V(o.H),r.T=(t,e)=>t(e),c},P={},q=t=>{if(P[t])return P[t];let e=Object.getPrototypeOf((function(){})).constructor,n=/^[\n\s]*if.*\(.*\)/.test(t.trim())||/^(let|const)\s/.test(t.trim())?`(()=>{ ${t} })()`:t;let s=(()=>{try{let s=new e(["scope"],`with(scope){return ${n}};`);return Object.defineProperty(s,"name",{value:`VifExp "${t}"`}),s}catch(e){return console.error("VifExp error : "+t,e),!1}})();return P[t]=s,s},z=(t,e,n)=>{_(e);let s=[];const o="item",r=e.getAttribute(o)||o;return b((()=>{const o=n(t.t);((t,e,n,s,o)=>{let r=0;const c=n.length,l=s.length;let i=l-c;for(;r0;)W(e,t,r,o,s[r]),i--,r++;i<0&&Z(e,r,r-i)})(t.t,e,s,o,r),s=o.slice()}))},B=(t,e,n)=>{_(e);let s=!1;return b((()=>{const o=!!n(t.t);o!==s&&(s=o,o?W(e,t.t,0):Z(e,0))}))};let F=location;const G=()=>F.pathname+F.search,J=g(G());addEventListener("popstate",(()=>{F=location,J(G())}));const K=t=>{if("string"==typeof t){const e=new URL(t,F);if(F.href!==e.href)return F=e,history.pushState({},"",F),J(G())}else{t.preventDefault();const e=t.currentTarget.href;if(e)return K(e)}};K.route=J;const Q=(t,e,n)=>{_(e);const s=new RegExp(n||"."),o="params",r=e.getAttribute(o)||o;let c=null;return b((()=>{const n=J().match(s)||null;n!==c&&(n&&c?Y(e,0,n):n?W(e,t.t,0,r,n):Z(e,0)),c=n}))},W=(t,e,n,s,o)=>{const r=t.U;let c=r[n+1];const l=i(f(t),!0);c?c.V&&c.V(o):c=r[n+1]=((t,e,n,s)=>{const o=n&&g(s);return o&&(o.index=e),{X:new v(n?{...t,[n]:o}:t),V:o}})(e,n,s,o),c.A=l.lastChild,t.S&&c.X.h(u(l),t.S);const p=r[n].A;p.parentNode.insertBefore(l,a(p))},Y=(t,e,n)=>{t.U[e+1].V(n)},Z=(t,e,n)=>{const s=t.U,o=s[e].A;for(;e++{M(t);const e=t.U=[{A:i(S)}];f(t).append(i(S)),t.u=()=>{for(let t=1;t{const n=[];for(let o=0;o0&&n};class et extends HTMLElement{constructor(){super(),this.l(),this.D={}}onMount(){}connectedCallback(){let t=this,e=t.t;for(const n of t.attributes)if(x(n)){const t=h(n,2);e[t]=g(e[t])}else e[n.name]=n.value||!0;t.onMount({props:e}),t.I()}onUnmount(){}u(){let t=this;t.onUnmount({props:t.t}),t.p()}I(){let t=this;const e=t.N;let n=e.P,s=e.$,o=e.R;const r=n?O:j,c=o?O:V,l=e.q,a={html:r,css:c,props:t.t},p=l.call(t,a);if("string"==typeof p?(n=e.P=(t=>{let e=i($);return e.innerHTML=t,M(e),f(e)})(p),s=e.$=tt(u(n))):n||(n=p&&p!==t?(t=>{let e=i(L);return e.append(...t),e})(p):t,s=t.S||tt(t.o||u(n))),t.R=e.R=o||R++,e.P&&(n=i(n,!0)),s&&t.h(t.o||u(n),s),n!==t){const e=t.parentNode;e.o||(e.o=[].slice.call(u(e))),t.replaceWith(n)}}useEffect(t){this.i.add(b(t))}useRef(t,e,n){const s=this.D,o=s[t]||(s[t]=g([]));if(!e)return o;{const t=o.value;n?t[(t.length||1)-1]=e:t.push(e),o(t)}}}Object.assign(et.prototype,E);const nt={},st=(t,e)=>{const n="X-"+t.toUpperCase();return nt[n]=class extends et{constructor(){super()}},nt[n].q=e,nt[n].prototype.N=nt[n],customElements.define(`x-${t}`,nt[n]),nt[n]},ot=g(localStorage.getItem("locale")||navigator.language),rt=(t,e)=>t[e]||t[t.default],ct=t=>{const e=g();let n=[];return e.onload=t=>{e()?t():n.push(t)},b((()=>{const[s,o]=ot().split("-"),r=rt(rt(t,s),o);r&&r().then((t=>{e(t.default),n&&(n=n.forEach((t=>t())))}))})),e};ct.locale=ot;export{st as useDefine,b as useEffect,ct as useI18n,K as useNavigate,r as useObserve,g as useSignal}; +const t=(t,n,s,o)=>{const r=n.handler||(n.handler=new e);r[o]=s(t.t),n.addEventListener(o,r)};class e{handleEvent(t){this[t.type](t)}}let n={},s=null;const o=t=>{n[t]&&(n[t](),n[t]=!1)},r=t=>{n={...t,...n},s=o},c=document,l=t=>c.createElement(t),i=(t,e)=>t.cloneNode(e),u=t=>t.children,f=t=>t.content,a=t=>t.nextSibling,p=t=>t.o||t.children,h=(t,e)=>t.name.substring(e),x=t=>0===t.name.indexOf("x-"),d=t=>0===t.tagName.indexOf("X-"),m=t=>"TEMPLATE"===t.tagName,w=t=>!!nt[t.tagName]||m(t),E={l(t){let e=this;e.t||(e.t=t||{}),e.i||(e.i=new Set)},u(){this.p()},h(t,e,n){let o=this,r=e.length-1,c=n;for(;r>=0;){const l=e[r],i=t[l.m];if(l.v&&(i.S=l.$,(n||o.i).add(i),s&&s(i.tagName)),!n)for(const[t,e]of l.L){const n=e.M(o,i,e.O,t);n&&o.i.add(n)}if(l.$){(!l.v||(c=!w(i)&&(i.i=new Set)))&&o.h(p(i),l.$,c)}r--}},p(){for(const t of this.i)t.u&&t.u();this.i.clear()}};function v(t){this.l(t)}v.prototype=E;let y=null;const g=t=>{const e=t=>{if(void 0!==t){const n=y;y=null,e.value=t;for(const t of e.j)t();y=n}else y&&(e.j.add(y),y.k.add(e.j));return e.value};return e.value=t,e.C=!0,e.j=new Set,e},b=t=>{const e=y;return y=t,y.k=new Set,y.u=(t=>()=>{for(const e of t.k)e.delete(t)})(y),t(),y=e,t};let S=c.createComment(""),$=l("template"),L=c.createDocumentFragment();const M=t=>{let e=f(t).firstChild;for(;e;){const t=a(e);1!==e.nodeType&&e.remove(),e=t}},O=()=>{},j=(t,...e)=>t.reduce(((n,s,o)=>n+(s+(o===t.length-1?"":e[o]))),""),k=l("style"),C="css-x";let R=1;const T=(t,e)=>"$"+(e||R)+t,V=(t,...e)=>{if("string"==typeof t)return`${C}="${T(t,R)}"`;{const n=j(t,e);k.textContent+=n,k.parentElement||c.head.appendChild(k)}},H=(t,e,n)=>{const s=n,o=t.R;e.setAttribute(C,T(s,o))},U=(t,e,n)=>{const s=n,o=t.useRef(s);let r=!0;return b((()=>{const t=o();if(r){for(const n of t)n(e);r=!1}else t[t.length-1](e)}))},X=(t,e,n)=>{const s=e.style.display;return b((()=>{n(t.t)?s?e.style.display=s:e.style.removeProperty("display"):e.style.display="none"}))},A=(t,e,n)=>b((()=>e.textContent=n(t.t))),D=(t,e,n,s)=>b((()=>e.setAttribute(s,n(t.t)))),I=t=>"x-text"===t?A:"x-show"===t?X:"x-ref"===t?U:"x-css"===t?H:D,N=(t,e,n,s)=>{e.t||(e.t={});let o=null;const r={T:(t,e)=>o={V:t,H:e}},c=b((()=>{const o=e.t[s],c=n(t.t);o&&o.C?r.T(o,c):e.t[s]=c}));return o&&o.V(o.H),r.T=(t,e)=>t(e),c},P={},q=t=>{if(P[t])return P[t];let e=Object.getPrototypeOf((function(){})).constructor,n=/^[\n\s]*if.*\(.*\)/.test(t.trim())||/^(let|const)\s/.test(t.trim())?`(()=>{ ${t} })()`:t;let s=(()=>{try{let s=new e(["scope"],`with(scope){return ${n}};`);return Object.defineProperty(s,"name",{value:`VifExp "${t}"`}),s}catch(e){return console.error("VifExp error : "+t,e),!1}})();return P[t]=s,s},z=(t,e,n)=>{_(e);let s=[];const o="item",r=e.getAttribute(o)||o;return b((()=>{const o=n(t.t);((t,e,n,s,o)=>{let r=0;const c=n.length,l=s.length;let i=l-c;for(;r0;)W(e,t,r,o,s[r]),i--,r++;i<0&&Z(e,r,r-i)})(t.t,e,s,o,r),s=o.slice()}))},B=(t,e,n)=>{_(e);let s=!1;return b((()=>{const o=!!n(t.t);o!==s&&(s=o,o?W(e,t.t,0):Z(e,0))}))};let F=location;const G=()=>F.pathname+F.search,J=g(G());addEventListener("popstate",(()=>{F=location,J(G())}));const K=t=>{if("string"==typeof t){const e=new URL(t,F);if(F.href!==e.href)return F=e,history.pushState({},"",F),J(G())}else{t.preventDefault();const e=t.currentTarget.href;if(e)return K(e)}};K.route=J;const Q=(t,e,n)=>{_(e);const s=new RegExp(n||"."),o="params",r=e.getAttribute(o)||o;let c=null;return b((()=>{const n=J().match(s)||null;n!==c&&(n&&c?Y(e,0,n):n?W(e,t.t,0,r,n):Z(e,0)),c=n}))},W=(t,e,n,s,o)=>{const r=t.U;let c=r[n+1];const l=i(f(t),!0);c?c.V&&c.V(o):c=r[n+1]=((t,e,n,s)=>{const o=n&&g(s);return o&&(o.index=e),{X:new v(n?{...t,[n]:o}:t),V:o}})(e,n,s,o),c.A=l.lastChild,t.S&&c.X.h(u(l),t.S);const p=r[n].A;p.parentNode.insertBefore(l,a(p))},Y=(t,e,n)=>{t.U[e+1].V(n)},Z=(t,e,n)=>{const s=t.U,o=s[e].A;for(;e++{M(t);const e=t.U=[{A:i(S)}];f(t).append(i(S)),t.u=()=>{for(let t=1;t{const n=[];for(let o=0;o0&&n};class et extends HTMLElement{constructor(){super(),this.l(),this.D={}}onMount(){}connectedCallback(){let t=this,e=t.t;for(const n of t.attributes)if(x(n)){const t=h(n,2);e[t]=g(e[t])}else e[n.name]=n.value||!0;t.onMount({props:e}),t.I()}onUnmount(){}u(){let t=this;t.onUnmount({props:t.t}),t.p()}I(){let t=this;const e=t.N;let n=e.P,s=e.$,o=e.R;const r=n?O:j,c=o?O:V,l=e.q,a={html:r,css:c,props:t.t},p=l.call(t,a);if("string"==typeof p?(n=e.P=(t=>{let e=i($);return e.innerHTML=t,M(e),f(e)})(p),s=e.$=tt(u(n))):n||(n=p&&p!==t?(t=>{let e=i(L);return e.append(...t),e})(p):t,s=t.S||tt(t.o||u(n))),t.R=e.R=o||R++,e.P&&(n=i(n,!0)),s&&t.h(t.o||u(n),s),n!==t){const e=t.parentNode;e.o||(e.o=[].slice.call(u(e))),t.replaceWith(n)}}useEffect(t){this.i.add(b(t))}useRef(t,e,n){const s=this.D,o=s[t]||(s[t]=g([]));if(!e)return o;{const t=o.value;n?t[(t.length||1)-1]=e:t.push(e),o(t)}}}Object.assign(et.prototype,E);const nt={},st=(t,e)=>{const n="X-"+t.toUpperCase();return nt[n]=class extends et{constructor(){super()}},nt[n].q=e,nt[n].prototype.N=nt[n],customElements.define(`x-${t}`,nt[n]),nt[n]},ot=g(localStorage.getItem("locale")||navigator.language),rt=(t,e)=>t[e]||t[t.default],ct=t=>{const e=g();let n=[];return e.onload=t=>{e()?t():n.push(t)},b((()=>{const[s,o]=ot().split("-"),r=rt(rt(t,s),o);r&&r().then((t=>{e(t.default),n&&(n=n.forEach((t=>t())))}))})),e};ct.locale=ot;export{st as useDefine,b as useEffect,ct as useI18n,K as useNavigate,r as useObserve,g as useSignal}; diff --git a/dist/iife/vif.js b/dist/iife/vif.js index a1f6a5f..2ad0759 100644 --- a/dist/iife/vif.js +++ b/dist/iife/vif.js @@ -1 +1 @@ -var Vif=function(t){"use strict";const e=(t,e,s,o)=>{const r=e.handler||(e.handler=new n);r[o]=s(t.t),e.addEventListener(o,r)};class n{handleEvent(t){this[t.type](t)}}let s={},o=null;const r=t=>{s[t]&&(s[t](),s[t]=!1)},c=document,l=t=>c.createElement(t),i=(t,e)=>t.cloneNode(e),f=t=>t.children,u=t=>t.content,a=t=>t.nextSibling,p=t=>t.o||t.children,h=(t,e)=>t.name.substring(e),d=t=>0===t.name.indexOf("x-"),x=t=>0===t.tagName.indexOf("X-"),m=t=>"TEMPLATE"===t.tagName,w=t=>!!nt[t.tagName]||m(t),y={l(t){let e=this;e.t||(e.t=t||{}),e.i||(e.i=new Set)},u(){this.p()},h(t,e,n){let s=this,r=e.length-1,c=n;for(;r>=0;){const l=e[r],i=t[l.m];if(l.v&&(i.$=l.S,(n||s.i).add(i),o&&o(i.tagName)),!n)for(const[t,e]of l.L){const n=e.M(s,i,e.V,t);n&&s.i.add(n)}if(l.S){(!l.v||(c=!w(i)&&(i.i=new Set)))&&s.h(p(i),l.S,c)}r--}},p(){for(const t of this.i)t.u&&t.u();this.i.clear()}};function E(t){this.l(t)}E.prototype=y;let v=null;const b=t=>{const e=t=>{if(void 0!==t){e.value=t;for(const t of e.j)t()}else v&&(e.j.add(v),v.k.add(e.j));return e.value};return e.value=t,e.C=!0,e.j=new Set,e},g=t=>{const e=v;return v=t,v.k=new Set,v.u=(t=>()=>{for(const e of t.k)e.delete(t)})(v),t(),v=e,t};let $=c.createComment(""),S=l("template"),L=c.createDocumentFragment();const M=t=>{let e=u(t).firstChild;for(;e;){const t=a(e);1!==e.nodeType&&e.remove(),e=t}},V=()=>{},j=(t,...e)=>t.reduce(((n,s,o)=>n+(s+(o===t.length-1?"":e[o]))),""),k=l("style"),C="css-x";let O=1;const R=(t,e)=>"$"+(e||O)+t,T=(t,...e)=>{if("string"==typeof t)return`${C}="${R(t,O)}"`;{const n=j(t,e);k.textContent+=n,k.parentElement||c.head.appendChild(k)}},H=(t,e,n)=>{const s=n,o=t.O;e.setAttribute(C,R(s,o))},U=(t,e,n)=>{const s=n,o=t.useRef(s);let r=!0;return g((()=>{const t=o();if(r){for(const n of t)n(e);r=!1}else t[t.length-1](e)}))},X=(t,e,n)=>{const s=e.style.display;return g((()=>{n(t.t)?s?e.style.display=s:e.style.removeProperty("display"):e.style.display="none"}))},A=(t,e,n)=>g((()=>e.textContent=n(t.t))),P=(t,e,n,s)=>g((()=>e.setAttribute(s,n(t.t)))),q=t=>"x-text"===t?A:"x-show"===t?X:"x-ref"===t?U:"x-css"===t?H:P,z=(t,e,n,s)=>{e.t||(e.t={});let o=null;const r={R:(t,e)=>o={T:t,H:e}},c=g((()=>{const o=e.t[s],c=n(t.t);o&&o.C?r.R(o,c):e.t[s]=c}));return o&&o.T(o.H),r.R=(t,e)=>t(e),c},B={},D=t=>{if(B[t])return B[t];let e=Object.getPrototypeOf((function(){})).constructor,n=/^[\n\s]*if.*\(.*\)/.test(t.trim())||/^(let|const)\s/.test(t.trim())?`(()=>{ ${t} })()`:t;let s=(()=>{try{let s=new e(["scope"],`with(scope){return ${n}};`);return Object.defineProperty(s,"name",{value:`VifExp "${t}"`}),s}catch(e){return console.error("VifExp error : "+t,e),!1}})();return B[t]=s,s},F=(t,e,n)=>{_(e);let s=[];const o="item",r=e.getAttribute(o)||o;return g((()=>{const o=n(t.t);((t,e,n,s,o)=>{let r=0;const c=n.length,l=s.length;let i=l-c;for(;r0;)W(e,t,r,o,s[r]),i--,r++;i<0&&Z(e,r,r-i)})(t.t,e,s,o,r),s=o.slice()}))},G=(t,e,n)=>{_(e);let s=!1;return g((()=>{const o=!!n(t.t);o!==s&&(s=o,o?W(e,t.t,0):Z(e,0))}))};let I=location;const J=()=>I.pathname+I.search,K=b(J());addEventListener("popstate",(()=>{I=location,K(J())}));const N=t=>{if("string"==typeof t){const e=new URL(t,I);if(I.href!==e.href)return I=e,history.pushState({},"",I),K(J())}else{t.preventDefault();const e=t.currentTarget.href;if(e)return N(e)}};N.route=K;const Q=(t,e,n)=>{_(e);const s=new RegExp(n||"."),o="params",r=e.getAttribute(o)||o;let c=null;return g((()=>{const n=K().match(s)||null;n!==c&&(n&&c?Y(e,0,n):n?W(e,t.t,0,r,n):Z(e,0)),c=n}))},W=(t,e,n,s,o)=>{const r=t.U;let c=r[n+1];const l=i(u(t),!0);c?c.T&&c.T(o):c=r[n+1]=((t,e,n,s)=>{const o=n&&b(s);return o&&(o.index=e),{X:new E(n?{...t,[n]:o}:t),T:o}})(e,n,s,o),c.A=l.lastChild,t.$&&c.X.h(f(l),t.$);const p=r[n].A;p.parentNode.insertBefore(l,a(p))},Y=(t,e,n)=>{t.U[e+1].T(n)},Z=(t,e,n)=>{const s=t.U,o=s[e].A;for(;e++{M(t);const e=t.U=[{A:i($)}];u(t).append(i($)),t.u=()=>{for(let t=1;t{const n=[];for(let o=0;o0&&n};class et extends HTMLElement{constructor(){super(),this.l(),this.P={}}onMount(){}connectedCallback(){let t=this,e=t.t;for(const n of t.attributes)if(d(n)){const t=h(n,2);e[t]=b(e[t])}else e[n.name]=n.value||!0;t.onMount({props:e}),t.q()}onUnmount(){}u(){let t=this;t.onUnmount({props:t.t}),t.p()}q(){let t=this;const e=t.B;let n=e.D,s=e.S,o=e.O;const r=n?V:j,c=o?V:T,l=e.F,a={html:r,css:c,props:t.t},p=l.call(t,a);if("string"==typeof p?(n=e.D=(t=>{let e=i(S);return e.innerHTML=t,M(e),u(e)})(p),s=e.S=tt(f(n))):n||(n=p&&p!==t?(t=>{let e=i(L);return e.append(...t),e})(p):t,s=t.$||tt(t.o||f(n))),t.O=e.O=o||O++,e.D&&(n=i(n,!0)),s&&t.h(t.o||f(n),s),n!==t){const e=t.parentNode;e.o||(e.o=[].slice.call(f(e))),t.replaceWith(n)}}useEffect(t){this.i.add(g(t))}useRef(t,e,n){const s=this.P,o=s[t]||(s[t]=b([]));if(!e)return o;{const t=o.value;n?t[(t.length||1)-1]=e:t.push(e),o(t)}}}Object.assign(et.prototype,y);const nt={},st=b(localStorage.getItem("locale")||navigator.language),ot=(t,e)=>t[e]||t[t.default],rt=t=>{const e=b();let n=[];return e.onload=t=>{e()?t():n.push(t)},g((()=>{const[s,o]=st().split("-"),r=ot(ot(t,s),o);r&&r().then((t=>{e(t.default),n&&(n=n.forEach((t=>t())))}))})),e};return rt.locale=st,t.useDefine=(t,e)=>{const n="X-"+t.toUpperCase();return nt[n]=class extends et{constructor(){super()}},nt[n].F=e,nt[n].prototype.B=nt[n],customElements.define(`x-${t}`,nt[n]),nt[n]},t.useEffect=g,t.useI18n=rt,t.useNavigate=N,t.useObserve=t=>{s={...t,...s},o=r},t.useSignal=b,t}({}); +var Vif=function(t){"use strict";const e=(t,e,s,o)=>{const r=e.handler||(e.handler=new n);r[o]=s(t.t),e.addEventListener(o,r)};class n{handleEvent(t){this[t.type](t)}}let s={},o=null;const r=t=>{s[t]&&(s[t](),s[t]=!1)},c=document,l=t=>c.createElement(t),i=(t,e)=>t.cloneNode(e),u=t=>t.children,f=t=>t.content,a=t=>t.nextSibling,p=t=>t.o||t.children,h=(t,e)=>t.name.substring(e),d=t=>0===t.name.indexOf("x-"),x=t=>0===t.tagName.indexOf("X-"),m=t=>"TEMPLATE"===t.tagName,w=t=>!!nt[t.tagName]||m(t),y={l(t){let e=this;e.t||(e.t=t||{}),e.i||(e.i=new Set)},u(){this.p()},h(t,e,n){let s=this,r=e.length-1,c=n;for(;r>=0;){const l=e[r],i=t[l.m];if(l.v&&(i.$=l.S,(n||s.i).add(i),o&&o(i.tagName)),!n)for(const[t,e]of l.L){const n=e.M(s,i,e.V,t);n&&s.i.add(n)}if(l.S){(!l.v||(c=!w(i)&&(i.i=new Set)))&&s.h(p(i),l.S,c)}r--}},p(){for(const t of this.i)t.u&&t.u();this.i.clear()}};function E(t){this.l(t)}E.prototype=y;let v=null;const b=t=>{const e=t=>{if(void 0!==t){const n=v;v=null,e.value=t;for(const t of e.j)t();v=n}else v&&(e.j.add(v),v.k.add(e.j));return e.value};return e.value=t,e.C=!0,e.j=new Set,e},g=t=>{const e=v;return v=t,v.k=new Set,v.u=(t=>()=>{for(const e of t.k)e.delete(t)})(v),t(),v=e,t};let $=c.createComment(""),S=l("template"),L=c.createDocumentFragment();const M=t=>{let e=f(t).firstChild;for(;e;){const t=a(e);1!==e.nodeType&&e.remove(),e=t}},V=()=>{},j=(t,...e)=>t.reduce(((n,s,o)=>n+(s+(o===t.length-1?"":e[o]))),""),k=l("style"),C="css-x";let O=1;const R=(t,e)=>"$"+(e||O)+t,T=(t,...e)=>{if("string"==typeof t)return`${C}="${R(t,O)}"`;{const n=j(t,e);k.textContent+=n,k.parentElement||c.head.appendChild(k)}},H=(t,e,n)=>{const s=n,o=t.O;e.setAttribute(C,R(s,o))},U=(t,e,n)=>{const s=n,o=t.useRef(s);let r=!0;return g((()=>{const t=o();if(r){for(const n of t)n(e);r=!1}else t[t.length-1](e)}))},X=(t,e,n)=>{const s=e.style.display;return g((()=>{n(t.t)?s?e.style.display=s:e.style.removeProperty("display"):e.style.display="none"}))},A=(t,e,n)=>g((()=>e.textContent=n(t.t))),P=(t,e,n,s)=>g((()=>e.setAttribute(s,n(t.t)))),q=t=>"x-text"===t?A:"x-show"===t?X:"x-ref"===t?U:"x-css"===t?H:P,z=(t,e,n,s)=>{e.t||(e.t={});let o=null;const r={R:(t,e)=>o={T:t,H:e}},c=g((()=>{const o=e.t[s],c=n(t.t);o&&o.C?r.R(o,c):e.t[s]=c}));return o&&o.T(o.H),r.R=(t,e)=>t(e),c},B={},D=t=>{if(B[t])return B[t];let e=Object.getPrototypeOf((function(){})).constructor,n=/^[\n\s]*if.*\(.*\)/.test(t.trim())||/^(let|const)\s/.test(t.trim())?`(()=>{ ${t} })()`:t;let s=(()=>{try{let s=new e(["scope"],`with(scope){return ${n}};`);return Object.defineProperty(s,"name",{value:`VifExp "${t}"`}),s}catch(e){return console.error("VifExp error : "+t,e),!1}})();return B[t]=s,s},F=(t,e,n)=>{_(e);let s=[];const o="item",r=e.getAttribute(o)||o;return g((()=>{const o=n(t.t);((t,e,n,s,o)=>{let r=0;const c=n.length,l=s.length;let i=l-c;for(;r0;)W(e,t,r,o,s[r]),i--,r++;i<0&&Z(e,r,r-i)})(t.t,e,s,o,r),s=o.slice()}))},G=(t,e,n)=>{_(e);let s=!1;return g((()=>{const o=!!n(t.t);o!==s&&(s=o,o?W(e,t.t,0):Z(e,0))}))};let I=location;const J=()=>I.pathname+I.search,K=b(J());addEventListener("popstate",(()=>{I=location,K(J())}));const N=t=>{if("string"==typeof t){const e=new URL(t,I);if(I.href!==e.href)return I=e,history.pushState({},"",I),K(J())}else{t.preventDefault();const e=t.currentTarget.href;if(e)return N(e)}};N.route=K;const Q=(t,e,n)=>{_(e);const s=new RegExp(n||"."),o="params",r=e.getAttribute(o)||o;let c=null;return g((()=>{const n=K().match(s)||null;n!==c&&(n&&c?Y(e,0,n):n?W(e,t.t,0,r,n):Z(e,0)),c=n}))},W=(t,e,n,s,o)=>{const r=t.U;let c=r[n+1];const l=i(f(t),!0);c?c.T&&c.T(o):c=r[n+1]=((t,e,n,s)=>{const o=n&&b(s);return o&&(o.index=e),{X:new E(n?{...t,[n]:o}:t),T:o}})(e,n,s,o),c.A=l.lastChild,t.$&&c.X.h(u(l),t.$);const p=r[n].A;p.parentNode.insertBefore(l,a(p))},Y=(t,e,n)=>{t.U[e+1].T(n)},Z=(t,e,n)=>{const s=t.U,o=s[e].A;for(;e++{M(t);const e=t.U=[{A:i($)}];f(t).append(i($)),t.u=()=>{for(let t=1;t{const n=[];for(let o=0;o0&&n};class et extends HTMLElement{constructor(){super(),this.l(),this.P={}}onMount(){}connectedCallback(){let t=this,e=t.t;for(const n of t.attributes)if(d(n)){const t=h(n,2);e[t]=b(e[t])}else e[n.name]=n.value||!0;t.onMount({props:e}),t.q()}onUnmount(){}u(){let t=this;t.onUnmount({props:t.t}),t.p()}q(){let t=this;const e=t.B;let n=e.D,s=e.S,o=e.O;const r=n?V:j,c=o?V:T,l=e.F,a={html:r,css:c,props:t.t},p=l.call(t,a);if("string"==typeof p?(n=e.D=(t=>{let e=i(S);return e.innerHTML=t,M(e),f(e)})(p),s=e.S=tt(u(n))):n||(n=p&&p!==t?(t=>{let e=i(L);return e.append(...t),e})(p):t,s=t.$||tt(t.o||u(n))),t.O=e.O=o||O++,e.D&&(n=i(n,!0)),s&&t.h(t.o||u(n),s),n!==t){const e=t.parentNode;e.o||(e.o=[].slice.call(u(e))),t.replaceWith(n)}}useEffect(t){this.i.add(g(t))}useRef(t,e,n){const s=this.P,o=s[t]||(s[t]=b([]));if(!e)return o;{const t=o.value;n?t[(t.length||1)-1]=e:t.push(e),o(t)}}}Object.assign(et.prototype,y);const nt={},st=b(localStorage.getItem("locale")||navigator.language),ot=(t,e)=>t[e]||t[t.default],rt=t=>{const e=b();let n=[];return e.onload=t=>{e()?t():n.push(t)},g((()=>{const[s,o]=st().split("-"),r=ot(ot(t,s),o);r&&r().then((t=>{e(t.default),n&&(n=n.forEach((t=>t())))}))})),e};return rt.locale=st,t.useDefine=(t,e)=>{const n="X-"+t.toUpperCase();return nt[n]=class extends et{constructor(){super()}},nt[n].F=e,nt[n].prototype.B=nt[n],customElements.define(`x-${t}`,nt[n]),nt[n]},t.useEffect=g,t.useI18n=rt,t.useNavigate=N,t.useObserve=t=>{s={...t,...s},o=r},t.useSignal=b,t}({}); diff --git a/dist/umd/vif.js b/dist/umd/vif.js index c5434d2..81b0e56 100644 --- a/dist/umd/vif.js +++ b/dist/umd/vif.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).t={})}(this,(function(t){"use strict";const e=(t,e,o,s)=>{const r=e.handler||(e.handler=new n);r[s]=o(t.o),e.addEventListener(s,r)};class n{handleEvent(t){this[t.type](t)}}let o={},s=null;const r=t=>{o[t]&&(o[t](),o[t]=!1)},c=document,l=t=>c.createElement(t),i=(t,e)=>t.cloneNode(e),f=t=>t.children,u=t=>t.content,a=t=>t.nextSibling,p=t=>t.l||t.children,d=(t,e)=>t.name.substring(e),h=t=>0===t.name.indexOf("x-"),x=t=>0===t.tagName.indexOf("X-"),y=t=>"TEMPLATE"===t.tagName,m=t=>!!nt[t.tagName]||y(t),w={i(t){let e=this;e.o||(e.o=t||{}),e.u||(e.u=new Set)},p(){this.h()},m(t,e,n){let o=this,r=e.length-1,c=n;for(;r>=0;){const l=e[r],i=t[l.v];if(l.$&&(i.S=l.T,(n||o.u).add(i),s&&s(i.tagName)),!n)for(const[t,e]of l.j){const n=e.L(o,i,e.M,t);n&&o.u.add(n)}if(l.T){(!l.$||(c=!m(i)&&(i.u=new Set)))&&o.m(p(i),l.T,c)}r--}},h(){for(const t of this.u)t.p&&t.p();this.u.clear()}};function b(t){this.i(t)}b.prototype=w;let E=null;const g=t=>{const e=t=>{if(void 0!==t){e.value=t;for(const t of e.k)t()}else E&&(e.k.add(E),E.C.add(e.k));return e.value};return e.value=t,e.O=!0,e.k=new Set,e},v=t=>{const e=E;return E=t,E.C=new Set,E.p=(t=>()=>{for(const e of t.C)e.delete(t)})(E),t(),E=e,t};let $=c.createComment(""),S=l("template"),T=c.createDocumentFragment();const j=t=>{let e=u(t).firstChild;for(;e;){const t=a(e);1!==e.nodeType&&e.remove(),e=t}},L=()=>{},M=(t,...e)=>t.reduce(((n,o,s)=>n+(o+(s===t.length-1?"":e[s]))),""),k=l("style"),C="css-x";let O=1;const R=(t,e)=>"$"+(e||O)+t,V=(t,...e)=>{if("string"==typeof t)return`${C}="${R(t,O)}"`;{const n=M(t,e);k.textContent+=n,k.parentElement||c.head.appendChild(k)}},H=(t,e,n)=>{const o=n,s=t.R;e.setAttribute(C,R(o,s))},U=(t,e,n)=>{const o=n,s=t.useRef(o);let r=!0;return v((()=>{const t=s();if(r){for(const n of t)n(e);r=!1}else t[t.length-1](e)}))},X=(t,e,n)=>{const o=e.style.display;return v((()=>{n(t.o)?o?e.style.display=o:e.style.removeProperty("display"):e.style.display="none"}))},A=(t,e,n)=>v((()=>e.textContent=n(t.o))),P=(t,e,n,o)=>v((()=>e.setAttribute(o,n(t.o)))),q=t=>"x-text"===t?A:"x-show"===t?X:"x-ref"===t?U:"x-css"===t?H:P,z=(t,e,n,o)=>{e.o||(e.o={});let s=null;const r={V:(t,e)=>s={H:t,U:e}},c=v((()=>{const s=e.o[o],c=n(t.o);s&&s.O?r.V(s,c):e.o[o]=c}));return s&&s.H(s.U),r.V=(t,e)=>t(e),c},B={},D=t=>{if(B[t])return B[t];let e=Object.getPrototypeOf((function(){})).constructor,n=/^[\n\s]*if.*\(.*\)/.test(t.trim())||/^(let|const)\s/.test(t.trim())?`(()=>{ ${t} })()`:t;let o=(()=>{try{let o=new e(["scope"],`with(scope){return ${n}};`);return Object.defineProperty(o,"name",{value:`VifExp "${t}"`}),o}catch(e){return console.error("VifExp error : "+t,e),!1}})();return B[t]=o,o},F=(t,e,n)=>{_(e);let o=[];const s="item",r=e.getAttribute(s)||s;return v((()=>{const s=n(t.o);((t,e,n,o,s)=>{let r=0;const c=n.length,l=o.length;let i=l-c;for(;r0;)W(e,t,r,s,o[r]),i--,r++;i<0&&Z(e,r,r-i)})(t.o,e,o,s,r),o=s.slice()}))},G=(t,e,n)=>{_(e);let o=!1;return v((()=>{const s=!!n(t.o);s!==o&&(o=s,s?W(e,t.o,0):Z(e,0))}))};let I=location;const J=()=>I.pathname+I.search,K=g(J());addEventListener("popstate",(()=>{I=location,K(J())}));const N=t=>{if("string"==typeof t){const e=new URL(t,I);if(I.href!==e.href)return I=e,history.pushState({},"",I),K(J())}else{t.preventDefault();const e=t.currentTarget.href;if(e)return N(e)}};N.route=K;const Q=(t,e,n)=>{_(e);const o=new RegExp(n||"."),s="params",r=e.getAttribute(s)||s;let c=null;return v((()=>{const n=K().match(o)||null;n!==c&&(n&&c?Y(e,0,n):n?W(e,t.o,0,r,n):Z(e,0)),c=n}))},W=(t,e,n,o,s)=>{const r=t.X;let c=r[n+1];const l=i(u(t),!0);c?c.H&&c.H(s):c=r[n+1]=((t,e,n,o)=>{const s=n&&g(o);return s&&(s.index=e),{A:new b(n?{...t,[n]:s}:t),H:s}})(e,n,o,s),c.P=l.lastChild,t.S&&c.A.m(f(l),t.S);const p=r[n].P;p.parentNode.insertBefore(l,a(p))},Y=(t,e,n)=>{t.X[e+1].H(n)},Z=(t,e,n)=>{const o=t.X,s=o[e].P;for(;e++{j(t);const e=t.X=[{P:i($)}];u(t).append(i($)),t.p=()=>{for(let t=1;t{const n=[];for(let s=0;s0&&n};class et extends HTMLElement{constructor(){super(),this.i(),this.q={}}onMount(){}connectedCallback(){let t=this,e=t.o;for(const n of t.attributes)if(h(n)){const t=d(n,2);e[t]=g(e[t])}else e[n.name]=n.value||!0;t.onMount({props:e}),t.B()}onUnmount(){}p(){let t=this;t.onUnmount({props:t.o}),t.h()}B(){let t=this;const e=t.D;let n=e.F,o=e.T,s=e.R;const r=n?L:M,c=s?L:V,l=e.G,a={html:r,css:c,props:t.o},p=l.call(t,a);if("string"==typeof p?(n=e.F=(t=>{let e=i(S);return e.innerHTML=t,j(e),u(e)})(p),o=e.T=tt(f(n))):n||(n=p&&p!==t?(t=>{let e=i(T);return e.append(...t),e})(p):t,o=t.S||tt(t.l||f(n))),t.R=e.R=s||O++,e.F&&(n=i(n,!0)),o&&t.m(t.l||f(n),o),n!==t){const e=t.parentNode;e.l||(e.l=[].slice.call(f(e))),t.replaceWith(n)}}useEffect(t){this.u.add(v(t))}useRef(t,e,n){const o=this.q,s=o[t]||(o[t]=g([]));if(!e)return s;{const t=s.value;n?t[(t.length||1)-1]=e:t.push(e),s(t)}}}Object.assign(et.prototype,w);const nt={},ot=g(localStorage.getItem("locale")||navigator.language),st=(t,e)=>t[e]||t[t.default],rt=t=>{const e=g();let n=[];return e.onload=t=>{e()?t():n.push(t)},v((()=>{const[o,s]=ot().split("-"),r=st(st(t,o),s);r&&r().then((t=>{e(t.default),n&&(n=n.forEach((t=>t())))}))})),e};rt.locale=ot,t.useDefine=(t,e)=>{const n="X-"+t.toUpperCase();return nt[n]=class extends et{constructor(){super()}},nt[n].G=e,nt[n].prototype.D=nt[n],customElements.define(`x-${t}`,nt[n]),nt[n]},t.useEffect=v,t.useI18n=rt,t.useNavigate=N,t.useObserve=t=>{o={...t,...o},s=r},t.useSignal=g})); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).t={})}(this,(function(t){"use strict";const e=(t,e,o,s)=>{const r=e.handler||(e.handler=new n);r[s]=o(t.o),e.addEventListener(s,r)};class n{handleEvent(t){this[t.type](t)}}let o={},s=null;const r=t=>{o[t]&&(o[t](),o[t]=!1)},c=document,l=t=>c.createElement(t),i=(t,e)=>t.cloneNode(e),f=t=>t.children,u=t=>t.content,a=t=>t.nextSibling,p=t=>t.l||t.children,d=(t,e)=>t.name.substring(e),h=t=>0===t.name.indexOf("x-"),x=t=>0===t.tagName.indexOf("X-"),y=t=>"TEMPLATE"===t.tagName,m=t=>!!nt[t.tagName]||y(t),w={i(t){let e=this;e.o||(e.o=t||{}),e.u||(e.u=new Set)},p(){this.h()},m(t,e,n){let o=this,r=e.length-1,c=n;for(;r>=0;){const l=e[r],i=t[l.v];if(l.$&&(i.S=l.T,(n||o.u).add(i),s&&s(i.tagName)),!n)for(const[t,e]of l.j){const n=e.L(o,i,e.M,t);n&&o.u.add(n)}if(l.T){(!l.$||(c=!m(i)&&(i.u=new Set)))&&o.m(p(i),l.T,c)}r--}},h(){for(const t of this.u)t.p&&t.p();this.u.clear()}};function b(t){this.i(t)}b.prototype=w;let E=null;const g=t=>{const e=t=>{if(void 0!==t){const n=E;E=null,e.value=t;for(const t of e.k)t();E=n}else E&&(e.k.add(E),E.C.add(e.k));return e.value};return e.value=t,e.O=!0,e.k=new Set,e},v=t=>{const e=E;return E=t,E.C=new Set,E.p=(t=>()=>{for(const e of t.C)e.delete(t)})(E),t(),E=e,t};let $=c.createComment(""),S=l("template"),T=c.createDocumentFragment();const j=t=>{let e=u(t).firstChild;for(;e;){const t=a(e);1!==e.nodeType&&e.remove(),e=t}},L=()=>{},M=(t,...e)=>t.reduce(((n,o,s)=>n+(o+(s===t.length-1?"":e[s]))),""),k=l("style"),C="css-x";let O=1;const R=(t,e)=>"$"+(e||O)+t,V=(t,...e)=>{if("string"==typeof t)return`${C}="${R(t,O)}"`;{const n=M(t,e);k.textContent+=n,k.parentElement||c.head.appendChild(k)}},H=(t,e,n)=>{const o=n,s=t.R;e.setAttribute(C,R(o,s))},U=(t,e,n)=>{const o=n,s=t.useRef(o);let r=!0;return v((()=>{const t=s();if(r){for(const n of t)n(e);r=!1}else t[t.length-1](e)}))},X=(t,e,n)=>{const o=e.style.display;return v((()=>{n(t.o)?o?e.style.display=o:e.style.removeProperty("display"):e.style.display="none"}))},A=(t,e,n)=>v((()=>e.textContent=n(t.o))),P=(t,e,n,o)=>v((()=>e.setAttribute(o,n(t.o)))),q=t=>"x-text"===t?A:"x-show"===t?X:"x-ref"===t?U:"x-css"===t?H:P,z=(t,e,n,o)=>{e.o||(e.o={});let s=null;const r={V:(t,e)=>s={H:t,U:e}},c=v((()=>{const s=e.o[o],c=n(t.o);s&&s.O?r.V(s,c):e.o[o]=c}));return s&&s.H(s.U),r.V=(t,e)=>t(e),c},B={},D=t=>{if(B[t])return B[t];let e=Object.getPrototypeOf((function(){})).constructor,n=/^[\n\s]*if.*\(.*\)/.test(t.trim())||/^(let|const)\s/.test(t.trim())?`(()=>{ ${t} })()`:t;let o=(()=>{try{let o=new e(["scope"],`with(scope){return ${n}};`);return Object.defineProperty(o,"name",{value:`VifExp "${t}"`}),o}catch(e){return console.error("VifExp error : "+t,e),!1}})();return B[t]=o,o},F=(t,e,n)=>{_(e);let o=[];const s="item",r=e.getAttribute(s)||s;return v((()=>{const s=n(t.o);((t,e,n,o,s)=>{let r=0;const c=n.length,l=o.length;let i=l-c;for(;r0;)W(e,t,r,s,o[r]),i--,r++;i<0&&Z(e,r,r-i)})(t.o,e,o,s,r),o=s.slice()}))},G=(t,e,n)=>{_(e);let o=!1;return v((()=>{const s=!!n(t.o);s!==o&&(o=s,s?W(e,t.o,0):Z(e,0))}))};let I=location;const J=()=>I.pathname+I.search,K=g(J());addEventListener("popstate",(()=>{I=location,K(J())}));const N=t=>{if("string"==typeof t){const e=new URL(t,I);if(I.href!==e.href)return I=e,history.pushState({},"",I),K(J())}else{t.preventDefault();const e=t.currentTarget.href;if(e)return N(e)}};N.route=K;const Q=(t,e,n)=>{_(e);const o=new RegExp(n||"."),s="params",r=e.getAttribute(s)||s;let c=null;return v((()=>{const n=K().match(o)||null;n!==c&&(n&&c?Y(e,0,n):n?W(e,t.o,0,r,n):Z(e,0)),c=n}))},W=(t,e,n,o,s)=>{const r=t.X;let c=r[n+1];const l=i(u(t),!0);c?c.H&&c.H(s):c=r[n+1]=((t,e,n,o)=>{const s=n&&g(o);return s&&(s.index=e),{A:new b(n?{...t,[n]:s}:t),H:s}})(e,n,o,s),c.P=l.lastChild,t.S&&c.A.m(f(l),t.S);const p=r[n].P;p.parentNode.insertBefore(l,a(p))},Y=(t,e,n)=>{t.X[e+1].H(n)},Z=(t,e,n)=>{const o=t.X,s=o[e].P;for(;e++{j(t);const e=t.X=[{P:i($)}];u(t).append(i($)),t.p=()=>{for(let t=1;t{const n=[];for(let s=0;s0&&n};class et extends HTMLElement{constructor(){super(),this.i(),this.q={}}onMount(){}connectedCallback(){let t=this,e=t.o;for(const n of t.attributes)if(h(n)){const t=d(n,2);e[t]=g(e[t])}else e[n.name]=n.value||!0;t.onMount({props:e}),t.B()}onUnmount(){}p(){let t=this;t.onUnmount({props:t.o}),t.h()}B(){let t=this;const e=t.D;let n=e.F,o=e.T,s=e.R;const r=n?L:M,c=s?L:V,l=e.G,a={html:r,css:c,props:t.o},p=l.call(t,a);if("string"==typeof p?(n=e.F=(t=>{let e=i(S);return e.innerHTML=t,j(e),u(e)})(p),o=e.T=tt(f(n))):n||(n=p&&p!==t?(t=>{let e=i(T);return e.append(...t),e})(p):t,o=t.S||tt(t.l||f(n))),t.R=e.R=s||O++,e.F&&(n=i(n,!0)),o&&t.m(t.l||f(n),o),n!==t){const e=t.parentNode;e.l||(e.l=[].slice.call(f(e))),t.replaceWith(n)}}useEffect(t){this.u.add(v(t))}useRef(t,e,n){const o=this.q,s=o[t]||(o[t]=g([]));if(!e)return s;{const t=s.value;n?t[(t.length||1)-1]=e:t.push(e),s(t)}}}Object.assign(et.prototype,w);const nt={},ot=g(localStorage.getItem("locale")||navigator.language),st=(t,e)=>t[e]||t[t.default],rt=t=>{const e=g();let n=[];return e.onload=t=>{e()?t():n.push(t)},v((()=>{const[o,s]=ot().split("-"),r=st(st(t,o),s);r&&r().then((t=>{e(t.default),n&&(n=n.forEach((t=>t())))}))})),e};rt.locale=ot,t.useDefine=(t,e)=>{const n="X-"+t.toUpperCase();return nt[n]=class extends et{constructor(){super()}},nt[n].G=e,nt[n].prototype.D=nt[n],customElements.define(`x-${t}`,nt[n]),nt[n]},t.useEffect=v,t.useI18n=rt,t.useNavigate=N,t.useObserve=t=>{o={...t,...o},s=r},t.useSignal=g})); diff --git a/src/reactivity/signal.js b/src/reactivity/signal.js index e0e667b..20060af 100644 --- a/src/reactivity/signal.js +++ b/src/reactivity/signal.js @@ -23,12 +23,18 @@ export const signal = (value) => { const currentSignal = (dataUpdated) => { // if new data is sent if (dataUpdated !== undefined) { - // update the value + // store the previous reactive value + const previousValue = currentReactive; + // clear the currentReactive to prevent deep binding + currentReactive = null; + // update signal value currentSignal.value = dataUpdated; // run all the dependencies for (const callback of currentSignal.reactives) { callback(); } + // set currentReactive value back to previousValue + currentReactive = previousValue; } else if (currentReactive) { // if signal is running inside of a reactive function // we create all necessary dependencies @@ -73,10 +79,10 @@ export const disconnectReactive = (reactive) => () => { * @returns {VIF.Reactive} */ export const reactive = (callback) => { - // store the previous value + // store the previous reactive value const previousValue = currentReactive; - // update currentReactive function and create a dependency Array + // update currentReactive function and create a dependency Set currentReactive = callback; /** * setup dependencies diff --git a/tests/benchmarks/vs-lit.js b/tests/benchmarks/vs-lit.js deleted file mode 100644 index c611a33..0000000 --- a/tests/benchmarks/vs-lit.js +++ /dev/null @@ -1,4 +0,0 @@ -// create a benchmark suit -// use settimeout to asynchronous libraries like lit.js -// else use performance.now() -// finally display a css freezer indicator diff --git a/tests/data-test.js b/tests/data-test.js new file mode 100644 index 0000000..e4dd7c5 --- /dev/null +++ b/tests/data-test.js @@ -0,0 +1,18 @@ +import { useDefine, useSignal } from "../src/bundle.js"; + +function App({ props }) { + props.count = useSignal(10); + + setTimeout(() => { + props.count(20); + }, 2000); + + this.useEffect(() => console.log("app " + props.count())); +} + +function Button({ props }) { + this.useEffect(() => console.log("button " + props.count())); +} + +useDefine("button", Button); +useDefine("app", App); diff --git a/tests/garbage/lit.js b/tests/garbage/lit.js deleted file mode 100644 index fa72c70..0000000 --- a/tests/garbage/lit.js +++ /dev/null @@ -1,104 +0,0 @@ -import { - LitElement, - html, -} from "https://cdn.jsdelivr.net/gh/lit/dist@3/core/lit-core.min.js"; - -let id = 0; - -function _random(max) { - return Math.round(Math.random() * 1000) % max; -} - -function buildData(count = 1000) { - var adjectives = [ - "pretty", - "large", - "big", - "small", - "tall", - "short", - "long", - "handsome", - "plain", - "quaint", - "clean", - "elegant", - "easy", - "angry", - "crazy", - "helpful", - "mushy", - "odd", - "unsightly", - "adorable", - "important", - "inexpensive", - "cheap", - "expensive", - "fancy", - ]; - var colours = [ - "red", - "yellow", - "blue", - "green", - "pink", - "brown", - "purple", - "brown", - "white", - "black", - "orange", - ]; - var nouns = [ - "table", - "chair", - "house", - "bbq", - "desk", - "car", - "pony", - "cookie", - "sandwich", - "burger", - "pizza", - "mouse", - "keyboard", - ]; - var data = []; - for (var i = 0; i < count; i++) - data.push({ - id: id++, - label: - adjectives[_random(adjectives.length)] + - " " + - colours[_random(colours.length)] + - " " + - nouns[_random(nouns.length)], - }); - return data; -} - -class LitApp extends LitElement { - static properties = { - array: {}, - }; - constructor() { - super(); - this.array = []; - setTimeout(() => { - this.array = this.array.length ? [] : buildData(10000); - }, 1000); - setTimeout(() => { - this.array = this.array.length ? [] : buildData(10000); - }, 2000); - setTimeout(() => { - this.array = this.array.length ? [] : buildData(10000); - }, 3000); - } - render() { - return html`${this.array.map((item) => html`

${item.label}

`)}`; - } -} - -customElements.define("lit-app", LitApp); diff --git a/tests/garbage/vif.js b/tests/garbage/vif.js deleted file mode 100644 index 40cdd55..0000000 --- a/tests/garbage/vif.js +++ /dev/null @@ -1,92 +0,0 @@ -import { useDefine, useSignal } from "../../src/bundle.js"; - -let id = 0; - -function _random(max) { - return Math.round(Math.random() * 1000) % max; -} - -function buildData(count = 1000) { - var adjectives = [ - "pretty", - "large", - "big", - "small", - "tall", - "short", - "long", - "handsome", - "plain", - "quaint", - "clean", - "elegant", - "easy", - "angry", - "crazy", - "helpful", - "mushy", - "odd", - "unsightly", - "adorable", - "important", - "inexpensive", - "cheap", - "expensive", - "fancy", - ]; - var colours = [ - "red", - "yellow", - "blue", - "green", - "pink", - "brown", - "purple", - "brown", - "white", - "black", - "orange", - ]; - var nouns = [ - "table", - "chair", - "house", - "bbq", - "desk", - "car", - "pony", - "cookie", - "sandwich", - "burger", - "pizza", - "mouse", - "keyboard", - ]; - var data = []; - for (var i = 0; i < count; i++) - data.push({ - id: id++, - label: - adjectives[_random(adjectives.length)] + - " " + - colours[_random(colours.length)] + - " " + - nouns[_random(nouns.length)], - }); - return data; -} - -function App({ props }) { - props.array = useSignal([]); - setTimeout(() => { - props.array(props.array.value.length ? [] : buildData(10000)); - }, 1000); - setTimeout(() => { - props.array(props.array.value.length ? [] : buildData(10000)); - }, 2000); - setTimeout(() => { - props.array(props.array.value.length ? [] : buildData(10000)); - }, 3000); -} - -useDefine("app", App); diff --git a/tests/garbage/index.html b/tests/index.html similarity index 65% rename from tests/garbage/index.html rename to tests/index.html index f96c0f2..f5b4603 100644 --- a/tests/garbage/index.html +++ b/tests/index.html @@ -4,9 +4,9 @@ Garbage testing - + - +

Primary tests here

@@ -18,11 +18,10 @@

Primary tests here

- + + + -