Skip to content

Commit c888ea3

Browse files
committed
Fix #17085
1 parent 960d114 commit c888ea3

File tree

5 files changed

+146
-5
lines changed

5 files changed

+146
-5
lines changed

src/compiler/declarationEmitter.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,10 +1249,18 @@ namespace ts {
12491249
writeLine();
12501250
}
12511251

1252+
function bindingNameContainsVisibleBindingElement(node: BindingName): boolean {
1253+
return !!node && isBindingPattern(node) && some(node.elements, elem => !isOmittedExpression(elem) && (resolver.isDeclarationVisible(elem) || bindingNameContainsVisibleBindingElement(elem.name)));
1254+
}
1255+
1256+
function isVariableDeclarationVisible(node: VariableDeclaration | BindingElement) {
1257+
return resolver.isDeclarationVisible(node) || bindingNameContainsVisibleBindingElement(node.name);
1258+
}
1259+
12521260
function emitVariableDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration) {
12531261
// If we are emitting property it isn't moduleElement and hence we already know it needs to be emitted
12541262
// so there is no check needed to see if declaration is visible
1255-
if (node.kind !== SyntaxKind.VariableDeclaration || resolver.isDeclarationVisible(node)) {
1263+
if (node.kind !== SyntaxKind.VariableDeclaration || isVariableDeclarationVisible(node)) {
12561264
if (isBindingPattern(node.name)) {
12571265
emitBindingPattern(<BindingPattern>node.name);
12581266
}
@@ -1324,14 +1332,14 @@ namespace ts {
13241332
}
13251333

13261334
function emitBindingPattern(bindingPattern: BindingPattern) {
1327-
// Only select non-omitted expression from the bindingPattern's elements.
1335+
// Only select visible, non-omitted expression from the bindingPattern's elements.
13281336
// We have to do this to avoid emitting trailing commas.
13291337
// For example:
13301338
// original: var [, c,,] = [ 2,3,4]
13311339
// emitted: declare var c: number; // instead of declare var c:number, ;
13321340
const elements: Node[] = [];
13331341
for (const element of bindingPattern.elements) {
1334-
if (element.kind !== SyntaxKind.OmittedExpression) {
1342+
if (element.kind !== SyntaxKind.OmittedExpression && isVariableDeclarationVisible(element)) {
13351343
elements.push(element);
13361344
}
13371345
}
@@ -1371,7 +1379,7 @@ namespace ts {
13711379
}
13721380

13731381
function isVariableStatementVisible(node: VariableStatement) {
1374-
return forEach(node.declarationList.declarations, varDeclaration => resolver.isDeclarationVisible(varDeclaration));
1382+
return forEach(node.declarationList.declarations, varDeclaration => isVariableDeclarationVisible(varDeclaration));
13751383
}
13761384

13771385
function writeVariableStatement(node: VariableStatement) {
@@ -1390,7 +1398,7 @@ namespace ts {
13901398
else {
13911399
write("var ");
13921400
}
1393-
emitCommaList(node.declarationList.declarations, emitVariableDeclaration, resolver.isDeclarationVisible);
1401+
emitCommaList(node.declarationList.declarations, emitVariableDeclaration, isVariableDeclarationVisible);
13941402
write(";");
13951403
writeLine();
13961404
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//// [tests/cases/compiler/destructuredDeclarationEmit.ts] ////
2+
3+
//// [foo.ts]
4+
const foo = { bar: 'hello', bat: 'world', bam: { bork: { bar: 'a', baz: 'b' } } };
5+
export { foo };
6+
//// [index.ts]
7+
import { foo } from './foo';
8+
export { foo };
9+
10+
const { bar: baz, bat, bam: { bork: { bar: ibar, baz: ibaz } } } = foo;
11+
export { baz, ibaz };
12+
13+
//// [foo.js]
14+
"use strict";
15+
exports.__esModule = true;
16+
var foo = { bar: 'hello', bat: 'world', bam: { bork: { bar: 'a', baz: 'b' } } };
17+
exports.foo = foo;
18+
//// [index.js]
19+
"use strict";
20+
exports.__esModule = true;
21+
var foo_1 = require("./foo");
22+
exports.foo = foo_1.foo;
23+
var baz = foo_1.foo.bar, bat = foo_1.foo.bat, _a = foo_1.foo.bam.bork, ibar = _a.bar, ibaz = _a.baz;
24+
exports.baz = baz;
25+
exports.ibaz = ibaz;
26+
27+
28+
//// [foo.d.ts]
29+
declare const foo: {
30+
bar: string;
31+
bat: string;
32+
bam: {
33+
bork: {
34+
bar: string;
35+
baz: string;
36+
};
37+
};
38+
};
39+
export { foo };
40+
//// [index.d.ts]
41+
import { foo } from './foo';
42+
export { foo };
43+
declare const baz: string, ibaz: string;
44+
export { baz, ibaz };
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
=== tests/cases/compiler/foo.ts ===
2+
const foo = { bar: 'hello', bat: 'world', bam: { bork: { bar: 'a', baz: 'b' } } };
3+
>foo : Symbol(foo, Decl(foo.ts, 0, 5))
4+
>bar : Symbol(bar, Decl(foo.ts, 0, 13))
5+
>bat : Symbol(bat, Decl(foo.ts, 0, 27))
6+
>bam : Symbol(bam, Decl(foo.ts, 0, 41))
7+
>bork : Symbol(bork, Decl(foo.ts, 0, 48))
8+
>bar : Symbol(bar, Decl(foo.ts, 0, 56))
9+
>baz : Symbol(baz, Decl(foo.ts, 0, 66))
10+
11+
export { foo };
12+
>foo : Symbol(foo, Decl(foo.ts, 1, 8))
13+
14+
=== tests/cases/compiler/index.ts ===
15+
import { foo } from './foo';
16+
>foo : Symbol(foo, Decl(index.ts, 0, 8))
17+
18+
export { foo };
19+
>foo : Symbol(foo, Decl(index.ts, 1, 8))
20+
21+
const { bar: baz, bat, bam: { bork: { bar: ibar, baz: ibaz } } } = foo;
22+
>bar : Symbol(bar, Decl(foo.ts, 0, 13))
23+
>baz : Symbol(baz, Decl(index.ts, 3, 7))
24+
>bat : Symbol(bat, Decl(index.ts, 3, 17))
25+
>bam : Symbol(bam, Decl(foo.ts, 0, 41))
26+
>bork : Symbol(bork, Decl(foo.ts, 0, 48))
27+
>bar : Symbol(bar, Decl(foo.ts, 0, 56))
28+
>ibar : Symbol(ibar, Decl(index.ts, 3, 37))
29+
>baz : Symbol(baz, Decl(foo.ts, 0, 66))
30+
>ibaz : Symbol(ibaz, Decl(index.ts, 3, 48))
31+
>foo : Symbol(foo, Decl(index.ts, 0, 8))
32+
33+
export { baz, ibaz };
34+
>baz : Symbol(baz, Decl(index.ts, 4, 8))
35+
>ibaz : Symbol(ibaz, Decl(index.ts, 4, 13))
36+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
=== tests/cases/compiler/foo.ts ===
2+
const foo = { bar: 'hello', bat: 'world', bam: { bork: { bar: 'a', baz: 'b' } } };
3+
>foo : { bar: string; bat: string; bam: { bork: { bar: string; baz: string; }; }; }
4+
>{ bar: 'hello', bat: 'world', bam: { bork: { bar: 'a', baz: 'b' } } } : { bar: string; bat: string; bam: { bork: { bar: string; baz: string; }; }; }
5+
>bar : string
6+
>'hello' : "hello"
7+
>bat : string
8+
>'world' : "world"
9+
>bam : { bork: { bar: string; baz: string; }; }
10+
>{ bork: { bar: 'a', baz: 'b' } } : { bork: { bar: string; baz: string; }; }
11+
>bork : { bar: string; baz: string; }
12+
>{ bar: 'a', baz: 'b' } : { bar: string; baz: string; }
13+
>bar : string
14+
>'a' : "a"
15+
>baz : string
16+
>'b' : "b"
17+
18+
export { foo };
19+
>foo : { bar: string; bat: string; bam: { bork: { bar: string; baz: string; }; }; }
20+
21+
=== tests/cases/compiler/index.ts ===
22+
import { foo } from './foo';
23+
>foo : { bar: string; bat: string; bam: { bork: { bar: string; baz: string; }; }; }
24+
25+
export { foo };
26+
>foo : { bar: string; bat: string; bam: { bork: { bar: string; baz: string; }; }; }
27+
28+
const { bar: baz, bat, bam: { bork: { bar: ibar, baz: ibaz } } } = foo;
29+
>bar : any
30+
>baz : string
31+
>bat : string
32+
>bam : any
33+
>bork : any
34+
>bar : any
35+
>ibar : string
36+
>baz : any
37+
>ibaz : string
38+
>foo : { bar: string; bat: string; bam: { bork: { bar: string; baz: string; }; }; }
39+
40+
export { baz, ibaz };
41+
>baz : string
42+
>ibaz : string
43+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// @declaration: true
2+
// @filename: foo.ts
3+
const foo = { bar: 'hello', bat: 'world', bam: { bork: { bar: 'a', baz: 'b' } } };
4+
export { foo };
5+
// @filename: index.ts
6+
import { foo } from './foo';
7+
export { foo };
8+
9+
const { bar: baz, bat, bam: { bork: { bar: ibar, baz: ibaz } } } = foo;
10+
export { baz, ibaz };

0 commit comments

Comments
 (0)