From 16b7ff972c5fa7b2937f64b1708204aabfd3f00a Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Mon, 19 Jan 2015 08:54:04 +1100 Subject: [PATCH] split up tdz into an optional transformer until it has a better implementation - fixes #527 --- lib/6to5/transformation/transform.js | 1 + .../transformers/es6-let-scoping.js | 47 +------------------ .../optional-block-scoping-tdz.js | 47 +++++++++++++++++++ .../temporal-dead-zone/options.json | 3 +- 4 files changed, 52 insertions(+), 46 deletions(-) create mode 100644 lib/6to5/transformation/transformers/optional-block-scoping-tdz.js diff --git a/lib/6to5/transformation/transform.js b/lib/6to5/transformation/transform.js index 2a5cbb26a2..e0238cc5f0 100644 --- a/lib/6to5/transformation/transform.js +++ b/lib/6to5/transformation/transform.js @@ -79,6 +79,7 @@ _.each({ constants: require("./transformers/es6-constants"), letScoping: require("./transformers/es6-let-scoping"), + blockScopingTDZ: require("./transformers/optional-block-scoping-tdz"), _blockHoist: require("./transformers/_block-hoist"), diff --git a/lib/6to5/transformation/transformers/es6-let-scoping.js b/lib/6to5/transformation/transformers/es6-let-scoping.js index 5a9c829b31..b7d7f5fbb2 100644 --- a/lib/6to5/transformation/transformers/es6-let-scoping.js +++ b/lib/6to5/transformation/transformers/es6-let-scoping.js @@ -84,7 +84,7 @@ function LetScoping(loopParent, block, parent, scope, file) { this.outsideLetReferences = {}; this.hasLetReferences = false; - this.letReferences = {}; + this.letReferences = block._letReferences = {}; this.body = []; } @@ -98,7 +98,6 @@ LetScoping.prototype.run = function () { block._letDone = true; var needsClosure = this.getLetReferences(); - this.checkTDZ(); // this is a block within a `Function/Program` so we can safely leave it be if (t.isFunction(this.parent) || t.isProgram(this.block)) return; @@ -113,48 +112,6 @@ 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; - var referenceLoc = node.loc; - - if (!declaredLoc || !referenceLoc) return; - - // does this reference appear on a line before the declaration? - var before = referenceLoc.start.line < declaredLoc.start.line; - - if (referenceLoc.start.line === declaredLoc.start.line) { - // this reference appears on the same line - // check it appears before the declaration - before = referenceLoc.start.col < declaredLoc.start.col; - } - - if (before) { - throw state.file.errorWithNode(node, "Temporal dead zone - accessing a variable before it's initialized"); - } - } - }, this.scope, state); -}; - /** * Description */ @@ -179,7 +136,7 @@ LetScoping.prototype.remap = function () { var uid = file.generateUidIdentifier(ref.name, scope).name; ref.name = uid; - remaps[key] = { + remaps[key] = remaps[uid] = { node: ref, uid: uid }; diff --git a/lib/6to5/transformation/transformers/optional-block-scoping-tdz.js b/lib/6to5/transformation/transformers/optional-block-scoping-tdz.js new file mode 100644 index 0000000000..22a9474197 --- /dev/null +++ b/lib/6to5/transformation/transformers/optional-block-scoping-tdz.js @@ -0,0 +1,47 @@ +var traverse = require("../../traverse"); +var t = require("../../types"); + +exports.optional = true; + +exports.Loop +exports.Program = +exports.BlockStatement = function (node, parent, scope, context, file) { + var letRefs = node._letReferences; + if (!letRefs) return; + + var state = { + letRefs: letRefs, + file: file + }; + + traverse(node, { + 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; + var referenceLoc = node.loc; + + if (!declaredLoc || !referenceLoc) return; + + // does this reference appear on a line before the declaration? + var before = referenceLoc.start.line < declaredLoc.start.line; + + if (referenceLoc.start.line === declaredLoc.start.line) { + // this reference appears on the same line + // check it appears before the declaration + before = referenceLoc.start.col < declaredLoc.start.col; + } + + if (before) { + throw state.file.errorWithNode(node, "Temporal dead zone - accessing a variable before it's initialized"); + } + } + }, scope, state); +}; diff --git a/test/fixtures/transformation/es6-let-scoping/temporal-dead-zone/options.json b/test/fixtures/transformation/es6-let-scoping/temporal-dead-zone/options.json index faba38c879..bcd3d8f6e2 100644 --- a/test/fixtures/transformation/es6-let-scoping/temporal-dead-zone/options.json +++ b/test/fixtures/transformation/es6-let-scoping/temporal-dead-zone/options.json @@ -1,3 +1,4 @@ { - "throws": "Temporal dead zone - accessing a variable before it's initialized" + "throws": "Temporal dead zone - accessing a variable before it's initialized", + "optional": ["blockScopingTDZ"] }