From 718b989eb42c5ca8a0718b0cfc9d6a7132fd9e9f Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Sat, 9 Aug 2025 21:29:07 -0400 Subject: [PATCH] Reduce string copies and allocations when emitting inlined sourcemaps --- internal/compiler/emitter.go | 6 +----- internal/sourcemap/generator.go | 23 +++++++++++++++++++---- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/internal/compiler/emitter.go b/internal/compiler/emitter.go index ab0cbf0f65..00ec371408 100644 --- a/internal/compiler/emitter.go +++ b/internal/compiler/emitter.go @@ -1,8 +1,6 @@ package compiler import ( - "encoding/base64" - "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/binder" "github.com/microsoft/typescript-go/internal/core" @@ -335,9 +333,7 @@ func (e *emitter) getSourceMapDirectory(mapOptions *core.CompilerOptions, filePa func (e *emitter) getSourceMappingURL(mapOptions *core.CompilerOptions, sourceMapGenerator *sourcemap.Generator, filePath string, sourceMapFilePath string, sourceFile *ast.SourceFile) string { if mapOptions.InlineSourceMap.IsTrue() { // Encode the sourceMap into the sourceMap url - sourceMapText := sourceMapGenerator.String() - base64SourceMapText := base64.StdEncoding.EncodeToString([]byte(sourceMapText)) - return "data:application/json;base64," + base64SourceMapText + return sourceMapGenerator.Base64DataURL() } sourceMapFile := tspath.GetBaseFileName(tspath.NormalizeSlashes(sourceMapFilePath)) diff --git a/internal/sourcemap/generator.go b/internal/sourcemap/generator.go index ea4edab607..d680f9b86d 100644 --- a/internal/sourcemap/generator.go +++ b/internal/sourcemap/generator.go @@ -1,11 +1,13 @@ package sourcemap import ( + "encoding/base64" + "encoding/json" "errors" "slices" "strings" + "unsafe" - "github.com/go-json-experiment/json" "github.com/microsoft/typescript-go/internal/tspath" ) @@ -333,13 +335,26 @@ func (gen *Generator) RawSourceMap() *RawSourceMap { } } -// Gets the string representation of the source map -func (gen *Generator) String() string { +func (gen *Generator) bytes() []byte { buf, err := json.Marshal(gen.RawSourceMap()) if err != nil { panic(err.Error()) } - return string(buf) + return buf +} + +// Gets the string representation of the source map +func (gen *Generator) String() string { + return string(gen.bytes()) +} + +func (gen *Generator) Base64DataURL() string { + const prefix = "data:application/json;base64," + data := gen.bytes() + buf := make([]byte, len(prefix)+base64.StdEncoding.EncodedLen(len(data))) + copy(buf, prefix) + base64.StdEncoding.Encode(buf[len(prefix):], data) + return unsafe.String(unsafe.SliceData(buf), len(buf)) } func base64FormatEncode(value int) rune {