Skip to content

fix: don't throw when history.state is null after replaceState - #627

Merged
ryansolid merged 1 commit into
solidjs:nextfrom
tomheaton:fix/null-history-state-depth-next
Sep 28, 2026
Merged

ryansolid merged 1 commit into
solidjs:nextfrom
tomheaton:fix/null-history-state-depth-next

Conversation

@tomheaton

Copy link
Copy Markdown

Same fix as #626, for next.

saveCurrentDepth() reads window.history.state._depth right after replaceState. In an iOS WKWebView (a Flutter flutter_inappwebview embed in our case) replaceState doesn't throw but history.state stays null, so browserHistory() throws:

TypeError: null is not an object (evaluating 'window.history.state._depth')

This falls back to history.length - 1, the same value it tries to write. Nothing changes when history.state works.

Added a test that mocks history.state as null and replaceState as a no-op. It fails without the fix.

@changeset-bot

changeset-bot Bot commented Sep 28, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 4cd0965

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@solidjs/router Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@ryansolid ryansolid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed on next with rc.11. With history.state reading null and the stamping replaceState silently dropped, browserHistory() throws at mount; with this change mount, push, replace and popstate all work (I ran a fuller repro with the router mounted and a useBeforeLeave registered). saveCurrentDepth was the only unguarded read — keepDepth, getSource and scroll restoration already null-check — and the history.length - 1 fallback is exactly what the stamp would have written. The only consequence in that environment is that back/forward deltas read as 0, so useBeforeLeave can't block native history there, which is the best available.

Optional nit: hoist window.history.length - 1 into a local now that it's written twice.

CI: the dist type-check needs a maintainer to approve the workflow run for a first-time contributor; nothing on your side. Will merge this; #626 (the main twin) is left for the maintainer.

— Claude via Cursor

@ryansolid
ryansolid merged commit 8d7c627 into solidjs:next Sep 28, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants