-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
Describe the bug
I believe this issue is a continuation of #15590. I was excited to see the fix for this issue, and immediately updated so I could remove some workarounds I had in place for my test suite. To my surprise, removing the workarounds caused the tests to fail.
I have JS module that takes a signal as input, feeds that signal into a mutable $derived
internally, and exposes an onChange
method to optimistically update the $derived
. The module and tests look something like this:
export type AppStateOptions = Readonly<{
source: () => string;
}>;
export interface AppState {
value: string;
onChange: (nextValue: string) => void;
}
export const createAppState = (
options: AppStateOptions
): AppState => {
const source = $derived(options.source());
let value = $derived(source);
const onChange = (nextValue: string) => {
value = nextValue;
};
return {
get value() {
return value;
},
onChange,
};
};
import { test, expect } from "vitest";
import * as Subject from "../app-state.svelte";
test("optimistically updates value", () => {
const result = Subject.createAppState({ source: () => "wrong" });
result.onChange("right");
expect(result.value).toBe("right");
});
This test fails!
FAIL src/lib/__tests__/app-state.svelte.spec.ts > optimistically updates value
AssertionError: expected 'wrong' to be 'right' // Object.is equality
Expected: "right"
Received: "wrong"
Just like in #15590, if I read result.value
before calling onChange
. The test passes.
+ void result.value;
result.onChange("right");
expect(result.value).toBe("right");
Interestingly, removing the intermediate const source = $derived(options.source())
also fixes the issue:
- const source = $derived(options.source());
- let value = $derived(source);
+ let value = $derived(options.source());
At this point, this is mostly an annoyance in testing. Outside of this particular issue, though, we've been having persistent issues with $derived
chains failing to update when expected. These issues have proved difficult to minimally reproduce, but I will file more issues if/when I'm able to boil them down
Reproduction
This was a bit tricky to reproduce in the REPL - it does not repro in the <script>
tag of a component. I was, however, able to repro by placing the code in question inside a button's click handler:
System Info
System:
OS: macOS 14.3.1
CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
Memory: 575.77 MB / 32.00 GB
Shell: 5.9 - /usr/local/bin/zsh
Binaries:
Node: 22.14.0 - /usr/local/bin/node
npm: 10.9.2 - /usr/local/bin/npm
pnpm: 9.15.5 - ~/.nvs/default/bin/pnpm
Browsers:
Chrome: 123.0.6312.86
Safari: 17.3.1
npmPackages:
svelte: latest => 5.25.10
Severity
annoyance