@@ -55,7 +55,9 @@ var array_splice = ArrayPrototype.splice;
55
55
var array_push = ArrayPrototype . push ;
56
56
var array_unshift = ArrayPrototype . unshift ;
57
57
var array_concat = ArrayPrototype . concat ;
58
+ var str_split = StringPrototype . split ;
58
59
var call = FunctionPrototype . call ;
60
+ var apply = FunctionPrototype . apply ;
59
61
var max = Math . max ;
60
62
var min = Math . min ;
61
63
@@ -163,7 +165,6 @@ var ES = {
163
165
// http://es5.github.com/#x9.9
164
166
/* replaceable with https://npmjs.com/package/es-abstract ES5.ToObject */
165
167
ToObject : function ( o ) {
166
- /* jshint eqnull: true */
167
168
if ( o == null ) { // this matches both null and undefined
168
169
throw new TypeError ( "can't convert " + o + ' to object' ) ;
169
170
}
@@ -176,11 +177,160 @@ var ES = {
176
177
}
177
178
} ;
178
179
180
+ // Check failure of by-index access of string characters (IE < 9)
181
+ // and failure of `0 in boxedString` (Rhino)
182
+ var boxedString = $Object ( 'a' ) ;
183
+ var splitString = boxedString [ 0 ] !== 'a' || ! ( 0 in boxedString ) ;
184
+
179
185
//
180
186
// Function
181
187
// ========
182
188
//
183
189
190
+ // Tests for inconsistent or buggy `[[Class]]` strings.
191
+ /* eslint-disable no-useless-call */
192
+ var hasToStringTagBasicBug = to_string . call ( ) !== '[object Undefined]' || to_string . call ( null ) !== '[object Null]' ;
193
+ /* eslint-enable no-useless-call */
194
+ var hasToStringTagLegacyArguments = to_string . call ( arguments ) !== '[object Arguments]' ;
195
+ var hasToStringTagInconsistency = hasToStringTagBasicBug || hasToStringTagLegacyArguments ;
196
+ // Others that could be fixed:
197
+ // Older ES3 native functions like `alert` return `[object Object]`.
198
+ // Inconsistent `[[Class]]` strings for `window` or `global`.
199
+
200
+ var hasApplyArrayLikeDeficiency = ( function ( ) {
201
+ var arrayLike = { length : 4 , 0 : 1 , 2 : 4 , 3 : true } ;
202
+ var expectedArray = [ 1 , undefined , 4 , true ] ;
203
+ var actualArray ;
204
+ try {
205
+ actualArray = ( function ( ) {
206
+ // `array_slice` is safe to use here, no known issue at present.
207
+ return array_slice . apply ( arguments ) ;
208
+ } . apply ( null , arrayLike ) ) ;
209
+ } catch ( e ) {
210
+ if ( to_string . call ( actualArray ) !== '[object Array]' || actualArray . length !== arrayLike . length ) {
211
+ return true ;
212
+ }
213
+ while ( expectedArray . length ) {
214
+ if ( actualArray . pop ( ) !== expectedArray . pop ( ) ) {
215
+ return true ;
216
+ }
217
+ }
218
+ }
219
+ return false ;
220
+ } ( ) ) ;
221
+
222
+ var shouldPatchCallApply = hasToStringTagInconsistency || hasApplyArrayLikeDeficiency ;
223
+
224
+ if ( shouldPatchCallApply ) {
225
+ // Constant. ES3 maximum array length.
226
+ var MAX_ARRAY_LENGTH = 4294967295 ;
227
+ // To prevent recursion when `call` and `apply` are patched. Robustness.
228
+ call . call = call ;
229
+ call . apply = apply ;
230
+ apply . call = call ;
231
+ apply . apply = apply ;
232
+ }
233
+
234
+ if ( hasToStringTagLegacyArguments ) {
235
+ // This function is for use within `call` and `apply` only.
236
+ // To avoid any possibility of `call` recursion we use original `hasOwnProperty`.
237
+ var isDuckTypeArguments = ( function ( hasOwnProperty ) {
238
+ return function ( value ) {
239
+ if ( value != null ) { // Checks `null` or `undefined`.
240
+ if ( typeof value === 'object' && call . call ( hasOwnProperty , value , 'length' ) ) {
241
+ var length = value . length ;
242
+ if ( length > - 1 && length % 1 === 0 && length <= MAX_ARRAY_LENGTH ) {
243
+ return ! call . call ( hasOwnProperty , value , 'arguments' ) && call . call ( hasOwnProperty , value , 'callee' ) ;
244
+ }
245
+ }
246
+ }
247
+ return false ;
248
+ } ;
249
+ } ( ObjectPrototype . hasOwnProperty ) ) ;
250
+ }
251
+
252
+ if ( shouldPatchCallApply ) {
253
+ // For use with `call` and `apply` fixes.
254
+ var toStringTag = function ( value ) {
255
+ // Add whatever fixes for getting `[[Class]]` strings here.
256
+ if ( value === null ) {
257
+ return '[object Null]' ;
258
+ }
259
+ if ( typeof value === 'undefined' ) {
260
+ return '[object Undefined]' ;
261
+ }
262
+ if ( hasToStringTagLegacyArguments && isDuckTypeArguments ( value ) ) {
263
+ return '[object Arguments]' ;
264
+ }
265
+ // `to_string` is safe to use here, no known issue at present.
266
+ return call . call ( to_string , value ) ;
267
+ } ;
268
+ // For use with `apply` fix.
269
+ var isArrayLikeObject = function ( value ) {
270
+ if ( value != null ) { // Checks `null` or `undefined`.
271
+ var type = typeof value ;
272
+ // `to_string` is safe to use here, no known issue at present.
273
+ if ( type === 'object' && type !== 'function' && call . call ( to_string , value ) !== '[object Function]' ) {
274
+ var length = value . length ;
275
+ if ( typeof length === 'number' ) {
276
+ return length > - 1 && length % 1 === 0 && length <= MAX_ARRAY_LENGTH ;
277
+ }
278
+ }
279
+ }
280
+ return false ;
281
+ } ;
282
+ }
283
+
284
+ defineProperties ( FunctionPrototype , {
285
+ // ES-5 15.3.4.3
286
+ // http://es5.github.io/#x15.3.4.3
287
+ // The apply() method calls a function with a given this value and arguments
288
+ // provided as an array (or an array-like object).
289
+ apply : function ( thisArg ) {
290
+ var argsArray = arguments [ 1 ] ;
291
+ if ( arguments . length > 1 ) {
292
+ // IE9 (though fix not needed) has a problem here for some reason!!!
293
+ // Pretty much any function here causes error `SCRIPT5007: Object expected`.
294
+ if ( ! isArrayLikeObject ( argsArray ) ) {
295
+ throw new TypeError ( 'Function.prototype.apply: Arguments list has wrong type' ) ;
296
+ }
297
+ }
298
+ // If `this` is `Object#toString`, captured or modified.
299
+ if ( this === to_string || this === Object . prototype . toString ) {
300
+ return toStringTag ( thisArg ) ;
301
+ }
302
+ // All other applys.
303
+ if ( arguments . length > 1 ) {
304
+ // Boxed string access bug fix.
305
+ if ( splitString && to_string . call ( thisArg ) === '[object String]' ) {
306
+ // `str_split` is safe to use here, no known issue at present.
307
+ argsArray = call . call ( str_split , argsArray , '' ) ;
308
+ }
309
+ // `array_slice` is safe to use here, no known issue at present.
310
+ argsArray = call . call ( array_slice , argsArray ) ;
311
+ } else {
312
+ // `argsArray` was `undefined` (not present).
313
+ argsArray = [ ] ;
314
+ }
315
+
316
+ return apply . call ( this , thisArg , argsArray ) ;
317
+ } ,
318
+
319
+ // ES-5 15.3.4.4
320
+ // http://es5.github.io/#x15.3.4.4
321
+ // The call() method calls a function with a given this value and arguments
322
+ // provided individually.
323
+ call : function ( thisArg ) {
324
+ // If `this` is `Object#toString`, captured or modified.
325
+ if ( this === to_string || this === Object . prototype . toString ) {
326
+ return toStringTag ( thisArg ) ;
327
+ }
328
+ // All other calls.
329
+ // `array_slice` is safe to use here, no known issue at present.
330
+ return apply . call ( this , thisArg , call . call ( array_slice , arguments , 1 ) ) ;
331
+ }
332
+ } , shouldPatchCallApply ) ;
333
+
184
334
// ES-5 15.3.4.5
185
335
// http://es5.github.com/#x15.3.4.5
186
336
@@ -321,7 +471,7 @@ defineProperties(FunctionPrototype, {
321
471
} ) ;
322
472
323
473
// _Please note: Shortcuts are defined after `Function.prototype.bind` as we
324
- // us it in defining shortcuts.
474
+ // use it in defining shortcuts.
325
475
var owns = call . bind ( ObjectPrototype . hasOwnProperty ) ;
326
476
var toStr = call . bind ( ObjectPrototype . toString ) ;
327
477
var strSlice = call . bind ( StringPrototype . slice ) ;
@@ -372,11 +522,6 @@ defineProperties($Array, { isArray: isArray });
372
522
// http://es5.github.com/#x15.4.4.18
373
523
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
374
524
375
- // Check failure of by-index access of string characters (IE < 9)
376
- // and failure of `0 in boxedString` (Rhino)
377
- var boxedString = $Object ( 'a' ) ;
378
- var splitString = boxedString [ 0 ] !== 'a' || ! ( 0 in boxedString ) ;
379
-
380
525
var properlyBoxesContext = function properlyBoxed ( method ) {
381
526
// Check node 0.6.21 bug where third parameter is not boxed
382
527
var properlyBoxesNonStrict = true ;
0 commit comments