1
- /**
2
- * @file
3
- *
4
- * Signals come in two types:
5
- *
6
- * 1. `Signal` - A storage of data
7
- * 2. `ComputedSignal` - A signal which is computed from other signals.
8
- *
9
- * ## Why is `ComputedSignal` different?
10
- *
11
- * - It needs to store a function which needs to re-run.
12
- * - It is `Readonly` because it is computed.
13
- */
14
1
import { isDomContainer } from '../client/dom-container' ;
15
2
import { pad , qwikDebugToString } from '../debug' ;
16
3
import type { OnRenderFn } from '../shared/component.public' ;
@@ -23,9 +10,8 @@ import { ChoreType } from '../shared/util-chore-type';
23
10
import { ELEMENT_PROPS , OnRenderProp } from '../shared/utils/markers' ;
24
11
import { SerializerSymbol } from '../shared/utils/serialize-utils' ;
25
12
import type { ISsrNode , SSRContainer } from '../ssr/ssr-types' ;
26
- import { trackSignal } from '../use/use-core' ;
27
13
import { TaskFlags , isTask } from '../use/use-task' ;
28
- import { NEEDS_COMPUTATION , _EFFECT_BACK_REF } from './flags' ;
14
+ import { _EFFECT_BACK_REF } from './flags' ;
29
15
import { ComputedSignalImpl } from './impl/computed-signal-impl' ;
30
16
import { SignalImpl } from './impl/signal-impl' ;
31
17
import type { WrappedSignalImpl } from './impl/wrapped-signal-impl' ;
@@ -35,8 +21,7 @@ import { SubscriptionData, type NodePropPayload } from './subscription-data';
35
21
import {
36
22
EffectProperty ,
37
23
EffectSubscriptionProp ,
38
- SignalFlags ,
39
- type ComputeQRL ,
24
+ type CustomSerializable ,
40
25
type EffectSubscription ,
41
26
} from './types' ;
42
27
@@ -159,103 +144,6 @@ export const triggerEffects = (
159
144
DEBUG && log ( 'done scheduling' ) ;
160
145
} ;
161
146
162
- /** @public */
163
- export type SerializerArgObject < T , S > = {
164
- /**
165
- * This will be called with initial or serialized data to reconstruct an object. If no
166
- * `initialData` is provided, it will be called with `undefined`.
167
- *
168
- * This must not return a Promise.
169
- */
170
- deserialize : ( data : Awaited < S > ) => T ;
171
- /** The initial value to use when deserializing. */
172
- initial ?: S | undefined ;
173
- /**
174
- * This will be called with the object to get the serialized data. You can return a Promise if you
175
- * need to do async work.
176
- *
177
- * The result may be anything that Qwik can serialize.
178
- *
179
- * If you do not provide it, the object will be serialized as `undefined`. However, if the object
180
- * has a `[SerializerSymbol]` property, that will be used as the serializer instead.
181
- */
182
- serialize ?: ( obj : T ) => S ;
183
- } ;
184
-
185
- /**
186
- * Serialize and deserialize custom objects.
187
- *
188
- * If you need to use scoped state, you can pass a function instead of an object. The function will
189
- * be called with the current value, and you can return a new value.
190
- *
191
- * @public
192
- */
193
- export type SerializerArg < T , S > =
194
- | SerializerArgObject < T , S >
195
- | ( ( ) => SerializerArgObject < T , S > & {
196
- /**
197
- * This gets called when reactive state used during `deserialize` changes. You may mutate the
198
- * current object, or return a new object.
199
- *
200
- * If it returns a value, that will be used as the new value, and listeners will be triggered.
201
- * If no change happened, don't return anything.
202
- *
203
- * If you mutate the current object, you must return it so that it will trigger listeners.
204
- */
205
- update ?: ( current : T ) => T | void ;
206
- } ) ;
207
-
208
- /**
209
- * A signal which provides a non-serializable value. It works like a computed signal, but it is
210
- * handled slightly differently during serdes.
211
- *
212
- * @public
213
- */
214
- export class SerializerSignalImpl < T , S > extends ComputedSignalImpl < T > {
215
- constructor ( container : Container | null , argQrl : QRLInternal < SerializerArg < T , S > > ) {
216
- super ( container , argQrl as unknown as ComputeQRL < T > ) ;
217
- }
218
- $didInitialize$ : boolean = false ;
219
-
220
- $computeIfNeeded$ ( ) : boolean {
221
- if ( ! ( this . $flags$ & SignalFlags . INVALID ) ) {
222
- return false ;
223
- }
224
- throwIfQRLNotResolved ( this . $computeQrl$ ) ;
225
- let arg = ( this . $computeQrl$ as any as QRLInternal < SerializerArg < T , S > > ) . resolved ! ;
226
- if ( typeof arg === 'function' ) {
227
- arg = arg ( ) ;
228
- }
229
- const { deserialize, initial } = arg ;
230
- const update = ( arg as any ) . update as ( ( current : T ) => T ) | undefined ;
231
- const currentValue =
232
- this . $untrackedValue$ === NEEDS_COMPUTATION ? initial : this . $untrackedValue$ ;
233
- const untrackedValue = trackSignal (
234
- ( ) =>
235
- this . $didInitialize$
236
- ? update ?.( currentValue as T )
237
- : deserialize ( currentValue as Awaited < S > ) ,
238
- this ,
239
- EffectProperty . VNODE ,
240
- this . $container$ !
241
- ) ;
242
- DEBUG && log ( 'SerializerSignal.$compute$' , untrackedValue ) ;
243
- const didChange =
244
- ( this . $didInitialize$ && untrackedValue !== 'undefined' ) ||
245
- untrackedValue !== this . $untrackedValue$ ;
246
- this . $flags$ &= ~ SignalFlags . INVALID ;
247
- this . $didInitialize$ = true ;
248
- if ( didChange ) {
249
- this . $untrackedValue$ = untrackedValue as T ;
250
- }
251
- return didChange ;
252
- }
253
- }
254
-
255
- // TODO move to serializer
256
- export type CustomSerializable < T extends { [ SerializerSymbol ] : ( obj : any ) => any } , S > = {
257
- [ SerializerSymbol ] : ( obj : T ) => S ;
258
- } ;
259
147
/** @internal */
260
148
export const isSerializerObj = < T extends { [ SerializerSymbol ] : ( obj : any ) => any } , S > (
261
149
obj : unknown
0 commit comments