Skip to content

SecurityError when restoring history.scrollRestoration in pagehide (Firefox) #1523

@francawinter

Description

@francawinter

Description

When the user navigates away or the page unloads, Turbo’s Session.pageWillUnload runs and calls History.relinquishControlOfScrollRestoration(), which does:

history.scrollRestoration = this.previousScrollRestoration;

In Firefox (observed in 148.0 on macOS), that assignment can throw:

SecurityError: The operation is insecure.

The error is thrown from inside the pagehide event path, so it’s uncaught and shows up in error reporting.

Environment

Turbo: 8.0.21
Browser: Firefox 148.0
OS: macOS 10.15 (Catalina)
Context: Production Rails app using turbo-rails; the page in question is a Rails-rendered view that mounts a separate frontend app and loads a cross-origin script; the error occurs on navigation away or tab close, not during normal in-page interaction.

Stack trace (representative)

SecurityError: The operation is insecure.
  at History.relinquishControlOfScrollRestoration
  at Session.pageWillUnload

Trigger: pagehideSession.pageWillUnloadthis.history.relinquishControlOfScrollRestoration().

Expected

No uncaught exception. Restoring history.scrollRestoration during unload is best-effort; if the browser rejects the write, Turbo should swallow the error.

Suggested fix

In src/core/drive/history.js, wrap the restore in a try/catch so the error doesn’t propagate:

relinquishControlOfScrollRestoration() {
  if (this.previousScrollRestoration) {
    try {
      history.scrollRestoration = this.previousScrollRestoration
    } catch (_) {
      // Some browsers throw SecurityError when setting history.scrollRestoration during pagehide. Ignore — page is unloading.
    }
    delete this.previousScrollRestoration
  }
}

Related

#505 (Firefox scroll restoration): same relinquishControlOfScrollRestoration / history.scrollRestoration code path, but this one is about the SecurityError when restoring the value during pagehide.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions