Skip to content

Commit 48cb3e0

Browse files
committed
Merge pull request #940 from Microsoft/asynchrounousAliasWriteCrash
Fix the crash in declaration file emit when alias is used before its declaration
2 parents 8392ff4 + eebc8f9 commit 48cb3e0

7 files changed

+124
-6
lines changed

src/compiler/emitter.ts

+15-6
Original file line numberDiff line numberDiff line change
@@ -345,13 +345,22 @@ module ts {
345345
var oldWriter = writer;
346346
forEach(importDeclarations, aliasToWrite => {
347347
var aliasEmitInfo = forEach(aliasDeclarationEmitInfo, declEmitInfo => declEmitInfo.declaration === aliasToWrite ? declEmitInfo : undefined);
348-
writer = createTextWriter(newLine, trackSymbol);
349-
for (var declarationIndent = aliasEmitInfo.indent; declarationIndent; declarationIndent--) {
350-
writer.increaseIndent();
348+
// If the alias was marked as not visible when we saw its declaration, we would have saved the aliasEmitInfo, but if we haven't yet visited the alias declaration
349+
// then we don't need to write it at this point. We will write it when we actually see its declaration
350+
// Eg.
351+
// export function bar(a: foo.Foo) { }
352+
// import foo = require("foo");
353+
// Writing of function bar would mark alias declaration foo as visible but we haven't yet visited that declaration so do nothing,
354+
// we would write alias foo declaration when we visit it since it would now be marked as visible
355+
if (aliasEmitInfo) {
356+
writer = createTextWriter(newLine, trackSymbol);
357+
for (var declarationIndent = aliasEmitInfo.indent; declarationIndent; declarationIndent--) {
358+
writer.increaseIndent();
359+
}
360+
361+
writeImportDeclaration(aliasToWrite);
362+
aliasEmitInfo.asynchronousOutput = writer.getText();
351363
}
352-
353-
writeImportDeclaration(aliasToWrite);
354-
aliasEmitInfo.asynchronousOutput = writer.getText();
355364
});
356365
writer = oldWriter;
357366
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//// [tests/cases/compiler/declFileAliasUseBeforeDeclaration.ts] ////
2+
3+
//// [declFileAliasUseBeforeDeclaration_foo.ts]
4+
5+
export class Foo { }
6+
7+
//// [declFileAliasUseBeforeDeclaration_test.ts]
8+
export function bar(a: foo.Foo) { }
9+
import foo = require("declFileAliasUseBeforeDeclaration_foo");
10+
11+
//// [declFileAliasUseBeforeDeclaration_foo.js]
12+
var Foo = (function () {
13+
function Foo() {
14+
}
15+
return Foo;
16+
})();
17+
exports.Foo = Foo;
18+
//// [declFileAliasUseBeforeDeclaration_test.js]
19+
function bar(a) {
20+
}
21+
exports.bar = bar;
22+
23+
24+
//// [declFileAliasUseBeforeDeclaration_foo.d.ts]
25+
export declare class Foo {
26+
}
27+
//// [declFileAliasUseBeforeDeclaration_test.d.ts]
28+
export declare function bar(a: foo.Foo): void;
29+
import foo = require("declFileAliasUseBeforeDeclaration_foo");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
=== tests/cases/compiler/declFileAliasUseBeforeDeclaration_test.ts ===
2+
export function bar(a: foo.Foo) { }
3+
>bar : (a: foo.Foo) => void
4+
>a : foo.Foo
5+
>foo : unknown
6+
>Foo : foo.Foo
7+
8+
import foo = require("declFileAliasUseBeforeDeclaration_foo");
9+
>foo : typeof foo
10+
11+
=== tests/cases/compiler/declFileAliasUseBeforeDeclaration_foo.ts ===
12+
13+
export class Foo { }
14+
>Foo : Foo
15+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//// [declFileAliasUseBeforeDeclaration2.ts]
2+
3+
declare module "test" {
4+
module A {
5+
class C {
6+
}
7+
}
8+
class B extends E {
9+
}
10+
import E = A.C;
11+
}
12+
13+
//// [declFileAliasUseBeforeDeclaration2.js]
14+
15+
16+
//// [declFileAliasUseBeforeDeclaration2.d.ts]
17+
declare module "test" {
18+
module A {
19+
class C {
20+
}
21+
}
22+
class B extends E {
23+
}
24+
import E = A.C;
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
=== tests/cases/compiler/declFileAliasUseBeforeDeclaration2.ts ===
2+
3+
declare module "test" {
4+
module A {
5+
>A : typeof A
6+
7+
class C {
8+
>C : C
9+
}
10+
}
11+
class B extends E {
12+
>B : B
13+
>E : E
14+
}
15+
import E = A.C;
16+
>E : typeof E
17+
>A : typeof A
18+
>C : E
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//@module: commonjs
2+
//@declaration: true
3+
4+
// @Filename: declFileAliasUseBeforeDeclaration_foo.ts
5+
export class Foo { }
6+
7+
// @Filename: declFileAliasUseBeforeDeclaration_test.ts
8+
export function bar(a: foo.Foo) { }
9+
import foo = require("declFileAliasUseBeforeDeclaration_foo");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//@module: commonjs
2+
//@declaration: true
3+
4+
declare module "test" {
5+
module A {
6+
class C {
7+
}
8+
}
9+
class B extends E {
10+
}
11+
import E = A.C;
12+
}

0 commit comments

Comments
 (0)