1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
// Various evaluation order tests..
// Argument list should be evaluated before checking whether functions is callable, etc.
function test1() {
function bad() {
throw "PASS";
}
try {
var f = 42;
f(bad());
} catch (e) {
return e;
}
}
shouldBe('test1()', '"PASS"');
// Make sure we do toObject properly
shouldThrow("var v = null; delete v.x;");
// Left hand-side of an assignment should be bound as a reference before evaluating RHS, test #1
x = 0;
function test2() {
x = eval("var x; 42;");
}
test2();
shouldBe('x', '42');
// Same, but using with and not eval.
y = 0;
function test3() {
var o = {};
with (o) {
y = (o.y = 42);
}
}
test3();
shouldBe('y', '42');
// Now also throwing in functions in a mix. Also tests 'this' computation
z = "FAIL - wrong scope bound?";
o = {};
function test4() {
var o = {fn: null /* so it goes there*/ };
with (o) {
fn = function() {
this.z = "FAIL - wrong this?";
return "PASS";
}
z = fn();
}
}
test4();
shouldBe('z', '"PASS"');
// Here, we are making sure we call toObject on base of foo[bar] before calling toString on index
var b = undefined; // so toObject fails
index = { toString: function() { throw "FAIL"; } }
caught = false;
theCatch = null;
try {
b[index];
} catch (e) {
caught = true;
theCatch = e;
}
shouldBeTrue('caught');
shouldBeTrue('theCatch != "FAIL"');
// Now make sure that toString on LHS gets called before evaluating RHS.
index = { toString: function() { throw "PASS"; } }
b = {}
function rhs() {
throw "FAIL";
}
caught = false;
theCatch = null;
try {
b[index] = rhs();
} catch (e) {
caught = true;
theCatch = e;
}
shouldBeTrue('caught');
shouldBe('theCatch', "'PASS'");
// Make sure all the steps (other than the toObject, which we can't trace w/o failing) are in order for foo[bar]
out = "";
function getBase() {
out += "1";
return {};
}
function getIndex() {
out += "2";
o = { toString: function() { out += "3"; return "42"; } };
return o;
}
function getRHS() {
out += "4";
return "answer";
}
getBase()[getIndex()] = getRHS();
shouldBe("out", "1234");
// Like assignment, 'var' binds the scope before doing evaluation
// So make sure it gets it right. eval can't inject a new variable here, so use catch/with capture.
function varScopeTest1() {
var capturer = { captureInject: function(val) { this.local = val; return "ret:" + val; } }
with (capturer) {
// This should write to the activation's local.
var local = captureInject(42);
}
if (local != "ret:42")
return "FAIL";
if (capturer.local != 42)
return "FAIL #2";
return "PASS";
}
shouldBe("varScopeTest1()", "'PASS'");
debug("Done.");
// kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on;
|