implement block scoping TDZ

This commit is contained in:
Sebastian McKenzie
2015-01-18 21:26:02 +11:00
parent ecfd5fadc6
commit 7c4701716c
3 changed files with 51 additions and 3 deletions

View File

@@ -57,6 +57,7 @@ exports.Loop = function (node, parent, scope, context, file) {
}
};
exports.Program =
exports.BlockStatement = function (block, parent, scope, context, file) {
if (!t.isLoop(parent)) {
var letScoping = new LetScoping(false, block, parent, scope, file);
@@ -95,10 +96,12 @@ LetScoping.prototype.run = function () {
if (block._letDone) return;
block._letDone = true;
// this is a block within a `Function` so we can safely leave it be
if (t.isFunction(this.parent)) return;
var needsClosure = this.getLetReferences();
this.checkTDZ();
// this is a block within a `Function` so we can safely leave it be
if (t.isFunction(this.parent) || t.isProgram(this.block)) return;
if (needsClosure) {
this.needsClosure();
} else {
@@ -106,6 +109,46 @@ LetScoping.prototype.run = function () {
}
};
/**
* Description
*/
LetScoping.prototype.checkTDZ = function () {
var state = {
letRefs: this.letReferences,
file: this.file
};
traverse(this.block, {
enter: function (node, parent, scope, context, state) {
if (!t.isIdentifier(node)) return;
if (!t.isReferenced(node, parent)) return;
var declared = state.letRefs[node.name];
if (!declared) return;
// declared node is different in this scope
if (scope.get(node.name, true) !== declared) return;
var declaredLoc = declared.loc.start;
var referenceLoc = node.loc.start;
// does this reference appear on a line before the declaration?
var before = referenceLoc.line < declaredLoc.line;
if (referenceLoc.line === declaredLoc.line) {
// this reference appears on the same line
// check it appears before the declaration
before = referenceLoc.col < declaredLoc.col;
}
if (before) {
throw state.file.errorWithNode(node, "Temporal dead zone - accessing a variable before it's initialized");
}
}
}, this.scope, state);
};
/**
* Description
*/

View File

@@ -0,0 +1,2 @@
qux;
let qux = 456;

View File

@@ -0,0 +1,3 @@
{
"throws": "Temporal dead zone - accessing a variable before it's initialized"
}