function-bind.js revision 50ef84f5fad2def87d3fbc737bec4a32711fdef4
1// Copyright 2010 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28// Tests the Function.prototype.bind (ES 15.3.4.5) method. 29 30// Simple tests. 31function foo(x, y, z) { 32 return x + y + z; 33} 34 35var f = foo.bind(foo); 36assertEquals(3, f(1, 1, 1)); 37assertEquals(3, f.length); 38 39f = foo.bind(foo, 2); 40assertEquals(4, f(1, 1)); 41assertEquals(2, f.length); 42 43f = foo.bind(foo, 2, 2); 44assertEquals(5, f(1)); 45assertEquals(1, f.length); 46 47f = foo.bind(foo, 2, 2, 2); 48assertEquals(6, f()); 49assertEquals(0, f.length); 50 51// Test that length works correctly even if more than the actual number 52// of arguments are given when binding. 53f = foo.bind(foo, 1, 2, 3, 4, 5, 6, 7, 8, 9); 54assertEquals(6, f()); 55assertEquals(0, f.length); 56 57// Use a different bound object. 58var obj = {x: 42, y: 43}; 59// Values that would normally be in "this" when calling f_bound_this. 60var x = 42; 61var y = 44; 62 63function f_bound_this(z) { 64 return z + this.y - this.x; 65} 66 67assertEquals(3, f_bound_this(1)) 68f = f_bound_this.bind(obj); 69assertEquals(2, f(1)); 70assertEquals(1, f.length); 71 72f = f_bound_this.bind(obj, 2); 73assertEquals(3, f()); 74assertEquals(0, f.length); 75 76// Test chained binds. 77 78// When only giving the thisArg, any number of binds should have 79// the same effect. 80f = foo.bind(foo); 81assertEquals(3, f(1, 1, 1)); 82f = foo.bind(foo).bind(foo).bind(foo).bind(foo); 83assertEquals(3, f(1, 1, 1)); 84assertEquals(3, f.length); 85 86// Giving bound parameters should work at any place in the chain. 87f = foo.bind(foo, 1).bind(foo).bind(foo).bind(foo); 88assertEquals(3, f(1, 1)); 89assertEquals(2, f.length); 90 91f = foo.bind(foo).bind(foo, 1).bind(foo).bind(foo); 92assertEquals(3, f(1, 1)); 93assertEquals(2, f.length); 94 95f = foo.bind(foo).bind(foo).bind(foo,1 ).bind(foo); 96assertEquals(3, f(1, 1)); 97assertEquals(2, f.length); 98 99f = foo.bind(foo).bind(foo).bind(foo).bind(foo, 1); 100assertEquals(3, f(1, 1)); 101assertEquals(2, f.length); 102 103// Several parameters can be given, and given in different bind invokations. 104f = foo.bind(foo, 1, 1).bind(foo).bind(foo).bind(foo); 105assertEquals(3, f(1)); 106assertEquals(1, f.length); 107 108f = foo.bind(foo).bind(foo, 1, 1).bind(foo).bind(foo); 109assertEquals(3, f(1)); 110assertEquals(1, f.length); 111 112f = foo.bind(foo).bind(foo, 1, 1).bind(foo).bind(foo); 113assertEquals(3, f(1)); 114assertEquals(1, f.length); 115 116f = foo.bind(foo).bind(foo).bind(foo, 1, 1).bind(foo); 117assertEquals(3, f(1)); 118assertEquals(1, f.length); 119 120f = foo.bind(foo).bind(foo).bind(foo).bind(foo, 1, 1); 121assertEquals(3, f(1)); 122assertEquals(1, f.length); 123 124f = foo.bind(foo, 1).bind(foo, 1).bind(foo).bind(foo); 125assertEquals(3, f(1)); 126assertEquals(1, f.length); 127 128f = foo.bind(foo, 1).bind(foo).bind(foo, 1).bind(foo); 129assertEquals(3, f(1)); 130assertEquals(1, f.length); 131 132f = foo.bind(foo, 1).bind(foo).bind(foo).bind(foo, 1); 133assertEquals(3, f(1)); 134assertEquals(1, f.length); 135 136f = foo.bind(foo).bind(foo, 1).bind(foo).bind(foo, 1); 137assertEquals(3, f(1)); 138assertEquals(1, f.length); 139 140// Test constructor calls. 141 142function bar(x, y, z) { 143 this.x = x; 144 this.y = y; 145 this.z = z; 146} 147 148f = bar.bind(bar); 149var obj2 = new f(1,2,3); 150assertEquals(1, obj2.x); 151assertEquals(2, obj2.y); 152assertEquals(3, obj2.z); 153 154f = bar.bind(bar, 1); 155obj2 = new f(2,3); 156assertEquals(1, obj2.x); 157assertEquals(2, obj2.y); 158assertEquals(3, obj2.z); 159 160f = bar.bind(bar, 1, 2); 161obj2 = new f(3); 162assertEquals(1, obj2.x); 163assertEquals(2, obj2.y); 164assertEquals(3, obj2.z); 165 166f = bar.bind(bar, 1, 2, 3); 167obj2 = new f(); 168assertEquals(1, obj2.x); 169assertEquals(2, obj2.y); 170assertEquals(3, obj2.z); 171 172 173// Test bind chains when used as a constructor. 174 175f = bar.bind(bar, 1).bind(bar, 2).bind(bar, 3); 176obj2 = new f(); 177assertEquals(1, obj2.x); 178assertEquals(2, obj2.y); 179assertEquals(3, obj2.z); 180 181// Test instanceof obj2 is bar, not f. 182assertTrue(obj2 instanceof bar); 183assertFalse(obj2 instanceof f); 184 185