aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Dylan Conway <35280289+dylan-conway@users.noreply.github.com> 2023-05-04 22:44:02 -0700
committerGravatar GitHub <noreply@github.com> 2023-05-04 22:44:02 -0700
commitd9386a68a4316052f355235a7ff4f4b5eb0a2722 (patch)
tree183845717e420645e2ab3b5705dc87b393b726b9
parent945d069290fcf0ce852120b809ed8aa6cdd1e245 (diff)
downloadbun-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.zig81
-rw-r--r--src/js_printer.zig37
-rw-r--r--src/sourcemap/sourcemap.zig11
-rw-r--r--src/string_joiner.zig37
-rw-r--r--src/string_mutable.zig2
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);
}