diff options
Diffstat (limited to 'js/src/tests/non262/Function/15.3.4.3-01.js')
-rw-r--r-- | js/src/tests/non262/Function/15.3.4.3-01.js | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/js/src/tests/non262/Function/15.3.4.3-01.js b/js/src/tests/non262/Function/15.3.4.3-01.js new file mode 100644 index 0000000000..955d773766 --- /dev/null +++ b/js/src/tests/non262/Function/15.3.4.3-01.js @@ -0,0 +1,245 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden <jwalden+code@mit.edu> + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 562448; +var summary = 'Function.prototype.apply should accept any arraylike arguments'; +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function expectTypeError(fun, msg) +{ + try + { + fun(); + assertEq(true, false, "should have thrown a TypeError"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, msg + "; instead threw " + e); + } +} + +function fun() { } + +var global = this; + + +/* Step 1. */ +var nonfuns = [null, 1, -1, 2.5, "[[Call]]", undefined, true, false, {}]; +for (var i = 0, sz = nonfuns.length; i < sz; i++) +{ + var f = function() + { + Function.prototype.apply.apply(nonfuns[i], [1, 2, 3]); + }; + var msg = + "expected TypeError calling Function.prototype.apply with uncallable this"; + expectTypeError(f, msg); +} + + +/* Step 2. */ +var thisObj = {}; + +var currentThis, currentThisBox; +function funLength() +{ + assertEq(arguments.length, 0, "should have been called with no arguments"); + assertEq(this, currentThis, "wrong this"); +} +function strictFunLength() +{ + "use strict"; + assertEq(arguments.length, 0, "should have been called with no arguments"); + assertEq(this, currentThis, "wrong this"); +} + +currentThis = global; +funLength.apply(); +funLength.apply(undefined); +funLength.apply(undefined, undefined); +funLength.apply(undefined, null); + +currentThis = undefined; +strictFunLength.apply(); +strictFunLength.apply(undefined); +strictFunLength.apply(undefined, undefined); +strictFunLength.apply(undefined, null); + +currentThis = null; +strictFunLength.apply(null); +strictFunLength.apply(null, undefined); +strictFunLength.apply(null, null); + +currentThis = thisObj; +funLength.apply(thisObj); +funLength.apply(thisObj, null); +funLength.apply(thisObj, undefined); +strictFunLength.apply(thisObj); +strictFunLength.apply(thisObj, null); +strictFunLength.apply(thisObj, undefined); + +currentThis = 17; +strictFunLength.apply(17); +strictFunLength.apply(17, null); +strictFunLength.apply(17, undefined); + +function funThisPrimitive() +{ + assertEq(arguments.length, 0, "should have been called with no arguments"); + assertEq(this instanceof currentThisBox, true, + "this not instanceof " + currentThisBox); + assertEq(this.valueOf(), currentThis, + "wrong this valueOf()"); +} + +currentThis = 17; +currentThisBox = Number; +funThisPrimitive.apply(17); +funThisPrimitive.apply(17, undefined); +funThisPrimitive.apply(17, null); + +currentThis = "foopy"; +currentThisBox = String; +funThisPrimitive.apply("foopy"); +funThisPrimitive.apply("foopy", undefined); +funThisPrimitive.apply("foopy", null); + +currentThis = false; +currentThisBox = Boolean; +funThisPrimitive.apply(false); +funThisPrimitive.apply(false, undefined); +funThisPrimitive.apply(false, null); + + +/* Step 3. */ +var nonobjs = [1, -1, 2.5, "[[Call]]", true, false]; +for (var i = 0, sz = nonobjs.length; i < sz; i++) +{ + var f = function() { fun.apply(thisObj, nonobjs[i]); }; + var msg = "should have thrown a TypeError with non-object arguments"; + expectTypeError(f, msg); +} + + +/* Step 4. */ +var args = { get length() { throw 42; } }; +try +{ + fun.apply(thisObj, args); +} +catch (e) +{ + assertEq(e, 42, "didn't throw result of [[Get]] on arguments object"); +} + + +/* + * NB: There was an erratum removing the steps numbered 5 and 7 in the original + * version of ES5; see also the comments in js_fun_apply. + */ + +/* Step 5. */ +var called = false; +var argsObjectLength = + { length: { valueOf: function() { called = true; return 17; } } }; + +fun.apply({}, argsObjectLength); +assertEq(called, true, "should have been set in valueOf called via ToUint32"); + +var upvar = "unset"; +var argsObjectPrimitiveLength = + { + length: + { + valueOf: function() { upvar = "valueOf"; return {}; }, + toString: function() + { + upvar = upvar === "valueOf" ? "both" : "toString"; + return 17; + } + } + }; +fun.apply({}, argsObjectPrimitiveLength); +assertEq(upvar, "both", "didn't call all hooks properly"); + + +/* Step 6-9. */ +var seenThis, res, steps; +var argsAccessors = + { + length: 4, + get 0() { steps.push("0"); return 1; }, + get 1() { steps.push("1"); return 2; }, + // make sure values shine through holes + get 3() { steps.push("3"); return 8; }, + }; + +Object.prototype[2] = 729; + +seenThis = "not seen"; +function argsAsArray() +{ + seenThis = this; + steps.push(Math.PI); + return Array.prototype.map.call(arguments, function(v) { return v; }); +} + +steps = []; +res = argsAsArray.apply(thisObj, argsAccessors); +assertEq(seenThis, thisObj, "saw wrong this"); + +assertEq(steps.length, 4, "wrong steps: " + steps); +assertEq(steps[0], "0", "bad step 0"); +assertEq(steps[1], "1", "bad step 1"); +assertEq(steps[2], "3", "bad step 3"); +assertEq(steps[3], Math.PI, "bad last step"); + +assertEq(res.length, 4, "wrong return: " + res); +assertEq(res[0], 1, "wrong ret[0]"); +assertEq(res[1], 2, "wrong ret[0]"); +assertEq(res[2], 729, "wrong ret[0]"); +assertEq(res[3], 8, "wrong ret[0]"); + +seenThis = "not seen"; +function strictArgsAsArray() +{ + "use strict"; + seenThis = this; + steps.push(NaN); + return Array.prototype.map.call(arguments, function(v) { return v; }); +} + +steps = []; +res = strictArgsAsArray.apply(null, argsAccessors); +assertEq(seenThis, null, "saw wrong this"); + +assertEq(steps.length, 4, "wrong steps: " + steps); +assertEq(steps[0], "0", "bad step 0"); +assertEq(steps[1], "1", "bad step 1"); +assertEq(steps[2], "3", "bad step 3"); +assertEq(steps[3], 0 / 0, "bad last step"); + +assertEq(res.length, 4, "wrong return: " + res); +assertEq(res[0], 1, "wrong ret[0]"); +assertEq(res[1], 2, "wrong ret[0]"); +assertEq(res[2], 729, "wrong ret[0]"); +assertEq(res[3], 8, "wrong ret[0]"); + +strictArgsAsArray.apply(17, argsAccessors); +assertEq(seenThis, 17, "saw wrong this"); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); |