@@ -22,24 +22,24 @@ import type { QRL } from '../shared/qrl/qrl.public';
22
22
import type { Container , HostElement } from '../shared/types' ;
23
23
import { ChoreType } from '../shared/util-chore-type' ;
24
24
import { ELEMENT_PROPS , OnRenderProp } from '../shared/utils/markers' ;
25
- import { isPromise } from '../shared/utils/promises' ;
26
25
import { SerializerSymbol } from '../shared/utils/serialize-utils' ;
27
26
import type { ISsrNode , SSRContainer } from '../ssr/ssr-types' ;
28
- import { trackSignal , tryGetInvokeContext } from '../use/use-core' ;
27
+ import { trackSignal } from '../use/use-core' ;
29
28
import { TaskFlags , isTask } from '../use/use-task' ;
30
29
import { NEEDS_COMPUTATION , _EFFECT_BACK_REF } from './flags' ;
30
+ import { ComputedSignalImpl } from './impl/computed-signal-impl' ;
31
31
import { SignalImpl } from './impl/signal-impl' ;
32
32
import { type BackRef } from './signal-cleanup' ;
33
33
import type { Signal } from './signal.public' ;
34
34
import type { TargetType } from './store' ;
35
- import { getSubscriber } from './subscriber' ;
36
35
import { SubscriptionData , type NodePropPayload } from './subscription-data' ;
37
36
import {
38
37
EffectProperty ,
39
38
EffectSubscriptionProp ,
40
39
SignalFlags ,
41
40
WrappedSignalFlags ,
42
41
type AllSignalFlags ,
42
+ type ComputeQRL ,
43
43
type EffectSubscription ,
44
44
} from './types' ;
45
45
@@ -162,107 +162,6 @@ export const triggerEffects = (
162
162
DEBUG && log ( 'done scheduling' ) ;
163
163
} ;
164
164
165
- type ComputeQRL < T > = QRLInternal < ( ) => T > ;
166
-
167
- /**
168
- * A signal which is computed from other signals.
169
- *
170
- * The value is available synchronously, but the computation is done lazily.
171
- */
172
- export class ComputedSignalImpl < T > extends SignalImpl < T > implements BackRef {
173
- /**
174
- * The compute function is stored here.
175
- *
176
- * The computed functions must be executed synchronously (because of this we need to eagerly
177
- * resolve the QRL during the mark dirty phase so that any call to it will be synchronous). )
178
- */
179
- $computeQrl$ : ComputeQRL < T > ;
180
- $flags$ : SignalFlags ;
181
- $forceRunEffects$ : boolean = false ;
182
- [ _EFFECT_BACK_REF ] : Map < EffectProperty | string , EffectSubscription > | null = null ;
183
-
184
- constructor (
185
- container : Container | null ,
186
- fn : ComputeQRL < T > ,
187
- // We need a separate flag to know when the computation needs running because
188
- // we need the old value to know if effects need running after computation
189
- flags = SignalFlags . INVALID
190
- ) {
191
- // The value is used for comparison when signals trigger, which can only happen
192
- // when it was calculated before. Therefore we can pass whatever we like.
193
- super ( container , NEEDS_COMPUTATION ) ;
194
- this . $computeQrl$ = fn ;
195
- this . $flags$ = flags ;
196
- }
197
-
198
- $invalidate$ ( ) {
199
- this . $flags$ |= SignalFlags . INVALID ;
200
- this . $forceRunEffects$ = false ;
201
- this . $container$ ?. $scheduler$ ( ChoreType . RECOMPUTE_AND_SCHEDULE_EFFECTS , null , this ) ;
202
- }
203
-
204
- /**
205
- * Use this to force running subscribers, for example when the calculated value has mutated but
206
- * remained the same object
207
- */
208
- force ( ) {
209
- this . $forceRunEffects$ = true ;
210
- this . $container$ ?. $scheduler$ ( ChoreType . RECOMPUTE_AND_SCHEDULE_EFFECTS , null , this ) ;
211
- }
212
-
213
- get untrackedValue ( ) {
214
- const didChange = this . $computeIfNeeded$ ( ) ;
215
- if ( didChange ) {
216
- this . $forceRunEffects$ = didChange ;
217
- }
218
- assertFalse ( this . $untrackedValue$ === NEEDS_COMPUTATION , 'Invalid state' ) ;
219
- return this . $untrackedValue$ ;
220
- }
221
-
222
- $computeIfNeeded$ ( ) {
223
- if ( ! ( this . $flags$ & SignalFlags . INVALID ) ) {
224
- return false ;
225
- }
226
- const computeQrl = this . $computeQrl$ ;
227
- throwIfQRLNotResolved ( computeQrl ) ;
228
-
229
- const ctx = tryGetInvokeContext ( ) ;
230
- const previousEffectSubscription = ctx ?. $effectSubscriber$ ;
231
- ctx && ( ctx . $effectSubscriber$ = getSubscriber ( this , EffectProperty . VNODE ) ) ;
232
- try {
233
- const untrackedValue = computeQrl . getFn ( ctx ) ( ) as T ;
234
- if ( isPromise ( untrackedValue ) ) {
235
- throw qError ( QError . computedNotSync , [
236
- computeQrl . dev ? computeQrl . dev . file : '' ,
237
- computeQrl . $hash$ ,
238
- ] ) ;
239
- }
240
- DEBUG && log ( 'Signal.$compute$' , untrackedValue ) ;
241
-
242
- this . $flags$ &= ~ SignalFlags . INVALID ;
243
-
244
- const didChange = untrackedValue !== this . $untrackedValue$ ;
245
- if ( didChange ) {
246
- this . $untrackedValue$ = untrackedValue ;
247
- }
248
- return didChange ;
249
- } finally {
250
- if ( ctx ) {
251
- ctx . $effectSubscriber$ = previousEffectSubscription ;
252
- }
253
- }
254
- }
255
-
256
- // Make this signal read-only
257
- set value ( _ : any ) {
258
- throw qError ( QError . computedReadOnly ) ;
259
- }
260
- // Getters don't get inherited when overriding a setter
261
- get value ( ) {
262
- return super . value ;
263
- }
264
- }
265
-
266
165
export class WrappedSignal < T > extends SignalImpl < T > implements BackRef {
267
166
$args$ : any [ ] ;
268
167
$func$ : ( ...args : any [ ] ) => T ;
0 commit comments