test_closure.js (4347B)
1 function assert(actual, expected, message) { 2 if (arguments.length == 1) 3 expected = true; 4 5 if (actual === expected) 6 return; 7 8 if (actual !== null && expected !== null 9 && typeof actual == 'object' && typeof expected == 'object' 10 && actual.toString() === expected.toString()) 11 return; 12 13 throw Error("assertion failed: got |" + actual + "|" + 14 ", expected |" + expected + "|" + 15 (message ? " (" + message + ")" : "")); 16 } 17 18 // load more elaborate version of assert if available 19 try { __loadScript("test_assert.js"); } catch(e) {} 20 21 /*----------------*/ 22 23 var log_str = ""; 24 25 function log(str) 26 { 27 log_str += str + ","; 28 } 29 30 function f(a, b, c) 31 { 32 var x = 10; 33 log("a="+a); 34 function g(d) { 35 function h() { 36 log("d=" + d); 37 log("x=" + x); 38 } 39 log("b=" + b); 40 log("c=" + c); 41 h(); 42 } 43 g(4); 44 return g; 45 } 46 47 var g1 = f(1, 2, 3); 48 g1(5); 49 50 assert(log_str, "a=1,b=2,c=3,d=4,x=10,b=2,c=3,d=5,x=10,", "closure1"); 51 52 function test_closure1() 53 { 54 function f2() 55 { 56 var val = 1; 57 58 function set(a) { 59 val = a; 60 } 61 function get(a) { 62 return val; 63 } 64 return { "set": set, "get": get }; 65 } 66 67 var obj = f2(); 68 obj.set(10); 69 var r; 70 r = obj.get(); 71 assert(r, 10, "closure2"); 72 } 73 74 function test_closure2() 75 { 76 var expr_func = function myfunc1(n) { 77 function myfunc2(n) { 78 return myfunc1(n - 1); 79 } 80 if (n == 0) 81 return 0; 82 else 83 return myfunc2(n); 84 }; 85 var r; 86 r = expr_func(1); 87 assert(r, 0, "expr_func"); 88 } 89 90 function test_closure3() 91 { 92 function fib(n) 93 { 94 if (n <= 0) 95 return 0; 96 else if (n == 1) 97 return 1; 98 else 99 return fib(n - 1) + fib(n - 2); 100 } 101 102 var fib_func = function fib1(n) 103 { 104 if (n <= 0) 105 return 0; 106 else if (n == 1) 107 return 1; 108 else 109 return fib1(n - 1) + fib1(n - 2); 110 }; 111 112 assert(fib(6), 8, "fib"); 113 assert(fib_func(6), 8, "fib_func"); 114 } 115 116 function test_arrow_function() 117 { 118 "use strict"; 119 120 function f1() { 121 return (() => arguments)(); 122 } 123 function f2() { 124 return (() => this)(); 125 } 126 function f3() { 127 return (() => eval("this"))(); 128 } 129 function f4() { 130 return (() => eval("new.target"))(); 131 } 132 var a; 133 134 a = f1(1, 2); 135 assert(a.length, 2); 136 assert(a[0] === 1 && a[1] === 2); 137 138 assert(f2.call("this_val") === "this_val"); 139 assert(f3.call("this_val") === "this_val"); 140 assert(new f4() === f4); 141 142 var o1 = { f() { return this; } }; 143 var o2 = { f() { 144 return (() => eval("super.f()"))(); 145 } }; 146 o2.__proto__ = o1; 147 148 assert(o2.f() === o2); 149 } 150 151 function test_with() 152 { 153 var o1 = { x: "o1", y: "o1" }; 154 var x = "local"; 155 eval('var z="var_obj";'); 156 assert(z === "var_obj"); 157 with (o1) { 158 assert(x === "o1"); 159 assert(eval("x") === "o1"); 160 var f = function () { 161 o2 = { x: "o2" }; 162 with (o2) { 163 assert(x === "o2"); 164 assert(y === "o1"); 165 assert(z === "var_obj"); 166 assert(eval("x") === "o2"); 167 assert(eval("y") === "o1"); 168 assert(eval("z") === "var_obj"); 169 assert(eval('eval("x")') === "o2"); 170 } 171 }; 172 f(); 173 } 174 } 175 176 function test_eval_closure() 177 { 178 var tab; 179 180 tab = []; 181 for(let i = 0; i < 3; i++) { 182 eval("tab.push(function g1() { return i; })"); 183 } 184 for(let i = 0; i < 3; i++) { 185 assert(tab[i]() === i); 186 } 187 188 tab = []; 189 for(let i = 0; i < 3; i++) { 190 let f = function f() { 191 eval("tab.push(function g2() { return i; })"); 192 }; 193 f(); 194 } 195 for(let i = 0; i < 3; i++) { 196 assert(tab[i]() === i); 197 } 198 } 199 200 function test_eval_const() 201 { 202 const a = 1; 203 var success = false; 204 var f = function () { 205 eval("a = 1"); 206 }; 207 try { 208 f(); 209 } catch(e) { 210 success = (e instanceof TypeError); 211 } 212 assert(success); 213 } 214 215 test_closure1(); 216 test_closure2(); 217 test_closure3(); 218 test_arrow_function(); 219 test_with(); 220 test_eval_closure(); 221 test_eval_const();