mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 18:38:55 +00:00
fix(install): incremental support for windows (#7991)
* update for windows * use correct sizes * mode * fchmod and correct error checking * some progress * walker_skippable.zig for windows * no segfault * comptime only * normalize * create files in .bin * bun.sys.write * string formatters in bun.fmt, diriterator enum * isAllASCII comptime * update more * some cleanup * fix 1 * fix 2 * simlink * cast * remove normalize * to zig err * update fchmod * fixup * fix running bin files * --bun for running binaries * --bun for scripts * remove binary linking * update * remove todo * todos * fix * simlink * cast * more cast
This commit is contained in:
@@ -25,6 +25,7 @@ pub inline fn contains(self: string, str: string) bool {
|
||||
}
|
||||
|
||||
pub fn w(comptime str: []const u8) [:0]const u16 {
|
||||
if (!@inComptime()) @compileError("strings.w() must be called in a comptime context");
|
||||
comptime var output: [str.len + 1]u16 = undefined;
|
||||
|
||||
for (str, 0..) |c, i| {
|
||||
@@ -206,78 +207,6 @@ pub fn indexOfCharNeg(self: string, char: u8) i32 {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/// Format a string to an ECMAScript identifier.
|
||||
/// Unlike the string_mutable.zig version, this always allocate/copy
|
||||
pub fn fmtIdentifier(name: string) FormatValidIdentifier {
|
||||
return FormatValidIdentifier{ .name = name };
|
||||
}
|
||||
|
||||
/// Format a string to an ECMAScript identifier.
|
||||
/// Different implementation than string_mutable because string_mutable may avoid allocating
|
||||
/// This will always allocate
|
||||
pub const FormatValidIdentifier = struct {
|
||||
name: string,
|
||||
pub fn format(self: FormatValidIdentifier, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
|
||||
var iterator = strings.CodepointIterator.init(self.name);
|
||||
var cursor = strings.CodepointIterator.Cursor{};
|
||||
|
||||
var has_needed_gap = false;
|
||||
var needs_gap = false;
|
||||
var start_i: usize = 0;
|
||||
|
||||
if (!iterator.next(&cursor)) {
|
||||
try writer.writeAll("_");
|
||||
return;
|
||||
}
|
||||
|
||||
// Common case: no gap necessary. No allocation necessary.
|
||||
needs_gap = !js_lexer.isIdentifierStart(cursor.c);
|
||||
if (!needs_gap) {
|
||||
// Are there any non-alphanumeric chars at all?
|
||||
while (iterator.next(&cursor)) {
|
||||
if (!js_lexer.isIdentifierContinue(cursor.c) or cursor.width > 1) {
|
||||
needs_gap = true;
|
||||
start_i = cursor.i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_gap) {
|
||||
needs_gap = false;
|
||||
if (start_i > 0) try writer.writeAll(self.name[0..start_i]);
|
||||
var slice = self.name[start_i..];
|
||||
iterator = strings.CodepointIterator.init(slice);
|
||||
cursor = strings.CodepointIterator.Cursor{};
|
||||
|
||||
while (iterator.next(&cursor)) {
|
||||
if (js_lexer.isIdentifierContinue(cursor.c) and cursor.width == 1) {
|
||||
if (needs_gap) {
|
||||
try writer.writeAll("_");
|
||||
needs_gap = false;
|
||||
has_needed_gap = true;
|
||||
}
|
||||
try writer.writeAll(slice[cursor.i .. cursor.i + @as(u32, cursor.width)]);
|
||||
} else if (!needs_gap) {
|
||||
needs_gap = true;
|
||||
// skip the code point, replace it with a single _
|
||||
}
|
||||
}
|
||||
|
||||
// If it ends with an emoji
|
||||
if (needs_gap) {
|
||||
try writer.writeAll("_");
|
||||
needs_gap = false;
|
||||
has_needed_gap = true;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try writer.writeAll(self.name);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn indexOfSigned(self: string, str: string) i32 {
|
||||
const i = std.mem.indexOf(u8, self, str) orelse return -1;
|
||||
return @as(i32, @intCast(i));
|
||||
@@ -768,82 +697,6 @@ pub fn endsWithAny(self: string, str: string) bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Formats a string to be safe to output in a Github action.
|
||||
// - Encodes "\n" as "%0A" to support multi-line strings.
|
||||
// https://github.com/actions/toolkit/issues/193#issuecomment-605394935
|
||||
// - Strips ANSI output as it will appear malformed.
|
||||
pub fn githubActionWriter(writer: anytype, self: string) !void {
|
||||
var offset: usize = 0;
|
||||
const end = @as(u32, @truncate(self.len));
|
||||
while (offset < end) {
|
||||
if (indexOfNewlineOrNonASCIIOrANSI(self, @as(u32, @truncate(offset)))) |i| {
|
||||
const byte = self[i];
|
||||
if (byte > 0x7F) {
|
||||
offset += @max(wtf8ByteSequenceLength(byte), 1);
|
||||
continue;
|
||||
}
|
||||
if (i > 0) {
|
||||
try writer.writeAll(self[offset..i]);
|
||||
}
|
||||
var n: usize = 1;
|
||||
if (byte == '\n') {
|
||||
try writer.writeAll("%0A");
|
||||
} else if (i + 1 < end) {
|
||||
const next = self[i + 1];
|
||||
if (byte == '\r' and next == '\n') {
|
||||
n += 1;
|
||||
try writer.writeAll("%0A");
|
||||
} else if (byte == '\x1b' and next == '[') {
|
||||
n += 1;
|
||||
if (i + 2 < end) {
|
||||
const remain = self[(i + 2)..@min(i + 5, end)];
|
||||
if (indexOfChar(remain, 'm')) |j| {
|
||||
n += j + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
offset = i + n;
|
||||
} else {
|
||||
try writer.writeAll(self[offset..end]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const GithubActionFormatter = struct {
|
||||
text: string,
|
||||
|
||||
pub fn format(this: GithubActionFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
|
||||
try githubActionWriter(writer, this.text);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn githubAction(self: string) strings.GithubActionFormatter {
|
||||
return GithubActionFormatter{
|
||||
.text = self,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn quotedWriter(writer: anytype, self: string) !void {
|
||||
const remain = self;
|
||||
if (strings.containsNewlineOrNonASCIIOrQuote(remain)) {
|
||||
try bun.js_printer.writeJSONString(self, @TypeOf(writer), writer, strings.Encoding.utf8);
|
||||
} else {
|
||||
try writer.writeAll("\"");
|
||||
try writer.writeAll(self);
|
||||
try writer.writeAll("\"");
|
||||
}
|
||||
}
|
||||
|
||||
pub const QuotedFormatter = struct {
|
||||
text: []const u8,
|
||||
|
||||
pub fn format(this: QuotedFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
|
||||
try strings.quotedWriter(writer, this.text);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn quotedAlloc(allocator: std.mem.Allocator, self: string) !string {
|
||||
var count: usize = 0;
|
||||
for (self) |char| {
|
||||
@@ -3446,6 +3299,15 @@ pub fn isValidUTF8(slice: []const u8) bool {
|
||||
}
|
||||
|
||||
pub fn isAllASCII(slice: []const u8) bool {
|
||||
if (@inComptime()) {
|
||||
for (slice) |char| {
|
||||
if (char > 127) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (bun.FeatureFlags.use_simdutf)
|
||||
return bun.simdutf.validate.ascii(slice);
|
||||
|
||||
@@ -3486,15 +3348,6 @@ pub fn isAllASCII(slice: []const u8) bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn isAllASCIISimple(comptime slice: []const u8) bool {
|
||||
for (slice) |char| {
|
||||
if (char > 127) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//#define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0)
|
||||
pub inline fn u16Lead(supplementary: anytype) u16 {
|
||||
return @as(u16, @intCast((supplementary >> 10) + 0xd7c0));
|
||||
@@ -4418,106 +4271,10 @@ test "firstNonASCII16" {
|
||||
}
|
||||
}
|
||||
|
||||
const SharedTempBuffer = [32 * 1024]u8;
|
||||
fn getSharedBuffer() []u8 {
|
||||
return std.mem.asBytes(shared_temp_buffer_ptr orelse brk: {
|
||||
shared_temp_buffer_ptr = bun.default_allocator.create(SharedTempBuffer) catch unreachable;
|
||||
break :brk shared_temp_buffer_ptr.?;
|
||||
});
|
||||
}
|
||||
threadlocal var shared_temp_buffer_ptr: ?*SharedTempBuffer = null;
|
||||
|
||||
pub fn formatUTF16Type(comptime Slice: type, slice_: Slice, writer: anytype) !void {
|
||||
var chunk = getSharedBuffer();
|
||||
|
||||
// Defensively ensure recursion doesn't cause the buffer to be overwritten in-place
|
||||
shared_temp_buffer_ptr = null;
|
||||
defer {
|
||||
if (shared_temp_buffer_ptr) |existing| {
|
||||
if (existing != chunk.ptr) {
|
||||
bun.default_allocator.destroy(@as(*SharedTempBuffer, @ptrCast(chunk.ptr)));
|
||||
}
|
||||
} else {
|
||||
shared_temp_buffer_ptr = @ptrCast(chunk.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
var slice = slice_;
|
||||
|
||||
while (slice.len > 0) {
|
||||
const result = strings.copyUTF16IntoUTF8(chunk, Slice, slice, true);
|
||||
if (result.read == 0 or result.written == 0)
|
||||
break;
|
||||
try writer.writeAll(chunk[0..result.written]);
|
||||
slice = slice[result.read..];
|
||||
}
|
||||
}
|
||||
|
||||
pub fn formatUTF16(slice_: []align(1) const u16, writer: anytype) !void {
|
||||
return formatUTF16Type([]align(1) const u16, slice_, writer);
|
||||
}
|
||||
|
||||
pub const FormatUTF16 = struct {
|
||||
buf: []const u16,
|
||||
pub fn format(self: @This(), comptime _: []const u8, opts: anytype, writer: anytype) !void {
|
||||
_ = opts;
|
||||
try formatUTF16Type([]const u16, self.buf, writer);
|
||||
}
|
||||
};
|
||||
|
||||
pub const FormatUTF8 = struct {
|
||||
buf: []const u8,
|
||||
pub fn format(self: @This(), comptime _: []const u8, _: anytype, writer: anytype) !void {
|
||||
try writer.writeAll(self.buf);
|
||||
}
|
||||
};
|
||||
|
||||
pub fn fmtUTF16(buf: []const u16) FormatUTF16 {
|
||||
return FormatUTF16{ .buf = buf };
|
||||
}
|
||||
|
||||
pub const FormatOSPath = if (Environment.isWindows) FormatUTF16 else FormatUTF8;
|
||||
|
||||
pub fn fmtOSPath(buf: bun.OSPathSliceWithoutSentinel) FormatOSPath {
|
||||
return FormatOSPath{ .buf = buf };
|
||||
}
|
||||
|
||||
pub fn formatLatin1(slice_: []const u8, writer: anytype) !void {
|
||||
var chunk = getSharedBuffer();
|
||||
var slice = slice_;
|
||||
|
||||
// Defensively ensure recursion doesn't cause the buffer to be overwritten in-place
|
||||
shared_temp_buffer_ptr = null;
|
||||
defer {
|
||||
if (shared_temp_buffer_ptr) |existing| {
|
||||
if (existing != chunk.ptr) {
|
||||
bun.default_allocator.destroy(@as(*SharedTempBuffer, @ptrCast(chunk.ptr)));
|
||||
}
|
||||
} else {
|
||||
shared_temp_buffer_ptr = @ptrCast(chunk.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
while (strings.firstNonASCII(slice)) |i| {
|
||||
if (i > 0) {
|
||||
try writer.writeAll(slice[0..i]);
|
||||
slice = slice[i..];
|
||||
}
|
||||
const result = strings.copyLatin1IntoUTF8(chunk, @TypeOf(slice), slice[0..@min(chunk.len, slice.len)]);
|
||||
if (result.read == 0 or result.written == 0)
|
||||
break;
|
||||
try writer.writeAll(chunk[0..result.written]);
|
||||
slice = slice[result.read..];
|
||||
}
|
||||
|
||||
if (slice.len > 0)
|
||||
try writer.writeAll(slice); // write the remaining bytes
|
||||
}
|
||||
|
||||
test "print UTF16" {
|
||||
var err = std.io.getStdErr();
|
||||
const utf16 = comptime toUTF16Literal("❌ ✅ opkay ");
|
||||
try formatUTF16(utf16, err.writer());
|
||||
try bun.fmt.str.formatUTF16(utf16, err.writer());
|
||||
// std.unicode.fmtUtf16le(utf16le: []const u16)
|
||||
}
|
||||
|
||||
@@ -5362,71 +5119,6 @@ pub fn concatIfNeeded(
|
||||
std.debug.assert(remain.len == 0);
|
||||
}
|
||||
|
||||
pub const HostFormatter = struct {
|
||||
host: string,
|
||||
port: ?u16 = null,
|
||||
is_https: bool = false,
|
||||
|
||||
pub fn format(formatter: HostFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
|
||||
if (strings.indexOfChar(formatter.host, ':') != null) {
|
||||
try writer.writeAll(formatter.host);
|
||||
return;
|
||||
}
|
||||
|
||||
try writer.writeAll(formatter.host);
|
||||
|
||||
const is_port_optional = formatter.port == null or (formatter.is_https and formatter.port == 443) or
|
||||
(!formatter.is_https and formatter.port == 80);
|
||||
if (!is_port_optional) {
|
||||
try writer.print(":{d}", .{formatter.port.?});
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const Proto = enum {
|
||||
http,
|
||||
https,
|
||||
unix,
|
||||
};
|
||||
|
||||
pub const URLFormatter = struct {
|
||||
proto: Proto = .http,
|
||||
hostname: ?string = null,
|
||||
port: ?u16 = null,
|
||||
|
||||
pub fn format(this: URLFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
|
||||
try writer.print("{s}://", .{switch (this.proto) {
|
||||
.http => "http",
|
||||
.https => "https",
|
||||
.unix => "unix",
|
||||
}});
|
||||
|
||||
if (this.hostname) |hostname| {
|
||||
const needs_brackets = hostname[0] != '[' and strings.isIPV6Address(hostname);
|
||||
if (needs_brackets) {
|
||||
try writer.print("[{s}]", .{hostname});
|
||||
} else {
|
||||
try writer.writeAll(hostname);
|
||||
}
|
||||
} else {
|
||||
try writer.writeAll("localhost");
|
||||
}
|
||||
|
||||
if (this.proto == .unix) {
|
||||
return;
|
||||
}
|
||||
|
||||
const is_port_optional = this.port == null or (this.proto == .https and this.port == 443) or
|
||||
(this.proto == .http and this.port == 80);
|
||||
if (is_port_optional) {
|
||||
try writer.writeAll("/");
|
||||
} else {
|
||||
try writer.print(":{d}/", .{this.port.?});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub fn convertUTF8toUTF16InBuffer(
|
||||
buf: []u16,
|
||||
input: []const u8,
|
||||
|
||||
Reference in New Issue
Block a user