Compare commits

...

1 Commits

Author SHA1 Message Date
Jarred Sumner
ac3da5b488 25% smaller sourcemaps 2025-03-09 03:55:16 -07:00
5 changed files with 36 additions and 15 deletions

View File

@@ -115,6 +115,7 @@ pub const SavedSourceMap = struct {
mutex: bun.Mutex = .{},
pub const vlq_offset = 24;
const debug = bun.Output.scoped(.SourceMap, true);
pub fn init(this: *SavedSourceMap, map: *HashTable) void {
this.* = .{
@@ -240,7 +241,7 @@ pub const SavedSourceMap = struct {
pub const HashTable = std.HashMap(u64, *anyopaque, IdentityContext(u64), 80);
pub fn onSourceMapChunk(this: *SavedSourceMap, chunk: SourceMap.Chunk, source: logger.Source) anyerror!void {
pub fn onSourceMapChunk(this: *SavedSourceMap, chunk: SourceMap.Chunk, source: *const logger.Source) anyerror!void {
try this.putMappings(source, chunk.buffer);
}
@@ -269,7 +270,8 @@ pub const SavedSourceMap = struct {
this.map.deinit();
}
pub fn putMappings(this: *SavedSourceMap, source: logger.Source, mappings: MutableString) !void {
pub fn putMappings(this: *SavedSourceMap, source: *const logger.Source, mappings: MutableString) !void {
debug("put {s} = {}", .{ source.path.text, bun.fmt.size(mappings.list.items.len, .{}) });
try this.putValue(source.path.text, Value.init(bun.cast(*SavedMappings, mappings.list.items.ptr)));
}
@@ -278,6 +280,7 @@ pub const SavedSourceMap = struct {
defer this.unlock();
const entry = try this.map.getOrPut(bun.hash(path));
if (entry.found_existing) {
var old_value = Value.from(entry.value_ptr.*);
if (old_value.get(ParsedSourceMap)) |parsed_source_map| {
@@ -1056,7 +1059,7 @@ pub const VirtualMachine = struct {
/// When the inspector is enabled, we want to generate an inline sourcemap.
/// And, for now, we also store it in source_mappings like normal
/// This is hideously expensive memory-wise...
pub fn onChunk(this: *SourceMapHandlerGetter, chunk: SourceMap.Chunk, source: logger.Source) anyerror!void {
pub fn onChunk(this: *SourceMapHandlerGetter, chunk: SourceMap.Chunk, source: *const logger.Source) anyerror!void {
var temp_json_buffer = bun.MutableString.initEmpty(bun.default_allocator);
defer temp_json_buffer.deinit();
temp_json_buffer = try chunk.printSourceMapContentsAtOffset(source, temp_json_buffer, true, SavedSourceMap.vlq_offset, true);

View File

@@ -548,7 +548,7 @@ pub const RuntimeTranspilerStore = struct {
}
if (cache.entry) |*entry| {
vm.source_mappings.putMappings(parse_result.source, .{
vm.source_mappings.putMappings(&parse_result.source, .{
.list = .{ .items = @constCast(entry.sourcemap), .capacity = entry.sourcemap.len },
.allocator = bun.default_allocator,
}) catch {};
@@ -1787,7 +1787,7 @@ pub const ModuleLoader = struct {
}
if (cache.entry) |*entry| {
jsc_vm.source_mappings.putMappings(parse_result.source, .{
jsc_vm.source_mappings.putMappings(&parse_result.source, .{
.list = .{ .items = @constCast(entry.sourcemap), .capacity = entry.sourcemap.len },
.allocator = bun.default_allocator,
}) catch {};

View File

@@ -420,14 +420,14 @@ pub const SourceMapHandler = struct {
ctx: *anyopaque,
callback: Callback,
const Callback = *const fn (*anyopaque, chunk: SourceMap.Chunk, source: logger.Source) anyerror!void;
pub fn onSourceMapChunk(self: *const @This(), chunk: SourceMap.Chunk, source: logger.Source) anyerror!void {
const Callback = *const fn (*anyopaque, chunk: SourceMap.Chunk, source: *const logger.Source) anyerror!void;
pub fn onSourceMapChunk(self: *const @This(), chunk: SourceMap.Chunk, source: *const logger.Source) anyerror!void {
try self.callback(self.ctx, chunk, source);
}
pub fn For(comptime Type: type, comptime handler: (fn (t: *Type, chunk: SourceMap.Chunk, source: logger.Source) anyerror!void)) type {
pub fn For(comptime Type: type, comptime handler: (fn (t: *Type, chunk: SourceMap.Chunk, source: *const logger.Source) anyerror!void)) type {
return struct {
pub fn onChunk(self: *anyopaque, chunk: SourceMap.Chunk, source: logger.Source) anyerror!void {
pub fn onChunk(self: *anyopaque, chunk: SourceMap.Chunk, source: *const logger.Source) anyerror!void {
try handler(@as(*Type, @ptrCast(@alignCast(self))), chunk, source);
}
@@ -454,6 +454,18 @@ pub const Options = struct {
source_map_allocator: ?std.mem.Allocator = null,
source_map_handler: ?SourceMapHandler = null,
source_map_builder: ?*bun.sourcemap.Chunk.Builder = null,
// Necessary for the `source-map` library to work correctly, which means we
// only need it if we're generating source maps externally, such as when
// bundling or when the debugger is enabled.
//
// _tsc.js sourcemap size:
//
// on: 3.18 MB
// off: 2.49 MB
//
source_map_cover_lines_without_mappings: bool = true,
css_import_behavior: Api.CssInJsBehavior = Api.CssInJsBehavior.facade,
target: options.Target = .browser,
@@ -5848,7 +5860,7 @@ pub fn getSourceMapBuilder(
opts.source_map_allocator orelse opts.allocator,
is_bun_platform and generate_source_map == .lazy,
),
.cover_lines_without_mappings = true,
.cover_lines_without_mappings = opts.source_map_cover_lines_without_mappings,
.approximate_input_line_count = tree.approximate_newline_count,
.prepend_count = is_bun_platform and generate_source_map == .lazy,
.line_offset_tables = opts.line_offset_tables orelse brk: {
@@ -6016,7 +6028,7 @@ pub fn printAst(
cache.put(printer.writer.ctx.getWritten(), source_maps_chunk.buffer.list.items);
}
try handler.onSourceMapChunk(source_maps_chunk, source.*);
try handler.onSourceMapChunk(source_maps_chunk, source);
} else {
if (opts.runtime_transpiler_cache) |cache| {
cache.put(printer.writer.ctx.getWritten(), "");
@@ -6024,7 +6036,7 @@ pub fn printAst(
}
} else if (comptime generate_source_map) {
if (opts.source_map_handler) |handler| {
try handler.onSourceMapChunk(printer.source_map_builder.generateChunk(printer.writer.ctx.getWritten()), source.*);
try handler.onSourceMapChunk(printer.source_map_builder.generateChunk(printer.writer.ctx.getWritten()), source);
}
}
@@ -6271,7 +6283,7 @@ pub fn printCommonJS(
if (comptime generate_source_map) {
if (opts.source_map_handler) |handler| {
try handler.onSourceMapChunk(printer.source_map_builder.generateChunk(printer.writer.ctx.getWritten()), source.*);
try handler.onSourceMapChunk(printer.source_map_builder.generateChunk(printer.writer.ctx.getWritten()), source);
}
}

View File

@@ -1226,7 +1226,7 @@ pub const Chunk = struct {
pub fn printSourceMapContents(
chunk: Chunk,
source: Logger.Source,
source: *const Logger.Source,
mutable: MutableString,
include_sources_contents: bool,
comptime ascii_only: bool,
@@ -1243,7 +1243,7 @@ pub const Chunk = struct {
pub fn printSourceMapContentsAtOffset(
chunk: Chunk,
source: Logger.Source,
source: *const Logger.Source,
mutable: MutableString,
include_sources_contents: bool,
offset: usize,

View File

@@ -910,6 +910,12 @@ pub const Transpiler = struct {
.print_dce_annotations = transpiler.options.emit_dce_annotations,
.hmr_ref = ast.wrapper_ref,
.mangled_props = null,
.source_map_cover_lines_without_mappings = if (is_bun)
// If the sourcemaps are strictly for internal usage, we can disable this
transpiler.options.debugger or transpiler.options.code_coverage or transpiler.options.dead_code_elimination == false
else
true,
},
enable_source_map,
),