diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 81599c88286..a3b0452f091 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -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((body).statements, namespaceElementVisitor, isStatement))); - statementsLocation = body.statements; - blockLocation = body; - } - else { - const result = visitModuleDeclaration(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((body).statements, namespaceElementVisitor, isStatement))); + statementsLocation = node.body.statements; + blockLocation = node.body; } + else { + const result = visitModuleDeclaration(node.body); + if (result) { + if (isArray(result)) { + addRange(statements, result); + } + else { + statements.push(result); + } + } - const moduleBlock = getInnerMostModuleDeclarationFromDottedModule(node)!.body; - statementsLocation = moveRangePos(moduleBlock.statements, -1); + const 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; diff --git a/tests/baselines/reference/nestedGlobalNamespaceInClass.errors.txt b/tests/baselines/reference/nestedGlobalNamespaceInClass.errors.txt new file mode 100644 index 00000000000..d8385fced3b --- /dev/null +++ b/tests/baselines/reference/nestedGlobalNamespaceInClass.errors.txt @@ -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. + \ No newline at end of file diff --git a/tests/baselines/reference/nestedGlobalNamespaceInClass.js b/tests/baselines/reference/nestedGlobalNamespaceInClass.js new file mode 100644 index 00000000000..67bc76f10ee --- /dev/null +++ b/tests/baselines/reference/nestedGlobalNamespaceInClass.js @@ -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; diff --git a/tests/baselines/reference/nestedGlobalNamespaceInClass.symbols b/tests/baselines/reference/nestedGlobalNamespaceInClass.symbols new file mode 100644 index 00000000000..abd91a98673 --- /dev/null +++ b/tests/baselines/reference/nestedGlobalNamespaceInClass.symbols @@ -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)) +} + diff --git a/tests/baselines/reference/nestedGlobalNamespaceInClass.types b/tests/baselines/reference/nestedGlobalNamespaceInClass.types new file mode 100644 index 00000000000..57e71143899 --- /dev/null +++ b/tests/baselines/reference/nestedGlobalNamespaceInClass.types @@ -0,0 +1,10 @@ +=== tests/cases/compiler/nestedGlobalNamespaceInClass.ts === +// should not crash - from #35717 +class C { +>C : C + + global x +>global : any +>x : any +} + diff --git a/tests/cases/compiler/nestedGlobalNamespaceInClass.ts b/tests/cases/compiler/nestedGlobalNamespaceInClass.ts new file mode 100644 index 00000000000..bd17662477c --- /dev/null +++ b/tests/cases/compiler/nestedGlobalNamespaceInClass.ts @@ -0,0 +1,4 @@ +// should not crash - from #35717 +class C { + global x +}