javascript - आईओएस 12 सफारी में ऐरे राज्य कैश किया जाएगा। क्या यह एक बग या फीचर है?




ios safari ios12 (5)

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

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

मुझे नए रिलीज आईओएस 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-bug.html


Answers

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

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

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

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

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

यह बग 21 अगस्त को ऐप्पल को बताया गया था। फिक्स 27 अगस्त को वेबकिट रिपोजिटरी में उतरा और सफारी 12.0.1 और आईओएस 12.1 में 30 अक्टूबर, 2018 को भेज दिया गया।


यह वेबकिट में एक बग है। हालांकि यह उनके अंत में हल हो गया है लेकिन अभी तक आईओएस जीएम रिलीज के साथ भेज दिया गया है। इस समस्या के समाधान में से एक:

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

मैंने बग को ठीक करने के लिए एक lib लिखा था। 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);
  }
})();


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

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


सरणी लंबाई संपत्ति काम करते हैं:

myarray[myarray.length] = 'new element value added to the end of the array';

myarray.length सरणी में तारों की संख्या देता है। जेएस शून्य आधारित है इसलिए सरणी की अगली तत्व कुंजी सरणी की वर्तमान लंबाई होगी। पूर्व:

var myarray = [0, 1, 2, 3],
    myarrayLength = myarray.length; //myarrayLength is set to 4




javascript ios safari ios12