ReviewOS

craft-native/craft

fix(ios): a cancelled page load switches the app to the bundled copy for the rest of the session

#252
Closed glennmichael123 opened this 9 days ago ·
9 days ago

Bug Description

With a remote devServerURL, any failed or cancelled main-frame load makes the iOS shell load the bundled copy (craft://app/index.html), and it stays there for the rest of the process's life.

didFailProvisionalNavigation and didFail both call loadBundledFallback(in:) without looking at the error (packages/ios/templates/CraftApp.swift:1455-1468 at v0.0.92), and loadedBundledFallback only ever goes one way.

Two consequences:

  • A cancelled load is not a failure. WebKit reports NSURLErrorCancelled (-999) whenever a new navigation starts before the previous one commits: two quick taps, a location.assign while a load is in flight, a redirect. Each of those currently ends the session on the bundled copy.
  • The bundled copy cannot reach the app's API. It is served from craft://app, so a frontend that calls its API by relative path (fetch('/api/…')) has no API until the app is killed and relaunched. In WildLoop it also showed a stale landing page, since the bundle is whatever web build was last copied in.

Steps to Reproduce

  1. Generate an iOS app whose devServerURL is a remote or dev-server URL.
  2. From a page, start two main-frame navigations in quick succession against a server slow enough that the first has not committed, e.g. location.assign('/a'); setTimeout(() => location.assign('/b'), 50).
  3. The first provisional navigation fails with -999; loadBundledFallback runs and the WebView loads craft://app/index.html.
  4. Every later navigation stays on craft://app.

Seen in WildLoop after quick tab taps on a slow dev server. The path above is read from the template; I have not written an automated repro.

Expected Behavior

  • Cancellations are ignored: NSURLErrorCancelled, and WebKit's frame-load-interrupted error (WebKitErrorDomain 102).
  • The bundled copy is used only for connectivity failures, e.g. not connected, cannot find or connect to host, timed out, connection lost.
  • Once on the bundled copy, the app goes back to the remote URL when connectivity returns (a path monitor) or on the next foreground, rather than staying there until the process dies.

Actual Behavior

Any error, -999 included, switches the WebView to the bundled copy for the rest of the process.

Platform

iOS (Simulator, iPhone 17 Pro)

OS Version

iOS 26.5

Craft Version

craft-native 0.0.92 (template at 186cd83)

Sign in to comment on this issue.