Skip to content

Commit 1ddc62d

Browse files
committed
fix: unit tests
1 parent d006823 commit 1ddc62d

File tree

15 files changed

+252
-176
lines changed

15 files changed

+252
-176
lines changed

eslint.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export default tseslint.config(
109109
},
110110
},
111111
{
112-
files: ['packages/docs/demo/**/*.{ts,tsx}'],
112+
files: ['packages/docs/**/*.{ts,tsx}'],
113113
rules: {
114114
'no-console': 'off',
115115
},

packages/docs/src/routes/api/qwik/api.json

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@
244244
}
245245
],
246246
"kind": "Interface",
247-
"content": "```typescript\nexport interface AsyncComputedReadonlySignal<T = unknown> extends ReadonlySignal<T> \n```\n**Extends:** [ReadonlySignal](#readonlysignal)<!-- -->&lt;T&gt;",
247+
"content": "```typescript\nexport interface AsyncComputedReadonlySignal<T = unknown> extends ComputedSignal<T> \n```\n**Extends:** [ComputedSignal](#computedsignal)<!-- -->&lt;T&gt;",
248248
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/reactive-primitives/signal.public.ts",
249249
"mdFile": "core.asynccomputedreadonlysignal.md"
250250
},
@@ -404,7 +404,7 @@
404404
}
405405
],
406406
"kind": "Interface",
407-
"content": "A computed signal is a signal which is calculated from other signals. When the signals change, the computed signal is recalculated, and if the result changed, all tasks which are tracking the signal will be re-run and all components that read the signal will be re-rendered.\n\n\n```typescript\nexport interface ComputedSignal<T> extends ReadonlySignal<T> \n```\n**Extends:** [ReadonlySignal](#readonlysignal)<!-- -->&lt;T&gt;\n\n\n<table><thead><tr><th>\n\nMethod\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\n[force()](#computedsignal-force)\n\n\n</td><td>\n\nUse this to force recalculation and running subscribers, for example when the calculated value mutates but remains the same object. Useful for third-party libraries.\n\n\n</td></tr>\n</tbody></table>",
407+
"content": "A computed signal is a signal which is calculated from other signals. When the signals change, the computed signal is recalculated, and if the result changed, all tasks which are tracking the signal will be re-run and all components that read the signal will be re-rendered.\n\n\n```typescript\nexport interface ComputedSignal<T> extends ReadonlySignal<T> \n```\n**Extends:** [ReadonlySignal](#readonlysignal)<!-- -->&lt;T&gt;\n\n\n<table><thead><tr><th>\n\nMethod\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\n[force()](#computedsignal-force)\n\n\n</td><td>\n\nUse this to force running subscribers, for example when the calculated value mutates but remains the same object.\n\n\n</td></tr>\n<tr><td>\n\n[invalidate()](#computedsignal-invalidate)\n\n\n</td><td>\n\nUse this to force recalculation and running subscribers, for example when the calculated value mutates but remains the same object.\n\n\n</td></tr>\n</tbody></table>",
408408
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/reactive-primitives/signal.public.ts",
409409
"mdFile": "core.computedsignal.md"
410410
},
@@ -669,7 +669,7 @@
669669
}
670670
],
671671
"kind": "MethodSignature",
672-
"content": "Use this to force recalculation and running subscribers, for example when the calculated value mutates but remains the same object. Useful for third-party libraries.\n\n\n```typescript\nforce(): void;\n```\n**Returns:**\n\nvoid",
672+
"content": "Use this to force running subscribers, for example when the calculated value mutates but remains the same object.\n\n\n```typescript\nforce(): void;\n```\n**Returns:**\n\nvoid",
673673
"mdFile": "core.computedsignal.force.md"
674674
},
675675
{
@@ -804,6 +804,23 @@
804804
"content": "```typescript\ninterface IntrinsicElements extends LenientQwikElements \n```\n**Extends:** LenientQwikElements",
805805
"mdFile": "core.qwikjsx.intrinsicelements.md"
806806
},
807+
{
808+
"name": "invalidate",
809+
"id": "computedsignal-invalidate",
810+
"hierarchy": [
811+
{
812+
"name": "ComputedSignal",
813+
"id": "computedsignal-invalidate"
814+
},
815+
{
816+
"name": "invalidate",
817+
"id": "computedsignal-invalidate"
818+
}
819+
],
820+
"kind": "MethodSignature",
821+
"content": "Use this to force recalculation and running subscribers, for example when the calculated value mutates but remains the same object.\n\n\n```typescript\ninvalidate(): void;\n```\n**Returns:**\n\nvoid",
822+
"mdFile": "core.computedsignal.invalidate.md"
823+
},
807824
{
808825
"name": "isSignal",
809826
"id": "issignal",

packages/docs/src/routes/api/qwik/index.mdx

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,10 +130,10 @@ export type AsyncComputedFn<T> = (ctx: AsyncComputedCtx) => Promise<T>;
130130
## AsyncComputedReadonlySignal
131131

132132
```typescript
133-
export interface AsyncComputedReadonlySignal<T = unknown> extends ReadonlySignal<T>
133+
export interface AsyncComputedReadonlySignal<T = unknown> extends ComputedSignal<T>
134134
```
135135
136-
**Extends:** [ReadonlySignal](#readonlysignal)&lt;T&gt;
136+
**Extends:** [ComputedSignal](#computedsignal)&lt;T&gt;
137137
138138
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/reactive-primitives/signal.public.ts)
139139
@@ -477,7 +477,16 @@ Description
477477
478478
</td><td>
479479
480-
Use this to force recalculation and running subscribers, for example when the calculated value mutates but remains the same object. Useful for third-party libraries.
480+
Use this to force running subscribers, for example when the calculated value mutates but remains the same object.
481+
482+
</td></tr>
483+
<tr><td>
484+
485+
[invalidate()](#computedsignal-invalidate)
486+
487+
</td><td>
488+
489+
Use this to force recalculation and running subscribers, for example when the calculated value mutates but remains the same object.
481490
482491
</td></tr>
483492
</tbody></table>
@@ -1291,7 +1300,7 @@ export type EventHandler<EV = Event, EL = Element> = {
12911300
12921301
## force
12931302
1294-
Use this to force recalculation and running subscribers, for example when the calculated value mutates but remains the same object. Useful for third-party libraries.
1303+
Use this to force running subscribers, for example when the calculated value mutates but remains the same object.
12951304
12961305
```typescript
12971306
force(): void;
@@ -1589,6 +1598,18 @@ interface IntrinsicElements extends LenientQwikElements
15891598
15901599
**Extends:** LenientQwikElements
15911600
1601+
## invalidate
1602+
1603+
Use this to force recalculation and running subscribers, for example when the calculated value mutates but remains the same object.
1604+
1605+
```typescript
1606+
invalidate(): void;
1607+
```
1608+
1609+
**Returns:**
1610+
1611+
void
1612+
15921613
## isSignal
15931614
15941615
```typescript

packages/qwik-router/src/runtime/src/qwik-router-component.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import {
1515
useStyles$,
1616
useTask$,
1717
type QRL,
18-
type Signal,
1918
} from '@qwik.dev/core';
2019
import {
2120
_getContextElement,
@@ -28,6 +27,7 @@ import {
2827
_getDomContainer,
2928
type _DomContainer,
3029
SerializerSymbol,
30+
type AsyncComputedReadonlySignal,
3131
} from '@qwik.dev/core/internal';
3232
import { clientNavigate } from './client-navigate';
3333
import { CLIENT_DATA_CACHE, Q_ROUTE } from './constants';
@@ -181,7 +181,7 @@ export const QwikRouterProvider = component$<QwikRouterProps>((props) => {
181181
};
182182

183183
const loadersObject: Record<string, unknown> = {};
184-
const loaderState: Record<string, Signal<unknown>> = {};
184+
const loaderState: Record<string, AsyncComputedReadonlySignal<unknown>> = {};
185185
for (const [key, value] of Object.entries(env.response.loaders)) {
186186
loadersObject[key] = value;
187187
loaderState[key] = createLoaderSignal(
@@ -516,7 +516,7 @@ export const QwikRouterProvider = component$<QwikRouterProps>((props) => {
516516
if (loaders) {
517517
const container = _getContextContainer();
518518
for (const [key, value] of Object.entries(loaders)) {
519-
const signal = loaderState[key] as Signal<unknown>;
519+
const signal = loaderState[key];
520520
const awaitedValue = await value;
521521
loadersObject[key] = awaitedValue;
522522
if (!signal) {
@@ -528,7 +528,7 @@ export const QwikRouterProvider = component$<QwikRouterProps>((props) => {
528528
container
529529
);
530530
} else {
531-
(signal as any).force();
531+
signal.invalidate();
532532
}
533533
}
534534
}

packages/qwik/src/core/qwik.core.api.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const $: <T>(expression: T) => QRL<T>;
2222
export type AsyncComputedFn<T> = (ctx: AsyncComputedCtx) => Promise<T>;
2323

2424
// @public (undocumented)
25-
export interface AsyncComputedReadonlySignal<T = unknown> extends ReadonlySignal<T> {
25+
export interface AsyncComputedReadonlySignal<T = unknown> extends ComputedSignal<T> {
2626
}
2727

2828
// @public (undocumented)
@@ -100,6 +100,7 @@ export type ComputedReturnType<T> = T extends Promise<any> ? never : ComputedSig
100100
// @public
101101
export interface ComputedSignal<T> extends ReadonlySignal<T> {
102102
force(): void;
103+
invalidate(): void;
103104
}
104105

105106
// @internal (undocumented)

packages/qwik/src/core/reactive-primitives/impl/async-computed-signal-impl.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ export class AsyncComputedSignalImpl<T>
9898
return this.$untrackedError$;
9999
}
100100

101-
override $invalidate$() {
102-
super.$invalidate$();
101+
override invalidate() {
102+
super.invalidate();
103103
this.$promiseValue$ = NEEDS_COMPUTATION;
104104
}
105105

packages/qwik/src/core/reactive-primitives/impl/computed-signal-impl.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { tryGetInvokeContext } from '../../use/use-core';
88
import { throwIfQRLNotResolved } from '../utils';
99
import type { BackRef } from '../cleanup';
1010
import { getSubscriber } from '../subscriber';
11-
import type { ComputedSignalFlags, ComputeQRL, EffectSubscription } from '../types';
11+
import { ComputedSignalFlags, ComputeQRL, EffectSubscription } from '../types';
1212
import { _EFFECT_BACK_REF, EffectProperty, NEEDS_COMPUTATION, SignalFlags } from '../types';
1313
import { SignalImpl } from './signal-impl';
1414
import type { QRLInternal } from '../../shared/qrl/qrl-class';
@@ -42,7 +42,8 @@ export class ComputedSignalImpl<T, S extends QRLInternal = ComputeQRL<T>>
4242
fn: S,
4343
// We need a separate flag to know when the computation needs running because
4444
// we need the old value to know if effects need running after computation
45-
flags: SignalFlags | ComputedSignalFlags = SignalFlags.INVALID
45+
flags: SignalFlags | ComputedSignalFlags = SignalFlags.INVALID |
46+
ComputedSignalFlags.SERIALIZATION_STRATEGY_ALWAYS
4647
) {
4748
// The value is used for comparison when signals trigger, which can only happen
4849
// when it was calculated before. Therefore we can pass whatever we like.
@@ -51,7 +52,7 @@ export class ComputedSignalImpl<T, S extends QRLInternal = ComputeQRL<T>>
5152
this.$flags$ = flags;
5253
}
5354

54-
$invalidate$() {
55+
invalidate() {
5556
this.$flags$ |= SignalFlags.INVALID;
5657
this.$forceRunEffects$ = false;
5758
this.$container$?.$scheduler$(
@@ -67,8 +68,13 @@ export class ComputedSignalImpl<T, S extends QRLInternal = ComputeQRL<T>>
6768
* remained the same object
6869
*/
6970
force() {
70-
this.$invalidate$();
7171
this.$forceRunEffects$ = true;
72+
this.$container$?.$scheduler$(
73+
ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS,
74+
null,
75+
this,
76+
this.$effects$
77+
);
7278
}
7379

7480
get untrackedValue() {

packages/qwik/src/core/reactive-primitives/impl/serializer-signal-impl.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@ import type { Container } from '../../shared/types';
44
import { trackSignal } from '../../use/use-core';
55
import { throwIfQRLNotResolved } from '../utils';
66
import type { SerializerArg } from '../types';
7-
import { EffectProperty, NEEDS_COMPUTATION, SignalFlags, type ComputeQRL } from '../types';
7+
import {
8+
ComputedSignalFlags,
9+
EffectProperty,
10+
NEEDS_COMPUTATION,
11+
SignalFlags,
12+
type ComputeQRL,
13+
} from '../types';
814
import { ComputedSignalImpl } from './computed-signal-impl';
915

1016
const DEBUG = false;
@@ -19,7 +25,11 @@ const log = (...args: any[]) => console.log('SERIALIZER SIGNAL', ...args.map(qwi
1925
*/
2026
export class SerializerSignalImpl<T, S> extends ComputedSignalImpl<T> {
2127
constructor(container: Container | null, argQrl: QRLInternal<SerializerArg<T, S>>) {
22-
super(container, argQrl as unknown as ComputeQRL<T>);
28+
super(
29+
container,
30+
argQrl as unknown as ComputeQRL<T>,
31+
SignalFlags.INVALID | ComputedSignalFlags.SERIALIZATION_STRATEGY_ALWAYS
32+
);
2333
}
2434
$didInitialize$: boolean = false;
2535

@@ -39,7 +49,7 @@ export class SerializerSignalImpl<T, S> extends ComputedSignalImpl<T> {
3949
const untrackedValue = trackSignal(
4050
() =>
4151
this.$didInitialize$
42-
? update?.(currentValue as T)
52+
? update?.(currentValue as T) || currentValue
4353
: deserialize(currentValue as Awaited<S>),
4454
this,
4555
EffectProperty.VNODE,

packages/qwik/src/core/reactive-primitives/impl/wrapped-signal-impl.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { QError, qError } from '../../shared/error/error';
33
import type { Container, HostElement } from '../../shared/types';
44
import { ChoreType } from '../../shared/util-chore-type';
55
import { trackSignal } from '../../use/use-core';
6-
import { triggerEffects } from '../utils';
76
import type { BackRef } from '../cleanup';
87
import type { AllSignalFlags, EffectSubscription } from '../types';
98
import {
@@ -41,7 +40,7 @@ export class WrappedSignalImpl<T> extends SignalImpl<T> implements BackRef {
4140
this.$flags$ = flags;
4241
}
4342

44-
$invalidate$() {
43+
invalidate() {
4544
this.$flags$ |= SignalFlags.INVALID;
4645
this.$forceRunEffects$ = false;
4746
this.$container$?.$scheduler$(
@@ -57,9 +56,13 @@ export class WrappedSignalImpl<T> extends SignalImpl<T> implements BackRef {
5756
* remained the same object.
5857
*/
5958
force() {
60-
this.$flags$ |= SignalFlags.INVALID;
61-
this.$forceRunEffects$ = false;
62-
triggerEffects(this.$container$, this, this.$effects$);
59+
this.$forceRunEffects$ = true;
60+
this.$container$?.$scheduler$(
61+
ChoreType.RECOMPUTE_AND_SCHEDULE_EFFECTS,
62+
this.$hostElement$,
63+
this,
64+
this.$effects$
65+
);
6366
}
6467

6568
get untrackedValue() {

packages/qwik/src/core/reactive-primitives/signal-api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const createComputedSignal = <T>(
2727
return new ComputedSignalImpl<T>(
2828
options?.container || null,
2929
qrl as ComputeQRL<T>,
30-
getComputedSignalFlags(options?.serializationStrategy || 'never')
30+
getComputedSignalFlags(options?.serializationStrategy || 'always')
3131
);
3232
};
3333

0 commit comments

Comments
 (0)