blob: cdf1a57a5bf87cf3bd7004b90ae25dca83f540a5 [file] [log] [blame]
"use strict";
function truth() {
return true;
}
noInline(truth);
function assert(cond) {
if (!cond)
throw new Error("broke assertion");
}
noInline(assert);
function shouldThrowTDZ(func) {
var hasThrown = false;
try {
func();
} catch(e) {
if (e.name.indexOf("ReferenceError") !== -1)
hasThrown = true;
}
assert(hasThrown);
}
noInline(shouldThrowTDZ);
// Test cases
const NUM_LOOPS = 1000;
const SHORT_LOOPS = 100;
;(function() {
function foo() {
x;
const x = 20;
}
function bar() {
const x = x;
}
function baz() {
const {x: prop, y: prop2} = {x: prop};
}
function jaz() {
const {x: prop, y: prop2} = {x: 20, y: prop};
}
for (var i = 0; i < NUM_LOOPS; i++) {
shouldThrowTDZ(foo);
shouldThrowTDZ(bar);
shouldThrowTDZ(baz);
shouldThrowTDZ(jaz);
}
})();
;(function() {
function foo() {
x;
const x = 20;
function captureX() { return x; }
}
function bar() {
captureX();
const x = 20;
function captureX() { return x; }
}
for (var i = 0; i < NUM_LOOPS; i++) {
shouldThrowTDZ(foo);
shouldThrowTDZ(bar);
}
})();
;(function() {
function foo() {
if (truth()) {
const x = 20;
assert(x === 20);
}
x;
const x = 20;
}
for (var i = 0; i < NUM_LOOPS; i++) {
shouldThrowTDZ(foo);
}
})();
;(function() {
function foo() {
if (truth()) {
const y = 20;
const captureY = function() { return y; }
assert(y === 20);
x;
}
const x = 20;
const y = 40;
}
for (var i = 0; i < NUM_LOOPS; i++) {
shouldThrowTDZ(foo);
}
})();
;(function() {
function foo() {
if (truth()) {
const y = 20;
const x = 40;
const captureAll = function() { return x + y; }
assert(y === 20);
assert(x === 40);
assert(captureAll() === 60);
}
tdz;
const tdz = 20;
}
for (var i = 0; i < NUM_LOOPS; i++) {
shouldThrowTDZ(foo);
}
})();
;(function() {
function foo() {
if (truth()) {
const y = 20;
const x = 40;
const captureAll = function() { return x + y + tdz; }
assert(y === 20);
assert(x === 40);
}
tdz;
const tdz = 20;
}
for (var i = 0; i < NUM_LOOPS; i++) {
shouldThrowTDZ(foo);
}
})();
;(function() {
function foo() {
x = 10;
const x = 20;
}
for (var i = 0; i < NUM_LOOPS; i++) {
shouldThrowTDZ(foo);
}
})();
;(function() {
function foo() {
x = 10;
const x = 20;
function cap() { return x; }
}
function bar() {
captureX();
const x = 20;
function captureX() { return x; }
}
for (var i = 0; i < NUM_LOOPS; i++) {
shouldThrowTDZ(foo);
shouldThrowTDZ(bar);
}
})();
;(function() {
function foo() {
if (!truth()) {
y;
assert(false);
}
const y = undefined;
assert(y === undefined);
if (truth()) {
x;
}
const x = undefined;
}
for (var i = 0; i < NUM_LOOPS; i++) {
shouldThrowTDZ(foo);
}
})();
;(function() {
function foo() {
eval("x;");
const x = 20;
}
function bar() {
function captureX() { return x; }
eval("captureX();");
const x = 20;
}
function baz() {
function captureX() { return x; }
function other() { return captureX; }
other()();
const x = 20;
}
for (var i = 0; i < SHORT_LOOPS; i++) {
shouldThrowTDZ(foo);
shouldThrowTDZ(bar);
shouldThrowTDZ(baz);
}
})();
;(function() {
function foo() {
const y = 40;
eval("y; x;");
const x = 20;
}
for (var i = 0; i < 1; i++) {
shouldThrowTDZ(foo);
}
})();
;(function() {
function foo() {
const x = 20;
const y = 40;
assert(eval("x;") === 20);
if (truth()) {
assert(eval("eval('y');") === 40);
eval("eval('x');");
const x = 40;
}
}
for (var i = 0; i < SHORT_LOOPS; i++) {
shouldThrowTDZ(foo);
}
})();
// FunctionResolveNode
;(function() {
function foo() {
function captureX() { return x; }
x();
const x = function() { return 20; };
}
function bar() {
x();
let x = function() { return 20; };
}
for (var i = 0; i < NUM_LOOPS; i++) {
shouldThrowTDZ(foo);
shouldThrowTDZ(bar);
}
})();
// TypeofResolveNode
;(function() {
function foo() {
function captureX() { return x; }
typeof x;
const x = function() { return 20; };
}
function bar() {
typeof x;
const x = function() { return 20; };
}
for (var i = 0; i < NUM_LOOPS; i++) {
shouldThrowTDZ(foo);
shouldThrowTDZ(bar);
}
})();
// ReadModifyResolveNode
;(function() {
function foo() {
function captureX() { return x; }
x++;
const x = 20;
}
function bar() {
x--;
const x = 30;
}
function baz() {
x *= 40;
const x = 30;
}
function kaz() {
function captureX() { return x; }
x /= 20;
const x = 20;
}
function haz() {
function captureX() { return x; }
--x;
const x = 20;
}
function jaz() {
--x;
const x = 30;
}
for (var i = 0; i < NUM_LOOPS; i++) {
shouldThrowTDZ(foo);
shouldThrowTDZ(bar);
shouldThrowTDZ(baz);
shouldThrowTDZ(kaz);
shouldThrowTDZ(haz);
shouldThrowTDZ(jaz);
}
})();
;(function() {
function foo(x) {
const y = 50;
let result = null;
switch(x) {
case 10:
const y = 40;
assert(y === 40);
case 20:
y += 1;
assert(y === 41);
result = y;
break;
default:
result = x;
break;
}
assert(y === 50);
return result;
}
function bar(x) {
const y = 50;
let result = null;
switch(x) {
case 10:
const y = 40;
assert(y === 40);
case 20:
const capY = function() { return y; }
y += 1;
assert(y === 41);
result = y;
break;
default:
result = x;
break;
}
assert(y === 50);
return result;
}
function baz(x) {
const y = 50;
let result = null;
switch(x) {
case 10:
const y = 40;
assert(y === 40);
case 20:
let inc = function() { y += 1; }
inc();
assert(y === 41);
result = y;
break;
default:
result = x;
break;
}
assert(y === 50);
return result;
}
for (var i = 0; i < NUM_LOOPS; i++) {
shouldThrowTDZ(function() { foo(20); });
shouldThrowTDZ(function() { bar(20); });
shouldThrowTDZ(function() { baz(20); });
}
})();
;(function() {
function foo() {
[x] = [1];
const x = null;
}
function boo() {
[x] = [1];
const x = 20;
function capX() { return x; }
}
function bar() {
({a, p: y} = {a: 100, p: 40});
const y = 40;
}
function zar() {
({a, p: y} = {a: 100, p: 40});
const y = 10;
function capY() { return y; }
}
function baz() {
({a, p: {y}} = {a: 100, p: {p: {y: 40}}});
const y = 100;
}
function jaz() {
({y} = {});
const y = null;
}
for (var i = 0; i < NUM_LOOPS; i++) {
shouldThrowTDZ(foo);
shouldThrowTDZ(boo);
shouldThrowTDZ(bar);
shouldThrowTDZ(zar);
shouldThrowTDZ(baz);
shouldThrowTDZ(jaz);
}
})();