estools / escope

Escope: ECMAScript scope analyzer
BSD 2-Clause "Simplified" License
546 stars 77 forks source link

Add ES6 Support #33

Open Constellation opened 10 years ago

Constellation commented 10 years ago

Supporting ES6 block scopes and some special scopes (such as arraw function and method)

nzakas commented 10 years ago

Are you still going to do this? ESLint has a bug related to let scoping that could use this: https://github.com/eslint/eslint/issues/917

Constellation commented 10 years ago

Oh, OK. I'll work on it on weekend :)

Constellation commented 10 years ago

semantics in ES6 spec may be mature enough :)

nzakas commented 10 years ago

They are. I've documented it in my book: https://github.com/nzakas/understandinges6/blob/master/manuscript/01-The-Basics.md#block-bindings

jlongster commented 10 years ago

This would be awesome to have!

nzakas commented 10 years ago

Just checking in - any chance you're working on this? :)

Constellation commented 10 years ago

Hi @nzakas, Sorry for my further late reply.

I'm now gradually supporting ES6 in the tools, now escodegen supports ES6 Syntax completely. So, next, I'm planning to support ES6 in estraverse since it is used in the escope. Then, support scoping in escope.

Since there's significant difference between ES5 scopes and ES6 scopes, maybe I'll introduce ecmaVersion option.

nzakas commented 10 years ago

That sounds awesome!

elwayman02 commented 10 years ago

@Constellation what's the status on this? Is there anything we can do to help out? I'm working on trying to get an ES6-supported version of ESlint using the harmony branch of esprima, so my next step is to approach ES6 support in escope and estraverse. :)

Constellation commented 10 years ago

OK, so, let's start to support ES6. I'll start it with estraverse.

Constellation commented 10 years ago

Support ES6 traversing in estraverse. https://github.com/Constellation/estraverse/commit/19f7a5c5dbb7bcaca3226d3cd608e59dbea1a275

StoneCypher commented 10 years ago

This would really help for getting eslint running on jsx

sebmck commented 9 years ago

Any update on this? Definently keen to use this for 6to5. Reference 6to5/6to5#175

Constellation commented 9 years ago

Currently, we're investigating the ES6 spec and Esprima AST nodes. And We're now updating escodegen and estraverse. Does anyone knows the issue about them? I think estraverse now completely support ES6 syntax. If it's correct, my mental model of ES6 AST may be stable.

sebmck commented 9 years ago

Main issues you'll run into is implementing temporal dead zones. Default parameters have their own scope and you can't access let/const variables before they're initialised.

Constellation commented 9 years ago

Main issues you'll run into is implementing temporal dead zones. Default parameters have their own scope and you can't access let/const variables before they're initialised.

Nice, it's very useful information. And we need to consider destructuring assigned variables.

var { a, b, c } = obj;  // it materialize a, b, c variables.
Constellation commented 9 years ago

And we need to ensure,

for (let i = 0; i < 10; ++i) { console.log(i); }

scope behavior.

Constellation commented 9 years ago

We're now implementing scopes for ES6. But be careful, it's experimental and the behavior might be changed

Constellation commented 9 years ago

@sebmck:

Do you know the actual section in the ES6 draft (rev28)? I'm now investigating it.

sebmck commented 9 years ago

@Constellation For what specifically?

Constellation commented 9 years ago

@sebmck I think sticking to the formal spec is very important ;) It provides a clear reason to "why it is so implemented". And makes the tool stable.

sebmck commented 9 years ago

@Constellation Yeah I understand that. I was referring to what section specifically that you were looking for.

Constellation commented 9 years ago

@sebmck Ah, I've misunderstood.

Default parameters have their own scope.

I'm looking for it. Now seeing 9.2.13, http://people.mozilla.org/~jorendorff/es6-draft.html#sec-functiondeclarationinstantiation

Constellation commented 9 years ago

Added class declaration / expression scope support.

Constellation commented 9 years ago

Remaining TODO is,

Please feel free to modify this list. Now, 4:00 JST, so I'll sleep today...

nzakas commented 9 years ago

There's also the import statement.

Constellation commented 9 years ago

@nzakas Nice. I've added it to TODO list.

Constellation commented 9 years ago

Destructuring assignments support is partially done. Initializers / Default parameters are not supported yet. Maybe need to change Esprima's AST architecture.

Constellation commented 9 years ago

Seeing the ClassDefinitionEvaluation1, we attempt to create class body scope only when the className is provided. However, in this case, computed property names are evaluated in the upper scope, so sometimes it is not strict scope. But spec says, ClassBody is strict code. I think it may be a spec bug. In this time, I always create the scope for strictness of scope. And I'll open the issue to TC39 bugzilla.

edit: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-strict-mode-code I'll investigate more.

Constellation commented 9 years ago

@ariya @michaelficarra Found Esprima's bug,

esprima.parse('try{}catch({a,b,c}){}').body[0].handlers[0].param

Should return ObjectPattern, but returns ObjectExpression.

Constellation commented 9 years ago

ForIn/ForOf with let / const's runtime evaluation spec http://people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-forin-div-ofbodyevaluation

Constellation commented 9 years ago

ES6 ForOf/ForIn scopes are supported :)

edit:

Oops, TDZ scope support is not landed. I'll reconstruct the logic.

edit: Done.

Constellation commented 9 years ago

Introduced ForStatement iteration scope for LetOrConstDeclaration.

Constellation commented 9 years ago

I'll add TDZ options. I think creating TDZ scope sometimes bothering users. Making it switchable with options is preferrable.

nzakas commented 9 years ago

One piece of complexity I just came across: variables can be referenced from within template strings. Just a special case to keep in mind. :)

Constellation commented 9 years ago

@nzakas Nice! Thank you for your note. I would appreciate if you would inform me the edge cases :) Yay! escope's ES6 template literal supports it :) https://github.com/estools/escope/blob/master/test/es6-template-literal.coffee#L28

Constellation commented 9 years ago

Some complicated scoping semantics requires fine-grained traversing order control of the child nodes. So I've created the esrecurse https://github.com/estools/esrecurse, it is recursive style visitor. I'll switch to it in escope.

Constellation commented 9 years ago

Switching traversing function from estraverse to esrecurse is done. Since escope needs fine-grained traversing order control, esrecurse is more suitable for escope. Current escope tests are passed, and integration tests with esmangle, which heavily uses escope, are also passed :)

nzakas commented 9 years ago

Nice!

Constellation commented 9 years ago

Implemented ImportDeclaration supports.

SimonDegraeve commented 9 years ago

Awesome, any idea how I can use the new escope with eslint? I am stuck with an error in escope.Scope.isScopeRequired.

Constellation commented 9 years ago

@SimonDegraeve,

new escope is drastically changed, so Scope.isScopeRequired API is now dropped. So please modify the caller not to use this.

This is because, now, escope cannot determine whether the node requires scope easily. For example, in ecmaVersion: 6 mode, BlockStatement requires scope, but not in ecmaVersion: 5. However, some BlockStatement in the AST tree doesn't require scope. In the current Mozilla AST, FunctionExpression, FunctionDeclaration has BlockStatement as it's body. But in this case, this BlockStatement doesn't require scope since the function scope is created for the parent node FunctionExpression.

Constellation commented 9 years ago

ExportDeclaration is now completely supported.

Constellation commented 9 years ago

@SimonDegraeve,

Seeing the code, I think it can be rewritten with https://github.com/estools/escope/blob/master/escope.js#L832 and https://github.com/estools/escope/blob/master/escope.js#L814 :)

SimonDegraeve commented 9 years ago

Ok I will have a look. Thank you.

Constellation commented 9 years ago

@SimonDegraeve

Great! If you find issues, please inform me. escope ES6 support is now heavily under the development. So feedbacks are welcome :)

Constellation commented 9 years ago

@SimonDegraeve

I'll extend acquire by using WeakMap. It will provide more good functionality for you. Please wait for a moment...

Constellation commented 9 years ago

@SimonDegraeve

I've added ScopeManager#acquireAll. It acquires all scopes bound to the specified node. And now, escope can use ScopeManager#acquire and ScopeManager#release without ScopeManager#attach and ScopeManager#detach.

SimonDegraeve commented 9 years ago

Si I had a look, and even if I managed to run it without Error. The scope are totally wrong. (Lack of knowledge how tree parsing works, I guess).... maybe I will try another attempt when I have free time. Thanks

Constellation commented 9 years ago

@nzakas Except for default parameters and destructuring assignment initializers, ES6 scopes are basically supported. (of cource, still it is experimental phase.) And these features require some updates for esprima, (or espree).

In the meantime, I've released it as 2.0.0. It shipps major changes. So to stabilize it, feedbacks are welcome. And futher release may include the drastic changes. (Maybe, TDZ scopes should be treated more nicely, and parameter scopes are needed when default parameters are supported.)