Skip to content

Commit b96acbe

Browse files
authored
fix(3560): fix nested export variable transformation in if/labeled statements (#3732)
1 parent 7f8d024 commit b96acbe

10 files changed

Lines changed: 25 additions & 51 deletions

internal/ast/visitor.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ func (v *NodeVisitor) VisitEmbeddedStatement(node *Statement) *Statement {
7676
return node
7777
}
7878

79-
if v.Visit != nil {
80-
return v.liftToBlock(v.Visit(node))
79+
visited := v.Visit(node)
80+
if visited == nil {
81+
return nil
8182
}
82-
83-
return node
83+
return v.liftToBlock(visited)
8484
}
8585

8686
// Visits a NodeList, possibly returning a new NodeList in its place.

internal/transformers/moduletransforms/commonjsmodule.go

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func (tx *CommonJSModuleTransformer) visitTopLevelNested(node *ast.Node) *ast.No
9494
func (tx *CommonJSModuleTransformer) visitTopLevelNestedNoStack(node *ast.Node) *ast.Node {
9595
switch node.Kind {
9696
case ast.KindVariableStatement:
97-
node = tx.visitTopLevelNestedVariableStatement(node.AsVariableStatement())
97+
node = tx.visitTopLevelVariableStatement(node.AsVariableStatement())
9898
case ast.KindForStatement:
9999
node = tx.visitTopLevelNestedForStatement(node.AsForStatement())
100100
case ast.KindForInStatement, ast.KindForOfStatement:
@@ -1243,11 +1243,11 @@ func (tx *CommonJSModuleTransformer) visitTopLevelNestedWhileStatement(node *ast
12431243
// Visits a top-level nested labeled statement as it may contain `var` declarations that are hoisted and may still be
12441244
// exported with `export {}`.
12451245
func (tx *CommonJSModuleTransformer) visitTopLevelNestedLabeledStatement(node *ast.LabeledStatement) *ast.Node {
1246-
return tx.Factory().UpdateLabeledStatement(
1247-
node,
1248-
node.Label,
1249-
tx.topLevelNestedVisitor.VisitEmbeddedStatement(node.Statement),
1250-
)
1246+
statement := tx.topLevelNestedVisitor.VisitEmbeddedStatement(node.Statement)
1247+
if statement == nil {
1248+
statement = tx.Factory().NewEmptyStatement()
1249+
}
1250+
return tx.Factory().UpdateLabeledStatement(node, node.Label, statement)
12511251
}
12521252

12531253
// Visits a top-level nested `with` statement as it may contain `var` declarations that are hoisted and may still be
@@ -1263,12 +1263,13 @@ func (tx *CommonJSModuleTransformer) visitTopLevelNestedWithStatement(node *ast.
12631263
// Visits a top-level nested `if` statement as it may contain `var` declarations that are hoisted and may still be
12641264
// exported with `export {}`.
12651265
func (tx *CommonJSModuleTransformer) visitTopLevelNestedIfStatement(node *ast.IfStatement) *ast.Node {
1266-
return tx.Factory().UpdateIfStatement(
1267-
node,
1268-
tx.Visitor().VisitNode(node.Expression),
1269-
tx.topLevelNestedVisitor.VisitEmbeddedStatement(node.ThenStatement),
1270-
tx.topLevelNestedVisitor.VisitEmbeddedStatement(node.ElseStatement),
1271-
)
1266+
expression := tx.Visitor().VisitNode(node.Expression)
1267+
thenStatement := tx.topLevelNestedVisitor.VisitEmbeddedStatement(node.ThenStatement)
1268+
if thenStatement == nil {
1269+
thenStatement = tx.Factory().NewBlock(tx.Factory().NewNodeList(nil), false /*multiLine*/)
1270+
}
1271+
elseStatement := tx.topLevelNestedVisitor.VisitEmbeddedStatement(node.ElseStatement)
1272+
return tx.Factory().UpdateIfStatement(node, expression, thenStatement, elseStatement)
12721273
}
12731274

12741275
// Visits a top-level nested `switch` statement as it may contain `var` declarations that are hoisted and may still be

internal/transformers/utilities.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,9 @@ func ConvertVariableDeclarationToAssignmentExpression(emitContext *printer.EmitC
220220
}
221221

222222
func SingleOrMany(nodes []*ast.Node, factory *printer.NodeFactory) *ast.Node {
223+
if nodes == nil {
224+
return nil
225+
}
223226
if len(nodes) == 1 {
224227
return nodes[0]
225228
}

testdata/baselines/reference/submodule/compiler/declarationEmitInvalidExport.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export type MyClass = typeof myClass;
1212
"use strict";
1313
Object.defineProperty(exports, "__esModule", { value: true });
1414
if (false) {
15-
export var myClass = 0;
15+
exports.myClass = 0;
1616
}
1717

1818

testdata/baselines/reference/submodule/conformance/exportNonInitializedVariablesInIfThenStatementNoCrash1(module=commonjs).js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,5 @@ export default cssExports;
1212
"use strict";
1313
// https://github.com/microsoft/TypeScript/issues/59373
1414
Object.defineProperty(exports, "__esModule", { value: true });
15-
if (true)
16-
export const cssExports;
15+
if (true) { }
1716
exports.default = exports.cssExports;

testdata/baselines/reference/submodule/conformance/labeledStatementExportDeclarationNoCrash1(module=commonjs).js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@ export const title: string
1313
// https://github.com/microsoft/TypeScript/issues/59372
1414
Object.defineProperty(exports, "__esModule", { value: true });
1515
exports.box = void 0;
16-
subTitle: export const title;
16+
subTitle: ;

testdata/baselines/reference/submoduleAccepted/compiler/declarationEmitInvalidExport.js.diff

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
--- old.declarationEmitInvalidExport.js
22
+++ new.declarationEmitInvalidExport.js
3-
@@= skipped -11, +11 lines =@@
4-
"use strict";
5-
Object.defineProperty(exports, "__esModule", { value: true });
3+
@@= skipped -13, +13 lines =@@
64
if (false) {
7-
- exports.myClass = 0;
8-
+ export var myClass = 0;
5+
exports.myClass = 0;
96
}
107
+
118
+

testdata/baselines/reference/submoduleTriaged/conformance/exportNonInitializedVariablesInIfThenStatementNoCrash1(module=commonjs).js.diff

Lines changed: 0 additions & 10 deletions
This file was deleted.

testdata/baselines/reference/submoduleTriaged/conformance/labeledStatementExportDeclarationNoCrash1(module=commonjs).js.diff

Lines changed: 0 additions & 8 deletions
This file was deleted.

testdata/submoduleTriaged.txt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -196,21 +196,13 @@ conformance/callbackTagVariadicType.js.diff
196196
## https://github.com/microsoft/typescript-go/issues/3557
197197
conformance/checkJsdocSatisfiesTag15.js.diff
198198

199-
# Labeled statement followed by export declaration loses original text
200-
## https://github.com/microsoft/typescript-go/issues/3558
201-
conformance/labeledStatementExportDeclarationNoCrash1(module=commonjs).js.diff
202-
203199
# CJS exports pattern changes in declaration emit
204200
## https://github.com/microsoft/typescript-go/issues/3559
205201
compiler/jsExportAssignmentNonMutableLocation.js.diff
206202
conformance/commonJSImportClassTypeReference.js.diff
207203
conformance/commonJSImportNestedClassTypeReference.js.diff
208204
conformance/jsDeclarationsExportDoubleAssignmentInClosure.js.diff
209205

210-
# exportNonInitializedVariables crash in declaration emit
211-
## https://github.com/microsoft/typescript-go/issues/3560
212-
conformance/exportNonInitializedVariablesInIfThenStatementNoCrash1(module=commonjs).js.diff
213-
214206
# noImplicitThis functions returning this now fully expand the object type
215207
## https://github.com/microsoft/typescript-go/issues/3561
216208
compiler/noImplicitThisBigThis.js.diff

0 commit comments

Comments
 (0)