@@ -55,6 +55,7 @@ var array_splice = ArrayPrototype.splice;
5555var array_push = ArrayPrototype . push ;
5656var array_unshift = ArrayPrototype . unshift ;
5757var array_concat = ArrayPrototype . concat ;
58+ var str_split = StringPrototype . split ;
5859var call = FunctionPrototype . call ;
5960var apply = FunctionPrototype . apply ;
6061var max = Math . max ;
@@ -175,11 +176,143 @@ var ES = {
175176 }
176177} ;
177178
179+ // Check failure of by-index access of string characters (IE < 9)
180+ // and failure of `0 in boxedString` (Rhino)
181+ var boxedString = $Object ( 'a' ) ;
182+ var splitString = boxedString [ 0 ] !== 'a' || ! ( 0 in boxedString ) ;
183+
178184//
179185// Function
180186// ========
181187//
182188
189+ // Tests for inconsistent or buggy `[[Class]]` strings.
190+ /* eslint-disable no-useless-call */
191+ var hasToStringTagBasicBug = to_string . call ( ) !== '[object Undefined]' || to_string . call ( null ) !== '[object Null]' ;
192+ /* eslint-enable no-useless-call */
193+ var hasToStringTagLegacyArguments = to_string . call ( arguments ) !== '[object Arguments]' ;
194+ var hasToStringTagInconsistency = hasToStringTagBasicBug || hasToStringTagLegacyArguments ;
195+ // Others that could be fixed:
196+ // Older ES3 native functions like `alert` return `[object Object]`.
197+ // Inconsistent `[[Class]]` strings for `window` or `global`.
198+
199+ var hasApplyArrayLikeDeficiency = ( function ( ) {
200+ var arrayLike = { length : 4 , 0 : 1 , 2 : 4 , 3 : true } ;
201+ var expectedArray = [ 1 , undefined , 4 , true ] ;
202+ var actualArray ;
203+ try {
204+ actualArray = ( function ( ) {
205+ // `array_slice` is safe to use here, no known issue at present.
206+ return array_slice . apply ( arguments ) ;
207+ } . apply ( null , arrayLike ) ) ;
208+ } catch ( e ) {
209+ if ( to_string . call ( actualArray ) !== '[object Array]' || actualArray . length !== arrayLike . length ) {
210+ return true ;
211+ }
212+ while ( expectedArray . length ) {
213+ if ( actualArray . pop ( ) !== expectedArray . pop ( ) ) {
214+ return true ;
215+ }
216+ }
217+ }
218+ return false ;
219+ } ( ) ) ;
220+
221+ var shouldPatchCallApply = hasToStringTagInconsistency || hasApplyArrayLikeDeficiency ;
222+
223+ if ( shouldPatchCallApply ) {
224+ // To prevent recursion when `call` and `apply` are patched. Robustness.
225+ call . call = call ;
226+ call . apply = apply ;
227+ apply . call = call ;
228+ apply . apply = apply ;
229+ }
230+
231+ // This function is for use within `call` and `apply` only.
232+ // To avoid any possibility of `call` recursion we use original `hasOwnProperty`.
233+ var isDuckTypeArguments = hasToStringTagLegacyArguments && ( function ( hasOwnProperty ) {
234+ return function ( value ) {
235+ if ( value != null ) { // Checks `null` or `undefined`.
236+ if ( typeof value === 'object' && call . call ( hasOwnProperty , value , 'length' ) ) {
237+ var length = value . length ;
238+ // Constant. ES3 maximum array length. 2^32-1
239+ if ( length > - 1 && length % 1 === 0 && length <= 4294967295 ) {
240+ return ! call . call ( hasOwnProperty , value , 'arguments' ) && call . call ( hasOwnProperty , value , 'callee' ) ;
241+ }
242+ }
243+ }
244+ return false ;
245+ } ;
246+ } ( ObjectPrototype . hasOwnProperty ) ) ;
247+
248+ // For use with `call` and `apply` fixes.
249+ var toStringTag = shouldPatchCallApply && function ( value ) {
250+ // Add whatever fixes for getting `[[Class]]` strings here.
251+ if ( value === null ) {
252+ return '[object Null]' ;
253+ }
254+ if ( typeof value === 'undefined' ) {
255+ return '[object Undefined]' ;
256+ }
257+ if ( hasToStringTagLegacyArguments && isDuckTypeArguments ( value ) ) {
258+ return '[object Arguments]' ;
259+ }
260+ // `to_string` is safe to use here, no known issue at present.
261+ return call . call ( to_string , value ) ;
262+ } ;
263+
264+ defineProperties ( FunctionPrototype , {
265+ // ES-5 15.3.4.3
266+ // http://es5.github.io/#x15.3.4.3
267+ // The apply() method calls a function with a given this value and arguments
268+ // provided as an array (or an array-like object).
269+ apply : function ( thisArg ) {
270+ var argsArray = arguments [ 1 ] ;
271+ var type = typeof argsArray ;
272+ if ( arguments . length > 1 ) {
273+ // IE9 (though fix not needed) has a problem here for some reason!!!
274+ // Pretty much any function here causes error `SCRIPT5007: Object expected`.
275+ if ( type !== 'undefined' && type !== 'object' && type !== 'function' ) {
276+ throw new TypeError ( 'Function.prototype.apply: Arguments list has wrong type' ) ;
277+ }
278+ }
279+ // If `this` is `Object#toString`, captured or modified.
280+ if ( this === to_string || this === Object . prototype . toString ) {
281+ return toStringTag ( thisArg ) ;
282+ }
283+ // All other applys.
284+ if ( arguments . length > 1 && type === 'object' && argsArray && argsArray . length > 0 ) {
285+ // Boxed string access bug fix.
286+ if ( splitString && to_string . call ( argsArray ) === '[object String]' ) {
287+ // `str_split` is safe to use here, no known issue at present.
288+ argsArray = call . call ( str_split , argsArray , '' ) ;
289+ } else {
290+ // `array_slice` is safe to use here, no known issue at present.
291+ argsArray = call . call ( array_slice , argsArray ) ;
292+ }
293+ } else {
294+ // `argsArray` was `undefined` (not present), `== null` or not an object.
295+ argsArray = [ ] ;
296+ }
297+
298+ return apply . call ( this , thisArg , argsArray ) ;
299+ } ,
300+
301+ // ES-5 15.3.4.4
302+ // http://es5.github.io/#x15.3.4.4
303+ // The call() method calls a function with a given this value and arguments
304+ // provided individually.
305+ call : function ( thisArg ) {
306+ // If `this` is `Object#toString`, captured or modified.
307+ if ( this === to_string || this === Object . prototype . toString ) {
308+ return toStringTag ( thisArg ) ;
309+ }
310+ // All other calls.
311+ // `array_slice` is safe to use here, no known issue at present.
312+ return apply . call ( this , thisArg , call . call ( array_slice , arguments , 1 ) ) ;
313+ }
314+ } , shouldPatchCallApply ) ;
315+
183316// ES-5 15.3.4.5
184317// http://es5.github.com/#x15.3.4.5
185318
@@ -375,11 +508,6 @@ defineProperties($Array, { isArray: isArray });
375508// http://es5.github.com/#x15.4.4.18
376509// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
377510
378- // Check failure of by-index access of string characters (IE < 9)
379- // and failure of `0 in boxedString` (Rhino)
380- var boxedString = $Object ( 'a' ) ;
381- var splitString = boxedString [ 0 ] !== 'a' || ! ( 0 in boxedString ) ;
382-
383511var properlyBoxesContext = function properlyBoxed ( method ) {
384512 // Check node 0.6.21 bug where third parameter is not boxed
385513 var properlyBoxesNonStrict = true ;
0 commit comments