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