function truth() { return true; } noInline(truth); function assert(cond) { if (!cond) throw new Error("broke assertion"); } noInline(assert); function shouldThrowInvalidConstAssignment(f) { var threw = false; try { f(); } catch(e) { if (e.name.indexOf("TypeError") !== -1 && e.message.indexOf("readonly") !== -1) threw = true; } assert(threw); } noInline(shouldThrowInvalidConstAssignment); // Tests const NUM_LOOPS = 100; ;(function() { function foo() { const x = 40; with ({x : 100}) { assert(x === 100); } with ({y : 100}) { assert(x === 40); } } noInline(foo); function bar() { const x = 40; function capX() { return x; } with ({x : 100}) { if (truth()) { const x = 50; const capX = function() { return x; } assert(x === 50); assert(capX() === x); } assert(x === 100); assert(capX() === 40); } with ({y : 100}) { if (truth()) { const x = 50; const capX = function() { return x; } assert(x === 50); assert(capX() === x); } assert(x === 40); assert(capX() === 40); } } noInline(bar); function baz() { const x = 40; function capX() { return x; } with ({x : 100}) { if (truth()) { const x = 50; assert(x === 50); } assert(x === 100); assert(capX() === 40); } with ({y : 100}) { if (truth()) { const x = 50; assert(x === 50); } assert(x === 40); assert(capX() === 40); } } noInline(baz); for (let i = 0; i < NUM_LOOPS; i++) { foo(); bar(); baz(); } })(); ;(function() { function foo() { const x = 40; with ({x : 100}) { assert(x === 100); x = 20; assert(x === 20); } assert(x === 40); with ({y : 100}) { assert(x === 40); x = 100; } } for (let i = 0; i < NUM_LOOPS; ++i) { shouldThrowInvalidConstAssignment(foo); } })();