From 9e453f27ccfb8b9d2248c8f5aa0c66dd492312bd Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Mon, 5 Jun 2017 20:18:21 +0200 Subject: [PATCH 1/4] update gulp-git version It uses an old version of require.dir, which is broken in node 8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 018dc7b..e988796 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "gulp-eslint": "^1.1.1", "gulp-espower": "^1.0.2", "gulp-filter": "^3.0.1", - "gulp-git": "^1.6.1", + "gulp-git": "^2.4.0", "gulp-mocha": "^2.2.0", "gulp-plumber": "^1.0.1", "gulp-sourcemaps": "^1.6.0", From 8038b0e11a4f19e5a5574a4793ffda9a45fd5a7f Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Mon, 5 Jun 2017 20:18:56 +0200 Subject: [PATCH 2/4] update travis configuration to current LTS node versions --- .travis.yml | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index dd43cd3..921e6c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,17 +1,6 @@ sudo: false language: node_js node_js: - - "0.10" - - "0.11" - - "0.12" - - "iojs-1" - - "iojs-2" - - "iojs-3" - "4" -matrix: - allow_failures: - - node_js: - - "0.11" - - "iojs-1" - - "iojs-2" - - "iojs-3" + - "6" + - "8" From 1567e9d2111b1560cc777f608039a326298ffa5b Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Mon, 5 Jun 2017 20:19:14 +0200 Subject: [PATCH 3/4] fix incorrect javascript syntax --- test/references.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/references.js b/test/references.js index 5de08f7..c76cc6f 100644 --- a/test/references.js +++ b/test/references.js @@ -499,9 +499,9 @@ describe('References:', function() { 'let a; a = 0;', 'let a; [a] = [];', 'let a; [a = 1] = [];', - 'let a; ({a}) = {};', - 'let a; ({b: a}) = {};', - 'let a; ({b: a = 0}) = {};', + 'let a; ({a} = {});', + 'let a; ({b: a} = {});', + 'let a; ({b: a = 0} = {});', 'let a; for (a in []);', 'let a; for ([a] in []);', 'let a; for ([a = 0] in []);', From a406b35ba1d348ab3771f3a9b34a0b445f04abe7 Mon Sep 17 00:00:00 2001 From: Tobias Koppers Date: Tue, 6 Jun 2017 10:13:21 +0200 Subject: [PATCH 4/4] add reference to inner variable to Definition of class --- src/definition.js | 6 +++++- src/referencer.js | 27 +++++++++++++++------------ src/scope.js | 6 ++++-- test/es6-class.js | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 15 deletions(-) diff --git a/src/definition.js b/src/definition.js index faef938..8c8d338 100644 --- a/src/definition.js +++ b/src/definition.js @@ -28,7 +28,7 @@ import Variable from './variable'; * @class Definition */ export default class Definition { - constructor(type, name, node, parent, index, kind) { + constructor(type, name, node, parent, index, kind, inner) { /** * @member {String} Definition#type - type of the occurrence (e.g. "Parameter", "Variable", ...). */ @@ -53,6 +53,10 @@ export default class Definition { * @member {String?} Definition#kind - the kind of the declaration statement. */ this.kind = kind; + /** + * @member {Variable} Definition#inner - the reference to the inner scope variable. + */ + this.inner = inner; } } diff --git a/src/referencer.js b/src/referencer.js index bd81080..4f94e7e 100644 --- a/src/referencer.js +++ b/src/referencer.js @@ -233,17 +233,7 @@ export default class Referencer extends esrecurse.Visitor { } visitClass(node) { - if (node.type === Syntax.ClassDeclaration) { - this.currentScope().__define(node.id, - new Definition( - Variable.ClassName, - node.id, - node, - null, - null, - null - )); - } + var innerVariable; // FIXME: Maybe consider TDZ. this.visit(node.superClass); @@ -251,7 +241,7 @@ export default class Referencer extends esrecurse.Visitor { this.scopeManager.__nestClassScope(node); if (node.id) { - this.currentScope().__define(node.id, + innerVariable = this.currentScope().__define(node.id, new Definition( Variable.ClassName, node.id, @@ -261,6 +251,19 @@ export default class Referencer extends esrecurse.Visitor { this.visit(node.body); this.close(node); + + if (node.type === Syntax.ClassDeclaration) { + this.currentScope().__define(node.id, + new Definition( + Variable.ClassName, + node.id, + node, + null, + null, + null, + innerVariable + )); + } } visitProperty(node) { diff --git a/src/scope.js b/src/scope.js index 0e4d8c2..09dd3d4 100644 --- a/src/scope.js +++ b/src/scope.js @@ -352,11 +352,13 @@ export default class Scope { if (node) { variable.identifiers.push(node); } + + return variable; } __define(node, def) { if (node && node.type === Syntax.Identifier) { - this.__defineGeneric( + return this.__defineGeneric( node.name, this.set, this.variables, @@ -504,7 +506,7 @@ export class GlobalScope extends Scope { __defineImplicit(node, def) { if (node && node.type === Syntax.Identifier) { - this.__defineGeneric( + return this.__defineGeneric( node.name, this.implicit.set, this.implicit.variables, diff --git a/test/es6-class.js b/test/es6-class.js index 8c6ffac..dac5b7e 100644 --- a/test/es6-class.js +++ b/test/es6-class.js @@ -191,6 +191,47 @@ describe('ES6 class', function() { expect(scope.references[0].identifier.name).to.be.equal('shoe'); expect(scope.references[1].identifier.name).to.be.equal('Shoe'); }); + + it('reference in class', function() { + const ast = parse(` + class Foo { + constructor() { + Foo; + } + } + `); + + + const scopeManager = analyze(ast, {ecmaVersion: 6}); + expect(scopeManager.scopes).to.have.length(3); + + let scope = scopeManager.scopes[0]; + expect(scope.type).to.be.equal('global'); + expect(scope.block.type).to.be.equal('Program'); + expect(scope.isStrict).to.be.false; + expect(scope.variables).to.have.length(1); + expect(scope.variables[0].name).to.be.equal('Foo'); + expect(scope.variables[0].defs).to.have.length(1); + + let classDef = scope.variables[0].defs[0] + + scope = scopeManager.scopes[1]; + expect(scope.type).to.be.equal('class'); + expect(scope.block.type).to.be.equal('ClassDeclaration'); + expect(scope.isStrict).to.be.true; + expect(scope.variables).to.have.length(1); + expect(classDef.inner).to.be.equal(scope.variables[0]); + expect(scope.references).to.have.length(0); + + scope = scopeManager.scopes[2]; + expect(scope.type).to.be.equal('function'); + expect(scope.block.type).to.be.equal('FunctionExpression'); + expect(scope.isStrict).to.be.true; + expect(scope.variables).to.have.length(1); + expect(scope.variables[0].name).to.be.equal('arguments'); + expect(scope.references).to.have.length(1); + expect(scope.references[0].identifier.name).to.be.equal('Foo'); + }); }); // vim: set sw=4 ts=4 et tw=80 :