diff --git a/Gulpfile.ts b/Gulpfile.ts index 72766de0857..bea8eb30de8 100644 --- a/Gulpfile.ts +++ b/Gulpfile.ts @@ -17,7 +17,6 @@ declare module "gulp-typescript" { stripInternal?: boolean; types?: string[]; } - interface CompileStream extends NodeJS.ReadWriteStream { } // Either gulp or gulp-typescript has some odd typings which don't reflect reality, making this required } import * as insert from "gulp-insert"; import * as sourcemaps from "gulp-sourcemaps"; @@ -169,7 +168,7 @@ for (const i in libraryTargets) { gulp.task(target, false, [], function() { return gulp.src(sources) .pipe(newer(target)) - .pipe(concat(target, { newLine: "" })) + .pipe(concat(target, { newLine: "\n\n" })) .pipe(gulp.dest(".")); }); } @@ -380,10 +379,10 @@ gulp.task(builtLocalCompiler, false, [servicesFile], () => { return localCompilerProject.src() .pipe(newer(builtLocalCompiler)) .pipe(sourcemaps.init()) - .pipe(tsc(localCompilerProject)) + .pipe(localCompilerProject()) .pipe(prependCopyright()) .pipe(sourcemaps.write(".")) - .pipe(gulp.dest(builtLocalDirectory)); + .pipe(gulp.dest(".")); }); gulp.task(servicesFile, false, ["lib", "generate-diagnostics"], () => { @@ -391,7 +390,7 @@ gulp.task(servicesFile, false, ["lib", "generate-diagnostics"], () => { const {js, dts} = servicesProject.src() .pipe(newer(servicesFile)) .pipe(sourcemaps.init()) - .pipe(tsc(servicesProject)); + .pipe(servicesProject()); const completedJs = js.pipe(prependCopyright()) .pipe(sourcemaps.write(".")); const completedDts = dts.pipe(prependCopyright(/*outputCopyright*/true)) @@ -409,13 +408,13 @@ gulp.task(servicesFile, false, ["lib", "generate-diagnostics"], () => { file.path = nodeDefinitionsFile; return content + "\r\nexport = ts;"; })) - .pipe(gulp.dest(builtLocalDirectory)), + .pipe(gulp.dest(".")), completedDts.pipe(clone()) .pipe(insert.transform((content, file) => { file.path = nodeStandaloneDefinitionsFile; return content.replace(/declare (namespace|module) ts/g, 'declare module "typescript"'); })) - ]).pipe(gulp.dest(builtLocalDirectory)); + ]).pipe(gulp.dest(".")); }); // cancellationToken.js @@ -425,7 +424,7 @@ gulp.task(cancellationTokenJs, false, [servicesFile], () => { return cancellationTokenProject.src() .pipe(newer(cancellationTokenJs)) .pipe(sourcemaps.init()) - .pipe(tsc(cancellationTokenProject)) + .pipe(cancellationTokenProject()) .pipe(prependCopyright()) .pipe(sourcemaps.write(".")) .pipe(gulp.dest(builtLocalDirectory)); @@ -438,10 +437,10 @@ gulp.task(typingsInstallerJs, false, [servicesFile], () => { return cancellationTokenProject.src() .pipe(newer(typingsInstallerJs)) .pipe(sourcemaps.init()) - .pipe(tsc(cancellationTokenProject)) + .pipe(cancellationTokenProject()) .pipe(prependCopyright()) .pipe(sourcemaps.write(".")) - .pipe(gulp.dest(builtLocalDirectory)); + .pipe(gulp.dest(".")); }); const serverFile = path.join(builtLocalDirectory, "tsserver.js"); @@ -451,10 +450,10 @@ gulp.task(serverFile, false, [servicesFile, typingsInstallerJs, cancellationToke return serverProject.src() .pipe(newer(serverFile)) .pipe(sourcemaps.init()) - .pipe(tsc(serverProject)) + .pipe(serverProject()) .pipe(prependCopyright()) .pipe(sourcemaps.write(".")) - .pipe(gulp.dest(builtLocalDirectory)); + .pipe(gulp.dest(".")); }); const tsserverLibraryFile = path.join(builtLocalDirectory, "tsserverlibrary.js"); @@ -465,14 +464,14 @@ gulp.task(tsserverLibraryFile, false, [servicesFile], (done) => { const {js, dts}: { js: NodeJS.ReadableStream, dts: NodeJS.ReadableStream } = serverLibraryProject.src() .pipe(sourcemaps.init()) .pipe(newer(tsserverLibraryFile)) - .pipe(tsc(serverLibraryProject)); + .pipe(serverLibraryProject()); return merge2([ js.pipe(prependCopyright()) .pipe(sourcemaps.write(".")) - .pipe(gulp.dest(builtLocalDirectory)), + .pipe(gulp.dest(".")), dts.pipe(prependCopyright()) - .pipe(gulp.dest(builtLocalDirectory)) + .pipe(gulp.dest(".")) ]); }); @@ -544,9 +543,9 @@ gulp.task(run, false, [servicesFile], () => { return testProject.src() .pipe(newer(run)) .pipe(sourcemaps.init()) - .pipe(tsc(testProject)) + .pipe(testProject()) .pipe(sourcemaps.write(".", { includeContent: false, sourceRoot: "../../" })) - .pipe(gulp.dest(builtLocalDirectory)); + .pipe(gulp.dest(".")); }); const internalTests = "internal/"; @@ -730,7 +729,7 @@ gulp.task("browserify", "Runs browserify on run.js to produce a file suitable fo return testProject.src() .pipe(newer("built/local/bundle.js")) .pipe(sourcemaps.init()) - .pipe(tsc(testProject)) + .pipe(testProject) .pipe(through2.obj((file, enc, next) => { const originalMap = file.sourceMap; const prebundledContent = file.contents.toString(); diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index e2d31162127..2fe7d30ab56 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -964,7 +964,11 @@ namespace ts { currentFlow = preTryFlow; bind(node.finallyBlock); } - currentFlow = finishFlowLabel(postFinallyLabel); + // if try statement has finally block and flow after finally block is unreachable - keep it + // otherwise use whatever flow was accumulated at postFinallyLabel + if (!node.finallyBlock || !(currentFlow.flags & FlowFlags.Unreachable)) { + currentFlow = finishFlowLabel(postFinallyLabel); + } } function bindSwitchStatement(node: SwitchStatement): void { diff --git a/src/compiler/transformers/es6.ts b/src/compiler/transformers/es6.ts index 4f2720c1507..e3ee1dd4c3a 100644 --- a/src/compiler/transformers/es6.ts +++ b/src/compiler/transformers/es6.ts @@ -1689,7 +1689,7 @@ namespace ts { assignment = flattenVariableDestructuringToExpression(context, decl, hoistVariableDeclaration, /*nameSubstitution*/ undefined, visitor); } else { - assignment = createBinary(decl.name, SyntaxKind.EqualsToken, decl.initializer); + assignment = createBinary(decl.name, SyntaxKind.EqualsToken, visitNode(decl.initializer, visitor, isExpression)); } (assignments || (assignments = [])).push(assignment); } diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 988e87284c3..5b934cc4b0b 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -51,8 +51,8 @@ namespace ts.projectSystem { export class TestTypingsInstaller extends TI.TypingsInstaller implements server.ITypingsInstaller { protected projectService: server.ProjectService; - constructor(readonly globalTypingsCacheLocation: string, throttleLimit: number, readonly installTypingHost: server.ServerHost) { - super(globalTypingsCacheLocation, "npm", safeList.path, throttleLimit); + constructor(readonly globalTypingsCacheLocation: string, throttleLimit: number, readonly installTypingHost: server.ServerHost, log?: TI.Log) { + super(globalTypingsCacheLocation, "npm", safeList.path, throttleLimit, log); this.init(); } diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 117ca65cb64..d79a1a7723c 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -11,11 +11,12 @@ namespace ts.projectSystem { } class Installer extends TestTypingsInstaller { - constructor(host: server.ServerHost, p?: InstallerParams) { + constructor(host: server.ServerHost, p?: InstallerParams, log?: TI.Log) { super( (p && p.globalTypingsCacheLocation) || "/a/data", (p && p.throttleLimit) || 5, - host); + host, + log); } installAll(expectedView: typeof TI.NpmViewRequest[], expectedInstall: typeof TI.NpmInstallRequest[]) { @@ -685,10 +686,10 @@ namespace ts.projectSystem { }; const bowerJson = { path: "/bower.json", - content: JSON.stringify({ - "dependencies": { - "jquery": "^3.1.0" - } + content: JSON.stringify({ + "dependencies": { + "jquery": "^3.1.0" + } }) }; const jqueryDTS = { @@ -720,4 +721,60 @@ namespace ts.projectSystem { checkProjectActualFiles(p, [app.path, jqueryDTS.path]); }); }); + + describe("Validate package name:", () => { + it ("name cannot be too long", () => { + let packageName = "a"; + for (let i = 0; i < 8; i++) { + packageName += packageName; + } + assert.equal(TI.validatePackageName(packageName), TI.PackageNameValidationResult.NameTooLong); + }); + it ("name cannot start with dot", () => { + assert.equal(TI.validatePackageName(".foo"), TI.PackageNameValidationResult.NameStartsWithDot); + }); + it ("name cannot start with underscore", () => { + assert.equal(TI.validatePackageName("_foo"), TI.PackageNameValidationResult.NameStartsWithUnderscore); + }); + it ("scoped packages not supported", () => { + assert.equal(TI.validatePackageName("@scope/bar"), TI.PackageNameValidationResult.ScopedPackagesNotSupported); + }); + it ("non URI safe characters are not supported", () => { + assert.equal(TI.validatePackageName(" scope "), TI.PackageNameValidationResult.NameContainsNonURISafeCharacters); + assert.equal(TI.validatePackageName("; say ‘Hello from TypeScript!’ #"), TI.PackageNameValidationResult.NameContainsNonURISafeCharacters); + assert.equal(TI.validatePackageName("a/b/c"), TI.PackageNameValidationResult.NameContainsNonURISafeCharacters); + }); + }); + + describe("Invalid package names", () => { + it ("should not be installed", () => { + const f1 = { + path: "/a/b/app.js", + content: "let x = 1" + }; + const packageJson = { + path: "/a/b/package.json", + content: JSON.stringify({ + "dependencies": { + "; say ‘Hello from TypeScript!’ #": "0.0.x" + } + }) + }; + const messages: string[] = []; + const host = createServerHost([f1, packageJson]); + const installer = new (class extends Installer { + constructor() { + super(host, { globalTypingsCacheLocation: "/tmp" }, { isEnabled: () => true, writeLine: msg => messages.push(msg) }); + } + runCommand(requestKind: TI.RequestKind, requestId: number, command: string, cwd: string, cb: server.typingsInstaller.RequestCompletedAction) { + assert(false, "runCommand should not be invoked"); + } + })(); + const projectService = createProjectService(host, { typingsInstaller: installer }); + projectService.openClientFile(f1.path); + + installer.checkPendingCommands([]); + assert.isTrue(messages.indexOf("Package name '; say ‘Hello from TypeScript!’ #' contains non URI safe characters") > 0, "should find package with invalid name"); + }); + }); } \ No newline at end of file diff --git a/src/server/cancellationToken/tsconfig.json b/src/server/cancellationToken/tsconfig.json index 94c81aa644f..1245fc34fd5 100644 --- a/src/server/cancellationToken/tsconfig.json +++ b/src/server/cancellationToken/tsconfig.json @@ -5,7 +5,6 @@ "removeComments": true, "preserveConstEnums": true, "pretty": true, - "outDir": "../../../built/local", "module": "commonjs", "sourceMap": true, "stripInternal": true, diff --git a/src/server/session.ts b/src/server/session.ts index 81732481d45..d076d5deb6d 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -93,6 +93,7 @@ namespace ts.server { export const Geterr = "geterr"; export const GeterrForProject = "geterrForProject"; export const Implementation = "implementation"; + export const ImplementationFull = "implementation-full"; export const SemanticDiagnosticsSync = "semanticDiagnosticsSync"; export const SyntacticDiagnosticsSync = "syntacticDiagnosticsSync"; export const NavBar = "navbar"; @@ -421,7 +422,7 @@ namespace ts.server { }); } - private getImplementation(args: protocol.FileLocationRequestArgs): protocol.FileSpan[] { + private getImplementation(args: protocol.FileLocationRequestArgs, simplifiedResult: boolean): protocol.FileSpan[] | ImplementationLocation[] { const { file, project } = this.getFileAndProject(args); const scriptInfo = project.getScriptInfoForNormalizedPath(file); const position = this.getPosition(args, scriptInfo); @@ -429,11 +430,16 @@ namespace ts.server { if (!implementations) { return []; } - return implementations.map(impl => ({ - file: impl.fileName, - start: scriptInfo.positionToLineOffset(impl.textSpan.start), - end: scriptInfo.positionToLineOffset(ts.textSpanEnd(impl.textSpan)) - })); + if (simplifiedResult) { + return implementations.map(impl => ({ + file: impl.fileName, + start: scriptInfo.positionToLineOffset(impl.textSpan.start), + end: scriptInfo.positionToLineOffset(ts.textSpanEnd(impl.textSpan)) + })); + } + else { + return implementations; + } } private getOccurrences(args: protocol.FileLocationRequestArgs): protocol.OccurrencesResponseItem[] { @@ -1329,7 +1335,10 @@ namespace ts.server { return this.requiredResponse(this.getTypeDefinition(request.arguments)); }, [CommandNames.Implementation]: (request: protocol.Request) => { - return this.requiredResponse(this.getImplementation(request.arguments)); + return this.requiredResponse(this.getImplementation(request.arguments, /*simplifiedResult*/ true)); + }, + [CommandNames.ImplementationFull]: (request: protocol.Request) => { + return this.requiredResponse(this.getImplementation(request.arguments, /*simplifiedResult*/ false)); }, [CommandNames.References]: (request: protocol.FileLocationRequest) => { return this.requiredResponse(this.getReferences(request.arguments, /*simplifiedResult*/ true)); diff --git a/src/server/tsconfig.json b/src/server/tsconfig.json index bd9bb14ba41..9e65eb2b8bc 100644 --- a/src/server/tsconfig.json +++ b/src/server/tsconfig.json @@ -5,7 +5,7 @@ "removeComments": true, "preserveConstEnums": true, "pretty": true, - "out": "../../built/local/tsserver.js", + "outFile": "../../built/local/tsserver.js", "sourceMap": true, "stripInternal": true, "types": [ diff --git a/src/server/tsconfig.library.json b/src/server/tsconfig.library.json index 5d4656a318b..a450b591a7e 100644 --- a/src/server/tsconfig.library.json +++ b/src/server/tsconfig.library.json @@ -3,7 +3,7 @@ "noImplicitAny": true, "removeComments": true, "preserveConstEnums": true, - "out": "../../built/local/tsserverlibrary.js", + "outFile": "../../built/local/tsserverlibrary.js", "sourceMap": true, "stripInternal": true, "declaration": true, diff --git a/src/server/typingsInstaller/tsconfig.json b/src/server/typingsInstaller/tsconfig.json index 20b3f5e266c..fc4b896f267 100644 --- a/src/server/typingsInstaller/tsconfig.json +++ b/src/server/typingsInstaller/tsconfig.json @@ -5,7 +5,7 @@ "removeComments": true, "preserveConstEnums": true, "pretty": true, - "out": "../../built/local/typingsInstaller.js", + "outFile": "../../../built/local/typingsInstaller.js", "sourceMap": true, "stripInternal": true, "types": [ diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 5437328b581..0ed2ccce99d 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -23,6 +23,43 @@ namespace ts.server.typingsInstaller { return result.resolvedModule && result.resolvedModule.resolvedFileName; } + export enum PackageNameValidationResult { + Ok, + ScopedPackagesNotSupported, + NameTooLong, + NameStartsWithDot, + NameStartsWithUnderscore, + NameContainsNonURISafeCharacters + } + + + export const MaxPackageNameLength = 214; + /** + * Validates package name using rules defined at https://docs.npmjs.com/files/package.json + */ + export function validatePackageName(packageName: string): PackageNameValidationResult { + Debug.assert(!!packageName, "Package name is not specified"); + if (packageName.length > MaxPackageNameLength) { + return PackageNameValidationResult.NameTooLong; + } + if (packageName.charCodeAt(0) === CharacterCodes.dot) { + return PackageNameValidationResult.NameStartsWithDot; + } + if (packageName.charCodeAt(0) === CharacterCodes._) { + return PackageNameValidationResult.NameStartsWithUnderscore; + } + // check if name is scope package like: starts with @ and has one '/' in the middle + // scoped packages are not currently supported + // TODO: when support will be added we'll need to split and check both scope and package name + if (/^@[^/]+\/[^/]+$/.test(packageName)) { + return PackageNameValidationResult.ScopedPackagesNotSupported; + } + if (encodeURIComponent(packageName) !== packageName) { + return PackageNameValidationResult.NameContainsNonURISafeCharacters; + } + return PackageNameValidationResult.Ok; + } + export const NpmViewRequest: "npm view" = "npm view"; export const NpmInstallRequest: "npm install" = "npm install"; @@ -185,14 +222,54 @@ namespace ts.server.typingsInstaller { this.knownCachesSet[cacheLocation] = true; } + private filterTypings(typingsToInstall: string[]) { + if (typingsToInstall.length === 0) { + return typingsToInstall; + } + const result: string[] = []; + for (const typing of typingsToInstall) { + if (this.missingTypingsSet[typing]) { + continue; + } + const validationResult = validatePackageName(typing); + if (validationResult === PackageNameValidationResult.Ok) { + result.push(typing); + } + else { + // add typing name to missing set so we won't process it again + this.missingTypingsSet[typing] = true; + if (this.log.isEnabled()) { + switch (validationResult) { + case PackageNameValidationResult.NameTooLong: + this.log.writeLine(`Package name '${typing}' should be less than ${MaxPackageNameLength} characters`); + break; + case PackageNameValidationResult.NameStartsWithDot: + this.log.writeLine(`Package name '${typing}' cannot start with '.'`); + break; + case PackageNameValidationResult.NameStartsWithUnderscore: + this.log.writeLine(`Package name '${typing}' cannot start with '_'`); + break; + case PackageNameValidationResult.ScopedPackagesNotSupported: + this.log.writeLine(`Package '${typing}' is scoped and currently is not supported`); + break; + case PackageNameValidationResult.NameContainsNonURISafeCharacters: + this.log.writeLine(`Package name '${typing}' contains non URI safe characters`); + break; + } + } + } + } + return result; + } + private installTypings(req: DiscoverTypings, cachePath: string, currentlyCachedTypings: string[], typingsToInstall: string[]) { if (this.log.isEnabled()) { this.log.writeLine(`Installing typings ${JSON.stringify(typingsToInstall)}`); } - typingsToInstall = filter(typingsToInstall, x => !this.missingTypingsSet[x]); + typingsToInstall = this.filterTypings(typingsToInstall); if (typingsToInstall.length === 0) { if (this.log.isEnabled()) { - this.log.writeLine(`All typings are known to be missing - no need to go any further`); + this.log.writeLine(`All typings are known to be missing or invalid - no need to go any further`); } return; } diff --git a/tests/baselines/reference/transformArrowInBlockScopedLoopVarInitializer.js b/tests/baselines/reference/transformArrowInBlockScopedLoopVarInitializer.js new file mode 100644 index 00000000000..4f2e1666275 --- /dev/null +++ b/tests/baselines/reference/transformArrowInBlockScopedLoopVarInitializer.js @@ -0,0 +1,19 @@ +//// [transformArrowInBlockScopedLoopVarInitializer.ts] + +// https://github.com/Microsoft/TypeScript/issues/11236 +while (true) +{ + let local = null; + var a = () => local; // <-- Lambda should be converted to function() +} + +//// [transformArrowInBlockScopedLoopVarInitializer.js] +var _loop_1 = function () { + var local = null; + a = function () { return local; }; // <-- Lambda should be converted to function() +}; +var a; +// https://github.com/Microsoft/TypeScript/issues/11236 +while (true) { + _loop_1(); +} diff --git a/tests/baselines/reference/transformArrowInBlockScopedLoopVarInitializer.symbols b/tests/baselines/reference/transformArrowInBlockScopedLoopVarInitializer.symbols new file mode 100644 index 00000000000..4c5e2cf686e --- /dev/null +++ b/tests/baselines/reference/transformArrowInBlockScopedLoopVarInitializer.symbols @@ -0,0 +1,12 @@ +=== tests/cases/compiler/transformArrowInBlockScopedLoopVarInitializer.ts === + +// https://github.com/Microsoft/TypeScript/issues/11236 +while (true) +{ + let local = null; +>local : Symbol(local, Decl(transformArrowInBlockScopedLoopVarInitializer.ts, 4, 7)) + + var a = () => local; // <-- Lambda should be converted to function() +>a : Symbol(a, Decl(transformArrowInBlockScopedLoopVarInitializer.ts, 5, 7)) +>local : Symbol(local, Decl(transformArrowInBlockScopedLoopVarInitializer.ts, 4, 7)) +} diff --git a/tests/baselines/reference/transformArrowInBlockScopedLoopVarInitializer.types b/tests/baselines/reference/transformArrowInBlockScopedLoopVarInitializer.types new file mode 100644 index 00000000000..6c6769dadbb --- /dev/null +++ b/tests/baselines/reference/transformArrowInBlockScopedLoopVarInitializer.types @@ -0,0 +1,15 @@ +=== tests/cases/compiler/transformArrowInBlockScopedLoopVarInitializer.ts === + +// https://github.com/Microsoft/TypeScript/issues/11236 +while (true) +>true : true +{ + let local = null; +>local : any +>null : null + + var a = () => local; // <-- Lambda should be converted to function() +>a : () => any +>() => local : () => any +>local : any +} diff --git a/tests/baselines/reference/unreachableFlowAfterFinally.js b/tests/baselines/reference/unreachableFlowAfterFinally.js new file mode 100644 index 00000000000..97f04b219b6 --- /dev/null +++ b/tests/baselines/reference/unreachableFlowAfterFinally.js @@ -0,0 +1,27 @@ +//// [unreachableFlowAfterFinally.ts] + +function f() { + let x = 100; + try { + throw "WAT" + } + catch (e) { + + } + finally { + return x; + } +} + +//// [unreachableFlowAfterFinally.js] +function f() { + var x = 100; + try { + throw "WAT"; + } + catch (e) { + } + finally { + return x; + } +} diff --git a/tests/baselines/reference/unreachableFlowAfterFinally.symbols b/tests/baselines/reference/unreachableFlowAfterFinally.symbols new file mode 100644 index 00000000000..92a5d7b06a5 --- /dev/null +++ b/tests/baselines/reference/unreachableFlowAfterFinally.symbols @@ -0,0 +1,20 @@ +=== tests/cases/compiler/unreachableFlowAfterFinally.ts === + +function f() { +>f : Symbol(f, Decl(unreachableFlowAfterFinally.ts, 0, 0)) + + let x = 100; +>x : Symbol(x, Decl(unreachableFlowAfterFinally.ts, 2, 7)) + + try { + throw "WAT" + } + catch (e) { +>e : Symbol(e, Decl(unreachableFlowAfterFinally.ts, 6, 11)) + + } + finally { + return x; +>x : Symbol(x, Decl(unreachableFlowAfterFinally.ts, 2, 7)) + } +} diff --git a/tests/baselines/reference/unreachableFlowAfterFinally.types b/tests/baselines/reference/unreachableFlowAfterFinally.types new file mode 100644 index 00000000000..814bebfc2fd --- /dev/null +++ b/tests/baselines/reference/unreachableFlowAfterFinally.types @@ -0,0 +1,22 @@ +=== tests/cases/compiler/unreachableFlowAfterFinally.ts === + +function f() { +>f : () => number + + let x = 100; +>x : number +>100 : 100 + + try { + throw "WAT" +>"WAT" : "WAT" + } + catch (e) { +>e : any + + } + finally { + return x; +>x : number + } +} diff --git a/tests/cases/compiler/transformArrowInBlockScopedLoopVarInitializer.ts b/tests/cases/compiler/transformArrowInBlockScopedLoopVarInitializer.ts new file mode 100644 index 00000000000..4f496dc6afe --- /dev/null +++ b/tests/cases/compiler/transformArrowInBlockScopedLoopVarInitializer.ts @@ -0,0 +1,8 @@ +// @target: es5 + +// https://github.com/Microsoft/TypeScript/issues/11236 +while (true) +{ + let local = null; + var a = () => local; // <-- Lambda should be converted to function() +} \ No newline at end of file diff --git a/tests/cases/compiler/unreachableFlowAfterFinally.ts b/tests/cases/compiler/unreachableFlowAfterFinally.ts new file mode 100644 index 00000000000..4a7c0944949 --- /dev/null +++ b/tests/cases/compiler/unreachableFlowAfterFinally.ts @@ -0,0 +1,14 @@ +// @noImplicitReturns: true + +function f() { + let x = 100; + try { + throw "WAT" + } + catch (e) { + + } + finally { + return x; + } +} \ No newline at end of file