From 8ffae86ca4ddec375d07cd0f2b7ea9d96ea1d5ef Mon Sep 17 00:00:00 2001 From: Cameron Clark Date: Mon, 11 Aug 2025 18:05:55 +0100 Subject: [PATCH 1/3] perf(tspath): optimize the fast path case for `ToFileNameLowerCase` --- internal/tspath/path.go | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/internal/tspath/path.go b/internal/tspath/path.go index a0d722b233..4813543a5c 100644 --- a/internal/tspath/path.go +++ b/internal/tspath/path.go @@ -533,13 +533,42 @@ func GetCanonicalFileName(fileName string, useCaseSensitiveFileNames bool) strin // Rest special characters are either already in lower case format or // they have corresponding upper case character so they dont need special handling -func ToFileNameLowerCase(fileName string) string { +func ToFileNameLowerCase(s string) string { + const IWithDot = '\u0130' + + ascii := true + needsLower := false + for i := 0; i < len(s); i++ { + c := s[i] + if c >= 0x80 { + ascii = false + break + } + if 'A' <= c && c <= 'Z' { + needsLower = true + } + } + if ascii { + if !needsLower { + return s + } + b := make([]byte, len(s)) + for i := 0; i < len(s); i++ { + c := s[i] + if 'A' <= c && c <= 'Z' { + c += 'a' - 'A' // +32 + } + b[i] = c + } + return string(b) + } + return strings.Map(func(r rune) rune { - if r == '\u0130' { + if r == IWithDot { return r } return unicode.ToLower(r) - }, fileName) + }, s) } func ToPath(fileName string, basePath string, useCaseSensitiveFileNames bool) Path { From 2462166aa1750d082e3737c0d647d8caf965c91d Mon Sep 17 00:00:00 2001 From: Cameron Clark Date: Mon, 11 Aug 2025 23:52:40 +0100 Subject: [PATCH 2/3] lint --- internal/tspath/path.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/internal/tspath/path.go b/internal/tspath/path.go index 4813543a5c..1bb78533a3 100644 --- a/internal/tspath/path.go +++ b/internal/tspath/path.go @@ -538,8 +538,7 @@ func ToFileNameLowerCase(s string) string { ascii := true needsLower := false - for i := 0; i < len(s); i++ { - c := s[i] + for _, c := range []byte(s) { if c >= 0x80 { ascii = false break @@ -553,8 +552,7 @@ func ToFileNameLowerCase(s string) string { return s } b := make([]byte, len(s)) - for i := 0; i < len(s); i++ { - c := s[i] + for i, c := range []byte(s) { if 'A' <= c && c <= 'Z' { c += 'a' - 'A' // +32 } From dcb78e8afda3c11175a704b9a3194029cd125f7e Mon Sep 17 00:00:00 2001 From: Cameron Clark Date: Tue, 12 Aug 2025 18:50:54 +0100 Subject: [PATCH 3/3] rename fn arg from `s` to `fileName` --- internal/tspath/path.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/tspath/path.go b/internal/tspath/path.go index 1bb78533a3..d5fe169564 100644 --- a/internal/tspath/path.go +++ b/internal/tspath/path.go @@ -533,12 +533,12 @@ func GetCanonicalFileName(fileName string, useCaseSensitiveFileNames bool) strin // Rest special characters are either already in lower case format or // they have corresponding upper case character so they dont need special handling -func ToFileNameLowerCase(s string) string { +func ToFileNameLowerCase(fileName string) string { const IWithDot = '\u0130' ascii := true needsLower := false - for _, c := range []byte(s) { + for _, c := range []byte(fileName) { if c >= 0x80 { ascii = false break @@ -549,10 +549,10 @@ func ToFileNameLowerCase(s string) string { } if ascii { if !needsLower { - return s + return fileName } - b := make([]byte, len(s)) - for i, c := range []byte(s) { + b := make([]byte, len(fileName)) + for i, c := range []byte(fileName) { if 'A' <= c && c <= 'Z' { c += 'a' - 'A' // +32 } @@ -566,7 +566,7 @@ func ToFileNameLowerCase(s string) string { return r } return unicode.ToLower(r) - }, s) + }, fileName) } func ToPath(fileName string, basePath string, useCaseSensitiveFileNames bool) Path {