File indexing completed on 2024-04-28 15:28:39

0001 // Various evaluation order tests..
0002 
0003 // Argument list should be evaluated before checking whether functions is callable, etc.
0004 function test1() {
0005     function bad() {
0006         throw "PASS";
0007     }
0008 
0009     try {
0010         var f = 42;
0011         f(bad());
0012     } catch (e) {
0013         return e;
0014     }
0015 }
0016 
0017 shouldBe('test1()', '"PASS"');
0018 
0019 
0020 // Make sure we do toObject properly
0021 shouldThrow("var v = null; delete v.x;");
0022 
0023 // Left hand-side of an assignment should be bound as a reference before evaluating RHS, test #1
0024 x = 0;
0025 function test2() {
0026     x = eval("var x; 42;");
0027 }
0028 test2();
0029 
0030 shouldBe('x', '42');
0031 
0032 // Same, but using with and not eval.
0033 y = 0;
0034 
0035 function test3() {
0036     var o = {};
0037     with (o) {
0038         y = (o.y = 42);
0039     }
0040 }
0041 test3();
0042 shouldBe('y', '42');
0043 
0044 // Now also throwing in functions in a mix. Also tests 'this' computation
0045 z = "FAIL - wrong scope bound?";
0046 o = {};
0047 
0048 function test4() {
0049     var o = {fn: null /* so it goes there*/ };
0050     with (o) {
0051         fn = function() {
0052             this.z = "FAIL - wrong this?";
0053             return "PASS";
0054         }
0055 
0056         z = fn();
0057     }
0058 }
0059 test4();
0060 shouldBe('z', '"PASS"');
0061 
0062 // Here, we are making sure we call toObject on base of foo[bar] before calling toString on index
0063 var b = undefined; // so toObject fails
0064 index = { toString: function() { throw "FAIL"; } }
0065 
0066 caught   = false;
0067 theCatch = null;
0068 try {
0069     b[index];
0070 } catch (e) {
0071     caught  = true;
0072     theCatch = e;
0073 }
0074 
0075 shouldBeTrue('caught');
0076 shouldBeTrue('theCatch != "FAIL"');
0077 
0078 // Now make sure that toString on LHS gets called before evaluating RHS.
0079 index = { toString: function() { throw "PASS"; } }
0080 b     = {}
0081 function rhs() {
0082     throw "FAIL";
0083 }
0084 
0085 caught   = false;
0086 theCatch = null;
0087 try {
0088     b[index] = rhs();
0089 } catch (e) {
0090     caught  = true;
0091     theCatch = e;
0092 }
0093 
0094 shouldBeTrue('caught');
0095 shouldBe('theCatch', "'PASS'");
0096 
0097 // Make sure all the steps (other than the toObject, which we can't trace w/o failing) are in order for foo[bar]
0098 out = "";
0099 function getBase() {
0100     out += "1";
0101     return {};
0102 }
0103 
0104 function getIndex() {
0105     out += "2";
0106     o = { toString: function() { out += "3"; return "42"; } };
0107     return o;
0108 }
0109 
0110 function getRHS() {
0111     out += "4";
0112     return "answer";
0113 }
0114 
0115 getBase()[getIndex()] = getRHS();
0116 shouldBe("out", "1234");
0117 
0118 
0119 // Like assignment, 'var' binds the scope before doing evaluation
0120 // So make sure it gets it right. eval can't inject a new variable here, so use catch/with capture.
0121 function varScopeTest1() {
0122     var capturer = { captureInject: function(val) { this.local = val; return "ret:" + val; } }
0123 
0124     with (capturer) {
0125         // This should write to the activation's local.
0126         var local = captureInject(42);
0127     }
0128 
0129     if (local != "ret:42")
0130         return "FAIL";
0131 
0132     if (capturer.local != 42)
0133         return "FAIL #2";
0134 
0135     return "PASS";
0136 }
0137 
0138 shouldBe("varScopeTest1()", "'PASS'");
0139 
0140 debug("Done.");
0141 // kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on;