IOS 12 सफारी में ऐरे स्टेट को कैश किया जाएगा। यह एक बग या सुविधा है?


432

2018.10.31 पर अपडेट करें

यह बग आईओएस 12.1 में तय किया गया है, एक अच्छा दिन है ~

मुझे नए जारी किए गए iOS 12 सफारी में ऐरे के मूल्य की स्थिति में एक समस्या मिली, उदाहरण के लिए, कोड इस तरह:

<!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>

पृष्ठ को ताज़ा करने के बाद, सरणी का मान अभी भी उलटा है। क्या यह बग या नई सफारी की विशेषता है?


यहाँ एक डेमो पेज है। आईओएस 12 सफारी के साथ इसका उपयोग करने का प्रयास करें: https://abelyao.github.io/others/ios12-safari-b.ru.html


41
Bug ने macOS
a_rahmanshah

43
सफारी संस्करण 12.0 (13606.2.11) के साथ macOS 10.13.6 (उच्च सिएरा) में एक ही मुद्दा है। पेज को रिफ्रेश करने के बाद भी ऐरे को उलट दिया जाता है।
केविन जिंबेल

2
बग को सफारी 12.0.1 (macOS), साथ ही iOS 12.1 में तय किया गया है।
MrMister

जवाबों:


272

यह निश्चित रूप से एक बग है! और यह बहुत गंभीर बग है।

बग एरेना इनिशियलाइज़र्स के अनुकूलन के कारण है जिसमें सभी मूल्य आदिम शाब्दिक हैं। उदाहरण के लिए, फ़ंक्शन दिया गया:

function buildArray() {
    return [1, null, 'x'];
}

सभी कॉल से संदर्भित सरणी संदर्भ buildArray()एक ही मेमोरी से लिंक होंगे, और कुछ तरीके जैसे कि toString()उनके परिणाम कैश होंगे। आम तौर पर, स्थिरता को बनाए रखने के लिए, इस तरह के अनुकूलित सरणियों पर कोई भी परिवर्तनशील ऑपरेशन डेटा को एक अलग मेमोरी स्पेस और लिंक करने के लिए कॉपी करेगा; इस पैटर्न को कॉपी-ऑन-राइट , या शॉर्ट के लिए CoW कहा जाता है

reverse()विधि mutates सरणी, तो यह एक प्रति-ऑन-राइट सक्रिय होना चाहिए। लेकिन ऐसा नहीं है, क्योंकि मूल कार्यान्वयनकर्ता (ऐपल के कीथ मिलर) ने इस reverse()मामले को याद किया , भले ही उन्होंने कई परीक्षण लिखे थे।

इस बग को 21 अगस्त को Apple को सूचित किया गया था । यह फिक्स 27 अगस्त को WebKit रिपॉजिटरी में उतरा और 30 अक्टूबर, 2018 को सफारी 12.0.1 और iOS 12.1 में भेज दिया गया।


11
नोट: मैक ओएस एक्स पर सफारी 12.0 भी एक ही मुद्दा है।
hax

17
हाँ, यह पहले से ही स्रोतों में तय किया गया है, और सफारी प्रौद्योगिकी पूर्वावलोकन में पहले से ही भेज दिया गया है। सफारी टेक्नोलॉजी प्रिव्यू 65 में cdn.miss.cat/demo/ios12-safari-bug.html आज़माएं । आप पाएंगे कि इसमें बग नहीं है।
साइडशॉबर्कर

6
मुझे विश्वास नहीं है कि बग का अंतर्निहित कारण एक इंडेक्स मिक्सअप का परिणाम है; इसके बजाय, ऐसा लगता है कि किसी वस्तु को संशोधित करने से पहले अपरिवर्तनीय है या नहीं यह देखने के लिए उपेक्षा के कारण होता है। स्लाइस समस्या का एक समान स्पष्टीकरण हो सकता है, लेकिन यह समान नहीं है, लेकिन रिवर्स के लिए पैच द्वारा तय नहीं किया जाएगा, जहां तक ​​मैं बता सकता हूं। आपको स्लाइस समस्या के लिए एक WebKit बग रिपोर्ट खोलने पर विचार करना चाहिए।
Zenexer

5
@Zenexer आप सही हैं। मैंने यह उत्तर लिखने से पहले मुझे बग्सवेबकैट.ऑर्किश_बग.कोजीआईडीई = 188794 पर पाया और स्रोत कोड देखें। मैं अपने उत्तर को संपादित करूंगा।
hax

75

मैंने बग को ठीक करने के लिए एक परिवाद लिखा था। https://www.npmjs.com/package/array-reverse-polyfill

यह कोड है :

(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);
  }
})();


4
किसी भी समय अपडेट करें। योगदान करने के लिए आपका स्वागत है।
एडियर फैन

14
@ ज़ेफी, मुझे लगता है कि लंबाई पर लिखने से ( this.length = this.length) कॉपी ऑन लिखने पर ट्रिगर हो जाएगा, इसलिए सरणी का मेमोरी पता बदल जाएगा, और इसलिए व्यवहार को ठीक कर देगा reverse
--œ

14

यह वेबकिट में एक बग है । हालांकि यह उनके अंत में हल किया गया है लेकिन अभी तक iOS जीएम रिलीज के साथ शिप नहीं किया गया है। इस समस्या के समाधान में से एक:

(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;
    }
  }
})();

6

लगता है कि तत्वों की संख्या में परिवर्तन नहीं किया जाएगा।
मैं इस तरह से बचने में सक्षम था।

<!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>

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.