Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Let and const support #904

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

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
8 participants