Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1913,6 +1913,15 @@ namespace ts {
}
}

function checkStrictModeLabeledStatement(node: LabeledStatement) {
// Grammar checking for labeledStatement
if (inStrictMode && options.target! >= ScriptTarget.ES2015) {
if (isDeclarationStatement(node.statement) || isVariableStatement(node.statement)) {
errorOnFirstToken(node.label, Diagnostics.A_label_is_not_allowed_here);
}
}
}

function errorOnFirstToken(node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any) {
const span = getSpanOfTokenAtPosition(file, node.pos);
file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2));
Expand Down Expand Up @@ -2099,6 +2108,8 @@ namespace ts {
return checkStrictModePrefixUnaryExpression(<PrefixUnaryExpression>node);
case SyntaxKind.WithStatement:
return checkStrictModeWithStatement(<WithStatement>node);
case SyntaxKind.LabeledStatement:
return checkStrictModeLabeledStatement(<LabeledStatement>node);
case SyntaxKind.ThisType:
seenThisKeyword = true;
return;
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,10 @@
"category": "Error",
"code": 1343
},
"'A label is not allowed here.": {
"category": "Error",
"code": 1344
},

"Duplicate identifier '{0}'.": {
"category": "Error",
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/transformers/es2015.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2207,7 +2207,7 @@ namespace ts {
const statement = unwrapInnermostStatementOfLabel(node, convertedLoopState && recordLabel);
return isIterationStatement(statement, /*lookInLabeledStatements*/ false)
? visitIterationStatement(statement, /*outermostLabeledStatement*/ node)
: restoreEnclosingLabel(visitNode(statement, visitor, isStatement), node, convertedLoopState && resetLabel);
: restoreEnclosingLabel(visitNode(statement, visitor, isStatement, liftToBlock), node, convertedLoopState && resetLabel);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure i understand what this change is doing?

Copy link
Copy Markdown
Member

@weswigham weswigham Jul 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixing #25340 by lifting a sequence of, eg VariableStatement, EndOfDeclarationMarker (like a downlevel class produces) into a block. (Since right now that triggers an assertion violation)

}

function visitIterationStatement(node: IterationStatement, outermostLabeledStatement: LabeledStatement) {
Expand Down
23 changes: 23 additions & 0 deletions tests/baselines/reference/labeledStatementWithLabel.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel.ts(11,8): error TS1235: A namespace declaration is only allowed in a namespace or module.
tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel.ts(12,8): error TS1235: A namespace declaration is only allowed in a namespace or module.


==== tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel.ts (2 errors) ====
label: function fn() { }
label: function* gen() { }
label: async function gen1() { }
label: enum E {}
label: interface I {}
label: class C { }
label: var a = 1;
label: let b = 1;
label: const c = 1;

label: module M { }
~~~~~~
!!! error TS1235: A namespace declaration is only allowed in a namespace or module.
label: namespace N {}
~~~~~~~~~
!!! error TS1235: A namespace declaration is only allowed in a namespace or module.
label: type T = {}

80 changes: 80 additions & 0 deletions tests/baselines/reference/labeledStatementWithLabel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//// [labeledStatementWithLabel.ts]
label: function fn() { }
label: function* gen() { }
label: async function gen1() { }
label: enum E {}
label: interface I {}
label: class C { }
label: var a = 1;
label: let b = 1;
label: const c = 1;

label: module M { }
label: namespace N {}
label: type T = {}


//// [labeledStatementWithLabel.js]
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
label: function fn() { }
label: function gen() { return __generator(this, function (_a) {
return [2 /*return*/];
}); }
label: function gen1() {
return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) {
return [2 /*return*/];
}); });
}
label: {
var E;
(function (E) {
})(E || (E = {}));
}
label:
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

related #25340, #22686
😅not my fault

label: {
var C = /** @class */ (function () {
function C() {
}
return C;
}());
}
label: var a = 1;
label: var b = 1;
label: var c = 1;
label:
label:
label:
37 changes: 37 additions & 0 deletions tests/baselines/reference/labeledStatementWithLabel.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
=== tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel.ts ===
label: function fn() { }
>fn : Symbol(fn, Decl(labeledStatementWithLabel.ts, 0, 6))

label: function* gen() { }
>gen : Symbol(gen, Decl(labeledStatementWithLabel.ts, 1, 6))

label: async function gen1() { }
>gen1 : Symbol(gen1, Decl(labeledStatementWithLabel.ts, 2, 6))

label: enum E {}
>E : Symbol(E, Decl(labeledStatementWithLabel.ts, 3, 6))

label: interface I {}
>I : Symbol(I, Decl(labeledStatementWithLabel.ts, 4, 6))

label: class C { }
>C : Symbol(C, Decl(labeledStatementWithLabel.ts, 5, 6))

label: var a = 1;
>a : Symbol(a, Decl(labeledStatementWithLabel.ts, 6, 10))

label: let b = 1;
>b : Symbol(b, Decl(labeledStatementWithLabel.ts, 7, 10))

label: const c = 1;
>c : Symbol(c, Decl(labeledStatementWithLabel.ts, 8, 12))

label: module M { }
>M : Symbol(M, Decl(labeledStatementWithLabel.ts, 10, 6))

label: namespace N {}
>N : Symbol(N, Decl(labeledStatementWithLabel.ts, 11, 6))

label: type T = {}
>T : Symbol(T, Decl(labeledStatementWithLabel.ts, 12, 6))

52 changes: 52 additions & 0 deletions tests/baselines/reference/labeledStatementWithLabel.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
=== tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel.ts ===
label: function fn() { }
>label : any
>fn : () => void

label: function* gen() { }
>label : any
>gen : () => IterableIterator<any>

label: async function gen1() { }
>label : any
>gen1 : () => Promise<void>

label: enum E {}
>label : any
>E : E

label: interface I {}
>label : any
>I : I

label: class C { }
>label : any
>C : C

label: var a = 1;
>label : any
>a : number
>1 : 1

label: let b = 1;
>label : any
>b : number
>1 : 1

label: const c = 1;
>label : any
>c : 1
>1 : 1

label: module M { }
>label : any
>M : any

label: namespace N {}
>label : any
>N : any

label: type T = {}
>label : any
>T : {}

Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_es2015.ts(11,8): error TS1235: A namespace declaration is only allowed in a namespace or module.
tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_es2015.ts(12,8): error TS1235: A namespace declaration is only allowed in a namespace or module.


==== tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_es2015.ts (2 errors) ====
label: function fn() { }
label: function* gen() { }
label: async function gen1() { }
label: enum E {}
label: interface I {}
label: class C { }
label: var a = 1;
label: let b = 1;
label: const c = 1;

label: module M { }
~~~~~~
!!! error TS1235: A namespace declaration is only allowed in a namespace or module.
label: namespace N {}
~~~~~~~~~
!!! error TS1235: A namespace declaration is only allowed in a namespace or module.
label: type T = {}

44 changes: 44 additions & 0 deletions tests/baselines/reference/labeledStatementWithLabel_es2015.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//// [labeledStatementWithLabel_es2015.ts]
label: function fn() { }
label: function* gen() { }
label: async function gen1() { }
label: enum E {}
label: interface I {}
label: class C { }
label: var a = 1;
label: let b = 1;
label: const c = 1;

label: module M { }
label: namespace N {}
label: type T = {}


//// [labeledStatementWithLabel_es2015.js]
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
label: function fn() { }
label: function* gen() { }
label: function gen1() {
return __awaiter(this, void 0, void 0, function* () { });
}
label: {
var E;
(function (E) {
})(E || (E = {}));
}
label:
label: class C {
}
label: var a = 1;
label: let b = 1;
label: const c = 1;
label:
label:
label:
37 changes: 37 additions & 0 deletions tests/baselines/reference/labeledStatementWithLabel_es2015.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
=== tests/cases/conformance/statements/labeledStatements/labeledStatementWithLabel_es2015.ts ===
label: function fn() { }
>fn : Symbol(fn, Decl(labeledStatementWithLabel_es2015.ts, 0, 6))

label: function* gen() { }
>gen : Symbol(gen, Decl(labeledStatementWithLabel_es2015.ts, 1, 6))

label: async function gen1() { }
>gen1 : Symbol(gen1, Decl(labeledStatementWithLabel_es2015.ts, 2, 6))

label: enum E {}
>E : Symbol(E, Decl(labeledStatementWithLabel_es2015.ts, 3, 6))

label: interface I {}
>I : Symbol(I, Decl(labeledStatementWithLabel_es2015.ts, 4, 6))

label: class C { }
>C : Symbol(C, Decl(labeledStatementWithLabel_es2015.ts, 5, 6))

label: var a = 1;
>a : Symbol(a, Decl(labeledStatementWithLabel_es2015.ts, 6, 10))

label: let b = 1;
>b : Symbol(b, Decl(labeledStatementWithLabel_es2015.ts, 7, 10))

label: const c = 1;
>c : Symbol(c, Decl(labeledStatementWithLabel_es2015.ts, 8, 12))

label: module M { }
>M : Symbol(M, Decl(labeledStatementWithLabel_es2015.ts, 10, 6))

label: namespace N {}
>N : Symbol(N, Decl(labeledStatementWithLabel_es2015.ts, 11, 6))

label: type T = {}
>T : Symbol(T, Decl(labeledStatementWithLabel_es2015.ts, 12, 6))

Loading