From 0725fb4664a1d5ec94040b6d94db77dc1cc354e4 Mon Sep 17 00:00:00 2001 From: TypeScript Bot <23042052+typescript-bot@users.noreply.github.com> Date: Mon, 6 Apr 2026 10:44:55 -0700 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=A4=96=20Pick=20PR=20#63310=20(Mark?= =?UTF-8?q?=20class=20property=20initializers=20as...)=20into=20release-6.?= =?UTF-8?q?0=20(#63327)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com> --- src/compiler/binder.ts | 3 + ...ssPropertyInferenceFromBroaderTypeConst.js | 55 +++++++++ ...pertyInferenceFromBroaderTypeConst.symbols | 68 +++++++++++ ...ropertyInferenceFromBroaderTypeConst.types | 107 ++++++++++++++++++ ...ssPropertyInferenceFromBroaderTypeConst.ts | 31 +++++ 5 files changed, 264 insertions(+) create mode 100644 tests/baselines/reference/classPropertyInferenceFromBroaderTypeConst.js create mode 100644 tests/baselines/reference/classPropertyInferenceFromBroaderTypeConst.symbols create mode 100644 tests/baselines/reference/classPropertyInferenceFromBroaderTypeConst.types create mode 100644 tests/cases/compiler/classPropertyInferenceFromBroaderTypeConst.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 9ea90805fb51e..5980b113e7baf 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -3869,6 +3869,9 @@ export function getContainerFlags(node: Node): ContainerFlags { case SyntaxKind.ModuleBlock: return ContainerFlags.IsControlFlowContainer; + case SyntaxKind.PropertyDeclaration: + return (node as PropertyDeclaration).initializer ? ContainerFlags.IsControlFlowContainer : ContainerFlags.None; + case SyntaxKind.CatchClause: case SyntaxKind.ForStatement: case SyntaxKind.ForInStatement: diff --git a/tests/baselines/reference/classPropertyInferenceFromBroaderTypeConst.js b/tests/baselines/reference/classPropertyInferenceFromBroaderTypeConst.js new file mode 100644 index 0000000000000..3293aa9e34a7b --- /dev/null +++ b/tests/baselines/reference/classPropertyInferenceFromBroaderTypeConst.js @@ -0,0 +1,55 @@ +//// [tests/cases/compiler/classPropertyInferenceFromBroaderTypeConst.ts] //// + +//// [classPropertyInferenceFromBroaderTypeConst.ts] +// Repro from GH#62264 +// Class property should infer the wider declared type (AB), not the narrowed literal type ("A") + +type AB = 'A' | 'B'; + +const DEFAULT: AB = 'A'; + +class C { + D = DEFAULT; + + method() { + switch (this.D) { + case 'A': break; + case 'B': break; // should not error + } + } +} + +// D should be AB, not "A" +declare const c: C; +declare function expectAB(x: AB): void; +expectAB(c.D); // ok +c.D = 'B'; // ok + +// Static property should work the same way +class D { + static SD = DEFAULT; +} +D.SD = 'B'; // ok + + +//// [classPropertyInferenceFromBroaderTypeConst.js] +"use strict"; +// Repro from GH#62264 +// Class property should infer the wider declared type (AB), not the narrowed literal type ("A") +const DEFAULT = 'A'; +class C { + D = DEFAULT; + method() { + switch (this.D) { + case 'A': break; + case 'B': break; // should not error + } + } +} +expectAB(c.D); // ok +c.D = 'B'; // ok +// Static property should work the same way +class D { + static SD = DEFAULT; +} +D.SD = 'B'; // ok diff --git a/tests/baselines/reference/classPropertyInferenceFromBroaderTypeConst.symbols b/tests/baselines/reference/classPropertyInferenceFromBroaderTypeConst.symbols new file mode 100644 index 0000000000000..997b69e5225b0 --- /dev/null +++ b/tests/baselines/reference/classPropertyInferenceFromBroaderTypeConst.symbols @@ -0,0 +1,68 @@ +//// [tests/cases/compiler/classPropertyInferenceFromBroaderTypeConst.ts] //// + +=== classPropertyInferenceFromBroaderTypeConst.ts === +// Repro from GH#62264 +// Class property should infer the wider declared type (AB), not the narrowed literal type ("A") + +type AB = 'A' | 'B'; +>AB : Symbol(AB, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 0, 0)) + +const DEFAULT: AB = 'A'; +>DEFAULT : Symbol(DEFAULT, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 5, 5)) +>AB : Symbol(AB, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 0, 0)) + +class C { +>C : Symbol(C, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 5, 24)) + + D = DEFAULT; +>D : Symbol(C.D, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 7, 9)) +>DEFAULT : Symbol(DEFAULT, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 5, 5)) + + method() { +>method : Symbol(C.method, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 8, 16)) + + switch (this.D) { +>this.D : Symbol(C.D, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 7, 9)) +>this : Symbol(C, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 5, 24)) +>D : Symbol(C.D, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 7, 9)) + + case 'A': break; + case 'B': break; // should not error + } + } +} + +// D should be AB, not "A" +declare const c: C; +>c : Symbol(c, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 19, 13)) +>C : Symbol(C, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 5, 24)) + +declare function expectAB(x: AB): void; +>expectAB : Symbol(expectAB, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 19, 19)) +>x : Symbol(x, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 20, 26)) +>AB : Symbol(AB, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 0, 0)) + +expectAB(c.D); // ok +>expectAB : Symbol(expectAB, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 19, 19)) +>c.D : Symbol(C.D, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 7, 9)) +>c : Symbol(c, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 19, 13)) +>D : Symbol(C.D, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 7, 9)) + +c.D = 'B'; // ok +>c.D : Symbol(C.D, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 7, 9)) +>c : Symbol(c, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 19, 13)) +>D : Symbol(C.D, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 7, 9)) + +// Static property should work the same way +class D { +>D : Symbol(D, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 22, 10)) + + static SD = DEFAULT; +>SD : Symbol(D.SD, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 25, 9)) +>DEFAULT : Symbol(DEFAULT, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 5, 5)) +} +D.SD = 'B'; // ok +>D.SD : Symbol(D.SD, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 25, 9)) +>D : Symbol(D, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 22, 10)) +>SD : Symbol(D.SD, Decl(classPropertyInferenceFromBroaderTypeConst.ts, 25, 9)) + diff --git a/tests/baselines/reference/classPropertyInferenceFromBroaderTypeConst.types b/tests/baselines/reference/classPropertyInferenceFromBroaderTypeConst.types new file mode 100644 index 0000000000000..e339f502bae82 --- /dev/null +++ b/tests/baselines/reference/classPropertyInferenceFromBroaderTypeConst.types @@ -0,0 +1,107 @@ +//// [tests/cases/compiler/classPropertyInferenceFromBroaderTypeConst.ts] //// + +=== classPropertyInferenceFromBroaderTypeConst.ts === +// Repro from GH#62264 +// Class property should infer the wider declared type (AB), not the narrowed literal type ("A") + +type AB = 'A' | 'B'; +>AB : AB +> : ^^ + +const DEFAULT: AB = 'A'; +>DEFAULT : AB +> : ^^ +>'A' : "A" +> : ^^^ + +class C { +>C : C +> : ^ + + D = DEFAULT; +>D : AB +> : ^^ +>DEFAULT : AB +> : ^^ + + method() { +>method : () => void +> : ^^^^^^^^^^ + + switch (this.D) { +>this.D : AB +> : ^^ +>this : this +> : ^^^^ +>D : AB +> : ^^ + + case 'A': break; +>'A' : "A" +> : ^^^ + + case 'B': break; // should not error +>'B' : "B" +> : ^^^ + } + } +} + +// D should be AB, not "A" +declare const c: C; +>c : C +> : ^ + +declare function expectAB(x: AB): void; +>expectAB : (x: AB) => void +> : ^ ^^ ^^^^^ +>x : AB +> : ^^ + +expectAB(c.D); // ok +>expectAB(c.D) : void +> : ^^^^ +>expectAB : (x: AB) => void +> : ^ ^^ ^^^^^ +>c.D : AB +> : ^^ +>c : C +> : ^ +>D : AB +> : ^^ + +c.D = 'B'; // ok +>c.D = 'B' : "B" +> : ^^^ +>c.D : AB +> : ^^ +>c : C +> : ^ +>D : AB +> : ^^ +>'B' : "B" +> : ^^^ + +// Static property should work the same way +class D { +>D : D +> : ^ + + static SD = DEFAULT; +>SD : AB +> : ^^ +>DEFAULT : AB +> : ^^ +} +D.SD = 'B'; // ok +>D.SD = 'B' : "B" +> : ^^^ +>D.SD : AB +> : ^^ +>D : typeof D +> : ^^^^^^^^ +>SD : AB +> : ^^ +>'B' : "B" +> : ^^^ + diff --git a/tests/cases/compiler/classPropertyInferenceFromBroaderTypeConst.ts b/tests/cases/compiler/classPropertyInferenceFromBroaderTypeConst.ts new file mode 100644 index 0000000000000..33faa717d76d6 --- /dev/null +++ b/tests/cases/compiler/classPropertyInferenceFromBroaderTypeConst.ts @@ -0,0 +1,31 @@ +// @strict: true + +// Repro from GH#62264 +// Class property should infer the wider declared type (AB), not the narrowed literal type ("A") + +type AB = 'A' | 'B'; + +const DEFAULT: AB = 'A'; + +class C { + D = DEFAULT; + + method() { + switch (this.D) { + case 'A': break; + case 'B': break; // should not error + } + } +} + +// D should be AB, not "A" +declare const c: C; +declare function expectAB(x: AB): void; +expectAB(c.D); // ok +c.D = 'B'; // ok + +// Static property should work the same way +class D { + static SD = DEFAULT; +} +D.SD = 'B'; // ok From ad1c695fada682764bb510dd680e8f175ae54094 Mon Sep 17 00:00:00 2001 From: TypeScript Bot <23042052+typescript-bot@users.noreply.github.com> Date: Tue, 7 Apr 2026 10:24:50 -0700 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=A4=96=20Pick=20PR=20#63368=20(Harden?= =?UTF-8?q?=20ATA=20package=20name=20filtering)=20into=20release-6.0=20(#6?= =?UTF-8?q?3372)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com> --- src/jsTyping/jsTyping.ts | 11 +++++---- .../unittests/tsserver/typingsInstaller.ts | 23 ++++++++++--------- .../typingsInstaller/malformed-packagejson.js | 2 +- .../should-handle-node-core-modules.js | 2 +- ...d-not-initialize-invaalid-package-names.js | 2 +- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/jsTyping/jsTyping.ts b/src/jsTyping/jsTyping.ts index a573536255a81..db699d5b32c5e 100644 --- a/src/jsTyping/jsTyping.ts +++ b/src/jsTyping/jsTyping.ts @@ -327,7 +327,8 @@ export const enum NameValidationResult { NameTooLong, NameStartsWithDot, NameStartsWithUnderscore, - NameContainsNonURISafeCharacters, + NameContainsInvalidCharacters, + NameContainsNonURISafeCharacters = NameContainsInvalidCharacters, // for backward compatibility } const maxPackageNameLength = 214; @@ -381,8 +382,8 @@ function validatePackageNameWorker(packageName: string, supportScopedPackage: bo return NameValidationResult.Ok; } } - if (encodeURIComponent(packageName) !== packageName) { - return NameValidationResult.NameContainsNonURISafeCharacters; + if (!/^[\w.-]+$/.test(packageName)) { + return NameValidationResult.NameContainsInvalidCharacters; } return NameValidationResult.Ok; } @@ -405,8 +406,8 @@ function renderPackageNameValidationFailureWorker(typing: string, result: NameVa return `'${typing}':: ${kind} name '${name}' cannot start with '.'`; case NameValidationResult.NameStartsWithUnderscore: return `'${typing}':: ${kind} name '${name}' cannot start with '_'`; - case NameValidationResult.NameContainsNonURISafeCharacters: - return `'${typing}':: ${kind} name '${name}' contains non URI safe characters`; + case NameValidationResult.NameContainsInvalidCharacters: + return `'${typing}':: ${kind} name '${name}' contains invalid characters`; case NameValidationResult.Ok: return Debug.fail(); // Shouldn't have called this. default: diff --git a/src/testRunner/unittests/tsserver/typingsInstaller.ts b/src/testRunner/unittests/tsserver/typingsInstaller.ts index 1c7e77ae4039f..a832f3f2fcfe6 100644 --- a/src/testRunner/unittests/tsserver/typingsInstaller.ts +++ b/src/testRunner/unittests/tsserver/typingsInstaller.ts @@ -1524,10 +1524,11 @@ describe("unittests:: tsserver:: typingsInstaller:: Validate package name:", () it("package name cannot start with underscore", () => { assert.equal(validatePackageName("_foo"), NameValidationResult.NameStartsWithUnderscore); }); - it("package non URI safe characters are not supported", () => { - assert.equal(validatePackageName(" scope "), NameValidationResult.NameContainsNonURISafeCharacters); - assert.equal(validatePackageName("; say ‘Hello from TypeScript!’ #"), NameValidationResult.NameContainsNonURISafeCharacters); - assert.equal(validatePackageName("a/b/c"), NameValidationResult.NameContainsNonURISafeCharacters); + it("package invalid characters are not supported", () => { + assert.equal(validatePackageName(" scope "), NameValidationResult.NameContainsInvalidCharacters); + assert.equal(validatePackageName("; say ‘Hello from TypeScript!’ #"), NameValidationResult.NameContainsInvalidCharacters); + assert.equal(validatePackageName("a/b/c"), NameValidationResult.NameContainsInvalidCharacters); + assert.equal(validatePackageName("react'test"), NameValidationResult.NameContainsInvalidCharacters); }); it("scoped package name is supported", () => { assert.equal(validatePackageName("@scope/bar"), NameValidationResult.Ok); @@ -1540,10 +1541,10 @@ describe("unittests:: tsserver:: typingsInstaller:: Validate package name:", () assert.deepEqual(validatePackageName("@_scope/bar"), { name: "_scope", isScopeName: true, result: NameValidationResult.NameStartsWithUnderscore }); assert.deepEqual(validatePackageName("@_scope/_bar"), { name: "_scope", isScopeName: true, result: NameValidationResult.NameStartsWithUnderscore }); }); - it("scope name in scoped package name with non URI safe characters are not supported", () => { - assert.deepEqual(validatePackageName("@ scope /bar"), { name: " scope ", isScopeName: true, result: NameValidationResult.NameContainsNonURISafeCharacters }); - assert.deepEqual(validatePackageName("@; say ‘Hello from TypeScript!’ #/bar"), { name: "; say ‘Hello from TypeScript!’ #", isScopeName: true, result: NameValidationResult.NameContainsNonURISafeCharacters }); - assert.deepEqual(validatePackageName("@ scope / bar "), { name: " scope ", isScopeName: true, result: NameValidationResult.NameContainsNonURISafeCharacters }); + it("scope name in scoped package name with invalid characters are not supported", () => { + assert.deepEqual(validatePackageName("@ scope /bar"), { name: " scope ", isScopeName: true, result: NameValidationResult.NameContainsInvalidCharacters }); + assert.deepEqual(validatePackageName("@; say ‘Hello from TypeScript!’ #/bar"), { name: "; say ‘Hello from TypeScript!’ #", isScopeName: true, result: NameValidationResult.NameContainsInvalidCharacters }); + assert.deepEqual(validatePackageName("@ scope / bar "), { name: " scope ", isScopeName: true, result: NameValidationResult.NameContainsInvalidCharacters }); }); it("package name in scoped package name cannot start with dot", () => { assert.deepEqual(validatePackageName("@scope/.bar"), { name: ".bar", isScopeName: false, result: NameValidationResult.NameStartsWithDot }); @@ -1551,9 +1552,9 @@ describe("unittests:: tsserver:: typingsInstaller:: Validate package name:", () it("package name in scoped package name cannot start with underscore", () => { assert.deepEqual(validatePackageName("@scope/_bar"), { name: "_bar", isScopeName: false, result: NameValidationResult.NameStartsWithUnderscore }); }); - it("package name in scoped package name with non URI safe characters are not supported", () => { - assert.deepEqual(validatePackageName("@scope/ bar "), { name: " bar ", isScopeName: false, result: NameValidationResult.NameContainsNonURISafeCharacters }); - assert.deepEqual(validatePackageName("@scope/; say ‘Hello from TypeScript!’ #"), { name: "; say ‘Hello from TypeScript!’ #", isScopeName: false, result: NameValidationResult.NameContainsNonURISafeCharacters }); + it("package name in scoped package name with invalid characters are not supported", () => { + assert.deepEqual(validatePackageName("@scope/ bar "), { name: " bar ", isScopeName: false, result: NameValidationResult.NameContainsInvalidCharacters }); + assert.deepEqual(validatePackageName("@scope/; say ‘Hello from TypeScript!’ #"), { name: "; say ‘Hello from TypeScript!’ #", isScopeName: false, result: NameValidationResult.NameContainsInvalidCharacters }); }); }); diff --git a/tests/baselines/reference/tsserver/typingsInstaller/malformed-packagejson.js b/tests/baselines/reference/tsserver/typingsInstaller/malformed-packagejson.js index b32a3c36b7636..27c9be5bd0cc8 100644 --- a/tests/baselines/reference/tsserver/typingsInstaller/malformed-packagejson.js +++ b/tests/baselines/reference/tsserver/typingsInstaller/malformed-packagejson.js @@ -200,7 +200,7 @@ Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/projects/pro Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Directory location for typing installer Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Directory location for typing installer TI:: [hh:mm:ss:mss] Installing typings ["co } }"] -TI:: [hh:mm:ss:mss] 'co } }':: Package name 'co } }' contains non URI safe characters +TI:: [hh:mm:ss:mss] 'co } }':: Package name 'co } }' contains invalid characters TI:: [hh:mm:ss:mss] All typings are known to be missing or invalid - no need to install more typings TI:: [hh:mm:ss:mss] Sending response: { diff --git a/tests/baselines/reference/tsserver/typingsInstaller/should-handle-node-core-modules.js b/tests/baselines/reference/tsserver/typingsInstaller/should-handle-node-core-modules.js index 3bc84f2df7cd2..29afbcf692263 100644 --- a/tests/baselines/reference/tsserver/typingsInstaller/should-handle-node-core-modules.js +++ b/tests/baselines/reference/tsserver/typingsInstaller/should-handle-node-core-modules.js @@ -654,7 +654,7 @@ TI:: [hh:mm:ss:mss] Sending response: "projectName": "/dev/null/inferredProject1*" } TI:: [hh:mm:ss:mss] Installing typings ["s tream"] -TI:: [hh:mm:ss:mss] 's tream':: Package name 's tream' contains non URI safe characters +TI:: [hh:mm:ss:mss] 's tream':: Package name 's tream' contains invalid characters TI:: [hh:mm:ss:mss] All typings are known to be missing or invalid - no need to install more typings TI:: [hh:mm:ss:mss] Sending response: { diff --git a/tests/baselines/reference/tsserver/typingsInstaller/should-not-initialize-invaalid-package-names.js b/tests/baselines/reference/tsserver/typingsInstaller/should-not-initialize-invaalid-package-names.js index 499d7ad5544a9..d29fb6696c67f 100644 --- a/tests/baselines/reference/tsserver/typingsInstaller/should-not-initialize-invaalid-package-names.js +++ b/tests/baselines/reference/tsserver/typingsInstaller/should-not-initialize-invaalid-package-names.js @@ -160,7 +160,7 @@ Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/projects/pro Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Directory location for typing installer Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/node_modules 1 undefined Project: /dev/null/inferredProject1* WatchType: Directory location for typing installer TI:: [hh:mm:ss:mss] Installing typings ["; say ‘Hello from TypeScript!’ #"] -TI:: [hh:mm:ss:mss] '; say ‘Hello from TypeScript!’ #':: Package name '; say ‘Hello from TypeScript!’ #' contains non URI safe characters +TI:: [hh:mm:ss:mss] '; say ‘Hello from TypeScript!’ #':: Package name '; say ‘Hello from TypeScript!’ #' contains invalid characters TI:: [hh:mm:ss:mss] All typings are known to be missing or invalid - no need to install more typings TI:: [hh:mm:ss:mss] Sending response: { From eeae9dd0f17aa494658e4ec079dc002e02dd625e Mon Sep 17 00:00:00 2001 From: TypeScript Bot <23042052+typescript-bot@users.noreply.github.com> Date: Wed, 15 Apr 2026 13:44:44 -0700 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=A4=96=20Pick=20PR=20#63401=20(Also?= =?UTF-8?q?=20check=20package=20name=20validity=20in...)=20into=20release-?= =?UTF-8?q?6.0=20(#63407)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com> --- src/testRunner/unittests/tsserver/codeFix.ts | 20 + src/typingsInstallerCore/typingsInstaller.ts | 16 + ...l-package-rejects-invalid-package-names.js | 438 ++++++++++++++++++ 3 files changed, 474 insertions(+) create mode 100644 tests/baselines/reference/tsserver/codeFix/install-package-rejects-invalid-package-names.js diff --git a/src/testRunner/unittests/tsserver/codeFix.ts b/src/testRunner/unittests/tsserver/codeFix.ts index 481441b7cd1b4..007d835ca48ba 100644 --- a/src/testRunner/unittests/tsserver/codeFix.ts +++ b/src/testRunner/unittests/tsserver/codeFix.ts @@ -56,4 +56,24 @@ describe("unittests:: tsserver:: codeFix::", () => { }); baselineTsserverLogs("codeFix", "install package when serialized", session); }); + + it("install package rejects invalid package names", () => { + const { host, session } = setup(); + // A client could craft an applyCodeActionCommand with arbitrary package names. + // The server must validate and reject names with invalid characters to prevent shell injection. + for (const packageName of ["; echo 'hello' #", "react'test", "a/b/c"]) { + session.executeCommandSeq({ + command: ts.server.protocol.CommandTypes.ApplyCodeActionCommand, + arguments: { + command: { + type: "install package", + file: "/home/src/projects/project/src/file.ts", + packageName, + }, + }, + }); + } + host.runPendingInstalls(); + baselineTsserverLogs("codeFix", "install package rejects invalid package names", session); + }); }); diff --git a/src/typingsInstallerCore/typingsInstaller.ts b/src/typingsInstallerCore/typingsInstaller.ts index 25f583513a5fe..aaafeaa477441 100644 --- a/src/typingsInstallerCore/typingsInstaller.ts +++ b/src/typingsInstallerCore/typingsInstaller.ts @@ -239,6 +239,22 @@ export abstract class TypingsInstaller { /** @internal */ installPackage(req: InstallPackageRequest): void { const { fileName, packageName, projectName, projectRootPath, id } = req; + const validationResult = JsTyping.validatePackageName(packageName); + if (validationResult !== JsTyping.NameValidationResult.Ok) { + const message = JsTyping.renderPackageNameValidationFailure(validationResult, packageName); + if (this.log.isEnabled()) { + this.log.writeLine(message); + } + const response: PackageInstalledResponse = { + kind: ActionPackageInstalled, + projectName, + id, + success: false, + message, + }; + this.sendResponse(response); + return; + } const cwd = forEachAncestorDirectory(getDirectoryPath(fileName), directory => { if (this.installTypingHost.fileExists(combinePaths(directory, "package.json"))) { return directory; diff --git a/tests/baselines/reference/tsserver/codeFix/install-package-rejects-invalid-package-names.js b/tests/baselines/reference/tsserver/codeFix/install-package-rejects-invalid-package-names.js new file mode 100644 index 0000000000000..14acc9d58c607 --- /dev/null +++ b/tests/baselines/reference/tsserver/codeFix/install-package-rejects-invalid-package-names.js @@ -0,0 +1,438 @@ +Info seq [hh:mm:ss:mss] currentDirectory:: /home/src/Vscode/Projects/bin useCaseSensitiveFileNames:: false +Info seq [hh:mm:ss:mss] libs Location:: /home/src/tslibs/TS/Lib +Info seq [hh:mm:ss:mss] globalTypingsCacheLocation:: /home/src/Library/Caches/typescript +Info seq [hh:mm:ss:mss] Provided types map file "/home/src/tslibs/TS/Lib/typesMap.json" doesn't exist +Before request +//// [/home/src/projects/project/src/file.ts] +import * as os from "os"; +import * as https from "https"; +import * as vscode from "vscode"; + + +//// [/home/src/projects/project/tsconfig.json] +{ } + +//// [/home/src/projects/project/node_modules/vscode/index.js] +export const x = 10; + +//// [/home/src/tslibs/TS/Lib/lib.d.ts] +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } +interface ReadonlyArray {} +declare const console: { log(msg: any): void; }; + + +Info seq [hh:mm:ss:mss] request: + { + "command": "open", + "arguments": { + "file": "/home/src/projects/project/src/file.ts" + }, + "seq": 1, + "type": "request" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /home/src/projects/project/src/file.ts ProjectRootPath: undefined:: Result: /home/src/projects/project/tsconfig.json +Info seq [hh:mm:ss:mss] Creating ConfiguredProject: /home/src/projects/project/tsconfig.json, currentDirectory: /home/src/projects/project +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/projects/project/tsconfig.json 2000 undefined Project: /home/src/projects/project/tsconfig.json WatchType: Config file +Info seq [hh:mm:ss:mss] Config: /home/src/projects/project/tsconfig.json : { + "rootNames": [ + "/home/src/projects/project/src/file.ts" + ], + "options": { + "configFilePath": "/home/src/projects/project/tsconfig.json" + } +} +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "projectLoadingStart", + "body": { + "projectName": "/home/src/projects/project/tsconfig.json", + "reason": "Creating possible configured project for /home/src/projects/project/src/file.ts to open" + } + } +Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project 1 undefined Config: /home/src/projects/project/tsconfig.json WatchType: Wild card directory +Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project 1 undefined Config: /home/src/projects/project/tsconfig.json WatchType: Wild card directory +Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /home/src/projects/project/tsconfig.json +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/tslibs/TS/Lib/lib.es2025.full.d.ts 500 undefined WatchType: Closed Script info +Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/src 1 undefined Project: /home/src/projects/project/tsconfig.json WatchType: Failed Lookup Locations +Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/src 1 undefined Project: /home/src/projects/project/tsconfig.json WatchType: Failed Lookup Locations +Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects 0 undefined Project: /home/src/projects/project/tsconfig.json WatchType: Failed Lookup Locations +Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects 0 undefined Project: /home/src/projects/project/tsconfig.json WatchType: Failed Lookup Locations +Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/node_modules 1 undefined Project: /home/src/projects/project/tsconfig.json WatchType: Failed Lookup Locations +Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/node_modules 1 undefined Project: /home/src/projects/project/tsconfig.json WatchType: Failed Lookup Locations +Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/node_modules 1 undefined Project: /home/src/projects/project/tsconfig.json WatchType: Failed Lookup Locations +Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/node_modules 1 undefined Project: /home/src/projects/project/tsconfig.json WatchType: Failed Lookup Locations +Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project 0 undefined Project: /home/src/projects/project/tsconfig.json WatchType: Failed Lookup Locations +Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project 0 undefined Project: /home/src/projects/project/tsconfig.json WatchType: Failed Lookup Locations +Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /home/src/projects/project/tsconfig.json projectStateVersion: 1 projectProgramVersion: 0 structureChanged: true structureIsReused:: Not Elapsed:: *ms +Info seq [hh:mm:ss:mss] Project '/home/src/projects/project/tsconfig.json' (Configured) +Info seq [hh:mm:ss:mss] Files (2) + /home/src/tslibs/TS/Lib/lib.es2025.full.d.ts Text-1 "interface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };" + /home/src/projects/project/src/file.ts SVC-1-0 "import * as os from \"os\";\nimport * as https from \"https\";\nimport * as vscode from \"vscode\";\n" + + + ../../tslibs/TS/Lib/lib.es2025.full.d.ts + Default library for target 'es2025' + src/file.ts + Matched by default include pattern '**/*' + +Info seq [hh:mm:ss:mss] ----------------------------------------------- +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "projectLoadingFinish", + "body": { + "projectName": "/home/src/projects/project/tsconfig.json" + } + } +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "telemetry", + "body": { + "telemetryEventName": "projectInfo", + "payload": { + "projectId": "1097a5f82e8323ba7aba7567ec06402f7ad4ea74abce44ec5efd223ac77ff169", + "fileStats": { + "js": 0, + "jsSize": 0, + "jsx": 0, + "jsxSize": 0, + "ts": 1, + "tsSize": 92, + "tsx": 0, + "tsxSize": 0, + "dts": 1, + "dtsSize": 374, + "deferred": 0, + "deferredSize": 0 + }, + "compilerOptions": {}, + "typeAcquisition": { + "enable": false, + "include": false, + "exclude": false + }, + "extends": false, + "files": false, + "include": false, + "exclude": false, + "compileOnSave": false, + "configFileName": "tsconfig.json", + "projectType": "configured", + "languageServiceEnabled": true, + "version": "FakeVersion" + } + } + } +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "configFileDiag", + "body": { + "triggerFile": "/home/src/projects/project/src/file.ts", + "configFile": "/home/src/projects/project/tsconfig.json", + "diagnostics": [] + } + } +Info seq [hh:mm:ss:mss] Project '/home/src/projects/project/tsconfig.json' (Configured) +Info seq [hh:mm:ss:mss] Files (2) + +Info seq [hh:mm:ss:mss] ----------------------------------------------- +Info seq [hh:mm:ss:mss] Open files: +Info seq [hh:mm:ss:mss] FileName: /home/src/projects/project/src/file.ts ProjectRootPath: undefined +Info seq [hh:mm:ss:mss] Projects: /home/src/projects/project/tsconfig.json +Info seq [hh:mm:ss:mss] response: + { + "seq": 0, + "type": "response", + "command": "open", + "request_seq": 1, + "success": true, + "performanceData": { + "updateGraphDurationMs": * + } + } +After request +//// [/home/src/tslibs/TS/Lib/lib.es2025.full.d.ts] *Lib* + + +PolledWatches:: +/home/src/projects/node_modules: *new* + {"pollingInterval":500} + +FsWatches:: +/home/src/projects: *new* + {} +/home/src/projects/project: *new* + {} +/home/src/projects/project/tsconfig.json: *new* + {} +/home/src/tslibs/TS/Lib/lib.es2025.full.d.ts: *new* + {} + +FsWatchesRecursive:: +/home/src/projects/project: *new* + {} +/home/src/projects/project/node_modules: *new* + {} +/home/src/projects/project/src: *new* + {} + +Projects:: +/home/src/projects/project/tsconfig.json (Configured) *new* + projectStateVersion: 1 + projectProgramVersion: 1 + autoImportProviderHost: false + +ScriptInfos:: +/home/src/projects/project/src/file.ts (Open) *new* + version: SVC-1-0 + containingProjects: 1 + /home/src/projects/project/tsconfig.json *default* +/home/src/tslibs/TS/Lib/lib.es2025.full.d.ts *new* + version: Text-1 + containingProjects: 1 + /home/src/projects/project/tsconfig.json + +Before request + +Info seq [hh:mm:ss:mss] request: + { + "command": "getCombinedCodeFix", + "arguments": { + "scope": { + "type": "file", + "args": { + "file": "/home/src/projects/project/src/file.ts" + } + }, + "fixId": "installTypesPackage" + }, + "seq": 2, + "type": "request" + } +TI:: Creating typing installer + +TI:: [hh:mm:ss:mss] Global cache location '/home/src/Library/Caches/typescript', safe file path '/home/src/tslibs/TS/Lib/typingSafeList.json', types map path /home/src/tslibs/TS/Lib/typesMap.json +TI:: [hh:mm:ss:mss] Processing cache location '/home/src/Library/Caches/typescript' +TI:: [hh:mm:ss:mss] Trying to find '/home/src/Library/Caches/typescript/package.json'... +TI:: [hh:mm:ss:mss] Finished processing cache location '/home/src/Library/Caches/typescript' +TI:: [hh:mm:ss:mss] Npm config file: /home/src/Library/Caches/typescript/package.json +TI:: [hh:mm:ss:mss] Npm config file: '/home/src/Library/Caches/typescript/package.json' is missing, creating new one... +TI:: [hh:mm:ss:mss] Updating types-registry npm package... +TI:: [hh:mm:ss:mss] npm install --ignore-scripts types-registry@latest +TI:: [hh:mm:ss:mss] Updated types-registry npm package +TI:: typing installer creation complete +//// [/home/src/Library/Caches/typescript/package.json] +{ "private": true } + +//// [/home/src/Library/Caches/typescript/node_modules/types-registry/index.json] +{ + "entries": { + "vscode": { + "latest": "1.3.0", + "ts2.0": "1.0.0", + "ts2.1": "1.0.0", + "ts2.2": "1.2.0", + "ts2.3": "1.3.0", + "ts2.4": "1.3.0", + "ts2.5": "1.3.0", + "ts2.6": "1.3.0", + "ts2.7": "1.3.0" + } + } +} + + +TI:: [hh:mm:ss:mss] Sending response: + { + "kind": "event::typesRegistry", + "typesRegistry": { + "vscode": { + "latest": "1.3.0", + "ts2.0": "1.0.0", + "ts2.1": "1.0.0", + "ts2.2": "1.2.0", + "ts2.3": "1.3.0", + "ts2.4": "1.3.0", + "ts2.5": "1.3.0", + "ts2.6": "1.3.0", + "ts2.7": "1.3.0" + } + } + } +Info seq [hh:mm:ss:mss] response: + { + "response": { + "changes": [], + "commands": [ + { + "type": "install package", + "file": "/home/src/projects/project/src/file.ts", + "packageName": "@types/node" + }, + { + "type": "install package", + "file": "/home/src/projects/project/src/file.ts", + "packageName": "@types/node" + }, + { + "type": "install package", + "file": "/home/src/projects/project/src/file.ts", + "packageName": "@types/vscode" + } + ] + }, + "responseRequired": true + } +After request + +Before request + +Info seq [hh:mm:ss:mss] request: + { + "command": "applyCodeActionCommand", + "arguments": { + "command": { + "type": "install package", + "file": "/home/src/projects/project/src/file.ts", + "packageName": "; echo 'hello' #" + } + }, + "seq": 3, + "type": "request" + } +TI:: [hh:mm:ss:mss] '; echo 'hello' #':: Package name '; echo 'hello' #' contains invalid characters +TI:: [hh:mm:ss:mss] Sending response: + { + "kind": "action::packageInstalled", + "projectName": "/home/src/projects/project/tsconfig.json", + "id": 1, + "success": false, + "message": "'; echo 'hello' #':: Package name '; echo 'hello' #' contains invalid characters" + } +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "setTypings", + "body": { + "kind": "action::packageInstalled", + "projectName": "/home/src/projects/project/tsconfig.json", + "id": 1, + "success": false, + "message": "'; echo 'hello' #':: Package name '; echo 'hello' #' contains invalid characters" + } + } +Info seq [hh:mm:ss:mss] response: + { + "response": {}, + "responseRequired": true + } +After request + +Before request + +Info seq [hh:mm:ss:mss] request: + { + "command": "applyCodeActionCommand", + "arguments": { + "command": { + "type": "install package", + "file": "/home/src/projects/project/src/file.ts", + "packageName": "react'test" + } + }, + "seq": 4, + "type": "request" + } +TI:: [hh:mm:ss:mss] 'react'test':: Package name 'react'test' contains invalid characters +TI:: [hh:mm:ss:mss] Sending response: + { + "kind": "action::packageInstalled", + "projectName": "/home/src/projects/project/tsconfig.json", + "id": 2, + "success": false, + "message": "'react'test':: Package name 'react'test' contains invalid characters" + } +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "setTypings", + "body": { + "kind": "action::packageInstalled", + "projectName": "/home/src/projects/project/tsconfig.json", + "id": 2, + "success": false, + "message": "'react'test':: Package name 'react'test' contains invalid characters" + } + } +Info seq [hh:mm:ss:mss] response: + { + "response": {}, + "responseRequired": true + } +After request + +Before request + +Info seq [hh:mm:ss:mss] request: + { + "command": "applyCodeActionCommand", + "arguments": { + "command": { + "type": "install package", + "file": "/home/src/projects/project/src/file.ts", + "packageName": "a/b/c" + } + }, + "seq": 5, + "type": "request" + } +TI:: [hh:mm:ss:mss] 'a/b/c':: Package name 'a/b/c' contains invalid characters +TI:: [hh:mm:ss:mss] Sending response: + { + "kind": "action::packageInstalled", + "projectName": "/home/src/projects/project/tsconfig.json", + "id": 3, + "success": false, + "message": "'a/b/c':: Package name 'a/b/c' contains invalid characters" + } +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "setTypings", + "body": { + "kind": "action::packageInstalled", + "projectName": "/home/src/projects/project/tsconfig.json", + "id": 3, + "success": false, + "message": "'a/b/c':: Package name 'a/b/c' contains invalid characters" + } + } +Info seq [hh:mm:ss:mss] response: + { + "response": {}, + "responseRequired": true + } +After request + +Before running PendingInstalls callback:: count: 0 + +After running PendingInstalls callback:: count: 0 From 050880ce59e30b356b686bd3144efe24f875ebc8 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Wed, 15 Apr 2026 22:34:47 +0000 Subject: [PATCH 4/4] Bump version to 6.0.3 and LKG --- lib/_tsc.js | 4 +++- lib/typescript.js | 31 +++++++++++++++++++++++++------ package-lock.json | 4 ++-- package.json | 2 +- src/compiler/corePublic.ts | 2 +- 5 files changed, 32 insertions(+), 11 deletions(-) diff --git a/lib/_tsc.js b/lib/_tsc.js index 43be2b1071e09..9a9c0ac10f26d 100644 --- a/lib/_tsc.js +++ b/lib/_tsc.js @@ -18,7 +18,7 @@ and limitations under the License. // src/compiler/corePublic.ts var versionMajorMinor = "6.0"; -var version = "6.0.2"; +var version = "6.0.3"; // src/compiler/core.ts var emptyArray = []; @@ -45186,6 +45186,8 @@ function getContainerFlags(node) { return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */ | 16 /* IsFunctionExpression */ | 256 /* PropagatesThisKeyword */; case 269 /* ModuleBlock */: return 4 /* IsControlFlowContainer */; + case 173 /* PropertyDeclaration */: + return node.initializer ? 4 /* IsControlFlowContainer */ : 0 /* None */; case 300 /* CatchClause */: case 249 /* ForStatement */: case 250 /* ForInStatement */: diff --git a/lib/typescript.js b/lib/typescript.js index d322bce730854..3ba0ce46aad37 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -2289,7 +2289,7 @@ module.exports = __toCommonJS(typescript_exports); // src/compiler/corePublic.ts var versionMajorMinor = "6.0"; -var version = "6.0.2"; +var version = "6.0.3"; var Comparison = /* @__PURE__ */ ((Comparison3) => { Comparison3[Comparison3["LessThan"] = -1] = "LessThan"; Comparison3[Comparison3["EqualTo"] = 0] = "EqualTo"; @@ -49721,6 +49721,8 @@ function getContainerFlags(node) { return 1 /* IsContainer */ | 4 /* IsControlFlowContainer */ | 32 /* HasLocals */ | 8 /* IsFunctionLike */ | 16 /* IsFunctionExpression */ | 256 /* PropagatesThisKeyword */; case 269 /* ModuleBlock */: return 4 /* IsControlFlowContainer */; + case 173 /* PropertyDeclaration */: + return node.initializer ? 4 /* IsControlFlowContainer */ : 0 /* None */; case 300 /* CatchClause */: case 249 /* ForStatement */: case 250 /* ForInStatement */: @@ -139651,7 +139653,8 @@ var NameValidationResult = /* @__PURE__ */ ((NameValidationResult2) => { NameValidationResult2[NameValidationResult2["NameTooLong"] = 2] = "NameTooLong"; NameValidationResult2[NameValidationResult2["NameStartsWithDot"] = 3] = "NameStartsWithDot"; NameValidationResult2[NameValidationResult2["NameStartsWithUnderscore"] = 4] = "NameStartsWithUnderscore"; - NameValidationResult2[NameValidationResult2["NameContainsNonURISafeCharacters"] = 5] = "NameContainsNonURISafeCharacters"; + NameValidationResult2[NameValidationResult2["NameContainsInvalidCharacters"] = 5] = "NameContainsInvalidCharacters"; + NameValidationResult2[NameValidationResult2["NameContainsNonURISafeCharacters"] = 5 /* NameContainsInvalidCharacters */] = "NameContainsNonURISafeCharacters"; return NameValidationResult2; })(NameValidationResult || {}); var maxPackageNameLength = 214; @@ -139697,8 +139700,8 @@ function validatePackageNameWorker(packageName, supportScopedPackage) { return 0 /* Ok */; } } - if (encodeURIComponent(packageName) !== packageName) { - return 5 /* NameContainsNonURISafeCharacters */; + if (!/^[\w.-]+$/.test(packageName)) { + return 5 /* NameContainsInvalidCharacters */; } return 0 /* Ok */; } @@ -139722,8 +139725,8 @@ function renderPackageNameValidationFailureWorker(typing, result, name, isScopeN return `'${typing}':: ${kind} name '${name}' cannot start with '.'`; case 4 /* NameStartsWithUnderscore */: return `'${typing}':: ${kind} name '${name}' cannot start with '_'`; - case 5 /* NameContainsNonURISafeCharacters */: - return `'${typing}':: ${kind} name '${name}' contains non URI safe characters`; + case 5 /* NameContainsInvalidCharacters */: + return `'${typing}':: ${kind} name '${name}' contains invalid characters`; case 0 /* Ok */: return Debug.fail(); // Shouldn't have called this. @@ -186596,6 +186599,22 @@ var TypingsInstaller = class { /** @internal */ installPackage(req) { const { fileName, packageName, projectName, projectRootPath, id } = req; + const validationResult = ts_JsTyping_exports.validatePackageName(packageName); + if (validationResult !== ts_JsTyping_exports.NameValidationResult.Ok) { + const message = ts_JsTyping_exports.renderPackageNameValidationFailure(validationResult, packageName); + if (this.log.isEnabled()) { + this.log.writeLine(message); + } + const response = { + kind: ActionPackageInstalled, + projectName, + id, + success: false, + message + }; + this.sendResponse(response); + return; + } const cwd = forEachAncestorDirectory(getDirectoryPath(fileName), (directory) => { if (this.installTypingHost.fileExists(combinePaths(directory, "package.json"))) { return directory; diff --git a/package-lock.json b/package-lock.json index 8096eb3b2da4b..700e2e7c83f24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "typescript", - "version": "6.0.2", + "version": "6.0.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "typescript", - "version": "6.0.2", + "version": "6.0.3", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", diff --git a/package.json b/package.json index 77e3fc02bfdf4..703fd46cf275d 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "typescript", "author": "Microsoft Corp.", "homepage": "https://www.typescriptlang.org/", - "version": "6.0.2", + "version": "6.0.3", "license": "Apache-2.0", "description": "TypeScript is a language for application scale JavaScript development", "keywords": [ diff --git a/src/compiler/corePublic.ts b/src/compiler/corePublic.ts index a52ba154ca2ff..b35b6e2916623 100644 --- a/src/compiler/corePublic.ts +++ b/src/compiler/corePublic.ts @@ -3,7 +3,7 @@ export const versionMajorMinor = "6.0"; // The following is baselined as a literal template type without intervention /** The version of the TypeScript compiler release */ -export const version = "6.0.2" as string; +export const version = "6.0.3" as string; /** * Type of objects whose values are all of the same type.