blob: 83876a00c333fb6ccb76c49767e24d76d3a16e02 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005// Tests the interaction of Function.prototype.bind with proxies.
6
7
8// (Helper)
9
10var log = [];
11var logger = {};
12var handler = new Proxy({}, logger);
13
14logger.get = function(t, trap, r) {
15 return function() {
16 log.push([trap, ...arguments]);
17 return Reflect[trap](...arguments);
18 }
19};
20
21
22// Simple case
23
24var target = function(a, b, c) { "use strict"; return this };
25var proxy = new Proxy(target, handler);
26var this_value = Symbol();
27
28log.length = 0;
29result = Function.prototype.bind.call(proxy, this_value, "foo");
30assertEquals(2, result.length);
31assertEquals(target.__proto__, result.__proto__);
32assertEquals(this_value, result());
33assertEquals(5, log.length);
34for (var i in log) assertSame(target, log[i][1]);
35assertEquals(["getPrototypeOf", target], log[0]);
36assertEquals(["getOwnPropertyDescriptor", target, "length"], log[1]);
37assertEquals(["get", target, "length", proxy], log[2]);
38assertEquals(["get", target, "name", proxy], log[3]);
39assertEquals(["apply", target, this_value, ["foo"]], log[4]);
40assertEquals(new target(), new result());
41
42
43// Custom prototype
44
45log.length = 0;
46target.__proto__ = {radio: "gaga"};
47result = Function.prototype.bind.call(proxy, this_value, "foo");
48assertEquals(2, result.length);
49assertSame(target.__proto__, result.__proto__);
50assertEquals(this_value, result());
51assertEquals(5, log.length);
52for (var i in log) assertSame(target, log[i][1]);
53assertEquals(["getPrototypeOf", target], log[0]);
54assertEquals(["getOwnPropertyDescriptor", target, "length"], log[1]);
55assertEquals(["get", target, "length", proxy], log[2]);
56assertEquals(["get", target, "name", proxy], log[3]);
57assertEquals(["apply", target, this_value, ["foo"]], log[4]);
58
59
60// Custom length
61
62handler = {
63 get() {return 42},
64 getOwnPropertyDescriptor() {return {configurable: true}}
65};
66proxy = new Proxy(target, handler);
67
68result = Function.prototype.bind.call(proxy, this_value, "foo");
69assertEquals(41, result.length);
70assertEquals(this_value, result());
71
72
73// Long length
74
75handler = {
76 get() {return Math.pow(2, 100)},
77 getOwnPropertyDescriptor() {return {configurable: true}}
78};
79proxy = new Proxy(target, handler);
80
81result = Function.prototype.bind.call(proxy, this_value, "foo");
82assertEquals(Math.pow(2, 100) - 1, result.length);
83assertEquals(this_value, result());
84
85
86// Very long length
87
88handler = {
89 get() {return 1/0},
90 getOwnPropertyDescriptor() {return {configurable: true}}
91};
92proxy = new Proxy(target, handler);
93
94result = Function.prototype.bind.call(proxy, this_value, "foo");
95assertEquals(1/0, result.length);
96assertEquals(this_value, result());
97
98
99// Non-integer length
100
101handler = {
102 get() {return 4.2},
103 getOwnPropertyDescriptor() {return {configurable: true}}
104};
105proxy = new Proxy(target, handler);
106
107result = Function.prototype.bind.call(proxy, this_value, "foo");
108assertEquals(3, result.length);
109assertEquals(this_value, result());
110
111
112// Undefined length
113
114handler = {
115 get() {},
116 getOwnPropertyDescriptor() {return {configurable: true}}
117};
118proxy = new Proxy(target, handler);
119
120result = Function.prototype.bind.call(proxy, this_value, "foo");
121assertEquals(0, result.length);
122assertEquals(this_value, result());
123
124
125// Non-callable
126
127assertThrows(() => Function.prototype.bind.call(new Proxy({}, {})), TypeError);
128assertThrows(() => Function.prototype.bind.call(new Proxy([], {})), TypeError);
129
130
131// Non-constructable
132
133result = Function.prototype.bind.call(() => 42, this_value, "foo");
134assertEquals(42, result());
135assertThrows(() => new result());