From 58e2d41f60c5fcdc1912911620a4f9eb15129659 Mon Sep 17 00:00:00 2001 From: Tom Heaton Date: Mon, 28 Sep 2026 11:24:40 +0100 Subject: [PATCH] fix: don't throw when history.state is null after replaceState --- .changeset/null-history-state-depth.md | 5 +++++ src/lifecycle.ts | 2 +- test/lifecycle.spec.ts | 13 ++++++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 .changeset/null-history-state-depth.md diff --git a/.changeset/null-history-state-depth.md b/.changeset/null-history-state-depth.md new file mode 100644 index 00000000..79256912 --- /dev/null +++ b/.changeset/null-history-state-depth.md @@ -0,0 +1,5 @@ +--- +"@solidjs/router": patch +--- + +Don't throw on import when `history.state` is still null after `replaceState` (seen in iOS WKWebView embeds) diff --git a/src/lifecycle.ts b/src/lifecycle.ts index b1cc15ab..ce8723d4 100644 --- a/src/lifecycle.ts +++ b/src/lifecycle.ts @@ -50,7 +50,7 @@ export function saveCurrentDepth() { if (!window.history.state || window.history.state._depth == null) { window.history.replaceState({ ...window.history.state, _depth: window.history.length - 1 }, ""); } - depth = window.history.state._depth; + depth = window.history.state?._depth ?? window.history.length - 1; } if (!isServer) { saveCurrentDepth(); diff --git a/test/lifecycle.spec.ts b/test/lifecycle.spec.ts index b1ef7679..cfad48fb 100644 --- a/test/lifecycle.spec.ts +++ b/test/lifecycle.spec.ts @@ -1,5 +1,5 @@ import { vi } from "vitest"; -import { createBeforeLeave } from "../src/lifecycle.js"; +import { createBeforeLeave, saveCurrentDepth } from "../src/lifecycle.js"; import type { BeforeLeaveEventArgs, Location } from "../src/types.js"; const mockLocation = { pathname: "/", search: "", hash: "", query: {}, state: null, key: "" } as unknown as Location; @@ -49,3 +49,14 @@ describe("createBeforeLeave", () => { expect(listener).not.toHaveBeenCalled(); }); }); + +describe("saveCurrentDepth", () => { + afterEach(() => vi.restoreAllMocks()); + + test("does not throw when replaceState leaves history.state null", () => { + vi.spyOn(window.history, "state", "get").mockReturnValue(null); + vi.spyOn(window.history, "replaceState").mockImplementation(() => {}); + + expect(() => saveCurrentDepth()).not.toThrow(); + }); +});