Skip to content

Let and const support #904

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 30 commits into from
Oct 24, 2014
Merged

Let and const support #904

merged 30 commits into from
Oct 24, 2014

Conversation

mhegazy
Copy link
Contributor

@mhegazy mhegazy commented Oct 16, 2014

This change adds support for ES6-style block-scoped variable declarations. these are only available when targeting ES6. the change also adds a new target for ES6.

There are two variants, let and const. Generaly let and const behave like a var declarations with the following exceptions:

  • Both let and const can not be re-declared:
let a = 0;
a = 1;
let a; // Error: redeclaration
  • It is an error to re-declare a block-scoped variable as 'var' in the same scope:
let a = 0;
{
     var a; // Error: redeclaration, as var is hoisted to the top of the scope, and re-declares a
}
  • Let and const can not be declared in a non-guarded statements
if (true) {
    let a = 0; // OK
}

if (false) 
   let b = 0; // Error

for (let i = 0; i< 10; i++)  // OK
    console.log(i); 
  • Let and const declarations are block scoped, and not hoisted to the top of the function like other JS declarations:
let a = 0;
{
    let a = "local";
    console.log(a) // local
}
console.log(a); // 0
  • Let and const can not be used before they are defined, to avoid the lexical dead zone of vars.
v = 2; // ok
var v;

a = 2;
let a; // Error, used before initialization
  • Const declarations must have an initializer, unless in ambient context
  • It is an error to write to a Const
const c = 0;
console.log(c); // OK: 0

c = 2; // Error
c++; // Error

{
    const c2 = 0;
    var c2 = 0; // not a redeclaration, as the var is hoisted out, but still a write to c2
}
  • Let and const can not be exported, only vars are allowed to.

What is left:

  • Block emit if any of the let/const errors are reported, these may be syntactic, binding, or semantic errors
  • Wire in Test262 for parser verification to ensure we are ES6 complaint

@@ -2827,7 +2848,7 @@ module ts {
parseExpected(SyntaxKind.CaseKeyword);
node.expression = parseExpression();
parseExpected(SyntaxKind.ColonToken);
node.statements = parseList(ParsingContext.SwitchClauseStatements, /*checkForStrictMode*/ false, parseStatement);
node.statements = parseList(ParsingContext.SwitchClauseStatements, /*checkForStrictMode*/ false, parseStatementAllowingLetDeclaration);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i thought we would not allow 'let' here as we're not in a block scope. or do you check for that later?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think you are correct. the ES6 spec makes it clear that lexical scopes do not include switch, try or finally blocks, section 8.1:

A Lexical Environment is a specification type used to define the association of Identifiers to specific variables and functions based upon the lexical nesting structure of ECMAScript code. A Lexical Environment consists of an Environment Record and a possibly null reference to an outer Lexical Environment. Usually a Lexical Environment is associated with some specific syntactic structure of ECMAScript code such as a FunctionDeclaration, a BlockStatement, or a Catch clause of a TryStatement and a new Lexical Environment is created each time such code is evaluated.

I will follow up to see if this is intentional or just an error in the spec and update this accordingly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They say "such as", which I normally interpret as "including but not limited to".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah. checked with @bterlson and he confirmed that that is not the intention. so keeping Switch, try and finally blocks as valid lexical scopes

@ahejlsberg
Copy link
Member

Overall looks great!

mhegazy added a commit that referenced this pull request Oct 24, 2014
@mhegazy mhegazy merged commit 290e43b into master Oct 24, 2014
@mhegazy mhegazy deleted the letAndConst branch October 24, 2014 18:26
@nickie
Copy link

nickie commented Feb 1, 2016

TypeScript's specification seems to allow a missing initializer for destructuring lexical bindings, whereas the EC262 specification does not. Is this intentional? In that case, I believe it should only be allowed in the case that a type annotation is present, e.g., in let [x, y]: number[]; The current playground implementation seems to disallow this.

@sandersn
Copy link
Member

sandersn commented Feb 1, 2016

@nickie, can you report a new bug for this, with the label Spec?

@nickie
Copy link

nickie commented Feb 1, 2016

@sandersn, done (6785) but I don't know how to add the label. Please add it, or advise me how to. Thanks.

@RyanCavanaugh
Copy link
Member

@sandersn FYI only Owners (i.e. us) can add Labels

# for free to subscribe to this conversation on GitHub. Already have an account? #.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants