iOS 12 的 safari 有哪些变化吗?今天发现了一个 Javascript 的问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
34C
V2EX    问与答

iOS 12 的 safari 有哪些变化吗?今天发现了一个 Javascript 的问题

  •  7
     
  •   34C 2018-09-18 21:09:38 +08:00 10833 次点击
    这是一个创建于 2649 天前的主题,其中的信息可能已经有所发展或是发生改变。

    正在开发的程序中,有一段代码大概如下:

    window.addEventListener("load", function () { var arr = [1, 2, 3, 4]; arr.reverse(); }); 

    今天升级了 iOS 12 之后,无意中发现数组的顺序有问题。

    第一次加载是正常的, 页面刷新会颠倒, 再刷新又正常了, 再刷新又颠倒了, 以此类推…

    而如果是关闭了页面、重新打开,则不会有问题。

    在 PC Chrome / Android / iOS 11 Safari 中都没出现这个问题,就好像这个变量,被 safari “缓存” 了一样,即使刷新页面也会被保留、继承之前的状态。

    这是 iOS 12 Safari 的 bug 还是 feature 啊?有没有哪里可以看到关于 safari 底层机制的改变呢?

    第 1 条附言    2018-09-18 21:54:04 +08:00
    测试了一下,代码改成 var arr = new Array(1, 2, 3, 4); 之后则没问题,
    难道真的有缓存变量状态的 new feature ?
    原来变流畅的方法就是缓存到内存而不执行…?
    第 2 条附言    2018-09-18 23:24:20 +08:00
    做了个测试页,有兴趣的可以试试,https://cdn.miss.cat/demo/ios12-safari-bug.html
    第 3 条附言    2018-09-19 17:41:12 +08:00
    stackoverflow 上的网友已经确认了在 macOS 10.14 Mojave 也有相同问题,
    31 条回复    2018-09-25 23:23:07 +08:00
    uuair
        1
    uuair  
       2018-09-18 21:18:35 +08:00
    adblock 没法用了。。
    34C
        2
    34C  
    OP
       2018-09-18 21:20:48 +08:00
    @uuair 求帮顶,如果这个 “ feature ” 真的存在,那依赖 js 变量做状态的(比如 var userinfo 之类的),要出很多大坑了
    34C
        3
    34C  
    OP
       2018-09-18 21:27:05 +08:00
    经测试,改成 var arr = new Array(1, 2, 3, 4); 之后则没问题,稍后 append 到主题中。
    看样子如果不是明确 new 的话是会被缓存了……
    gkiwi
        4
    gkiwi  
       2018-09-18 21:46:58 +08:00
    @34C 找人测试了,果然如此,这个世界要爆炸。。
    34C
        5
    34C  
    OP
       2018-09-18 21:56:39 +08:00
    @gkiwi 想象一下有多少人升级 12 而不会升级 12.1 的,如果是 bug 以后即便修复了也会有人一直受影响,如果是 feature 这特么也太严重了,多少项目多少代码会受影响,还有 npm 上那些被数千万项目引用的包…
    gkiwi
        6
    gkiwi  
       2018-09-18 22:06:37 +08:00
    @34C #5 定性肯定是 bug。我这边测试不加 load,直接 alert 出来数据都偶发不对。
    一方面浏览器修,二方面就是靠 pollify 了
    34C
        7
    34C  
    OP
       2018-09-18 22:10:13 +08:00
    @gkiwi 我这边测试是 load 事件都会触发,但 load 中申明的变量,有概率会被缓存,太坑了,还好项目开发了一半,有改语法的机会
    yinanc
        8
    yinanc  
       2018-09-18 22:22:41 +08:00 via iPhone
    mark
    前端日常骂娘时间
    34C
        9
    34C  
    OP
       2018-09-18 22:25:30 +08:00
    @yinanc 顶上去让更多人看到,V2 上前端还蛮多的
    yinanc
        10
    yinanc  
       2018-09-18 22:32:55 +08:00 via iPhone
    @34C 真是这么严重的问题的话很快就会有轩然大波了。不如自己先去确认下吧。
    34C
        11
    34C  
    OP
       2018-09-18 22:46:04 +08:00
    @yinanc 所以我的标题是问有哪些变化啊… 因为我这是小项目,也没提前升级测试版 iOS 12,所以来问问看苹果之前有没有公开说明过 safari 会有那些改动啊,除了苹果官方的说明是一种 “确认” 我不知道还能怎么自己先确认了,我和楼上的都测试过可以复现问题,难道是我对 js 的工作机制理解有误… 那 ios 11 和 chrome 之类的都没问题啊…
    edire
        12
    edire  
       2018-09-19 02:53:40 +08:00
    写了个文件修复这个问题:

    https://www.npmjs.com/package/fix-array-reverse

    https://github.com/fanmingfei/array-reverse-ios12

    目前发现只有使用 reverse 才会缓存,另外,不知道苹果是否会热更新修复这个问题。
    edire
        13
    edire  
       2018-09-19 04:44:27 +08:00
    npm 现在限制实在太多了。本来想 npm unpublish 一下再 publish,告诉我 24 小时之内不能 publish 索性改了个名字 https://www.npmjs.com/package/array-reverse-polyfill
    Trim21
        14
    Trim21  
       2018-09-19 05:30:35 +08:00 via Android
    成功复现…
    hax
        15
    hax  
       2018-09-19 06:26:41 +08:00   6
    这显然是一个 bug。并且是个惊天大 bug。

    此 bug 跟 load 事件无关。直接执行即可重现。与刷新也并不直接相关。
    简化的测试代码见: https://github.com/hax/hax.github.com/blob/master/browser-bugs/ios12-safari-array-reverse/test.html
    测试页面链接: https://johnhax.net/browser-bugs/ios12-safari-array-reverse/test


    此 bug 的本质是,Safari 对所有值是 primitive literal (如 null, true, 1, 'x' 是,但 /x/,undefined、NaN 就不是)的 array initializer 做了优化,同一个 initializer 产生的数组在内存里永远指向一份,其 toString 的结果也预先计算好,所以 reverse()之后 toString()结果不变,但实际数组已经变化。正常来说,如果该 array 执行了任何修改操作,则复制到一份独立内存去。这是所谓 copy-on-write 的优化策略。但不幸的,reverse 方法没有触发 CoW。

    另一方面,所有不修改 array 的方法应该不触发 CoW。我实测下来,甚至 copyWithin 和 fill 这样的方法,如果 start/end 相同使得实际上并没有修改效果,也不会触发 CoW。但是神奇的是 slice()会触发 CoW。所以我猜有可能某个苹果的临时工把 reverse/slice 的方法索引搞颠倒了。
    34C
        16
    34C  
    OP
       2018-09-19 09:27:23 +08:00 via iPhone
    @edire @hax 原来 SO 上两条回复也是你们啊…
    atian25
        17
    atian25  
       2018-09-19 11:28:20 +08:00
    @edire 不要 unpublish,直接按 semver 规范发一个 minor 或 patch 就好了
    34D
        18
    34D  
       2018-09-19 13:41:13 +08:00
    没我大。
    34C
        19
    34C  
    OP
       2018-09-19 14:10:23 +08:00 via iPhone
    @34D 你赢了
    oh
        20
    oh  
       2018-09-19 16:42:00 +08:00
    @hax 你这个分析并不能解释为什么 safari 为了性能要缓存变量啊,页面都 reload 了内存都不清空,为了性能值得这么冒险吗?那说不定还有其它隐藏 bug 呢
    JayZangwill
        21
    JayZangwill  
       2018-09-19 16:49:29 +08:00
    这个问题在 qq 浏览器上也能复现
    34C
        22
    34C  
    OP
       2018-09-19 16:57:12 +08:00
    @JayZangwill ios 上所有浏览器都是基于 safari 内核
    mrcode
        23
    mrcode  
       2018-09-19 19:36:47 +08:00
    @34C @34D 两兄弟很溜
    mrcode
        24
    mrcode  
       2018-09-19 19:37:30 +08:00
    #22 @34C 包括 Chrome、Firefox 这些吗?
    mrcode
        25
    mrcode  
       2018-09-19 19:43:36 +08:00
    这个问题是因为什么导致的呢?
    34C
        26
    34C  
    OP
       2018-09-19 19:46:24 +08:00 via iPhone
    @mrcode

    firefox 没装过,但 ios 上的 chrome 就是 safari 套了个皮(仅仅指 ios 上的),什么微信啊 QQ 啊 内置的浏览器都一样

    原因见楼上 hax 的分析咯
    hax
        27
    hax  
       2018-09-19 21:11:59 +08:00
    @oh 根据源码来看,基本上就是我说的问题(除了 reverse/slice 颠倒的瞎猜之外)。至于说刷新,其实是无关的。估计应该是 safari 在刷新本页的时候,一看啥都没变,就不销毁之前的资源继续用了。实际上不是每次刷新都复用的,有概率全清掉的。
    hax
        28
    hax  
       2018-09-19 21:15:04 +08:00
    bug 来源: https://github.com/WebKit/webkit/commit/c02f5d334455d7fe8b16fe642d1f5900c5cde6e9
    修复: https://bugs.webkit.org/show_bug.cgi?id=188794

    是的,上个月 webkit 已经修掉了( 6 月上的 bug 代码),但是 apple 不知道为啥这次发版没把 patch 打上。
    hax
        29
    hax  
       2018-09-19 21:17:58 +08:00
    至于为什么要用 CoW,当然就是为了性能。在 https://bugs.webkit.org/show_bug.cgi?id=185003 这里有提到在某些性能测试中有显著提升。
    但是 CoW 很复杂,一下改了好多代码,所以出 bug 了。其实当时作者也写了很多 testcase,无奈还是漏掉了 reverse()。
    mrcode
        30
    mrcode  
       2018-09-19 23:00:38 +08:00
    大胆猜测一下 hax 就是那个实习生 (逃
    spiderGgl
        31
    spiderGgl  
       2018-09-25 23:23:07 +08:00
    兄弟,你吃屎了,这样害我
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1205 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 17:29 PVG 01:29 LAX 09:29 JFK 12:29
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86