Wed, 31 Dec 2014 06:09:35 +0100
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 | * Contributor: |
michael@0 | 5 | * Jeff Walden <jwalden+code@mit.edu> |
michael@0 | 6 | */ |
michael@0 | 7 | |
michael@0 | 8 | //----------------------------------------------------------------------------- |
michael@0 | 9 | var BUGNUMBER = 562448; |
michael@0 | 10 | var summary = 'Function.prototype.apply should accept any arraylike arguments'; |
michael@0 | 11 | print(BUGNUMBER + ": " + summary); |
michael@0 | 12 | |
michael@0 | 13 | /************** |
michael@0 | 14 | * BEGIN TEST * |
michael@0 | 15 | **************/ |
michael@0 | 16 | |
michael@0 | 17 | function expectTypeError(fun, msg) |
michael@0 | 18 | { |
michael@0 | 19 | try |
michael@0 | 20 | { |
michael@0 | 21 | fun(); |
michael@0 | 22 | assertEq(true, false, "should have thrown a TypeError"); |
michael@0 | 23 | } |
michael@0 | 24 | catch (e) |
michael@0 | 25 | { |
michael@0 | 26 | assertEq(e instanceof TypeError, true, msg + "; instead threw " + e); |
michael@0 | 27 | } |
michael@0 | 28 | } |
michael@0 | 29 | |
michael@0 | 30 | function fun() { } |
michael@0 | 31 | |
michael@0 | 32 | var global = this; |
michael@0 | 33 | |
michael@0 | 34 | |
michael@0 | 35 | /* Step 1. */ |
michael@0 | 36 | var nonfuns = [null, 1, -1, 2.5, "[[Call]]", undefined, true, false, {}]; |
michael@0 | 37 | for (var i = 0, sz = nonfuns.length; i < sz; i++) |
michael@0 | 38 | { |
michael@0 | 39 | var f = function() |
michael@0 | 40 | { |
michael@0 | 41 | Function.prototype.apply.apply(nonfuns[i], [1, 2, 3]); |
michael@0 | 42 | }; |
michael@0 | 43 | var msg = |
michael@0 | 44 | "expected TypeError calling Function.prototype.apply with uncallable this"; |
michael@0 | 45 | expectTypeError(f, msg); |
michael@0 | 46 | } |
michael@0 | 47 | |
michael@0 | 48 | |
michael@0 | 49 | /* Step 2. */ |
michael@0 | 50 | var thisObj = {}; |
michael@0 | 51 | |
michael@0 | 52 | var currentThis, currentThisBox; |
michael@0 | 53 | function funLength() |
michael@0 | 54 | { |
michael@0 | 55 | assertEq(arguments.length, 0, "should have been called with no arguments"); |
michael@0 | 56 | assertEq(this, currentThis, "wrong this"); |
michael@0 | 57 | } |
michael@0 | 58 | function strictFunLength() |
michael@0 | 59 | { |
michael@0 | 60 | "use strict"; |
michael@0 | 61 | assertEq(arguments.length, 0, "should have been called with no arguments"); |
michael@0 | 62 | assertEq(this, currentThis, "wrong this"); |
michael@0 | 63 | } |
michael@0 | 64 | |
michael@0 | 65 | currentThis = global; |
michael@0 | 66 | funLength.apply(); |
michael@0 | 67 | funLength.apply(undefined); |
michael@0 | 68 | funLength.apply(undefined, undefined); |
michael@0 | 69 | funLength.apply(undefined, null); |
michael@0 | 70 | |
michael@0 | 71 | currentThis = undefined; |
michael@0 | 72 | strictFunLength.apply(); |
michael@0 | 73 | strictFunLength.apply(undefined); |
michael@0 | 74 | strictFunLength.apply(undefined, undefined); |
michael@0 | 75 | strictFunLength.apply(undefined, null); |
michael@0 | 76 | |
michael@0 | 77 | currentThis = null; |
michael@0 | 78 | strictFunLength.apply(null); |
michael@0 | 79 | strictFunLength.apply(null, undefined); |
michael@0 | 80 | strictFunLength.apply(null, null); |
michael@0 | 81 | |
michael@0 | 82 | currentThis = thisObj; |
michael@0 | 83 | funLength.apply(thisObj); |
michael@0 | 84 | funLength.apply(thisObj, null); |
michael@0 | 85 | funLength.apply(thisObj, undefined); |
michael@0 | 86 | strictFunLength.apply(thisObj); |
michael@0 | 87 | strictFunLength.apply(thisObj, null); |
michael@0 | 88 | strictFunLength.apply(thisObj, undefined); |
michael@0 | 89 | |
michael@0 | 90 | currentThis = 17; |
michael@0 | 91 | strictFunLength.apply(17); |
michael@0 | 92 | strictFunLength.apply(17, null); |
michael@0 | 93 | strictFunLength.apply(17, undefined); |
michael@0 | 94 | |
michael@0 | 95 | function funThisPrimitive() |
michael@0 | 96 | { |
michael@0 | 97 | assertEq(arguments.length, 0, "should have been called with no arguments"); |
michael@0 | 98 | assertEq(this instanceof currentThisBox, true, |
michael@0 | 99 | "this not instanceof " + currentThisBox); |
michael@0 | 100 | assertEq(this.valueOf(), currentThis, |
michael@0 | 101 | "wrong this valueOf()"); |
michael@0 | 102 | } |
michael@0 | 103 | |
michael@0 | 104 | currentThis = 17; |
michael@0 | 105 | currentThisBox = Number; |
michael@0 | 106 | funThisPrimitive.apply(17); |
michael@0 | 107 | funThisPrimitive.apply(17, undefined); |
michael@0 | 108 | funThisPrimitive.apply(17, null); |
michael@0 | 109 | |
michael@0 | 110 | currentThis = "foopy"; |
michael@0 | 111 | currentThisBox = String; |
michael@0 | 112 | funThisPrimitive.apply("foopy"); |
michael@0 | 113 | funThisPrimitive.apply("foopy", undefined); |
michael@0 | 114 | funThisPrimitive.apply("foopy", null); |
michael@0 | 115 | |
michael@0 | 116 | currentThis = false; |
michael@0 | 117 | currentThisBox = Boolean; |
michael@0 | 118 | funThisPrimitive.apply(false); |
michael@0 | 119 | funThisPrimitive.apply(false, undefined); |
michael@0 | 120 | funThisPrimitive.apply(false, null); |
michael@0 | 121 | |
michael@0 | 122 | |
michael@0 | 123 | /* Step 3. */ |
michael@0 | 124 | var nonobjs = [1, -1, 2.5, "[[Call]]", true, false]; |
michael@0 | 125 | for (var i = 0, sz = nonobjs.length; i < sz; i++) |
michael@0 | 126 | { |
michael@0 | 127 | var f = function() { fun.apply(thisObj, nonobjs[i]); }; |
michael@0 | 128 | var msg = "should have thrown a TypeError with non-object arguments"; |
michael@0 | 129 | expectTypeError(f, msg); |
michael@0 | 130 | } |
michael@0 | 131 | |
michael@0 | 132 | |
michael@0 | 133 | /* Step 4. */ |
michael@0 | 134 | var args = { get length() { throw 42; } }; |
michael@0 | 135 | try |
michael@0 | 136 | { |
michael@0 | 137 | fun.apply(thisObj, args); |
michael@0 | 138 | } |
michael@0 | 139 | catch (e) |
michael@0 | 140 | { |
michael@0 | 141 | assertEq(e, 42, "didn't throw result of [[Get]] on arguments object"); |
michael@0 | 142 | } |
michael@0 | 143 | |
michael@0 | 144 | |
michael@0 | 145 | /* |
michael@0 | 146 | * NB: There was an erratum removing the steps numbered 5 and 7 in the original |
michael@0 | 147 | * version of ES5; see also the comments in js_fun_apply. |
michael@0 | 148 | */ |
michael@0 | 149 | |
michael@0 | 150 | /* Step 5. */ |
michael@0 | 151 | var called = false; |
michael@0 | 152 | var argsObjectLength = |
michael@0 | 153 | { length: { valueOf: function() { called = true; return 17; } } }; |
michael@0 | 154 | |
michael@0 | 155 | fun.apply({}, argsObjectLength); |
michael@0 | 156 | assertEq(called, true, "should have been set in valueOf called via ToUint32"); |
michael@0 | 157 | |
michael@0 | 158 | var upvar = "unset"; |
michael@0 | 159 | var argsObjectPrimitiveLength = |
michael@0 | 160 | { |
michael@0 | 161 | length: |
michael@0 | 162 | { |
michael@0 | 163 | valueOf: function() { upvar = "valueOf"; return {}; }, |
michael@0 | 164 | toString: function() |
michael@0 | 165 | { |
michael@0 | 166 | upvar = upvar === "valueOf" ? "both" : "toString"; |
michael@0 | 167 | return 17; |
michael@0 | 168 | } |
michael@0 | 169 | } |
michael@0 | 170 | }; |
michael@0 | 171 | fun.apply({}, argsObjectPrimitiveLength); |
michael@0 | 172 | assertEq(upvar, "both", "didn't call all hooks properly"); |
michael@0 | 173 | |
michael@0 | 174 | |
michael@0 | 175 | /* Step 6-9. */ |
michael@0 | 176 | var seenThis, res, steps; |
michael@0 | 177 | var argsAccessors = |
michael@0 | 178 | { |
michael@0 | 179 | length: 4, |
michael@0 | 180 | get 0() { steps.push("0"); return 1; }, |
michael@0 | 181 | get 1() { steps.push("1"); return 2; }, |
michael@0 | 182 | // make sure values shine through holes |
michael@0 | 183 | get 3() { steps.push("3"); return 8; }, |
michael@0 | 184 | }; |
michael@0 | 185 | |
michael@0 | 186 | Object.prototype[2] = 729; |
michael@0 | 187 | |
michael@0 | 188 | seenThis = "not seen"; |
michael@0 | 189 | function argsAsArray() |
michael@0 | 190 | { |
michael@0 | 191 | seenThis = this; |
michael@0 | 192 | steps.push(Math.PI); |
michael@0 | 193 | return Array.prototype.map.call(arguments, function(v) { return v; }); |
michael@0 | 194 | } |
michael@0 | 195 | |
michael@0 | 196 | steps = []; |
michael@0 | 197 | res = argsAsArray.apply(thisObj, argsAccessors); |
michael@0 | 198 | assertEq(seenThis, thisObj, "saw wrong this"); |
michael@0 | 199 | |
michael@0 | 200 | assertEq(steps.length, 4, "wrong steps: " + steps); |
michael@0 | 201 | assertEq(steps[0], "0", "bad step 0"); |
michael@0 | 202 | assertEq(steps[1], "1", "bad step 1"); |
michael@0 | 203 | assertEq(steps[2], "3", "bad step 3"); |
michael@0 | 204 | assertEq(steps[3], Math.PI, "bad last step"); |
michael@0 | 205 | |
michael@0 | 206 | assertEq(res.length, 4, "wrong return: " + res); |
michael@0 | 207 | assertEq(res[0], 1, "wrong ret[0]"); |
michael@0 | 208 | assertEq(res[1], 2, "wrong ret[0]"); |
michael@0 | 209 | assertEq(res[2], 729, "wrong ret[0]"); |
michael@0 | 210 | assertEq(res[3], 8, "wrong ret[0]"); |
michael@0 | 211 | |
michael@0 | 212 | seenThis = "not seen"; |
michael@0 | 213 | function strictArgsAsArray() |
michael@0 | 214 | { |
michael@0 | 215 | "use strict"; |
michael@0 | 216 | seenThis = this; |
michael@0 | 217 | steps.push(NaN); |
michael@0 | 218 | return Array.prototype.map.call(arguments, function(v) { return v; }); |
michael@0 | 219 | } |
michael@0 | 220 | |
michael@0 | 221 | steps = []; |
michael@0 | 222 | res = strictArgsAsArray.apply(null, argsAccessors); |
michael@0 | 223 | assertEq(seenThis, null, "saw wrong this"); |
michael@0 | 224 | |
michael@0 | 225 | assertEq(steps.length, 4, "wrong steps: " + steps); |
michael@0 | 226 | assertEq(steps[0], "0", "bad step 0"); |
michael@0 | 227 | assertEq(steps[1], "1", "bad step 1"); |
michael@0 | 228 | assertEq(steps[2], "3", "bad step 3"); |
michael@0 | 229 | assertEq(steps[3], 0 / 0, "bad last step"); |
michael@0 | 230 | |
michael@0 | 231 | assertEq(res.length, 4, "wrong return: " + res); |
michael@0 | 232 | assertEq(res[0], 1, "wrong ret[0]"); |
michael@0 | 233 | assertEq(res[1], 2, "wrong ret[0]"); |
michael@0 | 234 | assertEq(res[2], 729, "wrong ret[0]"); |
michael@0 | 235 | assertEq(res[3], 8, "wrong ret[0]"); |
michael@0 | 236 | |
michael@0 | 237 | strictArgsAsArray.apply(17, argsAccessors); |
michael@0 | 238 | assertEq(seenThis, 17, "saw wrong this"); |
michael@0 | 239 | |
michael@0 | 240 | /******************************************************************************/ |
michael@0 | 241 | |
michael@0 | 242 | if (typeof reportCompare === "function") |
michael@0 | 243 | reportCompare(true, true); |
michael@0 | 244 | |
michael@0 | 245 | print("All tests passed!"); |