Javascript-funksjonen Array.prototype.reverse() tar en array og snur den på hodet. For eksempel så [1, 2, 3] blir til [3, 2, 1].
Men brukes funksjonen på en nettside, forventer man at den gamle, ikke-reverserte arrayen kommer tilbake når sida lastes på nytt.
Hva kreves når Apple lanserer tre nye iPhone-er?
Da iOS 12 ble lansert nylig, endret dette seg. En reversert array på en nettside forblir reversert om man laster sida på nytt.
Den muterte arrayen lagres altså tilsynelatende i en slags cache.
Dette ble først omtalt som en feil i iOS 12 sin Safari, men viser seg å gjelde alt i iOS 12 som bruker WebKit-motoren til å tegne opp nettsider. Og ikke nok med det:
- Feilen ligger i WebKit sitt JavaScriptCore-rammeverk, som også brukes av React Native-apper, forteller utvikleren Christian Brevik i Novanet/Ice.net til kode24.
Disse rammes
Da kode24 tok kontakt med Brevik angående feilen ble han nysgjerrig. Han hadde allerede lest om feilmeldingen på Stackoverflow, men kunne feilen ha større konsekvenser?
Svaret var et rungende «ja». Da feilen ser ut til å ligge i JavaScriptCore, som blant annet Apple bruker som sin Javascript-motor, skriver Brevik i et blogginnlegg at feilen i alle fall rammer:
- Alle nettlesere, som Safari og Chrome, på iOS 12.
- Apper som bruker webview på iOS 12.
- Safari på nyeste versjoner av macOS.
- React Native-apper på iOS 12, fordi de også kjører i JavaScriptCore-motoren.
- Det som gjør dette litt skummelt, er at om du installerte React Native-appen min på iOS 11, og oppgraderer til iOS 12, vil appen min være den samme, men plutselig ligger feilen der. Og det kan få veldig subtile konsekvenser, da det er en veldig spesiell feil, forteller Brevik til kode24.
- Dette virker kanskje som skremselspropaganda, men det er ment som en opplysningstjeneste, for folk bør sjekke koden sin. Her kan det bli konsekvenser, som kan være vanskelige å merke.
Løses med polyfill
Brevik har de siste dagene gått gjennom mye kode, både sin egen og i avhengigheter. Spesielt sistnevnte kan gjøre feil vanskelig å oppdage.
Foreløpig har ikke Brevik funnet noen problemer, blant annet fordi feilen bare ser ut til å melde seg i hardkoda arrayer – ikke arrayer som blir dynamisk konstruert, for eksempel av data fra en API.
Derfor lagde SOL ny app i React Native
Også SpareBank1 forteller at de nå går gjennom koden sin.
- Vi bruker heldigvis ikke denne funksjonen i veldig stor grad, men vi ser nå på de stedene vi bruker det, og om vi blir nødt til å fikse koden med en ekstern polyfill-fiks som allerede er tilgjengelig flere steder, forteller utvikler Gunnar Kriik i SpareBank1 til kode24.
NPM-pakka «array-reverse-polyfill» skal nemlig løse problemet. Men Brevik synes ikke det å løse et problem på denne måten er en spesielt god løsning på sikt.
- Det er viktigere å geleide folk til en fikset versjon av OS-et, som fikser feilen globalt for alle apper, enn å fikse symptomet i din app, mener Brevik.
Handler om ytelse
Foreløpig har ikke brukerne noe annet valg enn å leve med feilen. Selv om feilen er rapportert fikset, vil ikke brukerne få løsningen før iOS og macOS oppdateres.
- Hva tror du kan være grunnen til feilen?
- Det virker som en performance-effekt. «Performance is king», og man ønsker å ligge foran andre aktører. Det er tydelig at Apple fokuserer mye på Javascript-rendering, sier Brevik.
Kriik i Sparebank1 er enig. Han mener feilen ligger i hvordan Array.reverse() har håndtert «copy-on-write» (implisitt deling), som handler om optimalisering ved å vise til samme minneadresse når data dupliseres, men ikke når den endres.
- Her har man rett og slett glemt å kalle copy-on-write-funksjonen i reverse-funksjonen som muterer dataene, og dermed oppstår denne feilen, mener Kriik, som har lest gjennom koden i patchen.
- Array.reverse() er allerede i «det mørke hjørnet» av array-API-et, og er kanskje ikke et eksempel på god API-design.