Make push_state / replace_state update Turbo's history#339
Draft
myabc wants to merge 4 commits into
Draft
Conversation
push_state / replace_state update Turbo's history
history_forward was exported but never wired into registerHistoryActions, so it never reached Turbo Streams in a real app. Existing tests missed it because the test helper registers per-action from the Actions namespace rather than through registerHistoryActions. Closes marcoroth#337
Raw window.history.pushState omits the {turbo:...} state key, so Turbo's
popstate handler ignores the entry and the Back button misbehaves. Push
through Turbo.navigator.history instead.
BREAKING: the state and title attributes are no longer supported; Turbo
owns its history state. Empty/missing url is now a no-op.
Refs marcoroth#11
Mirror push_state: replace through Turbo.navigator.history so the {turbo}
state key is set and Back works.
BREAKING: state and title attributes dropped; empty/missing url is a no-op.
Refs marcoroth#11
myabc
force-pushed
the
turbo-aware-history
branch
from
June 27, 2026 15:23
90c0822 to
89d39c1
Compare
3 tasks
Contributor
Author
|
@marcoroth I've purposely left this in draft since it needs some direction from you. The disadvantage of this solution - as it currently stands - is that it as a breaking change. My take on it though, is that the pain of a breaking change might be worth it if making Turbo Power actions play "nicely" with Turbo Drive out-of-the-box is a goal. My colleague @dfriquet hit an issue with this downstream in opf/openproject#24076 - so I guess this validates that this is a real world issue! 😄 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacks on #337 / #338. Until #338 merges, this PR's diff also shows that PR's single commit (
Register history_forward action); GitHub will trim it automatically once #338 lands. The substantive commits here are the two action changes plus the README update.Problem
push_state/replace_statedrovewindow.historydirectly. RawpushState/replaceStateomit the{ turbo: { restorationIdentifier } }state key, so Turbo'spopstatehandler ignores the entry and the browser Back button does not behave as expected (#11). The current workaround is theinvokeaction.Change
Route both actions through
Turbo.navigator.history.push/.replace(typed, exported API), which set Turbo's state key so restoration works. Relative URLs resolve againstdocument.baseURI. Empty/missingurlis a no-op.Breaking change — your call
The
stateandtitleattributes are dropped: Turbo owns its history state ({ turbo: { restorationIdentifier } }) and arbitrary state is unsupported. A test locks in that these legacy attributes are now ignored.I reused the existing action names rather than adding
turbo_*variants. Happy to switch to new names or a non-breaking fallback (keep raw behavior whenstateis present, Turbo path otherwise) if you'd prefer — flagging before this is merge-ready.Notes
urlraises the sameSecurityErrorthe old code did — not a regression, behaves like a normal Turbo navigation. Not handled here; happy to add a guard if you want one.Turbo.navigator.historyand assert the rightURLis passed for both actions (absolute + relative), plus no-op cases. Full suite green (202 tests), lint clean.Closes #11