sinho 0.2.0 → 0.2.2
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/dist/bundle.d.ts +3 -2
- package/dist/bundle.js +55 -45
- package/dist/bundle.min.js +1 -1
- package/dist/scope.d.ts +3 -2
- package/dist/scope.js +55 -45
- package/dist/scope.js.map +1 -1
- package/package.json +1 -1
- package/src/scope.ts +57 -52
package/dist/bundle.d.ts
CHANGED
|
@@ -40,9 +40,10 @@ interface SubscopeOptions {
|
|
|
40
40
|
details?: object;
|
|
41
41
|
}
|
|
42
42
|
interface Effect {
|
|
43
|
+
_scope: Scope;
|
|
44
|
+
_pure: boolean;
|
|
43
45
|
_clean?: Cleanup;
|
|
44
46
|
_deps: Set<Signal<unknown>>;
|
|
45
|
-
_scope: Scope;
|
|
46
47
|
_run(): void;
|
|
47
48
|
}
|
|
48
49
|
/**
|
|
@@ -71,7 +72,7 @@ declare const useSignal: (<T>(value: T, opts?: SetSignalOptions) => readonly [Si
|
|
|
71
72
|
* and updated at the same time.
|
|
72
73
|
*/
|
|
73
74
|
declare const useBatch: <T>(fn: () => T) => T;
|
|
74
|
-
declare
|
|
75
|
+
declare const flushBatch: () => void;
|
|
75
76
|
/**
|
|
76
77
|
* Creates a memoized signal.
|
|
77
78
|
*
|
package/dist/bundle.js
CHANGED
|
@@ -62,10 +62,7 @@ const useSignal = (value, opts) => {
|
|
|
62
62
|
value = newValue;
|
|
63
63
|
}
|
|
64
64
|
else {
|
|
65
|
-
currBatch._setters.push(() =>
|
|
66
|
-
value = newValue;
|
|
67
|
-
return signal;
|
|
68
|
-
});
|
|
65
|
+
currBatch._setters.push(() => (value = newValue));
|
|
69
66
|
}
|
|
70
67
|
if (!innerOpts?.silent) {
|
|
71
68
|
signal._effects.forEach((effect) => currBatch._effects.add(effect));
|
|
@@ -85,43 +82,42 @@ const useSignal = (value, opts) => {
|
|
|
85
82
|
* and updated at the same time.
|
|
86
83
|
*/
|
|
87
84
|
const useBatch = (fn) => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
85
|
+
if (currBatch)
|
|
86
|
+
return fn();
|
|
87
|
+
currBatch = { _setters: [], _effects: new Set() };
|
|
88
|
+
try {
|
|
89
|
+
const result = fn();
|
|
93
90
|
flushBatch();
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
94
|
currBatch = undefined;
|
|
95
95
|
}
|
|
96
|
-
return result;
|
|
97
96
|
};
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
while (currBatch &&
|
|
97
|
+
const flushBatch = () => {
|
|
98
|
+
a: while (currBatch &&
|
|
101
99
|
(currBatch._setters.length > 0 || currBatch._effects.size > 0)) {
|
|
102
100
|
// Clean effect subscope
|
|
103
|
-
|
|
104
|
-
currBatch._effects = new Set();
|
|
105
|
-
effects.forEach((effect) => effect._clean?.());
|
|
101
|
+
currBatch._effects.forEach((effect) => effect._clean?.());
|
|
106
102
|
// Run signal updates
|
|
107
|
-
|
|
108
|
-
for (const setter of currBatch._setters) {
|
|
109
|
-
const signal = setter();
|
|
110
|
-
mutatedSignals.add(signal);
|
|
111
|
-
}
|
|
103
|
+
currBatch._setters.forEach((setter) => setter());
|
|
112
104
|
currBatch._setters = [];
|
|
113
|
-
// Run
|
|
114
|
-
for (const effect of
|
|
115
|
-
if (
|
|
116
|
-
[...effect._deps].every((dep) => mutatedSignals.has(dep))) {
|
|
105
|
+
// Run next effect
|
|
106
|
+
for (const effect of currBatch._effects) {
|
|
107
|
+
if (effect._pure) {
|
|
117
108
|
effect._run();
|
|
109
|
+
currBatch._effects.delete(effect);
|
|
110
|
+
continue a;
|
|
118
111
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
112
|
+
}
|
|
113
|
+
for (const effect of currBatch._effects) {
|
|
114
|
+
effect._run();
|
|
115
|
+
currBatch._effects.delete(effect);
|
|
116
|
+
break;
|
|
122
117
|
}
|
|
123
118
|
}
|
|
124
|
-
}
|
|
119
|
+
};
|
|
120
|
+
let pureEffectFlag = false;
|
|
125
121
|
/**
|
|
126
122
|
* Creates an effect which will rerun when any accessed signal changes.
|
|
127
123
|
*
|
|
@@ -131,6 +127,7 @@ const useEffect = (fn, deps) => {
|
|
|
131
127
|
const untracked = !!deps;
|
|
132
128
|
const effect = {
|
|
133
129
|
_scope: currScope,
|
|
130
|
+
_pure: pureEffectFlag,
|
|
134
131
|
_deps: new Set(),
|
|
135
132
|
_run() {
|
|
136
133
|
const prevEffect = currEffect;
|
|
@@ -179,10 +176,16 @@ const useEffect = (fn, deps) => {
|
|
|
179
176
|
const useMemo = (fn, opts) => {
|
|
180
177
|
const [memo, setMemo] = useSignal();
|
|
181
178
|
let firstTime = true;
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
179
|
+
pureEffectFlag = true;
|
|
180
|
+
try {
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
setMemo(fn, firstTime ? { ...opts, force: true } : opts);
|
|
183
|
+
firstTime = false;
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
pureEffectFlag = false;
|
|
188
|
+
}
|
|
186
189
|
return memo;
|
|
187
190
|
};
|
|
188
191
|
/**
|
|
@@ -192,21 +195,28 @@ const useMemo = (fn, opts) => {
|
|
|
192
195
|
* @returns A function to manually destroy the subscope.
|
|
193
196
|
*/
|
|
194
197
|
const useSubscope = (fn, opts) => {
|
|
198
|
+
const prevBatch = currBatch;
|
|
199
|
+
currBatch = undefined;
|
|
195
200
|
const parent = currScope;
|
|
196
201
|
const scope = createScope(parent);
|
|
197
202
|
Object.assign(scope._details, opts?.details);
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
203
|
+
try {
|
|
204
|
+
parent._subscopes.push(scope);
|
|
205
|
+
const result = scope._run(fn);
|
|
206
|
+
return [
|
|
207
|
+
result,
|
|
208
|
+
() => {
|
|
209
|
+
const index = parent._subscopes.indexOf(scope);
|
|
210
|
+
if (index >= 0) {
|
|
211
|
+
parent._subscopes.splice(index, 1);
|
|
212
|
+
}
|
|
213
|
+
scope._cleanup();
|
|
214
|
+
},
|
|
215
|
+
];
|
|
216
|
+
}
|
|
217
|
+
finally {
|
|
218
|
+
currBatch = prevBatch;
|
|
219
|
+
}
|
|
210
220
|
};
|
|
211
221
|
/**
|
|
212
222
|
* Creates a new signal with write capabilities.
|
package/dist/bundle.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const t=t=>({t:t,o:[],i:[],l:{...t?.l},u(t){const n=o;o=this;try{return t()}finally{o=n}},h(){for(let t=this.i.length-1;t>=0;t--)this.i[t].h();this.i=[];for(let t=this.o.length-1;t>=0;t--){const n=this.o[t];n._?.(),n.u=()=>{},n.p.forEach((t=>t.o.delete(n))),n.p.clear()}this.o=[]}});let n,e,o=t(),s=!1;const r=()=>o,c=(t,o)=>{const r=()=>(!s&&n&&(n.p.add(r),r.o.add(n)),r.peek());r.o=new Set,r.peek=()=>t;const c=(n,s)=>{if(s={...o,...s},e){const o="function"==typeof n?n(r.peek()):n;(s?.force||o!==r.peek())&&(s?.force?t=o:e.m.push((()=>
|
|
1
|
+
const t=t=>({t:t,o:[],i:[],l:{...t?.l},u(t){const n=o;o=this;try{return t()}finally{o=n}},h(){for(let t=this.i.length-1;t>=0;t--)this.i[t].h();this.i=[];for(let t=this.o.length-1;t>=0;t--){const n=this.o[t];n._?.(),n.u=()=>{},n.p.forEach((t=>t.o.delete(n))),n.p.clear()}this.o=[]}});let n,e,o=t(),s=!1;const r=()=>o,c=(t,o)=>{const r=()=>(!s&&n&&(n.p.add(r),r.o.add(n)),r.peek());r.o=new Set,r.peek=()=>t;const c=(n,s)=>{if(s={...o,...s},e){const o="function"==typeof n?n(r.peek()):n;(s?.force||o!==r.peek())&&(s?.force?t=o:e.m.push((()=>t=o)),s?.silent||r.o.forEach((t=>e.o.add(t))))}else i((()=>c(n,s)))};return[r,c]},i=t=>{if(e)return t();e={m:[],o:new Set};try{const n=t();return l(),n}finally{e=void 0}},l=()=>{t:for(;e&&(e.m.length>0||e.o.size>0);){e.o.forEach((t=>t._?.())),e.m.forEach((t=>t())),e.m=[];for(const t of e.o)if(t.v){t.u(),e.o.delete(t);continue t}for(const t of e.o){t.u(),e.o.delete(t);break}}};let u=!1;const f=(t,e)=>{const r=!!e,c={S:o,v:u,p:new Set,u(){const o=n,c=s;n=this;try{this.p.forEach((t=>t.o.delete(this))),this.p.clear(),e&&(s=!1,e.forEach((t=>t()))),s=r,this._?.();const n=this.S.u((()=>i(t)));this._=n?()=>{this.S.u((()=>i(n))),this._=null}:null}finally{n=o,s=c}}};o.o.push(c),c.u(),c.p.size||c._||o.o.pop()},a=(t,n)=>{const[e,o]=c();let s=!0;u=!0;try{f((()=>{o(t,s?{...n,force:!0}:n),s=!1}))}finally{u=!1}return e},d=(n,s)=>{const r=e;e=void 0;const c=o,i=t(c);Object.assign(i.l,s?.details);try{c.i.push(i);return[i.u(n),()=>{const t=c.i.indexOf(i);t>=0&&c.i.splice(t,1),i.h()}]}finally{e=r}},h=(t,n)=>{const[e,o]=c(t,n);return e.set=o,e},_={upgrade:t=>()=>_.get(t),get:t=>"function"==typeof t?t():t,peek(t){const n=s;s=!0;try{return this.get(t)}finally{s=n}}},p=(t={})=>({M:[],k(t){return this.C?.next().value??t()},...t}),m=()=>{const t=r();return t.l.N??=p()},y=(t,n)=>{const e=m(),o=p({...e,...t}),[s,r]=d(n,{details:{N:o}});return f((()=>r)),s},w=t=>(t[0]??"").toLowerCase()+t.slice(1).replace(/[A-Z]/g,(t=>"-"+t.toLowerCase())),b=t=>t.startsWith("on:")?t.slice(3):w(t.slice(2)),g=Symbol(),v=(t,n)=>({[g]:Math.random().toString(36).slice(2),j:t,H:n}),x=t=>!!t?.[g],S=(t,n,e)=>{n.addEventListener(t[g],(t=>{const n=_.get(e);void 0!==n&&(t.stopPropagation(),t.detail(n))}))},M=t=>{const n=m();return a((()=>{let e=t.j;return n.L?.dispatchEvent(new CustomEvent(t[g],{detail:t=>e=t,bubbles:!0,composed:!0})),e}))},k=(t,n)=>({T:"p",A:t,...n}),C=(t=CustomEvent)=>({T:"e",O:t}),E=Symbol();let N;const j=(t,n)=>{N?N.push([t,n]):f(t,n)},H=(t,n={},e={})=>{const o=[],s=new Map;for(const t in n){const e=n[t];if("p"==e.T&&e.attribute){"function"==typeof e.attribute&&(e.attribute={transform:e.attribute});const n=e.attribute={name:w(t),static:!1,transform:t=>t,...e.attribute};s.set(n.name,{name:t,meta:e}),n.static||o.push(n.name)}}e.shadow??={mode:"open"};class i extends HTMLElement{static[E]={D:t};static observedAttributes=o;props={};events={};[E]={};constructor(){super();for(const t in n){const e=n[t];if("p"==e.T){const n=x(e.A)?e.A:null,[o,s]=c(n?void 0:e.A);this.props[t]=o,n&&S(n,this,o),Object.defineProperty(this,t,{get:o.peek,set:t=>s((()=>t),{force:!0})})}else if("e"==e.T&&t.startsWith("on")){const n=b(t);this.events[t]=t=>this.dispatchEvent(new e.O(n,t))}}}connectedCallback(){const t=(n=this,e.shadow?n.shadowRoot??n.attachShadow(e.shadow):n);var n;this[E].I=d((()=>y({$:!1,L:this,C:t.childNodes.values()},(()=>{this[E].S=r();const n=N;N=[];try{t?.append(...this.render().build()),N.forEach((([t,n])=>f(t,n)))}finally{N=n}}))))[1]}disconnectedCallback(){this[E].I?.()}attributeChangedCallback(t,n,e){const o=s.get(t);o&&(this[o.name]=null!=e?o.meta.attribute.transform.call(this,e):x(o.meta.A)?void 0:o.meta.A)}}return i},L=t=>!!t?.[E],T=(...t)=>{const[n,e]="string"==typeof t[0]?[t[0],t.slice(1)]:["",t];for(const t of e)customElements.define(n+t[E].D,t)},A=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,O=(t,n,e)=>{"-"==n[0]?t.style.setProperty(n,""+e):t.style[n]=null==e?"":"number"!=typeof e||A.test(n)?""+e:e+"px"},D=(t,n,e,o)=>{const s=null==e||!1===e&&!n.includes("-");if(n.startsWith("prop:"))t[n.slice(5)]=e;else if(n.startsWith("attr:"))n=n.slice(5),s?t.removeAttribute(n):t.setAttribute(n,e);else if(!["innerHTML","outerHTML"].includes(n)){if(!["tabIndex","role",...o?["width","height","href","list","form","download","rowSpan","colSpan"]:[]].includes(n)&&n in t)try{return void(t[n]=e)}catch(t){}"function"==typeof e||(s?t.removeAttribute(n):t.setAttribute(n,e))}},I=t=>({build(){const n=t();return n.build?.()??n}}),$=({text:t,marker:n})=>I((()=>{const e=m(),o=n&&e.k((()=>document.createComment(""))),s=e.k((()=>document.createTextNode("")));return f((()=>{const n=""+(_.get(t)??"");s.textContent!=n&&(s.textContent=n)})),o?[o,s]:[s]})),z=({children:t})=>I((()=>Array.isArray(t)?t.flatMap((t=>z({children:t}).build())):null==t?[]:"object"==typeof t?t:$({text:t}))),P=(t,n,e,o)=>{const{ref:s,style:c,children:l,dangerouslySetInnerHTML:u,...a}=e;for(const n in c??{}){const e=c[n];f((()=>{O(t,n,_.get(e))}))}for(const n in a){const e=a[n];if(n.startsWith("on")){const o=r(),s=t=>{o.u((()=>i((()=>e(t)))))},c=b(n);f((()=>(t.addEventListener(c,s),()=>t.removeEventListener(c,s))))}else f((()=>{D(t,n,_.get(e),o)}))}return u&&f((()=>{const n=_.get(u).__html;t.innerHTML!=n&&(t.innerHTML=n)})),s&&f((()=>(s.set(t),()=>s.set(void 0)))),null!=e.children&&t.append(...y({$:n,C:t.childNodes.values()},(()=>z({children:e.children}).build()))),t},V=(t,n={},e)=>(null!=e&&(n.children=e),L(t)?((t,n)=>I((()=>{const e=m().k((()=>new t));return customElements.upgrade(e),P(e,!1,n),[e]})))(t,n):"function"==typeof t?I((()=>t(n))):((t,n={})=>I((()=>{const e=m(),o="svg"==t||!!e.$;return[P(e.k((()=>o?document.createElementNS("http://www.w3.org/2000/svg",t):document.createElement(t))),o,n,!0)]})))(t,n)),Z=new Proxy(V,{get:(t,n)=>(e,o)=>t(n,e,o)}),q=(t,n)=>{const[e,o]=c({P:[],V:new Map});let s=new Map;return f((()=>{const e=[],r=s,c=((t,n)=>{const e=new Map;for(let o=0;o<t.length;o++){const s=n(t[o],o);if(e.has(s))throw Error(`Duplicate key '${s}'`);e.set(s,o)}return e})(t(),n),i=(t=NaN)=>e.map((t=>"r"==t.Z?n=>n<t.q?n:n==t.q?NaN:n-1:"a"==t.Z?n=>n<t.q?n:n+1:"m"==t.Z?n=>t.B<=n&&n<t.F?n+1:n==t.F?t.B:n:t=>t)).reduce(((t,n)=>n(t)),t);for(const t of r.keys()){const n=i(r.get(t));c.has(t)||e.push({Z:"r",G:t,q:n})}for(let o=0;o<t().length;o++){const s=n(t()[o],o),c=i(r.get(s));isNaN(c)?e.push({Z:"a",G:s,q:o}):c!=o&&e.push({Z:"m",G:s,F:c,B:o})}e.length>0&&o({P:e,V:c}),s=c})),e},B=t=>I((()=>{const n=m(),e=_.upgrade(t.each??[]),o=n.k((()=>document.createComment(""))),s=t.key??((t,n)=>n),r=[o],i=new Map,l=q(e,s),u=t=>{for(let n=t-1;n>=0;n--){const n=s(e()[t-1],t-1),o=i.get(n)?.J??[];if(o.length>0)return o[o.length-1]}return o};return f((()=>{for(const n of l().P)if("r"==n.Z){const{J:t=[],I:e}=i.get(n.G)??{};e?.();const o=r.indexOf(t[0]);o>0&&r.splice(o,t.length),t.forEach((t=>t.parentNode?.removeChild(t))),i.delete(n.G)}else if("a"==n.Z){let o=[];const[,s]=d((()=>{const[s,i]=c(n.q),[a,d]=c(e()[n.q]);f((()=>{0<=s()&&s()<e().length&&d((()=>e()[s()]))})),f((()=>{const t=l().V.get(n.G);null!=t&&i(t)})),o=t.children?.(a,s,e).build()??[];const h=u(n.q),_=r.indexOf(h);_>=0&&r.splice(_+1,0,...o),o.forEach((t=>h.parentNode?.insertBefore(t,h.nextSibling)))}));i.set(n.G,{J:o,I:s})}else if("m"==n.Z){const{J:t=[]}=i.get(n.G)??{},e=r.indexOf(t[0]);e>=0&&r.splice(e,t.length);const o=u(n.B),s=r.indexOf(o);s>=0&&r.splice(s+1,0,...t),t.forEach((t=>o.parentNode?.insertBefore(t,o.nextSibling)))}}),[l]),r})),F=t=>(m().M=[],G({condition:t.condition,children:t.children})),G=t=>{const n=m(),e=n.M,o=a((()=>e.every((t=>!t()))&&_.get(t.condition)));return n.M=[...e,o],y({M:[]},(()=>I((()=>{const e=n.k((()=>document.createComment(""))),s=[e],r=a((()=>o()?z({children:t.children}):null));let c=[];return f((()=>{c.forEach((t=>t.parentNode?.removeChild(t))),s.length=1;const[,t]=d((()=>{c=r()?.build()??[],e.after(...c),s.push(...c)}));return t}),[r]),s}))))},J=({children:t})=>G({condition:!0,children:t}),K=({mount:t,children:n})=>I((()=>y({C:void 0},(()=>{const e=z({children:n}).build();return f((()=>(e.forEach((n=>t.appendChild(n))),()=>{e.forEach((t=>t.parentNode?.removeChild(t)))}))),[]})))),Q=Symbol(),R=new Map,U=t=>{const n=t.children;if("function"==typeof n){const e=V("style",{},$({text:n,marker:!1}));return t.light?K({mount:document.head,children:e}):e}if(n){const o=m(),s=t.light?document:o.L?.shadowRoot??document,r=((t,n,e)=>{if(!R.has(n)){const t=new CSSStyleSheet;t.replaceSync(n),R.set(n,{K:t,R:0})}const o=R.get(n);o.R++,t.has(n)||t.set(n,{K:o.K,R:0});const s=t.get(n);return s.R++,f((()=>()=>{--s.R||(t.delete(n),e()),--o.R||R.delete(n)})),s.K})((e=s,e[Q]??=new Map),n,(()=>{s.adoptedStyleSheets=s.adoptedStyleSheets.filter((t=>t!=r))}));s.adoptedStyleSheets.push(r)}var e;return z({})},W=(t,...n)=>{const e=()=>t.reduce(((t,e,o)=>t+e+(_.get(n[o])??"")),"");return n.some((t=>"function"==typeof t))?e:e()},X=(t,n,e)=>(n&&null!=e&&(n.key=e),V(t,n));export{H as Component,J as Else,G as ElseIf,B as For,z as Fragment,F as If,_ as MaybeSignal,K as Portal,U as Style,v as createContext,V as createElement,W as css,T as defineComponents,C as event,l as flushBatch,Z as h,L as isComponent,X as jsx,X as jsxDEV,X as jsxs,k as prop,i as useBatch,M as useContext,j as useEffect,a as useMemo,h as useRef,c as useSignal,d as useSubscope};
|
package/dist/scope.d.ts
CHANGED
|
@@ -40,9 +40,10 @@ export interface SubscopeOptions {
|
|
|
40
40
|
details?: object;
|
|
41
41
|
}
|
|
42
42
|
interface Effect {
|
|
43
|
+
_scope: Scope;
|
|
44
|
+
_pure: boolean;
|
|
43
45
|
_clean?: Cleanup;
|
|
44
46
|
_deps: Set<Signal<unknown>>;
|
|
45
|
-
_scope: Scope;
|
|
46
47
|
_run(): void;
|
|
47
48
|
}
|
|
48
49
|
/**
|
|
@@ -71,7 +72,7 @@ export declare const useSignal: (<T>(value: T, opts?: SetSignalOptions) => reado
|
|
|
71
72
|
* and updated at the same time.
|
|
72
73
|
*/
|
|
73
74
|
export declare const useBatch: <T>(fn: () => T) => T;
|
|
74
|
-
export declare
|
|
75
|
+
export declare const flushBatch: () => void;
|
|
75
76
|
/**
|
|
76
77
|
* Creates an effect which will rerun when any accessed signal changes.
|
|
77
78
|
*
|
package/dist/scope.js
CHANGED
|
@@ -62,10 +62,7 @@ export const useSignal = (value, opts) => {
|
|
|
62
62
|
value = newValue;
|
|
63
63
|
}
|
|
64
64
|
else {
|
|
65
|
-
currBatch._setters.push(() =>
|
|
66
|
-
value = newValue;
|
|
67
|
-
return signal;
|
|
68
|
-
});
|
|
65
|
+
currBatch._setters.push(() => (value = newValue));
|
|
69
66
|
}
|
|
70
67
|
if (!innerOpts?.silent) {
|
|
71
68
|
signal._effects.forEach((effect) => currBatch._effects.add(effect));
|
|
@@ -85,43 +82,42 @@ export const useSignal = (value, opts) => {
|
|
|
85
82
|
* and updated at the same time.
|
|
86
83
|
*/
|
|
87
84
|
export const useBatch = (fn) => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
85
|
+
if (currBatch)
|
|
86
|
+
return fn();
|
|
87
|
+
currBatch = { _setters: [], _effects: new Set() };
|
|
88
|
+
try {
|
|
89
|
+
const result = fn();
|
|
93
90
|
flushBatch();
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
finally {
|
|
94
94
|
currBatch = undefined;
|
|
95
95
|
}
|
|
96
|
-
return result;
|
|
97
96
|
};
|
|
98
|
-
export
|
|
99
|
-
|
|
100
|
-
while (currBatch &&
|
|
97
|
+
export const flushBatch = () => {
|
|
98
|
+
a: while (currBatch &&
|
|
101
99
|
(currBatch._setters.length > 0 || currBatch._effects.size > 0)) {
|
|
102
100
|
// Clean effect subscope
|
|
103
|
-
|
|
104
|
-
currBatch._effects = new Set();
|
|
105
|
-
effects.forEach((effect) => effect._clean?.());
|
|
101
|
+
currBatch._effects.forEach((effect) => effect._clean?.());
|
|
106
102
|
// Run signal updates
|
|
107
|
-
|
|
108
|
-
for (const setter of currBatch._setters) {
|
|
109
|
-
const signal = setter();
|
|
110
|
-
mutatedSignals.add(signal);
|
|
111
|
-
}
|
|
103
|
+
currBatch._setters.forEach((setter) => setter());
|
|
112
104
|
currBatch._setters = [];
|
|
113
|
-
// Run
|
|
114
|
-
for (const effect of
|
|
115
|
-
if (
|
|
116
|
-
[...effect._deps].every((dep) => mutatedSignals.has(dep))) {
|
|
105
|
+
// Run next effect
|
|
106
|
+
for (const effect of currBatch._effects) {
|
|
107
|
+
if (effect._pure) {
|
|
117
108
|
effect._run();
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
currBatch._effects.add(effect);
|
|
109
|
+
currBatch._effects.delete(effect);
|
|
110
|
+
continue a;
|
|
121
111
|
}
|
|
122
112
|
}
|
|
113
|
+
for (const effect of currBatch._effects) {
|
|
114
|
+
effect._run();
|
|
115
|
+
currBatch._effects.delete(effect);
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
123
118
|
}
|
|
124
|
-
}
|
|
119
|
+
};
|
|
120
|
+
let pureEffectFlag = false;
|
|
125
121
|
/**
|
|
126
122
|
* Creates an effect which will rerun when any accessed signal changes.
|
|
127
123
|
*
|
|
@@ -131,6 +127,7 @@ export const useEffect = (fn, deps) => {
|
|
|
131
127
|
const untracked = !!deps;
|
|
132
128
|
const effect = {
|
|
133
129
|
_scope: currScope,
|
|
130
|
+
_pure: pureEffectFlag,
|
|
134
131
|
_deps: new Set(),
|
|
135
132
|
_run() {
|
|
136
133
|
const prevEffect = currEffect;
|
|
@@ -179,10 +176,16 @@ export const useEffect = (fn, deps) => {
|
|
|
179
176
|
export const useMemo = (fn, opts) => {
|
|
180
177
|
const [memo, setMemo] = useSignal();
|
|
181
178
|
let firstTime = true;
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
179
|
+
pureEffectFlag = true;
|
|
180
|
+
try {
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
setMemo(fn, firstTime ? { ...opts, force: true } : opts);
|
|
183
|
+
firstTime = false;
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
pureEffectFlag = false;
|
|
188
|
+
}
|
|
186
189
|
return memo;
|
|
187
190
|
};
|
|
188
191
|
/**
|
|
@@ -192,21 +195,28 @@ export const useMemo = (fn, opts) => {
|
|
|
192
195
|
* @returns A function to manually destroy the subscope.
|
|
193
196
|
*/
|
|
194
197
|
export const useSubscope = (fn, opts) => {
|
|
198
|
+
const prevBatch = currBatch;
|
|
199
|
+
currBatch = undefined;
|
|
195
200
|
const parent = currScope;
|
|
196
201
|
const scope = createScope(parent);
|
|
197
202
|
Object.assign(scope._details, opts?.details);
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
203
|
+
try {
|
|
204
|
+
parent._subscopes.push(scope);
|
|
205
|
+
const result = scope._run(fn);
|
|
206
|
+
return [
|
|
207
|
+
result,
|
|
208
|
+
() => {
|
|
209
|
+
const index = parent._subscopes.indexOf(scope);
|
|
210
|
+
if (index >= 0) {
|
|
211
|
+
parent._subscopes.splice(index, 1);
|
|
212
|
+
}
|
|
213
|
+
scope._cleanup();
|
|
214
|
+
},
|
|
215
|
+
];
|
|
216
|
+
}
|
|
217
|
+
finally {
|
|
218
|
+
currBatch = prevBatch;
|
|
219
|
+
}
|
|
210
220
|
};
|
|
211
221
|
/**
|
|
212
222
|
* Creates a new signal with write capabilities.
|
package/dist/scope.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/scope.ts
CHANGED
|
@@ -46,9 +46,10 @@ export interface SubscopeOptions {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
interface Effect {
|
|
49
|
+
_scope: Scope;
|
|
50
|
+
_pure: boolean;
|
|
49
51
|
_clean?: Cleanup;
|
|
50
52
|
_deps: Set<Signal<unknown>>;
|
|
51
|
-
_scope: Scope;
|
|
52
53
|
|
|
53
54
|
_run(): void;
|
|
54
55
|
}
|
|
@@ -113,7 +114,7 @@ let currUntracked: boolean = false;
|
|
|
113
114
|
let currEffect: Effect | undefined;
|
|
114
115
|
let currBatch:
|
|
115
116
|
| {
|
|
116
|
-
_setters: (() =>
|
|
117
|
+
_setters: (() => void)[];
|
|
117
118
|
_effects: Set<Effect>;
|
|
118
119
|
}
|
|
119
120
|
| undefined;
|
|
@@ -161,10 +162,7 @@ export const useSignal: (<T>(
|
|
|
161
162
|
if (innerOpts?.force) {
|
|
162
163
|
value = newValue;
|
|
163
164
|
} else {
|
|
164
|
-
currBatch._setters.push(() =>
|
|
165
|
-
value = newValue;
|
|
166
|
-
return signal;
|
|
167
|
-
});
|
|
165
|
+
currBatch._setters.push(() => (value = newValue));
|
|
168
166
|
}
|
|
169
167
|
|
|
170
168
|
if (!innerOpts?.silent) {
|
|
@@ -186,58 +184,52 @@ export const useSignal: (<T>(
|
|
|
186
184
|
* and updated at the same time.
|
|
187
185
|
*/
|
|
188
186
|
export const useBatch = <T>(fn: () => T): T => {
|
|
189
|
-
|
|
190
|
-
if (createBatch) currBatch = { _setters: [], _effects: new Set() };
|
|
187
|
+
if (currBatch) return fn();
|
|
191
188
|
|
|
192
|
-
|
|
189
|
+
currBatch = { _setters: [], _effects: new Set() };
|
|
193
190
|
|
|
194
|
-
|
|
191
|
+
try {
|
|
192
|
+
const result = fn();
|
|
195
193
|
flushBatch();
|
|
194
|
+
return result;
|
|
195
|
+
} finally {
|
|
196
196
|
currBatch = undefined;
|
|
197
197
|
}
|
|
198
|
-
|
|
199
|
-
return result;
|
|
200
198
|
};
|
|
201
199
|
|
|
202
|
-
export
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
while (
|
|
200
|
+
export const flushBatch = (): void => {
|
|
201
|
+
a: while (
|
|
206
202
|
currBatch &&
|
|
207
203
|
(currBatch._setters.length > 0 || currBatch._effects.size > 0)
|
|
208
204
|
) {
|
|
209
205
|
// Clean effect subscope
|
|
210
206
|
|
|
211
|
-
|
|
212
|
-
currBatch._effects = new Set();
|
|
213
|
-
|
|
214
|
-
effects.forEach((effect) => effect._clean?.());
|
|
207
|
+
currBatch._effects.forEach((effect) => effect._clean?.());
|
|
215
208
|
|
|
216
209
|
// Run signal updates
|
|
217
210
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
for (const setter of currBatch._setters) {
|
|
221
|
-
const signal = setter();
|
|
222
|
-
mutatedSignals.add(signal);
|
|
223
|
-
}
|
|
224
|
-
|
|
211
|
+
currBatch._setters.forEach((setter) => setter());
|
|
225
212
|
currBatch._setters = [];
|
|
226
213
|
|
|
227
|
-
// Run
|
|
214
|
+
// Run next effect
|
|
228
215
|
|
|
229
|
-
for (const effect of
|
|
230
|
-
if (
|
|
231
|
-
!settersCount ||
|
|
232
|
-
[...effect._deps].every((dep) => mutatedSignals.has(dep))
|
|
233
|
-
) {
|
|
216
|
+
for (const effect of currBatch._effects) {
|
|
217
|
+
if (effect._pure) {
|
|
234
218
|
effect._run();
|
|
235
|
-
|
|
236
|
-
|
|
219
|
+
currBatch._effects.delete(effect);
|
|
220
|
+
continue a;
|
|
237
221
|
}
|
|
238
222
|
}
|
|
223
|
+
|
|
224
|
+
for (const effect of currBatch._effects) {
|
|
225
|
+
effect._run();
|
|
226
|
+
currBatch._effects.delete(effect);
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
239
229
|
}
|
|
240
|
-
}
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
let pureEffectFlag: boolean = false;
|
|
241
233
|
|
|
242
234
|
/**
|
|
243
235
|
* Creates an effect which will rerun when any accessed signal changes.
|
|
@@ -252,6 +244,7 @@ export const useEffect = (
|
|
|
252
244
|
|
|
253
245
|
const effect: Effect = {
|
|
254
246
|
_scope: currScope,
|
|
247
|
+
_pure: pureEffectFlag,
|
|
255
248
|
_deps: new Set(),
|
|
256
249
|
|
|
257
250
|
_run(): void {
|
|
@@ -316,12 +309,17 @@ export const useMemo = <T>(fn: () => T, opts?: SetSignalOptions): Signal<T> => {
|
|
|
316
309
|
const [memo, setMemo] = useSignal<T>();
|
|
317
310
|
|
|
318
311
|
let firstTime = true;
|
|
312
|
+
pureEffectFlag = true;
|
|
319
313
|
|
|
320
|
-
|
|
321
|
-
|
|
314
|
+
try {
|
|
315
|
+
useEffect(() => {
|
|
316
|
+
setMemo(fn, firstTime ? { ...opts, force: true } : opts);
|
|
322
317
|
|
|
323
|
-
|
|
324
|
-
|
|
318
|
+
firstTime = false;
|
|
319
|
+
});
|
|
320
|
+
} finally {
|
|
321
|
+
pureEffectFlag = false;
|
|
322
|
+
}
|
|
325
323
|
|
|
326
324
|
return memo as Signal<T>;
|
|
327
325
|
};
|
|
@@ -336,24 +334,31 @@ export const useSubscope = <T>(
|
|
|
336
334
|
fn: () => T,
|
|
337
335
|
opts?: SubscopeOptions,
|
|
338
336
|
): [T, () => void] => {
|
|
337
|
+
const prevBatch = currBatch;
|
|
338
|
+
currBatch = undefined;
|
|
339
|
+
|
|
339
340
|
const parent = currScope;
|
|
340
341
|
const scope = createScope(parent);
|
|
341
342
|
Object.assign(scope._details, opts?.details);
|
|
342
343
|
|
|
343
|
-
|
|
344
|
-
|
|
344
|
+
try {
|
|
345
|
+
parent._subscopes.push(scope);
|
|
346
|
+
const result = scope._run(fn);
|
|
345
347
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
348
|
+
return [
|
|
349
|
+
result,
|
|
350
|
+
() => {
|
|
351
|
+
const index = parent._subscopes.indexOf(scope);
|
|
352
|
+
if (index >= 0) {
|
|
353
|
+
parent._subscopes.splice(index, 1);
|
|
354
|
+
}
|
|
353
355
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
356
|
+
scope._cleanup();
|
|
357
|
+
},
|
|
358
|
+
];
|
|
359
|
+
} finally {
|
|
360
|
+
currBatch = prevBatch;
|
|
361
|
+
}
|
|
357
362
|
};
|
|
358
363
|
|
|
359
364
|
/**
|