Array state will be cached in iOS 12 Safari. Is it a bug or feature?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
402
down vote

favorite
55












I found a problem with Array's value state in the newly released iOS 12 Safari, for example, code like this:



<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>iOS 12 Safari bugs</title>
<script type="text/javascript">
window.addEventListener("load", function ()

let arr = [1, 2, 3, 4, 5];
alert(arr.join());

document.querySelector("button").addEventListener("click", function ()

arr.reverse();
);
);
</script>
</head>
<body>
<button>Array.reverse()</button>
<p style="color:red;">test: click button and refresh page, code:</p>
</body>
</html>


After refreshing the page, the array's value is still reversed. Is this a bug or a feature of new Safari?




Here is a demo page. Try to use it with iOS 12 Safari:
https://cdn.miss.cat/demo/ios12-safari-bug.html










share|improve this question



















  • 40




    Bug confirmed also in macOS 10.14 Mojave - i.imgur.com/ZJtJJC1.png
    – a_rahmanshah
    Sep 19 at 9:39






  • 42




    macOS 10.13.6 (High Sierra) with Safari Version 12.0 (13606.2.11) has the same issue. Array is still reversed after refreshing the page.
    – Kevin Gimbel
    Sep 19 at 11:15






  • 4




    Comments need to be constructive and on-topic, please refrain from commenting if you don't have something new and topical to add.
    – meagar♦
    Sep 20 at 15:07















up vote
402
down vote

favorite
55












I found a problem with Array's value state in the newly released iOS 12 Safari, for example, code like this:



<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>iOS 12 Safari bugs</title>
<script type="text/javascript">
window.addEventListener("load", function ()

let arr = [1, 2, 3, 4, 5];
alert(arr.join());

document.querySelector("button").addEventListener("click", function ()

arr.reverse();
);
);
</script>
</head>
<body>
<button>Array.reverse()</button>
<p style="color:red;">test: click button and refresh page, code:</p>
</body>
</html>


After refreshing the page, the array's value is still reversed. Is this a bug or a feature of new Safari?




Here is a demo page. Try to use it with iOS 12 Safari:
https://cdn.miss.cat/demo/ios12-safari-bug.html










share|improve this question



















  • 40




    Bug confirmed also in macOS 10.14 Mojave - i.imgur.com/ZJtJJC1.png
    – a_rahmanshah
    Sep 19 at 9:39






  • 42




    macOS 10.13.6 (High Sierra) with Safari Version 12.0 (13606.2.11) has the same issue. Array is still reversed after refreshing the page.
    – Kevin Gimbel
    Sep 19 at 11:15






  • 4




    Comments need to be constructive and on-topic, please refrain from commenting if you don't have something new and topical to add.
    – meagar♦
    Sep 20 at 15:07













up vote
402
down vote

favorite
55









up vote
402
down vote

favorite
55






55





I found a problem with Array's value state in the newly released iOS 12 Safari, for example, code like this:



<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>iOS 12 Safari bugs</title>
<script type="text/javascript">
window.addEventListener("load", function ()

let arr = [1, 2, 3, 4, 5];
alert(arr.join());

document.querySelector("button").addEventListener("click", function ()

arr.reverse();
);
);
</script>
</head>
<body>
<button>Array.reverse()</button>
<p style="color:red;">test: click button and refresh page, code:</p>
</body>
</html>


After refreshing the page, the array's value is still reversed. Is this a bug or a feature of new Safari?




Here is a demo page. Try to use it with iOS 12 Safari:
https://cdn.miss.cat/demo/ios12-safari-bug.html










share|improve this question















I found a problem with Array's value state in the newly released iOS 12 Safari, for example, code like this:



<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>iOS 12 Safari bugs</title>
<script type="text/javascript">
window.addEventListener("load", function ()

let arr = [1, 2, 3, 4, 5];
alert(arr.join());

document.querySelector("button").addEventListener("click", function ()

arr.reverse();
);
);
</script>
</head>
<body>
<button>Array.reverse()</button>
<p style="color:red;">test: click button and refresh page, code:</p>
</body>
</html>


After refreshing the page, the array's value is still reversed. Is this a bug or a feature of new Safari?




Here is a demo page. Try to use it with iOS 12 Safari:
https://cdn.miss.cat/demo/ios12-safari-bug.html







javascript ios safari ios12






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Sep 20 at 14:35









meagar♦

173k29268288




173k29268288










asked Sep 18 at 15:51









abelyao

841237




841237







  • 40




    Bug confirmed also in macOS 10.14 Mojave - i.imgur.com/ZJtJJC1.png
    – a_rahmanshah
    Sep 19 at 9:39






  • 42




    macOS 10.13.6 (High Sierra) with Safari Version 12.0 (13606.2.11) has the same issue. Array is still reversed after refreshing the page.
    – Kevin Gimbel
    Sep 19 at 11:15






  • 4




    Comments need to be constructive and on-topic, please refrain from commenting if you don't have something new and topical to add.
    – meagar♦
    Sep 20 at 15:07













  • 40




    Bug confirmed also in macOS 10.14 Mojave - i.imgur.com/ZJtJJC1.png
    – a_rahmanshah
    Sep 19 at 9:39






  • 42




    macOS 10.13.6 (High Sierra) with Safari Version 12.0 (13606.2.11) has the same issue. Array is still reversed after refreshing the page.
    – Kevin Gimbel
    Sep 19 at 11:15






  • 4




    Comments need to be constructive and on-topic, please refrain from commenting if you don't have something new and topical to add.
    – meagar♦
    Sep 20 at 15:07








40




40




Bug confirmed also in macOS 10.14 Mojave - i.imgur.com/ZJtJJC1.png
– a_rahmanshah
Sep 19 at 9:39




Bug confirmed also in macOS 10.14 Mojave - i.imgur.com/ZJtJJC1.png
– a_rahmanshah
Sep 19 at 9:39




42




42




macOS 10.13.6 (High Sierra) with Safari Version 12.0 (13606.2.11) has the same issue. Array is still reversed after refreshing the page.
– Kevin Gimbel
Sep 19 at 11:15




macOS 10.13.6 (High Sierra) with Safari Version 12.0 (13606.2.11) has the same issue. Array is still reversed after refreshing the page.
– Kevin Gimbel
Sep 19 at 11:15




4




4




Comments need to be constructive and on-topic, please refrain from commenting if you don't have something new and topical to add.
– meagar♦
Sep 20 at 15:07





Comments need to be constructive and on-topic, please refrain from commenting if you don't have something new and topical to add.
– meagar♦
Sep 20 at 15:07













4 Answers
4






active

oldest

votes

















up vote
254
down vote













It's definitely a BUG! And it's a very serious bug.



Per my testing, the bug is due to the optimization of array initializers in which all values are primitive literals. For example, () => [1, null, 'x'] will result in such an array; all returned array references from this lambda will link to the same memory address, and some method like toString() will be cached. Normally, any mutable operation on such arrays will copy the data to a separate memory space and link to it; this is called copy-on-write, or CoW for short.



The reverse() method mutates the array, so it should trigger a copy-on-write. Apparently, it no longer does so, which causes the bug you’re seeing.



On the other hand, all methods which do not modify the array should not trigger CoW, and I’ve found that even a.fill(value, 0, 0) or a.copyWithin(index, 0, 0) won't trigger CoW because such callings don't really mutate the array. But I noticed that a.slice() WILL trigger CoW. So, if I had to guess, I’d say the underlying cause of this bug may be that someone accidentally swapped the indices of slice and reverse.My guess is not correct, the original author (Keith Miller @ Apple) just simply miss the reverse() case though he already wrote many test cases. slice() is a separate story, may be related to fastSlice optimization though I still don't understand the reason. Anyway, unnecessary CoW won't cause bug.






share|improve this answer


















  • 9




    Note: Safari 12.0 on Mac OS X also have the same issue.
    – hax
    Sep 19 at 11:48






  • 15




    Yeah it’s been fixed in the sources already, and shipped in Safari Technology Preview already. Try cdn.miss.cat/demo/ios12-safari-bug.html in Safari Technology Preview 65. You’ll find that it doesn’t have the bug.
    – sideshowbarker
    Sep 19 at 12:24







  • 4




    I don’t believe the underlying cause of the bug is the result of an index mixup; instead, it seems to be caused by neglecting to check whether an object is immutable before modifying it. The slice issue may have a similar explanation, but it’s not the same but and won’t be fixed by the patch for reverse, as far as I can tell. You should consider opening a WebKit bug report for the slice issue.
    – Zenexer
    Sep 19 at 14:46







  • 4




    @Zenexer You are right. I wrote this answer before I found the bugs.webkit.org/show_bug.cgi?id=188794 and see the source code. I will edit my answer.
    – hax
    Sep 19 at 14:54

















up vote
69
down vote













I wrote a lib to fix the bug.
https://www.npmjs.com/package/array-reverse-polyfill



This is the code:






(function() 
function buggy()
var a = [1, 2];
return String(a) === String(a.reverse());

if(!buggy()) return;
var r = Array.prototype.reverse;
Array.prototype.reverse = function reverse()
if (Array.isArray(this)) this.length = this.length;
return r.call(this);

)();








share|improve this answer


















  • 3




    Update at any time. Welcome to contribute.
    – Edire Fan
    Sep 19 at 11:52






  • 4




    @EdireFan why does this work?
    – zephi
    Sep 19 at 20:47






  • 10




    @zephi, I guess that writing on length (this.length = this.length) will trigger Copy On Write, so will change the memory address of the array, and so will fix the behavior of reverse.
    – Cœur
    Sep 20 at 1:47










  • Applers are looking at this.
    – Maggie Phillips
    Sep 28 at 8:21

















up vote
11
down vote













This is a bug in webkit. Though this has been solved at their end but not yet shipped with iOS GM release. One of the solutions to this problem:



(function() 
function getReverseStr()
return [1, 2].reverse();


var n1 = getReverseStr()[0];
var n2 = getReverseStr()[0];
// check if there is an issue
if(n1 != n2)
var origReverseFunction = Array.prototype.reverse;
Array.prototype.reverse = function()
var newArr = this.slice();
// use original reverse function so that edge cases are taken care of
origReverseFunction.apply(newArr, arguments);
var that = this;
// copy reversed array
newArr.forEach(function(value, index)
that[index] = value;
);
return this;


)();





share|improve this answer



























    up vote
    4
    down vote













    It seems not to be cached if the number of elements changes.

    I was able to avoid this like this.






    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <title>iOS 12 Safari bugs</title>
    <script type="text/javascript">
    window.addEventListener("load", function ()

    let arr = [1, 2, 3, 4, 5];
    arr.push('');
    arr.pop();
    alert(arr.join());

    document.querySelector("button").addEventListener("click", function ()

    arr.reverse();
    );
    );
    </script>
    </head>
    <body>
    <button>Array.reverse()</button>
    <p style="color:red;">test: click button and refresh page, code:</p>
    </body>
    </html>








    share|improve this answer




















      Your Answer





      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      convertImagesToLinks: true,
      noModals: false,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













       

      draft saved


      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52390368%2farray-state-will-be-cached-in-ios-12-safari-is-it-a-bug-or-feature%23new-answer', 'question_page');

      );

      Post as a guest






























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      254
      down vote













      It's definitely a BUG! And it's a very serious bug.



      Per my testing, the bug is due to the optimization of array initializers in which all values are primitive literals. For example, () => [1, null, 'x'] will result in such an array; all returned array references from this lambda will link to the same memory address, and some method like toString() will be cached. Normally, any mutable operation on such arrays will copy the data to a separate memory space and link to it; this is called copy-on-write, or CoW for short.



      The reverse() method mutates the array, so it should trigger a copy-on-write. Apparently, it no longer does so, which causes the bug you’re seeing.



      On the other hand, all methods which do not modify the array should not trigger CoW, and I’ve found that even a.fill(value, 0, 0) or a.copyWithin(index, 0, 0) won't trigger CoW because such callings don't really mutate the array. But I noticed that a.slice() WILL trigger CoW. So, if I had to guess, I’d say the underlying cause of this bug may be that someone accidentally swapped the indices of slice and reverse.My guess is not correct, the original author (Keith Miller @ Apple) just simply miss the reverse() case though he already wrote many test cases. slice() is a separate story, may be related to fastSlice optimization though I still don't understand the reason. Anyway, unnecessary CoW won't cause bug.






      share|improve this answer


















      • 9




        Note: Safari 12.0 on Mac OS X also have the same issue.
        – hax
        Sep 19 at 11:48






      • 15




        Yeah it’s been fixed in the sources already, and shipped in Safari Technology Preview already. Try cdn.miss.cat/demo/ios12-safari-bug.html in Safari Technology Preview 65. You’ll find that it doesn’t have the bug.
        – sideshowbarker
        Sep 19 at 12:24







      • 4




        I don’t believe the underlying cause of the bug is the result of an index mixup; instead, it seems to be caused by neglecting to check whether an object is immutable before modifying it. The slice issue may have a similar explanation, but it’s not the same but and won’t be fixed by the patch for reverse, as far as I can tell. You should consider opening a WebKit bug report for the slice issue.
        – Zenexer
        Sep 19 at 14:46







      • 4




        @Zenexer You are right. I wrote this answer before I found the bugs.webkit.org/show_bug.cgi?id=188794 and see the source code. I will edit my answer.
        – hax
        Sep 19 at 14:54














      up vote
      254
      down vote













      It's definitely a BUG! And it's a very serious bug.



      Per my testing, the bug is due to the optimization of array initializers in which all values are primitive literals. For example, () => [1, null, 'x'] will result in such an array; all returned array references from this lambda will link to the same memory address, and some method like toString() will be cached. Normally, any mutable operation on such arrays will copy the data to a separate memory space and link to it; this is called copy-on-write, or CoW for short.



      The reverse() method mutates the array, so it should trigger a copy-on-write. Apparently, it no longer does so, which causes the bug you’re seeing.



      On the other hand, all methods which do not modify the array should not trigger CoW, and I’ve found that even a.fill(value, 0, 0) or a.copyWithin(index, 0, 0) won't trigger CoW because such callings don't really mutate the array. But I noticed that a.slice() WILL trigger CoW. So, if I had to guess, I’d say the underlying cause of this bug may be that someone accidentally swapped the indices of slice and reverse.My guess is not correct, the original author (Keith Miller @ Apple) just simply miss the reverse() case though he already wrote many test cases. slice() is a separate story, may be related to fastSlice optimization though I still don't understand the reason. Anyway, unnecessary CoW won't cause bug.






      share|improve this answer


















      • 9




        Note: Safari 12.0 on Mac OS X also have the same issue.
        – hax
        Sep 19 at 11:48






      • 15




        Yeah it’s been fixed in the sources already, and shipped in Safari Technology Preview already. Try cdn.miss.cat/demo/ios12-safari-bug.html in Safari Technology Preview 65. You’ll find that it doesn’t have the bug.
        – sideshowbarker
        Sep 19 at 12:24







      • 4




        I don’t believe the underlying cause of the bug is the result of an index mixup; instead, it seems to be caused by neglecting to check whether an object is immutable before modifying it. The slice issue may have a similar explanation, but it’s not the same but and won’t be fixed by the patch for reverse, as far as I can tell. You should consider opening a WebKit bug report for the slice issue.
        – Zenexer
        Sep 19 at 14:46







      • 4




        @Zenexer You are right. I wrote this answer before I found the bugs.webkit.org/show_bug.cgi?id=188794 and see the source code. I will edit my answer.
        – hax
        Sep 19 at 14:54












      up vote
      254
      down vote










      up vote
      254
      down vote









      It's definitely a BUG! And it's a very serious bug.



      Per my testing, the bug is due to the optimization of array initializers in which all values are primitive literals. For example, () => [1, null, 'x'] will result in such an array; all returned array references from this lambda will link to the same memory address, and some method like toString() will be cached. Normally, any mutable operation on such arrays will copy the data to a separate memory space and link to it; this is called copy-on-write, or CoW for short.



      The reverse() method mutates the array, so it should trigger a copy-on-write. Apparently, it no longer does so, which causes the bug you’re seeing.



      On the other hand, all methods which do not modify the array should not trigger CoW, and I’ve found that even a.fill(value, 0, 0) or a.copyWithin(index, 0, 0) won't trigger CoW because such callings don't really mutate the array. But I noticed that a.slice() WILL trigger CoW. So, if I had to guess, I’d say the underlying cause of this bug may be that someone accidentally swapped the indices of slice and reverse.My guess is not correct, the original author (Keith Miller @ Apple) just simply miss the reverse() case though he already wrote many test cases. slice() is a separate story, may be related to fastSlice optimization though I still don't understand the reason. Anyway, unnecessary CoW won't cause bug.






      share|improve this answer














      It's definitely a BUG! And it's a very serious bug.



      Per my testing, the bug is due to the optimization of array initializers in which all values are primitive literals. For example, () => [1, null, 'x'] will result in such an array; all returned array references from this lambda will link to the same memory address, and some method like toString() will be cached. Normally, any mutable operation on such arrays will copy the data to a separate memory space and link to it; this is called copy-on-write, or CoW for short.



      The reverse() method mutates the array, so it should trigger a copy-on-write. Apparently, it no longer does so, which causes the bug you’re seeing.



      On the other hand, all methods which do not modify the array should not trigger CoW, and I’ve found that even a.fill(value, 0, 0) or a.copyWithin(index, 0, 0) won't trigger CoW because such callings don't really mutate the array. But I noticed that a.slice() WILL trigger CoW. So, if I had to guess, I’d say the underlying cause of this bug may be that someone accidentally swapped the indices of slice and reverse.My guess is not correct, the original author (Keith Miller @ Apple) just simply miss the reverse() case though he already wrote many test cases. slice() is a separate story, may be related to fastSlice optimization though I still don't understand the reason. Anyway, unnecessary CoW won't cause bug.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Sep 19 at 15:04

























      answered Sep 18 at 20:53









      hax

      1,1021611




      1,1021611







      • 9




        Note: Safari 12.0 on Mac OS X also have the same issue.
        – hax
        Sep 19 at 11:48






      • 15




        Yeah it’s been fixed in the sources already, and shipped in Safari Technology Preview already. Try cdn.miss.cat/demo/ios12-safari-bug.html in Safari Technology Preview 65. You’ll find that it doesn’t have the bug.
        – sideshowbarker
        Sep 19 at 12:24







      • 4




        I don’t believe the underlying cause of the bug is the result of an index mixup; instead, it seems to be caused by neglecting to check whether an object is immutable before modifying it. The slice issue may have a similar explanation, but it’s not the same but and won’t be fixed by the patch for reverse, as far as I can tell. You should consider opening a WebKit bug report for the slice issue.
        – Zenexer
        Sep 19 at 14:46







      • 4




        @Zenexer You are right. I wrote this answer before I found the bugs.webkit.org/show_bug.cgi?id=188794 and see the source code. I will edit my answer.
        – hax
        Sep 19 at 14:54












      • 9




        Note: Safari 12.0 on Mac OS X also have the same issue.
        – hax
        Sep 19 at 11:48






      • 15




        Yeah it’s been fixed in the sources already, and shipped in Safari Technology Preview already. Try cdn.miss.cat/demo/ios12-safari-bug.html in Safari Technology Preview 65. You’ll find that it doesn’t have the bug.
        – sideshowbarker
        Sep 19 at 12:24







      • 4




        I don’t believe the underlying cause of the bug is the result of an index mixup; instead, it seems to be caused by neglecting to check whether an object is immutable before modifying it. The slice issue may have a similar explanation, but it’s not the same but and won’t be fixed by the patch for reverse, as far as I can tell. You should consider opening a WebKit bug report for the slice issue.
        – Zenexer
        Sep 19 at 14:46







      • 4




        @Zenexer You are right. I wrote this answer before I found the bugs.webkit.org/show_bug.cgi?id=188794 and see the source code. I will edit my answer.
        – hax
        Sep 19 at 14:54







      9




      9




      Note: Safari 12.0 on Mac OS X also have the same issue.
      – hax
      Sep 19 at 11:48




      Note: Safari 12.0 on Mac OS X also have the same issue.
      – hax
      Sep 19 at 11:48




      15




      15




      Yeah it’s been fixed in the sources already, and shipped in Safari Technology Preview already. Try cdn.miss.cat/demo/ios12-safari-bug.html in Safari Technology Preview 65. You’ll find that it doesn’t have the bug.
      – sideshowbarker
      Sep 19 at 12:24





      Yeah it’s been fixed in the sources already, and shipped in Safari Technology Preview already. Try cdn.miss.cat/demo/ios12-safari-bug.html in Safari Technology Preview 65. You’ll find that it doesn’t have the bug.
      – sideshowbarker
      Sep 19 at 12:24





      4




      4




      I don’t believe the underlying cause of the bug is the result of an index mixup; instead, it seems to be caused by neglecting to check whether an object is immutable before modifying it. The slice issue may have a similar explanation, but it’s not the same but and won’t be fixed by the patch for reverse, as far as I can tell. You should consider opening a WebKit bug report for the slice issue.
      – Zenexer
      Sep 19 at 14:46





      I don’t believe the underlying cause of the bug is the result of an index mixup; instead, it seems to be caused by neglecting to check whether an object is immutable before modifying it. The slice issue may have a similar explanation, but it’s not the same but and won’t be fixed by the patch for reverse, as far as I can tell. You should consider opening a WebKit bug report for the slice issue.
      – Zenexer
      Sep 19 at 14:46





      4




      4




      @Zenexer You are right. I wrote this answer before I found the bugs.webkit.org/show_bug.cgi?id=188794 and see the source code. I will edit my answer.
      – hax
      Sep 19 at 14:54




      @Zenexer You are right. I wrote this answer before I found the bugs.webkit.org/show_bug.cgi?id=188794 and see the source code. I will edit my answer.
      – hax
      Sep 19 at 14:54












      up vote
      69
      down vote













      I wrote a lib to fix the bug.
      https://www.npmjs.com/package/array-reverse-polyfill



      This is the code:






      (function() 
      function buggy()
      var a = [1, 2];
      return String(a) === String(a.reverse());

      if(!buggy()) return;
      var r = Array.prototype.reverse;
      Array.prototype.reverse = function reverse()
      if (Array.isArray(this)) this.length = this.length;
      return r.call(this);

      )();








      share|improve this answer


















      • 3




        Update at any time. Welcome to contribute.
        – Edire Fan
        Sep 19 at 11:52






      • 4




        @EdireFan why does this work?
        – zephi
        Sep 19 at 20:47






      • 10




        @zephi, I guess that writing on length (this.length = this.length) will trigger Copy On Write, so will change the memory address of the array, and so will fix the behavior of reverse.
        – Cœur
        Sep 20 at 1:47










      • Applers are looking at this.
        – Maggie Phillips
        Sep 28 at 8:21














      up vote
      69
      down vote













      I wrote a lib to fix the bug.
      https://www.npmjs.com/package/array-reverse-polyfill



      This is the code:






      (function() 
      function buggy()
      var a = [1, 2];
      return String(a) === String(a.reverse());

      if(!buggy()) return;
      var r = Array.prototype.reverse;
      Array.prototype.reverse = function reverse()
      if (Array.isArray(this)) this.length = this.length;
      return r.call(this);

      )();








      share|improve this answer


















      • 3




        Update at any time. Welcome to contribute.
        – Edire Fan
        Sep 19 at 11:52






      • 4




        @EdireFan why does this work?
        – zephi
        Sep 19 at 20:47






      • 10




        @zephi, I guess that writing on length (this.length = this.length) will trigger Copy On Write, so will change the memory address of the array, and so will fix the behavior of reverse.
        – Cœur
        Sep 20 at 1:47










      • Applers are looking at this.
        – Maggie Phillips
        Sep 28 at 8:21












      up vote
      69
      down vote










      up vote
      69
      down vote









      I wrote a lib to fix the bug.
      https://www.npmjs.com/package/array-reverse-polyfill



      This is the code:






      (function() 
      function buggy()
      var a = [1, 2];
      return String(a) === String(a.reverse());

      if(!buggy()) return;
      var r = Array.prototype.reverse;
      Array.prototype.reverse = function reverse()
      if (Array.isArray(this)) this.length = this.length;
      return r.call(this);

      )();








      share|improve this answer














      I wrote a lib to fix the bug.
      https://www.npmjs.com/package/array-reverse-polyfill



      This is the code:






      (function() 
      function buggy()
      var a = [1, 2];
      return String(a) === String(a.reverse());

      if(!buggy()) return;
      var r = Array.prototype.reverse;
      Array.prototype.reverse = function reverse()
      if (Array.isArray(this)) this.length = this.length;
      return r.call(this);

      )();








      (function() 
      function buggy()
      var a = [1, 2];
      return String(a) === String(a.reverse());

      if(!buggy()) return;
      var r = Array.prototype.reverse;
      Array.prototype.reverse = function reverse()
      if (Array.isArray(this)) this.length = this.length;
      return r.call(this);

      )();





      (function() 
      function buggy()
      var a = [1, 2];
      return String(a) === String(a.reverse());

      if(!buggy()) return;
      var r = Array.prototype.reverse;
      Array.prototype.reverse = function reverse()
      if (Array.isArray(this)) this.length = this.length;
      return r.call(this);

      )();






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Sep 19 at 19:31









      Community♦

      11




      11










      answered Sep 18 at 18:51









      Edire Fan

      61127




      61127







      • 3




        Update at any time. Welcome to contribute.
        – Edire Fan
        Sep 19 at 11:52






      • 4




        @EdireFan why does this work?
        – zephi
        Sep 19 at 20:47






      • 10




        @zephi, I guess that writing on length (this.length = this.length) will trigger Copy On Write, so will change the memory address of the array, and so will fix the behavior of reverse.
        – Cœur
        Sep 20 at 1:47










      • Applers are looking at this.
        – Maggie Phillips
        Sep 28 at 8:21












      • 3




        Update at any time. Welcome to contribute.
        – Edire Fan
        Sep 19 at 11:52






      • 4




        @EdireFan why does this work?
        – zephi
        Sep 19 at 20:47






      • 10




        @zephi, I guess that writing on length (this.length = this.length) will trigger Copy On Write, so will change the memory address of the array, and so will fix the behavior of reverse.
        – Cœur
        Sep 20 at 1:47










      • Applers are looking at this.
        – Maggie Phillips
        Sep 28 at 8:21







      3




      3




      Update at any time. Welcome to contribute.
      – Edire Fan
      Sep 19 at 11:52




      Update at any time. Welcome to contribute.
      – Edire Fan
      Sep 19 at 11:52




      4




      4




      @EdireFan why does this work?
      – zephi
      Sep 19 at 20:47




      @EdireFan why does this work?
      – zephi
      Sep 19 at 20:47




      10




      10




      @zephi, I guess that writing on length (this.length = this.length) will trigger Copy On Write, so will change the memory address of the array, and so will fix the behavior of reverse.
      – Cœur
      Sep 20 at 1:47




      @zephi, I guess that writing on length (this.length = this.length) will trigger Copy On Write, so will change the memory address of the array, and so will fix the behavior of reverse.
      – Cœur
      Sep 20 at 1:47












      Applers are looking at this.
      – Maggie Phillips
      Sep 28 at 8:21




      Applers are looking at this.
      – Maggie Phillips
      Sep 28 at 8:21










      up vote
      11
      down vote













      This is a bug in webkit. Though this has been solved at their end but not yet shipped with iOS GM release. One of the solutions to this problem:



      (function() 
      function getReverseStr()
      return [1, 2].reverse();


      var n1 = getReverseStr()[0];
      var n2 = getReverseStr()[0];
      // check if there is an issue
      if(n1 != n2)
      var origReverseFunction = Array.prototype.reverse;
      Array.prototype.reverse = function()
      var newArr = this.slice();
      // use original reverse function so that edge cases are taken care of
      origReverseFunction.apply(newArr, arguments);
      var that = this;
      // copy reversed array
      newArr.forEach(function(value, index)
      that[index] = value;
      );
      return this;


      )();





      share|improve this answer
























        up vote
        11
        down vote













        This is a bug in webkit. Though this has been solved at their end but not yet shipped with iOS GM release. One of the solutions to this problem:



        (function() 
        function getReverseStr()
        return [1, 2].reverse();


        var n1 = getReverseStr()[0];
        var n2 = getReverseStr()[0];
        // check if there is an issue
        if(n1 != n2)
        var origReverseFunction = Array.prototype.reverse;
        Array.prototype.reverse = function()
        var newArr = this.slice();
        // use original reverse function so that edge cases are taken care of
        origReverseFunction.apply(newArr, arguments);
        var that = this;
        // copy reversed array
        newArr.forEach(function(value, index)
        that[index] = value;
        );
        return this;


        )();





        share|improve this answer






















          up vote
          11
          down vote










          up vote
          11
          down vote









          This is a bug in webkit. Though this has been solved at their end but not yet shipped with iOS GM release. One of the solutions to this problem:



          (function() 
          function getReverseStr()
          return [1, 2].reverse();


          var n1 = getReverseStr()[0];
          var n2 = getReverseStr()[0];
          // check if there is an issue
          if(n1 != n2)
          var origReverseFunction = Array.prototype.reverse;
          Array.prototype.reverse = function()
          var newArr = this.slice();
          // use original reverse function so that edge cases are taken care of
          origReverseFunction.apply(newArr, arguments);
          var that = this;
          // copy reversed array
          newArr.forEach(function(value, index)
          that[index] = value;
          );
          return this;


          )();





          share|improve this answer












          This is a bug in webkit. Though this has been solved at their end but not yet shipped with iOS GM release. One of the solutions to this problem:



          (function() 
          function getReverseStr()
          return [1, 2].reverse();


          var n1 = getReverseStr()[0];
          var n2 = getReverseStr()[0];
          // check if there is an issue
          if(n1 != n2)
          var origReverseFunction = Array.prototype.reverse;
          Array.prototype.reverse = function()
          var newArr = this.slice();
          // use original reverse function so that edge cases are taken care of
          origReverseFunction.apply(newArr, arguments);
          var that = this;
          // copy reversed array
          newArr.forEach(function(value, index)
          that[index] = value;
          );
          return this;


          )();






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Sep 20 at 16:05









          Shubhansh

          4,11421941




          4,11421941




















              up vote
              4
              down vote













              It seems not to be cached if the number of elements changes.

              I was able to avoid this like this.






              <!DOCTYPE html>
              <html>
              <head>
              <meta charset="utf-8">
              <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
              <title>iOS 12 Safari bugs</title>
              <script type="text/javascript">
              window.addEventListener("load", function ()

              let arr = [1, 2, 3, 4, 5];
              arr.push('');
              arr.pop();
              alert(arr.join());

              document.querySelector("button").addEventListener("click", function ()

              arr.reverse();
              );
              );
              </script>
              </head>
              <body>
              <button>Array.reverse()</button>
              <p style="color:red;">test: click button and refresh page, code:</p>
              </body>
              </html>








              share|improve this answer
























                up vote
                4
                down vote













                It seems not to be cached if the number of elements changes.

                I was able to avoid this like this.






                <!DOCTYPE html>
                <html>
                <head>
                <meta charset="utf-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
                <title>iOS 12 Safari bugs</title>
                <script type="text/javascript">
                window.addEventListener("load", function ()

                let arr = [1, 2, 3, 4, 5];
                arr.push('');
                arr.pop();
                alert(arr.join());

                document.querySelector("button").addEventListener("click", function ()

                arr.reverse();
                );
                );
                </script>
                </head>
                <body>
                <button>Array.reverse()</button>
                <p style="color:red;">test: click button and refresh page, code:</p>
                </body>
                </html>








                share|improve this answer






















                  up vote
                  4
                  down vote










                  up vote
                  4
                  down vote









                  It seems not to be cached if the number of elements changes.

                  I was able to avoid this like this.






                  <!DOCTYPE html>
                  <html>
                  <head>
                  <meta charset="utf-8">
                  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
                  <title>iOS 12 Safari bugs</title>
                  <script type="text/javascript">
                  window.addEventListener("load", function ()

                  let arr = [1, 2, 3, 4, 5];
                  arr.push('');
                  arr.pop();
                  alert(arr.join());

                  document.querySelector("button").addEventListener("click", function ()

                  arr.reverse();
                  );
                  );
                  </script>
                  </head>
                  <body>
                  <button>Array.reverse()</button>
                  <p style="color:red;">test: click button and refresh page, code:</p>
                  </body>
                  </html>








                  share|improve this answer












                  It seems not to be cached if the number of elements changes.

                  I was able to avoid this like this.






                  <!DOCTYPE html>
                  <html>
                  <head>
                  <meta charset="utf-8">
                  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
                  <title>iOS 12 Safari bugs</title>
                  <script type="text/javascript">
                  window.addEventListener("load", function ()

                  let arr = [1, 2, 3, 4, 5];
                  arr.push('');
                  arr.pop();
                  alert(arr.join());

                  document.querySelector("button").addEventListener("click", function ()

                  arr.reverse();
                  );
                  );
                  </script>
                  </head>
                  <body>
                  <button>Array.reverse()</button>
                  <p style="color:red;">test: click button and refresh page, code:</p>
                  </body>
                  </html>








                  <!DOCTYPE html>
                  <html>
                  <head>
                  <meta charset="utf-8">
                  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
                  <title>iOS 12 Safari bugs</title>
                  <script type="text/javascript">
                  window.addEventListener("load", function ()

                  let arr = [1, 2, 3, 4, 5];
                  arr.push('');
                  arr.pop();
                  alert(arr.join());

                  document.querySelector("button").addEventListener("click", function ()

                  arr.reverse();
                  );
                  );
                  </script>
                  </head>
                  <body>
                  <button>Array.reverse()</button>
                  <p style="color:red;">test: click button and refresh page, code:</p>
                  </body>
                  </html>





                  <!DOCTYPE html>
                  <html>
                  <head>
                  <meta charset="utf-8">
                  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
                  <title>iOS 12 Safari bugs</title>
                  <script type="text/javascript">
                  window.addEventListener("load", function ()

                  let arr = [1, 2, 3, 4, 5];
                  arr.push('');
                  arr.pop();
                  alert(arr.join());

                  document.querySelector("button").addEventListener("click", function ()

                  arr.reverse();
                  );
                  );
                  </script>
                  </head>
                  <body>
                  <button>Array.reverse()</button>
                  <p style="color:red;">test: click button and refresh page, code:</p>
                  </body>
                  </html>






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Sep 20 at 4:37









                  Atsushi Sasaki

                  571




                  571



























                       

                      draft saved


                      draft discarded















































                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52390368%2farray-state-will-be-cached-in-ios-12-safari-is-it-a-bug-or-feature%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      Popular posts from this blog

                      How to check contact read email or not when send email to Individual?

                      Bahrain

                      Postfix configuration issue with fips on centos 7; mailgun relay