RESOLVED CONFIGURATION CHANGED298711
REGRESSION (iOS 26): Shopee.sg: sessionStorage/localStorage calls does not work
https://bugs.webkit.org/show_bug.cgi?id=298711
Summary REGRESSION (iOS 26): Shopee.sg: sessionStorage/localStorage calls does not work
kenrick95
Reported 2025-09-11 05:30:57 PDT
Disclosure: I'm working at Shopee I received several reports from internal staff who uses iOS 26 Beta that visitting https://shopee.sg/ (or other Shopee sites like https://shopee.co.id https://shopee.com.my https://shopee.vn https://shopee.com.br https://shopee.com.mx etc) on iOS Safari (real device, like iPhone 12 or iPhone 14) having some issue with Safari behavior on setting items on sessionStorage/localStorage. Our site works by serving a HTML page on the main domain (e.g. https://shopee.sg/ ), and the rest of the scripts are hosted on CDN 'deo.shopeemobile.com' Here are my observations: 1. During the page load, calls to window.sessionStorage.setItem() and window.localStorage.setItem() does not throw any error, but when we inspected the storage (via iPhone's remote debugging by plugging in cable to a macbook), the value is not set in session storage nor local storage. 2. After the page load settles, some scripts calling sessionStorage/localStorage setItem works again. 3. I also observed that using the remote debugger's console, we can sucessfully call window.sessionStorage.setItem() and window.localStorage.setItem() and it will be actually set in the storage. 4. If I go to iPhone setting > Safari > and I turned off 'Prevent cross-site tracking', things will behave as expected. I suspect that this is due to Safari's tracking protection mechanism. However there's no such hint to developers what works and what wouldn't. With the imminent release of iOS 26 in a few days, I'm at loss on how to resolve the issue where some functionality of our site is broken due to this
Attachments
1 (196.50 KB, image/png)
2025-09-11 18:54 PDT, kenrick95
no flags
getItem of localStorage/sessionStorage will always be null here (471.16 KB, image/png)
2025-09-11 18:55 PDT, kenrick95
no flags
getItem of localStorage/sessionStorage will always be null here even on click (484.11 KB, image/png)
2025-09-11 18:55 PDT, kenrick95
no flags
Storage > sessionStorage (198.34 KB, image/png)
2025-09-11 18:57 PDT, kenrick95
no flags
Storage > localStorage (202.71 KB, image/png)
2025-09-11 18:57 PDT, kenrick95
no flags
Prevent cross-site tracking toggle (185.66 KB, image/jpeg)
2025-09-11 19:23 PDT, kenrick95
no flags
Storage > localStorage (when Prevent Cross-site tracking is turned OFF) (258.49 KB, image/png)
2025-09-11 19:23 PDT, kenrick95
no flags
Storage > sessionStorage (when Prevent Cross-site tracking is turned OFF) (227.64 KB, image/png)
2025-09-11 19:24 PDT, kenrick95
no flags
kenrick95
Comment 1 2025-09-11 18:53:41 PDT
The testing code is something like this: ``` import * as React from 'react'; export default function RouteTestingStorage() { React.useEffect(() => { try { globalThis.console.warn('!!debug!! localStorage.setItem __testEffect'); localStorage.setItem('__testEffect', '__testEffect'); globalThis.console.warn('!!debug!! sessionStorage.setItem __testEffect'); sessionStorage.setItem('__testEffect', '__testEffect'); globalThis.console.warn( '!!debug!! localStorage.getItem __testEffect', localStorage.getItem('__testEffect') ); globalThis.console.warn( '!!debug!! sessionStorage.getItem __testEffect', sessionStorage.getItem('__testEffect') ); } catch (e) { globalThis.console.warn('!!debug!! __testEffect error', e); } (async () => { try { const cache = await self.caches.open('__testEffect'); await cache.put('/__testEffect', new Response('__testEffect')); } catch (e) { globalThis.console.warn('!!debug!! __testEffect error', e); } try { const cache = await self.caches.open('__testEffect'); const response = await cache.match('/__testEffect'); const data = await response?.text(); globalThis.console.warn( '!!debug!! __testEffect response', response, data ); } catch (e) { globalThis.console.warn('!!debug!! __testEffect error', e); } })(); }, []); const handleClick = React.useCallback(() => { try { globalThis.console.warn('!!debug!! localStorage.setItem __testClick'); localStorage.setItem('__testClick', '__testClick'); globalThis.console.warn('!!debug!! sessionStorage.setItem __testClick'); sessionStorage.setItem('__testClick', '__testClick'); globalThis.console.warn( '!!debug!! localStorage.getItem __testClick', localStorage.getItem('__testClick') ); globalThis.console.warn( '!!debug!! sessionStorage.getItem __testClick', sessionStorage.getItem('__testClick') ); } catch (e) { globalThis.console.warn('!!debug!! __testClick error', e); } (async () => { try { const cache = await self.caches.open('__testClick'); await cache.put('/__testClick', new Response('__testClick')); } catch (e) { globalThis.console.warn('!!debug!! __testClick error', e); } try { const cache = await self.caches.open('__testClick'); const response = await cache.match('/__testClick'); const data = await response?.text(); globalThis.console.warn( '!!debug!! __testClick response', response, data ); } catch (e) { globalThis.console.warn('!!debug!! __testClick error', e); } })(); }, []); return ( <div> RouteTestingStorage <button onClick={handleClick}>Click</button> </div> ); } ``` We found out that in both cases (whether 'effect' or 'click'), localStorage.getItem sessionStorage.getItem returns null
kenrick95
Comment 2 2025-09-11 18:54:19 PDT
kenrick95
Comment 3 2025-09-11 18:55:01 PDT
Created attachment 476704 [details] getItem of localStorage/sessionStorage will always be null here
kenrick95
Comment 4 2025-09-11 18:55:47 PDT
Created attachment 476705 [details] getItem of localStorage/sessionStorage will always be null here even on click
kenrick95
Comment 5 2025-09-11 18:57:05 PDT
Created attachment 476706 [details] Storage > sessionStorage
kenrick95
Comment 6 2025-09-11 18:57:28 PDT
Created attachment 476707 [details] Storage > localStorage
kenrick95
Comment 7 2025-09-11 19:23:04 PDT
Created attachment 476708 [details] Prevent cross-site tracking toggle If I turn this off, then everything will work as per expected
kenrick95
Comment 8 2025-09-11 19:23:44 PDT
Created attachment 476709 [details] Storage > localStorage (when Prevent Cross-site tracking is turned OFF)
kenrick95
Comment 9 2025-09-11 19:24:02 PDT
Created attachment 476710 [details] Storage > sessionStorage (when Prevent Cross-site tracking is turned OFF)
Radar WebKit Bug Importer
Comment 10 2025-09-12 04:37:48 PDT
Tim Nguyen (:ntim)
Comment 11 2025-09-17 20:30:31 PDT
This was fixed by updating our cross-site tracking list in iOS 26.0.
kenrick95
Comment 12 2025-09-17 20:43:42 PDT
Thank you very much!
Note You need to log in before you can comment on or make changes to this bug.