@@ -86,6 +86,7 @@ export interface SignalState<T> extends SourceMapValue {
8686 value : T ;
8787 observers : Computation < any > [ ] | null ;
8888 observerSlots : number [ ] | null ;
89+ lastObserver : Computation < any > | null ;
8990 tValue ?: T ;
9091 comparator ?: ( prev : T , next : T ) => boolean ;
9192 // development-only
@@ -157,17 +158,17 @@ export function createRoot<T>(fn: RootFunction<T>, detachedOwner?: typeof Owner)
157158 ? { owned : null , cleanups : null , context : null , owner : null }
158159 : UNOWNED
159160 : {
160- owned : null ,
161- cleanups : null ,
162- context : current ? current . context : null ,
163- owner : current
164- } ,
161+ owned : null ,
162+ cleanups : null ,
163+ context : current ? current . context : null ,
164+ owner : current
165+ } ,
165166 updateFn = unowned
166167 ? IS_DEV
167168 ? ( ) =>
168- fn ( ( ) => {
169- throw new Error ( "Dispose method must be an explicit argument to createRoot function" ) ;
170- } )
169+ fn ( ( ) => {
170+ throw new Error ( "Dispose method must be an explicit argument to createRoot function" ) ;
171+ } )
171172 : fn
172173 : ( ) => fn ( ( ) => untrack ( ( ) => cleanNode ( root ) ) ) ;
173174
@@ -236,6 +237,7 @@ export function createSignal<T>(
236237 value,
237238 observers : null ,
238239 observerSlots : null ,
240+ lastObserver : null ,
239241 comparator : options . equals || undefined
240242 } ;
241243
@@ -257,7 +259,10 @@ export function createSignal<T>(
257259 return writeSignal ( s , value ) ;
258260 } ;
259261
260- return [ readSignal . bind ( s ) , setter ] ;
262+ const result = [ readSignal . bind ( s ) , setter ] as Signal < T | undefined > ;
263+ if ( IS_DEV ) ( result as any ) . state = s ;
264+
265+ return result ;
261266}
262267
263268export interface BaseOptions {
@@ -269,7 +274,7 @@ export interface BaseOptions {
269274// TypeScript Discord conversation: https://discord.com/channels/508357248330760243/508357248330760249/911266491024949328
270275export type NoInfer < T extends any > = [ T ] [ T extends any ? 0 : never ] ;
271276
272- export interface EffectOptions extends BaseOptions { }
277+ export interface EffectOptions extends BaseOptions { }
273278
274279// Also similar to OnEffectFunction
275280export type EffectFunction < Prev , Next extends Prev = Prev > = ( v : Prev ) => Next ;
@@ -386,15 +391,15 @@ export function createEffect<Next, Init>(
386391export function createReaction ( onInvalidate : ( ) => void , options ?: EffectOptions ) {
387392 let fn : ( ( ) => void ) | undefined ;
388393 const c = createComputation (
389- ( ) => {
390- fn ? fn ( ) : untrack ( onInvalidate ) ;
391- fn = undefined ;
392- } ,
393- undefined ,
394- false ,
395- 0 ,
396- IS_DEV ? options : undefined
397- ) ,
394+ ( ) => {
395+ fn ? fn ( ) : untrack ( onInvalidate ) ;
396+ fn = undefined ;
397+ } ,
398+ undefined ,
399+ false ,
400+ 0 ,
401+ IS_DEV ? options : undefined
402+ ) ,
398403 s = SuspenseContext && useContext ( SuspenseContext ) ;
399404 if ( s ) c . suspense = s ;
400405 c . user = true ;
@@ -700,15 +705,15 @@ export function createResource<T, S, R>(
700705 initP !== NO_INIT
701706 ? ( initP as T | Promise < T > )
702707 : untrack ( ( ) => {
703- try {
704- return fetcher ( lookup , {
705- value : value ( ) ,
706- refetching
707- } ) ;
708- } catch ( fetcherError ) {
709- error = fetcherError ;
710- }
711- } ) ;
708+ try {
709+ return fetcher ( lookup , {
710+ value : value ( ) ,
711+ refetching
712+ } ) ;
713+ } catch ( fetcherError ) {
714+ error = fetcherError ;
715+ }
716+ } ) ;
712717 if ( error !== undefined ) {
713718 loadEnd ( pr , undefined , castError ( error ) , lookup ) ;
714719 return ;
@@ -909,8 +914,8 @@ export function untrack<T>(fn: Accessor<T>): T {
909914export type ReturnTypes < T > = T extends readonly Accessor < unknown > [ ]
910915 ? { [ K in keyof T ] : T [ K ] extends Accessor < infer I > ? I : never }
911916 : T extends Accessor < infer I >
912- ? I
913- : never ;
917+ ? I
918+ : never ;
914919
915920// transforms a tuple to a tuple of accessors in a way that allows generics to be inferred
916921export type AccessorArray < T > = [ ...Extract < { [ K in keyof T ] : Accessor < T [ K ] > } , readonly unknown [ ] > ] ;
@@ -1305,7 +1310,8 @@ export function readSignal(this: SignalState<any> | Memo<any>) {
13051310 Updates = updates ;
13061311 }
13071312 }
1308- if ( Listener ) {
1313+ if ( Listener && this . lastObserver !== Listener ) {
1314+ this . lastObserver = Listener ;
13091315 const sSlot = this . observers ? this . observers . length : 0 ;
13101316 if ( ! Listener . sources ) {
13111317 Listener . sources = [ this ] ;
@@ -1691,6 +1697,7 @@ function cleanNode(node: Owner) {
16911697 source . observerSlots ! [ index ] = s ;
16921698 }
16931699 }
1700+ source . lastObserver = null ;
16941701 }
16951702 }
16961703
@@ -1771,10 +1778,10 @@ function createProvider(id: symbol, options?: EffectOptions) {
17711778 let res ;
17721779 createRenderEffect (
17731780 ( ) =>
1774- ( res = untrack ( ( ) => {
1775- Owner ! . context = { ...Owner ! . context , [ id ] : props . value } ;
1776- return children ( ( ) => props . children ) ;
1777- } ) ) ,
1781+ ( res = untrack ( ( ) => {
1782+ Owner ! . context = { ...Owner ! . context , [ id ] : props . value } ;
1783+ return children ( ( ) => props . children ) ;
1784+ } ) ) ,
17781785 undefined ,
17791786 options
17801787 ) ;
0 commit comments