Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1059)

Side by Side Diff: src/v8natives.js

Issue 8199004: Reimplement Function.prototype.bind. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed review comments Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/runtime.js ('k') | src/x64/code-stubs-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 1499 matching lines...) Expand 10 before | Expand all | Expand 10 after
1510 1510
1511 1511
1512 function FunctionToString() { 1512 function FunctionToString() {
1513 return FunctionSourceString(this); 1513 return FunctionSourceString(this);
1514 } 1514 }
1515 1515
1516 1516
1517 // ES5 15.3.4.5 1517 // ES5 15.3.4.5
1518 function FunctionBind(this_arg) { // Length is 1. 1518 function FunctionBind(this_arg) { // Length is 1.
1519 if (!IS_SPEC_FUNCTION(this)) { 1519 if (!IS_SPEC_FUNCTION(this)) {
1520 throw new $TypeError('Bind must be called on a function'); 1520 throw new $TypeError('Bind must be called on a function');
1521 } 1521 }
1522 // this_arg is not an argument that should be bound. 1522 var boundFunction = function () {
1523 var argc_bound = (%_ArgumentsLength() || 1) - 1; 1523 // This function must not use any object literals (Object, Array, RegExp),
1524 var fn = this; 1524 // since the literals-array is being used to store the bound data.
1525 if (%_IsConstructCall()) {
1526 return %NewObjectFromBound(boundFunction);
1527 }
1528 var bindings = %BoundFunctionGetBindings(boundFunction);
1525 1529
1526 if (argc_bound == 0) { 1530 var argc = %_ArgumentsLength();
1527 var result = function() { 1531 if (argc == 0) {
1528 if (%_IsConstructCall()) { 1532 return %Apply(bindings[0], bindings[1], bindings, 2, bindings.length - 2);
1529 // %NewObjectFromBound implicitly uses arguments passed to this
1530 // function. We do not pass the arguments object explicitly to avoid
1531 // materializing it and guarantee that this function will be optimized.
1532 return %NewObjectFromBound(fn, null);
1533 }
1534 return %Apply(fn, this_arg, arguments, 0, %_ArgumentsLength());
1535 };
1536 } else {
1537 var bound_args = new InternalArray(argc_bound);
1538 for(var i = 0; i < argc_bound; i++) {
1539 bound_args[i] = %_Arguments(i+1);
1540 } 1533 }
1534 if (bindings.length === 2) {
1535 return %Apply(bindings[0], bindings[1], arguments, 0, argc);
1536 }
1537 var bound_argc = bindings.length - 2;
1538 var argv = new InternalArray(bound_argc + argc);
1539 for (var i = 0; i < bound_argc; i++) {
1540 argv[i] = bindings[i + 2];
1541 }
1542 for (var j = 0; j < argc; j++) {
1543 argv[i++] = %_Arguments(j);
1544 }
1545 return %Apply(bindings[0], bindings[1], argv, 0, bound_argc + argc);
1546 };
1541 1547
1542 var result = function() { 1548 %FunctionRemovePrototype(boundFunction);
1543 // If this is a construct call we use a special runtime method 1549 var new_length = 0;
1544 // to generate the actual object using the bound function. 1550 if (%_ClassOf(this) == "Function") {
1545 if (%_IsConstructCall()) { 1551 // Function or FunctionProxy.
1546 // %NewObjectFromBound implicitly uses arguments passed to this 1552 var old_length = this.length;
1547 // function. We do not pass the arguments object explicitly to avoid 1553 // FunctionProxies might provide a non-UInt32 value. If so, ignore it.
1548 // materializing it and guarantee that this function will be optimized. 1554 if ((typeof old_length === "number") &&
1549 return %NewObjectFromBound(fn, bound_args); 1555 ((old_length >>> 0) === old_length)) {
1550 }
1551
1552 // Combine the args we got from the bind call with the args
1553 // given as argument to the invocation.
1554 var argc = %_ArgumentsLength(); 1556 var argc = %_ArgumentsLength();
1555 var args = new InternalArray(argc + argc_bound); 1557 if (argc > 0) argc--; // Don't count the thisArg as parameter.
1556 // Add bound arguments. 1558 new_length = old_length - argc;
1557 for (var i = 0; i < argc_bound; i++) { 1559 if (new_length < 0) new_length = 0;
1558 args[i] = bound_args[i]; 1560 }
1559 }
1560 // Add arguments from call.
1561 for (var i = 0; i < argc; i++) {
1562 args[argc_bound + i] = %_Arguments(i);
1563 }
1564 return %Apply(fn, this_arg, args, 0, argc + argc_bound);
1565 };
1566 } 1561 }
1562 // This runtime function finds any remaining arguments on the stack,
1563 // so we don't pass the arguments object.
1564 var result = %FunctionBindArguments(boundFunction, this, this_arg, new_length) ;
1567 1565
1568 // We already have caller and arguments properties on functions, 1566 // We already have caller and arguments properties on functions,
1569 // which are non-configurable. It therefore makes no sence to 1567 // which are non-configurable. It therefore makes no sence to
1570 // try to redefine these as defined by the spec. The spec says 1568 // try to redefine these as defined by the spec. The spec says
1571 // that bind should make these throw a TypeError if get or set 1569 // that bind should make these throw a TypeError if get or set
1572 // is called and make them non-enumerable and non-configurable. 1570 // is called and make them non-enumerable and non-configurable.
1573 // To be consistent with our normal functions we leave this as it is. 1571 // To be consistent with our normal functions we leave this as it is.
1574 1572 // TODO(lrn): Do set these to be thrower.
1575 %FunctionRemovePrototype(result);
1576 %FunctionSetBound(result);
1577 // Set the correct length. If this is a function proxy, this.length might
1578 // throw, or return a bogus result. Leave length alone in that case.
1579 // TODO(rossberg): This is underspecified in the current proxy proposal.
1580 try {
1581 var old_length = ToInteger(this.length);
1582 var length = (old_length - argc_bound) > 0 ? old_length - argc_bound : 0;
1583 %BoundFunctionSetLength(result, length);
1584 } catch(x) {}
1585 return result; 1573 return result;
1586 } 1574 }
1587 1575
1588 1576
1589 function NewFunction(arg1) { // length == 1 1577 function NewFunction(arg1) { // length == 1
1590 var n = %_ArgumentsLength(); 1578 var n = %_ArgumentsLength();
1591 var p = ''; 1579 var p = '';
1592 if (n > 1) { 1580 if (n > 1) {
1593 p = new InternalArray(n - 1); 1581 p = new InternalArray(n - 1);
1594 for (var i = 0; i < n - 1; i++) p[i] = %_Arguments(i); 1582 for (var i = 0; i < n - 1; i++) p[i] = %_Arguments(i);
(...skipping 19 matching lines...) Expand all
1614 1602
1615 function SetUpFunction() { 1603 function SetUpFunction() {
1616 %CheckIsBootstrapping(); 1604 %CheckIsBootstrapping();
1617 InstallFunctions($Function.prototype, DONT_ENUM, $Array( 1605 InstallFunctions($Function.prototype, DONT_ENUM, $Array(
1618 "bind", FunctionBind, 1606 "bind", FunctionBind,
1619 "toString", FunctionToString 1607 "toString", FunctionToString
1620 )); 1608 ));
1621 } 1609 }
1622 1610
1623 SetUpFunction(); 1611 SetUpFunction();
OLDNEW
« no previous file with comments | « src/runtime.js ('k') | src/x64/code-stubs-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698