diff --git a/packages/babel-traverse/src/scope/index.js b/packages/babel-traverse/src/scope/index.js index 4a5022d46ab9..5c5395877291 100644 --- a/packages/babel-traverse/src/scope/index.js +++ b/packages/babel-traverse/src/scope/index.js @@ -161,6 +161,8 @@ export default class Scope { this.parentBlock = path.parent; this.block = path.node; this.path = path; + + this.labels = new Map(); } /** @@ -218,7 +220,7 @@ export default class Scope { do { uid = this._generateUid(name, i); i++; - } while (this.hasBinding(uid) || this.hasGlobal(uid) || this.hasReference(uid)); + } while (this.hasLabel(uid) || this.hasBinding(uid) || this.hasGlobal(uid) || this.hasReference(uid)); let program = this.getProgramParent(); program.references[uid] = true; @@ -426,9 +428,21 @@ export default class Scope { return t.callExpression(file.addHelper(helperName), args); } + hasLabel(name: string) { + return !!this.getLabel(name); + } + + getLabel(name: string) { + return this.labels.get(name); + } + + registerLabel(path: NodePath) { + this.labels.set(path.node.label.name, path); + } + registerDeclaration(path: NodePath) { if (path.isLabeledStatement()) { - this.registerBinding("label", path); + this.registerLabel(path); } else if (path.isFunctionDeclaration()) { this.registerBinding("hoisted", path.get("id"), path); } else if (path.isVariableDeclaration()) { diff --git a/packages/babel-traverse/test/scope.js b/packages/babel-traverse/test/scope.js index 0df9e8fbf251..332a3eabd9b9 100644 --- a/packages/babel-traverse/test/scope.js +++ b/packages/babel-traverse/test/scope.js @@ -38,5 +38,27 @@ describe("scope", function () { it("purity", function () { assert.ok(getPath("({ x: 1 })").get("body")[0].get("expression").isPure()); }); + + test("label", function () { + assert.strictEqual(getPath("foo: { }").scope.getBinding("foo"), undefined); + assert.strictEqual(getPath("foo: { }").scope.getLabel("foo").type, "LabeledStatement"); + assert.strictEqual(getPath("foo: { }").scope.getLabel("toString"), undefined); + + assert.strictEqual(getPath(` + foo: { } + `).scope.generateUid("foo"), "_foo"); + }); + + test("generateUid collision check with labels", function () { + assert.strictEqual(getPath(` + _foo: { } + `).scope.generateUid("foo"), "_foo2"); + + assert.strictEqual(getPath(` + _foo: { } + _foo1: { } + _foo2: { } + `).scope.generateUid("foo"), "_foo3"); + }); }); });