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;