From e71787f78c6a6bcd3fd043d7459a669e00f1e196 Mon Sep 17 00:00:00 2001 From: David Di Biase <1168397+davedbase@users.noreply.github.com> Date: Sat, 18 Apr 2026 08:39:33 -0400 Subject: [PATCH 1/3] Initial implementation for Solid 2.0 --- package.json | 2 +- packages/timer/README.md | 128 +++++++------ packages/timer/package.json | 6 +- packages/timer/src/index.ts | 116 ++++++------ packages/timer/test/index.test.ts | 288 +++++++++++++++++++++++++++--- pnpm-lock.yaml | 119 ++++++++---- 6 files changed, 483 insertions(+), 176 deletions(-) diff --git a/package.json b/package.json index a2614f8c7..9d124550c 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "rehype-highlight": "^7.0.2", "rehype-slug": "^6.0.0", "remark-gfm": "^4.0.1", - "solid-js": "^1.9.7", + "solid-js": "2.0.0-experimental.16", "typescript": "^5.8.3", "vinxi": "^0.5.7", "vite": "^6.3.5", diff --git a/packages/timer/README.md b/packages/timer/README.md index eef33f1f8..dba20c0c7 100644 --- a/packages/timer/README.md +++ b/packages/timer/README.md @@ -10,110 +10,126 @@ Timer primitives related to [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/setInterval) and [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout): -- [`makeTimer`](#maketimer) - Makes an automatically cleaned up timer. -- [`createTimer`](#createtimer) - [makeTimer](#maketimer), but with a fully reactive delay -- [`createTimeoutLoop`](#createtimeoutloop) - Like createInterval, except the delay only updates between executions. -- [`createPolled`](#createpolled) - Polls a function periodically. Returns an to the latest polled value. -- [`createIntervalCounter`](#createintervalcounter) - Creates a counter which increments periodically. +- [`makeTimer`](#maketimer) - Creates a timer and returns a function to clear it. No reactive lifecycle — the caller decides cleanup. +- [`createTimer`](#createtimer) - Reactive timer with an optionally reactive delay and automatic cleanup. +- [`createTimeoutLoop`](#createtimeoutloop) - Like `createTimer` with `setInterval`, but the delay only updates between executions. +- [`createPolled`](#createpolled) - Polls a function periodically and returns an accessor to its latest value. +- [`createIntervalCounter`](#createintervalcounter) - A counter that increments periodically. ## Installation ```bash npm install @solid-primitives/timer # or -yarn add @solid-primitives/timer +pnpm add @solid-primitives/timer ``` ## How to use it -### Basic Usage +### makeTimer -#### makeTimer +Creates a timer ([setTimeout](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout) or [setInterval](https://developer.mozilla.org/en-US/docs/Web/API/setInterval)) and returns a function to clear it. This is a base primitive with no reactive lifecycle integration — the caller is responsible for cleanup. -Makes a timer ([setTimeout](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout) or [setInterval](https://developer.mozilla.org/en-US/docs/Web/API/setInterval)), automatically cleaning up when the current reactive scope is disposed. +To tie cleanup to a reactive scope, pass the returned function to `onCleanup`: ```ts -const callback = () => {}; -const disposeTimeout = makeTimer(callback, 1000, setTimeout); -const disposeInterval = makeTimer(callback, 1000, setInterval); +import { onCleanup } from "solid-js"; +import { makeTimer } from "@solid-primitives/timer"; + +// Manual cleanup +const clear = makeTimer(() => console.log("tick"), 1000, setInterval); // ... -dispose(); // clean up manually if needed +clear(); + +// Tied to a reactive scope +onCleanup(makeTimer(() => console.log("tick"), 1000, setInterval)); ``` -#### createTimer +### createTimer + +A reactive timer whose delay can be a static number or a reactive accessor. When the delay accessor returns `false`, the timer is disabled. Automatically cleans up when the reactive scope is disposed. -[makeTimer](#maketimer), but with a fully reactive delay. The delay can also be `false`, in which case the timer is disabled. Does not return a dispose function. +When the delay changes, the elapsed fraction of the previous delay carries forward — so changing from 1000ms to 2000ms after 250ms elapsed will fire the next callback after 1500ms, not 2000ms. ```ts -const callback = () => {}; -createTimer(callback, 1000, setTimeout); -createTimer(callback, 1000, setInterval); -// with reactive delay -const callback = () => {}; +import { createSignal } from "solid-js"; +import { createTimer } from "@solid-primitives/timer"; + +// Static delay +createTimer(() => console.log("timeout"), 1000, setTimeout); +createTimer(() => console.log("interval"), 1000, setInterval); + +// Reactive delay with pause support const [paused, setPaused] = createSignal(false); const [delay, setDelay] = createSignal(1000); -createTimer(callback, () => !paused() && delay(), setTimeout); -createTimer(callback, () => !paused() && delay(), setInterval); -// ... -setDelay(500); -// pause -setPaused(true); -// unpause -setPaused(false); + +createTimer(() => console.log("tick"), () => !paused() && delay(), setInterval); + +setDelay(500); // change interval +setPaused(true); // pause +setPaused(false); // resume ``` -#### createTimeoutLoop +### createTimeoutLoop -Similar to an interval created with [createTimer](#createtimer), but the delay does not update until the callback is executed. +Similar to `createTimer` with `setInterval`, but the delay is only read between executions rather than reactively. This means a delay change takes effect after the current interval completes. ```ts -const callback = () => {}; -createTimeoutLoop(callback, 1000); -// with reactive delay -const callback = () => {}; +import { createSignal } from "solid-js"; +import { createTimeoutLoop } from "@solid-primitives/timer"; + +// Static delay +createTimeoutLoop(() => console.log("loop"), 1000); + +// Reactive delay — updates between executions const [delay, setDelay] = createSignal(1000); -createTimeoutLoop(callback, delay); +createTimeoutLoop(() => console.log("loop"), delay); // ... -setDelay(500); +setDelay(500); // takes effect after the current interval fires ``` -#### createPolled +### createPolled -Periodically polls a function, returning an accessor to its last return value. +Polls a function periodically and returns an accessor to its latest return value. The function is called immediately on creation, then after each interval. If the polling function reads reactive signals, the accessor also updates when those signals change. ```tsx +import { createSignal } from "solid-js"; +import { createPolled } from "@solid-primitives/timer"; + +// Poll current time every second const date = createPolled(() => new Date(), 1000); -// ... -The time is: {date()}; -// with reactive delay +The time is: {date()} + +// Reactive source — updates on interval AND when source changes +const [id, setId] = createSignal(1); +const user = createPolled(() => cache.get(id()), 5000); + +// Reactive delay const [delay, setDelay] = createSignal(1000); -createPolled(() => new Date(), delay); -// ... +const polled = createPolled(() => new Date(), delay); setDelay(500); ``` -#### createIntervalCounter +### createIntervalCounter -A counter which increments periodically based on the delay. +A counter that starts at `0` and increments by one each interval. Accepts a static or reactive delay. ```tsx +import { createSignal } from "solid-js"; +import { createIntervalCounter } from "@solid-primitives/timer"; + const count = createIntervalCounter(1000); -// ... -Count: {count()}; -// with reactive delay +Count: {count()} + +// Reactive delay const [delay, setDelay] = createSignal(1000); -createIntervalCounter(delay); -// ... +const count = createIntervalCounter(delay); setDelay(500); ``` -### Note on Reactive Delays - -When a delay is changed, the fraction of the existing delay already elapsed be carried forward to the new delay. For instance, a delay of 1000ms changed to 2000ms after 250ms will be considered 1/4 done, and next callback will be executed after 250ms + 1500ms. Afterwards, the new delay will be used. - -## Demo +## Note on Reactive Delays -You may view a working example here: https://codesandbox.io/s/solid-primitives-timer-6n7dt?file=/src/index.tsx +When a delay changes, the fraction of the current interval already elapsed carries over to the new delay. For example, if a 1000ms delay is changed to 2000ms after 250ms (25% done), the first callback with the new delay fires after 1500ms (75% of 2000ms), and subsequent callbacks fire every 2000ms. ## Changelog diff --git a/packages/timer/package.json b/packages/timer/package.json index d6cfece84..2cd66474a 100644 --- a/packages/timer/package.json +++ b/packages/timer/package.json @@ -59,10 +59,12 @@ "primitives" ], "peerDependencies": { - "solid-js": "^1.6.12" + "@solidjs/web": "2.0.0-experimental.16", + "solid-js": "2.0.0-experimental.16" }, "typesVersions": {}, "devDependencies": { - "solid-js": "^1.9.7" + "@solidjs/web": "2.0.0-experimental.16", + "solid-js": "2.0.0-experimental.16" } } diff --git a/packages/timer/src/index.ts b/packages/timer/src/index.ts index b3ee51e10..0ebd74d73 100644 --- a/packages/timer/src/index.ts +++ b/packages/timer/src/index.ts @@ -7,18 +7,18 @@ import { type SignalOptions, createMemo, } from "solid-js"; -import { isServer } from "solid-js/web"; +import { isServer } from "@solidjs/web"; export type TimeoutSource = number | Accessor; /** - * Create a timer ({@link setTimeout} or {@link setInterval}) - * which automatically clears when the reactive scope is disposed. + * Create a timer ({@link setTimeout} or {@link setInterval}) and return a function to clear it. + * Does not integrate with the reactive lifecycle — the caller is responsible for cleanup. * * @param fn Function to be called every {@link delay}. * @param delay Number representing the time between executions of {@link fn} in ms. * @param timer The timer to create: {@link setTimeout} or {@link setInterval}. - * @returns Function to manually clear the interval. + * @returns Function to clear the timer. */ export const makeTimer = ( fn: VoidFunction, @@ -28,9 +28,8 @@ export const makeTimer = ( if (isServer) { return () => void 0; } - const intervalId = timer(fn, delay); - const clear = () => clearInterval(intervalId); - return onCleanup(clear); + const id = timer(fn, delay); + return () => clearInterval(id); }; /** @@ -53,61 +52,67 @@ export const createTimer = ( return void 0; } if (typeof delay === "number") { - makeTimer(fn, delay, timer); + onCleanup(makeTimer(fn, delay, timer)); return; } let done = false; let prevTime = performance.now(); - let fractionDone: number = 0; + let fractionDone = 0; let shouldHandleFraction = false; + const callHandler = () => { untrack(fn); prevTime = performance.now(); done = timer === setTimeout; }; - createEffect((prevDelay?: number | false) => { - if (done) return; - const currDelay = delay(); - if (currDelay === false) { - // if false, update fractionDone and pause - if (prevDelay) fractionDone += (performance.now() - prevTime) / prevDelay; - return currDelay; - } + createEffect( + () => delay(), + (currDelay: number | false, prevDelay?: number | false) => { + if (done) return; + + if (currDelay === false) { + if (typeof prevDelay === "number") { + fractionDone += (performance.now() - prevTime) / prevDelay; + } + return; + } - // if resuming from pause, set prevTime to now - if (prevDelay === false) prevTime = performance.now(); + if (prevDelay === false) prevTime = performance.now(); - if (shouldHandleFraction) { - if (prevDelay) fractionDone += (performance.now() - prevTime) / prevDelay; - prevTime = performance.now(); - if (fractionDone >= 1) { - fractionDone = 0; - callHandler(); - } else if (fractionDone > 0) { - // 0 < fractionDone < 1, need to reconcile the delay - // signal to rerun this effect when we're done reconciling the delay - const [listen, rerunEffect] = createSignal(undefined, { equals: false }); - listen(); - makeTimer( - () => { - fractionDone = 0; + if (shouldHandleFraction) { + if (typeof prevDelay === "number") { + fractionDone += (performance.now() - prevTime) / prevDelay; + } + prevTime = performance.now(); + if (fractionDone >= 1) { + fractionDone = 0; + callHandler(); + } else if (fractionDone > 0) { + const reconcileDelay = (1 - fractionDone) * currDelay; + fractionDone = 0; + let mainId: ReturnType | undefined; + const reconcileId = setTimeout(() => { shouldHandleFraction = false; - rerunEffect(); callHandler(); - }, - (1 - fractionDone) * currDelay, - setTimeout, - ); - return currDelay; + if (!done) { + mainId = timer(callHandler, currDelay); + } + }, reconcileDelay); + return () => { + clearTimeout(reconcileId); + if (mainId !== undefined) clearInterval(mainId); + }; + } } - } - shouldHandleFraction = true; - makeTimer(callHandler, currDelay, timer); - return currDelay; - }); + fractionDone = 0; + shouldHandleFraction = true; + const id = timer(callHandler, currDelay); + return () => clearInterval(id); + }, + ); }; /** @@ -123,22 +128,21 @@ export const createTimeoutLoop = (handler: VoidFunction, timeout: TimeoutSource) return void 0; } if (typeof timeout === "number") { - makeTimer(handler, timeout, setInterval); + onCleanup(makeTimer(handler, timeout, setInterval)); return; } const [currentTimeout, setCurrentTimeout] = createSignal(untrack(timeout)); - createEffect(() => { - const currTimeout = currentTimeout(); - if (currTimeout === false) return; - makeTimer( - () => { + createEffect( + () => currentTimeout(), + (currTimeout: number | false) => { + if (currTimeout === false) return; + const id = setInterval(() => { handler(); - setCurrentTimeout(timeout); - }, - currTimeout, - setInterval, - ); - }); + setCurrentTimeout((timeout as Accessor)()); + }, currTimeout); + return () => clearInterval(id); + }, + ); }; /** diff --git a/packages/timer/test/index.test.ts b/packages/timer/test/index.test.ts index 4c53a641f..3dfcba5b4 100644 --- a/packages/timer/test/index.test.ts +++ b/packages/timer/test/index.test.ts @@ -1,6 +1,12 @@ -import { batch, createRoot, createSignal } from "solid-js"; +import { createRoot, createSignal, flush, onCleanup } from "solid-js"; import { describe, test, expect, vi, beforeEach, afterAll, beforeAll } from "vitest"; -import { createPolled, createTimer } from "../src/index.js"; +import { + makeTimer, + createTimer, + createTimeoutLoop, + createPolled, + createIntervalCounter, +} from "../src/index.js"; beforeAll(() => { vi.useFakeTimers(); @@ -14,8 +20,60 @@ afterAll(() => { vi.useRealTimers(); }); -describe("createTimes", () => { - test("disposing of root disposes of timers", () => { +// --------------------------------------------------------------------------- +// makeTimer +// --------------------------------------------------------------------------- + +describe("makeTimer", () => { + test("setTimeout fires once after delay", () => { + let count = 0; + makeTimer(() => count++, 100, setTimeout); + vi.advanceTimersByTime(50); + expect(count).toBe(0); + vi.advanceTimersByTime(60); + expect(count).toBe(1); + vi.advanceTimersByTime(200); + expect(count).toBe(1); + }); + + test("setInterval fires repeatedly", () => { + let count = 0; + const clear = makeTimer(() => count++, 100, setInterval); + vi.advanceTimersByTime(350); + expect(count).toBe(3); + clear(); + }); + + test("returned function clears the timer", () => { + let count = 0; + const clear = makeTimer(() => count++, 100, setInterval); + vi.advanceTimersByTime(150); + expect(count).toBe(1); + clear(); + vi.advanceTimersByTime(300); + expect(count).toBe(1); + }); + + test("caller can register with onCleanup to tie to reactive scope", () => { + let count = 0; + const dispose = createRoot(dispose => { + onCleanup(makeTimer(() => count++, 100, setInterval)); + return dispose; + }); + vi.advanceTimersByTime(150); + expect(count).toBe(1); + dispose(); + vi.advanceTimersByTime(200); + expect(count).toBe(1); + }); +}); + +// --------------------------------------------------------------------------- +// createTimer +// --------------------------------------------------------------------------- + +describe("createTimer", () => { + test("disposing of root clears timers", () => { let timeout_count = 0; let interval_count = 0; @@ -31,7 +89,7 @@ describe("createTimes", () => { expect(interval_count).toBe(0); }); - test("createTimer calls and disposes when expected with number", () => { + test("number delay: fires and disposes correctly", () => { let timeout_count = 0; let interval_count = 0; @@ -41,25 +99,25 @@ describe("createTimes", () => { return dispose; }); - vi.advanceTimersByTime(50); // 0.5, account for drift + vi.advanceTimersByTime(50); expect(timeout_count).toBe(0); expect(interval_count).toBe(0); - vi.advanceTimersByTime(100); // 1.5 + vi.advanceTimersByTime(100); expect(timeout_count).toBe(1); expect(interval_count).toBe(1); - vi.advanceTimersByTime(100); // 2.5 - expect(timeout_count).toBe(1); + vi.advanceTimersByTime(100); + expect(timeout_count).toBe(1); // setTimeout fires only once expect(interval_count).toBe(2); dispose(); - vi.advanceTimersByTime(100); // 3.5 + vi.advanceTimersByTime(100); expect(timeout_count).toBe(1); expect(interval_count).toBe(2); }); - test("createInterval calls when expected with accessor", () => { + test("accessor delay: pause and resume", () => { let timeout_count = 0; let interval_count = 0; @@ -81,7 +139,6 @@ describe("createTimes", () => { }); setPaused(true); - vi.advanceTimersByTime(300); setPaused(false); @@ -89,30 +146,127 @@ describe("createTimes", () => { expect(interval_count).toBe(0); setPaused(true); - vi.advanceTimersByTime(100); - batch(() => { - setPaused(false); - setDelay(100); - }); + setPaused(false); + setDelay(100); + flush(); vi.advanceTimersByTime(10); - expect(timeout_count).toBe(0); expect(interval_count).toBe(0); vi.advanceTimersByTime(160); - expect(timeout_count).toBe(1); expect(interval_count).toBe(1); dispose(); }); + + test("accessor delay: false disables the timer", () => { + let count = 0; + const [delay, setDelay] = createSignal(100); + + const dispose = createRoot(dispose => { + createTimer(() => count++, delay, setInterval); + return dispose; + }); + + flush(); + vi.advanceTimersByTime(100); + expect(count).toBe(1); + + setDelay(false); + flush(); + vi.advanceTimersByTime(500); + expect(count).toBe(1); + + setDelay(100); + flush(); + vi.advanceTimersByTime(100); + expect(count).toBe(2); + + dispose(); + }); +}); + +// --------------------------------------------------------------------------- +// createTimeoutLoop +// --------------------------------------------------------------------------- + +describe("createTimeoutLoop", () => { + test("number delay: fires repeatedly and stops on dispose", () => { + let count = 0; + const dispose = createRoot(dispose => { + createTimeoutLoop(() => count++, 100); + return dispose; + }); + vi.advanceTimersByTime(350); + expect(count).toBe(3); + dispose(); + vi.advanceTimersByTime(200); + expect(count).toBe(3); + }); + + test("delay only updates between executions", () => { + let count = 0; + const [delay, setDelay] = createSignal(100); + const dispose = createRoot(dispose => { + createTimeoutLoop(() => count++, delay); + return dispose; + }); + flush(); + + vi.advanceTimersByTime(100); // fires; setCurrentTimeout(100) — same, no re-run + expect(count).toBe(1); + + setDelay(200); + flush(); // commit delay._value=200 so the next callback reads it + + vi.advanceTimersByTime(100); // fires; reads delay()=200, setCurrentTimeout(200) + expect(count).toBe(2); + flush(); // effect re-runs: clear old 100ms interval, start new 200ms interval + + vi.advanceTimersByTime(199); + expect(count).toBe(2); + vi.advanceTimersByTime(1); + expect(count).toBe(3); + + dispose(); + }); + + test("false delay stops the loop after the current execution", () => { + let count = 0; + const [delay, setDelay] = createSignal(100); + const dispose = createRoot(dispose => { + createTimeoutLoop(() => count++, delay); + return dispose; + }); + flush(); + + vi.advanceTimersByTime(100); + expect(count).toBe(1); + + setDelay(false); + flush(); // commit delay._value=false so the next callback reads it + + vi.advanceTimersByTime(100); // fires; reads delay()=false, setCurrentTimeout(false) + expect(count).toBe(2); + flush(); // effect re-runs: clear interval, false → no new interval + + vi.advanceTimersByTime(500); + expect(count).toBe(2); + + dispose(); + }); }); +// --------------------------------------------------------------------------- +// createPolled +// --------------------------------------------------------------------------- + describe("createPolled", () => { - test("fn called initially and after timeout", () => { + test("fn called immediately and after each interval", () => { let n = 0; const { polled, dispose } = createRoot(dispose => ({ polled: createPolled(() => ++n, 100), @@ -121,16 +275,20 @@ describe("createPolled", () => { expect(polled()).toBe(1); vi.advanceTimersByTime(100); + flush(); expect(polled()).toBe(2); - dispose(); - expect(polled()).toBe(2); + vi.advanceTimersByTime(100); + flush(); + expect(polled()).toBe(3); + dispose(); vi.advanceTimersByTime(100); - expect(polled()).toBe(2); + flush(); + expect(polled()).toBe(3); }); - test("is reactive", () => { + test("is reactive to fn's signal dependencies", () => { const [source, setSource] = createSignal(0); const { polled, dispose } = createRoot(dispose => ({ @@ -140,10 +298,92 @@ describe("createPolled", () => { expect(polled()).toBe(0); setSource(1); + flush(); expect(polled()).toBe(1); dispose(); setSource(2); expect(polled()).toBe(1); }); + + test("initial value is passed to fn on first call", () => { + const { polled } = createRoot(dispose => ({ + polled: createPolled(prev => (prev ?? 10) + 1, 100, 10), + dispose, + })); + expect(polled()).toBe(11); + }); + + test("reactive delay", () => { + let n = 0; + const [delay, setDelay] = createSignal(100); + + const { polled, dispose } = createRoot(dispose => ({ + polled: createPolled(() => ++n, delay), + dispose, + })); + expect(polled()).toBe(1); + flush(); + + vi.advanceTimersByTime(100); + flush(); + expect(polled()).toBe(2); + + setDelay(50); + flush(); + vi.advanceTimersByTime(50); + flush(); + expect(polled()).toBe(3); + + dispose(); + }); +}); + +// --------------------------------------------------------------------------- +// createIntervalCounter +// --------------------------------------------------------------------------- + +describe("createIntervalCounter", () => { + test("starts at 0 and increments each interval", () => { + const { count, dispose } = createRoot(dispose => ({ + count: createIntervalCounter(100), + dispose, + })); + expect(count()).toBe(0); + + vi.advanceTimersByTime(100); + flush(); + expect(count()).toBe(1); + + vi.advanceTimersByTime(100); + flush(); + expect(count()).toBe(2); + + dispose(); + vi.advanceTimersByTime(100); + flush(); + expect(count()).toBe(2); + }); + + test("reactive delay", () => { + const [delay, setDelay] = createSignal(100); + const { count, dispose } = createRoot(dispose => ({ + count: createIntervalCounter(delay), + dispose, + })); + expect(count()).toBe(0); + flush(); + + vi.advanceTimersByTime(100); + flush(); + expect(count()).toBe(1); + + setDelay(50); + flush(); + vi.advanceTimersByTime(50); + flush(); + expect(count()).toBe(2); + + dispose(); + }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ecadfdb95..5147c1b03 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ importers: version: 1.0.1 '@solidjs/start': specifier: ^1.1.4 - version: 1.1.4(solid-js@1.9.7)(vinxi@0.5.7(@types/node@22.15.31)(db0@0.3.2)(ioredis@5.6.1)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0))(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0)) + version: 1.1.4(solid-js@2.0.0-experimental.16)(vinxi@0.5.7(@types/node@22.15.31)(db0@0.3.2)(ioredis@5.6.1)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0))(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0)) '@types/jsdom': specifier: ^21.1.7 version: 21.1.7 @@ -34,7 +34,7 @@ importers: version: 0.25.5 esbuild-plugin-solid: specifier: ^0.6.0 - version: 0.6.0(esbuild@0.25.5)(solid-js@1.9.7) + version: 0.6.0(esbuild@0.25.5)(solid-js@2.0.0-experimental.16) eslint: specifier: ^9.28.0 version: 9.28.0(jiti@2.4.2) @@ -69,8 +69,8 @@ importers: specifier: ^4.0.1 version: 4.0.1 solid-js: - specifier: ^1.9.7 - version: 1.9.7 + specifier: 2.0.0-experimental.16 + version: 2.0.0-experimental.16 typescript: specifier: ^5.8.3 version: 5.8.3 @@ -82,7 +82,7 @@ importers: version: 6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0) vite-plugin-solid: specifier: ^2.11.6 - version: 2.11.6(solid-js@1.9.7)(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0)) + version: 2.11.6(solid-js@2.0.0-experimental.16)(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0)) vitest: specifier: ^2.1.9 version: 2.1.9(@types/node@22.15.31)(jsdom@25.0.1)(sass@1.77.8)(terser@5.42.0) @@ -926,9 +926,12 @@ importers: packages/timer: devDependencies: + '@solidjs/web': + specifier: 2.0.0-experimental.16 + version: 2.0.0-experimental.16(solid-js@2.0.0-experimental.16) solid-js: - specifier: ^1.9.7 - version: 1.9.7 + specifier: 2.0.0-experimental.16 + version: 2.0.0-experimental.16 packages/transition-group: devDependencies: @@ -1048,10 +1051,10 @@ importers: version: link:../packages/utils '@solidjs/meta': specifier: ^0.29.3 - version: 0.29.4(solid-js@1.9.7) + version: 0.29.4(solid-js@2.0.0-experimental.16) '@solidjs/router': specifier: ^0.13.1 - version: 0.13.6(solid-js@1.9.7) + version: 0.13.6(solid-js@2.0.0-experimental.16) clsx: specifier: ^2.0.0 version: 2.1.1 @@ -1078,13 +1081,13 @@ importers: version: 1.77.8 solid-dismiss: specifier: ^1.7.121 - version: 1.8.2(solid-js@1.9.7) + version: 1.8.2(solid-js@2.0.0-experimental.16) solid-icons: specifier: ^1.1.0 - version: 1.1.0(solid-js@1.9.7) + version: 1.1.0(solid-js@2.0.0-experimental.16) solid-tippy: specifier: ^0.2.1 - version: 0.2.1(solid-js@1.9.7)(tippy.js@6.3.7) + version: 0.2.1(solid-js@2.0.0-experimental.16)(tippy.js@6.3.7) tippy.js: specifier: ^6.3.7 version: 6.3.7 @@ -2587,11 +2590,19 @@ packages: peerDependencies: solid-js: ^1.5.3 + '@solidjs/signals@0.11.3': + resolution: {integrity: sha512-udMfutYPOlcxKUmc5+n1QtarsxOiAlC6LJY2TqFyaMwdXgo+reiYUcYGDlOiAPXfCLE0lavZHQ/6GT5pJbXKBA==} + '@solidjs/start@1.1.4': resolution: {integrity: sha512-ma1TBYqoTju87tkqrHExMReM5Z/+DTXSmi30CCTavtwuR73Bsn4rVGqm528p4sL2koRMfAuBMkrhuttjzhL68g==} peerDependencies: vinxi: ^0.5.3 + '@solidjs/web@2.0.0-experimental.16': + resolution: {integrity: sha512-TcgvLKOYN2cIExX307SRxvd1aXj5eLaQUlGDLdQoQBqDHhuDdeZUfKLYrn/JOzWs1u5DYNOc+gR0SaG17vYsng==} + peerDependencies: + solid-js: ^2.0.0-experimental.16 + '@speed-highlight/core@1.2.7': resolution: {integrity: sha512-0dxmVj4gxg3Jg879kvFS/msl4s9F3T9UXC1InxgOf7t5NvcPD97u/WTA5vL/IxWHMn7qSxBozqrnnE2wvl1m8g==} @@ -5892,10 +5903,20 @@ packages: peerDependencies: seroval: ^1.0 + seroval-plugins@1.5.2: + resolution: {integrity: sha512-qpY0Cl+fKYFn4GOf3cMiq6l72CpuVaawb6ILjubOQ+diJ54LfOWaSSPsaswN8DRPIPW4Yq+tE1k5aKd7ILyaFg==} + engines: {node: '>=10'} + peerDependencies: + seroval: ^1.0 + seroval@1.3.2: resolution: {integrity: sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==} engines: {node: '>=10'} + seroval@1.5.2: + resolution: {integrity: sha512-xcRN39BdsnO9Tf+VzsE7b3JyTJASItIV1FVFewJKCFcW4s4haIKS3e6vj8PGB9qBwC7tnuOywQMdv5N4qkzi7Q==} + engines: {node: '>=10'} + serve-placeholder@2.0.2: resolution: {integrity: sha512-/TMG8SboeiQbZJWRlfTCqMs2DD3SZgWp0kDQePz9yUuCnDfDh/92gf7/PxGhzXTKBIPASIHxFcZndoNbp6QOLQ==} @@ -6001,6 +6022,9 @@ packages: solid-js@1.9.7: resolution: {integrity: sha512-/saTKi8iWEM233n5OSi1YHCCuh66ZIQ7aK2hsToPe4tqGm7qAejU1SwNuTPivbWAYq7SjuHVVYxxuZQNRbICiw==} + solid-js@2.0.0-experimental.16: + resolution: {integrity: sha512-zZ1dU7cR0EnvLnrYiRLQbCFiDw5blLdlqmofgLzKUYE1TCMWDcisBlSwz0Ez8l4yXB4adbdhtaYCuynH4xSq9A==} + solid-refresh@0.6.3: resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==} peerDependencies: @@ -8576,19 +8600,21 @@ snapshots: dependencies: solid-js: 1.9.7 - '@solidjs/meta@0.29.4(solid-js@1.9.7)': + '@solidjs/meta@0.29.4(solid-js@2.0.0-experimental.16)': dependencies: - solid-js: 1.9.7 + solid-js: 2.0.0-experimental.16 - '@solidjs/router@0.13.6(solid-js@1.9.7)': + '@solidjs/router@0.13.6(solid-js@2.0.0-experimental.16)': dependencies: - solid-js: 1.9.7 + solid-js: 2.0.0-experimental.16 '@solidjs/router@0.8.4(solid-js@1.9.7)': dependencies: solid-js: 1.9.7 - '@solidjs/start@1.1.4(solid-js@1.9.7)(vinxi@0.5.7(@types/node@22.15.31)(db0@0.3.2)(ioredis@5.6.1)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0))(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0))': + '@solidjs/signals@0.11.3': {} + + '@solidjs/start@1.1.4(solid-js@2.0.0-experimental.16)(vinxi@0.5.7(@types/node@22.15.31)(db0@0.3.2)(ioredis@5.6.1)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0))(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0))': dependencies: '@tanstack/server-functions-plugin': 1.121.0(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0)) '@vinxi/plugin-directives': 0.5.1(vinxi@0.5.7(@types/node@22.15.31)(db0@0.3.2)(ioredis@5.6.1)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0)) @@ -8601,16 +8627,22 @@ snapshots: seroval-plugins: 1.3.2(seroval@1.3.2) shiki: 1.29.2 source-map-js: 1.2.1 - terracotta: 1.0.6(solid-js@1.9.7) + terracotta: 1.0.6(solid-js@2.0.0-experimental.16) tinyglobby: 0.2.14 vinxi: 0.5.7(@types/node@22.15.31)(db0@0.3.2)(ioredis@5.6.1)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0) - vite-plugin-solid: 2.11.6(solid-js@1.9.7)(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0)) + vite-plugin-solid: 2.11.6(solid-js@2.0.0-experimental.16)(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0)) transitivePeerDependencies: - '@testing-library/jest-dom' - solid-js - supports-color - vite + '@solidjs/web@2.0.0-experimental.16(solid-js@2.0.0-experimental.16)': + dependencies: + seroval: 1.3.2 + seroval-plugins: 1.3.2(seroval@1.3.2) + solid-js: 2.0.0-experimental.16 + '@speed-highlight/core@1.2.7': {} '@supabase/auth-js@2.67.3': @@ -9975,13 +10007,13 @@ snapshots: has-tostringtag: 1.0.2 hasown: 2.0.2 - esbuild-plugin-solid@0.6.0(esbuild@0.25.5)(solid-js@1.9.7): + esbuild-plugin-solid@0.6.0(esbuild@0.25.5)(solid-js@2.0.0-experimental.16): dependencies: '@babel/core': 7.27.4 '@babel/preset-typescript': 7.27.1(@babel/core@7.27.4) babel-preset-solid: 1.9.6(@babel/core@7.27.4) esbuild: 0.25.5 - solid-js: 1.9.7 + solid-js: 2.0.0-experimental.16 transitivePeerDependencies: - supports-color @@ -12441,8 +12473,14 @@ snapshots: dependencies: seroval: 1.3.2 + seroval-plugins@1.5.2(seroval@1.5.2): + dependencies: + seroval: 1.5.2 + seroval@1.3.2: {} + seroval@1.5.2: {} + serve-placeholder@2.0.2: dependencies: defu: 6.1.4 @@ -12557,13 +12595,13 @@ snapshots: dot-case: 3.0.4 tslib: 2.8.1 - solid-dismiss@1.8.2(solid-js@1.9.7): + solid-dismiss@1.8.2(solid-js@2.0.0-experimental.16): dependencies: - solid-js: 1.9.7 + solid-js: 2.0.0-experimental.16 - solid-icons@1.1.0(solid-js@1.9.7): + solid-icons@1.1.0(solid-js@2.0.0-experimental.16): dependencies: - solid-js: 1.9.7 + solid-js: 2.0.0-experimental.16 solid-js@1.9.7: dependencies: @@ -12571,18 +12609,25 @@ snapshots: seroval: 1.3.2 seroval-plugins: 1.3.2(seroval@1.3.2) - solid-refresh@0.6.3(solid-js@1.9.7): + solid-js@2.0.0-experimental.16: + dependencies: + '@solidjs/signals': 0.11.3 + csstype: 3.1.3 + seroval: 1.5.2 + seroval-plugins: 1.5.2(seroval@1.5.2) + + solid-refresh@0.6.3(solid-js@2.0.0-experimental.16): dependencies: '@babel/generator': 7.27.5 '@babel/helper-module-imports': 7.27.1 '@babel/types': 7.27.6 - solid-js: 1.9.7 + solid-js: 2.0.0-experimental.16 transitivePeerDependencies: - supports-color - solid-tippy@0.2.1(solid-js@1.9.7)(tippy.js@6.3.7): + solid-tippy@0.2.1(solid-js@2.0.0-experimental.16)(tippy.js@6.3.7): dependencies: - solid-js: 1.9.7 + solid-js: 2.0.0-experimental.16 tippy.js: 6.3.7 solid-transition-group@0.2.3(solid-js@1.9.7): @@ -12591,9 +12636,9 @@ snapshots: '@solid-primitives/transition-group': 1.0.5(solid-js@1.9.7) solid-js: 1.9.7 - solid-use@0.9.1(solid-js@1.9.7): + solid-use@0.9.1(solid-js@2.0.0-experimental.16): dependencies: - solid-js: 1.9.7 + solid-js: 2.0.0-experimental.16 source-map-js@1.2.1: {} @@ -12814,10 +12859,10 @@ snapshots: term-size@2.2.1: {} - terracotta@1.0.6(solid-js@1.9.7): + terracotta@1.0.6(solid-js@2.0.0-experimental.16): dependencies: - solid-js: 1.9.7 - solid-use: 0.9.1(solid-js@1.9.7) + solid-js: 2.0.0-experimental.16 + solid-use: 0.9.1(solid-js@2.0.0-experimental.16) terser@5.42.0: dependencies: @@ -13244,14 +13289,14 @@ snapshots: - supports-color - terser - vite-plugin-solid@2.11.6(solid-js@1.9.7)(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0)): + vite-plugin-solid@2.11.6(solid-js@2.0.0-experimental.16)(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0)): dependencies: '@babel/core': 7.27.4 '@types/babel__core': 7.20.5 babel-preset-solid: 1.9.6(@babel/core@7.27.4) merge-anything: 5.1.7 - solid-js: 1.9.7 - solid-refresh: 0.6.3(solid-js@1.9.7) + solid-js: 2.0.0-experimental.16 + solid-refresh: 0.6.3(solid-js@2.0.0-experimental.16) vite: 6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0) vitefu: 1.0.6(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0)) transitivePeerDependencies: From 55298c0575a2cc669afd9772607ba2ea90631a89 Mon Sep 17 00:00:00 2001 From: David Di Biase <1168397+davedbase@users.noreply.github.com> Date: Sat, 18 Apr 2026 18:23:06 -0400 Subject: [PATCH 2/3] Attempted a batch and regression test addition --- packages/timer/README.md | 12 ++++++++---- packages/timer/src/index.ts | 20 +++++++++++++++----- packages/timer/test/index.test.ts | 22 ++++++++++++++++++++++ 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/packages/timer/README.md b/packages/timer/README.md index dba20c0c7..a08a4ea4e 100644 --- a/packages/timer/README.md +++ b/packages/timer/README.md @@ -63,9 +63,13 @@ createTimer(() => console.log("interval"), 1000, setInterval); const [paused, setPaused] = createSignal(false); const [delay, setDelay] = createSignal(1000); -createTimer(() => console.log("tick"), () => !paused() && delay(), setInterval); +createTimer( + () => console.log("tick"), + () => !paused() && delay(), + setInterval, +); -setDelay(500); // change interval +setDelay(500); // change interval setPaused(true); // pause setPaused(false); // resume ``` @@ -98,7 +102,7 @@ import { createPolled } from "@solid-primitives/timer"; // Poll current time every second const date = createPolled(() => new Date(), 1000); -The time is: {date()} +The time is: {date()}; // Reactive source — updates on interval AND when source changes const [id, setId] = createSignal(1); @@ -119,7 +123,7 @@ import { createSignal } from "solid-js"; import { createIntervalCounter } from "@solid-primitives/timer"; const count = createIntervalCounter(1000); -Count: {count()} +Count: {count()}; // Reactive delay const [delay, setDelay] = createSignal(1000); diff --git a/packages/timer/src/index.ts b/packages/timer/src/index.ts index 0ebd74d73..b55f9c422 100644 --- a/packages/timer/src/index.ts +++ b/packages/timer/src/index.ts @@ -3,9 +3,10 @@ import { onCleanup, createEffect, untrack, + createMemo, type Accessor, + type Setter, type SignalOptions, - createMemo, } from "solid-js"; import { isServer } from "@solidjs/web"; @@ -138,7 +139,7 @@ export const createTimeoutLoop = (handler: VoidFunction, timeout: TimeoutSource) if (currTimeout === false) return; const id = setInterval(() => { handler(); - setCurrentTimeout((timeout as Accessor)()); + setCurrentTimeout(timeout()); }, currTimeout); return () => clearInterval(id); }, @@ -182,9 +183,18 @@ export function createPolled( if (isServer) { return fn as Accessor; } - const memo = createMemo(() => createSignal(fn(value), options)); - createTimer(() => memo()[1](fn), timeout, setInterval); - return () => memo()[0](); + // Capture the current signal's setter in a closure. When fn's reactive deps change, + // createMemo re-runs, creating a fresh signal and updating `set` to its new setter. + // This avoids memo()[1] being undefined in production (issue #808). + let set!: Setter; + const memo = createMemo(() => { + const [get, _set] = createSignal(fn(value) as Exclude, options); + set = _set; + return get; + }); + untrack(memo); // Force initial evaluation so `set` is defined before the timer fires. + createTimer(() => set(prev => fn(prev)), timeout, setInterval); + return () => memo()(); } /** diff --git a/packages/timer/test/index.test.ts b/packages/timer/test/index.test.ts index 3dfcba5b4..701afb602 100644 --- a/packages/timer/test/index.test.ts +++ b/packages/timer/test/index.test.ts @@ -337,6 +337,28 @@ describe("createPolled", () => { dispose(); }); + + // Regression test for issue #808: memo()[1] is not a function + // The old implementation used createMemo(() => createSignal(...)) which caused + // memo()[1] (the setter) to be undefined in production builds. + test("timer fires correctly before polled accessor is ever read (issue #808)", () => { + let n = 0; + const { polled, dispose } = createRoot(dispose => ({ + polled: createPolled(() => ++n, 100), + dispose, + })); + + // Advance time without ever calling polled() first — this was the failure mode + vi.advanceTimersByTime(100); + flush(); + vi.advanceTimersByTime(100); + flush(); + + // Now read — should reflect the timer-driven updates + expect(polled()).toBe(3); // initial + 2 timer fires + + dispose(); + }); }); // --------------------------------------------------------------------------- From 71c6e9d3ddd25f411e825050f43b0ef161f60c5a Mon Sep 17 00:00:00 2001 From: David Di Biase <1168397+davedbase@users.noreply.github.com> Date: Sun, 19 Apr 2026 23:28:25 -0400 Subject: [PATCH 3/3] More experimentation --- packages/timer/package.json | 8 +++---- packages/timer/src/index.ts | 33 +++++++++++++++----------- pnpm-lock.yaml | 46 +++++++++++++++++++++++++++---------- 3 files changed, 57 insertions(+), 30 deletions(-) diff --git a/packages/timer/package.json b/packages/timer/package.json index 2cd66474a..2ce56f658 100644 --- a/packages/timer/package.json +++ b/packages/timer/package.json @@ -59,12 +59,12 @@ "primitives" ], "peerDependencies": { - "@solidjs/web": "2.0.0-experimental.16", - "solid-js": "2.0.0-experimental.16" + "@solidjs/web": "2.0.0-beta.7", + "solid-js": "2.0.0-beta.7" }, "typesVersions": {}, "devDependencies": { - "@solidjs/web": "2.0.0-experimental.16", - "solid-js": "2.0.0-experimental.16" + "@solidjs/web": "2.0.0-beta.7", + "solid-js": "2.0.0-beta.7" } } diff --git a/packages/timer/src/index.ts b/packages/timer/src/index.ts index b55f9c422..255400938 100644 --- a/packages/timer/src/index.ts +++ b/packages/timer/src/index.ts @@ -3,9 +3,7 @@ import { onCleanup, createEffect, untrack, - createMemo, type Accessor, - type Setter, type SignalOptions, } from "solid-js"; import { isServer } from "@solidjs/web"; @@ -181,20 +179,27 @@ export function createPolled( options?: SignalOptions, ): Accessor { if (isServer) { - return fn as Accessor; + const v = fn(value); + return () => v; } - // Capture the current signal's setter in a closure. When fn's reactive deps change, - // createMemo re-runs, creating a fresh signal and updating `set` to its new setter. - // This avoids memo()[1] being undefined in production (issue #808). - let set!: Setter; - const memo = createMemo(() => { - const [get, _set] = createSignal(fn(value) as Exclude, options); - set = _set; - return get; + // depSignal tracks `tick` (timer) and fn's own reactive deps. Using a plain + // signal for the public accessor avoids the REACTIVE_DISPOSED re-run issue + // that compute signals exhibit when read after their owner scope is disposed. + // TODO: Investigate other options, this feels wrong. + const [tick, setTick] = createSignal(0); + const [depSignal] = createSignal((prev: T | undefined) => { + tick(); + return fn(prev !== undefined ? (prev as T) : value); }); - untrack(memo); // Force initial evaluation so `set` is defined before the timer fires. - createTimer(() => set(prev => fn(prev)), timeout, setInterval); - return () => memo()(); + const [polled, setPolled] = createSignal(depSignal() as Exclude, options); + createEffect( + () => depSignal(), + (newValue: T) => { + setPolled(() => newValue); + }, + ); + createTimer(() => setTick(t => t + 1), timeout, setInterval); + return polled; } /** diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5147c1b03..a217d3f99 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -927,11 +927,11 @@ importers: packages/timer: devDependencies: '@solidjs/web': - specifier: 2.0.0-experimental.16 - version: 2.0.0-experimental.16(solid-js@2.0.0-experimental.16) + specifier: 2.0.0-beta.7 + version: 2.0.0-beta.7(@solidjs/signals@2.0.0-beta.7)(solid-js@2.0.0-beta.7) solid-js: - specifier: 2.0.0-experimental.16 - version: 2.0.0-experimental.16 + specifier: 2.0.0-beta.7 + version: 2.0.0-beta.7 packages/transition-group: devDependencies: @@ -2045,6 +2045,7 @@ packages: '@graphql-tools/prisma-loader@8.0.4': resolution: {integrity: sha512-hqKPlw8bOu/GRqtYr0+dINAI13HinTVYBDqhwGAPIFmLr5s+qKskzgCiwbsckdrb5LWVFmVZc+UXn80OGiyBzg==} engines: {node: '>=16.0.0'} + deprecated: 'This package was intended to be used with an older versions of Prisma.\nThe newer versions of Prisma has a different approach to GraphQL integration.\nTherefore, this package is no longer needed and has been deprecated and removed.\nLearn more: https://www.prisma.io/graphql' peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 @@ -2593,15 +2594,19 @@ packages: '@solidjs/signals@0.11.3': resolution: {integrity: sha512-udMfutYPOlcxKUmc5+n1QtarsxOiAlC6LJY2TqFyaMwdXgo+reiYUcYGDlOiAPXfCLE0lavZHQ/6GT5pJbXKBA==} + '@solidjs/signals@2.0.0-beta.7': + resolution: {integrity: sha512-SgK6oQlQZofz82LiEJ2RzT3sbs1lWTqFEtLoWjLsUo/dk1v9EoIFpJJlmvgkXvNugASWG+l1yOHa1a8lPamxug==} + '@solidjs/start@1.1.4': resolution: {integrity: sha512-ma1TBYqoTju87tkqrHExMReM5Z/+DTXSmi30CCTavtwuR73Bsn4rVGqm528p4sL2koRMfAuBMkrhuttjzhL68g==} peerDependencies: vinxi: ^0.5.3 - '@solidjs/web@2.0.0-experimental.16': - resolution: {integrity: sha512-TcgvLKOYN2cIExX307SRxvd1aXj5eLaQUlGDLdQoQBqDHhuDdeZUfKLYrn/JOzWs1u5DYNOc+gR0SaG17vYsng==} + '@solidjs/web@2.0.0-beta.7': + resolution: {integrity: sha512-m5VjmDBufrOX0ZKGbhvwkT0CPK0TbMxDbxVPDB1PH2evGbWXQZcUlrpFM1N8RBO5md3aR/T1PgMfnOjleJbrRg==} peerDependencies: - solid-js: ^2.0.0-experimental.16 + '@solidjs/signals': ^2.0.0-beta.7 + solid-js: ^2.0.0-beta.7 '@speed-highlight/core@1.2.7': resolution: {integrity: sha512-0dxmVj4gxg3Jg879kvFS/msl4s9F3T9UXC1InxgOf7t5NvcPD97u/WTA5vL/IxWHMn7qSxBozqrnnE2wvl1m8g==} @@ -3524,6 +3529,7 @@ packages: dax-sh@0.43.2: resolution: {integrity: sha512-uULa1sSIHgXKGCqJ/pA0zsnzbHlVnuq7g8O2fkHokWFNwEGIhh5lAJlxZa1POG5En5ba7AU4KcBAvGQWMMf8rg==} + deprecated: This package has moved to simply be 'dax' instead of 'dax-sh' db0@0.3.2: resolution: {integrity: sha512-xzWNQ6jk/+NtdfLyXEipbX55dmDSeteLFt/ayF+wZUU5bzKgmrDOxmInUTbyVRp46YwnJdkDA1KhB7WIXFofJw==} @@ -4175,11 +4181,12 @@ packages: glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} @@ -6022,6 +6029,9 @@ packages: solid-js@1.9.7: resolution: {integrity: sha512-/saTKi8iWEM233n5OSi1YHCCuh66ZIQ7aK2hsToPe4tqGm7qAejU1SwNuTPivbWAYq7SjuHVVYxxuZQNRbICiw==} + solid-js@2.0.0-beta.7: + resolution: {integrity: sha512-7JHs+BhLeZXoU+u9dG+eKnyxxfZyGpOuJEBbN/1XbHKO/WhxecdplOAurlg/YDllNWPhsbXqmLR1H2paqSu62g==} + solid-js@2.0.0-experimental.16: resolution: {integrity: sha512-zZ1dU7cR0EnvLnrYiRLQbCFiDw5blLdlqmofgLzKUYE1TCMWDcisBlSwz0Ez8l4yXB4adbdhtaYCuynH4xSq9A==} @@ -6219,6 +6229,7 @@ packages: tar@7.4.3: resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} engines: {node: '>=18'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} @@ -6734,6 +6745,7 @@ packages: whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation whatwg-mimetype@4.0.0: resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} @@ -8614,6 +8626,8 @@ snapshots: '@solidjs/signals@0.11.3': {} + '@solidjs/signals@2.0.0-beta.7': {} + '@solidjs/start@1.1.4(solid-js@2.0.0-experimental.16)(vinxi@0.5.7(@types/node@22.15.31)(db0@0.3.2)(ioredis@5.6.1)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0))(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0))': dependencies: '@tanstack/server-functions-plugin': 1.121.0(vite@6.3.5(@types/node@22.15.31)(jiti@2.4.2)(sass@1.77.8)(terser@5.42.0)(tsx@4.20.2)(yaml@2.5.0)) @@ -8637,11 +8651,12 @@ snapshots: - supports-color - vite - '@solidjs/web@2.0.0-experimental.16(solid-js@2.0.0-experimental.16)': + '@solidjs/web@2.0.0-beta.7(@solidjs/signals@2.0.0-beta.7)(solid-js@2.0.0-beta.7)': dependencies: - seroval: 1.3.2 - seroval-plugins: 1.3.2(seroval@1.3.2) - solid-js: 2.0.0-experimental.16 + '@solidjs/signals': 2.0.0-beta.7 + seroval: 1.5.2 + seroval-plugins: 1.5.2(seroval@1.5.2) + solid-js: 2.0.0-beta.7 '@speed-highlight/core@1.2.7': {} @@ -12609,6 +12624,13 @@ snapshots: seroval: 1.3.2 seroval-plugins: 1.3.2(seroval@1.3.2) + solid-js@2.0.0-beta.7: + dependencies: + '@solidjs/signals': 2.0.0-beta.7 + csstype: 3.1.3 + seroval: 1.5.2 + seroval-plugins: 1.5.2(seroval@1.5.2) + solid-js@2.0.0-experimental.16: dependencies: '@solidjs/signals': 0.11.3