Merge pull request #8014 from Microsoft/strictBlockScopeFunction

Make function block scoped in strict mode and report error in es5 for block scope level declaration of function
This commit is contained in:
Sheetal Nandi
2016-04-11 16:48:35 -07:00
41 changed files with 841 additions and 336 deletions
+39 -1
View File
@@ -104,6 +104,7 @@ namespace ts {
function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
let file: SourceFile;
let options: CompilerOptions;
let languageVersion: ScriptTarget;
let parent: Node;
let container: Node;
let blockScopeContainer: Node;
@@ -136,6 +137,7 @@ namespace ts {
function bindSourceFile(f: SourceFile, opts: CompilerOptions) {
file = f;
options = opts;
languageVersion = getEmitScriptTarget(options);
inStrictMode = !!file.externalModuleIndicator;
classifiableNames = {};
@@ -149,6 +151,7 @@ namespace ts {
file = undefined;
options = undefined;
languageVersion = undefined;
parent = undefined;
container = undefined;
blockScopeContainer = undefined;
@@ -1125,6 +1128,35 @@ namespace ts {
}
}
function getStrictModeBlockScopeFunctionDeclarationMessage(node: Node) {
// Provide specialized messages to help the user understand why we think they're in
// strict mode.
if (getContainingClass(node)) {
return Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Class_definitions_are_automatically_in_strict_mode;
}
if (file.externalModuleIndicator) {
return Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5_Modules_are_automatically_in_strict_mode;
}
return Diagnostics.Function_declarations_are_not_allowed_inside_blocks_in_strict_mode_when_targeting_ES3_or_ES5;
}
function checkStrictModeFunctionDeclaration(node: FunctionDeclaration) {
if (languageVersion < ScriptTarget.ES6) {
// Report error if function is not top level function declaration
if (blockScopeContainer.kind !== SyntaxKind.SourceFile &&
blockScopeContainer.kind !== SyntaxKind.ModuleDeclaration &&
!isFunctionLike(blockScopeContainer)) {
// We check first if the name is inside class declaration or class expression; if so give explicit message
// otherwise report generic error message.
const errorSpan = getErrorSpanForNode(file, node);
file.bindDiagnostics.push(createFileDiagnostic(file, errorSpan.start, errorSpan.length,
getStrictModeBlockScopeFunctionDeclarationMessage(node)));
}
}
}
function checkStrictModeNumericLiteral(node: LiteralExpression) {
if (inStrictMode && node.isOctalLiteral) {
file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode));
@@ -1640,7 +1672,13 @@ namespace ts {
}
checkStrictModeFunctionName(<FunctionDeclaration>node);
return declareSymbolAndAddToSymbolTable(<Declaration>node, SymbolFlags.Function, SymbolFlags.FunctionExcludes);
if (inStrictMode) {
checkStrictModeFunctionDeclaration(node);
return bindBlockScopedDeclaration(node, SymbolFlags.Function, SymbolFlags.FunctionExcludes);
}
else {
return declareSymbolAndAddToSymbolTable(<Declaration>node, SymbolFlags.Function, SymbolFlags.FunctionExcludes);
}
}
function bindFunctionExpression(node: FunctionExpression) {
+12
View File
@@ -811,6 +811,18 @@
"category": "Error",
"code": 1249
},
"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.": {
"category": "Error",
"code": 1250
},
"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Class definitions are automatically in strict mode.": {
"category": "Error",
"code": 1251
},
"Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.": {
"category": "Error",
"code": 1252
},
"'with' statements are not allowed in an async function block.": {
"category": "Error",
"code": 1300
+115 -112
View File
@@ -256,125 +256,128 @@ class CompilerBaselineRunner extends RunnerBase {
}
// NEWTODO: Type baselines
if (result.errors.length === 0) {
// The full walker simulates the types that you would get from doing a full
// compile. The pull walker simulates the types you get when you just do
// a type query for a random node (like how the LS would do it). Most of the
// time, these will be the same. However, occasionally, they can be different.
// Specifically, when the compiler internally depends on symbol IDs to order
// things, then we may see different results because symbols can be created in a
// different order with 'pull' operations, and thus can produce slightly differing
// output.
//
// For example, with a full type check, we may see a type displayed as: number | string
// But with a pull type check, we may see it as: string | number
//
// These types are equivalent, but depend on what order the compiler observed
// certain parts of the program.
const program = result.program;
const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName));
const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true);
const fullResults: ts.Map<TypeWriterResult[]> = {};
const pullResults: ts.Map<TypeWriterResult[]> = {};
for (const sourceFile of allFiles) {
fullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
pullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
}
// Produce baselines. The first gives the types for all expressions.
// The second gives symbols for all identifiers.
let e1: Error, e2: Error;
try {
checkBaseLines(/*isSymbolBaseLine*/ false);
}
catch (e) {
e1 = e;
}
try {
checkBaseLines(/*isSymbolBaseLine*/ true);
}
catch (e) {
e2 = e;
}
if (e1 || e2) {
throw e1 || e2;
}
if (result.errors.length !== 0) {
return;
}
function checkBaseLines(isSymbolBaseLine: boolean) {
const fullBaseLine = generateBaseLine(fullResults, isSymbolBaseLine);
const pullBaseLine = generateBaseLine(pullResults, isSymbolBaseLine);
// The full walker simulates the types that you would get from doing a full
// compile. The pull walker simulates the types you get when you just do
// a type query for a random node (like how the LS would do it). Most of the
// time, these will be the same. However, occasionally, they can be different.
// Specifically, when the compiler internally depends on symbol IDs to order
// things, then we may see different results because symbols can be created in a
// different order with 'pull' operations, and thus can produce slightly differing
// output.
//
// For example, with a full type check, we may see a type displayed as: number | string
// But with a pull type check, we may see it as: string | number
//
// These types are equivalent, but depend on what order the compiler observed
// certain parts of the program.
const fullExtension = isSymbolBaseLine ? ".symbols" : ".types";
const pullExtension = isSymbolBaseLine ? ".symbols.pull" : ".types.pull";
const program = result.program;
const allFiles = toBeCompiled.concat(otherFiles).filter(file => !!program.getSourceFile(file.unitName));
if (fullBaseLine !== pullBaseLine) {
Harness.Baseline.runBaseline("Correct full information for " + fileName, justName.replace(/\.tsx?/, fullExtension), () => fullBaseLine);
Harness.Baseline.runBaseline("Correct pull information for " + fileName, justName.replace(/\.tsx?/, pullExtension), () => pullBaseLine);
}
else {
Harness.Baseline.runBaseline("Correct information for " + fileName, justName.replace(/\.tsx?/, fullExtension), () => fullBaseLine);
}
const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true);
const fullResults: ts.Map<TypeWriterResult[]> = {};
const pullResults: ts.Map<TypeWriterResult[]> = {};
for (const sourceFile of allFiles) {
fullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
pullResults[sourceFile.unitName] = fullWalker.getTypeAndSymbols(sourceFile.unitName);
}
// Produce baselines. The first gives the types for all expressions.
// The second gives symbols for all identifiers.
let e1: Error, e2: Error;
try {
checkBaseLines(/*isSymbolBaseLine*/ false);
}
catch (e) {
e1 = e;
}
try {
checkBaseLines(/*isSymbolBaseLine*/ true);
}
catch (e) {
e2 = e;
}
if (e1 || e2) {
throw e1 || e2;
}
return;
function checkBaseLines(isSymbolBaseLine: boolean) {
const fullBaseLine = generateBaseLine(fullResults, isSymbolBaseLine);
const pullBaseLine = generateBaseLine(pullResults, isSymbolBaseLine);
const fullExtension = isSymbolBaseLine ? ".symbols" : ".types";
const pullExtension = isSymbolBaseLine ? ".symbols.pull" : ".types.pull";
if (fullBaseLine !== pullBaseLine) {
Harness.Baseline.runBaseline("Correct full information for " + fileName, justName.replace(/\.tsx?/, fullExtension), () => fullBaseLine);
Harness.Baseline.runBaseline("Correct pull information for " + fileName, justName.replace(/\.tsx?/, pullExtension), () => pullBaseLine);
}
function generateBaseLine(typeWriterResults: ts.Map<TypeWriterResult[]>, isSymbolBaseline: boolean): string {
const typeLines: string[] = [];
const typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {};
allFiles.forEach(file => {
const codeLines = file.content.split("\n");
typeWriterResults[file.unitName].forEach(result => {
if (isSymbolBaseline && !result.symbol) {
return;
}
const typeOrSymbolString = isSymbolBaseline ? result.symbol : result.type;
const formattedLine = result.sourceText.replace(/\r?\n/g, "") + " : " + typeOrSymbolString;
if (!typeMap[file.unitName]) {
typeMap[file.unitName] = {};
}
let typeInfo = [formattedLine];
const existingTypeInfo = typeMap[file.unitName][result.line];
if (existingTypeInfo) {
typeInfo = existingTypeInfo.concat(typeInfo);
}
typeMap[file.unitName][result.line] = typeInfo;
});
typeLines.push("=== " + file.unitName + " ===\r\n");
for (let i = 0; i < codeLines.length; i++) {
const currentCodeLine = codeLines[i];
typeLines.push(currentCodeLine + "\r\n");
if (typeMap[file.unitName]) {
const typeInfo = typeMap[file.unitName][i];
if (typeInfo) {
typeInfo.forEach(ty => {
typeLines.push(">" + ty + "\r\n");
});
if (i + 1 < codeLines.length && (codeLines[i + 1].match(/^\s*[{|}]\s*$/) || codeLines[i + 1].trim() === "")) {
}
else {
typeLines.push("\r\n");
}
}
}
else {
typeLines.push("No type information for this code.");
}
}
});
return typeLines.join("");
else {
Harness.Baseline.runBaseline("Correct information for " + fileName, justName.replace(/\.tsx?/, fullExtension), () => fullBaseLine);
}
}
function generateBaseLine(typeWriterResults: ts.Map<TypeWriterResult[]>, isSymbolBaseline: boolean): string {
const typeLines: string[] = [];
const typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {};
allFiles.forEach(file => {
const codeLines = file.content.split("\n");
typeWriterResults[file.unitName].forEach(result => {
if (isSymbolBaseline && !result.symbol) {
return;
}
const typeOrSymbolString = isSymbolBaseline ? result.symbol : result.type;
const formattedLine = result.sourceText.replace(/\r?\n/g, "") + " : " + typeOrSymbolString;
if (!typeMap[file.unitName]) {
typeMap[file.unitName] = {};
}
let typeInfo = [formattedLine];
const existingTypeInfo = typeMap[file.unitName][result.line];
if (existingTypeInfo) {
typeInfo = existingTypeInfo.concat(typeInfo);
}
typeMap[file.unitName][result.line] = typeInfo;
});
typeLines.push("=== " + file.unitName + " ===\r\n");
for (let i = 0; i < codeLines.length; i++) {
const currentCodeLine = codeLines[i];
typeLines.push(currentCodeLine + "\r\n");
if (typeMap[file.unitName]) {
const typeInfo = typeMap[file.unitName][i];
if (typeInfo) {
typeInfo.forEach(ty => {
typeLines.push(">" + ty + "\r\n");
});
if (i + 1 < codeLines.length && (codeLines[i + 1].match(/^\s*[{|}]\s*$/) || codeLines[i + 1].trim() === "")) {
}
else {
typeLines.push("\r\n");
}
}
}
else {
typeLines.push("No type information for this code.");
}
}
});
return typeLines.join("");
}
});
});
}
@@ -0,0 +1,13 @@
//// [blockScopedFunctionDeclarationES5.ts]
if (true) {
function foo() { }
foo();
}
foo();
//// [blockScopedFunctionDeclarationES5.js]
if (true) {
function foo() { }
foo();
}
foo();
@@ -0,0 +1,11 @@
=== tests/cases/compiler/blockScopedFunctionDeclarationES5.ts ===
if (true) {
function foo() { }
>foo : Symbol(foo, Decl(blockScopedFunctionDeclarationES5.ts, 0, 11))
foo();
>foo : Symbol(foo, Decl(blockScopedFunctionDeclarationES5.ts, 0, 11))
}
foo();
>foo : Symbol(foo, Decl(blockScopedFunctionDeclarationES5.ts, 0, 11))
@@ -0,0 +1,15 @@
=== tests/cases/compiler/blockScopedFunctionDeclarationES5.ts ===
if (true) {
>true : boolean
function foo() { }
>foo : () => void
foo();
>foo() : void
>foo : () => void
}
foo();
>foo() : void
>foo : () => void
@@ -0,0 +1,13 @@
//// [blockScopedFunctionDeclarationES6.ts]
if (true) {
function foo() { }
foo();
}
foo();
//// [blockScopedFunctionDeclarationES6.js]
if (true) {
function foo() { }
foo();
}
foo();
@@ -0,0 +1,11 @@
=== tests/cases/compiler/blockScopedFunctionDeclarationES6.ts ===
if (true) {
function foo() { }
>foo : Symbol(foo, Decl(blockScopedFunctionDeclarationES6.ts, 0, 11))
foo();
>foo : Symbol(foo, Decl(blockScopedFunctionDeclarationES6.ts, 0, 11))
}
foo();
>foo : Symbol(foo, Decl(blockScopedFunctionDeclarationES6.ts, 0, 11))
@@ -0,0 +1,15 @@
=== tests/cases/compiler/blockScopedFunctionDeclarationES6.ts ===
if (true) {
>true : boolean
function foo() { }
>foo : () => void
foo();
>foo() : void
>foo : () => void
}
foo();
>foo() : void
>foo : () => void
@@ -0,0 +1,18 @@
tests/cases/compiler/blockScopedFunctionDeclarationInStrictClass.ts(4,22): error TS1251: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Class definitions are automatically in strict mode.
tests/cases/compiler/blockScopedFunctionDeclarationInStrictClass.ts(7,9): error TS2304: Cannot find name 'foo'.
==== tests/cases/compiler/blockScopedFunctionDeclarationInStrictClass.ts (2 errors) ====
class c {
method() {
if (true) {
function foo() { }
~~~
!!! error TS1251: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Class definitions are automatically in strict mode.
foo(); // ok
}
foo(); // not ok
~~~
!!! error TS2304: Cannot find name 'foo'.
}
}
@@ -0,0 +1,24 @@
//// [blockScopedFunctionDeclarationInStrictClass.ts]
class c {
method() {
if (true) {
function foo() { }
foo(); // ok
}
foo(); // not ok
}
}
//// [blockScopedFunctionDeclarationInStrictClass.js]
var c = (function () {
function c() {
}
c.prototype.method = function () {
if (true) {
function foo() { }
foo(); // ok
}
foo(); // not ok
};
return c;
}());
@@ -0,0 +1,15 @@
tests/cases/compiler/blockScopedFunctionDeclarationInStrictModule.ts(2,14): error TS1252: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.
tests/cases/compiler/blockScopedFunctionDeclarationInStrictModule.ts(6,10): error TS2304: Cannot find name 'foo'.
==== tests/cases/compiler/blockScopedFunctionDeclarationInStrictModule.ts (2 errors) ====
if (true) {
function foo() { }
~~~
!!! error TS1252: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'. Modules are automatically in strict mode.
foo(); // ok
}
export = foo; // not ok
~~~
!!! error TS2304: Cannot find name 'foo'.
@@ -0,0 +1,16 @@
//// [blockScopedFunctionDeclarationInStrictModule.ts]
if (true) {
function foo() { }
foo(); // ok
}
export = foo; // not ok
//// [blockScopedFunctionDeclarationInStrictModule.js]
define(["require", "exports"], function (require, exports) {
"use strict";
if (true) {
function foo() { }
foo(); // ok
}
});
@@ -0,0 +1,15 @@
tests/cases/compiler/blockScopedFunctionDeclarationStrictES5.ts(3,14): error TS1250: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.
tests/cases/compiler/blockScopedFunctionDeclarationStrictES5.ts(6,1): error TS2304: Cannot find name 'foo'.
==== tests/cases/compiler/blockScopedFunctionDeclarationStrictES5.ts (2 errors) ====
"use strict";
if (true) {
function foo() { } // Error to declare function in block scope
~~~
!!! error TS1250: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.
foo(); // This call should be ok
}
foo(); // Error to find name foo
~~~
!!! error TS2304: Cannot find name 'foo'.
@@ -0,0 +1,15 @@
//// [blockScopedFunctionDeclarationStrictES5.ts]
"use strict";
if (true) {
function foo() { } // Error to declare function in block scope
foo(); // This call should be ok
}
foo(); // Error to find name foo
//// [blockScopedFunctionDeclarationStrictES5.js]
"use strict";
if (true) {
function foo() { } // Error to declare function in block scope
foo(); // This call should be ok
}
foo(); // Error to find name foo
@@ -0,0 +1,12 @@
tests/cases/compiler/blockScopedFunctionDeclarationStrictES6.ts(6,1): error TS2304: Cannot find name 'foo'.
==== tests/cases/compiler/blockScopedFunctionDeclarationStrictES6.ts (1 errors) ====
"use strict";
if (true) {
function foo() { } // Allowed to declare block scope function
foo(); // This call should be ok
}
foo(); // Cannot find name since foo is block scoped
~~~
!!! error TS2304: Cannot find name 'foo'.
@@ -0,0 +1,15 @@
//// [blockScopedFunctionDeclarationStrictES6.ts]
"use strict";
if (true) {
function foo() { } // Allowed to declare block scope function
foo(); // This call should be ok
}
foo(); // Cannot find name since foo is block scoped
//// [blockScopedFunctionDeclarationStrictES6.js]
"use strict";
if (true) {
function foo() { } // Allowed to declare block scope function
foo(); // This call should be ok
}
foo(); // Cannot find name since foo is block scoped
@@ -0,0 +1,37 @@
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(3,18): error TS2393: Duplicate function implementation.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(5,9): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(8,18): error TS2393: Duplicate function implementation.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(10,9): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(12,5): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts(16,1): error TS2346: Supplied parameters do not match any signature of call target.
==== tests/cases/compiler/blockScopedSameNameFunctionDeclarationES5.ts (6 errors) ====
function foo(a: number) {
if (a === 1) {
function foo() { } // duplicate function
~~~
!!! error TS2393: Duplicate function implementation.
foo();
foo(10); // not ok
~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
}
else {
function foo() { } // duplicate function
~~~
!!! error TS2393: Duplicate function implementation.
foo();
foo(10); // not ok
~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
}
foo(10); // not ok
~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
foo();
}
foo(10);
foo(); // not ok - needs number
~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
@@ -0,0 +1,35 @@
//// [blockScopedSameNameFunctionDeclarationES5.ts]
function foo(a: number) {
if (a === 1) {
function foo() { } // duplicate function
foo();
foo(10); // not ok
}
else {
function foo() { } // duplicate function
foo();
foo(10); // not ok
}
foo(10); // not ok
foo();
}
foo(10);
foo(); // not ok - needs number
//// [blockScopedSameNameFunctionDeclarationES5.js]
function foo(a) {
if (a === 1) {
function foo() { } // duplicate function
foo();
foo(10); // not ok
}
else {
function foo() { } // duplicate function
foo();
foo(10); // not ok
}
foo(10); // not ok
foo();
}
foo(10);
foo(); // not ok - needs number
@@ -0,0 +1,37 @@
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(3,18): error TS2393: Duplicate function implementation.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(5,9): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(8,18): error TS2393: Duplicate function implementation.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(10,9): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(12,5): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts(16,1): error TS2346: Supplied parameters do not match any signature of call target.
==== tests/cases/compiler/blockScopedSameNameFunctionDeclarationES6.ts (6 errors) ====
function foo(a: number) {
if (a === 10) {
function foo() { } // duplicate
~~~
!!! error TS2393: Duplicate function implementation.
foo();
foo(10); // not ok
~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
}
else {
function foo() { } // duplicate
~~~
!!! error TS2393: Duplicate function implementation.
foo();
foo(10);// not ok
~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
}
foo(10); // not ok
~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
foo();
}
foo(10);
foo(); // not ok - needs number
~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
@@ -0,0 +1,35 @@
//// [blockScopedSameNameFunctionDeclarationES6.ts]
function foo(a: number) {
if (a === 10) {
function foo() { } // duplicate
foo();
foo(10); // not ok
}
else {
function foo() { } // duplicate
foo();
foo(10);// not ok
}
foo(10); // not ok
foo();
}
foo(10);
foo(); // not ok - needs number
//// [blockScopedSameNameFunctionDeclarationES6.js]
function foo(a) {
if (a === 10) {
function foo() { } // duplicate
foo();
foo(10); // not ok
}
else {
function foo() { } // duplicate
foo();
foo(10); // not ok
}
foo(10); // not ok
foo();
}
foo(10);
foo(); // not ok - needs number
@@ -0,0 +1,38 @@
tests/cases/compiler/blockScopedSameNameFunctionDeclarationStrictES5.ts(4,18): error TS1250: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationStrictES5.ts(6,9): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationStrictES5.ts(9,18): error TS1250: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationStrictES5.ts(11,9): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationStrictES5.ts(14,5): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationStrictES5.ts(17,1): error TS2346: Supplied parameters do not match any signature of call target.
==== tests/cases/compiler/blockScopedSameNameFunctionDeclarationStrictES5.ts (6 errors) ====
"use strict";
function foo(a: number) {
if (a === 1) {
function foo() { } // Error to declare function in block scope
~~~
!!! error TS1250: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.
foo();
foo(10); // not ok
~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
}
else {
function foo() { } // Error to declare function in block scope
~~~
!!! error TS1250: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.
foo();
foo(10); // not ok
~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
}
foo(10);
foo(); // not ok - needs number
~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
}
foo(10);
foo(); // not ok - needs number
~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
@@ -0,0 +1,37 @@
//// [blockScopedSameNameFunctionDeclarationStrictES5.ts]
"use strict";
function foo(a: number) {
if (a === 1) {
function foo() { } // Error to declare function in block scope
foo();
foo(10); // not ok
}
else {
function foo() { } // Error to declare function in block scope
foo();
foo(10); // not ok
}
foo(10);
foo(); // not ok - needs number
}
foo(10);
foo(); // not ok - needs number
//// [blockScopedSameNameFunctionDeclarationStrictES5.js]
"use strict";
function foo(a) {
if (a === 1) {
function foo() { } // Error to declare function in block scope
foo();
foo(10); // not ok
}
else {
function foo() { } // Error to declare function in block scope
foo();
foo(10); // not ok
}
foo(10);
foo(); // not ok - needs number
}
foo(10);
foo(); // not ok - needs number
@@ -0,0 +1,32 @@
tests/cases/compiler/blockScopedSameNameFunctionDeclarationStrictES6.ts(6,9): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationStrictES6.ts(11,9): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationStrictES6.ts(14,5): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/compiler/blockScopedSameNameFunctionDeclarationStrictES6.ts(17,1): error TS2346: Supplied parameters do not match any signature of call target.
==== tests/cases/compiler/blockScopedSameNameFunctionDeclarationStrictES6.ts (4 errors) ====
"use strict";
function foo(a: number) {
if (a === 10) {
function foo() { }
foo();
foo(10); // not ok
~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
}
else {
function foo() { }
foo();
foo(10); // not ok
~~~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
}
foo(10);
foo(); // not ok
~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
}
foo(10);
foo(); // not ok - needs number
~~~~~
!!! error TS2346: Supplied parameters do not match any signature of call target.
@@ -0,0 +1,37 @@
//// [blockScopedSameNameFunctionDeclarationStrictES6.ts]
"use strict";
function foo(a: number) {
if (a === 10) {
function foo() { }
foo();
foo(10); // not ok
}
else {
function foo() { }
foo();
foo(10); // not ok
}
foo(10);
foo(); // not ok
}
foo(10);
foo(); // not ok - needs number
//// [blockScopedSameNameFunctionDeclarationStrictES6.js]
"use strict";
function foo(a) {
if (a === 10) {
function foo() { }
foo();
foo(10); // not ok
}
else {
function foo() { }
foo();
foo(10); // not ok
}
foo(10);
foo(); // not ok
}
foo(10);
foo(); // not ok - needs number
@@ -0,0 +1,40 @@
tests/cases/compiler/downlevelLetConst18.ts(5,14): error TS1250: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.
tests/cases/compiler/downlevelLetConst18.ts(9,14): error TS1250: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.
==== tests/cases/compiler/downlevelLetConst18.ts (2 errors) ====
'use strict'
for (let x; ;) {
function foo() { x };
~~~
!!! error TS1250: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.
}
for (let x; ;) {
function foo1() { x };
~~~~
!!! error TS1250: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.
}
for (let x; ;) {
(() => { x })();
}
for (const x = 1; ;) {
(() => { x })();
}
for (let x; ;) {
({ foo() { x }})
}
for (let x; ;) {
({ get foo() { return x } })
}
for (let x; ;) {
({ set foo(v) { x } })
}
@@ -1,59 +0,0 @@
=== tests/cases/compiler/downlevelLetConst18.ts ===
'use strict'
for (let x; ;) {
>x : Symbol(x, Decl(downlevelLetConst18.ts, 3, 8))
function foo() { x };
>foo : Symbol(foo, Decl(downlevelLetConst18.ts, 3, 16))
>x : Symbol(x, Decl(downlevelLetConst18.ts, 3, 8))
}
for (let x; ;) {
>x : Symbol(x, Decl(downlevelLetConst18.ts, 7, 8))
function foo1() { x };
>foo1 : Symbol(foo1, Decl(downlevelLetConst18.ts, 7, 16))
>x : Symbol(x, Decl(downlevelLetConst18.ts, 7, 8))
}
for (let x; ;) {
>x : Symbol(x, Decl(downlevelLetConst18.ts, 11, 8))
(() => { x })();
>x : Symbol(x, Decl(downlevelLetConst18.ts, 11, 8))
}
for (const x = 1; ;) {
>x : Symbol(x, Decl(downlevelLetConst18.ts, 15, 10))
(() => { x })();
>x : Symbol(x, Decl(downlevelLetConst18.ts, 15, 10))
}
for (let x; ;) {
>x : Symbol(x, Decl(downlevelLetConst18.ts, 19, 8))
({ foo() { x }})
>foo : Symbol(foo, Decl(downlevelLetConst18.ts, 20, 6))
>x : Symbol(x, Decl(downlevelLetConst18.ts, 19, 8))
}
for (let x; ;) {
>x : Symbol(x, Decl(downlevelLetConst18.ts, 23, 8))
({ get foo() { return x } })
>foo : Symbol(foo, Decl(downlevelLetConst18.ts, 24, 6))
>x : Symbol(x, Decl(downlevelLetConst18.ts, 23, 8))
}
for (let x; ;) {
>x : Symbol(x, Decl(downlevelLetConst18.ts, 27, 8))
({ set foo(v) { x } })
>foo : Symbol(foo, Decl(downlevelLetConst18.ts, 28, 6))
>v : Symbol(v, Decl(downlevelLetConst18.ts, 28, 15))
>x : Symbol(x, Decl(downlevelLetConst18.ts, 27, 8))
}
@@ -1,73 +0,0 @@
=== tests/cases/compiler/downlevelLetConst18.ts ===
'use strict'
>'use strict' : string
for (let x; ;) {
>x : any
function foo() { x };
>foo : () => void
>x : any
}
for (let x; ;) {
>x : any
function foo1() { x };
>foo1 : () => void
>x : any
}
for (let x; ;) {
>x : any
(() => { x })();
>(() => { x })() : void
>(() => { x }) : () => void
>() => { x } : () => void
>x : any
}
for (const x = 1; ;) {
>x : number
>1 : number
(() => { x })();
>(() => { x })() : void
>(() => { x }) : () => void
>() => { x } : () => void
>x : number
}
for (let x; ;) {
>x : any
({ foo() { x }})
>({ foo() { x }}) : { foo(): void; }
>{ foo() { x }} : { foo(): void; }
>foo : () => void
>x : any
}
for (let x; ;) {
>x : any
({ get foo() { return x } })
>({ get foo() { return x } }) : { readonly foo: any; }
>{ get foo() { return x } } : { readonly foo: any; }
>foo : any
>x : any
}
for (let x; ;) {
>x : any
({ set foo(v) { x } })
>({ set foo(v) { x } }) : { foo: any; }
>{ set foo(v) { x } } : { foo: any; }
>foo : any
>v : any
>x : any
}
@@ -0,0 +1,25 @@
tests/cases/compiler/downlevelLetConst19.ts(9,14): error TS1250: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.
==== tests/cases/compiler/downlevelLetConst19.ts (1 errors) ====
'use strict'
declare function use(a: any);
var x;
function a() {
{
let x;
use(x);
function b() {
~
!!! error TS1250: Function declarations are not allowed inside blocks in strict mode when targeting 'ES3' or 'ES5'.
{
let x;
use(x);
}
use(x);
}
}
use(x)
}
use(x)
@@ -1,42 +0,0 @@
=== tests/cases/compiler/downlevelLetConst19.ts ===
'use strict'
declare function use(a: any);
>use : Symbol(use, Decl(downlevelLetConst19.ts, 0, 12))
>a : Symbol(a, Decl(downlevelLetConst19.ts, 1, 21))
var x;
>x : Symbol(x, Decl(downlevelLetConst19.ts, 2, 3))
function a() {
>a : Symbol(a, Decl(downlevelLetConst19.ts, 2, 6))
{
let x;
>x : Symbol(x, Decl(downlevelLetConst19.ts, 5, 7))
use(x);
>use : Symbol(use, Decl(downlevelLetConst19.ts, 0, 12))
>x : Symbol(x, Decl(downlevelLetConst19.ts, 5, 7))
function b() {
>b : Symbol(b, Decl(downlevelLetConst19.ts, 6, 11))
{
let x;
>x : Symbol(x, Decl(downlevelLetConst19.ts, 10, 15))
use(x);
>use : Symbol(use, Decl(downlevelLetConst19.ts, 0, 12))
>x : Symbol(x, Decl(downlevelLetConst19.ts, 10, 15))
}
use(x);
>use : Symbol(use, Decl(downlevelLetConst19.ts, 0, 12))
>x : Symbol(x, Decl(downlevelLetConst19.ts, 5, 7))
}
}
use(x)
>use : Symbol(use, Decl(downlevelLetConst19.ts, 0, 12))
>x : Symbol(x, Decl(downlevelLetConst19.ts, 2, 3))
}
use(x)
>use : Symbol(use, Decl(downlevelLetConst19.ts, 0, 12))
>x : Symbol(x, Decl(downlevelLetConst19.ts, 2, 3))
@@ -1,49 +0,0 @@
=== tests/cases/compiler/downlevelLetConst19.ts ===
'use strict'
>'use strict' : string
declare function use(a: any);
>use : (a: any) => any
>a : any
var x;
>x : any
function a() {
>a : () => void
{
let x;
>x : any
use(x);
>use(x) : any
>use : (a: any) => any
>x : any
function b() {
>b : () => void
{
let x;
>x : any
use(x);
>use(x) : any
>use : (a: any) => any
>x : any
}
use(x);
>use(x) : any
>use : (a: any) => any
>x : any
}
}
use(x)
>use(x) : any
>use : (a: any) => any
>x : any
}
use(x)
>use(x) : any
>use : (a: any) => any
>x : any
@@ -0,0 +1,6 @@
// @target: ES5
if (true) {
function foo() { }
foo();
}
foo();
@@ -0,0 +1,6 @@
// @target: ES6
if (true) {
function foo() { }
foo();
}
foo();
@@ -0,0 +1,10 @@
// @target: ES5
class c {
method() {
if (true) {
function foo() { }
foo(); // ok
}
foo(); // not ok
}
}
@@ -0,0 +1,8 @@
// @target: ES5
// @module: amd
if (true) {
function foo() { }
foo(); // ok
}
export = foo; // not ok
@@ -0,0 +1,7 @@
// @target: ES5
"use strict";
if (true) {
function foo() { } // Error to declare function in block scope
foo(); // This call should be ok
}
foo(); // Error to find name foo
@@ -0,0 +1,7 @@
// @target: ES6
"use strict";
if (true) {
function foo() { } // Allowed to declare block scope function
foo(); // This call should be ok
}
foo(); // Cannot find name since foo is block scoped
@@ -0,0 +1,17 @@
// @target: ES5
function foo(a: number) {
if (a === 1) {
function foo() { } // duplicate function
foo();
foo(10); // not ok
}
else {
function foo() { } // duplicate function
foo();
foo(10); // not ok
}
foo(10); // not ok
foo();
}
foo(10);
foo(); // not ok - needs number
@@ -0,0 +1,17 @@
// @target: ES6
function foo(a: number) {
if (a === 10) {
function foo() { } // duplicate
foo();
foo(10); // not ok
}
else {
function foo() { } // duplicate
foo();
foo(10);// not ok
}
foo(10); // not ok
foo();
}
foo(10);
foo(); // not ok - needs number
@@ -0,0 +1,18 @@
// @target: ES5
"use strict";
function foo(a: number) {
if (a === 1) {
function foo() { } // Error to declare function in block scope
foo();
foo(10); // not ok
}
else {
function foo() { } // Error to declare function in block scope
foo();
foo(10); // not ok
}
foo(10);
foo(); // not ok - needs number
}
foo(10);
foo(); // not ok - needs number
@@ -0,0 +1,18 @@
// @target: ES6
"use strict";
function foo(a: number) {
if (a === 10) {
function foo() { }
foo();
foo(10); // not ok
}
else {
function foo() { }
foo();
foo(10); // not ok
}
foo(10);
foo(); // not ok
}
foo(10);
foo(); // not ok - needs number