aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile95
-rw-r--r--src/javascript/jsc/api/transpiler.zig18
-rw-r--r--src/logger.zig2
-rw-r--r--src/options.zig6
-rw-r--r--src/runtime.zig8
-rw-r--r--src/sourcemap/sourcemap.zig171
6 files changed, 210 insertions, 90 deletions
diff --git a/Makefile b/Makefile
index 9f6bae934..a2fbaf826 100644
--- a/Makefile
+++ b/Makefile
@@ -161,7 +161,16 @@ MACOS_MIN_FLAG=
POSIX_PKG_MANAGER=sudo apt
-STRIP ?= $(shell which llvm-strip || which llvm-strip-13 || echo "Missing llvm-strip. Please pass it in the STRIP environment var"; exit 1;)
+STRIP=
+
+ifeq ($(OS_NAME),darwin)
+STRIP=strip -u -r
+endif
+
+ifeq ($(OS_NAME),linux)
+STRIP=$(which llvm-strip || echo "Missing strip")
+endif
+
HOMEBREW_PREFIX ?= $(BREW_PREFIX_PATH)
@@ -234,17 +243,18 @@ CLANG_FLAGS = $(INCLUDE_DIRS) \
-DBUILDING_JSCONLY__ \
-DASSERT_ENABLED=0 \
-fvisibility=hidden \
- -fvisibility-inlines-hidden \
- -fno-omit-frame-pointer $(CFLAGS)
+ -fvisibility-inlines-hidden
+
+PLATFORM_LINKER_FLAGS =
# This flag is only added to webkit builds on Apple platforms
# It has something to do with ICU
ifeq ($(OS_NAME), darwin)
-CLANG_FLAGS += -DDU_DISABLE_RENAMING=1 \
+PLATFORM_LINKER_FLAGS += -DDU_DISABLE_RENAMING=1 \
-lstdc++ \
+ -fno-keep-static-consts \
-ffunction-sections \
-fdata-sections \
- -Wl,-no_eh_labels \
-Wl,-dead_strip \
-Wl,-dead_strip_dylibs
endif
@@ -256,12 +266,11 @@ ARCHIVE_FILES_WITHOUT_LIBCRYPTO = $(MIMALLOC_FILE_PATH) \
$(BUN_DEPS_OUT_DIR)/libarchive.a \
$(BUN_DEPS_OUT_DIR)/libssl.a \
$(BUN_DEPS_OUT_DIR)/picohttpparser.o \
- $(BUN_DEPS_OUT_DIR)/libbacktrace.a
ARCHIVE_FILES = $(ARCHIVE_FILES_WITHOUT_LIBCRYPTO) $(BUN_DEPS_OUT_DIR)/libcrypto.boring.a
-PLATFORM_LINKER_FLAGS =
+
STATIC_MUSL_FLAG ?=
@@ -277,24 +286,23 @@ PLATFORM_LINKER_FLAGS = \
-fdata-sections \
-static-libstdc++ \
-static-libgcc \
+ -fno-omit-frame-pointer $(CFLAGS) \
-Wl,--compress-debug-sections,zlib \
${STATIC_MUSL_FLAG}
-endif
-ifeq ($(OS_NAME), darwin)
-PLATFORM_LINKER_FLAGS = \
- -Wl,-keep_private_externs
+ARCHIVE_FILES_WITHOUT_LIBCRYPTO += $(BUN_DEPS_OUT_DIR)/libbacktrace.a
endif
-BUN_LLD_FLAGS = $(OBJ_FILES) \
- ${ICU_FLAGS} \
- ${JSC_FILES} \
- $(ARCHIVE_FILES) \
+BUN_LLD_FLAGS_WITHOUT_JSC = $(ARCHIVE_FILES) \
$(LIBICONV_PATH) \
$(CLANG_FLAGS) \
$(DEFAULT_LINKER_FLAGS) \
- $(PLATFORM_LINKER_FLAGS)
+ $(PLATFORM_LINKER_FLAGS)
+
+
+
+BUN_LLD_FLAGS = $(OBJ_FILES) $(JSC_FILES) ${ICU_FLAGS} $(BUN_LLD_FLAGS_WITHOUT_JSC)
CLANG_VERSION = $(shell $(CC) --version | awk '/version/ {for(i=1; i<=NF; i++){if($$i=="version"){split($$(i+1),v,".");print v[1]}}}')
@@ -402,9 +410,22 @@ build-obj-wasm:
-o packages/bun-freestanding-wasm32/bun-wasm.wasm
cp packages/bun-freestanding-wasm32/bun-wasm.wasm src/api/demo/public/bun-wasm.wasm
+build-obj-wasm-small:
+ $(ZIG) build bun-wasm -Drelease-small -Dtarget=wasm32-freestanding --prominent-compile-errors
+ emcc -sEXPORTED_FUNCTIONS="['_bun_free', '_cycleStart', '_cycleEnd', '_bun_malloc', '_scan', '_transform', '_init']" \
+ -g -s ERROR_ON_UNDEFINED_SYMBOLS=0 -DNDEBUG \
+ $(BUN_DEPS_DIR)/libmimalloc.a.wasm \
+ packages/bun-freestanding-wasm32/bun-wasm.o -Oz --no-entry --allow-undefined -s ASSERTIONS=0 -s ALLOW_MEMORY_GROWTH=1 -s WASM_BIGINT=1 \
+ -o packages/bun-freestanding-wasm32/bun-wasm.wasm
+ cp packages/bun-freestanding-wasm32/bun-wasm.wasm src/api/demo/public/bun-wasm.wasm
+
+
build-obj-safe:
$(ZIG) build obj -Drelease-safe
+
+
+
sign-macos-x64:
gon sign.macos-x64.json
@@ -755,10 +776,11 @@ jsc-build-mac-compile:
mkdir -p $(WEBKIT_RELEASE_DIR) $(WEBKIT_DIR);
cd $(WEBKIT_RELEASE_DIR) && \
ICU_INCLUDE_DIRS="$(HOMEBREW_PREFIX)opt/icu4c/include" \
- CMAKE_BUILD_TYPE=Release cmake \
+ cmake \
-DPORT="JSCOnly" \
-DENABLE_STATIC_JSC=ON \
-DCMAKE_BUILD_TYPE=Release \
+ -DCMAKE_BUILD_TYPE=Release \
-DUSE_THIN_ARCHIVES=OFF \
-DENABLE_FTL_JIT=ON \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
@@ -806,7 +828,7 @@ jsc-build-mac-copy:
cp $(WEBKIT_RELEASE_DIR)/lib/libbmalloc.a $(BUN_DEPS_OUT_DIR)/libbmalloc.a
clean-jsc:
- cd src/javascript/jsc/WebKit && rm -rf **/CMakeCache.txt **/CMakeFiles
+ cd src/javascript/jsc/WebKit && rm -rf **/CMakeCache.txt **/CMakeFiles && rm -rf src/javascript/jsc/WebKit/WebKitBuild
clean-bindings:
rm -rf $(OBJ_DIR)/*.o
@@ -824,7 +846,16 @@ jsc-bindings-mac: $(OBJ_FILES)
# mimalloc is built as object files so that it can overload the system malloc
mimalloc:
rm -rf $(BUN_DEPS_DIR)/mimalloc/CMakeCache* $(BUN_DEPS_DIR)/mimalloc/CMakeFiles
- cd $(BUN_DEPS_DIR)/mimalloc; CFLAGS="$(CFLAGS)" cmake $(CMAKE_FLAGS) -DMI_SKIP_COLLECT_ON_EXIT=1 -DMI_BUILD_SHARED=OFF -DMI_BUILD_STATIC=ON -DMI_BUILD_TESTS=OFF -DMI_BUILD_OBJECT=ON ${MIMALLOC_OVERRIDE_FLAG} -DMI_USE_CXX=ON .; make;
+ cd $(BUN_DEPS_DIR)/mimalloc; \
+ CFLAGS="$(CFLAGS)" cmake $(CMAKE_FLAGS) \
+ -DMI_SKIP_COLLECT_ON_EXIT=1 \
+ -DMI_BUILD_SHARED=OFF \
+ -DMI_BUILD_STATIC=ON \
+ -DMI_BUILD_TESTS=OFF \
+ -DMI_BUILD_OBJECT=ON \
+ ${MIMALLOC_OVERRIDE_FLAG} \
+ -DMI_USE_CXX=OFF .\
+ && make -j $(CPUS);
cp $(BUN_DEPS_DIR)/mimalloc/$(MIMALLOC_INPUT_PATH) $(BUN_DEPS_OUT_DIR)/$(MIMALLOC_FILE)
@@ -837,9 +868,23 @@ bun-link-lld-debug:
-g \
$(DEBUG_BIN)/bun-debug.o \
-W \
- -o $(DEBUG_BIN)/bun-debug \
+ -o $(DEBUG_BIN)/bun-debug
+
+bun-link-lld-debug-no-jsc:
+ $(CXX) $(BUN_LLD_FLAGS_WITHOUT_JSC) \
+ -g \
+ $(DEBUG_BIN)/bun-debug.o \
+ -W \
+ -o $(DEBUG_BIN)/bun-debug
+bun-link-lld-release-no-jsc:
+ $(CXX) $(BUN_LLD_FLAGS_WITHOUT_JSC) \
+ -g \
+ $(BUN_RELEASE_BIN).o \
+ -W \
+ -o $(BUN_RELEASE_BIN) -Wl,-undefined,dynamic_lookup -Wl,-why_load
+
bun-relink-copy:
cp /tmp/bun-$(PACKAGE_JSON_VERSION).o $(BUN_RELEASE_BIN).o
@@ -851,7 +896,6 @@ bun-link-lld-release:
-o $(BUN_RELEASE_BIN) \
-W \
-flto \
- -ftls-model=initial-exec \
-O3
rm -rf $(BUN_RELEASE_BIN).dSYM
cp $(BUN_RELEASE_BIN) $(BUN_RELEASE_BIN)-profile
@@ -859,7 +903,7 @@ bun-link-lld-release:
ifeq ($(OS_NAME),darwin)
bun-link-lld-release-dsym:
$(DSYMUTIL) -o $(BUN_RELEASE_BIN).dSYM $(BUN_RELEASE_BIN)
- # -$(STRIP) $(BUN_RELEASE_BIN)
+ -$(STRIP) $(BUN_RELEASE_BIN)
mv $(BUN_RELEASE_BIN).o /tmp/bun-$(PACKAGE_JSON_VERSION).o
copy-to-bun-release-dir-dsym:
@@ -885,10 +929,11 @@ wasm-return1:
# The C compilation stuff with build.zig is really slow and we don't need to run this as often as the rest
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
$(CXX) -c -o $@ $< \
- $(CLANG_FLAGS) $(PLATFORM_LINKER_FLAGS) \
+ $(CLANG_FLAGS) \
+ $(MACOS_MIN_FLAG) \
-O3 \
- -fvectorize \
- -w -g \
+ -fno-exceptions \
+ -ffunction-sections -fdata-sections -g \
-ferror-limit=1000
sizegen:
diff --git a/src/javascript/jsc/api/transpiler.zig b/src/javascript/jsc/api/transpiler.zig
index 5863f0a69..5f66247bb 100644
--- a/src/javascript/jsc/api/transpiler.zig
+++ b/src/javascript/jsc/api/transpiler.zig
@@ -481,6 +481,24 @@ fn transformOptionsFromJSC(ctx: JSC.C.JSContextRef, temp_allocator: std.mem.Allo
transpiler.runtime.allow_runtime = flag.toBoolean();
}
+ if (object.get(globalThis, "sourcemap")) |flag| {
+ if (flag.isBoolean() or flag.isUndefinedOrNull()) {
+ if (flag.toBoolean()) {
+ transpiler.transform.source_map = Api.SourceMapMode.external;
+ } else {
+ transpiler.transform.source_map = Api.SourceMapMode.inline_into_file;
+ }
+ } else {
+ var sourcemap = flag.toSlice(globalThis, allocator);
+ if (options.SourceMapOption.map.get(sourcemap.slice())) |source| {
+ transpiler.transform.source_map = source.toAPI();
+ } else {
+ JSC.throwInvalidArguments("sourcemap must be one of \"inline\", \"external\", or \"none\"", .{}, ctx, exception);
+ return transpiler;
+ }
+ }
+ }
+
return transpiler;
}
diff --git a/src/logger.zig b/src/logger.zig
index 63590fcda..bab017ebc 100644
--- a/src/logger.zig
+++ b/src/logger.zig
@@ -80,7 +80,7 @@ pub const Loc = packed struct {
pub const Empty = Loc{ .start = -1 };
- pub inline fn eql(loc: *Loc, other: Loc) bool {
+ pub inline fn eql(loc: Loc, other: Loc) bool {
return loc.start == other.start;
}
diff --git a/src/options.zig b/src/options.zig
index d635b674a..80034db12 100644
--- a/src/options.zig
+++ b/src/options.zig
@@ -1092,10 +1092,10 @@ pub const SourceMapOption = enum {
};
}
- pub fn toAPI(source_map: SourceMapOption) Api.SourceMapMode {
- return switch (source_map orelse Api.SourceMapMode._none) {
+ pub fn toAPI(source_map: ?SourceMapOption) Api.SourceMapMode {
+ return switch (source_map orelse .none) {
.external => .external,
- .@"inline" => .@"inline",
+ .@"inline" => .@"inline_into_file",
else => ._none,
};
}
diff --git a/src/runtime.zig b/src/runtime.zig
index 32f45ffad..222b89919 100644
--- a/src/runtime.zig
+++ b/src/runtime.zig
@@ -33,9 +33,7 @@ pub const ErrorCSS = struct {
var paths = [_]string{ dirname, BUN_ROOT, ErrorCSSPathDev };
const file = std.fs.cwd().openFile(
resolve_path.joinAbsString(dirname, std.mem.span(&paths), .auto),
- .{
- .read = true,
- },
+ .{ .mode = .read_only },
) catch @panic("Missing packages/bun-error/bun-error.css. Please run \"make bun_error\"");
defer file.close();
return file.readToEndAlloc(default_allocator, (file.stat() catch unreachable).size) catch unreachable;
@@ -59,9 +57,7 @@ pub const ErrorJS = struct {
var paths = [_]string{ dirname, BUN_ROOT, ErrorJSPath };
const file = std.fs.cwd().openFile(
resolve_path.joinAbsString(dirname, std.mem.span(&paths), .auto),
- .{
- .read = true,
- },
+ .{ .mode = .read_only },
) catch @panic("Missing " ++ ErrorJSPath ++ ". Please run \"make bun_error\"");
defer file.close();
return file.readToEndAlloc(default_allocator, (file.stat() catch unreachable).size) catch unreachable;
diff --git a/src/sourcemap/sourcemap.zig b/src/sourcemap/sourcemap.zig
index cf96afa4e..3b6048985 100644
--- a/src/sourcemap/sourcemap.zig
+++ b/src/sourcemap/sourcemap.zig
@@ -14,22 +14,19 @@ const Joiner = @import("../string_joiner.zig");
const JSPrinter = @import("../js_printer.zig");
const URL = @import("../query_string_map.zig").URL;
const FileSystem = @import("../fs.zig").FileSystem;
-const base64_lut: [std.math.maxInt(u8)]u8 = brk: {
- @setEvalBranchQuota(9999);
- var bytes = [_]u8{255} ** std.math.maxInt(u8);
-
- for (base64) |c, i| {
- bytes[c] = i;
- }
- break :brk bytes;
-};
const SourceMap = @This();
-// One VLQ value never exceeds 20 bits of data, so 15 is more than enough
+const vlq_max_in_bytes = 8;
pub const VLQ = struct {
- bytes: [15]u8,
- len: u8 = 0,
+ // We only need to worry about i32
+ // That means the maximum VLQ-encoded value is 8 bytes
+ // because there are only 4 bits of number inside each VLQ value
+ // and it expects i32
+ // therefore, it can never be more than 32 bits long
+ // I believe the actual number is 7 bytes long, however we can add an extra byte to be more cautious
+ bytes: [vlq_max_in_bytes]u8,
+ len: u4 = 0,
};
/// Coordinates in source maps are stored using relative offsets for size
@@ -182,6 +179,62 @@ pub fn appendSourceMapChunk(j: *Joiner, prev_end_state_: SourceMapState, start_s
j.append(source_map_.list.items, @truncate(u32, @ptrToInt(source_map.ptr) - @ptrToInt(source_map_.list.items.ptr)), source_map_.allocator);
}
+const vlq_lookup_table: [256]VLQ = brk: {
+ var entries: [256]VLQ = undefined;
+ var i: usize = 0;
+ var j: i32 = 0;
+ while (i < 256) : (i += 1) {
+ entries[i] = encodeVLQ(j);
+ j += 1;
+ }
+ break :brk entries;
+};
+
+pub fn encodeVLQWithLookupTable(
+ value: i32,
+) VLQ {
+ return if (value >= 0 and value <= 255)
+ vlq_lookup_table[@intCast(usize, value)]
+ else
+ encodeVLQ(value);
+}
+
+test "encodeVLQ" {
+ const fixtures = .{
+ .{ 2_147_483_647, "+/////D" },
+ .{ -2_147_483_647, "//////D" },
+ .{ 0, "A" },
+ .{ 1, "C" },
+ .{ -1, "D" },
+ .{ 123, "2H" },
+ .{ 123456789, "qxmvrH" },
+ };
+ inline for (fixtures) |fixture| {
+ const result = encodeVLQ(fixture[0]);
+ try std.testing.expectEqualStrings(fixture[1], result.bytes[0..result.len]);
+ }
+}
+
+test "decodeVLQ" {
+ const fixtures = .{
+ .{ 2_147_483_647, "+/////D" },
+ .{ -2_147_483_647, "//////D" },
+ .{ 0, "A" },
+ .{ 1, "C" },
+ .{ -1, "D" },
+ .{ 123, "2H" },
+ .{ 123456789, "qxmvrH" },
+ .{ 8, "Q" },
+ };
+ inline for (fixtures) |fixture| {
+ const result = decodeVLQ(fixture[1], 0);
+ try std.testing.expectEqual(
+ result.value,
+ fixture[0],
+ );
+ }
+}
+
// A single base 64 digit can contain 6 bits of data. For the base 64 variable
// length quantities we use in the source map spec, the first bit is the sign,
// the next four bits are the actual value, and the 6th bit is the continuation
@@ -197,27 +250,19 @@ pub fn appendSourceMapChunk(j: *Joiner, prev_end_state_: SourceMapState, start_s
pub fn encodeVLQ(
value: i32,
) VLQ {
- var vlq: i32 = 0;
- var bytes = std.mem.zeroes([15]u8);
- var len: u8 = 0;
- if (value < 0) {
- vlq = ((-value) << 1) | 1;
- } else {
- vlq = value << 1;
- }
+ var len: u4 = 0;
+ var bytes: [vlq_max_in_bytes]u8 = undefined;
- if ((vlq >> 5) == 0) {
- const digit = @intCast(u8, vlq & 31);
- bytes[0] = base64[digit];
- return .{ .bytes = bytes, .len = 1 };
- }
+ var vlq: u32 = if (value >= 0)
+ @bitCast(u32, value << 1)
+ else
+ @bitCast(u32, (-value << 1) | 1);
- // i32 contains 32 bits
- // since
- // the maximum possible number is @maxInt(u20)
- //
- while (true) {
- var digit = @intCast(u8, vlq & 31);
+ // The max amount of digits a VLQ value for sourcemaps can contain is 9
+ // therefore, we can unroll the loop
+ comptime var i: usize = 0;
+ inline while (i < vlq_max_in_bytes) : (i += 1) {
+ var digit = vlq & 31;
vlq >>= 5;
// If there are still more digits in this value, we must make sure the
@@ -230,11 +275,11 @@ pub fn encodeVLQ(
len += 1;
if (vlq == 0) {
- break;
+ return .{ .bytes = bytes, .len = len };
}
}
- return .{ .bytes = bytes, .len = len };
+ return .{ .bytes = bytes, .len = 0 };
}
pub const VLQResult = struct {
@@ -242,33 +287,45 @@ pub const VLQResult = struct {
start: usize = 0,
};
+const base64_lut: [std.math.maxInt(u7)]u7 = brk: {
+ @setEvalBranchQuota(9999);
+ var bytes = [_]u7{std.math.maxInt(u7)} ** std.math.maxInt(u7);
+
+ for (base64) |c, i| {
+ bytes[c] = i;
+ }
+
+ break :brk bytes;
+};
+
fn decodeVLQ(encoded: []const u8, start: usize) VLQResult {
- var shift: i32 = 0;
- var vlq: i32 = 0;
- var len: usize = encoded.len;
- var i: usize = start;
+ var shift: u8 = 0;
+ var vlq: u32 = 0;
- while (i < len) {
- const index = @as(i32, base64_lut[encoded[i]]);
- if (index == std.math.maxInt(u8)) break;
+ // it will never exceed 9
+ // by doing it this way, we can hint to the compiler that it will not exceed 9
+ const encoded_ = encoded[start..][0..@minimum(encoded.len - start, comptime (vlq_max_in_bytes + 1))];
+
+ for (encoded_) |c, i| {
+ const index = @as(u32, base64_lut[@truncate(u7, c)]);
// decode a byte
- vlq |= (index & 31) << shift;
- i += 1;
+ vlq |= (index & 31) << @truncate(u5, shift);
shift += 5;
// Stop if there's no continuation bit
if ((index & 32) == 0) {
- break;
+ return VLQResult{
+ .start = i + start,
+ .value = if ((vlq & 1) == 0)
+ @intCast(i32, vlq >> 1)
+ else
+ -@intCast(i32, (vlq >> 1)),
+ };
}
}
- var value = vlq >> 1;
- if ((vlq & 1) != 0) {
- value = -value;
- }
-
- return VLQResult{ .start = i, .value = value };
+ return VLQResult{ .start = start + encoded_.len, .value = 0 };
}
pub const LineOffsetTable = struct {
@@ -473,6 +530,9 @@ pub fn appendSourceMappingURLRemote(
try writer.writeAll(strings.withoutTrailingSlash(origin.href));
if (asset_prefix_path.len > 0)
try writer.writeAll(asset_prefix_path);
+ if (source.path.pretty.len > 0 and source.path.pretty[0] != '/') {
+ try writer.writeAll("/");
+ }
try writer.writeAll(source.path.pretty);
try writer.writeAll(".map");
}
@@ -483,13 +543,13 @@ pub fn appendMappingToBuffer(buffer_: MutableString, last_byte: u8, prev_state:
const vlq = [_]VLQ{
// Record the generated column (the line is recorded using ';' elsewhere)
- encodeVLQ(current_state.generated_column - prev_state.generated_column),
+ encodeVLQWithLookupTable(current_state.generated_column - prev_state.generated_column),
// Record the generated source
- encodeVLQ(current_state.source_index - prev_state.source_index),
+ encodeVLQWithLookupTable(current_state.source_index - prev_state.source_index),
// Record the original line
- encodeVLQ(current_state.original_line - prev_state.original_line),
+ encodeVLQWithLookupTable(current_state.original_line - prev_state.original_line),
// Record the original column
- encodeVLQ(current_state.original_column - prev_state.original_column),
+ encodeVLQWithLookupTable(current_state.original_column - prev_state.original_column),
};
// Count exactly how many bytes we need to write
@@ -687,7 +747,8 @@ pub const Chunk = struct {
}
pub fn addSourceMapping(b: *Builder, loc: Logger.Loc, output: []const u8) void {
- if (b.prev_loc.eql(loc)) {
+ // exclude generated code from source
+ if (b.prev_loc.eql(loc) or loc.start == Logger.Loc.Empty.start) {
return;
}
@@ -699,7 +760,7 @@ pub const Chunk = struct {
// Use the line to compute the column
var original_column = loc.start - @intCast(i32, line.byte_offset_to_start_of_line);
if (line.columns_for_non_ascii.len > 0 and original_column >= @intCast(i32, line.byte_offset_to_first_non_ascii)) {
- original_column = line.columns_for_non_ascii.slice()[@intCast(u32, original_column) - line.byte_offset_to_first_non_ascii];
+ original_column = line.columns_for_non_ascii.ptr[@intCast(u32, original_column) - line.byte_offset_to_first_non_ascii];
}
b.updateGeneratedLineAndColumn(output);