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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 * Any copyright is dedicated to the Public Domain.
michael@0 3 * http://creativecommons.org/licenses/publicdomain/
michael@0 4 */
michael@0 5
michael@0 6 var gTestfile = 'function-bind.js';
michael@0 7 var BUGNUMBER = 429507;
michael@0 8 var summary = "ES5: Function.prototype.bind";
michael@0 9
michael@0 10 print(BUGNUMBER + ": " + summary);
michael@0 11
michael@0 12 /**************
michael@0 13 * BEGIN TEST *
michael@0 14 **************/
michael@0 15
michael@0 16 // ad-hoc testing
michael@0 17
michael@0 18 assertEq(Function.prototype.hasOwnProperty("bind"), true);
michael@0 19
michael@0 20 var bind = Function.prototype.bind;
michael@0 21 assertEq(bind.length, 1);
michael@0 22
michael@0 23
michael@0 24 var strictReturnThis = function() { "use strict"; return this; };
michael@0 25
michael@0 26 assertEq(strictReturnThis.bind(undefined)(), undefined);
michael@0 27 assertEq(strictReturnThis.bind(null)(), null);
michael@0 28
michael@0 29 var obj = {};
michael@0 30 assertEq(strictReturnThis.bind(obj)(), obj);
michael@0 31
michael@0 32 assertEq(strictReturnThis.bind(NaN)(), NaN);
michael@0 33
michael@0 34 assertEq(strictReturnThis.bind(true)(), true);
michael@0 35 assertEq(strictReturnThis.bind(false)(), false);
michael@0 36
michael@0 37 assertEq(strictReturnThis.bind("foopy")(), "foopy");
michael@0 38
michael@0 39
michael@0 40 // rigorous, step-by-step testing
michael@0 41
michael@0 42 function expectThrowTypeError(fun)
michael@0 43 {
michael@0 44 try
michael@0 45 {
michael@0 46 var r = fun();
michael@0 47 throw new Error("didn't throw TypeError, returned " + r);
michael@0 48 }
michael@0 49 catch (e)
michael@0 50 {
michael@0 51 assertEq(e instanceof TypeError, true,
michael@0 52 "didn't throw TypeError, got: " + e);
michael@0 53 }
michael@0 54 }
michael@0 55
michael@0 56 /*
michael@0 57 * 1. Let Target be the this value.
michael@0 58 * 2. If IsCallable(Target) is false, throw a TypeError exception.
michael@0 59 */
michael@0 60 expectThrowTypeError(function() { bind.call(null); });
michael@0 61 expectThrowTypeError(function() { bind.call(undefined); });
michael@0 62 expectThrowTypeError(function() { bind.call(NaN); });
michael@0 63 expectThrowTypeError(function() { bind.call(0); });
michael@0 64 expectThrowTypeError(function() { bind.call(-0); });
michael@0 65 expectThrowTypeError(function() { bind.call(17); });
michael@0 66 expectThrowTypeError(function() { bind.call(42); });
michael@0 67 expectThrowTypeError(function() { bind.call("foobar"); });
michael@0 68 expectThrowTypeError(function() { bind.call(true); });
michael@0 69 expectThrowTypeError(function() { bind.call(false); });
michael@0 70 expectThrowTypeError(function() { bind.call([]); });
michael@0 71 expectThrowTypeError(function() { bind.call({}); });
michael@0 72
michael@0 73
michael@0 74 /*
michael@0 75 * 3. Let A be a new (possibly empty) internal list of all of the argument
michael@0 76 * values provided after thisArg (arg1, arg2 etc), in order.
michael@0 77 * 4. Let F be a new native ECMAScript object .
michael@0 78 * 5. Set all the internal methods, except for [[Get]], of F as specified in
michael@0 79 * 8.12.
michael@0 80 * 6. Set the [[Get]] internal property of F as specified in 15.3.5.4.
michael@0 81 * 7. Set the [[TargetFunction]] internal property of F to Target.
michael@0 82 * 8. Set the [[BoundThis]] internal property of F to the value of thisArg.
michael@0 83 * 9. Set the [[BoundArgs]] internal property of F to A.
michael@0 84 */
michael@0 85 // throughout
michael@0 86
michael@0 87
michael@0 88 /* 10. Set the [[Class]] internal property of F to "Function". */
michael@0 89 var toString = Object.prototype.toString;
michael@0 90 assertEq(toString.call(function(){}), "[object Function]");
michael@0 91 assertEq(toString.call(function a(){}), "[object Function]");
michael@0 92 assertEq(toString.call(function(a){}), "[object Function]");
michael@0 93 assertEq(toString.call(function a(b){}), "[object Function]");
michael@0 94 assertEq(toString.call(function(){}.bind()), "[object Function]");
michael@0 95 assertEq(toString.call(function a(){}.bind()), "[object Function]");
michael@0 96 assertEq(toString.call(function(a){}.bind()), "[object Function]");
michael@0 97 assertEq(toString.call(function a(b){}.bind()), "[object Function]");
michael@0 98
michael@0 99
michael@0 100 /*
michael@0 101 * 11. Set the [[Prototype]] internal property of F to the standard built-in
michael@0 102 * Function prototype object as specified in 15.3.3.1.
michael@0 103 */
michael@0 104 assertEq(Object.getPrototypeOf(bind.call(function(){})), Function.prototype);
michael@0 105 assertEq(Object.getPrototypeOf(bind.call(function a(){})), Function.prototype);
michael@0 106 assertEq(Object.getPrototypeOf(bind.call(function(a){})), Function.prototype);
michael@0 107 assertEq(Object.getPrototypeOf(bind.call(function a(b){})), Function.prototype);
michael@0 108
michael@0 109
michael@0 110 /*
michael@0 111 * 12. Set the [[Call]] internal property of F as described in 15.3.4.5.1.
michael@0 112 */
michael@0 113 var a = Array.bind(1, 2);
michael@0 114 assertEq(a().length, 2);
michael@0 115 assertEq(a(4).length, 2);
michael@0 116 assertEq(a(4, 8).length, 3);
michael@0 117
michael@0 118 function t() { return this; }
michael@0 119 var bt = t.bind(t);
michael@0 120 assertEq(bt(), t);
michael@0 121
michael@0 122 function callee() { return arguments.callee; }
michael@0 123 var call = callee.bind();
michael@0 124 assertEq(call(), callee);
michael@0 125 assertEq(new call(), callee);
michael@0 126
michael@0 127
michael@0 128 /*
michael@0 129 * 13. Set the [[Construct]] internal property of F as described in 15.3.4.5.2.
michael@0 130 */
michael@0 131 function Point(x, y)
michael@0 132 {
michael@0 133 this.x = x;
michael@0 134 this.y = y;
michael@0 135 }
michael@0 136 var YAxisPoint = Point.bind(null, 0)
michael@0 137
michael@0 138 assertEq(YAxisPoint.hasOwnProperty("prototype"), false);
michael@0 139 var p = new YAxisPoint(5);
michael@0 140 assertEq(p.x, 0);
michael@0 141 assertEq(p.y, 5);
michael@0 142 assertEq(p instanceof Point, true);
michael@0 143 assertEq(p instanceof YAxisPoint, true);
michael@0 144 assertEq(Object.prototype.toString.call(YAxisPoint), "[object Function]");
michael@0 145 assertEq(YAxisPoint.length, 1);
michael@0 146
michael@0 147
michael@0 148 /*
michael@0 149 * 14. Set the [[HasInstance]] internal property of F as described in
michael@0 150 * 15.3.4.5.3.
michael@0 151 */
michael@0 152 function JoinArguments()
michael@0 153 {
michael@0 154 this.args = Array.prototype.join.call(arguments, ", ");
michael@0 155 }
michael@0 156
michael@0 157 var Join1 = JoinArguments.bind(null, 1);
michael@0 158 var Join2 = Join1.bind(null, 2);
michael@0 159 var Join3 = Join2.bind(null, 3);
michael@0 160 var Join4 = Join3.bind(null, 4);
michael@0 161 var Join5 = Join4.bind(null, 5);
michael@0 162 var Join6 = Join5.bind(null, 6);
michael@0 163
michael@0 164 var r = new Join6(7);
michael@0 165 assertEq(r instanceof Join6, true);
michael@0 166 assertEq(r instanceof Join5, true);
michael@0 167 assertEq(r instanceof Join4, true);
michael@0 168 assertEq(r instanceof Join3, true);
michael@0 169 assertEq(r instanceof Join2, true);
michael@0 170 assertEq(r instanceof Join1, true);
michael@0 171 assertEq(r instanceof JoinArguments, true);
michael@0 172 assertEq(r.args, "1, 2, 3, 4, 5, 6, 7");
michael@0 173
michael@0 174
michael@0 175 /*
michael@0 176 * 15. If the [[Class]] internal property of Target is "Function", then
michael@0 177 * a. Let L be the length property of Target minus the length of A.
michael@0 178 * b. Set the length own property of F to either 0 or L, whichever is larger.
michael@0 179 * 16. Else set the length own property of F to 0.
michael@0 180 */
michael@0 181 function none() { return arguments.length; }
michael@0 182 assertEq(none.bind(1, 2)(3, 4), 3);
michael@0 183 assertEq(none.bind(1, 2)(), 1);
michael@0 184 assertEq(none.bind(1)(2, 3), 2);
michael@0 185 assertEq(none.bind().length, 0);
michael@0 186 assertEq(none.bind(null).length, 0);
michael@0 187 assertEq(none.bind(null, 1).length, 0);
michael@0 188 assertEq(none.bind(null, 1, 2).length, 0);
michael@0 189
michael@0 190 function one(a) { }
michael@0 191 assertEq(one.bind().length, 1);
michael@0 192 assertEq(one.bind(null).length, 1);
michael@0 193 assertEq(one.bind(null, 1).length, 0);
michael@0 194 assertEq(one.bind(null, 1, 2).length, 0);
michael@0 195
michael@0 196 // retch
michael@0 197 var br = Object.create(null, { length: { value: 0 } });
michael@0 198 try
michael@0 199 {
michael@0 200 br = bind.call(/a/g, /a/g, "aaaa");
michael@0 201 }
michael@0 202 catch (e) { /* nothing */ }
michael@0 203 assertEq(br.length, 0);
michael@0 204
michael@0 205
michael@0 206 /*
michael@0 207 * 17. Set the attributes of the length own property of F to the values
michael@0 208 * specified in 15.3.5.1.
michael@0 209 */
michael@0 210 var len1Desc =
michael@0 211 Object.getOwnPropertyDescriptor(function(a, b, c){}.bind(), "length");
michael@0 212 assertEq(len1Desc.value, 3);
michael@0 213 assertEq(len1Desc.writable, false);
michael@0 214 assertEq(len1Desc.enumerable, false);
michael@0 215 assertEq(len1Desc.configurable, false);
michael@0 216
michael@0 217 var len2Desc =
michael@0 218 Object.getOwnPropertyDescriptor(function(a, b, c){}.bind(null, 2), "length");
michael@0 219 assertEq(len2Desc.value, 2);
michael@0 220 assertEq(len2Desc.writable, false);
michael@0 221 assertEq(len2Desc.enumerable, false);
michael@0 222 assertEq(len2Desc.configurable, false);
michael@0 223
michael@0 224
michael@0 225 /*
michael@0 226 * 18. Set the [[Extensible]] internal property of F to true.
michael@0 227 */
michael@0 228 var bound = (function() { }).bind();
michael@0 229
michael@0 230 var isExtensible = Object.isExtensible || function() { return true; };
michael@0 231 assertEq(isExtensible(bound), true);
michael@0 232
michael@0 233 bound.foo = 17;
michael@0 234 var fooDesc = Object.getOwnPropertyDescriptor(bound, "foo");
michael@0 235 assertEq(fooDesc.value, 17);
michael@0 236 assertEq(fooDesc.writable, true);
michael@0 237 assertEq(fooDesc.enumerable, true);
michael@0 238 assertEq(fooDesc.configurable, true);
michael@0 239
michael@0 240
michael@0 241 /*
michael@0 242 * 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
michael@0 243 * 20. Call the [[DefineOwnProperty]] internal method of F with arguments
michael@0 244 * "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]: thrower,
michael@0 245 * [[Enumerable]]: false, [[Configurable]]: false}, and false.
michael@0 246 * 21. Call the [[DefineOwnProperty]] internal method of F with arguments
michael@0 247 * "arguments", PropertyDescriptor {[[Get]]: thrower, [[Set]]: thrower,
michael@0 248 * [[Enumerable]]: false, [[Configurable]]: false}, and false.
michael@0 249 */
michael@0 250 function f() { "use strict"; }
michael@0 251 var canonicalTTE = Object.getOwnPropertyDescriptor(f, "caller").get;
michael@0 252
michael@0 253 var tte;
michael@0 254
michael@0 255 var boundf = f.bind();
michael@0 256
michael@0 257 var boundfCaller = Object.getOwnPropertyDescriptor(boundf, "caller");
michael@0 258 assertEq("get" in boundfCaller, true);
michael@0 259 assertEq("set" in boundfCaller, true);
michael@0 260 tte = boundfCaller.get;
michael@0 261 assertEq(tte, canonicalTTE);
michael@0 262 assertEq(tte, boundfCaller.set);
michael@0 263
michael@0 264 var boundfArguments = Object.getOwnPropertyDescriptor(boundf, "arguments");
michael@0 265 assertEq("get" in boundfArguments, true);
michael@0 266 assertEq("set" in boundfArguments, true);
michael@0 267 tte = boundfArguments.get;
michael@0 268 assertEq(tte, canonicalTTE);
michael@0 269 assertEq(tte, boundfArguments.set);
michael@0 270
michael@0 271
michael@0 272 /* 22. Return F. */
michael@0 273 var passim = function p(){}.bind(1);
michael@0 274 assertEq(typeof passim, "function");
michael@0 275
michael@0 276
michael@0 277 /******************************************************************************/
michael@0 278
michael@0 279 if (typeof reportCompare === "function")
michael@0 280 reportCompare(true, true);
michael@0 281
michael@0 282 print("All tests passed!");

mercurial