From 4aff9c357d31a5b3e2efce40b313d83b93eb2b1e Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 16 Feb 2015 13:39:32 -0800 Subject: [PATCH] explicitly initialize let binding in generated code to default value --- src/compiler/emitter.ts | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index da19862e3d8..638b78812cc 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3155,6 +3155,14 @@ module ts { emitEnd(node.name); } + function createVoidZero(): Expression { + var zero = createNode(SyntaxKind.NumericLiteral); + zero.text = "0"; + var result = createNode(SyntaxKind.VoidExpression); + result.expression = zero; + return result; + } + function emitDestructuring(root: BinaryExpression | VariableDeclaration | ParameterDeclaration, value?: Expression) { var emitCount = 0; // An exported declaration is actually emitted as an assignment (to a property on the module object), so @@ -3195,14 +3203,6 @@ module ts { return expr; } - function createVoidZero(): Expression { - var zero = createNode(SyntaxKind.NumericLiteral); - zero.text = "0"; - var result = createNode(SyntaxKind.VoidExpression); - result.expression = zero; - return result; - } - function createDefaultValueCheck(value: Expression, defaultValue: Expression): Expression { // The value expression will be evaluated twice, so for anything but a simple identifier // we need to generate a temporary variable @@ -3384,9 +3384,14 @@ module ts { } } else { - renameNonTopLevelLetAndConst(node.name); + var initializeToDefault = renameNonTopLevelLetAndConst(node.name); emitModuleMemberName(node); - emitOptional(" = ", node.initializer); + + var initializer = + node.initializer || + (initializeToDefault && createVoidZero()); + + emitOptional(" = ", initializer); } } @@ -3417,7 +3422,7 @@ module ts { } } - function renameNonTopLevelLetAndConst(node: Node): void { + function renameNonTopLevelLetAndConst(node: Node): boolean { // do not rename if // - language version is ES6+ // - node is synthesized (does not have a parent) @@ -3426,20 +3431,20 @@ module ts { if (languageVersion >= ScriptTarget.ES6 || !node.parent || (node.parent.kind !== SyntaxKind.VariableDeclaration && node.parent.kind !== SyntaxKind.BindingElement)) { - return; + return false; } var combinedFlags = getCombinedNodeFlags(node.parent); if (((combinedFlags & NodeFlags.BlockScoped) === 0) || combinedFlags & NodeFlags.Export) { // do not rename exported or non-block scoped variables - return; + return false; } // here it is known that node is a block scoped variable var list = getAncestor(node, SyntaxKind.VariableDeclarationList); if (list.parent.kind === SyntaxKind.VariableStatement && list.parent.parent.kind === SyntaxKind.SourceFile) { // do not rename variables that are defined on source file level - return; + return false; } var generatedName = makeUniqueName(getEnclosingBlockScopeContainer(node), (node).text); @@ -3448,6 +3453,8 @@ module ts { generatedBlockScopeNames = []; } generatedBlockScopeNames[symbolId] = generatedName; + + return (combinedFlags & NodeFlags.Let) !== 0; } function emitVariableStatement(node: VariableStatement) {