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