michael@0: load(libdir + "asserts.js"); michael@0: michael@0: function check_one(expected, f, err) { michael@0: var failed = true; michael@0: try { michael@0: f(); michael@0: failed = false; michael@0: } catch (ex) { michael@0: var s = ex.toString(); michael@0: assertEq(s.slice(0, 11), "TypeError: "); michael@0: assertEq(s.slice(-err.length), err, "" + f); michael@0: assertEq(s.slice(11, -err.length), expected); michael@0: } michael@0: if (!failed) michael@0: throw new Error("didn't fail"); michael@0: } michael@0: ieval = eval; michael@0: function check(expr, expected=expr) { michael@0: var end, err; michael@0: for ([end, err] of [[".random_prop", " is undefined"], ["()", " is not a function"]]) { michael@0: var statement = "o = {};" + expr + end, f; michael@0: var cases = [ michael@0: // Global scope michael@0: function () { michael@0: ieval("var o, undef;\n" + statement); michael@0: }, michael@0: // Function scope michael@0: Function("o", "undef", statement), michael@0: // Function scope with variables michael@0: Function("var o, undef;\n" + statement), michael@0: // Function scope with some different arugments michael@0: Function("arg1", "arg2", "var o, undef;\n" + statement), michael@0: // Deoptimized function scope michael@0: Function("o", "undef", "with (Object) {}\n" + statement), michael@0: // Inside with michael@0: Function("with (Object) { " + statement + " }"), michael@0: // Closure michael@0: Function("o", "undef", "function myfunc() { return o + undef; }\n" + statement), michael@0: // Let definitions in a block michael@0: Function("{ let o, undef;\n" + statement + "}"), michael@0: // Let block michael@0: Function("let (o, undef) { " + statement + " }"), michael@0: // Let block with some other variables michael@0: Function("var v1, v2; let (o, undef) { " + statement + " }"), michael@0: // Shadowed let block michael@0: Function("o", "undef", "let (o, undef) { " + statement + " }"), michael@0: // Let in a switch michael@0: Function("var x = 4; switch (x) { case 4: let o, undef;" + statement + "\ncase 6: break;}"), michael@0: // The more lets the merrier michael@0: Function("let (x=4, y=5) { x + y; }\nlet (a, b, c) { a + b - c; }\nlet (o, undef) {" + statement + " }"), michael@0: // Let destructuring michael@0: Function("o", "undef", "let ([] = 4) {} let (o, undef) { " + statement + " }"), michael@0: // Try-catch blocks michael@0: Function("o", "undef", "try { let q = 4; try { let p = 4; } catch (e) {} } catch (e) {} let (o, undef) { " + statement + " }") michael@0: ]; michael@0: michael@0: try { michael@0: // Let in for-in michael@0: check_one(expected, michael@0: Function("var undef, o; for (let z in [1, 2]) { " + statement + " }"), michael@0: err); michael@0: } catch (ex) { michael@0: // Bug 831120. See bug 942804 comment 5. michael@0: if (expected == 'undef' && err == ' is undefined') michael@0: check_one(expected + end, michael@0: Function("var undef, o; for (let z in [1, 2]) { " + statement + " }"), michael@0: err); michael@0: else michael@0: throw ex; michael@0: } michael@0: michael@0: for (var f of cases) { michael@0: check_one(expected, f, err); michael@0: } michael@0: } michael@0: } michael@0: michael@0: check("undef"); michael@0: check("o.b"); michael@0: check("o.length"); michael@0: check("o[true]"); michael@0: check("o[false]"); michael@0: check("o[null]"); michael@0: check("o[0]"); michael@0: check("o[1]"); michael@0: check("o[3]"); michael@0: check("o[256]"); michael@0: check("o[65536]"); michael@0: check("o[268435455]"); michael@0: check("o['1.1']"); michael@0: check("o[4 + 'h']", "o['4h']"); michael@0: check("this.x"); michael@0: check("ieval(undef)", "ieval(...)"); michael@0: check("ieval.call()", "ieval.call(...)"); michael@0: check("ieval(...[])", "ieval(...)"); michael@0: check("ieval(...[undef])", "ieval(...)"); michael@0: check("ieval(...[undef, undef])", "ieval(...)"); michael@0: michael@0: for (let tok of ["|", "^", "&", "==", "!==", "===", "!==", "<", "<=", ">", ">=", michael@0: ">>", "<<", ">>>", "+", "-", "*", "/", "%"]) { michael@0: check("o[(undef " + tok + " 4)]"); michael@0: } michael@0: michael@0: check("o[!(o)]"); michael@0: check("o[~(o)]"); michael@0: check("o[+ (o)]"); michael@0: check("o[- (o)]"); michael@0: michael@0: // A few one off tests michael@0: check_one("6", (function () { 6() }), " is not a function"); michael@0: check_one("Array.prototype.reverse.call(...)", (function () { Array.prototype.reverse.call('123'); }), " is read-only"); michael@0: check_one("null", function () { var [{ x }] = [null, {}]; }, " has no properties"); michael@0: check_one("x", function () { ieval("let (x) { var [a, b, [c0, c1]] = [x, x, x]; }") }, " is undefined"); michael@0: michael@0: // Check fallback behavior michael@0: assertThrowsInstanceOf(function () { for (let x of undefined) {} }, TypeError);