OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 } | 407 } |
408 var body = (n > 0) ? ToString(%_Arguments(n - 1)) : ''; | 408 var body = (n > 0) ? ToString(%_Arguments(n - 1)) : ''; |
409 var source = '(function anonymous(' + p + ') { ' + body + ' })'; | 409 var source = '(function anonymous(' + p + ') { ' + body + ' })'; |
410 | 410 |
411 // The call to SetNewFunctionAttributes will ensure the prototype | 411 // The call to SetNewFunctionAttributes will ensure the prototype |
412 // property of the resulting function is enumerable (ECMA262, 15.3.5.2). | 412 // property of the resulting function is enumerable (ECMA262, 15.3.5.2). |
413 return %SetNewFunctionAttributes(%CompileString(source, false)()); | 413 return %SetNewFunctionAttributes(%CompileString(source, false)()); |
414 }; | 414 }; |
415 | 415 |
416 %SetCode($Function, NewFunction); | 416 %SetCode($Function, NewFunction); |
417 | |
418 | |
419 // NOTE: The following functions (call and apply) are only used in this | |
420 // form on the ARM platform. On IA-32 they are handled through specialized | |
421 // builtins; see builtins-ia32.cc. | |
422 | |
423 %AddProperty($Function.prototype, "call", function(receiver) { | |
424 // Make sure the receiver of this call is a function. If it isn't | |
425 // we "fake" a call of it (without the right arguments) to force | |
426 // an exception to be thrown. | |
427 if (!IS_FUNCTION(this)) this(); | |
428 | |
429 // If receiver is null or undefined set the receiver to the global | |
430 // object. If the receiver isn't an object, we convert the | |
431 // receiver to an object. | |
432 if (receiver == null) receiver = global; | |
433 else if (!IS_OBJECT(receiver)) receiver = ToObject(receiver); | |
434 | |
435 %_SetThisFunction(this); | |
436 %_SetThis(receiver); | |
437 | |
438 var len = %_GetArgumentsLength(1); | |
439 return %_ShiftDownAndTailCall(len ? len - 1 : 0); | |
440 }, DONT_ENUM); | |
441 | |
442 | |
443 // This implementation of Function.prototype.apply replaces the stack frame | |
444 // of the apply call with the new stack frame containing the arguments from | |
445 // the args array. | |
446 %AddProperty($Function.prototype, "apply", function(receiver, args) { | |
447 var length = (args == null) ? 0 : ToUint32(args.length); | |
448 | |
449 // We can handle any number of apply arguments if the stack is | |
450 // big enough, but sanity check the value to avoid overflow when | |
451 // multiplying with pointer size. | |
452 if (length > 0x800000) { | |
453 throw new $RangeError( | |
454 "Function.prototype.apply cannot support " + length + " arguments."); | |
455 } | |
456 | |
457 if (!IS_FUNCTION(this)) { | |
458 throw new $TypeError('Function.prototype.apply was called on ' + this.toStri
ng() + ', which is a ' + (typeof this) + ' and not a function'); | |
459 } | |
460 | |
461 // Make sure args has the right type. | |
462 if (args != null && %ClassOf(args) !== 'Array' && %ClassOf(args) !== 'Argument
s') { | |
463 throw new $TypeError('Function.prototype.apply: args has wrong type'); | |
464 } | |
465 | |
466 // If receiver is null or undefined set the receiver to the global | |
467 // object. If the receiver isn't an object, we convert the | |
468 // receiver to an object. | |
469 if (receiver == null) receiver = global; | |
470 else if (!IS_OBJECT(receiver)) receiver = ToObject(receiver); | |
471 | |
472 %_SetThisFunction(this); | |
473 %_SetThis(receiver); | |
474 | |
475 var arguments_length = %_GetArgumentsLength(2); | |
476 | |
477 // This method has 2 formal arguments so if less are passed, then space has | |
478 // been made. | |
479 if (arguments_length < 2) | |
480 arguments_length = 2; | |
481 | |
482 // Move some stuff to locals so they don't get overwritten when we start | |
483 // expanding the args array. | |
484 var saved_args = args; | |
485 | |
486 if (arguments_length > length) { | |
487 // We have too many arguments - we need to squash the frame. | |
488 %_SquashFrame(arguments_length, length); | |
489 } else if (arguments_length != length) { | |
490 // We have too few spaces for arguments - we need to expand the frame. | |
491 if (!%_ExpandFrame(arguments_length, length)) { | |
492 throw new $RangeError( | |
493 "Function.prototype.apply cannot find stack space for " + length + " a
rguments."); | |
494 } | |
495 // GC doesn't like junk in the arguments! | |
496 for (var i = 0; i < length; i++) { | |
497 %_SetArgument(i, 0, length); | |
498 } | |
499 } | |
500 | |
501 // Update-number-of-arguments field to keep things looking consistent for | |
502 // stack traces, and uses of arguments or arguments.length. | |
503 %_SetArgumentsLength(length); | |
504 | |
505 // NOTE: For the fast case this should be implemented in assembler, | |
506 // which would allow us to omit bounds and class checks galore. The | |
507 // assembler version could fall back to this implementation if | |
508 // tricky stuff is found, like arrays implemented as dictionaries or | |
509 // holes in arrays. | |
510 for (var i = 0; i < length; i++) { | |
511 %_SetArgument(i, saved_args[i], length); | |
512 } | |
513 | |
514 // Replaces the current frame with the new call. This has the added effect | |
515 // of removing apply from the stack trace entirely, which matches the | |
516 // behaviour of Firefox. | |
517 return %_TailCallWithArguments(length); | |
518 }, DONT_ENUM); | |
519 | |
520 | |
OLD | NEW |