diff options
author | 2023-05-04 22:44:02 -0700 | |
---|---|---|
committer | 2023-05-04 22:44:02 -0700 | |
commit | d9386a68a4316052f355235a7ff4f4b5eb0a2722 (patch) | |
tree | 183845717e420645e2ab3b5705dc87b393b726b9 | |
parent | 945d069290fcf0ce852120b809ed8aa6cdd1e245 (diff) | |
download | bun-d9386a68a4316052f355235a7ff4f4b5eb0a2722.tar.gz bun-d9386a68a4316052f355235a7ff4f4b5eb0a2722.tar.zst bun-d9386a68a4316052f355235a7ff4f4b5eb0a2722.zip |
fix source map line offsets (#2791)
* find codepoint at `i`
* fix allocator usage
* missing comment
* switch to `Cursor` iterator
-rw-r--r-- | src/bundler/bundle_v2.zig | 81 | ||||
-rw-r--r-- | src/js_printer.zig | 37 | ||||
-rw-r--r-- | src/sourcemap/sourcemap.zig | 11 | ||||
-rw-r--r-- | src/string_joiner.zig | 37 | ||||
-rw-r--r-- | src/string_mutable.zig | 2 |
5 files changed, 116 insertions, 52 deletions
diff --git a/src/bundler/bundle_v2.zig b/src/bundler/bundle_v2.zig index de5962671..85cbe4ccf 100644 --- a/src/bundler/bundle_v2.zig +++ b/src/bundler/bundle_v2.zig @@ -6309,6 +6309,7 @@ const LinkerContext = struct { j.push(hashbang); j.push("\n"); line_offset.advance(hashbang); + line_offset.advance("\n"); newline_before_comment = true; is_executable = true; } @@ -6316,6 +6317,7 @@ const LinkerContext = struct { if (chunk.entry_point.is_entry_point and ctx.c.graph.ast.items(.target)[chunk.entry_point.source_index].isBun()) { j.push("// @bun\n"); + line_offset.advance("// @bun\n"); } // TODO: banner @@ -6400,24 +6402,20 @@ const LinkerContext = struct { line_offset.advance(compile_result.code()); j.append(compile_result.code(), 0, bun.default_allocator); } else { + const generated_offset = line_offset; j.append(compile_result.code(), 0, bun.default_allocator); - var generated_offset = line_offset; - line_offset.reset(); - - if (c.options.source_maps != .none) { - switch (compile_result.javascript.result) { - .result => |res| { - if (res.source_map) |source_map| { - try compile_results_for_source_map.append(allocator, CompileResultForSourceMap{ - .source_map_chunk = source_map, - .generated_offset = generated_offset.value, - .source_index = compile_result.sourceIndex(), - }); - } - }, - else => {}, + if (compile_result.source_map_chunk()) |source_map_chunk| { + line_offset.reset(); + if (c.options.source_maps != .none) { + try compile_results_for_source_map.append(allocator, CompileResultForSourceMap{ + .source_map_chunk = source_map_chunk, + .generated_offset = generated_offset.value, + .source_index = compile_result.sourceIndex(), + }); } + } else { + line_offset.advance(compile_result.code()); } } @@ -6437,7 +6435,6 @@ const LinkerContext = struct { if (cross_chunk_suffix.len > 0) { if (newline_before_comment) { j.push("\n"); - line_offset.advance("\n"); } j.append(cross_chunk_suffix, 0, bun.default_allocator); @@ -8783,10 +8780,15 @@ const LinkerContext = struct { const code_allocator = max_heap_allocator.init(bun.default_allocator); - var max_heap_allocator_sourcemap: bun.MaxHeapAllocator = undefined; - defer max_heap_allocator_sourcemap.deinit(); + var max_heap_allocator_source_map: bun.MaxHeapAllocator = undefined; + defer max_heap_allocator_source_map.deinit(); + + const source_map_allocator = max_heap_allocator_source_map.init(bun.default_allocator); - const sourcemap_allocator = max_heap_allocator_sourcemap.init(bun.default_allocator); + var max_heap_allocator_inline_source_map: bun.MaxHeapAllocator = undefined; + defer max_heap_allocator_inline_source_map.deinit(); + + const code_with_inline_source_map_allocator = max_heap_allocator_inline_source_map.init(bun.default_allocator); var pathbuf: [bun.MAX_PATH_BYTES]u8 = undefined; @@ -8831,7 +8833,7 @@ const LinkerContext = struct { switch (c.options.source_maps) { .external => { - var output_source_map = chunk.output_source_map.finalize(sourcemap_allocator, code_result.shifts) catch @panic("Failed to allocate memory for external source map"); + var output_source_map = chunk.output_source_map.finalize(source_map_allocator, code_result.shifts) catch @panic("Failed to allocate memory for external source map"); const source_map_final_rel_path = strings.concat(default_allocator, &.{ chunk.final_rel_path, ".map", @@ -8879,12 +8881,12 @@ const LinkerContext = struct { }); }, .@"inline" => { - var output_source_map = chunk.output_source_map.finalize(sourcemap_allocator, code_result.shifts) catch @panic("Failed to allocate memory for external source map"); + var output_source_map = chunk.output_source_map.finalize(source_map_allocator, code_result.shifts) catch @panic("Failed to allocate memory for external source map"); const encode_len = base64.encodeLen(output_source_map); const source_map_start = "//# sourceMappingURL=data:application/json;base64,"; const total_len = code_result.buffer.len + source_map_start.len + encode_len + 1; - var buf = std.ArrayList(u8).initCapacity(sourcemap_allocator, total_len) catch @panic("Failed to allocate memory for output file with inline source map"); + var buf = std.ArrayList(u8).initCapacity(code_with_inline_source_map_allocator, total_len) catch @panic("Failed to allocate memory for output file with inline source map"); buf.appendSliceAssumeCapacity(code_result.buffer); buf.appendSliceAssumeCapacity(source_map_start); @@ -10542,17 +10544,25 @@ pub const Chunk = struct { // TODO: make this safe var joiny = joiner_; - if (comptime FeatureFlags.source_map_debug_id) { - // This comment must go before the //# sourceMappingURL comment - joiny.push(std.fmt.allocPrint( - graph.allocator, - "\n//# debugId={}\n", - .{bun.sourcemap.DebugIDFormatter{ .id = chunk.isolated_hash }}, - ) catch unreachable); - } + const allocator = allocator_to_use orelse allocatorForSize(joiny.len); + + const buffer = brk: { + if (comptime FeatureFlags.source_map_debug_id) { + // This comment must go before the //# sourceMappingURL comment + const debug_id_fmt = std.fmt.allocPrint( + graph.allocator, + "\n//# debugId={}\n", + .{bun.sourcemap.DebugIDFormatter{ .id = chunk.isolated_hash }}, + ) catch unreachable; + + break :brk try joiny.doneWithEnd(allocator, debug_id_fmt); + } + + break :brk try joiny.done(allocator); + }; return .{ - .buffer = try joiny.done((allocator_to_use orelse allocatorForSize(joiny.len))), + .buffer = buffer, .shifts = &[_]sourcemap.SourceMapShifts{}, }; }, @@ -10817,6 +10827,15 @@ const CompileResult = union(enum) { }; } + pub fn source_map_chunk(this: *const CompileResult) ?sourcemap.Chunk { + return switch (this.*) { + .javascript => |r| switch (r.result) { + .result => |r2| r2.source_map, + else => null, + }, + }; + } + pub fn sourceIndex(this: *const CompileResult) Index.Int { return switch (this.*) { .javascript => |r| r.source_index, diff --git a/src/js_printer.zig b/src/js_printer.zig index 718632ef6..b1509bf6d 100644 --- a/src/js_printer.zig +++ b/src/js_printer.zig @@ -5590,14 +5590,19 @@ pub const Format = enum { cjs_ascii, }; +const GenerateSourceMap = enum { + disable, + lazy, + eager, +}; pub fn getSourceMapBuilder( - comptime generate_source_map: bool, + comptime generate_source_map: GenerateSourceMap, comptime is_bun_platform: bool, opts: Options, source: *const logger.Source, tree: *const Ast, ) SourceMap.Chunk.Builder { - if (comptime !generate_source_map) + if (comptime generate_source_map == .disable) return undefined; return .{ @@ -5606,15 +5611,19 @@ pub fn getSourceMapBuilder( is_bun_platform, ), .cover_lines_without_mappings = true, - .prepend_count = is_bun_platform, - .line_offset_tables = opts.line_offset_tables orelse SourceMap.LineOffsetTable.generate( - opts.allocator, - source.contents, - @intCast( - i32, - tree.approximate_newline_count, - ), - ), + .prepend_count = is_bun_platform and generate_source_map == .lazy, + .line_offset_tables = opts.line_offset_tables orelse brk: { + if (generate_source_map == .lazy) break :brk SourceMap.LineOffsetTable.generate( + opts.allocator, + source.contents, + @intCast( + i32, + tree.approximate_newline_count, + ), + ); + + break :brk SourceMap.LineOffsetTable.List{}; + }, }; } @@ -5718,7 +5727,7 @@ pub fn printAst( tree.import_records.slice(), opts, renamer, - getSourceMapBuilder(generate_source_map, ascii_only, opts, source, &tree), + getSourceMapBuilder(if (generate_source_map) .lazy else .disable, ascii_only, opts, source, &tree), ); defer { imported_module_ids_list = printer.imported_module_ids; @@ -5873,7 +5882,7 @@ pub fn printWithWriterAndPlatform( import_records, opts, renamer, - getSourceMapBuilder(generate_source_maps, is_bun_platform, opts, source, &ast), + getSourceMapBuilder(if (generate_source_maps) .eager else .disable, is_bun_platform, opts, source, &ast), ); defer printer.temporary_bindings.deinit(bun.default_allocator); defer _writer.* = printer.writer.*; @@ -5930,7 +5939,7 @@ pub fn printCommonJS( tree.import_records.slice(), opts, renamer.toRenamer(), - getSourceMapBuilder(generate_source_map, false, opts, source, &tree), + getSourceMapBuilder(if (generate_source_map) .lazy else .disable, false, opts, source, &tree), ); defer { imported_module_ids_list = printer.imported_module_ids; diff --git a/src/sourcemap/sourcemap.zig b/src/sourcemap/sourcemap.zig index b7441ccc9..cc557caf1 100644 --- a/src/sourcemap/sourcemap.zig +++ b/src/sourcemap/sourcemap.zig @@ -356,17 +356,16 @@ pub const LineColumnOffset = struct { std.debug.assert(i >= offset); std.debug.assert(i < input.len); - offset = i + 1; + var iter = strings.CodepointIterator.initOffset(input, i); + var cursor = strings.CodepointIterator.Cursor{ .i = @truncate(u32, iter.i) }; + _ = iter.next(&cursor); + offset = i + cursor.width; - var cp = strings.CodepointIterator.initOffset(input, offset); - var cursor = strings.CodepointIterator.Cursor{}; - _ = cp.next(&cursor); switch (cursor.c) { '\r', '\n', 0x2028, 0x2029 => { // Handle Windows-specific "\r\n" newlines - if (cp.c == '\r' and input.len > offset + 1 and input[offset + 1] == '\n') { + if (cursor.c == '\r' and input.len > i + 1 and input[i + 1] == '\n') { columns += 1; - offset += 1; continue; } diff --git a/src/string_joiner.zig b/src/string_joiner.zig index 7896743cb..c1b42dee7 100644 --- a/src/string_joiner.zig +++ b/src/string_joiner.zig @@ -60,6 +60,43 @@ pub fn done(this: *Joiner, allocator: Allocator) ![]u8 { return slice[0 .. slice.len - remaining.len]; } +pub fn doneWithEnd(this: *Joiner, allocator: Allocator, end: []const u8) ![]u8 { + if (this.head == null and end.len == 0) { + return &[_]u8{}; + } + + if (this.head == null) { + var slice = try allocator.alloc(u8, end.len); + @memcpy(slice.ptr, end.ptr, end.len); + return slice; + } + + var slice = try allocator.alloc(u8, this.len + end.len); + var remaining = slice; + var el_ = this.head; + while (el_) |join| { + const to_join = join.data.slice[join.data.offset..]; + @memcpy(remaining.ptr, to_join.ptr, to_join.len); + + remaining = remaining[@min(remaining.len, to_join.len)..]; + + var prev = join; + el_ = join.next; + if (prev.data.needs_deinit) { + prev.data.allocator.free(prev.data.slice); + prev.data = Joinable{}; + } + + if (this.use_pool) prev.release(); + } + + @memcpy(remaining.ptr, end.ptr, end.len); + + remaining = remaining[@min(remaining.len, end.len)..]; + + return slice[0 .. slice.len - remaining.len]; +} + pub fn lastByte(this: *const Joiner) u8 { if (this.tail) |tail| { const slice = tail.data.slice[tail.data.offset..]; diff --git a/src/string_mutable.zig b/src/string_mutable.zig index 9fdc3d090..2b8d80429 100644 --- a/src/string_mutable.zig +++ b/src/string_mutable.zig @@ -250,7 +250,7 @@ pub const MutableString = struct { return self.indexOfChar(char) != null; } - pub fn indexOfChar(self: *const MutableString, char: u8) ?usize { + pub fn indexOfChar(self: *const MutableString, char: u8) ?u32 { return strings.indexOfChar(self.list.items, char); } |