| 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 |