function assert(b) { if (!b) throw new Error("Bad assertion."); } function test(f, ...args) { for (let i = 0; i < 500; i++) f(...args); } function falsey() { return false; } noInline(falsey); function truthy() { return true; } noInline(truthy); test(function() { var a; assert(a === undefined); { function a() { return 20; } } assert(a() === 20); }); test(function(a) { var a; assert(a === undefined); { function a() { return 20; } } assert(a === undefined); }); test(function({a}) { var a; assert(a === undefined); { function a() { return 20; } } assert(a === undefined); }, {}); test(function() { let a; assert(a === undefined); { function a() { return 20; } } assert(a === undefined); }); test(function() { assert(a === undefined); function foo() { return a(); } { function a() { return 20; } } assert(a() === 20); assert(foo() === 20); }); test(function(a = 30) { assert(a === 30); function foo() { return a; } assert(foo() === 30); { function a() { return 20; } assert(a() === 20); assert(foo() === 30); } assert(a === 30); assert(foo() === 30); }); test(function() { let x = 15; assert(x === 15); assert(a === undefined); { let x = {x: 20}; function a() { return x; } assert(a() === x); assert(a().x === 20); } assert(a().x === 20); assert(x === 15); }); test(function() { let x = 15; assert(x === 15); assert(a === undefined); let f; { let x = {x: 20}; assert(a() === x); assert(a().x === 20); function a() { throw new Error; } function a() { return x; } f = a; } assert(a().x === 20); assert(x === 15); assert(f().x === 20); }); test(function() { let x = 15; let f; assert(x === 15); assert(a === undefined); assert(f === undefined); { function a() { return f; } f = a; } assert(x === 15); assert(f() === f); }); test(function() { function a() { return 20; } let f = a; assert(a() === 20); { function a() { return 25; } assert(a() === 25); } assert(f() === 20); assert(a() === 25); }); test(function() { assert(f === undefined); for (let i = 0; i < 10; i++) { function f() { return i; } assert(f() === i); } assert(f() === 9); }); test(function() { assert(f === undefined); let nums = [0, 1, 2, 3]; for (let i of nums) { function f() { return i; } assert(f() === i); } assert(f() === 3); }); test(function() { assert(f === undefined); let obj = {0:0, 1:1, 2:2, 3:3}; for (let i in obj) { function f() { return i; } assert(f() === i); } assert(f() === "3"); }); test(function() { assert(f === undefined); let nums = [0, 1, 2, 3]; let funcs = [] for (let i of nums) { function f() { return i; } funcs.push(f); assert(f() === i); } assert(f() === 3); assert(funcs.length === nums.length); for (let i = 0; i < funcs.length; i++) { assert(funcs[i]() === nums[i]); } }); test(function() { assert(f === undefined); try { throw new Error("foo"); } catch(e) { function f() { return 20; } } assert(f() === 20); }); test(function() { assert(f === undefined); try { ; } catch(e) { function f() { return 20; } } assert(f === undefined); }); test(function() { assert(foo === undefined); if (falsey()) { function foo() { return 20; } } assert(foo === undefined); }); test(function() { assert(foo === undefined); if (falsey()) function foo() { return 20; } assert(foo === undefined); }); test(function() { assert(foo === undefined); if (truthy()) { function foo() { return 20; } } assert(foo() === 20); }); test(function() { assert(foo === undefined); while (truthy()) { assert(foo() === 20); break; function foo() { return 20; } } assert(foo === undefined); }); test(function() { assert(foo === undefined); while (truthy()) { assert(foo() === 20); function foo() { return 20; } break; } assert(foo() === 20); }); test(function() { function bar() { return foo; } assert(foo === undefined); assert(bar() === undefined); while (truthy()) { break; function foo() { return 20; } } assert(foo === undefined); assert(bar() === undefined); }); test(function() { function bar() { return foo; } assert(foo === undefined); assert(bar() === undefined); while (truthy()) { function foo() { return 20; } break; } assert(foo() === 20); assert(bar()() === 20); }); test(function() { function bar() { return foo; } assert(foo === undefined); assert(bar() === undefined); while (falsey()) { function foo() { return 20; } } assert(foo === undefined); assert(bar() === undefined); }); test(function() { var a = "a"; assert(a === "a"); { let b = 1; assert(a === "a"); { let c = 2; assert(a === "a"); { let d = 3; function a() { return b + c+ d; } assert(a() === 6); } assert(a() === 6); } assert(a() === 6); } assert(a() === 6); }); test(function() { assert(foo === undefined); switch(1) { case 0: function foo() { return 20; } break; case 1: assert(foo() === 20); break; } assert(foo === undefined); }); test(function() { assert(foo === undefined); switch(1) { case 1: assert(foo() === 20); case 0: function foo() { return 20; } break; } assert(foo() === 20); }); test(function() { assert(foo === undefined); switch(1) { case 0:{ function foo() { return 20; } break; } } assert(foo === undefined); }); test(function() { assert(foo === undefined); switch(0) { case 0:{ function foo() { return 20; } break; } } assert(foo() === 20); }); test(function() { assert(foo === undefined); switch(0) { case 0: function foo() { return bar; } break; case 1: let bar = 20; break; } let threw = false; try { foo(); } catch (e) { assert(e instanceof ReferenceError); threw = true; } assert(threw); }); test(function() { assert(foo === undefined); switch(0) { case 0: function foo() { return bar; } case 1: let bar = 20; break; } assert(foo() === 20); }); test(function() { assert(foo === undefined); switch(1) { case 0: function foo() { return bar; } case 1: let bar = 20; assert(foo() === 20); break; } assert(foo === undefined); }); test(function() { function capFoo1() { return foo; } assert(foo === undefined); assert(capFoo1() === undefined); switch(1) { case 0: function foo() { return bar; } function capFoo2() { return foo; } case 1: let bar = 20; assert(foo() === 20); assert(capFoo1() === undefined); assert(capFoo2() === foo); assert(capFoo2()() === 20); break; } assert(foo === undefined); }); test(function() { assert(foo === undefined); switch(1) { case 1: let bar = 20; assert(foo() === 20); case 0: function foo() { return bar; } } assert(foo() === 20); }); test(function(a) { assert(a === 25); switch(1) { case 0: function a() { return bar; } case 1: let bar = 20; assert(a() === 20); break; } assert(a === 25); }, 25); test(function() { let a = 25; assert(a === 25); switch(1) { case 0: function a() { return bar; } case 1: let bar = 20; assert(a() === 20); break; } assert(a === 25); }); test(function() { const a = 25; assert(a === 25); switch(1) { case 0: function a() { return bar; } case 1: let bar = 20; assert(a() === 20); break; } assert(a === 25); }); test(function() { let foo = {}; class a { constructor() { return foo; } } assert(new a === foo); switch(1) { case 0: function a() { return bar; } case 1: let bar = 20; assert(a() === 20); break; } assert(new a === foo); }); test(function() { assert(f === undefined); { if (true) function f() { return 20; } assert(f() === 20); } assert(f() === 20); }); test(function() { assert(f === undefined); { if (false) function f() { return 20; } assert(f === undefined); } assert(f === undefined); }); test(function() { var x; assert(f === undefined); if (true) if (true) if (true) function f() { return 20; } assert(f() === 20); }); test(function() { var x; assert(f === undefined); { if (true) if (false) if (true) function f() { return 20; } } assert(f === undefined); }); test(function() { var x; assert(f === undefined); { while (false) while (false) if (true) function f() { return 20; } } assert(f === undefined); }); test(function() { assert(f === undefined); var f = 20; assert(f === 20); while (false) while (false) if (true) function f() { return 20; } assert(f === 20); }); test(function() { assert(f === undefined); var f = 20; assert(f === 20); var i = 2; { while (i-- > 0) while (i-- > 0) if (true) function f() { return 20; } } assert(f() === 20); }); test(function() { assert(f === undefined); var f = 20; assert(f === 20); var i = 2; { while (i-- > 0) while (i-- > 0) if (false) function f() { return 20; } } assert(f === 20); }); test(function() { assert(f === undefined); var f = 20; assert(f === 20); var i = 2; { while (i-- > 0) while (i-- > 0) if (false) function f() { return 20; } else function f() { return 30; } } assert(f() === 30); }); test(function() { assert(f === undefined); if (true) { label: function f() { return 20; } } assert(f() === 20); }); test(function() { assert(f === undefined); if (true) { label: label2: label3: function f() { return 20; } } assert(f() === 20); }); test(function() { assert(a === undefined); assert(b === undefined); assert(c === undefined); assert(d === undefined); assert(e === undefined); assert(f === undefined); assert(g === undefined); assert(h === undefined); assert(i === undefined); assert(j === undefined); assert(k === undefined); assert(l === undefined); assert(m === undefined); assert(n === undefined); assert(o === undefined); assert(p === undefined); assert(q === undefined); assert(r === undefined); assert(s === undefined); assert(t === undefined); assert(u === undefined); assert(v === undefined); assert(w === undefined); assert(x === undefined); assert(y === undefined); assert(z === undefined); { function a() { } function b() { } function c() { } function d() { } function e() { } function f() { } function g() { } function h() { } function i() { } function j() { } function k() { } function l() { } function m() { } function n() { } function o() { } function p() { } function q() { } function r() { } function s() { } function t() { } function u() { } function v() { } function w() { } function x() { } function y() { } function z() { } } assert(typeof a === "function"); assert(typeof b === "function"); assert(typeof c === "function"); assert(typeof d === "function"); assert(typeof e === "function"); assert(typeof f === "function"); assert(typeof g === "function"); assert(typeof h === "function"); assert(typeof i === "function"); assert(typeof j === "function"); assert(typeof k === "function"); assert(typeof l === "function"); assert(typeof m === "function"); assert(typeof n === "function"); assert(typeof o === "function"); assert(typeof p === "function"); assert(typeof q === "function"); assert(typeof r === "function"); assert(typeof s === "function"); assert(typeof t === "function"); assert(typeof u === "function"); assert(typeof v === "function"); assert(typeof w === "function"); assert(typeof x === "function"); assert(typeof y === "function"); assert(typeof z === "function"); }); test(function() { function outer() { return f; } assert(outer() === undefined); { assert(outer() === undefined); assert(f() === 2); f = 100 assert(outer() === undefined); function f() { return 1 } assert(outer() === 100); f = 200 assert(outer() === 100); // 100 function f() { return 2 } assert(outer() === 200); } }); for (let i = 0; i < 500; i++) assert(foo() === 25); function foo() { return 20; } { function foo() { return 25; } assert(foo() === 25); } assert(foo() === 25); for (let i = 0; i < 500; i++) assert(bar() === "bar2"); function bar() { return "bar1"; } if (falsey()) { { if (falsey()) { function bar() { return "bar2"; } } } } assert(bar() === "bar2"); for (let i = 0; i < 500; i++) assert(baz() === "baz2"); function baz() { return "baz1"; } while (falsey()) { if (falsey()) { function baz() { return "baz2"; } } } assert(baz() === "baz2");