From a732999da578ca92a1d9e633036225a32e77529d Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Mon, 26 Jun 2023 12:49:20 -0700 Subject: Runtime support for `__esModule` annotations (#3393) * Runtime support for `__esModule` annotations * Ignore `__esModule` annotation when `"type": "module"` is set --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> --- src/bun.js/bindings/headers-handwritten.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/bun.js/bindings/headers-handwritten.h') diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h index 57940550f..db1e38d3e 100644 --- a/src/bun.js/bindings/headers-handwritten.h +++ b/src/bun.js/bindings/headers-handwritten.h @@ -72,6 +72,7 @@ typedef struct ResolvedSource { void* allocator; uint64_t tag; } ResolvedSource; +static const uint64_t ResolvedSourceTagPackageJSONTypeModule = 1; typedef union ErrorableResolvedSourceResult { ResolvedSource value; ZigErrorType err; -- cgit v1.2.3 From 68e6fe00a4be7857f474cb3aa80e0d876499e3f8 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Wed, 28 Jun 2023 21:11:06 -0700 Subject: Use `bun.String` for `ZigException` (#3451) * Use `bun.String` for `ZigException` * woopsie --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> --- src/bun.js/bindings/ZigGlobalObject.cpp | 4 +- src/bun.js/bindings/bindings.cpp | 69 +++++----------- src/bun.js/bindings/exports.zig | 130 ++++++++++++++++++++---------- src/bun.js/bindings/headers-handwritten.h | 16 ++-- src/bun.js/javascript.zig | 72 ++++++++++------- src/bun.js/test/jest.zig | 18 ++--- src/js/out/modules/node/path.js | 2 +- src/js/out/modules/node/stream.web.js | 2 +- src/logger.zig | 4 +- src/string.zig | 24 ++++++ 10 files changed, 198 insertions(+), 143 deletions(-) (limited to 'src/bun.js/bindings/headers-handwritten.h') diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 4b4edf097..9ff3ebf93 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -390,7 +390,7 @@ static String computeErrorInfoWithoutPrepareStackTrace(JSC::VM& vm, Vectorline.zeroBasedInt(); remappedFrames[i].position.column_start = sourcePositions->startColumn.zeroBasedInt() + 1; diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 68aef29dd..141215ebe 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -3303,7 +3303,7 @@ bool JSC__JSValue__stringIncludes(JSC__JSValue value, JSC__JSGlobalObject* globa static void populateStackFrameMetadata(JSC::VM& vm, const JSC::StackFrame* stackFrame, ZigStackFrame* frame) { - frame->source_url = Zig::toZigString(stackFrame->sourceURL(vm)); + frame->source_url = Bun::toString(stackFrame->sourceURL(vm)); if (stackFrame->isWasmFrame()) { frame->code_type = ZigStackFrameCodeWasm; @@ -3340,37 +3340,11 @@ static void populateStackFrameMetadata(JSC::VM& vm, const JSC::StackFrame* stack JSC::JSObject* callee = JSC::jsCast(calleeCell); - // Does the code block have a user-defined name property? - JSC::JSValue name = callee->getDirect(vm, vm.propertyNames->name); - if (name && name.isString()) { - auto str = name.toWTFString(m_codeBlock->globalObject()); - frame->function_name = Zig::toZigString(str); - return; - } - - /* For functions (either JSFunction or InternalFunction), fallback to their "native" name - * property. Based on JSC::getCalculatedDisplayName, "inlining" the - * JSFunction::calculatedDisplayName\InternalFunction::calculatedDisplayName calls */ - if (JSC::JSFunction* function = JSC::jsDynamicCast(callee)) { - - WTF::String actualName = function->name(vm); - if (!actualName.isEmpty() || function->isHostOrBuiltinFunction()) { - frame->function_name = Zig::toZigString(actualName); - return; - } - - auto inferred_name = function->jsExecutable()->name(); - frame->function_name = Zig::toZigString(inferred_name.string()); - } - - if (JSC::InternalFunction* function = JSC::jsDynamicCast(callee)) { - // Based on JSC::InternalFunction::calculatedDisplayName, skipping the "displayName" property - frame->function_name = Zig::toZigString(function->name()); - } + frame->function_name = Bun::toString(JSC::getCalculatedDisplayName(vm, callee)); } // Based on // https://github.com/mceSystems/node-jsc/blob/master/deps/jscshim/src/shim/JSCStackTrace.cpp#L298 -static void populateStackFramePosition(const JSC::StackFrame* stackFrame, ZigString* source_lines, +static void populateStackFramePosition(const JSC::StackFrame* stackFrame, BunString* source_lines, int32_t* source_line_numbers, uint8_t source_lines_count, ZigStackFramePosition* position) { @@ -3440,7 +3414,7 @@ static void populateStackFramePosition(const JSC::StackFrame* stackFrame, ZigStr // Most of the time, when you look at a stack trace, you want a couple lines above - source_lines[0] = { &chars[lineStart], lineStop - lineStart }; + source_lines[0] = Bun::toString(sourceString.substring(lineStart, lineStop - lineStart).toStringWithoutCopying()); source_line_numbers[0] = line; if (lineStart > 0) { @@ -3457,8 +3431,7 @@ static void populateStackFramePosition(const JSC::StackFrame* stackFrame, ZigStr } // We are at the beginning of the line - source_lines[source_line_i] = { &chars[byte_offset_in_source_string], - end_of_line_offset - byte_offset_in_source_string + 1 }; + source_lines[source_line_i] = Bun::toString(sourceString.substring(byte_offset_in_source_string, end_of_line_offset - byte_offset_in_source_string + 1).toStringWithoutCopying()); source_line_numbers[source_line_i] = line - source_line_i; source_line_i++; @@ -3546,30 +3519,30 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, except->code = 8; } if (except->code == SYNTAX_ERROR_CODE) { - except->message = Zig::toZigString(err->sanitizedMessageString(global)); + except->message = Bun::toString(err->sanitizedMessageString(global)); } else if (JSC::JSValue message = obj->getIfPropertyExists(global, vm.propertyNames->message)) { - except->message = Zig::toZigString(message, global); + except->message = Bun::toString(global, message); } else { - except->message = Zig::toZigString(err->sanitizedMessageString(global)); + except->message = Bun::toString(err->sanitizedMessageString(global)); } - except->name = Zig::toZigString(err->sanitizedNameString(global)); + except->name = Bun::toString(err->sanitizedNameString(global)); except->runtime_type = err->runtimeTypeForCause(); auto clientData = WebCore::clientData(vm); if (except->code != SYNTAX_ERROR_CODE) { if (JSC::JSValue syscall = obj->getIfPropertyExists(global, clientData->builtinNames().syscallPublicName())) { - except->syscall = Zig::toZigString(syscall, global); + except->syscall = Bun::toString(global, syscall); } if (JSC::JSValue code = obj->getIfPropertyExists(global, clientData->builtinNames().codePublicName())) { - except->code_ = Zig::toZigString(code, global); + except->code_ = Bun::toString(global, code); } if (JSC::JSValue path = obj->getIfPropertyExists(global, clientData->builtinNames().pathPublicName())) { - except->path = Zig::toZigString(path, global); + except->path = Bun::toString(global, path); } if (JSC::JSValue fd = obj->getIfPropertyExists(global, Identifier::fromString(vm, "fd"_s))) { @@ -3585,7 +3558,7 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, if (getFromSourceURL) { if (JSC::JSValue sourceURL = obj->getIfPropertyExists(global, vm.propertyNames->sourceURL)) { - except->stack.frames_ptr[0].source_url = Zig::toZigString(sourceURL, global); + except->stack.frames_ptr[0].source_url = Bun::toString(global, sourceURL); if (JSC::JSValue column = obj->getIfPropertyExists(global, vm.propertyNames->column)) { except->stack.frames_ptr[0].position.column_start = column.toInt32(global); @@ -3597,7 +3570,7 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, if (JSC::JSValue lineText = obj->getIfPropertyExists(global, JSC::Identifier::fromString(vm, "lineText"_s))) { if (JSC::JSString* jsStr = lineText.toStringOrNull(global)) { auto str = jsStr->value(global); - except->stack.source_lines_ptr[0] = Zig::toZigString(str); + except->stack.source_lines_ptr[0] = Bun::toString(str); except->stack.source_lines_numbers[0] = except->stack.frames_ptr[0].position.line; except->stack.source_lines_len = 1; except->remapped = true; @@ -3620,7 +3593,7 @@ void exceptionFromString(ZigException* except, JSC::JSValue value, JSC::JSGlobal if (JSC::JSObject* obj = JSC::jsDynamicCast(value)) { if (obj->hasProperty(global, global->vm().propertyNames->name)) { auto name_str = obj->getIfPropertyExists(global, global->vm().propertyNames->name).toWTFString(global); - except->name = Zig::toZigString(name_str); + except->name = Bun::toString(name_str); if (name_str == "Error"_s) { except->code = JSErrorCodeError; } else if (name_str == "EvalError"_s) { @@ -3642,14 +3615,14 @@ void exceptionFromString(ZigException* except, JSC::JSValue value, JSC::JSGlobal if (JSC::JSValue message = obj->getIfPropertyExists(global, global->vm().propertyNames->message)) { if (message) { - except->message = Zig::toZigString( + except->message = Bun::toString( message.toWTFString(global)); } } if (JSC::JSValue sourceURL = obj->getIfPropertyExists(global, global->vm().propertyNames->sourceURL)) { if (sourceURL) { - except->stack.frames_ptr[0].source_url = Zig::toZigString( + except->stack.frames_ptr[0].source_url = Bun::toString( sourceURL.toWTFString(global)); except->stack.frames_len = 1; } @@ -3678,9 +3651,7 @@ void exceptionFromString(ZigException* except, JSC::JSValue value, JSC::JSGlobal } scope.release(); - auto ref = OpaqueJSString::tryCreate(str); - except->message = ZigString { ref->characters8(), ref->length() }; - ref->ref(); + except->message = Bun::toString(str); } void JSC__VM__releaseWeakRefs(JSC__VM* arg0) @@ -3790,8 +3761,8 @@ void JSC__JSValue__toZigException(JSC__JSValue JSValue0, JSC__JSGlobalObject* ar JSC::JSValue value = JSC::JSValue::decode(JSValue0); if (value == JSC::JSValue {}) { exception->code = JSErrorCodeError; - exception->name = Zig::toZigString("Error"_s); - exception->message = Zig::toZigString("Unknown error"_s); + exception->name = Bun::toString("Error"_s); + exception->message = Bun::toString("Unknown error"_s); return; } diff --git a/src/bun.js/bindings/exports.zig b/src/bun.js/bindings/exports.zig index 213291e7b..73a26e4be 100644 --- a/src/bun.js/bindings/exports.zig +++ b/src/bun.js/bindings/exports.zig @@ -29,6 +29,7 @@ const Backtrace = @import("../../crash_reporter.zig"); const JSPrinter = bun.js_printer; const JSLexer = bun.js_lexer; const typeBaseName = @import("../../meta.zig").typeBaseName; +const String = bun.String; pub const ZigGlobalObject = extern struct { pub const shim = Shimmer("Zig", "GlobalObject", @This()); @@ -438,7 +439,7 @@ pub const Process = extern struct { }; pub const ZigStackTrace = extern struct { - source_lines_ptr: [*c]ZigString, + source_lines_ptr: [*c]bun.String, source_lines_numbers: [*c]i32, source_lines_len: u8, source_lines_to_collect: u8, @@ -456,23 +457,24 @@ pub const ZigStackTrace = extern struct { { var source_lines_iter = this.sourceLineIterator(); - var source_line_len: usize = 0; - var count: usize = 0; - while (source_lines_iter.next()) |source| { - count += 1; - source_line_len += source.text.len; - } + var source_line_len = source_lines_iter.getLength(); - if (count > 0 and source_line_len > 0) { - var source_lines = try allocator.alloc(Api.SourceLine, count); + if (source_line_len > 0) { + var source_lines = try allocator.alloc(Api.SourceLine, @intCast(usize, @max(source_lines_iter.i, 0))); var source_line_buf = try allocator.alloc(u8, source_line_len); source_lines_iter = this.sourceLineIterator(); var remain_buf = source_line_buf[0..]; var i: usize = 0; while (source_lines_iter.next()) |source| { - bun.copy(u8, remain_buf, source.text); - const copied_line = remain_buf[0..source.text.len]; - remain_buf = remain_buf[source.text.len..]; + const text = source.text.slice(); + defer source.text.deinit(); + defer bun.copy( + u8, + remain_buf, + text, + ); + const copied_line = remain_buf[0..text.len]; + remain_buf = remain_buf[text.len..]; source_lines[i] = .{ .text = copied_line, .line = source.line }; i += 1; } @@ -508,9 +510,18 @@ pub const ZigStackTrace = extern struct { pub const SourceLine = struct { line: i32, - text: string, + text: ZigString.Slice, }; + pub fn getLength(this: *SourceLineIterator) usize { + var count: usize = 0; + for (this.trace.source_lines_ptr[0..@intCast(usize, this.i)]) |*line| { + count += line.length(); + } + + return count; + } + pub fn untilLast(this: *SourceLineIterator) ?SourceLine { if (this.i < 1) return null; return this.next(); @@ -522,7 +533,7 @@ pub const ZigStackTrace = extern struct { const source_line = this.trace.source_lines_ptr[@intCast(usize, this.i)]; const result = SourceLine{ .line = this.trace.source_lines_numbers[@intCast(usize, this.i)], - .text = source_line.slice(), + .text = source_line.toUTF8(bun.default_allocator), }; this.i -= 1; return result; @@ -541,21 +552,28 @@ pub const ZigStackTrace = extern struct { }; pub const ZigStackFrame = extern struct { - function_name: ZigString, - source_url: ZigString, + function_name: String, + source_url: String, position: ZigStackFramePosition, code_type: ZigStackFrameCode, /// This informs formatters whether to display as a blob URL or not remapped: bool = false, + pub fn deinit(this: *ZigStackFrame) void { + this.function_name.deref(); + this.source_url.deref(); + } + pub fn toAPI(this: *const ZigStackFrame, root_path: string, origin: ?*const ZigURL, allocator: std.mem.Allocator) !Api.StackFrame { var frame: Api.StackFrame = comptime std.mem.zeroes(Api.StackFrame); - if (this.function_name.len > 0) { - frame.function_name = try allocator.dupe(u8, this.function_name.slice()); + if (!this.function_name.isEmpty()) { + var slicer = this.function_name.toUTF8(allocator); + defer slicer.deinit(); + frame.function_name = (try slicer.clone(allocator)).slice(); } - if (this.source_url.len > 0) { + if (!this.source_url.isEmpty()) { frame.file = try std.fmt.allocPrint(allocator, "{any}", .{this.sourceURLFormatter(root_path, origin, true, false)}); } @@ -576,7 +594,7 @@ pub const ZigStackFrame = extern struct { } pub const SourceURLFormatter = struct { - source_url: ZigString, + source_url: bun.String, position: ZigStackFramePosition, enable_color: bool, origin: ?*const ZigURL, @@ -588,7 +606,9 @@ pub const ZigStackFrame = extern struct { try writer.writeAll(Output.prettyFmt("", true)); } - var source_slice = this.source_url.slice(); + var source_slice_ = this.source_url.toUTF8(bun.default_allocator); + var source_slice = source_slice_.slice(); + defer source_slice_.deinit(); if (!this.remapped) { if (this.origin) |origin| { @@ -647,12 +667,12 @@ pub const ZigStackFrame = extern struct { }; pub const NameFormatter = struct { - function_name: ZigString, + function_name: String, code_type: ZigStackFrameCode, enable_color: bool, pub fn format(this: NameFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void { - const name = this.function_name.slice(); + const name = this.function_name; switch (this.code_type) { .Eval => { @@ -662,26 +682,26 @@ pub const ZigStackFrame = extern struct { // try writer.writeAll("(esm)"); }, .Function => { - if (name.len > 0) { + if (!name.isEmpty()) { if (this.enable_color) { - try std.fmt.format(writer, comptime Output.prettyFmt("{s}", true), .{name}); + try std.fmt.format(writer, comptime Output.prettyFmt("{}", true), .{name}); } else { - try std.fmt.format(writer, "{s}", .{name}); + try std.fmt.format(writer, "{}", .{name}); } } }, .Global => { - if (name.len > 0) { - try std.fmt.format(writer, "globalThis {s}", .{name}); + if (!name.isEmpty()) { + try std.fmt.format(writer, "globalThis {}", .{name}); } else { try writer.writeAll("globalThis"); } }, .Wasm => { - try std.fmt.format(writer, "WASM {s}", .{name}); + try std.fmt.format(writer, "WASM {}", .{name}); }, .Constructor => { - try std.fmt.format(writer, "new {s}", .{name}); + try std.fmt.format(writer, "new {}", .{name}); }, else => {}, } @@ -689,9 +709,9 @@ pub const ZigStackFrame = extern struct { }; pub const Zero: ZigStackFrame = ZigStackFrame{ - .function_name = ZigString{ ._unsafe_ptr_do_not_use = "", .len = 0 }, + .function_name = String.empty, .code_type = ZigStackFrameCode.None, - .source_url = ZigString{ ._unsafe_ptr_do_not_use = "", .len = 0 }, + .source_url = String.empty, .position = ZigStackFramePosition.Invalid, }; @@ -744,14 +764,14 @@ pub const ZigException = extern struct { /// SystemError only errno: c_int = 0, /// SystemError only - syscall: ZigString = ZigString.Empty, + syscall: String = String.empty, /// SystemError only - system_code: ZigString = ZigString.Empty, + system_code: String = String.empty, /// SystemError only - path: ZigString = ZigString.Empty, + path: String = String.empty, - name: ZigString, - message: ZigString, + name: String, + message: String, stack: ZigStackTrace, exception: ?*anyopaque, @@ -760,6 +780,19 @@ pub const ZigException = extern struct { fd: i32 = -1, + pub fn deinit(this: *ZigException) void { + this.syscall.deref(); + this.system_code.deref(); + this.path.deref(); + + this.name.deref(); + this.message.deref(); + + for (this.stack.frames_ptr[0..this.stack.frames_len]) |*frame| { + frame.deinit(); + } + } + pub const shim = Shimmer("Zig", "Exception", @This()); pub const name = "ZigException"; pub const namespace = shim.namespace; @@ -768,7 +801,7 @@ pub const ZigException = extern struct { const frame_count = 32; pub const source_lines_count = 6; source_line_numbers: [source_lines_count]i32, - source_lines: [source_lines_count]ZigString, + source_lines: [source_lines_count]String, frames: [frame_count]ZigStackFrame, loaded: bool, zig_exception: ZigException, @@ -786,8 +819,8 @@ pub const ZigException = extern struct { }, .source_lines = brk: { - var lines: [source_lines_count]ZigString = undefined; - @memset(&lines, ZigString.Empty); + var lines: [source_lines_count]String = undefined; + @memset(&lines, String.empty); break :brk lines; }, .zig_exception = undefined, @@ -798,13 +831,17 @@ pub const ZigException = extern struct { return Holder.Zero; } + pub fn deinit(this: *Holder) void { + this.zigException().deinit(); + } + pub fn zigException(this: *Holder) *ZigException { if (!this.loaded) { this.zig_exception = ZigException{ .code = @enumFromInt(JSErrorCode, 255), .runtime_type = JSRuntimeType.Nothing, - .name = ZigString.Empty, - .message = ZigString.Empty, + .name = String.empty, + .message = String.empty, .exception = null, .stack = ZigStackTrace{ .source_lines_ptr = &this.source_lines, @@ -832,8 +869,13 @@ pub const ZigException = extern struct { root_path: string, origin: ?*const ZigURL, ) !void { - const _name: string = @field(this, "name").slice(); - const message: string = @field(this, "message").slice(); + const name_slice = @field(this, "name").toUTF8(bun.default_allocator); + const message_slice = @field(this, "message").toUTF8(bun.default_allocator); + + const _name = name_slice.slice(); + defer name_slice.deinit(); + const message = message_slice.slice(); + defer message_slice.deinit(); var is_empty = true; var api_exception = Api.JsException{ diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h index db1e38d3e..c7429b633 100644 --- a/src/bun.js/bindings/headers-handwritten.h +++ b/src/bun.js/bindings/headers-handwritten.h @@ -120,15 +120,15 @@ typedef struct ZigStackFramePosition { } ZigStackFramePosition; typedef struct ZigStackFrame { - ZigString function_name; - ZigString source_url; + BunString function_name; + BunString source_url; ZigStackFramePosition position; ZigStackFrameCode code_type; bool remapped; } ZigStackFrame; typedef struct ZigStackTrace { - ZigString* source_lines_ptr; + BunString* source_lines_ptr; int32_t* source_lines_numbers; uint8_t source_lines_len; uint8_t source_lines_to_collect; @@ -140,11 +140,11 @@ typedef struct ZigException { unsigned char code; uint16_t runtime_type; int errno_; - ZigString syscall; - ZigString code_; - ZigString path; - ZigString name; - ZigString message; + BunString syscall; + BunString code_; + BunString path; + BunString name; + BunString message; ZigStackTrace stack; void* exception; bool remapped; diff --git a/src/bun.js/javascript.zig b/src/bun.js/javascript.zig index cf6a65841..605cc0c25 100644 --- a/src/bun.js/javascript.zig +++ b/src/bun.js/javascript.zig @@ -1805,6 +1805,7 @@ pub const VirtualMachine = struct { if (exception) |exception_| { var holder = ZigException.Holder.init(); var zig_exception: *ZigException = holder.zigException(); + defer zig_exception.deinit(); exception_.getStackTrace(&zig_exception.stack); if (zig_exception.stack.frames_len > 0) { if (allow_ansi_color) { @@ -1932,8 +1933,14 @@ pub const VirtualMachine = struct { while (i < stack.len) : (i += 1) { const frame = stack[@intCast(usize, i)]; - const file = frame.source_url.slice(); - const func = frame.function_name.slice(); + const file_slice = frame.source_url.toSlice(bun.default_allocator); + defer file_slice.deinit(); + const func_slice = frame.function_name.toSlice(bun.default_allocator); + defer func_slice.deinit(); + + const file = file_slice.slice(); + const func = func_slice.slice(); + if (file.len == 0 and func.len == 0) continue; const has_name = std.fmt.count("{any}", .{frame.nameFormatter( @@ -1985,7 +1992,7 @@ pub const VirtualMachine = struct { pub fn remapStackFramePositions(this: *VirtualMachine, frames: [*]JSC.ZigStackFrame, frames_count: usize) void { for (frames[0..frames_count]) |*frame| { if (frame.position.isInvalid() or frame.remapped) continue; - var sourceURL = frame.source_url.toSlice(bun.default_allocator); + var sourceURL = frame.source_url.toUTF8(bun.default_allocator); defer sourceURL.deinit(); if (this.source_mappings.resolveMapping( @@ -2049,8 +2056,10 @@ pub const VirtualMachine = struct { if (frames.len == 0) return; var top = &frames[0]; + var top_source_url = top.source_url.toUTF8(bun.default_allocator); + defer top_source_url.deinit(); if (this.source_mappings.resolveMapping( - top.source_url.slice(), + top_source_url.slice(), @max(top.position.line, 0), @max(top.position.column_start, 0), )) |mapping| { @@ -2078,18 +2087,18 @@ pub const VirtualMachine = struct { )) |lines| { var source_lines = exception.stack.source_lines_ptr[0..JSC.ZigException.Holder.source_lines_count]; var source_line_numbers = exception.stack.source_lines_numbers[0..JSC.ZigException.Holder.source_lines_count]; - @memset(source_lines, ZigString.Empty); + @memset(source_lines, String.empty); @memset(source_line_numbers, 0); var lines_ = lines[0..@min(lines.len, source_lines.len)]; for (lines_, 0..) |line, j| { - source_lines[(lines_.len - 1) - j] = ZigString.init(line); + source_lines[(lines_.len - 1) - j] = String.init(line); source_line_numbers[j] = top.position.line - @intCast(i32, j) + 1; } exception.stack.source_lines_len = @intCast(u8, lines_.len); - top.position.column_stop = @intCast(i32, source_lines[lines_.len - 1].len); + top.position.column_stop = @intCast(i32, source_lines[lines_.len - 1].length()); top.position.line_stop = top.position.column_stop; // This expression range is no longer accurate @@ -2101,8 +2110,10 @@ pub const VirtualMachine = struct { if (frames.len > 1) { for (frames[1..]) |*frame| { if (frame.position.isInvalid()) continue; + const source_url = frame.source_url.toUTF8(bun.default_allocator); + defer source_url.deinit(); if (this.source_mappings.resolveMapping( - frame.source_url.slice(), + source_url.slice(), @max(frame.position.line, 0), @max(frame.position.column_start, 0), )) |mapping| { @@ -2117,6 +2128,7 @@ pub const VirtualMachine = struct { pub fn printErrorInstance(this: *VirtualMachine, error_instance: JSValue, exception_list: ?*ExceptionList, comptime Writer: type, writer: Writer, comptime allow_ansi_color: bool, comptime allow_side_effects: bool) !void { var exception_holder = ZigException.Holder.init(); var exception = exception_holder.zigException(); + defer exception_holder.deinit(); this.remapZigException(exception, error_instance, exception_list); this.had_errors = true; @@ -2134,15 +2146,18 @@ pub const VirtualMachine = struct { var source_lines = exception.stack.sourceLineIterator(); var last_pad: u64 = 0; while (source_lines.untilLast()) |source| { + defer source.text.deinit(); + const int_size = std.fmt.count("{d}", .{source.line}); const pad = max_line_number_pad - int_size; last_pad = pad; try writer.writeByteNTimes(' ', pad); + try writer.print( comptime Output.prettyFmt("{d} | {s}\n", allow_ansi_color), .{ source.line, - std.mem.trim(u8, source.text, "\n"), + std.mem.trim(u8, source.text.slice(), "\n"), }, ); } @@ -2158,7 +2173,8 @@ pub const VirtualMachine = struct { const top_frame = if (exception.stack.frames_len > 0) exception.stack.frames()[0] else null; if (top_frame == null or top_frame.?.position.isInvalid()) { defer did_print_name = true; - var text = std.mem.trim(u8, source.text, "\n"); + defer source.text.deinit(); + var text = std.mem.trim(u8, source.text.slice(), "\n"); try writer.print( comptime Output.prettyFmt( @@ -2176,7 +2192,9 @@ pub const VirtualMachine = struct { const int_size = std.fmt.count("{d}", .{source.line}); const pad = max_line_number_pad - int_size; try writer.writeByteNTimes(' ', pad); - var remainder = std.mem.trim(u8, source.text, "\n"); + defer source.text.deinit(); + const text = source.text.slice(); + var remainder = std.mem.trim(u8, text, "\n"); try writer.print( comptime Output.prettyFmt( @@ -2188,7 +2206,7 @@ pub const VirtualMachine = struct { if (!top.position.isInvalid()) { var first_non_whitespace = @intCast(u32, top.position.column_start); - while (first_non_whitespace < source.text.len and source.text[first_non_whitespace] == ' ') { + while (first_non_whitespace < text.len and text[first_non_whitespace] == ' ') { first_non_whitespace += 1; } const indent = @intCast(usize, pad) + " | ".len + first_non_whitespace; @@ -2219,10 +2237,10 @@ pub const VirtualMachine = struct { }; var show = Show{ - .system_code = exception.system_code.len > 0 and !strings.eql(exception.system_code.slice(), name.slice()), - .syscall = exception.syscall.len > 0, + .system_code = !exception.system_code.eql(name) and !exception.system_code.isEmpty(), + .syscall = !exception.syscall.isEmpty(), .errno = exception.errno < 0, - .path = exception.path.len > 0, + .path = !exception.path.isEmpty(), .fd = exception.fd != -1, }; @@ -2262,7 +2280,7 @@ pub const VirtualMachine = struct { } else if (show.errno) { try writer.writeAll(" "); } - try writer.print(comptime Output.prettyFmt(" path: \"{s}\"\n", allow_ansi_color), .{exception.path}); + try writer.print(comptime Output.prettyFmt(" path: \"{}\"\n", allow_ansi_color), .{exception.path}); } if (show.fd) { @@ -2281,12 +2299,12 @@ pub const VirtualMachine = struct { } else if (show.errno) { try writer.writeAll(" "); } - try writer.print(comptime Output.prettyFmt(" code: \"{s}\"\n", allow_ansi_color), .{exception.system_code}); + try writer.print(comptime Output.prettyFmt(" code: \"{}\"\n", allow_ansi_color), .{exception.system_code}); add_extra_line = true; } if (show.syscall) { - try writer.print(comptime Output.prettyFmt(" syscall: \"{s}\"\n", allow_ansi_color), .{exception.syscall}); + try writer.print(comptime Output.prettyFmt(" syscall: \"{}\"\n", allow_ansi_color), .{exception.syscall}); add_extra_line = true; } @@ -2303,22 +2321,22 @@ pub const VirtualMachine = struct { try printStackTrace(@TypeOf(writer), writer, exception.stack, allow_ansi_color); } - fn printErrorNameAndMessage(_: *VirtualMachine, name: ZigString, message: ZigString, comptime Writer: type, writer: Writer, comptime allow_ansi_color: bool) !void { - if (name.len > 0 and message.len > 0) { - const display_name: ZigString = if (!name.is16Bit() and strings.eqlComptime(name.slice(), "Error")) ZigString.init("error") else name; + fn printErrorNameAndMessage(_: *VirtualMachine, name: String, message: String, comptime Writer: type, writer: Writer, comptime allow_ansi_color: bool) !void { + if (!name.isEmpty() and !message.isEmpty()) { + const display_name: String = if (name.eqlComptime("Error")) String.init("error") else name; try writer.print(comptime Output.prettyFmt("{any}: {s}\n", allow_ansi_color), .{ display_name, message, }); - } else if (name.len > 0) { - if (name.is16Bit() or !strings.hasPrefixComptime(name.slice(), "error")) { - try writer.print(comptime Output.prettyFmt("error: {s}\n", allow_ansi_color), .{name}); + } else if (!name.isEmpty()) { + if (!name.hasPrefixComptime("error")) { + try writer.print(comptime Output.prettyFmt("error: {}\n", allow_ansi_color), .{name}); } else { - try writer.print(comptime Output.prettyFmt("{s}\n", allow_ansi_color), .{name}); + try writer.print(comptime Output.prettyFmt("{}\n", allow_ansi_color), .{name}); } - } else if (message.len > 0) { - try writer.print(comptime Output.prettyFmt("error: {s}\n", allow_ansi_color), .{message}); + } else if (!message.isEmpty()) { + try writer.print(comptime Output.prettyFmt("error: {}\n", allow_ansi_color), .{message}); } else { try writer.print(comptime Output.prettyFmt("error\n", allow_ansi_color), .{}); } diff --git a/src/bun.js/test/jest.zig b/src/bun.js/test/jest.zig index d3bb90747..5ae2337f9 100644 --- a/src/bun.js/test/jest.zig +++ b/src/bun.js/test/jest.zig @@ -1532,8 +1532,8 @@ inline fn createIfScope( // In Github Actions, emit an annotation that renders the error and location. // https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message pub fn printGithubAnnotation(exception: *JSC.ZigException) void { - const name = exception.name; - const message = exception.message; + const name = @field(exception, "name"); + const message = @field(exception, "message"); const frames = exception.stack.frames(); const top_frame = if (frames.len > 0) frames[0] else null; const dir = bun.getenvZ("GITHUB_WORKSPACE") orelse bun.fs.FileSystem.instance.top_level_dir; @@ -1543,7 +1543,7 @@ pub fn printGithubAnnotation(exception: *JSC.ZigException) void { if (top_frame) |frame| { if (!frame.position.isInvalid()) { - const source_url = frame.source_url.toSlice(allocator); + const source_url = frame.source_url.toUTF8(allocator); defer source_url.deinit(); const file = bun.path.relative(dir, source_url.slice()); Output.printError("\n::error file={s},line={d},col={d},title=", .{ @@ -1559,14 +1559,14 @@ pub fn printGithubAnnotation(exception: *JSC.ZigException) void { Output.printError("\n::error title=", .{}); } - if (name.len == 0 or name.eqlComptime("Error")) { + if (name.isEmpty() or name.eqlComptime("Error")) { Output.printError("error", .{}); } else { Output.printError("{s}", .{name.githubAction()}); } - if (message.len > 0) { - const message_slice = message.toSlice(allocator); + if (!message.isEmpty()) { + const message_slice = message.toUTF8(allocator); defer message_slice.deinit(); const msg = message_slice.slice(); @@ -1574,7 +1574,7 @@ pub fn printGithubAnnotation(exception: *JSC.ZigException) void { while (strings.indexOfNewlineOrNonASCIIOrANSI(msg, cursor)) |i| { cursor = i + 1; if (msg[i] == '\n') { - const first_line = ZigString.init(msg[0..i]); + const first_line = bun.String.fromUTF8(msg[0..i]); Output.printError(": {s}::", .{first_line.githubAction()}); break; } @@ -1605,10 +1605,10 @@ pub fn printGithubAnnotation(exception: *JSC.ZigException) void { var i: i16 = 0; while (i < frames.len) : (i += 1) { const frame = frames[@intCast(usize, i)]; - const source_url = frame.source_url.toSlice(allocator); + const source_url = frame.source_url.toUTF8(allocator); defer source_url.deinit(); const file = bun.path.relative(dir, source_url.slice()); - const func = frame.function_name.toSlice(allocator); + const func = frame.function_name.toUTF8(allocator); if (file.len == 0 and func.len == 0) continue; diff --git a/src/js/out/modules/node/path.js b/src/js/out/modules/node/path.js index f8cc1ec08..3a3a75207 100644 --- a/src/js/out/modules/node/path.js +++ b/src/js/out/modules/node/path.js @@ -1 +1 @@ -var g=function(i){var f=m({basename:i.basename.bind(i),dirname:i.dirname.bind(i),extname:i.extname.bind(i),format:i.format.bind(i),isAbsolute:i.isAbsolute.bind(i),join:i.join.bind(i),normalize:i.normalize.bind(i),parse:i.parse.bind(i),relative:i.relative.bind(i),resolve:i.resolve.bind(i),toNamespacedPath:i.toNamespacedPath.bind(i),sep:i.sep,delimiter:i.delimiter});return f.default=f,f},m=(i)=>Object.assign(Object.create(null),i),k=g(Bun._Path()),q=g(Bun._Path(!1)),v=g(Bun._Path(!0));k.win32=v;k.posix=q;var{basename:y,dirname:z,extname:A,format:B,isAbsolute:C,join:D,normalize:E,parse:F,relative:G,resolve:H,toNamespacedPath:I,sep:J,delimiter:K,__esModule:L}=k;k[Symbol.for("CommonJS")]=0;k.__esModule=!0;var O=k;export{v as win32,I as toNamespacedPath,J as sep,H as resolve,G as relative,q as posix,F as parse,E as normalize,D as join,C as isAbsolute,B as format,A as extname,z as dirname,K as delimiter,O as default,m as createModule,y as basename,L as __esModule}; +var i=function(N){var m=g({basename:N.basename.bind(N),dirname:N.dirname.bind(N),extname:N.extname.bind(N),format:N.format.bind(N),isAbsolute:N.isAbsolute.bind(N),join:N.join.bind(N),normalize:N.normalize.bind(N),parse:N.parse.bind(N),relative:N.relative.bind(N),resolve:N.resolve.bind(N),toNamespacedPath:N.toNamespacedPath.bind(N),sep:N.sep,delimiter:N.delimiter});return m.default=m,m},g=(N)=>Object.assign(Object.create(null),N),f=i(Bun._Path()),J=i(Bun._Path(!1)),k=i(Bun._Path(!0));f.win32=k;f.posix=J;var{basename:q,dirname:v,extname:y,format:z,isAbsolute:A,join:B,normalize:K,parse:C,relative:D,resolve:E,toNamespacedPath:F,sep:G,delimiter:H,__esModule:I}=f;f[Symbol.for("CommonJS")]=0;f.__esModule=!0;var O=f;export{k as win32,F as toNamespacedPath,G as sep,E as resolve,D as relative,J as posix,C as parse,K as normalize,B as join,A as isAbsolute,z as format,y as extname,v as dirname,H as delimiter,O as default,g as createModule,q as basename,I as __esModule}; diff --git a/src/js/out/modules/node/stream.web.js b/src/js/out/modules/node/stream.web.js index bb906418c..f91ee03b4 100644 --- a/src/js/out/modules/node/stream.web.js +++ b/src/js/out/modules/node/stream.web.js @@ -1 +1 @@ -var{ReadableStream:c,ReadableStreamDefaultController:j,WritableStream:k,WritableStreamDefaultController:p,WritableStreamDefaultWriter:v,TransformStream:w,TransformStreamDefaultController:x,ByteLengthQueuingStrategy:z,CountQueuingStrategy:A,ReadableStreamBYOBReader:E,ReadableStreamBYOBRequest:F,ReadableStreamDefaultReader:G}=globalThis,H={ReadableStream:c,ReadableStreamDefaultController:j,WritableStream:k,WritableStreamDefaultController:p,WritableStreamDefaultWriter:v,TransformStream:w,TransformStreamDefaultController:x,ByteLengthQueuingStrategy:z,CountQueuingStrategy:A,ReadableStreamBYOBReader:E,ReadableStreamBYOBRequest:F,ReadableStreamDefaultReader:G,[Symbol.for("CommonJS")]:0};export{H as default,v as WritableStreamDefaultWriter,p as WritableStreamDefaultController,k as WritableStream,x as TransformStreamDefaultController,w as TransformStream,G as ReadableStreamDefaultReader,j as ReadableStreamDefaultController,F as ReadableStreamBYOBRequest,E as ReadableStreamBYOBReader,c as ReadableStream,A as CountQueuingStrategy,z as ByteLengthQueuingStrategy}; +var{ReadableStream:k,ReadableStreamDefaultController:v,WritableStream:w,WritableStreamDefaultController:x,WritableStreamDefaultWriter:z,TransformStream:A,TransformStreamDefaultController:E,ByteLengthQueuingStrategy:F,CountQueuingStrategy:c,ReadableStreamBYOBReader:j,ReadableStreamBYOBRequest:G,ReadableStreamDefaultReader:p}=globalThis,H={ReadableStream:k,ReadableStreamDefaultController:v,WritableStream:w,WritableStreamDefaultController:x,WritableStreamDefaultWriter:z,TransformStream:A,TransformStreamDefaultController:E,ByteLengthQueuingStrategy:F,CountQueuingStrategy:c,ReadableStreamBYOBReader:j,ReadableStreamBYOBRequest:G,ReadableStreamDefaultReader:p,[Symbol.for("CommonJS")]:0};export{H as default,z as WritableStreamDefaultWriter,x as WritableStreamDefaultController,w as WritableStream,E as TransformStreamDefaultController,A as TransformStream,p as ReadableStreamDefaultReader,v as ReadableStreamDefaultController,G as ReadableStreamBYOBRequest,j as ReadableStreamBYOBReader,k as ReadableStream,c as CountQueuingStrategy,F as ByteLengthQueuingStrategy}; diff --git a/src/logger.zig b/src/logger.zig index 3279e9fd5..fc25541de 100644 --- a/src/logger.zig +++ b/src/logger.zig @@ -421,12 +421,12 @@ pub const Msg = struct { if (err.toError()) |value| { value.toZigException(globalObject, zig_exception_holder.zigException()); } else { - zig_exception_holder.zig_exception.message = JSC.ZigString.fromUTF8(err.toSlice(globalObject, allocator).slice()); + zig_exception_holder.zig_exception.message = err.toBunString(globalObject); } return Msg{ .data = .{ - .text = zig_exception_holder.zigException().message.toSliceClone(allocator).slice(), + .text = try zig_exception_holder.zigException().message.toOwnedSlice(allocator), .location = Location{ .file = file, }, diff --git a/src/string.zig b/src/string.zig index 54af2ba68..3c0c99ce5 100644 --- a/src/string.zig +++ b/src/string.zig @@ -247,6 +247,26 @@ pub const String = extern struct { extern fn BunString__fromLatin1(bytes: [*]const u8, len: usize) String; extern fn BunString__fromBytes(bytes: [*]const u8, len: usize) String; + pub fn toOwnedSlice(this: String, allocator: std.mem.Allocator) ![]u8 { + switch (this.tag) { + .ZigString => return try this.value.ZigString.toOwnedSlice(allocator), + .WTFStringImpl => { + var utf8_slice = this.value.WTFStringImpl.toUTF8(allocator); + + if (utf8_slice.allocator.get()) |alloc| { + if (isWTFAllocator(alloc)) { + return @constCast((try utf8_slice.clone(allocator)).slice()); + } + } + + return @constCast(utf8_slice.slice()); + }, + .StaticZigString => return try this.value.StaticZigString.toOwnedSlice(allocator), + .Empty => return &[_]u8{}, + else => unreachable, + } + } + pub fn createLatin1(bytes: []const u8) String { JSC.markBinding(@src()); return BunString__fromLatin1(bytes.ptr, bytes.len); @@ -429,6 +449,10 @@ pub const String = extern struct { return .latin1; } + pub fn githubAction(self: String) ZigString.GithubActionFormatter { + return self.toZigString().githubAction(); + } + pub fn byteSlice(this: String) []const u8 { return switch (this.tag) { .ZigString, .StaticZigString => this.value.ZigString.byteSlice(), -- cgit v1.2.3 From f00e2be548da21b9feaef178bb0ac22230801d6f Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Sat, 1 Jul 2023 17:37:44 -0700 Subject: Use `BunString` in `SystemError` (#3485) * Use `BunString` in SystemError * Use Bun::toStringRef when we will de-ref strings * Move `napi_create_error` to C++ to support `code` being a Symbol potentially * Update blob.zig * Make this test less flaky --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> --- src/bun.js/api/bun/dns_resolver.zig | 8 ++-- src/bun.js/api/bun/socket.zig | 12 ++--- src/bun.js/api/ffi.zig | 6 +-- src/bun.js/api/server.zig | 12 ++--- src/bun.js/bindings/BunString.cpp | 48 +++++++++++++++++--- src/bun.js/bindings/bindings.cpp | 66 +++++++++++++--------------- src/bun.js/bindings/bindings.zig | 8 ++-- src/bun.js/bindings/headers-handwritten.h | 12 +++-- src/bun.js/bindings/helpers.h | 4 +- src/bun.js/bindings/napi.cpp | 29 +++++++++--- src/bun.js/bindings/webcore/JSCloseEvent.cpp | 2 +- src/bun.js/node/node_os.zig | 32 +++++++------- src/bun.js/node/syscall.zig | 8 ++-- src/bun.js/webcore/blob.zig | 55 +++++++++++------------ src/bun.js/webcore/response.zig | 14 +++--- src/bun.js/webcore/streams.zig | 6 +-- src/bundler/bundle_v2.zig | 16 +++++-- src/http.zig | 5 ++- src/napi/napi.zig | 11 +---- test/js/bun/util/error-gc-test.test.js | 41 ++++++++++++++++- 20 files changed, 242 insertions(+), 153 deletions(-) (limited to 'src/bun.js/bindings/headers-handwritten.h') diff --git a/src/bun.js/api/bun/dns_resolver.zig b/src/bun.js/api/bun/dns_resolver.zig index fee834e5e..d0d4f5b7b 100644 --- a/src/bun.js/api/bun/dns_resolver.zig +++ b/src/bun.js/api/bun/dns_resolver.zig @@ -1925,8 +1925,8 @@ pub const DNSResolver = struct { .err => |err| { const system_error = JSC.SystemError{ .errno = -1, - .code = JSC.ZigString.init(err.code()), - .message = JSC.ZigString.init(err.label()), + .code = bun.String.static(err.code()), + .message = bun.String.static(err.label()), }; globalThis.throwValue(system_error.toErrorInstance(globalThis)); @@ -1972,8 +1972,8 @@ pub const DNSResolver = struct { .err => |err| { const system_error = JSC.SystemError{ .errno = -1, - .code = JSC.ZigString.init(err.code()), - .message = JSC.ZigString.init(err.label()), + .code = bun.String.static(err.code()), + .message = bun.String.static(err.label()), }; globalThis.throwValue(system_error.toErrorInstance(globalThis)); diff --git a/src/bun.js/api/bun/socket.zig b/src/bun.js/api/bun/socket.zig index 00e34a77d..69d6611cb 100644 --- a/src/bun.js/api/bun/socket.zig +++ b/src/bun.js/api/bun/socket.zig @@ -1022,8 +1022,8 @@ fn NewSocket(comptime ssl: bool) type { var globalObject = handlers.globalObject; const err = JSC.SystemError{ .errno = errno, - .message = ZigString.init("Failed to connect"), - .syscall = ZigString.init("connect"), + .message = bun.String.static("Failed to connect"), + .syscall = bun.String.static("connect"), }; if (callback == .zero) { @@ -1232,8 +1232,8 @@ fn NewSocket(comptime ssl: bool) type { const reason = if (ssl_error.reason == null) "" else ssl_error.reason[0..bun.len(ssl_error.reason)]; const fallback = JSC.SystemError{ - .code = ZigString.init(code), - .message = ZigString.init(reason), + .code = bun.String.create(code), + .message = bun.String.create(reason), }; authorization_error = fallback.toErrorInstance(globalObject); @@ -1409,8 +1409,8 @@ fn NewSocket(comptime ssl: bool) type { const reason = if (ssl_error.reason == null) "" else ssl_error.reason[0..bun.len(ssl_error.reason)]; const fallback = JSC.SystemError{ - .code = ZigString.init(code), - .message = ZigString.init(reason), + .code = bun.String.create(code), + .message = bun.String.create(reason), }; return fallback.toErrorInstance(globalObject); diff --git a/src/bun.js/api/ffi.zig b/src/bun.js/api/ffi.zig index e46e054ec..ba31b67ed 100644 --- a/src/bun.js/api/ffi.zig +++ b/src/bun.js/api/ffi.zig @@ -311,9 +311,9 @@ pub const FFI = struct { break :brk std.DynLib.open(backup_name) catch { // Then, if that fails, report an error. const system_error = JSC.SystemError{ - .code = ZigString.init(@tagName(JSC.Node.ErrorCode.ERR_DLOPEN_FAILED)), - .message = ZigString.init("Failed to open library. This is usually caused by a missing library or an invalid library path."), - .syscall = ZigString.init("dlopen"), + .code = bun.String.create(@tagName(JSC.Node.ErrorCode.ERR_DLOPEN_FAILED)), + .message = bun.String.create("Failed to open library. This is usually caused by a missing library or an invalid library path."), + .syscall = bun.String.create("dlopen"), }; return system_error.toErrorInstance(global); }; diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index 136737069..140e62ce4 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -1796,7 +1796,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp .syscall = .sendfile, }; var sys = err.withPathLike(file.pathlike).toSystemError(); - sys.message = ZigString.init("MacOS does not support sending non-regular files"); + sys.message = bun.String.static("MacOS does not support sending non-regular files"); this.runErrorHandler(sys.toErrorInstance( this.server.globalThis, )); @@ -1815,7 +1815,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp .syscall = .sendfile, }; var sys = err.withPathLike(file.pathlike).toSystemError(); - sys.message = ZigString.init("File must be regular or FIFO"); + sys.message = bun.String.static("File must be regular or FIFO"); this.runErrorHandler(sys.toErrorInstance( this.server.globalThis, )); @@ -2375,8 +2375,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp } const fallback = JSC.SystemError{ - .code = ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_UNHANDLED_ERROR))), - .message = ZigString.init("Unhandled error in ReadableStream"), + .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_UNHANDLED_ERROR))), + .message = bun.String.static("Unhandled error in ReadableStream"), }; req.handleReject(fallback.toErrorInstance(globalThis)); } @@ -2422,8 +2422,8 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp if (stream.isLocked(this.server.globalThis)) { streamLog("was locked but it shouldn't be", .{}); var err = JSC.SystemError{ - .code = ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_STREAM_CANNOT_PIPE))), - .message = ZigString.init("Stream already used, please create a new one"), + .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_STREAM_CANNOT_PIPE))), + .message = bun.String.static("Stream already used, please create a new one"), }; stream.value.unprotect(); this.runErrorHandler(err.toErrorInstance(this.server.globalThis)); diff --git a/src/bun.js/bindings/BunString.cpp b/src/bun.js/bindings/BunString.cpp index f590edd35..4c8ff384e 100644 --- a/src/bun.js/bindings/BunString.cpp +++ b/src/bun.js/bindings/BunString.cpp @@ -86,31 +86,69 @@ BunString toString(JSC::JSGlobalObject* globalObject, JSValue value) return fromJS(globalObject, value); } +BunString toStringRef(JSC::JSGlobalObject* globalObject, JSValue value) +{ + auto str = value.toWTFString(globalObject); + if (str.isEmpty()) { + return { BunStringTag::Empty }; + } + + str.impl()->ref(); + + return { BunStringTag::WTFStringImpl, { .wtf = str.impl() } }; +} + BunString toString(WTF::String& wtfString) { - if (wtfString.length() == 0) + if (wtfString.isEmpty()) return { BunStringTag::Empty }; return { BunStringTag::WTFStringImpl, { .wtf = wtfString.impl() } }; } BunString toString(const WTF::String& wtfString) { - if (wtfString.length() == 0) + if (wtfString.isEmpty()) return { BunStringTag::Empty }; return { BunStringTag::WTFStringImpl, { .wtf = wtfString.impl() } }; } BunString toString(WTF::StringImpl* wtfString) { - if (wtfString->length() == 0) + if (wtfString->isEmpty()) return { BunStringTag::Empty }; return { BunStringTag::WTFStringImpl, { .wtf = wtfString } }; } +BunString toStringRef(WTF::String& wtfString) +{ + if (wtfString.isEmpty()) + return { BunStringTag::Empty }; + + wtfString.impl()->ref(); + return { BunStringTag::WTFStringImpl, { .wtf = wtfString.impl() } }; +} +BunString toStringRef(const WTF::String& wtfString) +{ + if (wtfString.isEmpty()) + return { BunStringTag::Empty }; + + wtfString.impl()->ref(); + return { BunStringTag::WTFStringImpl, { .wtf = wtfString.impl() } }; +} +BunString toStringRef(WTF::StringImpl* wtfString) +{ + if (wtfString->isEmpty()) + return { BunStringTag::Empty }; + + wtfString->ref(); + + return { BunStringTag::WTFStringImpl, { .wtf = wtfString } }; +} + BunString fromString(WTF::String& wtfString) { - if (wtfString.length() == 0) + if (wtfString.isEmpty()) return { BunStringTag::Empty }; return { BunStringTag::WTFStringImpl, { .wtf = wtfString.impl() } }; @@ -118,7 +156,7 @@ BunString fromString(WTF::String& wtfString) BunString fromString(WTF::StringImpl* wtfString) { - if (wtfString->length() == 0) + if (wtfString->isEmpty()) return { BunStringTag::Empty }; return { BunStringTag::WTFStringImpl, { .wtf = wtfString } }; diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 96fcde303..9f9b20c1e 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -1279,15 +1279,14 @@ JSC__JSValue SystemError__toErrorInstance(const SystemError* arg0, JSC__JSGlobalObject* globalObject) { - static const char* system_error_name = "SystemError"; SystemError err = *arg0; JSC::VM& vm = globalObject->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSC::JSValue message = JSC::jsUndefined(); - if (err.message.len > 0) { - message = Zig::toJSString(err.message, globalObject); + if (err.message.tag != BunStringTag::Empty) { + message = Bun::toJS(globalObject, err.message); } JSC::JSValue options = JSC::jsUndefined(); @@ -1297,8 +1296,8 @@ JSC__JSValue SystemError__toErrorInstance(const SystemError* arg0, auto clientData = WebCore::clientData(vm); - if (err.code.len > 0 && !(err.code.len == 1 and err.code.ptr[0] == 0)) { - JSC::JSValue code = Zig::toJSStringGC(err.code, globalObject); + if (err.code.tag != BunStringTag::Empty) { + JSC::JSValue code = Bun::toJS(globalObject, err.code); result->putDirect(vm, clientData->builtinNames().codePublicName(), code, JSC::PropertyAttribute::DontDelete | 0); @@ -1307,13 +1306,12 @@ JSC__JSValue SystemError__toErrorInstance(const SystemError* arg0, result->putDirect( vm, vm.propertyNames->name, - JSC::JSValue(JSC::jsOwnedString( - vm, WTF::String(WTF::StringImpl::createWithoutCopying(system_error_name, 11)))), + JSC::JSValue(jsString(vm, String("SystemError"_s))), JSC::PropertyAttribute::DontEnum | 0); } - if (err.path.len > 0) { - JSC::JSValue path = JSC::JSValue(Zig::toJSStringGC(err.path, globalObject)); + if (err.path.tag != BunStringTag::Empty) { + JSC::JSValue path = Bun::toJS(globalObject, err.path); result->putDirect(vm, clientData->builtinNames().pathPublicName(), path, JSC::PropertyAttribute::DontDelete | 0); } @@ -1324,8 +1322,8 @@ JSC__JSValue SystemError__toErrorInstance(const SystemError* arg0, JSC::PropertyAttribute::DontDelete | 0); } - if (err.syscall.len > 0) { - JSC::JSValue syscall = JSC::JSValue(Zig::toJSString(err.syscall, globalObject)); + if (err.syscall.tag != BunStringTag::Empty) { + JSC::JSValue syscall = Bun::toJS(globalObject, err.syscall); result->putDirect(vm, clientData->builtinNames().syscallPublicName(), syscall, JSC::PropertyAttribute::DontDelete | 0); } @@ -3303,11 +3301,8 @@ bool JSC__JSValue__stringIncludes(JSC__JSValue value, JSC__JSGlobalObject* globa static void populateStackFrameMetadata(JSC::VM& vm, const JSC::StackFrame* stackFrame, ZigStackFrame* frame) { - String str = stackFrame->sourceURL(vm); - if (!str.isEmpty()) - str.impl()->ref(); - frame->source_url = Bun::toString(str); + frame->source_url = Bun::toStringRef(stackFrame->sourceURL(vm)); if (stackFrame->isWasmFrame()) { frame->code_type = ZigStackFrameCodeWasm; @@ -3344,10 +3339,7 @@ static void populateStackFrameMetadata(JSC::VM& vm, const JSC::StackFrame* stack JSC::JSObject* callee = JSC::jsCast(calleeCell); - String displayName = JSC::getCalculatedDisplayName(vm, callee); - if (!displayName.isEmpty()) - displayName.impl()->ref(); - frame->function_name = Bun::toString(displayName); + frame->function_name = Bun::toStringRef(JSC::getCalculatedDisplayName(vm, callee)); } // Based on // https://github.com/mceSystems/node-jsc/blob/master/deps/jscshim/src/shim/JSCStackTrace.cpp#L298 @@ -3421,7 +3413,7 @@ static void populateStackFramePosition(const JSC::StackFrame* stackFrame, BunStr // Most of the time, when you look at a stack trace, you want a couple lines above - source_lines[0] = Bun::toString(sourceString.substring(lineStart, lineStop - lineStart).toStringWithoutCopying()); + source_lines[0] = Bun::toStringRef(sourceString.substring(lineStart, lineStop - lineStart).toStringWithoutCopying()); source_line_numbers[0] = line; if (lineStart > 0) { @@ -3438,7 +3430,7 @@ static void populateStackFramePosition(const JSC::StackFrame* stackFrame, BunStr } // We are at the beginning of the line - source_lines[source_line_i] = Bun::toString(sourceString.substring(byte_offset_in_source_string, end_of_line_offset - byte_offset_in_source_string + 1).toStringWithoutCopying()); + source_lines[source_line_i] = Bun::toStringRef(sourceString.substring(byte_offset_in_source_string, end_of_line_offset - byte_offset_in_source_string + 1).toStringWithoutCopying()); source_line_numbers[source_line_i] = line - source_line_i; source_line_i++; @@ -3526,30 +3518,32 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, except->code = 8; } if (except->code == SYNTAX_ERROR_CODE) { - except->message = Bun::toString(err->sanitizedMessageString(global)); + except->message = Bun::toStringRef(err->sanitizedMessageString(global)); } else if (JSC::JSValue message = obj->getIfPropertyExists(global, vm.propertyNames->message)) { - except->message = Bun::toString(global, message); + except->message = Bun::toStringRef(global, message); } else { - except->message = Bun::toString(err->sanitizedMessageString(global)); + except->message = Bun::toStringRef(err->sanitizedMessageString(global)); } - except->name = Bun::toString(err->sanitizedNameString(global)); + + except->name = Bun::toStringRef(err->sanitizedNameString(global)); + except->runtime_type = err->runtimeTypeForCause(); auto clientData = WebCore::clientData(vm); if (except->code != SYNTAX_ERROR_CODE) { if (JSC::JSValue syscall = obj->getIfPropertyExists(global, clientData->builtinNames().syscallPublicName())) { - except->syscall = Bun::toString(global, syscall); + except->syscall = Bun::toStringRef(global, syscall); } if (JSC::JSValue code = obj->getIfPropertyExists(global, clientData->builtinNames().codePublicName())) { - except->code_ = Bun::toString(global, code); + except->code_ = Bun::toStringRef(global, code); } if (JSC::JSValue path = obj->getIfPropertyExists(global, clientData->builtinNames().pathPublicName())) { - except->path = Bun::toString(global, path); + except->path = Bun::toStringRef(global, path); } if (JSC::JSValue fd = obj->getIfPropertyExists(global, Identifier::fromString(vm, "fd"_s))) { @@ -3565,7 +3559,7 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, if (getFromSourceURL) { if (JSC::JSValue sourceURL = obj->getIfPropertyExists(global, vm.propertyNames->sourceURL)) { - except->stack.frames_ptr[0].source_url = Bun::toString(global, sourceURL); + except->stack.frames_ptr[0].source_url = Bun::toStringRef(global, sourceURL); if (JSC::JSValue column = obj->getIfPropertyExists(global, vm.propertyNames->column)) { except->stack.frames_ptr[0].position.column_start = column.toInt32(global); @@ -3577,7 +3571,7 @@ static void fromErrorInstance(ZigException* except, JSC::JSGlobalObject* global, if (JSC::JSValue lineText = obj->getIfPropertyExists(global, JSC::Identifier::fromString(vm, "lineText"_s))) { if (JSC::JSString* jsStr = lineText.toStringOrNull(global)) { auto str = jsStr->value(global); - except->stack.source_lines_ptr[0] = Bun::toString(str); + except->stack.source_lines_ptr[0] = Bun::toStringRef(str); except->stack.source_lines_numbers[0] = except->stack.frames_ptr[0].position.line; except->stack.source_lines_len = 1; except->remapped = true; @@ -3600,7 +3594,7 @@ void exceptionFromString(ZigException* except, JSC::JSValue value, JSC::JSGlobal if (JSC::JSObject* obj = JSC::jsDynamicCast(value)) { if (obj->hasProperty(global, global->vm().propertyNames->name)) { auto name_str = obj->getIfPropertyExists(global, global->vm().propertyNames->name).toWTFString(global); - except->name = Bun::toString(name_str); + except->name = Bun::toStringRef(name_str); if (name_str == "Error"_s) { except->code = JSErrorCodeError; } else if (name_str == "EvalError"_s) { @@ -3622,14 +3616,14 @@ void exceptionFromString(ZigException* except, JSC::JSValue value, JSC::JSGlobal if (JSC::JSValue message = obj->getIfPropertyExists(global, global->vm().propertyNames->message)) { if (message) { - except->message = Bun::toString( + except->message = Bun::toStringRef( message.toWTFString(global)); } } if (JSC::JSValue sourceURL = obj->getIfPropertyExists(global, global->vm().propertyNames->sourceURL)) { if (sourceURL) { - except->stack.frames_ptr[0].source_url = Bun::toString( + except->stack.frames_ptr[0].source_url = Bun::toStringRef( sourceURL.toWTFString(global)); except->stack.frames_len = 1; } @@ -3658,7 +3652,7 @@ void exceptionFromString(ZigException* except, JSC::JSValue value, JSC::JSGlobal } scope.release(); - except->message = Bun::toString(str); + except->message = Bun::toStringRef(str); } void JSC__VM__releaseWeakRefs(JSC__VM* arg0) @@ -3768,8 +3762,8 @@ void JSC__JSValue__toZigException(JSC__JSValue JSValue0, JSC__JSGlobalObject* ar JSC::JSValue value = JSC::JSValue::decode(JSValue0); if (value == JSC::JSValue {}) { exception->code = JSErrorCodeError; - exception->name = Bun::toString("Error"_s); - exception->message = Bun::toString("Unknown error"_s); + exception->name = Bun::toStringRef("Error"_s); + exception->message = Bun::toStringRef("Unknown error"_s); return; } diff --git a/src/bun.js/bindings/bindings.zig b/src/bun.js/bindings/bindings.zig index 1c09378a8..777860d3c 100644 --- a/src/bun.js/bindings/bindings.zig +++ b/src/bun.js/bindings/bindings.zig @@ -1561,10 +1561,10 @@ pub const FetchHeaders = opaque { pub const SystemError = extern struct { errno: c_int = 0, /// label for errno - code: ZigString = ZigString.init(""), - message: ZigString = ZigString.init(""), - path: ZigString = ZigString.init(""), - syscall: ZigString = ZigString.init(""), + code: String = String.empty, + message: String = String.empty, + path: String = String.empty, + syscall: String = String.empty, fd: i32 = -1, pub fn Maybe(comptime Result: type) type { diff --git a/src/bun.js/bindings/headers-handwritten.h b/src/bun.js/bindings/headers-handwritten.h index c7429b633..90c8f86d2 100644 --- a/src/bun.js/bindings/headers-handwritten.h +++ b/src/bun.js/bindings/headers-handwritten.h @@ -84,10 +84,10 @@ typedef struct ErrorableResolvedSource { typedef struct SystemError { int errno_; - ZigString code; - ZigString message; - ZigString path; - ZigString syscall; + BunString code; + BunString message; + BunString path; + BunString syscall; int fd; } SystemError; @@ -246,6 +246,10 @@ BunString toString(WTF::String& wtfString); BunString toString(const WTF::String& wtfString); BunString toString(WTF::StringImpl* wtfString); +BunString toStringRef(JSC::JSGlobalObject* globalObject, JSC::JSValue value); +BunString toStringRef(WTF::String& wtfString); +BunString toStringRef(const WTF::String& wtfString); +BunString toStringRef(WTF::StringImpl* wtfString); } using Uint8Array_alias = JSC::JSUint8Array; diff --git a/src/bun.js/bindings/helpers.h b/src/bun.js/bindings/helpers.h index 402807f3d..00777c304 100644 --- a/src/bun.js/bindings/helpers.h +++ b/src/bun.js/bindings/helpers.h @@ -342,10 +342,10 @@ static const WTF::String toStringStatic(ZigString str) } if (isTaggedUTF16Ptr(str.ptr)) { - return WTF::String(WTF::ExternalStringImpl::createStatic(reinterpret_cast(untag(str.ptr)), str.len)); + return WTF::String(AtomStringImpl::add(reinterpret_cast(untag(str.ptr)), str.len)); } - return WTF::String(WTF::ExternalStringImpl::createStatic( + return WTF::String(AtomStringImpl::add( reinterpret_cast(untag(str.ptr)), str.len)); } diff --git a/src/bun.js/bindings/napi.cpp b/src/bun.js/bindings/napi.cpp index a859e3ac5..bb62cb2a0 100644 --- a/src/bun.js/bindings/napi.cpp +++ b/src/bun.js/bindings/napi.cpp @@ -554,7 +554,6 @@ extern "C" napi_status napi_wrap(napi_env env, auto* globalObject = toJS(env); auto& vm = globalObject->vm(); - auto* val = jsDynamicCast(value); @@ -572,7 +571,7 @@ extern "C" napi_status napi_wrap(napi_env env, auto clientData = WebCore::clientData(vm); auto* ref = new NapiRef(globalObject, 1); - ref->strongRef.set(globalObject->vm(), value.getObject()); + ref->strongRef.set(globalObject->vm(), value.getObject()); if (finalize_cb) { ref->finalizer.finalize_cb = finalize_cb; @@ -816,7 +815,7 @@ extern "C" napi_status napi_create_reference(napi_env env, napi_value value, } } - if(object) { + if (object) { object->napiRef = ref; } @@ -1029,7 +1028,26 @@ extern "C" napi_status napi_create_type_error(napi_env env, napi_value code, auto error = JSC::createTypeError(globalObject, messageValue.toWTFString(globalObject)); if (codeValue) { - error->putDirect(vm, Identifier::fromString(vm, "code"_s), codeValue, 0); + error->putDirect(vm, WebCore::builtinNames(vm).codePublicName(), codeValue, 0); + } + + *result = reinterpret_cast(JSC::JSValue::encode(error)); + return napi_ok; +} + +extern "C" napi_status napi_create_error(napi_env env, napi_value code, + napi_value msg, + napi_value* result) +{ + Zig::GlobalObject* globalObject = toJS(env); + JSC::VM& vm = globalObject->vm(); + + JSC::JSValue codeValue = JSC::JSValue::decode(reinterpret_cast(code)); + JSC::JSValue messageValue = JSC::JSValue::decode(reinterpret_cast(msg)); + + auto error = JSC::createError(globalObject, messageValue.toWTFString(globalObject)); + if (codeValue) { + error->putDirect(vm, WebCore::builtinNames(vm).codePublicName(), codeValue, 0); } *result = reinterpret_cast(JSC::JSValue::encode(error)); @@ -1474,7 +1492,8 @@ extern "C" napi_status napi_get_property_names(napi_env env, napi_value object, return napi_ok; } -extern "C" napi_status napi_create_object(napi_env env, napi_value* result){ +extern "C" napi_status napi_create_object(napi_env env, napi_value* result) +{ if (UNLIKELY(result == nullptr)) { return napi_invalid_arg; diff --git a/src/bun.js/bindings/webcore/JSCloseEvent.cpp b/src/bun.js/bindings/webcore/JSCloseEvent.cpp index be07cbcfe..ad7b6ed57 100644 --- a/src/bun.js/bindings/webcore/JSCloseEvent.cpp +++ b/src/bun.js/bindings/webcore/JSCloseEvent.cpp @@ -99,7 +99,7 @@ template<> CloseEvent::Init convertDictionary(JSGlobalObject& if (isNullOrUndefined) codeValue = jsUndefined(); else { - codeValue = object->get(&lexicalGlobalObject, Identifier::fromString(vm, "code"_s)); + codeValue = object->get(&lexicalGlobalObject, WebCore::builtinNames(vm).codePublicName()); RETURN_IF_EXCEPTION(throwScope, {}); } if (!codeValue.isUndefined()) { diff --git a/src/bun.js/node/node_os.zig b/src/bun.js/node/node_os.zig index f71143315..483acb3e2 100644 --- a/src/bun.js/node/node_os.zig +++ b/src/bun.js/node/node_os.zig @@ -78,8 +78,8 @@ pub const Os = struct { return if (comptime Environment.isLinux) cpusImplLinux(globalThis) catch { const err = JSC.SystemError{ - .message = JSC.ZigString.init("Failed to get cpu information"), - .code = JSC.ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))), + .message = bun.String.static("Failed to get cpu information"), + .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))), }; globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis)); @@ -88,8 +88,8 @@ pub const Os = struct { else if (comptime Environment.isMac) cpusImplDarwin(globalThis) catch { const err = JSC.SystemError{ - .message = JSC.ZigString.init("Failed to get cpu information"), - .code = JSC.ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))), + .message = bun.String.static("Failed to get cpu information"), + .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))), }; globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis)); @@ -318,11 +318,11 @@ pub const Os = struct { //info.put(globalThis, JSC.ZigString.static("syscall"), JSC.ZigString.init("uv_os_getpriority").withEncoding().toValueGC(globalThis)); const err = JSC.SystemError{ - .message = JSC.ZigString.init("A system error occurred: uv_os_getpriority returned ESRCH (no such process)"), - .code = JSC.ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))), + .message = bun.String.static("A system error occurred: uv_os_getpriority returned ESRCH (no such process)"), + .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))), //.info = info, .errno = -3, - .syscall = JSC.ZigString.init("uv_os_getpriority"), + .syscall = bun.String.static("uv_os_getpriority"), }; globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis)); @@ -377,10 +377,10 @@ pub const Os = struct { const rc = C.getifaddrs(&interface_start); if (rc != 0) { const err = JSC.SystemError{ - .message = JSC.ZigString.init("A system error occurred: getifaddrs returned an error"), - .code = JSC.ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))), + .message = bun.String.static("A system error occurred: getifaddrs returned an error"), + .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))), .errno = @intFromEnum(std.os.errno(rc)), - .syscall = JSC.ZigString.init("getifaddrs"), + .syscall = bun.String.static("getifaddrs"), }; globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis)); @@ -591,11 +591,11 @@ pub const Os = struct { switch (errcode) { .SRCH => { const err = JSC.SystemError{ - .message = JSC.ZigString.init("A system error occurred: uv_os_setpriority returned ESRCH (no such process)"), - .code = JSC.ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))), + .message = bun.String.static("A system error occurred: uv_os_setpriority returned ESRCH (no such process)"), + .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))), //.info = info, .errno = -3, - .syscall = JSC.ZigString.init("uv_os_setpriority"), + .syscall = bun.String.static("uv_os_setpriority"), }; globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis)); @@ -603,11 +603,11 @@ pub const Os = struct { }, .ACCES => { const err = JSC.SystemError{ - .message = JSC.ZigString.init("A system error occurred: uv_os_setpriority returned EACCESS (permission denied)"), - .code = JSC.ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))), + .message = bun.String.static("A system error occurred: uv_os_setpriority returned EACCESS (permission denied)"), + .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))), //.info = info, .errno = -13, - .syscall = JSC.ZigString.init("uv_os_setpriority"), + .syscall = bun.String.static("uv_os_setpriority"), }; globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis)); diff --git a/src/bun.js/node/syscall.zig b/src/bun.js/node/syscall.zig index 48c5b1305..5ff0b2f44 100644 --- a/src/bun.js/node/syscall.zig +++ b/src/bun.js/node/syscall.zig @@ -873,20 +873,20 @@ pub const Error = struct { pub fn toSystemError(this: Error) SystemError { var err = SystemError{ .errno = @as(c_int, this.errno) * -1, - .syscall = JSC.ZigString.init(@tagName(this.syscall)), + .syscall = bun.String.static(@tagName(this.syscall)), }; // errno label if (this.errno > 0 and this.errno < C.SystemErrno.max) { const system_errno = @enumFromInt(C.SystemErrno, this.errno); - err.code = JSC.ZigString.init(@tagName(system_errno)); + err.code = bun.String.static(@tagName(system_errno)); if (C.SystemErrno.labels.get(system_errno)) |label| { - err.message = JSC.ZigString.init(label); + err.message = bun.String.static(label); } } if (this.path.len > 0) { - err.path = JSC.ZigString.init(this.path); + err.path = bun.String.create(this.path); } if (this.fd != -1) { diff --git a/src/bun.js/webcore/blob.zig b/src/bun.js/webcore/blob.zig index faf503a3f..86b5414e3 100644 --- a/src/bun.js/webcore/blob.zig +++ b/src/bun.js/webcore/blob.zig @@ -1194,9 +1194,6 @@ pub const Blob = struct { .syscall = .open, }).toSystemError(); - // assert we never end up reusing the memory - std.debug.assert(@intFromPtr(this.system_error.?.path.slice().ptr) != @intFromPtr(path_buffer)); - callback(this, null_fd); return; }; @@ -1359,12 +1356,13 @@ pub const Blob = struct { return; } else if (this.store == null) { bun.default_allocator.destroy(this); - cb(cb_ctx, ResultType{ .err = SystemError{ - .code = ZigString.init("INTERNAL_ERROR"), - .path = ZigString.Empty, - .message = ZigString.init("assertion failure - store should not be null"), - .syscall = ZigString.init("read"), - } }); + cb(cb_ctx, ResultType{ + .err = SystemError{ + .code = bun.String.static("INTERNAL_ERROR"), + .message = bun.String.static("assertion failure - store should not be null"), + .syscall = bun.String.static("read"), + }, + }); return; } @@ -1396,12 +1394,12 @@ pub const Blob = struct { }).toSystemError(); } else { this.system_error = JSC.SystemError{ - .code = ZigString.init(bun.asByteSlice(@errorName(err))), + .code = bun.String.static(bun.asByteSlice(@errorName(err))), .path = if (this.file_store.pathlike == .path) - ZigString.init(this.file_store.pathlike.path.slice()) + bun.String.create(this.file_store.pathlike.path.slice()) else - ZigString.Empty, - .syscall = ZigString.init("read"), + bun.String.empty, + .syscall = bun.String.static("read"), }; this.errno = err; @@ -1458,13 +1456,13 @@ pub const Blob = struct { if (std.os.S.ISDIR(stat.mode)) { this.errno = error.EISDIR; this.system_error = JSC.SystemError{ - .code = ZigString.init("EISDIR"), + .code = bun.String.static("EISDIR"), .path = if (this.file_store.pathlike == .path) - ZigString.init(this.file_store.pathlike.path.slice()) + bun.String.create(this.file_store.pathlike.path.slice()) else - ZigString.Empty, - .message = ZigString.init("Directories cannot be read like files"), - .syscall = ZigString.init("read"), + bun.String.empty, + .message = bun.String.static("Directories cannot be read like files"), + .syscall = bun.String.static("read"), }; return; } @@ -1643,8 +1641,8 @@ pub const Blob = struct { this.wrote += @truncate(SizeType, result catch |errno| { this.errno = errno; this.system_error = this.system_error orelse JSC.SystemError{ - .code = ZigString.init(bun.asByteSlice(@errorName(errno))), - .syscall = ZigString.init("write"), + .code = bun.String.static(bun.asByteSlice(@errorName(errno))), + .syscall = bun.String.static("write"), }; this.wrote = 0; @@ -1703,13 +1701,13 @@ pub const Blob = struct { const unsupported_directory_error = SystemError{ .errno = @intCast(c_int, @intFromEnum(bun.C.SystemErrno.EISDIR)), - .message = ZigString.init("That doesn't work on folders"), - .syscall = ZigString.init("fstat"), + .message = bun.String.static("That doesn't work on folders"), + .syscall = bun.String.static("fstat"), }; const unsupported_non_regular_file_error = SystemError{ .errno = @intCast(c_int, @intFromEnum(bun.C.SystemErrno.ENOTSUP)), - .message = ZigString.init("Non-regular files aren't supported yet"), - .syscall = ZigString.init("fstat"), + .message = bun.String.static("Non-regular files aren't supported yet"), + .syscall = bun.String.static("fstat"), }; // blocking, but off the main thread @@ -1777,13 +1775,12 @@ pub const Blob = struct { pub fn reject(this: *CopyFile, promise: *JSC.JSPromise) void { var globalThis = this.globalThis; var system_error: SystemError = this.system_error orelse SystemError{}; - if (this.source_file_store.pathlike == .path and system_error.path.len == 0) { - system_error.path = ZigString.init(this.source_file_store.pathlike.path.slice()); - system_error.path.mark(); + if (this.source_file_store.pathlike == .path and system_error.path.isEmpty()) { + system_error.path = bun.String.create(this.source_file_store.pathlike.path.slice()); } - if (system_error.message.len == 0) { - system_error.message = ZigString.init("Failed to copy file"); + if (system_error.message.isEmpty()) { + system_error.message = bun.String.static("Failed to copy file"); } var instance = system_error.toErrorInstance(this.globalThis); diff --git a/src/bun.js/webcore/response.zig b/src/bun.js/webcore/response.zig index b4ea08579..e888ffa5a 100644 --- a/src/bun.js/webcore/response.zig +++ b/src/bun.js/webcore/response.zig @@ -777,15 +777,15 @@ pub const Fetch = struct { } const fetch_error = JSC.SystemError{ - .code = ZigString.init(@errorName(this.result.fail)), + .code = bun.String.static(@errorName(this.result.fail)), .message = switch (this.result.fail) { - error.ConnectionClosed => ZigString.init("The socket connection was closed unexpectedly. For more information, pass `verbose: true` in the second argument to fetch()"), - error.FailedToOpenSocket => ZigString.init("Was there a typo in the url or port?"), - error.TooManyRedirects => ZigString.init("The response redirected too many times. For more information, pass `verbose: true` in the second argument to fetch()"), - error.ConnectionRefused => ZigString.init("Unable to connect. Is the computer able to access the url?"), - else => ZigString.init("fetch() failed. For more information, pass `verbose: true` in the second argument to fetch()"), + error.ConnectionClosed => bun.String.static("The socket connection was closed unexpectedly. For more information, pass `verbose: true` in the second argument to fetch()"), + error.FailedToOpenSocket => bun.String.static("Was there a typo in the url or port?"), + error.TooManyRedirects => bun.String.static("The response redirected too many times. For more information, pass `verbose: true` in the second argument to fetch()"), + error.ConnectionRefused => bun.String.static("Unable to connect. Is the computer able to access the url?"), + else => bun.String.static("fetch() failed. For more information, pass `verbose: true` in the second argument to fetch()"), }, - .path = ZigString.init(this.http.?.url.href), + .path = bun.String.create(this.http.?.url.href), }; return fetch_error.toErrorInstance(this.global_this); diff --git a/src/bun.js/webcore/streams.zig b/src/bun.js/webcore/streams.zig index 5986afac7..343ce37ab 100644 --- a/src/bun.js/webcore/streams.zig +++ b/src/bun.js/webcore/streams.zig @@ -1964,10 +1964,10 @@ pub fn NewJSSink(comptime SinkType: type, comptime name_: []const u8) type { pub const message = std.fmt.comptimePrint("{s} is not constructable", .{SinkType.name}); }; const err = JSC.SystemError{ - .message = ZigString.init(Static.message), - .code = ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_ILLEGAL_CONSTRUCTOR))), + .message = bun.String.static(Static.message), + .code = bun.String.static(@as(string, @tagName(JSC.Node.ErrorCode.ERR_ILLEGAL_CONSTRUCTOR))), }; - globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis)); + globalThis.throwValue(err.toErrorInstance(globalThis)); return JSC.JSValue.jsUndefined(); } diff --git a/src/bundler/bundle_v2.zig b/src/bundler/bundle_v2.zig index 814e49a20..f534e4184 100644 --- a/src/bundler/bundle_v2.zig +++ b/src/bundler/bundle_v2.zig @@ -9174,8 +9174,10 @@ const LinkerContext = struct { }, )) { .err => |err| { + var message = err.toSystemError().message.toUTF8(bun.default_allocator); + defer message.deinit(); c.log.addErrorFmt(null, Logger.Loc.Empty, bun.default_allocator, "{} writing sourcemap for chunk {}", .{ - bun.fmt.quote(err.toSystemError().message.slice()), + bun.fmt.quote(message.slice()), bun.fmt.quote(chunk.final_rel_path), }) catch unreachable; return error.WriteFailed; @@ -9242,8 +9244,10 @@ const LinkerContext = struct { }, )) { .err => |err| { + var message = err.toSystemError().message.toUTF8(bun.default_allocator); + defer message.deinit(); c.log.addErrorFmt(null, Logger.Loc.Empty, bun.default_allocator, "{} writing chunk {}", .{ - bun.fmt.quote(err.toSystemError().message.slice()), + bun.fmt.quote(message.slice()), bun.fmt.quote(chunk.final_rel_path), }) catch unreachable; return error.WriteFailed; @@ -9309,8 +9313,10 @@ const LinkerContext = struct { }, )) { .err => |err| { + const utf8 = err.toSystemError().message.toUTF8(bun.default_allocator); + defer utf8.deinit(); c.log.addErrorFmt(null, Logger.Loc.Empty, bun.default_allocator, "{} writing chunk {}", .{ - bun.fmt.quote(err.toSystemError().message.slice()), + bun.fmt.quote(utf8.slice()), bun.fmt.quote(components_manifest_path), }) catch unreachable; return error.WriteFailed; @@ -9383,8 +9389,10 @@ const LinkerContext = struct { }, )) { .err => |err| { + const utf8 = err.toSystemError().message.toUTF8(bun.default_allocator); + defer utf8.deinit(); c.log.addErrorFmt(null, Logger.Loc.Empty, bun.default_allocator, "{} writing file {}", .{ - bun.fmt.quote(err.toSystemError().message.slice()), + bun.fmt.quote(utf8.slice()), bun.fmt.quote(src.src_path.text), }) catch unreachable; return error.WriteFailed; diff --git a/src/http.zig b/src/http.zig index 80718db2f..b1d97c382 100644 --- a/src/http.zig +++ b/src/http.zig @@ -684,8 +684,9 @@ pub const RequestContext = struct { if (erro == error.EBADF or erro == error.ECONNABORTED or erro == error.ECONNREFUSED) { return error.SocketClosed; } - - Output.prettyErrorln("send() error: {s}", .{err.toSystemError().message.slice()}); + const msg = err.toSystemError().message.toUTF8(bun.default_allocator); + defer msg.deinit(); + Output.prettyErrorln("send() error: {s}", .{msg.slice()}); return erro; }, diff --git a/src/napi/napi.zig b/src/napi/napi.zig index 0973ca559..439319489 100644 --- a/src/napi/napi.zig +++ b/src/napi/napi.zig @@ -303,16 +303,7 @@ pub export fn napi_create_string_utf16(env: napi_env, str: [*]const char16_t, le return .ok; } pub extern fn napi_create_symbol(env: napi_env, description: napi_value, result: *napi_value) napi_status; -pub export fn napi_create_error(env: napi_env, code: napi_value, msg: napi_value, result: *napi_value) napi_status { - log("napi_create_error: \"{any}\"", .{msg.getZigString(env)}); - const system_error = JSC.SystemError{ - .code = if (!code.isEmptyOrUndefinedOrNull()) code.getZigString(env) else ZigString.Empty, - .message = msg.getZigString(env), - }; - result.* = system_error.toErrorInstance(env); - return .ok; -} - +pub extern fn napi_create_error(env: napi_env, code: napi_value, msg: napi_value, result: *napi_value) napi_status; pub extern fn napi_create_type_error(env: napi_env, code: napi_value, msg: napi_value, result: *napi_value) napi_status; pub extern fn napi_create_range_error(env: napi_env, code: napi_value, msg: napi_value, result: *napi_value) napi_status; pub extern fn napi_typeof(env: napi_env, value: napi_value, result: *napi_valuetype) napi_status; diff --git a/test/js/bun/util/error-gc-test.test.js b/test/js/bun/util/error-gc-test.test.js index 247bd68ef..4a45346b6 100644 --- a/test/js/bun/util/error-gc-test.test.js +++ b/test/js/bun/util/error-gc-test.test.js @@ -1,5 +1,5 @@ import { test, expect } from "bun:test"; - +import { readFileSync } from "fs"; // This test checks that printing stack traces increments and decrements // reference-counted strings test("error gc test", () => { @@ -34,7 +34,7 @@ test("error gc test #2", () => { } }); -test("error gc test #2", () => { +test("error gc test #3", () => { for (let i = 0; i < 1000; i++) { var err = new Error(); Error.captureStackTrace(err); @@ -42,3 +42,40 @@ test("error gc test #2", () => { Bun.gc(); } }); + +// This test fails if: +// - it crashes +// - The test failure message gets a non-sensical error +test("error gc test #4", () => { + for (let i = 0; i < 1000; i++) { + let path = + // Use a long-enough string for it to be obvious if we leak memory + "/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/ii/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/ii/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i/don/t/exist/tmp/i"; + try { + readFileSync(path); + throw new Error("unreachable"); + } catch (e) { + if (e.message === "unreachable") { + throw e; + } + + const inspected = Bun.inspect(e); + Bun.gc(true); + + // Deliberately avoid using .toContain() directly to avoid + // BunString shenanigins. + // + // Only JSC builtin functions to operate on the string after inspecting it. + // + if (!inspected.includes(path)) { + expect(inspected).toContain(path); + } + + if (!inspected.includes("ENOENT")) { + expect(inspected).toContain("ENOENT"); + } + } finally { + Bun.gc(true); + } + } +}); -- cgit v1.2.3