prototypejs / prototype

Prototype JavaScript framework
http://prototypejs.org/
Other
3.53k stars 639 forks source link

Native Array.from is overwritten by $A which is not able to handle all cases used by the native function #338

Open maxwangry opened 6 years ago

maxwangry commented 6 years ago

In version 1.7.3, the native Array.from is overwritten by $A as below:

function $A(iterable) {
  if (!iterable) return [];
  if ('toArray' in Object(iterable)) return iterable.toArray();
  var length = iterable.length || 0, results = new Array(length);
  while (length--) results[length] = iterable[length];
  return results;
}

Array.from = $A;

From the definition of these two functions: The Array.from() method creates a new Array instance from an array-like or iterable object. However, the $A function only accepts an array-like collection (anything with numeric indices). So $A is not able to handle other iterable objects without numeric indices such as MapIterator.

When $A try to create a new array by reading the iterable.length which does exist in some native iterable objects such as MapIterator, the result will be an array with length 0 returned back.

Hope this will be fixed soon.

Thanks, Max

manticorp commented 2 years ago

+1 to this...

ejuanis commented 2 years ago

+1 to this. Perhaps make this a conditional polyfill if Array,from is supported natively. Google Maps v3.46 and above failed to load the satellite imagery due to this.

This site overrides Array.from() with an implementation that doesn't support iterables, which could cause Google Maps JavaScript API v3 to not work correctly.

Lubrum commented 2 years ago

+1 to this. Also having issues with Google Maps 3.46 and above (satellite images).

savetheclocktower commented 2 years ago

For a number of reasons, I view it as unlikely that there will ever be another release of Prototype, so I'd suggest working around this:

Similar approaches are possible if you bundle your dependencies.

stefanbackor commented 2 weeks ago

Try executing this snippet before any other code to protect native implementation

const nativeArrayFrom = Array.from
Object.defineProperty(Array, 'from', {
  get: function () {
    return nativeArrayFrom
  },
  set: function () {
    console.warn('Attempt to overwriting native `Array.from` prevented.')
  },
})