sinho 0.2.1 → 0.2.3

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 CHANGED
@@ -18,6 +18,12 @@ interface Signal<out T> extends SignalLike<T> {
18
18
  */
19
19
  peek(): T;
20
20
  }
21
+ interface SignalOptions<T> extends SetSignalOptions {
22
+ /**
23
+ * A custom equality function to compare the new value with the old value.
24
+ */
25
+ equals?: (a: T, b: T) => boolean;
26
+ }
21
27
  interface SetSignalOptions {
22
28
  /**
23
29
  * Whether to force the update of the signal even if the new value has the
@@ -40,9 +46,10 @@ interface SubscopeOptions {
40
46
  details?: object;
41
47
  }
42
48
  interface Effect {
49
+ _scope: Scope;
50
+ _pure: boolean;
43
51
  _clean?: Cleanup;
44
52
  _deps: Set<Signal<unknown>>;
45
- _scope: Scope;
46
53
  _run(): void;
47
54
  }
48
55
  /**
@@ -63,7 +70,7 @@ declare const useScope: <T = {}>() => Scope<T>;
63
70
  * Creates a new signal with the given value.
64
71
  * @returns A tuple with the signal and its setter.
65
72
  */
66
- declare const useSignal: (<T>(value: T, opts?: SetSignalOptions) => readonly [Signal<T>, SignalSetter<T>]) & (<T>(value?: T, opts?: SetSignalOptions) => readonly [Signal<T | undefined>, SignalSetter<T | undefined>]);
73
+ declare const useSignal: (<T>(value: T, opts?: SignalOptions<T>) => readonly [Signal<T>, SignalSetter<T>]) & (<T>(value?: T, opts?: SignalOptions<T | undefined>) => readonly [Signal<T | undefined>, SignalSetter<T | undefined>]);
67
74
  /**
68
75
  * Runs the given function in a batch.
69
76
  *
@@ -71,13 +78,13 @@ declare const useSignal: (<T>(value: T, opts?: SetSignalOptions) => readonly [Si
71
78
  * and updated at the same time.
72
79
  */
73
80
  declare const useBatch: <T>(fn: () => T) => T;
74
- declare function flushBatch(): void;
81
+ declare const flushBatch: () => void;
75
82
  /**
76
83
  * Creates a memoized signal.
77
84
  *
78
85
  * @param fn The computation function.
79
86
  */
80
- declare const useMemo: <T>(fn: () => T, opts?: SetSignalOptions) => Signal<T>;
87
+ declare const useMemo: <T>(fn: () => T, opts?: SignalOptions<T>) => Signal<T>;
81
88
  /**
82
89
  * Executes a function inside a subscope which can be manually destroyed.
83
90
  *
@@ -106,7 +113,7 @@ interface RefSignalSetter<in T> {
106
113
  /**
107
114
  * Creates a new signal with write capabilities.
108
115
  */
109
- declare const useRef: (<T>(value: T, opts?: SetSignalOptions) => RefSignal<T>) & (<T>(value?: T, opts?: SetSignalOptions) => RefSignal<T | undefined>);
116
+ declare const useRef: (<T>(value: T, opts?: SignalOptions<T>) => RefSignal<T>) & (<T>(value?: T, opts?: SignalOptions<T | undefined>) => RefSignal<T | undefined>);
110
117
  /**
111
118
  * Represents a value that can be a signal or a constant value.
112
119
  *
package/dist/bundle.js CHANGED
@@ -52,24 +52,33 @@ const useSignal = (value, opts) => {
52
52
  signal._effects = new Set();
53
53
  signal.peek = () => value;
54
54
  const setter = (arg, innerOpts) => {
55
- innerOpts = { ...opts, ...innerOpts };
55
+ const allOpts = { ...opts, ...innerOpts };
56
+ allOpts.equals ??= (a, b) => a === b;
56
57
  if (currBatch) {
57
58
  const newValue = typeof arg == "function"
58
59
  ? arg(signal.peek())
59
60
  : arg;
60
- if (innerOpts?.force || newValue !== signal.peek()) {
61
- if (innerOpts?.force) {
61
+ if (allOpts?.force || !allOpts.equals(newValue, signal.peek())) {
62
+ if (allOpts?.force) {
62
63
  value = newValue;
63
64
  }
64
- currBatch._setters.push([
65
- signal,
66
- () => (value = newValue),
67
- innerOpts?.silent,
68
- ]);
65
+ else {
66
+ currBatch._setters.push(() => (value = newValue));
67
+ }
68
+ if (!allOpts?.silent) {
69
+ signal._effects.forEach((effect) => {
70
+ if (effect._pure) {
71
+ currBatch._pureEffects.add(effect);
72
+ }
73
+ else {
74
+ currBatch._effects.add(effect);
75
+ }
76
+ });
77
+ }
69
78
  }
70
79
  }
71
80
  else {
72
- useBatch(() => setter(arg, innerOpts));
81
+ useBatch(() => setter(arg, allOpts));
73
82
  }
74
83
  };
75
84
  return [signal, setter];
@@ -81,50 +90,44 @@ const useSignal = (value, opts) => {
81
90
  * and updated at the same time.
82
91
  */
83
92
  const useBatch = (fn) => {
84
- const createBatch = !currBatch;
85
- if (createBatch)
86
- currBatch = { _setters: [], _effects: new Set() };
87
- const result = fn();
88
- if (createBatch) {
93
+ if (currBatch)
94
+ return fn();
95
+ currBatch = {
96
+ _setters: [],
97
+ _effects: new Set(),
98
+ _pureEffects: new Set(),
99
+ };
100
+ try {
101
+ const result = fn();
89
102
  flushBatch();
103
+ return result;
104
+ }
105
+ finally {
90
106
  currBatch = undefined;
91
107
  }
92
- return result;
93
108
  };
94
- function flushBatch() {
95
- const mutatedSignals = new Set();
109
+ const flushBatch = () => {
96
110
  while (currBatch &&
97
- (currBatch._setters.length > 0 || currBatch._effects.size > 0)) {
98
- const settersCount = currBatch._setters.length;
99
- const effects = currBatch._effects;
100
- currBatch._effects = new Set();
101
- // Collect and clean effects
102
- for (const [signal, , silent] of currBatch._setters) {
103
- if (!silent) {
104
- signal._effects.forEach((effect) => {
105
- effect._clean?.();
106
- effects.add(effect);
107
- });
108
- }
109
- }
111
+ currBatch._setters.length +
112
+ currBatch._effects.size +
113
+ currBatch._pureEffects.size >
114
+ 0) {
115
+ // Clean effect subscope
116
+ currBatch._effects.forEach((effect) => effect._clean?.());
110
117
  // Run signal updates
111
- for (const [signal, setter] of currBatch._setters) {
112
- setter();
113
- mutatedSignals.add(signal);
114
- }
118
+ currBatch._setters.forEach((setter) => setter());
115
119
  currBatch._setters = [];
116
- // Run effects
117
- for (const effect of effects) {
118
- if (!settersCount ||
119
- [...effect._deps].every((dep) => mutatedSignals.has(dep))) {
120
- effect._run();
121
- }
122
- else {
123
- currBatch._effects.add(effect);
124
- }
120
+ // Run next effect
121
+ const effect = currBatch._pureEffects.values().next().value ??
122
+ currBatch._effects.values().next().value;
123
+ if (effect) {
124
+ effect._run();
125
+ currBatch._pureEffects.delete(effect);
126
+ currBatch._effects.delete(effect);
125
127
  }
126
128
  }
127
- }
129
+ };
130
+ let pureEffectFlag = false;
128
131
  /**
129
132
  * Creates an effect which will rerun when any accessed signal changes.
130
133
  *
@@ -134,6 +137,7 @@ const useEffect = (fn, deps) => {
134
137
  const untracked = !!deps;
135
138
  const effect = {
136
139
  _scope: currScope,
140
+ _pure: pureEffectFlag,
137
141
  _deps: new Set(),
138
142
  _run() {
139
143
  const prevEffect = currEffect;
@@ -180,12 +184,18 @@ const useEffect = (fn, deps) => {
180
184
  * @param fn The computation function.
181
185
  */
182
186
  const useMemo = (fn, opts) => {
183
- const [memo, setMemo] = useSignal();
187
+ const [memo, setMemo] = useSignal(undefined, opts);
184
188
  let firstTime = true;
185
- useEffect(() => {
186
- setMemo(fn, firstTime ? { ...opts, force: true } : opts);
187
- firstTime = false;
188
- });
189
+ pureEffectFlag = true;
190
+ try {
191
+ useEffect(() => {
192
+ setMemo(fn, firstTime ? { force: true } : {});
193
+ firstTime = false;
194
+ });
195
+ }
196
+ finally {
197
+ pureEffectFlag = false;
198
+ }
189
199
  return memo;
190
200
  };
191
201
  /**
@@ -195,30 +205,37 @@ const useMemo = (fn, opts) => {
195
205
  * @returns A function to manually destroy the subscope.
196
206
  */
197
207
  const useSubscope = (fn, opts) => {
208
+ const prevBatch = currBatch;
209
+ currBatch = undefined;
198
210
  const parent = currScope;
199
211
  const scope = createScope(parent);
200
212
  Object.assign(scope._details, opts?.details);
201
- parent._subscopes.push(scope);
202
- const result = scope._run(fn);
203
- return [
204
- result,
205
- () => {
206
- const index = parent._subscopes.indexOf(scope);
207
- if (index >= 0) {
208
- parent._subscopes.splice(index, 1);
209
- }
210
- scope._cleanup();
211
- },
212
- ];
213
+ try {
214
+ parent._subscopes.push(scope);
215
+ const result = scope._run(fn);
216
+ return [
217
+ result,
218
+ () => {
219
+ const index = parent._subscopes.indexOf(scope);
220
+ if (index >= 0) {
221
+ parent._subscopes.splice(index, 1);
222
+ }
223
+ scope._cleanup();
224
+ },
225
+ ];
226
+ }
227
+ finally {
228
+ currBatch = prevBatch;
229
+ }
213
230
  };
214
231
  /**
215
232
  * Creates a new signal with write capabilities.
216
233
  */
217
- const useRef = (value, opts) => {
234
+ const useRef = ((value, opts) => {
218
235
  const [signal, setter] = useSignal(value, opts);
219
236
  signal.set = setter;
220
237
  return signal;
221
- };
238
+ });
222
239
  /**
223
240
  * @namespace
224
241
  */
@@ -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([r,()=>t=o,s?.silent]))}else i((()=>c(n,s)))};return[r,c]},i=t=>{const n=!e;n&&(e={m:[],o:new Set});const o=t();return n&&(l(),e=void 0),o};function l(){const t=new Set;for(;e&&(e.m.length>0||e.o.size>0);){const n=e.m.length,o=e.o;e.o=new Set;for(const[t,,n]of e.m)n||t.o.forEach((t=>{t._?.(),o.add(t)}));for(const[n,o]of e.m)o(),t.add(n);e.m=[];for(const s of o)!n||[...s.p].every((n=>t.has(n)))?s.u():e.o.add(s)}}const u=(t,e)=>{const r=!!e,c={v:o,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.v.u((()=>i(t)));this._=n?()=>{this.v.u((()=>i(n))),this._=null}:null}finally{n=o,s=c}}};o.o.push(c),c.u(),c.p.size||c._||o.o.pop()},f=(t,n)=>{const[e,o]=c();let s=!0;return u((()=>{o(t,s?{...n,force:!0}:n),s=!1})),e},a=(n,e)=>{const s=o,r=t(s);Object.assign(r.l,e?.details),s.i.push(r);return[r.u(n),()=>{const t=s.i.indexOf(r);t>=0&&s.i.splice(t,1),r.h()}]},d=(t,n)=>{const[e,o]=c(t,n);return e.set=o,e},h={upgrade:t=>()=>h.get(t),get:t=>"function"==typeof t?t():t,peek(t){const n=s;s=!0;try{return this.get(t)}finally{s=n}}},_=(t={})=>({S:[],M(t){return this.k?.next().value??t()},...t}),p=()=>{const t=r();return t.l.C??=_()},m=(t,n)=>{const e=p(),o=_({...e,...t}),[s,r]=a(n,{details:{C:o}});return u((()=>r)),s},y=t=>(t[0]??"").toLowerCase()+t.slice(1).replace(/[A-Z]/g,(t=>"-"+t.toLowerCase())),w=t=>t.startsWith("on:")?t.slice(3):y(t.slice(2)),b=Symbol(),g=(t,n)=>({[b]:Math.random().toString(36).slice(2),N:t,j:n}),v=t=>!!t?.[b],S=(t,n,e)=>{n.addEventListener(t[b],(t=>{const n=h.get(e);void 0!==n&&(t.stopPropagation(),t.detail(n))}))},x=t=>{const n=p();return f((()=>{let e=t.N;return n.H?.dispatchEvent(new CustomEvent(t[b],{detail:t=>e=t,bubbles:!0,composed:!0})),e}))},M=(t,n)=>({L:"p",T:t,...n}),k=(t=CustomEvent)=>({L:"e",A:t}),C=Symbol();let E;const N=(t,n)=>{E?E.push([t,n]):u(t,n)},j=(t,n={},e={})=>{const o=[],s=new Map;for(const t in n){const e=n[t];if("p"==e.L&&e.attribute){"function"==typeof e.attribute&&(e.attribute={transform:e.attribute});const n=e.attribute={name:y(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[C]={O:t};static observedAttributes=o;props={};events={};[C]={};constructor(){super();for(const t in n){const e=n[t];if("p"==e.L){const n=v(e.T)?e.T:null,[o,s]=c(n?void 0:e.T);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.L&&t.startsWith("on")){const n=w(t);this.events[t]=t=>this.dispatchEvent(new e.A(n,t))}}}connectedCallback(){const t=(n=this,e.shadow?n.shadowRoot??n.attachShadow(e.shadow):n);var n;this[C].D=a((()=>m({I:!1,H:this,k:t.childNodes.values()},(()=>{this[C].v=r();const n=E;E=[];try{t?.append(...this.render().build()),E.forEach((([t,n])=>u(t,n)))}finally{E=n}}))))[1]}disconnectedCallback(){this[C].D?.()}attributeChangedCallback(t,n,e){const o=s.get(t);o&&(this[o.name]=null!=e?o.meta.attribute.transform.call(this,e):v(o.meta.T)?void 0:o.meta.T)}}return i},H=t=>!!t?.[C],L=(...t)=>{const[n,e]="string"==typeof t[0]?[t[0],t.slice(1)]:["",t];for(const t of e)customElements.define(n+t[C].O,t)},T=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,A=(t,n,e)=>{"-"==n[0]?t.style.setProperty(n,""+e):t.style[n]=null==e?"":"number"!=typeof e||T.test(n)?""+e:e+"px"},O=(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))}},D=t=>({build(){const n=t();return n.build?.()??n}}),I=({text:t,marker:n})=>D((()=>{const e=p(),o=n&&e.M((()=>document.createComment(""))),s=e.M((()=>document.createTextNode("")));return u((()=>{const n=""+(h.get(t)??"");s.textContent!=n&&(s.textContent=n)})),o?[o,s]:[s]})),$=({children:t})=>D((()=>Array.isArray(t)?t.flatMap((t=>$({children:t}).build())):null==t?[]:"object"==typeof t?t:I({text:t}))),z=(t,n,e,o)=>{const{ref:s,style:c,children:l,dangerouslySetInnerHTML:f,...a}=e;for(const n in c??{}){const e=c[n];u((()=>{A(t,n,h.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=w(n);u((()=>(t.addEventListener(c,s),()=>t.removeEventListener(c,s))))}else u((()=>{O(t,n,h.get(e),o)}))}return f&&u((()=>{const n=h.get(f).__html;t.innerHTML!=n&&(t.innerHTML=n)})),s&&u((()=>(s.set(t),()=>s.set(void 0)))),null!=e.children&&t.append(...m({I:n,k:t.childNodes.values()},(()=>$({children:e.children}).build()))),t},P=(t,n={},e)=>(null!=e&&(n.children=e),H(t)?((t,n)=>D((()=>{const e=p().M((()=>new t));return customElements.upgrade(e),z(e,!1,n),[e]})))(t,n):"function"==typeof t?D((()=>t(n))):((t,n={})=>D((()=>{const e=p(),o="svg"==t||!!e.I;return[z(e.M((()=>o?document.createElementNS("http://www.w3.org/2000/svg",t):document.createElement(t))),o,n,!0)]})))(t,n)),V=new Proxy(P,{get:(t,n)=>(e,o)=>t(n,e,o)}),Z=(t,n)=>{const[e,o]=c({$:[],P:new Map});let s=new Map;return u((()=>{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.V?n=>n<t.Z?n:n==t.Z?NaN:n-1:"a"==t.V?n=>n<t.Z?n:n+1:"m"==t.V?n=>t.q<=n&&n<t.B?n+1:n==t.B?t.q: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({V:"r",F:t,Z:n})}for(let o=0;o<t().length;o++){const s=n(t()[o],o),c=i(r.get(s));isNaN(c)?e.push({V:"a",F:s,Z:o}):c!=o&&e.push({V:"m",F:s,B:c,q:o})}e.length>0&&o({$:e,P:c}),s=c})),e},q=t=>D((()=>{const n=p(),e=h.upgrade(t.each??[]),o=n.M((()=>document.createComment(""))),s=t.key??((t,n)=>n),r=[o],i=new Map,l=Z(e,s),f=t=>{for(let n=t-1;n>=0;n--){const n=s(e()[t-1],t-1),o=i.get(n)?.G??[];if(o.length>0)return o[o.length-1]}return o};return u((()=>{for(const n of l().$)if("r"==n.V){const{G:t=[],D:e}=i.get(n.F)??{};e?.();const o=r.indexOf(t[0]);o>0&&r.splice(o,t.length),t.forEach((t=>t.parentNode?.removeChild(t))),i.delete(n.F)}else if("a"==n.V){let o=[];const[,s]=a((()=>{const[s,i]=c(n.Z),[a,d]=c(e()[n.Z]);u((()=>{0<=s()&&s()<e().length&&d((()=>e()[s()]))})),u((()=>{const t=l().P.get(n.F);null!=t&&i(t)})),o=t.children?.(a,s,e).build()??[];const h=f(n.Z),_=r.indexOf(h);_>=0&&r.splice(_+1,0,...o),o.forEach((t=>h.parentNode?.insertBefore(t,h.nextSibling)))}));i.set(n.F,{G:o,D:s})}else if("m"==n.V){const{G:t=[]}=i.get(n.F)??{},e=r.indexOf(t[0]);e>=0&&r.splice(e,t.length);const o=f(n.q),s=r.indexOf(o);s>=0&&r.splice(s+1,0,...t),t.forEach((t=>o.parentNode?.insertBefore(t,o.nextSibling)))}}),[l]),r})),B=t=>(p().S=[],F({condition:t.condition,children:t.children})),F=t=>{const n=p(),e=n.S,o=f((()=>e.every((t=>!t()))&&h.get(t.condition)));return n.S=[...e,o],m({S:[]},(()=>D((()=>{const e=n.M((()=>document.createComment(""))),s=[e],r=f((()=>o()?$({children:t.children}):null));let c=[];return u((()=>{c.forEach((t=>t.parentNode?.removeChild(t))),s.length=1;const[,t]=a((()=>{c=r()?.build()??[],e.after(...c),s.push(...c)}));return t}),[r]),s}))))},G=({children:t})=>F({condition:!0,children:t}),J=({mount:t,children:n})=>D((()=>m({k:void 0},(()=>{const e=$({children:n}).build();return u((()=>(e.forEach((n=>t.appendChild(n))),()=>{e.forEach((t=>t.parentNode?.removeChild(t)))}))),[]})))),K=Symbol(),Q=new Map,R=t=>{const n=t.children;if("function"==typeof n){const e=P("style",{},I({text:n,marker:!1}));return t.light?J({mount:document.head,children:e}):e}if(n){const o=p(),s=t.light?document:o.H?.shadowRoot??document,r=((t,n,e)=>{if(!Q.has(n)){const t=new CSSStyleSheet;t.replaceSync(n),Q.set(n,{J:t,K:0})}const o=Q.get(n);o.K++,t.has(n)||t.set(n,{J:o.J,K:0});const s=t.get(n);return s.K++,u((()=>()=>{--s.K||(t.delete(n),e()),--o.K||Q.delete(n)})),s.J})((e=s,e[K]??=new Map),n,(()=>{s.adoptedStyleSheets=s.adoptedStyleSheets.filter((t=>t!=r))}));s.adoptedStyleSheets.push(r)}var e;return $({})},U=(t,...n)=>{const e=()=>t.reduce(((t,e,o)=>t+e+(h.get(n[o])??"")),"");return n.some((t=>"function"==typeof t))?e:e()},W=(t,n,e)=>(n&&null!=e&&(n.key=e),P(t,n));export{j as Component,G as Else,F as ElseIf,q as For,$ as Fragment,B as If,h as MaybeSignal,J as Portal,R as Style,g as createContext,P as createElement,U as css,L as defineComponents,k as event,l as flushBatch,V as h,H as isComponent,W as jsx,W as jsxDEV,W as jsxs,M as prop,i as useBatch,x as useContext,N as useEffect,f as useMemo,d as useRef,c as useSignal,a as useSubscope};
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)=>{const l={...o,...s};if(l.equals??=(t,n)=>t===n,e){const o="function"==typeof n?n(r.peek()):n;!l?.force&&l.equals(o,r.peek())||(l?.force?t=o:e.m.push((()=>t=o)),l?.silent||r.o.forEach((t=>{t.v?e.S.add(t):e.o.add(t)})))}else i((()=>c(n,l)))};return[r,c]},i=t=>{if(e)return t();e={m:[],o:new Set,S:new Set};try{const n=t();return l(),n}finally{e=void 0}},l=()=>{for(;e&&e.m.length+e.o.size+e.S.size>0;){e.o.forEach((t=>t._?.())),e.m.forEach((t=>t())),e.m=[];const t=e.S.values().next().value??e.o.values().next().value;t&&(t.u(),e.S.delete(t),e.o.delete(t))}};let u=!1;const f=(t,e)=>{const r=!!e,c={M: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.M.u((()=>i(t)));this._=n?()=>{this.M.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(void 0,n);let s=!0;u=!0;try{f((()=>{o(t,s?{force:!0}:{}),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={})=>({k:[],C(t){return this.N?.next().value??t()},...t}),m=()=>{const t=r();return t.l.j??=p()},y=(t,n)=>{const e=m(),o=p({...e,...t}),[s,r]=d(n,{details:{j: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)),v=Symbol(),g=(t,n)=>({[v]:Math.random().toString(36).slice(2),H:t,L:n}),x=t=>!!t?.[v],S=(t,n,e)=>{n.addEventListener(t[v],(t=>{const n=_.get(e);void 0!==n&&(t.stopPropagation(),t.detail(n))}))},M=t=>{const n=m();return a((()=>{let e=t.H;return n.T?.dispatchEvent(new CustomEvent(t[v],{detail:t=>e=t,bubbles:!0,composed:!0})),e}))},k=(t,n)=>({A:"p",O:t,...n}),C=(t=CustomEvent)=>({A:"e",D: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.A&&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]={I:t};static observedAttributes=o;props={};events={};[E]={};constructor(){super();for(const t in n){const e=n[t];if("p"==e.A){const n=x(e.O)?e.O:null,[o,s]=c(n?void 0:e.O);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.A&&t.startsWith("on")){const n=b(t);this.events[t]=t=>this.dispatchEvent(new e.D(n,t))}}}connectedCallback(){const t=(n=this,e.shadow?n.shadowRoot??n.attachShadow(e.shadow):n);var n;this[E].$=d((()=>y({P:!1,T:this,N:t.childNodes.values()},(()=>{this[E].M=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].$?.()}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.O)?void 0:o.meta.O)}}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].I,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.C((()=>document.createComment(""))),s=e.C((()=>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({P:n,N: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().C((()=>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.P;return[P(e.C((()=>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({V:[],Z: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.q?n=>n<t.B?n:n==t.B?NaN:n-1:"a"==t.q?n=>n<t.B?n:n+1:"m"==t.q?n=>t.F<=n&&n<t.G?n+1:n==t.G?t.F: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({q:"r",J:t,B:n})}for(let o=0;o<t().length;o++){const s=n(t()[o],o),c=i(r.get(s));isNaN(c)?e.push({q:"a",J:s,B:o}):c!=o&&e.push({q:"m",J:s,G:c,F:o})}e.length>0&&o({V:e,Z:c}),s=c})),e},B=t=>I((()=>{const n=m(),e=_.upgrade(t.each??[]),o=n.C((()=>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)?.K??[];if(o.length>0)return o[o.length-1]}return o};return f((()=>{for(const n of l().V)if("r"==n.q){const{K:t=[],$:e}=i.get(n.J)??{};e?.();const o=r.indexOf(t[0]);o>0&&r.splice(o,t.length),t.forEach((t=>t.parentNode?.removeChild(t))),i.delete(n.J)}else if("a"==n.q){let o=[];const[,s]=d((()=>{const[s,i]=c(n.B),[a,d]=c(e()[n.B]);f((()=>{0<=s()&&s()<e().length&&d((()=>e()[s()]))})),f((()=>{const t=l().Z.get(n.J);null!=t&&i(t)})),o=t.children?.(a,s,e).build()??[];const h=u(n.B),_=r.indexOf(h);_>=0&&r.splice(_+1,0,...o),o.forEach((t=>h.parentNode?.insertBefore(t,h.nextSibling)))}));i.set(n.J,{K:o,$:s})}else if("m"==n.q){const{K:t=[]}=i.get(n.J)??{},e=r.indexOf(t[0]);e>=0&&r.splice(e,t.length);const o=u(n.F),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().k=[],G({condition:t.condition,children:t.children})),G=t=>{const n=m(),e=n.k,o=a((()=>e.every((t=>!t()))&&_.get(t.condition)));return n.k=[...e,o],y({k:[]},(()=>I((()=>{const e=n.C((()=>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({N: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.T?.shadowRoot??document,r=((t,n,e)=>{if(!R.has(n)){const t=new CSSStyleSheet;t.replaceSync(n),R.set(n,{R:t,U:0})}const o=R.get(n);o.U++,t.has(n)||t.set(n,{R:o.R,U:0});const s=t.get(n);return s.U++,f((()=>()=>{--s.U||(t.delete(n),e()),--o.U||R.delete(n)})),s.R})((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,g 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
@@ -18,6 +18,12 @@ export interface Signal<out T> extends SignalLike<T> {
18
18
  */
19
19
  peek(): T;
20
20
  }
21
+ export interface SignalOptions<T> extends SetSignalOptions {
22
+ /**
23
+ * A custom equality function to compare the new value with the old value.
24
+ */
25
+ equals?: (a: T, b: T) => boolean;
26
+ }
21
27
  export interface SetSignalOptions {
22
28
  /**
23
29
  * Whether to force the update of the signal even if the new value has the
@@ -40,9 +46,10 @@ export interface SubscopeOptions {
40
46
  details?: object;
41
47
  }
42
48
  interface Effect {
49
+ _scope: Scope;
50
+ _pure: boolean;
43
51
  _clean?: Cleanup;
44
52
  _deps: Set<Signal<unknown>>;
45
- _scope: Scope;
46
53
  _run(): void;
47
54
  }
48
55
  /**
@@ -63,7 +70,7 @@ export declare const useScope: <T = {}>() => Scope<T>;
63
70
  * Creates a new signal with the given value.
64
71
  * @returns A tuple with the signal and its setter.
65
72
  */
66
- export declare const useSignal: (<T>(value: T, opts?: SetSignalOptions) => readonly [Signal<T>, SignalSetter<T>]) & (<T>(value?: T, opts?: SetSignalOptions) => readonly [Signal<T | undefined>, SignalSetter<T | undefined>]);
73
+ export declare const useSignal: (<T>(value: T, opts?: SignalOptions<T>) => readonly [Signal<T>, SignalSetter<T>]) & (<T>(value?: T, opts?: SignalOptions<T | undefined>) => readonly [Signal<T | undefined>, SignalSetter<T | undefined>]);
67
74
  /**
68
75
  * Runs the given function in a batch.
69
76
  *
@@ -71,7 +78,7 @@ export declare const useSignal: (<T>(value: T, opts?: SetSignalOptions) => reado
71
78
  * and updated at the same time.
72
79
  */
73
80
  export declare const useBatch: <T>(fn: () => T) => T;
74
- export declare function flushBatch(): void;
81
+ export declare const flushBatch: () => void;
75
82
  /**
76
83
  * Creates an effect which will rerun when any accessed signal changes.
77
84
  *
@@ -83,7 +90,7 @@ export declare const useEffect: (fn: () => Cleanup, deps?: SignalLike<unknown>[]
83
90
  *
84
91
  * @param fn The computation function.
85
92
  */
86
- export declare const useMemo: <T>(fn: () => T, opts?: SetSignalOptions) => Signal<T>;
93
+ export declare const useMemo: <T>(fn: () => T, opts?: SignalOptions<T>) => Signal<T>;
87
94
  /**
88
95
  * Executes a function inside a subscope which can be manually destroyed.
89
96
  *
@@ -112,7 +119,7 @@ export interface RefSignalSetter<in T> {
112
119
  /**
113
120
  * Creates a new signal with write capabilities.
114
121
  */
115
- export declare const useRef: (<T>(value: T, opts?: SetSignalOptions) => RefSignal<T>) & (<T>(value?: T, opts?: SetSignalOptions) => RefSignal<T | undefined>);
122
+ export declare const useRef: (<T>(value: T, opts?: SignalOptions<T>) => RefSignal<T>) & (<T>(value?: T, opts?: SignalOptions<T | undefined>) => RefSignal<T | undefined>);
116
123
  /**
117
124
  * Represents a value that can be a signal or a constant value.
118
125
  *
package/dist/scope.js CHANGED
@@ -52,24 +52,33 @@ export const useSignal = (value, opts) => {
52
52
  signal._effects = new Set();
53
53
  signal.peek = () => value;
54
54
  const setter = (arg, innerOpts) => {
55
- innerOpts = { ...opts, ...innerOpts };
55
+ const allOpts = { ...opts, ...innerOpts };
56
+ allOpts.equals ??= (a, b) => a === b;
56
57
  if (currBatch) {
57
58
  const newValue = typeof arg == "function"
58
59
  ? arg(signal.peek())
59
60
  : arg;
60
- if (innerOpts?.force || newValue !== signal.peek()) {
61
- if (innerOpts?.force) {
61
+ if (allOpts?.force || !allOpts.equals(newValue, signal.peek())) {
62
+ if (allOpts?.force) {
62
63
  value = newValue;
63
64
  }
64
- currBatch._setters.push([
65
- signal,
66
- () => (value = newValue),
67
- innerOpts?.silent,
68
- ]);
65
+ else {
66
+ currBatch._setters.push(() => (value = newValue));
67
+ }
68
+ if (!allOpts?.silent) {
69
+ signal._effects.forEach((effect) => {
70
+ if (effect._pure) {
71
+ currBatch._pureEffects.add(effect);
72
+ }
73
+ else {
74
+ currBatch._effects.add(effect);
75
+ }
76
+ });
77
+ }
69
78
  }
70
79
  }
71
80
  else {
72
- useBatch(() => setter(arg, innerOpts));
81
+ useBatch(() => setter(arg, allOpts));
73
82
  }
74
83
  };
75
84
  return [signal, setter];
@@ -81,50 +90,44 @@ export const useSignal = (value, opts) => {
81
90
  * and updated at the same time.
82
91
  */
83
92
  export const useBatch = (fn) => {
84
- const createBatch = !currBatch;
85
- if (createBatch)
86
- currBatch = { _setters: [], _effects: new Set() };
87
- const result = fn();
88
- if (createBatch) {
93
+ if (currBatch)
94
+ return fn();
95
+ currBatch = {
96
+ _setters: [],
97
+ _effects: new Set(),
98
+ _pureEffects: new Set(),
99
+ };
100
+ try {
101
+ const result = fn();
89
102
  flushBatch();
103
+ return result;
104
+ }
105
+ finally {
90
106
  currBatch = undefined;
91
107
  }
92
- return result;
93
108
  };
94
- export function flushBatch() {
95
- const mutatedSignals = new Set();
109
+ export const flushBatch = () => {
96
110
  while (currBatch &&
97
- (currBatch._setters.length > 0 || currBatch._effects.size > 0)) {
98
- const settersCount = currBatch._setters.length;
99
- const effects = currBatch._effects;
100
- currBatch._effects = new Set();
101
- // Collect and clean effects
102
- for (const [signal, , silent] of currBatch._setters) {
103
- if (!silent) {
104
- signal._effects.forEach((effect) => {
105
- effect._clean?.();
106
- effects.add(effect);
107
- });
108
- }
109
- }
111
+ currBatch._setters.length +
112
+ currBatch._effects.size +
113
+ currBatch._pureEffects.size >
114
+ 0) {
115
+ // Clean effect subscope
116
+ currBatch._effects.forEach((effect) => effect._clean?.());
110
117
  // Run signal updates
111
- for (const [signal, setter] of currBatch._setters) {
112
- setter();
113
- mutatedSignals.add(signal);
114
- }
118
+ currBatch._setters.forEach((setter) => setter());
115
119
  currBatch._setters = [];
116
- // Run effects
117
- for (const effect of effects) {
118
- if (!settersCount ||
119
- [...effect._deps].every((dep) => mutatedSignals.has(dep))) {
120
- effect._run();
121
- }
122
- else {
123
- currBatch._effects.add(effect);
124
- }
120
+ // Run next effect
121
+ const effect = currBatch._pureEffects.values().next().value ??
122
+ currBatch._effects.values().next().value;
123
+ if (effect) {
124
+ effect._run();
125
+ currBatch._pureEffects.delete(effect);
126
+ currBatch._effects.delete(effect);
125
127
  }
126
128
  }
127
- }
129
+ };
130
+ let pureEffectFlag = false;
128
131
  /**
129
132
  * Creates an effect which will rerun when any accessed signal changes.
130
133
  *
@@ -134,6 +137,7 @@ export const useEffect = (fn, deps) => {
134
137
  const untracked = !!deps;
135
138
  const effect = {
136
139
  _scope: currScope,
140
+ _pure: pureEffectFlag,
137
141
  _deps: new Set(),
138
142
  _run() {
139
143
  const prevEffect = currEffect;
@@ -180,12 +184,18 @@ export const useEffect = (fn, deps) => {
180
184
  * @param fn The computation function.
181
185
  */
182
186
  export const useMemo = (fn, opts) => {
183
- const [memo, setMemo] = useSignal();
187
+ const [memo, setMemo] = useSignal(undefined, opts);
184
188
  let firstTime = true;
185
- useEffect(() => {
186
- setMemo(fn, firstTime ? { ...opts, force: true } : opts);
187
- firstTime = false;
188
- });
189
+ pureEffectFlag = true;
190
+ try {
191
+ useEffect(() => {
192
+ setMemo(fn, firstTime ? { force: true } : {});
193
+ firstTime = false;
194
+ });
195
+ }
196
+ finally {
197
+ pureEffectFlag = false;
198
+ }
189
199
  return memo;
190
200
  };
191
201
  /**
@@ -195,30 +205,37 @@ export const useMemo = (fn, opts) => {
195
205
  * @returns A function to manually destroy the subscope.
196
206
  */
197
207
  export const useSubscope = (fn, opts) => {
208
+ const prevBatch = currBatch;
209
+ currBatch = undefined;
198
210
  const parent = currScope;
199
211
  const scope = createScope(parent);
200
212
  Object.assign(scope._details, opts?.details);
201
- parent._subscopes.push(scope);
202
- const result = scope._run(fn);
203
- return [
204
- result,
205
- () => {
206
- const index = parent._subscopes.indexOf(scope);
207
- if (index >= 0) {
208
- parent._subscopes.splice(index, 1);
209
- }
210
- scope._cleanup();
211
- },
212
- ];
213
+ try {
214
+ parent._subscopes.push(scope);
215
+ const result = scope._run(fn);
216
+ return [
217
+ result,
218
+ () => {
219
+ const index = parent._subscopes.indexOf(scope);
220
+ if (index >= 0) {
221
+ parent._subscopes.splice(index, 1);
222
+ }
223
+ scope._cleanup();
224
+ },
225
+ ];
226
+ }
227
+ finally {
228
+ currBatch = prevBatch;
229
+ }
213
230
  };
214
231
  /**
215
232
  * Creates a new signal with write capabilities.
216
233
  */
217
- export const useRef = (value, opts) => {
234
+ export const useRef = ((value, opts) => {
218
235
  const [signal, setter] = useSignal(value, opts);
219
236
  signal.set = setter;
220
237
  return signal;
221
- };
238
+ });
222
239
  /**
223
240
  * @namespace
224
241
  */
package/dist/scope.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"AAsEA,MAAM,WAAW,GAAG,CAAC,MAAc,EAAS,EAAE;IAC5C,OAAO;QACL,OAAO,EAAE,MAAM;QACf,QAAQ,EAAE,EAAE;QACZ,UAAU,EAAE,EAAE;QACd,QAAQ,EAAE,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE;QAEjC,IAAI,CAAI,EAAW;YACjB,MAAM,SAAS,GAAG,SAAS,CAAC;YAC5B,SAAS,GAAG,IAAI,CAAC;YAEjB,IAAI,CAAC;gBACH,OAAO,EAAE,EAAE,CAAC;YACd,CAAC;oBAAS,CAAC;gBACT,SAAS,GAAG,SAAS,CAAC;YACxB,CAAC;QACH,CAAC;QAED,QAAQ;YACN,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBACrD,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;YAChC,CAAC;YAED,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;YAErB,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBACnD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBAChC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;gBAClB,MAAM,CAAC,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;gBAEvB,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;gBACjE,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACvB,CAAC;YAED,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;QACrB,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,IAAI,SAAS,GAAU,WAAW,EAAE,CAAC;AACrC,IAAI,SAAS,GAAU,SAAS,CAAC;AACjC,IAAI,aAAa,GAAY,KAAK,CAAC;AACnC,IAAI,UAA8B,CAAC;AACnC,IAAI,SASS,CAAC;AAEd,cAAc;AACd,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAqB,EAAE,CAAC,SAAqB,CAAC;AAEtE;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAOkD,CACtE,KAAQ,EACR,IAAuB,EACgB,EAAE;IACzC,MAAM,MAAM,GAAc,GAAG,EAAE;QAC7B,IAAI,CAAC,aAAa,IAAI,UAAU,EAAE,CAAC;YACjC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC7B,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAClC,CAAC;QAED,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC,CAAC;IAEF,MAAM,CAAC,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;IAC5B,MAAM,CAAC,IAAI,GAAG,GAAG,EAAE,CAAC,KAAK,CAAC;IAE1B,MAAM,MAAM,GAAG,CAAC,GAA0B,EAAE,SAA4B,EAAE,EAAE;QAC1E,SAAS,GAAG,EAAE,GAAG,IAAI,EAAE,GAAG,SAAS,EAAE,CAAC;QAEtC,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,QAAQ,GACZ,OAAO,GAAG,IAAI,UAAU;gBACtB,CAAC,CAAE,GAAuB,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBACzC,CAAC,CAAC,GAAG,CAAC;YAEV,IAAI,SAAS,EAAE,KAAK,IAAI,QAAQ,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;gBACnD,IAAI,SAAS,EAAE,KAAK,EAAE,CAAC;oBACrB,KAAK,GAAG,QAAQ,CAAC;gBACnB,CAAC;gBAED,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC;oBACtB,MAAM;oBACN,GAAG,EAAE,CAAC,CAAC,KAAK,GAAG,QAAQ,CAAC;oBACxB,SAAS,EAAE,MAAM;iBAClB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC;QACzC,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CAAC,MAAM,EAAE,MAAa,CAAC,CAAC;AACjC,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAI,EAAW,EAAK,EAAE;IAC5C,MAAM,WAAW,GAAG,CAAC,SAAS,CAAC;IAC/B,IAAI,WAAW;QAAE,SAAS,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;IAEnE,MAAM,MAAM,GAAG,EAAE,EAAE,CAAC;IAEpB,IAAI,WAAW,EAAE,CAAC;QAChB,UAAU,EAAE,CAAC;QACb,SAAS,GAAG,SAAS,CAAC;IACxB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,UAAU,UAAU;IACxB,MAAM,cAAc,GAAG,IAAI,GAAG,EAAmB,CAAC;IAElD,OACE,SAAS;QACT,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC,EAC9D,CAAC;QACD,MAAM,YAAY,GAAG,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;QAC/C,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC;QACnC,SAAS,CAAC,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;QAE/B,4BAA4B;QAE5B,KAAK,MAAM,CAAC,MAAM,EAAE,AAAD,EAAG,MAAM,CAAC,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC;YACpD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;oBACjC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;oBAClB,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACtB,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,qBAAqB;QAErB,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC;YAClD,MAAM,EAAE,CAAC;YACT,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC;QAED,SAAS,CAAC,QAAQ,GAAG,EAAE,CAAC;QAExB,cAAc;QAEd,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IACE,CAAC,YAAY;gBACb,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EACzD,CAAC;gBACD,MAAM,CAAC,IAAI,EAAE,CAAC;YAChB,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACvB,EAAiB,EACjB,IAA4B,EACtB,EAAE;IACR,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC;IAEzB,MAAM,MAAM,GAAW;QACrB,MAAM,EAAE,SAAS;QACjB,KAAK,EAAE,IAAI,GAAG,EAAE;QAEhB,IAAI;YACF,MAAM,UAAU,GAAG,UAAU,CAAC;YAC9B,MAAM,aAAa,GAAG,aAAa,CAAC;YAEpC,UAAU,GAAG,IAAI,CAAC;YAElB,IAAI,CAAC;gBACH,sCAAsC;gBAEtC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;gBACvD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;gBAEnB,IAAI,IAAI,EAAE,CAAC;oBACT,+BAA+B;oBAE/B,aAAa,GAAG,KAAK,CAAC;oBACtB,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;gBAC/B,CAAC;gBAED,aAAa;gBAEb,aAAa,GAAG,SAAS,CAAC;gBAE1B,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;gBAEhB,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;gBAErD,IAAI,CAAC,MAAM,GAAG,CAAC,OAAO;oBACpB,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC,GAAG,EAAE;wBACH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;wBAC1C,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;oBACrB,CAAC,CAAC;YACR,CAAC;oBAAS,CAAC;gBACT,sBAAsB;gBAEtB,UAAU,GAAG,UAAU,CAAC;gBACxB,aAAa,GAAG,aAAa,CAAC;YAChC,CAAC;QACH,CAAC;KACF,CAAC;IAEF,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChC,MAAM,CAAC,IAAI,EAAE,CAAC;IAEd,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACzC,wEAAwE;QACxE,wBAAwB;QAExB,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;IAC3B,CAAC;AACH,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAI,EAAW,EAAE,IAAuB,EAAa,EAAE;IAC5E,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,SAAS,EAAK,CAAC;IAEvC,IAAI,SAAS,GAAG,IAAI,CAAC;IAErB,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAEzD,SAAS,GAAG,KAAK,CAAC;IACpB,CAAC,CAAC,CAAC;IAEH,OAAO,IAAiB,CAAC;AAC3B,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,EAAW,EACX,IAAsB,EACL,EAAE;IACnB,MAAM,MAAM,GAAG,SAAS,CAAC;IACzB,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAE7C,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAE9B,OAAO;QACL,MAAM;QACN,GAAG,EAAE;YACH,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC/C,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;gBACf,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;YACrC,CAAC;YAED,KAAK,CAAC,QAAQ,EAAE,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAsBF;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GACuD,CACxE,KAAS,EACT,IAAuB,EACkB,EAAE;IAC3C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC/C,MAAmC,CAAC,GAAG,GAAG,MAAM,CAAC;IAClD,OAAO,MAAiD,CAAC;AAC3D,CAAC,CAAC;AASF;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB;;OAEG;IACH,OAAO,EACL,CAAI,MAAsB,EAAiB,EAAE,CAC7C,GAAG,EAAE,CACH,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC;IAE3B;;OAEG;IACH,GAAG,EAAE,CAAI,MAAsB,EAAK,EAAE,CACpC,OAAO,MAAM,IAAI,UAAU,CAAC,CAAC,CAAE,MAAwB,EAAE,CAAC,CAAC,CAAC,MAAM;IAEpE;;OAEG;IACH,IAAI,CAAI,MAAsB;QAC5B,MAAM,aAAa,GAAG,aAAa,CAAC;QACpC,aAAa,GAAG,IAAI,CAAC;QAErB,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;gBAAS,CAAC;YACT,aAAa,GAAG,aAAa,CAAC;QAChC,CAAC;IACH,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"scope.js","sourceRoot":"","sources":["../src/scope.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sinho",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "A lightweight signal-based library for building web components with a React-like API.",
5
5
  "keywords": [
6
6
  "ui",
package/src/scope.ts CHANGED
@@ -21,6 +21,13 @@ export interface Signal<out T> extends SignalLike<T> {
21
21
  peek(): T;
22
22
  }
23
23
 
24
+ export interface SignalOptions<T> extends SetSignalOptions {
25
+ /**
26
+ * A custom equality function to compare the new value with the old value.
27
+ */
28
+ equals?: (a: T, b: T) => boolean;
29
+ }
30
+
24
31
  export interface SetSignalOptions {
25
32
  /**
26
33
  * Whether to force the update of the signal even if the new value has the
@@ -46,9 +53,10 @@ export interface SubscopeOptions {
46
53
  }
47
54
 
48
55
  interface Effect {
56
+ _scope: Scope;
57
+ _pure: boolean;
49
58
  _clean?: Cleanup;
50
59
  _deps: Set<Signal<unknown>>;
51
- _scope: Scope;
52
60
 
53
61
  _run(): void;
54
62
  }
@@ -113,12 +121,9 @@ let currUntracked: boolean = false;
113
121
  let currEffect: Effect | undefined;
114
122
  let currBatch:
115
123
  | {
116
- _setters: [
117
- signal: Signal<unknown>,
118
- setter: () => void,
119
- silent?: boolean,
120
- ][];
124
+ _setters: (() => void)[];
121
125
  _effects: Set<Effect>;
126
+ _pureEffects: Set<Effect>;
122
127
  }
123
128
  | undefined;
124
129
 
@@ -131,14 +136,14 @@ export const useScope = <T = {}>(): Scope<T> => currScope as Scope<T>;
131
136
  */
132
137
  export const useSignal: (<T>(
133
138
  value: T,
134
- opts?: SetSignalOptions,
139
+ opts?: SignalOptions<T>,
135
140
  ) => readonly [Signal<T>, SignalSetter<T>]) &
136
141
  (<T>(
137
142
  value?: T,
138
- opts?: SetSignalOptions,
143
+ opts?: SignalOptions<T | undefined>,
139
144
  ) => readonly [Signal<T | undefined>, SignalSetter<T | undefined>]) = <T>(
140
145
  value: T,
141
- opts?: SetSignalOptions,
146
+ opts?: SignalOptions<T>,
142
147
  ): readonly [Signal<T>, SignalSetter<T>] => {
143
148
  const signal: Signal<T> = () => {
144
149
  if (!currUntracked && currEffect) {
@@ -153,7 +158,8 @@ export const useSignal: (<T>(
153
158
  signal.peek = () => value;
154
159
 
155
160
  const setter = (arg: T | ((value: T) => T), innerOpts?: SetSignalOptions) => {
156
- innerOpts = { ...opts, ...innerOpts };
161
+ const allOpts = { ...opts, ...innerOpts };
162
+ allOpts.equals ??= (a, b) => a === b;
157
163
 
158
164
  if (currBatch) {
159
165
  const newValue =
@@ -161,19 +167,25 @@ export const useSignal: (<T>(
161
167
  ? (arg as (value: T) => T)(signal.peek())
162
168
  : arg;
163
169
 
164
- if (innerOpts?.force || newValue !== signal.peek()) {
165
- if (innerOpts?.force) {
170
+ if (allOpts?.force || !allOpts.equals(newValue, signal.peek())) {
171
+ if (allOpts?.force) {
166
172
  value = newValue;
173
+ } else {
174
+ currBatch._setters.push(() => (value = newValue));
167
175
  }
168
176
 
169
- currBatch._setters.push([
170
- signal,
171
- () => (value = newValue),
172
- innerOpts?.silent,
173
- ]);
177
+ if (!allOpts?.silent) {
178
+ signal._effects.forEach((effect) => {
179
+ if (effect._pure) {
180
+ currBatch!._pureEffects.add(effect);
181
+ } else {
182
+ currBatch!._effects.add(effect);
183
+ }
184
+ });
185
+ }
174
186
  }
175
187
  } else {
176
- useBatch(() => setter(arg, innerOpts));
188
+ useBatch(() => setter(arg, allOpts));
177
189
  }
178
190
  };
179
191
 
@@ -187,64 +199,55 @@ export const useSignal: (<T>(
187
199
  * and updated at the same time.
188
200
  */
189
201
  export const useBatch = <T>(fn: () => T): T => {
190
- const createBatch = !currBatch;
191
- if (createBatch) currBatch = { _setters: [], _effects: new Set() };
202
+ if (currBatch) return fn();
192
203
 
193
- const result = fn();
204
+ currBatch = {
205
+ _setters: [],
206
+ _effects: new Set(),
207
+ _pureEffects: new Set(),
208
+ };
194
209
 
195
- if (createBatch) {
210
+ try {
211
+ const result = fn();
196
212
  flushBatch();
213
+ return result;
214
+ } finally {
197
215
  currBatch = undefined;
198
216
  }
199
-
200
- return result;
201
217
  };
202
218
 
203
- export function flushBatch(): void {
204
- const mutatedSignals = new Set<Signal<unknown>>();
205
-
219
+ export const flushBatch = (): void => {
206
220
  while (
207
221
  currBatch &&
208
- (currBatch._setters.length > 0 || currBatch._effects.size > 0)
222
+ currBatch._setters.length +
223
+ currBatch._effects.size +
224
+ currBatch._pureEffects.size >
225
+ 0
209
226
  ) {
210
- const settersCount = currBatch._setters.length;
211
- const effects = currBatch._effects;
212
- currBatch._effects = new Set();
213
-
214
- // Collect and clean effects
215
-
216
- for (const [signal, , silent] of currBatch._setters) {
217
- if (!silent) {
218
- signal._effects.forEach((effect) => {
219
- effect._clean?.();
220
- effects.add(effect);
221
- });
222
- }
223
- }
227
+ // Clean effect subscope
224
228
 
225
- // Run signal updates
229
+ currBatch._effects.forEach((effect) => effect._clean?.());
226
230
 
227
- for (const [signal, setter] of currBatch._setters) {
228
- setter();
229
- mutatedSignals.add(signal);
230
- }
231
+ // Run signal updates
231
232
 
233
+ currBatch._setters.forEach((setter) => setter());
232
234
  currBatch._setters = [];
233
235
 
234
- // Run effects
236
+ // Run next effect
235
237
 
236
- for (const effect of effects) {
237
- if (
238
- !settersCount ||
239
- [...effect._deps].every((dep) => mutatedSignals.has(dep))
240
- ) {
241
- effect._run();
242
- } else {
243
- currBatch._effects.add(effect);
244
- }
238
+ const effect: Effect | undefined =
239
+ currBatch._pureEffects.values().next().value ??
240
+ currBatch._effects.values().next().value;
241
+
242
+ if (effect) {
243
+ effect._run();
244
+ currBatch._pureEffects.delete(effect);
245
+ currBatch._effects.delete(effect);
245
246
  }
246
247
  }
247
- }
248
+ };
249
+
250
+ let pureEffectFlag: boolean = false;
248
251
 
249
252
  /**
250
253
  * Creates an effect which will rerun when any accessed signal changes.
@@ -259,6 +262,7 @@ export const useEffect = (
259
262
 
260
263
  const effect: Effect = {
261
264
  _scope: currScope,
265
+ _pure: pureEffectFlag,
262
266
  _deps: new Set(),
263
267
 
264
268
  _run(): void {
@@ -319,16 +323,24 @@ export const useEffect = (
319
323
  *
320
324
  * @param fn The computation function.
321
325
  */
322
- export const useMemo = <T>(fn: () => T, opts?: SetSignalOptions): Signal<T> => {
323
- const [memo, setMemo] = useSignal<T>();
326
+ export const useMemo = <T>(fn: () => T, opts?: SignalOptions<T>): Signal<T> => {
327
+ const [memo, setMemo] = useSignal<T>(
328
+ undefined,
329
+ opts as SignalOptions<T | undefined>,
330
+ );
324
331
 
325
332
  let firstTime = true;
333
+ pureEffectFlag = true;
326
334
 
327
- useEffect(() => {
328
- setMemo(fn, firstTime ? { ...opts, force: true } : opts);
335
+ try {
336
+ useEffect(() => {
337
+ setMemo(fn, firstTime ? { force: true } : {});
329
338
 
330
- firstTime = false;
331
- });
339
+ firstTime = false;
340
+ });
341
+ } finally {
342
+ pureEffectFlag = false;
343
+ }
332
344
 
333
345
  return memo as Signal<T>;
334
346
  };
@@ -343,24 +355,31 @@ export const useSubscope = <T>(
343
355
  fn: () => T,
344
356
  opts?: SubscopeOptions,
345
357
  ): [T, () => void] => {
358
+ const prevBatch = currBatch;
359
+ currBatch = undefined;
360
+
346
361
  const parent = currScope;
347
362
  const scope = createScope(parent);
348
363
  Object.assign(scope._details, opts?.details);
349
364
 
350
- parent._subscopes.push(scope);
351
- const result = scope._run(fn);
365
+ try {
366
+ parent._subscopes.push(scope);
367
+ const result = scope._run(fn);
352
368
 
353
- return [
354
- result,
355
- () => {
356
- const index = parent._subscopes.indexOf(scope);
357
- if (index >= 0) {
358
- parent._subscopes.splice(index, 1);
359
- }
369
+ return [
370
+ result,
371
+ () => {
372
+ const index = parent._subscopes.indexOf(scope);
373
+ if (index >= 0) {
374
+ parent._subscopes.splice(index, 1);
375
+ }
360
376
 
361
- scope._cleanup();
362
- },
363
- ];
377
+ scope._cleanup();
378
+ },
379
+ ];
380
+ } finally {
381
+ currBatch = prevBatch;
382
+ }
364
383
  };
365
384
 
366
385
  /**
@@ -386,15 +405,18 @@ export interface RefSignalSetter<in T> {
386
405
  /**
387
406
  * Creates a new signal with write capabilities.
388
407
  */
389
- export const useRef: (<T>(value: T, opts?: SetSignalOptions) => RefSignal<T>) &
390
- (<T>(value?: T, opts?: SetSignalOptions) => RefSignal<T | undefined>) = <T>(
408
+ export const useRef: (<T>(value: T, opts?: SignalOptions<T>) => RefSignal<T>) &
409
+ (<T>(
410
+ value?: T,
411
+ opts?: SignalOptions<T | undefined>,
412
+ ) => RefSignal<T | undefined>) = (<T>(
391
413
  value?: T,
392
- opts?: SetSignalOptions,
414
+ opts?: SignalOptions<T | undefined>,
393
415
  ): RefSignal<T> & RefSignal<T | undefined> => {
394
416
  const [signal, setter] = useSignal(value, opts);
395
417
  (signal as RefSignal<T | undefined>).set = setter;
396
418
  return signal as RefSignal<T> & RefSignal<T | undefined>;
397
- };
419
+ }) as any;
398
420
 
399
421
  /**
400
422
  * Represents a value that can be a signal or a constant value.