OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 11 matching lines...) Expand all Loading... | |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 // Tests the Function.prototype.bind (ES 15.3.4.5) method. | 28 // Tests the Function.prototype.bind (ES 15.3.4.5) method. |
29 | 29 |
30 // Simple tests. | 30 // Simple tests. |
31 function foo(x, y, z) { | 31 function foo(x, y, z) { |
32 return x + y + z; | 32 return [this, arguments.length, x]; |
33 } | 33 } |
34 | 34 |
35 assertEquals(3, foo.length); | |
36 | |
35 var f = foo.bind(foo); | 37 var f = foo.bind(foo); |
36 assertEquals(3, f(1, 1, 1)); | 38 assertEquals([foo, 3, 1], f(1, 2, 3)); |
37 assertEquals(3, f.length); | 39 assertEquals(3, f.length); |
38 | 40 |
39 f = foo.bind(foo, 2); | 41 f = foo.bind(foo, 1); |
40 assertEquals(4, f(1, 1)); | 42 assertEquals([foo, 3, 1], f(2, 3)); |
41 assertEquals(2, f.length); | 43 assertEquals(2, f.length); |
42 | 44 |
43 f = foo.bind(foo, 2, 2); | 45 f = foo.bind(foo, 1, 2); |
44 assertEquals(5, f(1)); | 46 assertEquals([foo, 3, 1], f(3)); |
45 assertEquals(1, f.length); | 47 assertEquals(1, f.length); |
46 | 48 |
47 f = foo.bind(foo, 2, 2, 2); | 49 f = foo.bind(foo, 1, 2, 3); |
48 assertEquals(6, f()); | 50 assertEquals([foo, 3, 1], f()); |
49 assertEquals(0, f.length); | 51 assertEquals(0, f.length); |
50 | 52 |
51 // Test that length works correctly even if more than the actual number | 53 // Test that length works correctly even if more than the actual number |
52 // of arguments are given when binding. | 54 // of arguments are given when binding. |
53 f = foo.bind(foo, 1, 2, 3, 4, 5, 6, 7, 8, 9); | 55 f = foo.bind(foo, 1, 2, 3, 4, 5, 6, 7, 8, 9); |
54 assertEquals(6, f()); | 56 assertEquals([foo, 9, 1], f()); |
55 assertEquals(0, f.length); | 57 assertEquals(0, f.length); |
56 | 58 |
57 // Use a different bound object. | 59 // Use a different bound object. |
58 var obj = {x: 42, y: 43}; | 60 var obj = {x: 42, y: 43}; |
59 // Values that would normally be in "this" when calling f_bound_this. | 61 // Values that would normally be in "this" when calling f_bound_this. |
60 var x = 42; | 62 var x = 42; |
61 var y = 44; | 63 var y = 44; |
62 | 64 |
63 function f_bound_this(z) { | 65 function f_bound_this(z) { |
64 return z + this.y - this.x; | 66 return z + this.y - this.x; |
65 } | 67 } |
66 | 68 |
67 assertEquals(3, f_bound_this(1)) | 69 assertEquals(3, f_bound_this(1)) |
68 f = f_bound_this.bind(obj); | 70 f = f_bound_this.bind(obj); |
69 assertEquals(2, f(1)); | 71 assertEquals(2, f(1)); |
70 assertEquals(1, f.length); | 72 assertEquals(1, f.length); |
71 | 73 |
72 f = f_bound_this.bind(obj, 2); | 74 f = f_bound_this.bind(obj, 2); |
73 assertEquals(3, f()); | 75 assertEquals(3, f()); |
74 assertEquals(0, f.length); | 76 assertEquals(0, f.length); |
75 | 77 |
76 // Test chained binds. | 78 // Test chained binds. |
77 | 79 |
78 // When only giving the thisArg, any number of binds should have | 80 // When only giving the thisArg, any number of binds should have |
79 // the same effect. | 81 // the same effect. |
80 f = foo.bind(foo); | 82 f = foo.bind(foo); |
81 assertEquals(3, f(1, 1, 1)); | 83 assertEquals([foo, 3, 1], f(1, 2, 3)); |
82 f = foo.bind(foo).bind(foo).bind(foo).bind(foo); | 84 |
83 assertEquals(3, f(1, 1, 1)); | 85 var not_foo = {}; |
86 f = foo.bind(foo).bind(not_foo).bind(not_foo).bind(not_foo); | |
87 assertEquals([foo, 3, 1], f(1, 2, 3)); | |
84 assertEquals(3, f.length); | 88 assertEquals(3, f.length); |
85 | 89 |
86 // Giving bound parameters should work at any place in the chain. | 90 // Giving bound parameters should work at any place in the chain. |
87 f = foo.bind(foo, 1).bind(foo).bind(foo).bind(foo); | 91 f = foo.bind(foo, 1).bind(not_foo).bind(not_foo).bind(not_foo); |
88 assertEquals(3, f(1, 1)); | 92 assertEquals([foo, 3, 1], f(2, 3)); |
89 assertEquals(2, f.length); | 93 assertEquals(2, f.length); |
90 | 94 |
91 f = foo.bind(foo).bind(foo, 1).bind(foo).bind(foo); | 95 f = foo.bind(foo).bind(not_foo, 1).bind(not_foo).bind(not_foo); |
92 assertEquals(3, f(1, 1)); | 96 assertEquals([foo, 3, 1], f(2, 3)); |
93 assertEquals(2, f.length); | 97 assertEquals(2, f.length); |
94 | 98 |
95 f = foo.bind(foo).bind(foo).bind(foo,1 ).bind(foo); | 99 f = foo.bind(foo).bind(not_foo).bind(not_foo,1 ).bind(not_foo); |
96 assertEquals(3, f(1, 1)); | 100 assertEquals([foo, 3, 1], f(2, 3)); |
97 assertEquals(2, f.length); | 101 assertEquals(2, f.length); |
98 | 102 |
99 f = foo.bind(foo).bind(foo).bind(foo).bind(foo, 1); | 103 f = foo.bind(foo).bind(not_foo).bind(not_foo).bind(not_foo, 1); |
100 assertEquals(3, f(1, 1)); | 104 assertEquals([foo, 3, 1], f(2, 3)); |
101 assertEquals(2, f.length); | 105 assertEquals(2, f.length); |
102 | 106 |
103 // Several parameters can be given, and given in different bind invokations. | 107 // Several parameters can be given, and given in different bind invokations. |
rossberg
2011/10/17 11:49:08
Typo: invocations
Lasse Reichstein
2011/10/17 12:38:39
Fixed.
| |
104 f = foo.bind(foo, 1, 1).bind(foo).bind(foo).bind(foo); | 108 f = foo.bind(foo, 1, 2).bind(not_foo).bind(not_foo).bind(not_foo); |
105 assertEquals(3, f(1)); | 109 assertEquals([foo, 3, 1], f(3)); |
106 assertEquals(1, f.length); | 110 assertEquals(1, f.length); |
107 | 111 |
108 f = foo.bind(foo).bind(foo, 1, 1).bind(foo).bind(foo); | 112 f = foo.bind(foo).bind(not_foo, 1, 2).bind(not_foo).bind(not_foo); |
109 assertEquals(3, f(1)); | 113 assertEquals([foo, 3, 1], f(1)); |
110 assertEquals(1, f.length); | 114 assertEquals(1, f.length); |
111 | 115 |
112 f = foo.bind(foo).bind(foo, 1, 1).bind(foo).bind(foo); | 116 f = foo.bind(foo).bind(not_foo, 1, 2).bind(not_foo).bind(not_foo); |
113 assertEquals(3, f(1)); | 117 assertEquals([foo, 3, 1], f(3)); |
114 assertEquals(1, f.length); | 118 assertEquals(1, f.length); |
115 | 119 |
116 f = foo.bind(foo).bind(foo).bind(foo, 1, 1).bind(foo); | 120 f = foo.bind(foo).bind(not_foo).bind(not_foo, 1, 2).bind(not_foo); |
117 assertEquals(3, f(1)); | 121 assertEquals([foo, 3, 1], f(1)); |
118 assertEquals(1, f.length); | 122 assertEquals(1, f.length); |
119 | 123 |
120 f = foo.bind(foo).bind(foo).bind(foo).bind(foo, 1, 1); | 124 f = foo.bind(foo).bind(not_foo).bind(not_foo).bind(not_foo, 1, 2); |
121 assertEquals(3, f(1)); | 125 assertEquals([foo, 3, 1], f(3)); |
122 assertEquals(1, f.length); | 126 assertEquals(1, f.length); |
123 | 127 |
124 f = foo.bind(foo, 1).bind(foo, 1).bind(foo).bind(foo); | 128 f = foo.bind(foo, 1).bind(not_foo, 2).bind(not_foo).bind(not_foo); |
125 assertEquals(3, f(1)); | 129 assertEquals([foo, 3, 1], f(3)); |
126 assertEquals(1, f.length); | 130 assertEquals(1, f.length); |
127 | 131 |
128 f = foo.bind(foo, 1).bind(foo).bind(foo, 1).bind(foo); | 132 f = foo.bind(foo, 1).bind(not_foo).bind(not_foo, 2).bind(not_foo); |
129 assertEquals(3, f(1)); | 133 assertEquals([foo, 3, 1], f(3)); |
130 assertEquals(1, f.length); | 134 assertEquals(1, f.length); |
131 | 135 |
132 f = foo.bind(foo, 1).bind(foo).bind(foo).bind(foo, 1); | 136 f = foo.bind(foo, 1).bind(not_foo).bind(not_foo).bind(not_foo, 2); |
133 assertEquals(3, f(1)); | 137 assertEquals([foo, 3, 1], f(3)); |
134 assertEquals(1, f.length); | 138 assertEquals(1, f.length); |
135 | 139 |
136 f = foo.bind(foo).bind(foo, 1).bind(foo).bind(foo, 1); | 140 f = foo.bind(foo).bind(not_foo, 1).bind(not_foo).bind(not_foo, 2); |
137 assertEquals(3, f(1)); | 141 assertEquals([foo, 3, 1], f(3)); |
138 assertEquals(1, f.length); | 142 assertEquals(1, f.length); |
139 | 143 |
144 // The wrong number of arguments can be given to bound functions too. | |
145 f = foo.bind(foo); | |
146 assertEquals(3, f.length); | |
147 assertEquals([foo, 0, undefined], f()); | |
148 assertEquals([foo, 1, 1], f(1)); | |
149 assertEquals([foo, 2, 1], f(1, 2)); | |
150 assertEquals([foo, 3, 1], f(1, 2, 3)); | |
151 assertEquals([foo, 4, 1], f(1, 2, 3, 4)); | |
152 | |
153 f = foo.bind(foo, 1); | |
154 assertEquals(2, f.length); | |
155 assertEquals([foo, 1, 1], f()); | |
156 assertEquals([foo, 2, 1], f(2)); | |
157 assertEquals([foo, 3, 1], f(2, 3)); | |
158 assertEquals([foo, 4, 1], f(2, 3, 4)); | |
159 | |
160 f = foo.bind(foo, 1, 2); | |
161 assertEquals(1, f.length); | |
162 assertEquals([foo, 2, 1], f()); | |
163 assertEquals([foo, 3, 1], f(3)); | |
164 assertEquals([foo, 4, 1], f(3, 4)); | |
165 | |
166 f = foo.bind(foo, 1, 2, 3); | |
167 assertEquals(0, f.length); | |
168 assertEquals([foo, 3, 1], f()); | |
169 assertEquals([foo, 4, 1], f(4)); | |
170 | |
171 f = foo.bind(foo, 1, 2, 3, 4); | |
172 assertEquals(0, f.length); | |
173 assertEquals([foo, 4, 1], f()); | |
174 | |
140 // Test constructor calls. | 175 // Test constructor calls. |
141 | 176 |
142 function bar(x, y, z) { | 177 function bar(x, y, z) { |
143 this.x = x; | 178 this.x = x; |
144 this.y = y; | 179 this.y = y; |
145 this.z = z; | 180 this.z = z; |
146 } | 181 } |
147 | 182 |
148 f = bar.bind(bar); | 183 f = bar.bind(bar); |
149 var obj2 = new f(1,2,3); | 184 var obj2 = new f(1,2,3); |
(...skipping 14 matching lines...) Expand all Loading... | |
164 assertEquals(3, obj2.z); | 199 assertEquals(3, obj2.z); |
165 | 200 |
166 f = bar.bind(bar, 1, 2, 3); | 201 f = bar.bind(bar, 1, 2, 3); |
167 obj2 = new f(); | 202 obj2 = new f(); |
168 assertEquals(1, obj2.x); | 203 assertEquals(1, obj2.x); |
169 assertEquals(2, obj2.y); | 204 assertEquals(2, obj2.y); |
170 assertEquals(3, obj2.z); | 205 assertEquals(3, obj2.z); |
171 | 206 |
172 | 207 |
173 // Test bind chains when used as a constructor. | 208 // Test bind chains when used as a constructor. |
174 | |
175 f = bar.bind(bar, 1).bind(bar, 2).bind(bar, 3); | 209 f = bar.bind(bar, 1).bind(bar, 2).bind(bar, 3); |
176 obj2 = new f(); | 210 obj2 = new f(); |
177 assertEquals(1, obj2.x); | 211 assertEquals(1, obj2.x); |
178 assertEquals(2, obj2.y); | 212 assertEquals(2, obj2.y); |
179 assertEquals(3, obj2.z); | 213 assertEquals(3, obj2.z); |
180 | 214 |
181 // Test instanceof obj2 is bar, not f. | 215 // Test obj2 is instanceof both bar and f. |
182 assertTrue(obj2 instanceof bar); | 216 assertTrue(obj2 instanceof bar); |
183 assertFalse(obj2 instanceof f); | 217 assertTrue(obj2 instanceof f); |
218 | |
219 // This-args are not relevant to instanceof. | |
220 f = bar.bind(foo.prototype, 1). | |
221 bind(String.prototype, 2). | |
222 bind(Function.prototype, 3); | |
223 var obj3 = new f(); | |
224 assertTrue(obj3 instanceof bar); | |
225 assertTrue(obj3 instanceof f); | |
226 assertFalse(obj3 instanceof foo); | |
227 assertFalse(obj3 instanceof Function); | |
228 assertFalse(obj3 instanceof String); | |
229 | |
230 // thisArg is converted to object. | |
231 f = foo.bind(undefined); | |
232 assertEquals([this, 0, undefined], f()); | |
233 | |
234 f = foo.bind(null); | |
235 assertEquals([this, 0, undefined], f()); | |
236 | |
237 f = foo.bind(42); | |
238 assertEquals([Object(42), 0, undefined], f()); | |
239 | |
240 f = foo.bind("foo"); | |
241 assertEquals([Object("foo"), 0, undefined], f()); | |
242 | |
243 f = foo.bind(true); | |
244 assertEquals([Object(true), 0, undefined], f()); | |
245 | |
246 // Strict functions don't convert thisArg. | |
247 function soo(x, y, z) { | |
248 "use strict"; | |
249 return [this, arguments.length, x]; | |
250 } | |
251 | |
252 var s = soo.bind(undefined); | |
253 assertEquals([undefined, 0, undefined], s()); | |
254 | |
255 s = soo.bind(null); | |
256 assertEquals([null, 0, undefined], s()); | |
257 | |
258 s = soo.bind(42); | |
259 assertEquals([42, 0, undefined], s()); | |
260 | |
261 s = soo.bind("foo"); | |
262 assertEquals(["foo", 0, undefined], s()); | |
263 | |
264 s = soo.bind(true); | |
265 assertEquals([true, 0, undefined], s()); | |
OLD | NEW |