1

I have not standard problem with my service.

I'm using library Zepto in my SaaS script on client's sites. But 2 hours ago one of my clients wrote me, that my script is not working. I checked all code and found that: he using Prototype JavaScript framework, version 1.7. And in this code I see:

var Enumerable = (function() {
...
  function each(iterator, context) {...}
  function all(iterator, context) {...}
...    
}();

I mean, that all native array methods are overwrote. Zepto.js using this native methods:

each: function(callback){
    emptyArray.every.call(this, function(el, idx){
        return callback.call(el, idx, el) !== false
    })
    return this
},

where

emptyArray = [];

I think this version of prototype library has some bug because (from console:)

xxx:xxx Uncaught RangeError: Maximum call stack size exceeded

There are circle with Zepto's emtyArray.each and Enumerable.all functions.

My question is, how can I use method [].all instead overwrited [].prototype.all?

Update

var words = ['hello', 'world', '!'];

console.log('Before overwrite');
[].every.call(words, function(el, idx) {
  console.log(el);
});

Array.prototype.every = function(iterator, context)
{
  console.error('not works');
}

console.log('After overwrite');
[].every.call(words, function(el, idx) {
  console.log(el);
});

How to use native .every again?

halfer
  • 19,824
  • 17
  • 99
  • 186
Leonid Zakharov
  • 940
  • 1
  • 6
  • 11
  • Which of the two libraries loads first? – Bergi Sep 05 '16 at 20:01
  • Prototype. I can't do something like `var baseEach = Array.prototype.each` before this library will load =( – Leonid Zakharov Sep 05 '16 at 20:04
  • could you show the part of your code, that causes this bug? Link your lib, provide a fiddle. something to reproduce/debug the problem. – Thomas Sep 05 '16 at 20:14
  • The problem not just in prototype 1.7. Problem is that any script can override any native functions and methods. I need to find some way to use really stable native versions of this functions and methods. – Leonid Zakharov Sep 05 '16 at 20:20
  • My question is how can I use native `Array.prototype.all` method if it was overwrote by any other script. – Leonid Zakharov Sep 05 '16 at 20:20
  • you can't, what's gone is gone. That's the reason that it's considered unsafe/dangerous to extend the prototypes of Classes you don't own. And if it's really a bug in Prototype causing this, it's the fault of your client to use a buggy lib. It's his responsibility if he includes a lib that has such side-effects. But still, since I have mostly positive experiences with Prototype, and at first glance, I see no obvious errors in prototypes code, can you provide some code to reproduce the bug? Or at least the significant parts of your code. – Thomas Sep 05 '16 at 20:33
  • 1
    I found solution: http://stackoverflow.com/questions/8580431/recovering-built-in-methods-that-have-been-overwritten – Leonid Zakharov Sep 05 '16 at 20:42
  • that's not a solution that's a hack and due to the mentioned side-effect, it's potentially more dangerous than everything that Prototype does. These recovered functions return types that are "clones" of the types on this page. And if you revert Prototypes changes by injecting this function to `Array.prototype`, it could break pretty much everything on your clients page ... except your script, maybe. – Thomas Sep 05 '16 at 21:03
  • If you are able to upgrade to Prototype 1.7.3, the native methods are preserved if they exist in the browser that is running it in the latest version. Between 1.7 and 1.7.1 that was the biggest change. – Geek Num 88 Sep 06 '16 at 19:15
  • This is not my site. Just one of my clients using my service. It's impossible to me check all 30000 sites. I trying to find solution when my script working is guarantied. – Leonid Zakharov Sep 07 '16 at 13:15

1 Answers1

0

Iframing is not allowed in code snippet, but that's is working variant:

Array.prototype.every = function()
{
  console.log('invalid');
}

var iframe = window.document.createElement("iframe");
window.document.documentElement.appendChild(iframe);
var nativeWnd = iframe.contentWindow;
var nativeArray = nativeWnd.Array;
var parent = iframe.parentNode || iframe.parent;
parent.removeChild(iframe);

var oArr = new Array();
var nArr = new nativeArray();

console.log(oArr.every);
console.log(nArr.every);
Leonid Zakharov
  • 940
  • 1
  • 6
  • 11
  • I'll be glad to find any better way without using iframes. If somebody know how to do it without iframes, write it please. – Leonid Zakharov Sep 06 '16 at 02:03
  • It seems iframes is THE solution. Check out http://stackoverflow.com/questions/8580431/recovering-built-in-methods-that-have-been-overwritten and http://stackoverflow.com/questions/12522618/how-to-restore-an-overridden-functions-original-state-in-javascript – rosell.dk Dec 07 '16 at 15:23
  • 1
    And I see no reason to want to avoid iframes. Are there any reasons? – rosell.dk Dec 07 '16 at 15:26