Skip to content

F5 (refresh) + back button regression in 3.11.0 - 'foreign script' error #773

@Tiph

Description

@Tiph

Description

In version 3.10.2, pressing F5 (page refresh) followed by the back button worked correctly.
However, in version 3.11.0, this functionality is broken (URL change but content don't) and shows the following console log:

up:location:changed New location is / 
up.history Ignoring history entry owned by foreign script

Steps to Reproduce

  1. Navigate to a page using Unpoly
  2. Navigate to another page (to create history)
  3. Press F5 (page refresh) on the current page
  4. Press the back button in your browser
  5. Observe the console log and note that the back navigation is not handled by Unpoly

Expected Behavior

After F5 + back button, Unpoly should handle the back navigation correctly as it did in 3.10.2.

IA Fix

I've done some testing to fix the issue using claude and got the following code that seems to fix it.

Index: src/unpoly/history.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/unpoly/history.js b/src/unpoly/history.js
--- a/src/unpoly/history.js	(revision 863f7b2bbf276e8c5d6169c041d0422633e6f5c8)
+++ b/src/unpoly/history.js	(date 1754587469172)
@@ -162,7 +162,7 @@
         reason = (getBase(location) === getBase(previousLocation)) ? 'hash' : 'pop'
       }
 
-      let willHandle = !alreadyHandled && isAdopted(location)
+      let willHandle = !alreadyHandled && (isAdopted(location) || (reason === 'pop' && up.protocol.initialRequestMethod() === 'GET'))
 
       let locationChangedEvent = up.event.build('up:location:changed', {
         reason,
@@ -431,6 +431,8 @@
     if (event.reason === 'pop') {
       up.viewport.saveFocus({ location: event.previousLocation })
       up.viewport.saveScroll({ location: event.previousLocation })
+      // Adopt the location we're navigating to, since we're about to handle it
+      adopt(event.location)
       restoreLocation(event.location)
     } else if (event.reason === 'hash') {
       // We handle every hashchange, since only we know reveal obstructions.
@@ -564,6 +566,13 @@
     if (up.protocol.initialRequestMethod() === 'GET') {
       // Replace the vanilla state of the initial page load with an Unpoly-enabled state
       adopt()
+      
+      // Also adopt the previous location if we have one, to handle cases where
+      // the user refreshed (F5) and then hits the back button. Without this,
+      // the previous location would be considered "foreign" after a refresh.
+      if (previousLocation) {
+        adopt(previousLocation)
+      }
     }
   }
 

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