Skip to content

Commit a03227d

Browse files
mprobstweswigham
authored andcommitted
Avoid a crash with @typedef in a script file. (#33847)
* Avoid a crash with `@typedef` in a script file. Scripts (as opposed to modules) do not have a symbol object. If a script contains a `@typdef` defined on a namespace called `exports`, TypeScript crashes because it attempts to create an exported symbol on the (non-existent) symbol of the SourceFile. This change avoids the crash by explicitly checking if the source file has a symbol object, i.e. whether it is a module. * Add usage of exports.SomeName typedef. * Fix bug at bind site rather than in declare func
1 parent 7cfa1df commit a03227d

6 files changed

+101
-2
lines changed

src/compiler/binder.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2003,7 +2003,12 @@ namespace ts {
20032003
switch (getAssignmentDeclarationPropertyAccessKind(declName.parent)) {
20042004
case AssignmentDeclarationKind.ExportsProperty:
20052005
case AssignmentDeclarationKind.ModuleExports:
2006-
container = file;
2006+
if (!isExternalOrCommonJsModule(file)) {
2007+
container = undefined!;
2008+
}
2009+
else {
2010+
container = file;
2011+
}
20072012
break;
20082013
case AssignmentDeclarationKind.ThisProperty:
20092014
container = declName.parent.expression;
@@ -2017,7 +2022,9 @@ namespace ts {
20172022
case AssignmentDeclarationKind.None:
20182023
return Debug.fail("Shouldn't have detected typedef or enum on non-assignment declaration");
20192024
}
2020-
declareModuleMember(typeAlias, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
2025+
if (container) {
2026+
declareModuleMember(typeAlias, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
2027+
}
20212028
container = oldContainer;
20222029
}
20232030
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
tests/cases/conformance/jsdoc/0.js(10,20): error TS2694: Namespace 'exports' has no exported member 'SomeName'.
2+
3+
4+
==== tests/cases/conformance/jsdoc/0.js (1 errors) ====
5+
// @ts-check
6+
7+
var exports = {};
8+
9+
/**
10+
* @typedef {string}
11+
*/
12+
exports.SomeName;
13+
14+
/** @type {exports.SomeName} */
15+
~~~~~~~~
16+
!!! error TS2694: Namespace 'exports' has no exported member 'SomeName'.
17+
const myString = 'str';
18+
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//// [0.js]
2+
// @ts-check
3+
4+
var exports = {};
5+
6+
/**
7+
* @typedef {string}
8+
*/
9+
exports.SomeName;
10+
11+
/** @type {exports.SomeName} */
12+
const myString = 'str';
13+
14+
15+
//// [0.js]
16+
// @ts-check
17+
var exports = {};
18+
/**
19+
* @typedef {string}
20+
*/
21+
exports.SomeName;
22+
/** @type {exports.SomeName} */
23+
var myString = 'str';
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
=== tests/cases/conformance/jsdoc/0.js ===
2+
// @ts-check
3+
4+
var exports = {};
5+
>exports : Symbol(exports, Decl(0.js, 2, 3))
6+
7+
/**
8+
* @typedef {string}
9+
*/
10+
exports.SomeName;
11+
>exports : Symbol(exports, Decl(0.js, 2, 3))
12+
13+
/** @type {exports.SomeName} */
14+
const myString = 'str';
15+
>myString : Symbol(myString, Decl(0.js, 10, 5))
16+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
=== tests/cases/conformance/jsdoc/0.js ===
2+
// @ts-check
3+
4+
var exports = {};
5+
>exports : {}
6+
>{} : {}
7+
8+
/**
9+
* @typedef {string}
10+
*/
11+
exports.SomeName;
12+
>exports.SomeName : any
13+
>exports : {}
14+
>SomeName : any
15+
16+
/** @type {exports.SomeName} */
17+
const myString = 'str';
18+
>myString : any
19+
>'str' : "str"
20+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// @allowJS: true
2+
// @suppressOutputPathCheck: true
3+
4+
// @filename: 0.js
5+
// @ts-check
6+
7+
var exports = {};
8+
9+
/**
10+
* @typedef {string}
11+
*/
12+
exports.SomeName;
13+
14+
/** @type {exports.SomeName} */
15+
const myString = 'str';

0 commit comments

Comments
 (0)