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