mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
Fix crash on bad namespace parse (#37626)
* Fix crash on bad namespace parse
`global` inside a class body is parsed as a module declaration, and in
the following example has no body:
```ts
class C {
global x
}
```
`x` is parsed as a separate ExpressionStatement. This caused a crash in
emit because the code didn't expect a module declaration with no body.
* inline node.body variable
* fix missed references to body
This commit is contained in:
parent
ed1863b3e6
commit
95a124f802
@ -2693,27 +2693,28 @@ namespace ts {
|
||||
const statements: Statement[] = [];
|
||||
startLexicalEnvironment();
|
||||
|
||||
let statementsLocation: TextRange;
|
||||
let statementsLocation: TextRange | undefined;
|
||||
let blockLocation: TextRange | undefined;
|
||||
const body = node.body!;
|
||||
if (body.kind === SyntaxKind.ModuleBlock) {
|
||||
saveStateAndInvoke(body, body => addRange(statements, visitNodes((<ModuleBlock>body).statements, namespaceElementVisitor, isStatement)));
|
||||
statementsLocation = body.statements;
|
||||
blockLocation = body;
|
||||
}
|
||||
else {
|
||||
const result = visitModuleDeclaration(<ModuleDeclaration>body);
|
||||
if (result) {
|
||||
if (isArray(result)) {
|
||||
addRange(statements, result);
|
||||
}
|
||||
else {
|
||||
statements.push(result);
|
||||
}
|
||||
if (node.body) {
|
||||
if (node.body.kind === SyntaxKind.ModuleBlock) {
|
||||
saveStateAndInvoke(node.body, body => addRange(statements, visitNodes((<ModuleBlock>body).statements, namespaceElementVisitor, isStatement)));
|
||||
statementsLocation = node.body.statements;
|
||||
blockLocation = node.body;
|
||||
}
|
||||
else {
|
||||
const result = visitModuleDeclaration(<ModuleDeclaration>node.body);
|
||||
if (result) {
|
||||
if (isArray(result)) {
|
||||
addRange(statements, result);
|
||||
}
|
||||
else {
|
||||
statements.push(result);
|
||||
}
|
||||
}
|
||||
|
||||
const moduleBlock = <ModuleBlock>getInnerMostModuleDeclarationFromDottedModule(node)!.body;
|
||||
statementsLocation = moveRangePos(moduleBlock.statements, -1);
|
||||
const moduleBlock = <ModuleBlock>getInnerMostModuleDeclarationFromDottedModule(node)!.body;
|
||||
statementsLocation = moveRangePos(moduleBlock.statements, -1);
|
||||
}
|
||||
}
|
||||
|
||||
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
|
||||
@ -2750,7 +2751,7 @@ namespace ts {
|
||||
// })(hi = hello.hi || (hello.hi = {}));
|
||||
// })(hello || (hello = {}));
|
||||
// We only want to emit comment on the namespace which contains block body itself, not the containing namespaces.
|
||||
if (body.kind !== SyntaxKind.ModuleBlock) {
|
||||
if (!node.body || node.body.kind !== SyntaxKind.ModuleBlock) {
|
||||
setEmitFlags(block, getEmitFlags(block) | EmitFlags.NoComments);
|
||||
}
|
||||
return block;
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
tests/cases/compiler/nestedGlobalNamespaceInClass.ts(3,5): error TS1068: Unexpected token. A constructor, method, accessor, or property was expected.
|
||||
tests/cases/compiler/nestedGlobalNamespaceInClass.ts(3,5): error TS2669: Augmentations for the global scope can only be directly nested in external modules or ambient module declarations.
|
||||
tests/cases/compiler/nestedGlobalNamespaceInClass.ts(3,5): error TS2670: Augmentations for the global scope should have 'declare' modifier unless they appear in already ambient context.
|
||||
tests/cases/compiler/nestedGlobalNamespaceInClass.ts(3,12): error TS1005: ';' expected.
|
||||
tests/cases/compiler/nestedGlobalNamespaceInClass.ts(3,12): error TS2304: Cannot find name 'x'.
|
||||
tests/cases/compiler/nestedGlobalNamespaceInClass.ts(4,1): error TS1128: Declaration or statement expected.
|
||||
|
||||
|
||||
==== tests/cases/compiler/nestedGlobalNamespaceInClass.ts (6 errors) ====
|
||||
// should not crash - from #35717
|
||||
class C {
|
||||
global x
|
||||
~~~~~~
|
||||
!!! error TS1068: Unexpected token. A constructor, method, accessor, or property was expected.
|
||||
~~~~~~
|
||||
!!! error TS2669: Augmentations for the global scope can only be directly nested in external modules or ambient module declarations.
|
||||
~~~~~~
|
||||
!!! error TS2670: Augmentations for the global scope should have 'declare' modifier unless they appear in already ambient context.
|
||||
~
|
||||
!!! error TS1005: ';' expected.
|
||||
~
|
||||
!!! error TS2304: Cannot find name 'x'.
|
||||
}
|
||||
~
|
||||
!!! error TS1128: Declaration or statement expected.
|
||||
|
||||
18
tests/baselines/reference/nestedGlobalNamespaceInClass.js
Normal file
18
tests/baselines/reference/nestedGlobalNamespaceInClass.js
Normal file
@ -0,0 +1,18 @@
|
||||
//// [nestedGlobalNamespaceInClass.ts]
|
||||
// should not crash - from #35717
|
||||
class C {
|
||||
global x
|
||||
}
|
||||
|
||||
|
||||
//// [nestedGlobalNamespaceInClass.js]
|
||||
// should not crash - from #35717
|
||||
var C = /** @class */ (function () {
|
||||
function C() {
|
||||
}
|
||||
return C;
|
||||
}());
|
||||
var global;
|
||||
(function (global) {
|
||||
})(global || (global = {}));
|
||||
x;
|
||||
@ -0,0 +1,9 @@
|
||||
=== tests/cases/compiler/nestedGlobalNamespaceInClass.ts ===
|
||||
// should not crash - from #35717
|
||||
class C {
|
||||
>C : Symbol(C, Decl(nestedGlobalNamespaceInClass.ts, 0, 0))
|
||||
|
||||
global x
|
||||
>global : Symbol(global, Decl(nestedGlobalNamespaceInClass.ts, 1, 9))
|
||||
}
|
||||
|
||||
10
tests/baselines/reference/nestedGlobalNamespaceInClass.types
Normal file
10
tests/baselines/reference/nestedGlobalNamespaceInClass.types
Normal file
@ -0,0 +1,10 @@
|
||||
=== tests/cases/compiler/nestedGlobalNamespaceInClass.ts ===
|
||||
// should not crash - from #35717
|
||||
class C {
|
||||
>C : C
|
||||
|
||||
global x
|
||||
>global : any
|
||||
>x : any
|
||||
}
|
||||
|
||||
4
tests/cases/compiler/nestedGlobalNamespaceInClass.ts
Normal file
4
tests/cases/compiler/nestedGlobalNamespaceInClass.ts
Normal file
@ -0,0 +1,4 @@
|
||||
// should not crash - from #35717
|
||||
class C {
|
||||
global x
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user