js/src/tests/ecma_5/Function/function-bind.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/tests/ecma_5/Function/function-bind.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,282 @@
     1.4 +/*
     1.5 + * Any copyright is dedicated to the Public Domain.
     1.6 + * http://creativecommons.org/licenses/publicdomain/
     1.7 + */
     1.8 +
     1.9 +var gTestfile = 'function-bind.js';
    1.10 +var BUGNUMBER = 429507;
    1.11 +var summary = "ES5: Function.prototype.bind";
    1.12 +
    1.13 +print(BUGNUMBER + ": " + summary);
    1.14 +
    1.15 +/**************
    1.16 + * BEGIN TEST *
    1.17 + **************/
    1.18 +
    1.19 +// ad-hoc testing
    1.20 +
    1.21 +assertEq(Function.prototype.hasOwnProperty("bind"), true);
    1.22 +
    1.23 +var bind = Function.prototype.bind;
    1.24 +assertEq(bind.length, 1);
    1.25 +
    1.26 +
    1.27 +var strictReturnThis = function() { "use strict"; return this; };
    1.28 +
    1.29 +assertEq(strictReturnThis.bind(undefined)(), undefined);
    1.30 +assertEq(strictReturnThis.bind(null)(), null);
    1.31 +
    1.32 +var obj = {};
    1.33 +assertEq(strictReturnThis.bind(obj)(), obj);
    1.34 +
    1.35 +assertEq(strictReturnThis.bind(NaN)(), NaN);
    1.36 +
    1.37 +assertEq(strictReturnThis.bind(true)(), true);
    1.38 +assertEq(strictReturnThis.bind(false)(), false);
    1.39 +
    1.40 +assertEq(strictReturnThis.bind("foopy")(), "foopy");
    1.41 +
    1.42 +
    1.43 +// rigorous, step-by-step testing
    1.44 +
    1.45 +function expectThrowTypeError(fun)
    1.46 +{
    1.47 +  try
    1.48 +  {
    1.49 +    var r = fun();
    1.50 +    throw new Error("didn't throw TypeError, returned " + r);
    1.51 +  }
    1.52 +  catch (e)
    1.53 +  {
    1.54 +    assertEq(e instanceof TypeError, true,
    1.55 +             "didn't throw TypeError, got: " + e);
    1.56 +  }
    1.57 +}
    1.58 +
    1.59 +/*
    1.60 + * 1. Let Target be the this value.
    1.61 + * 2. If IsCallable(Target) is false, throw a TypeError exception.
    1.62 + */
    1.63 +expectThrowTypeError(function() { bind.call(null); });
    1.64 +expectThrowTypeError(function() { bind.call(undefined); });
    1.65 +expectThrowTypeError(function() { bind.call(NaN); });
    1.66 +expectThrowTypeError(function() { bind.call(0); });
    1.67 +expectThrowTypeError(function() { bind.call(-0); });
    1.68 +expectThrowTypeError(function() { bind.call(17); });
    1.69 +expectThrowTypeError(function() { bind.call(42); });
    1.70 +expectThrowTypeError(function() { bind.call("foobar"); });
    1.71 +expectThrowTypeError(function() { bind.call(true); });
    1.72 +expectThrowTypeError(function() { bind.call(false); });
    1.73 +expectThrowTypeError(function() { bind.call([]); });
    1.74 +expectThrowTypeError(function() { bind.call({}); });
    1.75 +
    1.76 +
    1.77 +/*
    1.78 + * 3. Let A be a new (possibly empty) internal list of all of the argument
    1.79 + *    values provided after thisArg (arg1, arg2 etc), in order.
    1.80 + * 4. Let F be a new native ECMAScript object .
    1.81 + * 5. Set all the internal methods, except for [[Get]], of F as specified in
    1.82 + *    8.12.
    1.83 + * 6. Set the [[Get]] internal property of F as specified in 15.3.5.4.
    1.84 + * 7. Set the [[TargetFunction]] internal property of F to Target.
    1.85 + * 8. Set the [[BoundThis]] internal property of F to the value of thisArg.
    1.86 + * 9. Set the [[BoundArgs]] internal property of F to A.
    1.87 + */
    1.88 +// throughout
    1.89 +
    1.90 +
    1.91 +/* 10. Set the [[Class]] internal property of F to "Function". */
    1.92 +var toString = Object.prototype.toString;
    1.93 +assertEq(toString.call(function(){}), "[object Function]");
    1.94 +assertEq(toString.call(function a(){}), "[object Function]");
    1.95 +assertEq(toString.call(function(a){}), "[object Function]");
    1.96 +assertEq(toString.call(function a(b){}), "[object Function]");
    1.97 +assertEq(toString.call(function(){}.bind()), "[object Function]");
    1.98 +assertEq(toString.call(function a(){}.bind()), "[object Function]");
    1.99 +assertEq(toString.call(function(a){}.bind()), "[object Function]");
   1.100 +assertEq(toString.call(function a(b){}.bind()), "[object Function]");
   1.101 +
   1.102 +
   1.103 +/*
   1.104 + * 11. Set the [[Prototype]] internal property of F to the standard built-in
   1.105 + *     Function prototype object as specified in 15.3.3.1.
   1.106 + */
   1.107 +assertEq(Object.getPrototypeOf(bind.call(function(){})), Function.prototype);
   1.108 +assertEq(Object.getPrototypeOf(bind.call(function a(){})), Function.prototype);
   1.109 +assertEq(Object.getPrototypeOf(bind.call(function(a){})), Function.prototype);
   1.110 +assertEq(Object.getPrototypeOf(bind.call(function a(b){})), Function.prototype);
   1.111 +
   1.112 +
   1.113 +/*
   1.114 + * 12. Set the [[Call]] internal property of F as described in 15.3.4.5.1.
   1.115 + */
   1.116 +var a = Array.bind(1, 2);
   1.117 +assertEq(a().length, 2);
   1.118 +assertEq(a(4).length, 2);
   1.119 +assertEq(a(4, 8).length, 3);
   1.120 +
   1.121 +function t() { return this; }
   1.122 +var bt = t.bind(t);
   1.123 +assertEq(bt(), t);
   1.124 +
   1.125 +function callee() { return arguments.callee; }
   1.126 +var call = callee.bind();
   1.127 +assertEq(call(), callee);
   1.128 +assertEq(new call(), callee);
   1.129 +
   1.130 +
   1.131 +/*
   1.132 + * 13. Set the [[Construct]] internal property of F as described in 15.3.4.5.2.
   1.133 + */
   1.134 +function Point(x, y)
   1.135 +{
   1.136 +  this.x = x;
   1.137 +  this.y = y;
   1.138 +}
   1.139 +var YAxisPoint = Point.bind(null, 0)
   1.140 +
   1.141 +assertEq(YAxisPoint.hasOwnProperty("prototype"), false);
   1.142 +var p = new YAxisPoint(5);
   1.143 +assertEq(p.x, 0);
   1.144 +assertEq(p.y, 5);
   1.145 +assertEq(p instanceof Point, true);
   1.146 +assertEq(p instanceof YAxisPoint, true);
   1.147 +assertEq(Object.prototype.toString.call(YAxisPoint), "[object Function]");
   1.148 +assertEq(YAxisPoint.length, 1);
   1.149 +
   1.150 +
   1.151 +/*
   1.152 + * 14. Set the [[HasInstance]] internal property of F as described in
   1.153 + *     15.3.4.5.3.
   1.154 + */
   1.155 +function JoinArguments()
   1.156 +{
   1.157 +  this.args = Array.prototype.join.call(arguments, ", ");
   1.158 +}
   1.159 +
   1.160 +var Join1 = JoinArguments.bind(null, 1);
   1.161 +var Join2 = Join1.bind(null, 2);
   1.162 +var Join3 = Join2.bind(null, 3);
   1.163 +var Join4 = Join3.bind(null, 4);
   1.164 +var Join5 = Join4.bind(null, 5);
   1.165 +var Join6 = Join5.bind(null, 6);
   1.166 +
   1.167 +var r = new Join6(7);
   1.168 +assertEq(r instanceof Join6, true);
   1.169 +assertEq(r instanceof Join5, true);
   1.170 +assertEq(r instanceof Join4, true);
   1.171 +assertEq(r instanceof Join3, true);
   1.172 +assertEq(r instanceof Join2, true);
   1.173 +assertEq(r instanceof Join1, true);
   1.174 +assertEq(r instanceof JoinArguments, true);
   1.175 +assertEq(r.args, "1, 2, 3, 4, 5, 6, 7");
   1.176 +
   1.177 +
   1.178 +/*
   1.179 + * 15. If the [[Class]] internal property of Target is "Function", then
   1.180 + *   a. Let L be the length property of Target minus the length of A.
   1.181 + *   b. Set the length own property of F to either 0 or L, whichever is larger.
   1.182 + * 16. Else set the length own property of F to 0.
   1.183 + */
   1.184 +function none() { return arguments.length; }
   1.185 +assertEq(none.bind(1, 2)(3, 4), 3);
   1.186 +assertEq(none.bind(1, 2)(), 1);
   1.187 +assertEq(none.bind(1)(2, 3), 2);
   1.188 +assertEq(none.bind().length, 0);
   1.189 +assertEq(none.bind(null).length, 0);
   1.190 +assertEq(none.bind(null, 1).length, 0);
   1.191 +assertEq(none.bind(null, 1, 2).length, 0);
   1.192 +
   1.193 +function one(a) { }
   1.194 +assertEq(one.bind().length, 1);
   1.195 +assertEq(one.bind(null).length, 1);
   1.196 +assertEq(one.bind(null, 1).length, 0);
   1.197 +assertEq(one.bind(null, 1, 2).length, 0);
   1.198 +
   1.199 +// retch
   1.200 +var br = Object.create(null, { length: { value: 0 } });
   1.201 +try
   1.202 +{
   1.203 +  br = bind.call(/a/g, /a/g, "aaaa");
   1.204 +}
   1.205 +catch (e) { /* nothing */ }
   1.206 +assertEq(br.length, 0);
   1.207 +
   1.208 +
   1.209 +/*
   1.210 + * 17. Set the attributes of the length own property of F to the values
   1.211 + *     specified in 15.3.5.1.
   1.212 + */
   1.213 +var len1Desc =
   1.214 +  Object.getOwnPropertyDescriptor(function(a, b, c){}.bind(), "length");
   1.215 +assertEq(len1Desc.value, 3);
   1.216 +assertEq(len1Desc.writable, false);
   1.217 +assertEq(len1Desc.enumerable, false);
   1.218 +assertEq(len1Desc.configurable, false);
   1.219 +
   1.220 +var len2Desc =
   1.221 +  Object.getOwnPropertyDescriptor(function(a, b, c){}.bind(null, 2), "length");
   1.222 +assertEq(len2Desc.value, 2);
   1.223 +assertEq(len2Desc.writable, false);
   1.224 +assertEq(len2Desc.enumerable, false);
   1.225 +assertEq(len2Desc.configurable, false);
   1.226 +
   1.227 +
   1.228 +/*
   1.229 + * 18. Set the [[Extensible]] internal property of F to true.
   1.230 + */
   1.231 +var bound = (function() { }).bind();
   1.232 +
   1.233 +var isExtensible = Object.isExtensible || function() { return true; };
   1.234 +assertEq(isExtensible(bound), true);
   1.235 +
   1.236 +bound.foo = 17;
   1.237 +var fooDesc = Object.getOwnPropertyDescriptor(bound, "foo");
   1.238 +assertEq(fooDesc.value, 17);
   1.239 +assertEq(fooDesc.writable, true);
   1.240 +assertEq(fooDesc.enumerable, true);
   1.241 +assertEq(fooDesc.configurable, true);
   1.242 +
   1.243 +
   1.244 +/*
   1.245 + * 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
   1.246 + * 20. Call the [[DefineOwnProperty]] internal method of F with arguments
   1.247 + *     "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]: thrower,
   1.248 + *     [[Enumerable]]: false, [[Configurable]]: false}, and false.
   1.249 + * 21. Call the [[DefineOwnProperty]] internal method of F with arguments
   1.250 + *     "arguments", PropertyDescriptor {[[Get]]: thrower, [[Set]]: thrower,
   1.251 + *     [[Enumerable]]: false, [[Configurable]]: false}, and false.
   1.252 + */
   1.253 +function f() { "use strict"; }
   1.254 +var canonicalTTE = Object.getOwnPropertyDescriptor(f, "caller").get;
   1.255 +
   1.256 +var tte;
   1.257 +
   1.258 +var boundf = f.bind();
   1.259 +
   1.260 +var boundfCaller = Object.getOwnPropertyDescriptor(boundf, "caller");
   1.261 +assertEq("get" in boundfCaller, true);
   1.262 +assertEq("set" in boundfCaller, true);
   1.263 +tte = boundfCaller.get;
   1.264 +assertEq(tte, canonicalTTE);
   1.265 +assertEq(tte, boundfCaller.set);
   1.266 +
   1.267 +var boundfArguments = Object.getOwnPropertyDescriptor(boundf, "arguments");
   1.268 +assertEq("get" in boundfArguments, true);
   1.269 +assertEq("set" in boundfArguments, true);
   1.270 +tte = boundfArguments.get;
   1.271 +assertEq(tte, canonicalTTE);
   1.272 +assertEq(tte, boundfArguments.set);
   1.273 +
   1.274 +
   1.275 +/* 22. Return F. */
   1.276 +var passim = function p(){}.bind(1);
   1.277 +assertEq(typeof passim, "function");
   1.278 +
   1.279 +
   1.280 +/******************************************************************************/
   1.281 +
   1.282 +if (typeof reportCompare === "function")
   1.283 +  reportCompare(true, true);
   1.284 +
   1.285 +print("All tests passed!");

mercurial