Serious bug, Array state will be cached in iOS 12 Safari.

Some problem of Array’s value state in the newly released iOS 12 Safari, for example, code like this:


<span class="dec">&lt;!DOCTYPE html&gt;</span>
<span class="tag">&lt;html&gt;</span>
<span class="tag">&lt;head&gt;</span>
    <span class="tag">&lt;meta</span> <span class="atn">charset</span><span class="pun">=</span><span class="atv">"utf-8"</span><span class="tag">&gt;</span>
    <span class="tag">&lt;meta</span> <span class="atn">name</span><span class="pun">=</span><span class="atv">"viewport"</span> <span class="atn">content</span><span class="pun">=</span><span class="atv">"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"</span><span class="tag">&gt;</span>
    <span class="tag">&lt;title&gt;</span><span class="pln">iOS 12 Safari bugs</span><span class="tag">&lt;/title&gt;</span>
    <span class="tag">&lt;script</span> <span class="atn">type</span><span class="pun">=</span><span class="atv">"text/javascript"</span><span class="tag">&gt;</span><span class="pln">
    window</span><span class="pun">.</span><span class="pln">addEventListener</span><span class="pun">(</span><span class="str">"load"</span><span class="pun">,</span> <span class="kwd">function</span> <span class="pun">()</span>
    <span class="pun">{</span>
        <span class="kwd">let</span><span class="pln"> arr </span><span class="pun">=</span> <span class="pun">[</span><span class="lit">1</span><span class="pun">,</span> <span class="lit">2</span><span class="pun">,</span> <span class="lit">3</span><span class="pun">,</span> <span class="lit">4</span><span class="pun">,</span> <span class="lit">5</span><span class="pun">];</span><span class="pln">
        alert</span><span class="pun">(</span><span class="pln">arr</span><span class="pun">.</span><span class="pln">join</span><span class="pun">());</span><span class="pln">

        document</span><span class="pun">.</span><span class="pln">querySelector</span><span class="pun">(</span><span class="str">"button"</span><span class="pun">).</span><span class="pln">addEventListener</span><span class="pun">(</span><span class="str">"click"</span><span class="pun">,</span> <span class="kwd">function</span> <span class="pun">()</span>
        <span class="pun">{</span><span class="pln">
            arr</span><span class="pun">.</span><span class="pln">reverse</span><span class="pun">();</span>
        <span class="pun">});</span>
    <span class="pun">});</span>
    <span class="tag">&lt;/script&gt;</span>
<span class="tag">&lt;/head&gt;</span>
<span class="tag">&lt;body&gt;</span>
    <span class="tag">&lt;button&gt;</span><span class="pln">Array.reverse()</span><span class="tag">&lt;/button&gt;</span>
    <span class="tag">&lt;p</span> <span class="atn">style</span><span class="pun">=</span><span class="atv">"</span><span class="kwd">color</span><span class="pun">:</span><span class="pln">red</span><span class="pun">;</span><span class="atv">"</span><span class="tag">&gt;</span><span class="pln">test: click button and refresh page, code:</span><span class="tag">&lt;/p&gt;</span>
<span class="tag">&lt;/body&gt;</span>
<span class="tag">&lt;/html&gt;</span>

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

As my test, the bug is due to the optimization of array initializer which all values are primitive literal. For example 

() =&gt; [1, null, 'x']

 will return such arrays, and all return arrays link to same memory address, and some method like 

toString()

 is also memorized. Normally, any mutable operation on such array will copy to a individual memory space and link to it, this is so-called copy-on-write technique (https://en.wikipedia.org/wiki/Copy-on-write).

reverse()

 method will mutate the array, so it should trigger CoW, Unfortunately, it doesn’t now, which cause bug.

On the other hand, all methods which do not modify the array should not trigger CoW, and I find 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 notice that 

a.slice()

 WILL trigger CoW. So I guess the real reason of this bug may be someone accidentally swap the index of 

slice

 and 

reverse

.

Add a demo page, try it use iOS 12 Safari: https://cdn.miss.cat/demo/ios12-safari-bug.html

thanks

РубрикиБез рубрики

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *