proxies-function.js revision 3ef787dbeca8a5fb1086949cda830dccee07bfbd
1// Copyright 2011 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// Flags: --harmony-proxies --allow-natives-syntax
29
30
31// Helper.
32
33function CreateFrozen(handler, callTrap, constructTrap) {
34  if (handler.fix === undefined) handler.fix = function() { return {} }
35  var f = Proxy.createFunction(handler, callTrap, constructTrap)
36  Object.freeze(f)
37  return f
38}
39
40
41// Ensures that checking the "length" property of a function proxy doesn't
42// crash due to lack of a [[Get]] method.
43var handler = {
44  get : function(r, n) { return n == "length" ? 2 : undefined }
45}
46
47
48// Calling (call, Function.prototype.call, Function.prototype.apply,
49//          Function.prototype.bind).
50
51var global_object = this
52var receiver
53
54function TestCall(isStrict, callTrap) {
55  assertEquals(42, callTrap(5, 37))
56  // TODO(rossberg): strict mode seems to be broken on x64...
57  // assertSame(isStrict ? undefined : global_object, receiver)
58
59  var handler = {
60    get: function(r, k) {
61      return k == "length" ? 2 : Function.prototype[k]
62    }
63  }
64  var f = Proxy.createFunction(handler, callTrap)
65  var o = {f: f}
66  global_object.f = f
67
68  receiver = 333
69  assertEquals(42, f(11, 31))
70  // TODO(rossberg): strict mode seems to be broken on x64...
71  // assertSame(isStrict ? undefined : global_object, receiver)
72  receiver = 333
73  assertEquals(42, o.f(10, 32))
74  assertSame(o, receiver)
75  receiver = 333
76  assertEquals(42, o["f"](9, 33))
77  assertSame(o, receiver)
78  receiver = 333
79  assertEquals(42, (1, o).f(8, 34))
80  assertSame(o, receiver)
81  receiver = 333
82  assertEquals(42, (1, o)["f"](7, 35))
83  assertSame(o, receiver)
84  receiver = 333
85  assertEquals(42, f.call(o, 32, 10))
86  assertSame(o, receiver)
87  receiver = 333
88  assertEquals(42, f.call(undefined, 33, 9))
89  assertSame(isStrict ? undefined : global_object, receiver)
90  receiver = 333
91  assertEquals(42, f.call(null, 33, 9))
92  assertSame(isStrict ? null : global_object, receiver)
93  receiver = 333
94  assertEquals(44, f.call(2, 21, 23))
95  assertSame(2, receiver.valueOf())
96  receiver = 333
97  assertEquals(42, Function.prototype.call.call(f, o, 20, 22))
98  assertSame(o, receiver)
99  receiver = 333
100  assertEquals(43, Function.prototype.call.call(f, null, 20, 23))
101  assertSame(isStrict ? null : global_object, receiver)
102  assertEquals(44, Function.prototype.call.call(f, 2, 21, 23))
103  assertEquals(2, receiver.valueOf())
104  receiver = 333
105  assertEquals(32, f.apply(o, [16, 16]))
106  assertSame(o, receiver)
107  receiver = 333
108  assertEquals(32, Function.prototype.apply.call(f, o, [17, 15]))
109  assertSame(o, receiver)
110  receiver = 333
111  assertEquals(42, %Call(o, 11, 31, f))
112  assertSame(o, receiver)
113  receiver = 333
114  assertEquals(42, %Call(null, 11, 31, f))
115  assertSame(isStrict ? null : global_object, receiver)
116  receiver = 333
117  assertEquals(42, %Apply(f, o, [11, 31], 0, 2))
118  assertSame(o, receiver)
119  receiver = 333
120  assertEquals(42, %Apply(f, null, [11, 31], 0, 2))
121  assertSame(isStrict ? null : global_object, receiver)
122  receiver = 333
123  assertEquals(42, %_CallFunction(o, 11, 31, f))
124  assertSame(o, receiver)
125  receiver = 333
126  assertEquals(42, %_CallFunction(null, 11, 31, f))
127  assertSame(isStrict ? null : global_object, receiver)
128
129  var ff = Function.prototype.bind.call(f, o, 12)
130  assertTrue(ff.length <= 1)  // TODO(rossberg): Not spec'ed yet, be lax.
131  receiver = 333
132  assertEquals(42, ff(30))
133  assertSame(o, receiver)
134  receiver = 333
135  assertEquals(33, Function.prototype.call.call(ff, {}, 21))
136  assertSame(o, receiver)
137  receiver = 333
138  assertEquals(32, Function.prototype.apply.call(ff, {}, [20]))
139  assertSame(o, receiver)
140  receiver = 333
141  assertEquals(23, %Call({}, 11, ff))
142  assertSame(o, receiver)
143  receiver = 333
144  assertEquals(23, %Call({}, 11, 3, ff))
145  assertSame(o, receiver)
146  receiver = 333
147  assertEquals(24, %Apply(ff, {}, [12, 13], 0, 1))
148  assertSame(o, receiver)
149  receiver = 333
150  assertEquals(24, %Apply(ff, {}, [12, 13], 0, 2))
151  assertSame(o, receiver)
152  receiver = 333
153  assertEquals(34, %_CallFunction({}, 22, ff))
154  assertSame(o, receiver)
155  receiver = 333
156  assertEquals(34, %_CallFunction({}, 22, 3, ff))
157  assertSame(o, receiver)
158
159  var fff = Function.prototype.bind.call(ff, o, 30)
160  assertEquals(0, fff.length)
161  receiver = 333
162  assertEquals(42, fff())
163  assertSame(o, receiver)
164  receiver = 333
165  assertEquals(42, Function.prototype.call.call(fff, {}))
166  assertSame(o, receiver)
167  receiver = 333
168  assertEquals(42, Function.prototype.apply.call(fff, {}))
169  assertSame(o, receiver)
170  receiver = 333
171  assertEquals(42, %Call({}, fff))
172  assertSame(o, receiver)
173  receiver = 333
174  assertEquals(42, %Call({}, 11, 3, fff))
175  assertSame(o, receiver)
176  receiver = 333
177  assertEquals(42, %Apply(fff, {}, [], 0, 0))
178  assertSame(o, receiver)
179  receiver = 333
180  assertEquals(42, %Apply(fff, {}, [12, 13], 0, 0))
181  assertSame(o, receiver)
182  receiver = 333
183  assertEquals(42, %Apply(fff, {}, [12, 13], 0, 2))
184  assertSame(o, receiver)
185  receiver = 333
186  assertEquals(42, %_CallFunction({}, fff))
187  assertSame(o, receiver)
188  receiver = 333
189  assertEquals(42, %_CallFunction({}, 3, 4, 5, fff))
190  assertSame(o, receiver)
191
192  var f = CreateFrozen({}, callTrap)
193  receiver = 333
194  assertEquals(42, f(11, 31))
195  assertSame(isStrict ? undefined : global_object, receiver)
196  var o = {f: f}
197  receiver = 333
198  assertEquals(42, o.f(10, 32))
199  assertSame(o, receiver)
200  receiver = 333
201  assertEquals(42, o["f"](9, 33))
202  assertSame(o, receiver)
203  receiver = 333
204  assertEquals(42, (1, o).f(8, 34))
205  assertSame(o, receiver)
206  receiver = 333
207  assertEquals(42, (1, o)["f"](7, 35))
208  assertSame(o, receiver)
209  receiver = 333
210  assertEquals(42, Function.prototype.call.call(f, o, 20, 22))
211  assertSame(o, receiver)
212  receiver = 333
213  assertEquals(32, Function.prototype.apply.call(f, o, [17, 15]))
214  assertSame(o, receiver)
215  receiver = 333
216  assertEquals(23, %Call(o, 11, 12, f))
217  assertSame(o, receiver)
218  receiver = 333
219  assertEquals(27, %Apply(f, o, [12, 13, 14], 1, 2))
220  assertSame(o, receiver)
221  receiver = 333
222  assertEquals(42, %_CallFunction(o, 18, 24, f))
223  assertSame(o, receiver)
224}
225
226TestCall(false, function(x, y) {
227  receiver = this
228  return x + y
229})
230
231TestCall(true, function(x, y) {
232  "use strict"
233  receiver = this
234  return x + y
235})
236
237TestCall(false, function() {
238  receiver = this
239  return arguments[0] + arguments[1]
240})
241
242TestCall(false, Proxy.createFunction(handler, function(x, y) {
243  receiver = this
244  return x + y
245}))
246
247TestCall(true, Proxy.createFunction(handler, function(x, y) {
248  "use strict"
249  receiver = this
250  return x + y
251}))
252
253TestCall(false, CreateFrozen(handler, function(x, y) {
254  receiver = this
255  return x + y
256}))
257
258
259
260// Using intrinsics as call traps.
261
262function TestCallIntrinsic(type, callTrap) {
263  var f = Proxy.createFunction({}, callTrap)
264  var x = f()
265  assertTrue(typeof x == type)
266}
267
268TestCallIntrinsic("boolean", Boolean)
269TestCallIntrinsic("number", Number)
270TestCallIntrinsic("string", String)
271TestCallIntrinsic("object", Object)
272TestCallIntrinsic("function", Function)
273
274
275
276// Throwing from call trap.
277
278function TestCallThrow(callTrap) {
279  var f = Proxy.createFunction({}, callTrap)
280  assertThrows(function(){ f(11) }, "myexn")
281  assertThrows(function(){ ({x: f}).x(11) }, "myexn")
282  assertThrows(function(){ ({x: f})["x"](11) }, "myexn")
283  assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn")
284  assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn")
285  assertThrows(function(){ %Call({}, f) }, "myexn")
286  assertThrows(function(){ %Call({}, 1, 2, f) }, "myexn")
287  assertThrows(function(){ %Apply({}, f, [], 3, 0) }, "myexn")
288  assertThrows(function(){ %Apply({}, f, [3, 4], 0, 1) }, "myexn")
289  assertThrows(function(){ %_CallFunction({}, f) }, "myexn")
290  assertThrows(function(){ %_CallFunction({}, 1, 2, f) }, "myexn")
291
292  var f = CreateFrozen({}, callTrap)
293  assertThrows(function(){ f(11) }, "myexn")
294  assertThrows(function(){ ({x: f}).x(11) }, "myexn")
295  assertThrows(function(){ ({x: f})["x"](11) }, "myexn")
296  assertThrows(function(){ Function.prototype.call.call(f, {}, 2) }, "myexn")
297  assertThrows(function(){ Function.prototype.apply.call(f, {}, [1]) }, "myexn")
298  assertThrows(function(){ %Call({}, f) }, "myexn")
299  assertThrows(function(){ %Call({}, 1, 2, f) }, "myexn")
300  assertThrows(function(){ %Apply({}, f, [], 3, 0) }, "myexn")
301  assertThrows(function(){ %Apply({}, f, [3, 4], 0, 1) }, "myexn")
302  assertThrows(function(){ %_CallFunction({}, f) }, "myexn")
303  assertThrows(function(){ %_CallFunction({}, 1, 2, f) }, "myexn")
304}
305
306TestCallThrow(function() { throw "myexn" })
307TestCallThrow(Proxy.createFunction({}, function() { throw "myexn" }))
308TestCallThrow(CreateFrozen({}, function() { throw "myexn" }))
309
310
311
312// Construction (new).
313
314var prototype = {myprop: 0}
315var receiver
316
317var handlerWithPrototype = {
318  fix: function() { return { prototype: { value: prototype } }; },
319  get: function(r, n) {
320    if (n == "length") return 2;
321    assertEquals("prototype", n);
322    return prototype;
323  }
324}
325
326var handlerSansPrototype = {
327  fix: function() { return { length: { value: 2 } } },
328  get: function(r, n) {
329    if (n == "length") return 2;
330    assertEquals("prototype", n);
331    return undefined;
332  }
333}
334
335function ReturnUndef(x, y) {
336  "use strict";
337  receiver = this;
338  this.sum = x + y;
339}
340
341function ReturnThis(x, y) {
342  "use strict";
343  receiver = this;
344  this.sum = x + y;
345  return this;
346}
347
348function ReturnNew(x, y) {
349  "use strict";
350  receiver = this;
351  return {sum: x + y};
352}
353
354function ReturnNewWithProto(x, y) {
355  "use strict";
356  receiver = this;
357  var result = Object.create(prototype);
358  result.sum = x + y;
359  return result;
360}
361
362function TestConstruct(proto, constructTrap) {
363  TestConstruct2(proto, constructTrap, handlerWithPrototype)
364  TestConstruct2(proto, constructTrap, handlerSansPrototype)
365}
366
367function TestConstruct2(proto, constructTrap, handler) {
368  var f = Proxy.createFunction(handler, function() {}, constructTrap)
369  var o = new f(11, 31)
370  assertEquals(undefined, receiver)
371  assertEquals(42, o.sum)
372  assertSame(proto, Object.getPrototypeOf(o))
373
374  var f = CreateFrozen(handler, function() {}, constructTrap)
375  var o = new f(11, 32)
376  assertEquals(undefined, receiver)
377  assertEquals(43, o.sum)
378  assertSame(proto, Object.getPrototypeOf(o))
379}
380
381TestConstruct(Object.prototype, ReturnNew)
382TestConstruct(prototype, ReturnNewWithProto)
383
384TestConstruct(Object.prototype, Proxy.createFunction(handler, ReturnNew))
385TestConstruct(prototype, Proxy.createFunction(handler, ReturnNewWithProto))
386
387TestConstruct(Object.prototype, CreateFrozen(handler, ReturnNew))
388TestConstruct(prototype, CreateFrozen(handler, ReturnNewWithProto))
389
390
391
392// Construction with derived construct trap.
393
394function TestConstructFromCall(proto, returnsThis, callTrap) {
395  TestConstructFromCall2(prototype, returnsThis, callTrap, handlerWithPrototype)
396  TestConstructFromCall2(proto, returnsThis, callTrap, handlerSansPrototype)
397}
398
399function TestConstructFromCall2(proto, returnsThis, callTrap, handler) {
400  // TODO(rossberg): handling of prototype for derived construct trap will be
401  // fixed in a separate change. Commenting out checks below for now.
402  var f = Proxy.createFunction(handler, callTrap)
403  var o = new f(11, 31)
404  if (returnsThis) assertEquals(o, receiver)
405  assertEquals(42, o.sum)
406  // assertSame(proto, Object.getPrototypeOf(o))
407
408  var g = CreateFrozen(handler, callTrap)
409  // assertSame(f.prototype, g.prototype)
410  var o = new g(11, 32)
411  if (returnsThis) assertEquals(o, receiver)
412  assertEquals(43, o.sum)
413  // assertSame(proto, Object.getPrototypeOf(o))
414}
415
416TestConstructFromCall(Object.prototype, true, ReturnUndef)
417TestConstructFromCall(Object.prototype, true, ReturnThis)
418TestConstructFromCall(Object.prototype, false, ReturnNew)
419TestConstructFromCall(prototype, false, ReturnNewWithProto)
420
421TestConstructFromCall(Object.prototype, true,
422                      Proxy.createFunction(handler, ReturnUndef))
423TestConstructFromCall(Object.prototype, true,
424                      Proxy.createFunction(handler, ReturnThis))
425TestConstructFromCall(Object.prototype, false,
426                      Proxy.createFunction(handler, ReturnNew))
427TestConstructFromCall(prototype, false,
428                      Proxy.createFunction(handler, ReturnNewWithProto))
429
430TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnUndef))
431TestConstructFromCall(Object.prototype, true, CreateFrozen({}, ReturnThis))
432TestConstructFromCall(Object.prototype, false, CreateFrozen({}, ReturnNew))
433TestConstructFromCall(prototype, false, CreateFrozen({}, ReturnNewWithProto))
434
435ReturnUndef.prototype = prototype
436ReturnThis.prototype = prototype
437ReturnNew.prototype = prototype
438ReturnNewWithProto.prototype = prototype
439
440TestConstructFromCall(prototype, true, ReturnUndef)
441TestConstructFromCall(prototype, true, ReturnThis)
442TestConstructFromCall(Object.prototype, false, ReturnNew)
443TestConstructFromCall(prototype, false, ReturnNewWithProto)
444
445TestConstructFromCall(Object.prototype, true,
446                      Proxy.createFunction(handler, ReturnUndef))
447TestConstructFromCall(Object.prototype, true,
448                      Proxy.createFunction(handler, ReturnThis))
449TestConstructFromCall(Object.prototype, false,
450                      Proxy.createFunction(handler, ReturnNew))
451TestConstructFromCall(prototype, false,
452                      Proxy.createFunction(handler, ReturnNewWithProto))
453
454TestConstructFromCall(prototype, true,
455                      Proxy.createFunction(handlerWithPrototype, ReturnUndef))
456TestConstructFromCall(prototype, true,
457                      Proxy.createFunction(handlerWithPrototype, ReturnThis))
458TestConstructFromCall(Object.prototype, false,
459                      Proxy.createFunction(handlerWithPrototype, ReturnNew))
460TestConstructFromCall(prototype, false,
461                      Proxy.createFunction(handlerWithPrototype,
462                                           ReturnNewWithProto))
463
464TestConstructFromCall(prototype, true,
465                      CreateFrozen(handlerWithPrototype, ReturnUndef))
466TestConstructFromCall(prototype, true,
467                      CreateFrozen(handlerWithPrototype, ReturnThis))
468TestConstructFromCall(Object.prototype, false,
469                      CreateFrozen(handlerWithPrototype, ReturnNew))
470TestConstructFromCall(prototype, false,
471                      CreateFrozen(handlerWithPrototype, ReturnNewWithProto))
472
473
474
475// Throwing from the construct trap.
476
477function TestConstructThrow(trap) {
478  TestConstructThrow2(Proxy.createFunction({ fix: function() {return {};} },
479                                           trap))
480  TestConstructThrow2(Proxy.createFunction({ fix: function() {return {};} },
481                                           function() {},
482                                           trap))
483}
484
485function TestConstructThrow2(f) {
486  assertThrows(function(){ new f(11) }, "myexn")
487  Object.freeze(f)
488  assertThrows(function(){ new f(11) }, "myexn")
489}
490
491TestConstructThrow(function() { throw "myexn" })
492TestConstructThrow(Proxy.createFunction({}, function() { throw "myexn" }))
493TestConstructThrow(CreateFrozen({}, function() { throw "myexn" }))
494
495
496
497// Using function proxies as getters and setters.
498
499var value
500var receiver
501
502function TestAccessorCall(getterCallTrap, setterCallTrap) {
503  var handler = { fix: function() { return {} } }
504  var pgetter = Proxy.createFunction(handler, getterCallTrap)
505  var psetter = Proxy.createFunction(handler, setterCallTrap)
506
507  var o = {}
508  var oo = Object.create(o)
509  Object.defineProperty(o, "a", {get: pgetter, set: psetter})
510  Object.defineProperty(o, "b", {get: pgetter})
511  Object.defineProperty(o, "c", {set: psetter})
512  Object.defineProperty(o, "3", {get: pgetter, set: psetter})
513  Object.defineProperty(oo, "a", {value: 43})
514
515  receiver = ""
516  assertEquals(42, o.a)
517  assertSame(o, receiver)
518  receiver = ""
519  assertEquals(42, o.b)
520  assertSame(o, receiver)
521  receiver = ""
522  assertEquals(undefined, o.c)
523  assertEquals("", receiver)
524  receiver = ""
525  assertEquals(42, o["a"])
526  assertSame(o, receiver)
527  receiver = ""
528  assertEquals(42, o[3])
529  assertSame(o, receiver)
530
531  receiver = ""
532  assertEquals(43, oo.a)
533  assertEquals("", receiver)
534  receiver = ""
535  assertEquals(42, oo.b)
536  assertSame(oo, receiver)
537  receiver = ""
538  assertEquals(undefined, oo.c)
539  assertEquals("", receiver)
540  receiver = ""
541  assertEquals(43, oo["a"])
542  assertEquals("", receiver)
543  receiver = ""
544  assertEquals(42, oo[3])
545  assertSame(oo, receiver)
546
547  receiver = ""
548  assertEquals(50, o.a = 50)
549  assertSame(o, receiver)
550  assertEquals(50, value)
551  receiver = ""
552  assertEquals(51, o.b = 51)
553  assertEquals("", receiver)
554  assertEquals(50, value)  // no setter
555  assertThrows(function() { "use strict"; o.b = 51 }, TypeError)
556  receiver = ""
557  assertEquals(52, o.c = 52)
558  assertSame(o, receiver)
559  assertEquals(52, value)
560  receiver = ""
561  assertEquals(53, o["a"] = 53)
562  assertSame(o, receiver)
563  assertEquals(53, value)
564  receiver = ""
565  assertEquals(54, o[3] = 54)
566  assertSame(o, receiver)
567  assertEquals(54, value)
568
569  value = 0
570  receiver = ""
571  assertEquals(60, oo.a = 60)
572  assertEquals("", receiver)
573  assertEquals(0, value)  // oo has own 'a'
574  assertEquals(61, oo.b = 61)
575  assertSame("", receiver)
576  assertEquals(0, value)  // no setter
577  assertThrows(function() { "use strict"; oo.b = 61 }, TypeError)
578  receiver = ""
579  assertEquals(62, oo.c = 62)
580  assertSame(oo, receiver)
581  assertEquals(62, value)
582  receiver = ""
583  assertEquals(63, oo["c"] = 63)
584  assertSame(oo, receiver)
585  assertEquals(63, value)
586  receiver = ""
587  assertEquals(64, oo[3] = 64)
588  assertSame(oo, receiver)
589  assertEquals(64, value)
590}
591
592TestAccessorCall(
593  function() { receiver = this; return 42 },
594  function(x) { receiver = this; value = x }
595)
596
597TestAccessorCall(
598  function() { "use strict"; receiver = this; return 42 },
599  function(x) { "use strict"; receiver = this; value = x }
600)
601
602TestAccessorCall(
603  Proxy.createFunction({}, function() { receiver = this; return 42 }),
604  Proxy.createFunction({}, function(x) { receiver = this; value = x })
605)
606
607TestAccessorCall(
608  CreateFrozen({}, function() { receiver = this; return 42 }),
609  CreateFrozen({}, function(x) { receiver = this; value = x })
610)
611
612
613
614// Passing a proxy function to higher-order library functions.
615
616function TestHigherOrder(f) {
617  assertEquals(6, [6, 2].map(f)[0])
618  assertEquals(4, [5, 2].reduce(f, 4))
619  assertTrue([1, 2].some(f))
620  assertEquals("a.b.c", "a.b.c".replace(".", f))
621}
622
623TestHigherOrder(function(x) { return x })
624TestHigherOrder(function(x) { "use strict"; return x })
625TestHigherOrder(Proxy.createFunction({}, function(x) { return x }))
626TestHigherOrder(CreateFrozen({}, function(x) { return x }))
627
628
629
630// TODO(rossberg): Ultimately, I want to have the following test function
631// run through, but it currently fails on so many cases (some not even
632// involving proxies), that I leave that for later...
633/*
634function TestCalls() {
635  var handler = {
636    get: function(r, k) {
637      return k == "length" ? 2 : Function.prototype[k]
638    }
639  }
640  var bind = Function.prototype.bind
641  var o = {}
642
643  var traps = [
644    function(x, y) {
645      return {receiver: this, result: x + y, strict: false}
646    },
647    function(x, y) { "use strict";
648      return {receiver: this, result: x + y, strict: true}
649    },
650    function() {
651      var x = arguments[0], y = arguments[1]
652      return {receiver: this, result: x + y, strict: false}
653    },
654    Proxy.createFunction(handler, function(x, y) {
655      return {receiver: this, result: x + y, strict: false}
656    }),
657    Proxy.createFunction(handler, function() {
658      var x = arguments[0], y = arguments[1]
659      return {receiver: this, result: x + y, strict: false}
660    }),
661    Proxy.createFunction(handler, function(x, y) { "use strict"
662      return {receiver: this, result: x + y, strict: true}
663    }),
664    CreateFrozen(handler, function(x, y) {
665      return {receiver: this, result: x + y, strict: false}
666    }),
667    CreateFrozen(handler, function(x, y) { "use strict"
668      return {receiver: this, result: x + y, strict: true}
669    }),
670  ]
671  var creates = [
672    function(trap) { return trap },
673    function(trap) { return CreateFrozen({}, callTrap) },
674    function(trap) { return Proxy.createFunction(handler, callTrap) },
675    function(trap) {
676      return Proxy.createFunction(handler, CreateFrozen({}, callTrap))
677    },
678    function(trap) {
679      return Proxy.createFunction(handler, Proxy.createFunction(handler, callTrap))
680    },
681  ]
682  var binds = [
683    function(f, o, x, y) { return f },
684    function(f, o, x, y) { return bind.call(f, o) },
685    function(f, o, x, y) { return bind.call(f, o, x) },
686    function(f, o, x, y) { return bind.call(f, o, x, y) },
687    function(f, o, x, y) { return bind.call(f, o, x, y, 5) },
688    function(f, o, x, y) { return bind.call(bind.call(f, o), {}, x, y) },
689    function(f, o, x, y) { return bind.call(bind.call(f, o, x), {}, y) },
690    function(f, o, x, y) { return bind.call(bind.call(f, o, x, y), {}, 5) },
691  ]
692  var calls = [
693    function(f, x, y) { return f(x, y) },
694    function(f, x, y) { var g = f; return g(x, y) },
695    function(f, x, y) { with ({}) return f(x, y) },
696    function(f, x, y) { var g = f; with ({}) return g(x, y) },
697    function(f, x, y, o) { with (o) return f(x, y) },
698    function(f, x, y, o) { return f.call(o, x, y) },
699    function(f, x, y, o) { return f.apply(o, [x, y]) },
700    function(f, x, y, o) { return Function.prototype.call.call(f, o, x, y) },
701    function(f, x, y, o) { return Function.prototype.apply.call(f, o, [x, y]) },
702    function(f, x, y, o) { return %_CallFunction(o, x, y, f) },
703    function(f, x, y, o) { return %Call(o, x, y, f) },
704    function(f, x, y, o) { return %Apply(f, o, [null, x, y, null], 1, 2) },
705    function(f, x, y, o) { return %Apply(f, o, arguments, 2, 2) },
706    function(f, x, y, o) { if (typeof o == "object") return o.f(x, y) },
707    function(f, x, y, o) { if (typeof o == "object") return o["f"](x, y) },
708    function(f, x, y, o) { if (typeof o == "object") return (1, o).f(x, y) },
709    function(f, x, y, o) { if (typeof o == "object") return (1, o)["f"](x, y) },
710  ]
711  var receivers = [o, global_object, undefined, null, 2, "bla", true]
712  var expectedNonStricts = [o, global_object, global_object, global_object]
713
714  for (var t = 0; t < traps.length; ++t) {
715    for (var i = 0; i < creates.length; ++i) {
716      for (var j = 0; j < binds.length; ++j) {
717        for (var k = 0; k < calls.length; ++k) {
718          for (var m = 0; m < receivers.length; ++m) {
719            for (var n = 0; n < receivers.length; ++n) {
720              var bound = receivers[m]
721              var receiver = receivers[n]
722              var func = binds[j](creates[i](traps[t]), bound, 31, 11)
723              var expected = j > 0 ? bound : receiver
724              var expectedNonStrict = expectedNonStricts[j > 0 ? m : n]
725              o.f = func
726              global_object.f = func
727              var x = calls[k](func, 11, 31, receiver)
728              if (x !== undefined) {
729                assertEquals(42, x.result)
730                if (calls[k].length < 4)
731                  assertSame(x.strict ? undefined : global_object, x.receiver)
732                else if (x.strict)
733                  assertSame(expected, x.receiver)
734                else if (expectedNonStrict === undefined)
735                  assertSame(expected, x.receiver.valueOf())
736                else
737                  assertSame(expectedNonStrict, x.receiver)
738              }
739            }
740          }
741        }
742      }
743    }
744  }
745}
746
747TestCalls()
748*/
749