Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve Bun.stringWidth's algorithm #9022

Merged
merged 17 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,4 @@ url = https://github.com/litespeedtech/ls-hpack.git
ignore = dirty
depth = 1
shallow = true
fetchRecurseSubmodules = false
fetchRecurseSubmodules = false
11 changes: 11 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,11 @@ endif()
set(ERROR_LIMIT 100 CACHE STRING "Maximum number of errors to show when compiling C++ code")

set(ARCH x86_64)
set(HOMEBREW_PREFIX "/usr/local")

if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|arm")
set(ARCH aarch64)
set(HOMEBREW_PREFIX "/opt/homebrew")
endif()

if(NOT CPU_TARGET)
Expand Down Expand Up @@ -463,6 +465,11 @@ if(NOT WEBKIT_DIR)
endif()

set(WEBKIT_INCLUDE_DIR "${BUN_WORKDIR}/bun-webkit/include")
if(APPLE)
set(ICU_INCLUDE_DIR "${HOMEBREW_PREFIX}/opt/icu4c/include")
else()
set(ICU_INCLUDE_DIR "${BUN_WORKDIR}/bun-webkit/include/wtf/unicode")
endif()
set(WEBKIT_LIB_DIR "${BUN_WORKDIR}/bun-webkit/lib")
elseif(WEBKIT_DIR STREQUAL "omit")
message(STATUS "Not using WebKit. This is only valid if you are only trying to build Zig code")
Expand Down Expand Up @@ -879,6 +886,10 @@ else()
add_compile_definitions("ASSERT_ENABLED=1")
endif()

if (ICU_INCLUDE_DIR)
include_directories(${ICU_INCLUDE_DIR})
endif()

include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/packages/
${CMAKE_CURRENT_SOURCE_DIR}/packages/bun-usockets
Expand Down
8 changes: 8 additions & 0 deletions packages/bun-types/bun.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ declare module "bun" {
*/
function which(command: string, options?: { PATH?: string; cwd?: string }): string | null;

function stringWidth(
input: string,
options?: {
countAnsiEscapeCodes?: boolean;
ambiguousIsNarrow?: boolean;
},
): number;

export type ShellFunction = (input: Uint8Array) => Uint8Array;

export type ShellExpression =
Expand Down
8 changes: 4 additions & 4 deletions src/bun.js/ConsoleObject.zig
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ const TablePrinter = struct {
fn updateColumnsForRow(this: *TablePrinter, columns: *std.ArrayList(Column), row_key: RowKey, row_value: JSValue) !void {
// update size of "(index)" column
const row_key_len: u32 = switch (row_key) {
.str => |value| @intCast(value.visibleWidthExcludeANSIColors()),
.str => |value| @intCast(value.visibleWidthExcludeANSIColors(false)),
.num => |value| @truncate(bun.fmt.fastDigitCount(value)),
};
columns.items[0].width = @max(columns.items[0].width, row_key_len);
Expand Down Expand Up @@ -400,7 +400,7 @@ const TablePrinter = struct {
try writer.writeAll("│");
{
const len: u32 = switch (row_key) {
.str => |value| @truncate(value.visibleWidthExcludeANSIColors()),
.str => |value| @truncate(value.visibleWidthExcludeANSIColors(false)),
.num => |value| @truncate(bun.fmt.fastDigitCount(value)),
};
const needed = columns.items[0].width -| len;
Expand Down Expand Up @@ -544,7 +544,7 @@ const TablePrinter = struct {
{
for (columns.items) |*col| {
// also update the col width with the length of the column name itself
col.width = @max(col.width, @as(u32, @intCast(col.name.visibleWidthExcludeANSIColors())));
col.width = @max(col.width, @as(u32, @intCast(col.name.visibleWidthExcludeANSIColors(false))));
}

try writer.writeAll("┌");
Expand All @@ -557,7 +557,7 @@ const TablePrinter = struct {

for (columns.items, 0..) |col, i| {
if (i > 0) try writer.writeAll("│");
const len = col.name.visibleWidthExcludeANSIColors();
const len = col.name.visibleWidthExcludeANSIColors(false);
const needed = col.width -| len;
try writer.writeByteNTimes(' ', 1);
if (comptime enable_ansi_colors) {
Expand Down
9 changes: 7 additions & 2 deletions src/bun.js/api/BunObject.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5163,19 +5163,24 @@ fn stringWidth(globalObject: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) cal
defer str.deref();

var count_ansi_escapes = false;
var ambiguous_as_wide = false;

if (options_object.isObject()) {
if (options_object.getTruthy(globalObject, "countAnsiEscapeCodes")) |count_ansi_escapes_value| {
if (count_ansi_escapes_value.isBoolean())
count_ansi_escapes = count_ansi_escapes_value.toBoolean();
}
if (options_object.getTruthy(globalObject, "ambiguousIsNarrow")) |ambiguous_is_narrow| {
if (ambiguous_is_narrow.isBoolean())
ambiguous_as_wide = !ambiguous_is_narrow.toBoolean();
}
}

if (count_ansi_escapes) {
return JSC.jsNumber(str.visibleWidth());
return JSC.jsNumber(str.visibleWidth(ambiguous_as_wide));
}

return JSC.jsNumber(str.visibleWidthExcludeANSIColors());
return JSC.jsNumber(str.visibleWidthExcludeANSIColors(ambiguous_as_wide));
}

/// EnvironmentVariables is runtime defined.
Expand Down
1 change: 1 addition & 0 deletions src/bun.js/bindings/BunObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,7 @@ JSC_DEFINE_HOST_FUNCTION(functionHashCode,
stdin BunObject_getter_wrap_stdin DontDelete|PropertyCallback
stdout BunObject_getter_wrap_stdout DontDelete|PropertyCallback
stringHashCode functionHashCode DontDelete|Function 1
stringWidth BunObject_callback_stringWidth DontDelete|Function 2
unsafe BunObject_getter_wrap_unsafe DontDelete|PropertyCallback
version constructBunVersion ReadOnly|DontDelete|PropertyCallback
which BunObject_callback_which DontDelete|Function 1
Expand Down
12 changes: 9 additions & 3 deletions src/bun.js/bindings/workaround-missing-symbols.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@

#if defined(WIN32)


#include <cstdint>
#include <algorithm>
#include <sys/stat.h>
Expand All @@ -14,7 +13,7 @@
#undef _environ
#undef environ

// Some libraries need these symbols. Windows makes it
// Some libraries need these symbols. Windows makes it
extern "C" char** environ = nullptr;
extern "C" char** _environ = nullptr;

Expand Down Expand Up @@ -76,7 +75,7 @@ extern "C" char* mkdtemp(char* template_name)
{
uv_fs_t req;
int status_code = uv_fs_mkdtemp(uv_default_loop(), &req, template_name, nullptr);

if (status_code < 0)
return nullptr;
size_t outlen = std::min(strlen(req.path), strlen(template_name));
Expand Down Expand Up @@ -369,3 +368,10 @@ extern "C" int __ulock_wait2(uint32_t operation, void* addr, uint64_t value,
}

#endif

#include <unicode/uchar.h>

extern "C" bool icu_hasBinaryProperty(UChar32 cp, unsigned int prop)
{
return u_hasBinaryProperty(cp, static_cast<UProperty>(prop));
}
2 changes: 1 addition & 1 deletion src/bun.js/webcore/encoding.zig
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ pub const TextDecoder = struct {
while (remainder.len > 0) {
switch (remainder[0]) {
0...127 => {
const count: usize = if (strings.firstNonASCII16CheckMin(Slice, remainder, false)) |index| index + 1 else remainder.len;
const count: usize = if (strings.firstNonASCII16IgnoreMin(Slice, remainder)) |index| index + 1 else remainder.len;

buffer.ensureUnusedCapacity(allocator, count) catch unreachable;

Expand Down
Loading
Loading