aboutsummaryrefslogtreecommitdiff
path: root/src/bun.js/bindings/exports.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/bun.js/bindings/exports.zig')
-rw-r--r--src/bun.js/bindings/exports.zig2548
1 files changed, 2548 insertions, 0 deletions
diff --git a/src/bun.js/bindings/exports.zig b/src/bun.js/bindings/exports.zig
new file mode 100644
index 000000000..b442be742
--- /dev/null
+++ b/src/bun.js/bindings/exports.zig
@@ -0,0 +1,2548 @@
+const JSC = @import("../../jsc.zig");
+const Fs = @import("../../fs.zig");
+const CAPI = JSC.C;
+const JS = @import("../javascript.zig");
+const JSBase = @import("../base.zig");
+const ZigURL = @import("../../url.zig").URL;
+const Api = @import("../../api/schema.zig").Api;
+const bun = @import("../../global.zig");
+const std = @import("std");
+const Shimmer = @import("./shimmer.zig").Shimmer;
+const strings = @import("strings");
+const default_allocator = bun.default_allocator;
+const NewGlobalObject = JSC.NewGlobalObject;
+const JSGlobalObject = JSC.JSGlobalObject;
+const is_bindgen: bool = std.meta.globalOption("bindgen", bool) orelse false;
+const ZigString = JSC.ZigString;
+const string = bun.string;
+const JSValue = JSC.JSValue;
+const Output = bun.Output;
+const Environment = bun.Environment;
+const ScriptArguments = JSC.ScriptArguments;
+const JSPromise = JSC.JSPromise;
+const JSPromiseRejectionOperation = JSC.JSPromiseRejectionOperation;
+const Exception = JSC.Exception;
+const JSModuleLoader = JSC.JSModuleLoader;
+const JSModuleRecord = JSC.JSModuleRecord;
+const Microtask = JSC.Microtask;
+const JSPrivateDataPtr = @import("../base.zig").JSPrivateDataPtr;
+const Backtrace = @import("../../deps/backtrace.zig");
+const JSPrinter = @import("../../js_printer.zig");
+const JSLexer = @import("../../js_lexer.zig");
+pub const ZigGlobalObject = extern struct {
+ pub const shim = Shimmer("Zig", "GlobalObject", @This());
+ bytes: shim.Bytes,
+ pub const Type = *anyopaque;
+ pub const name = "Zig::GlobalObject";
+ pub const include = "\"ZigGlobalObject.h\"";
+ pub const namespace = shim.namespace;
+ pub const Interface: type = NewGlobalObject(JS.VirtualMachine);
+
+ pub fn create(class_ref: [*]CAPI.JSClassRef, count: i32, console: *anyopaque) *JSGlobalObject {
+ var global = shim.cppFn("create", .{ class_ref, count, console });
+ Backtrace.reloadHandlers();
+ return global;
+ }
+
+ pub fn getModuleRegistryMap(global: *JSGlobalObject) *anyopaque {
+ return shim.cppFn("getModuleRegistryMap", .{global});
+ }
+
+ pub fn resetModuleRegistryMap(global: *JSGlobalObject, map: *anyopaque) bool {
+ return shim.cppFn("resetModuleRegistryMap", .{ global, map });
+ }
+
+ pub fn import(global: *JSGlobalObject, specifier: *ZigString, source: *ZigString) callconv(.C) ErrorableZigString {
+ if (comptime is_bindgen) {
+ unreachable;
+ }
+
+ return @call(.{ .modifier = .always_inline }, Interface.import, .{ global, specifier, source });
+ }
+ pub fn resolve(res: *ErrorableZigString, global: *JSGlobalObject, specifier: *ZigString, source: *ZigString) callconv(.C) void {
+ if (comptime is_bindgen) {
+ unreachable;
+ }
+ @call(.{ .modifier = .always_inline }, Interface.resolve, .{ res, global, specifier, source });
+ }
+ pub fn fetch(ret: *ErrorableResolvedSource, global: *JSGlobalObject, specifier: *ZigString, source: *ZigString) callconv(.C) void {
+ if (comptime is_bindgen) {
+ unreachable;
+ }
+ @call(.{ .modifier = .always_inline }, Interface.fetch, .{ ret, global, specifier, source });
+ }
+
+ pub fn promiseRejectionTracker(global: *JSGlobalObject, promise: *JSPromise, rejection: JSPromiseRejectionOperation) callconv(.C) JSValue {
+ if (comptime is_bindgen) {
+ unreachable;
+ }
+ return @call(.{ .modifier = .always_inline }, Interface.promiseRejectionTracker, .{ global, promise, rejection });
+ }
+
+ pub fn reportUncaughtException(global: *JSGlobalObject, exception: *Exception) callconv(.C) JSValue {
+ if (comptime is_bindgen) {
+ unreachable;
+ }
+ return @call(.{ .modifier = .always_inline }, Interface.reportUncaughtException, .{ global, exception });
+ }
+
+ pub fn createImportMetaProperties(global: *JSGlobalObject, loader: *JSModuleLoader, obj: JSValue, record: *JSModuleRecord, specifier: JSValue) callconv(.C) JSValue {
+ if (comptime is_bindgen) {
+ unreachable;
+ }
+ return @call(.{ .modifier = .always_inline }, Interface.createImportMetaProperties, .{ global, loader, obj, record, specifier });
+ }
+
+ pub fn onCrash() callconv(.C) void {
+ if (comptime is_bindgen) {
+ unreachable;
+ }
+ return @call(.{ .modifier = .always_inline }, Interface.onCrash, .{});
+ }
+
+ pub fn queueMicrotaskToEventLoop(global: *JSGlobalObject, microtask: *Microtask) callconv(.C) void {
+ if (comptime is_bindgen) {
+ unreachable;
+ }
+ return @call(.{ .modifier = .always_inline }, Interface.queueMicrotaskToEventLoop, .{ global, microtask });
+ }
+
+ pub const Export = shim.exportFunctions(
+ .{
+ .@"import" = import,
+ .@"resolve" = resolve,
+ .@"fetch" = fetch,
+ // .@"eval" = eval,
+ .@"promiseRejectionTracker" = promiseRejectionTracker,
+ .@"reportUncaughtException" = reportUncaughtException,
+ .@"createImportMetaProperties" = createImportMetaProperties,
+ .@"onCrash" = onCrash,
+ .@"queueMicrotaskToEventLoop" = queueMicrotaskToEventLoop,
+ },
+ );
+
+ pub const Extern = [_][]const u8{ "create", "getModuleRegistryMap", "resetModuleRegistryMap" };
+
+ comptime {
+ @export(import, .{ .name = Export[0].symbol_name });
+ @export(resolve, .{ .name = Export[1].symbol_name });
+ @export(fetch, .{ .name = Export[2].symbol_name });
+ @export(promiseRejectionTracker, .{ .name = Export[3].symbol_name });
+ @export(reportUncaughtException, .{ .name = Export[4].symbol_name });
+ @export(createImportMetaProperties, .{ .name = Export[5].symbol_name });
+ @export(onCrash, .{ .name = Export[6].symbol_name });
+ @export(queueMicrotaskToEventLoop, .{ .name = Export[7].symbol_name });
+ }
+};
+
+const ErrorCodeInt = u16;
+
+pub const ErrorCode = enum(ErrorCodeInt) {
+ _,
+
+ pub inline fn from(code: anyerror) ErrorCode {
+ return @intToEnum(ErrorCode, @errorToInt(code));
+ }
+
+ pub const ParserError = @enumToInt(ErrorCode.from(error.ParserError));
+ pub const JSErrorObject = @enumToInt(ErrorCode.from(error.JSErrorObject));
+
+ pub const Type = ErrorCodeInt;
+};
+
+pub const ZigErrorType = extern struct {
+ pub const shim = Shimmer("Zig", "ErrorType", @This());
+ pub const name = "ErrorType";
+ pub const namespace = shim.namespace;
+
+ code: ErrorCode,
+ ptr: ?*anyopaque,
+
+ pub fn isPrivateData(ptr: ?*anyopaque) callconv(.C) bool {
+ return JSBase.JSPrivateDataPtr.isValidPtr(ptr);
+ }
+
+ pub const Export = shim.exportFunctions(.{
+ .@"isPrivateData" = isPrivateData,
+ });
+
+ comptime {
+ @export(isPrivateData, .{
+ .name = Export[0].symbol_name,
+ });
+ }
+};
+
+/// do not use this reference directly, use JSC.Node.Readable
+pub const NodeReadableStream = JSC.Node.Readable.State;
+/// do not use this reference directly, use JSC.Node.Writable
+pub const NodeWritableStream = JSC.Node.Writable.State;
+pub const NodePath = JSC.Node.Path;
+
+// Web Streams
+pub const JSReadableStreamBlob = JSC.WebCore.ByteBlobLoader.Source.JSReadableStreamSource;
+pub const JSReadableStreamFile = JSC.WebCore.FileBlobLoader.Source.JSReadableStreamSource;
+
+// Sinks
+pub const JSArrayBufferSink = JSC.WebCore.ArrayBufferSink.JSSink;
+
+// WebSocket
+pub const WebSocketHTTPClient = @import("../../http/websocket_http_client.zig").WebSocketHTTPClient;
+pub const WebSocketHTTSPClient = @import("../../http/websocket_http_client.zig").WebSocketHTTPSClient;
+pub const WebSocketClient = @import("../../http/websocket_http_client.zig").WebSocketClient;
+pub const WebSocketClientTLS = @import("../../http/websocket_http_client.zig").WebSocketClientTLS;
+
+pub fn Errorable(comptime Type: type) type {
+ return extern struct {
+ result: Result,
+ success: bool,
+ pub const name = "Errorable" ++ @typeName(Type);
+
+ pub const Result = extern union {
+ value: Type,
+ err: ZigErrorType,
+ };
+
+ pub fn value(val: Type) @This() {
+ return @This(){ .result = .{ .value = val }, .success = true };
+ }
+
+ pub fn ok(val: Type) @This() {
+ return @This(){ .result = .{ .value = val }, .success = true };
+ }
+
+ threadlocal var err_buf: [4096]u8 = undefined;
+ pub fn err(code: anyerror, ptr: *anyopaque) @This() {
+ return @This(){
+ .result = .{
+ .err = .{
+ .code = ErrorCode.from(code),
+ .ptr = ptr,
+ },
+ },
+ .success = false,
+ };
+ }
+ };
+}
+
+pub const ResolvedSource = extern struct {
+ pub const shim = Shimmer("Zig", "ResolvedSource", @This());
+ pub const name = "ResolvedSource";
+ pub const namespace = shim.namespace;
+
+ specifier: ZigString,
+ source_code: ZigString,
+ source_url: ZigString,
+ hash: u32,
+
+ allocator: ?*anyopaque,
+
+ tag: Tag = Tag.javascript,
+
+ pub const Tag = enum(u64) {
+ javascript = 0,
+ wasm = 1,
+ };
+};
+
+const Mimalloc = @import("../../allocators/mimalloc.zig");
+
+export fn ZigString__free(raw: [*]const u8, len: usize, allocator_: ?*anyopaque) void {
+ var allocator: std.mem.Allocator = @ptrCast(*std.mem.Allocator, @alignCast(@alignOf(*std.mem.Allocator), allocator_ orelse return)).*;
+ var ptr = ZigString.init(raw[0..len]).slice().ptr;
+ if (comptime Environment.allow_assert) {
+ std.debug.assert(Mimalloc.mi_check_owned(ptr));
+ }
+ var str = ptr[0..len];
+
+ allocator.free(str);
+}
+
+export fn ZigString__free_global(ptr: [*]const u8, len: usize) void {
+ if (comptime Environment.allow_assert) {
+ std.debug.assert(Mimalloc.mi_check_owned(ZigString.init(ptr[0..len]).slice().ptr));
+ }
+ // we must untag the string pointer
+ Mimalloc.mi_free(@intToPtr(*anyopaque, @ptrToInt(ZigString.init(ptr[0..len]).slice().ptr)));
+}
+
+export fn Zig__getAPIGlobals(count: *usize) [*]JSC.C.JSClassRef {
+ var globals = JSC.VirtualMachine.getAPIGlobals();
+ count.* = globals.len;
+ return globals.ptr;
+}
+
+export fn Zig__getAPIConstructors(count: *usize, ctx: *JSGlobalObject) [*]const JSValue {
+ var globals = JSC.VirtualMachine.getAPIConstructors(ctx);
+ count.* = globals.len;
+ return globals.ptr;
+}
+
+pub const JSErrorCode = enum(u8) {
+ Error = 0,
+ EvalError = 1,
+ RangeError = 2,
+ ReferenceError = 3,
+ SyntaxError = 4,
+ TypeError = 5,
+ URIError = 6,
+ AggregateError = 7,
+
+ // StackOverflow & OutOfMemoryError is not an ErrorType in "JavaScriptCore/ErrorType.h" within JSC, so the number here is just totally made up
+ OutOfMemoryError = 8,
+ BundlerError = 252,
+ StackOverflow = 253,
+ UserErrorCode = 254,
+ _,
+};
+
+pub const JSRuntimeType = enum(u16) {
+ Nothing = 0x0,
+ Function = 0x1,
+ Undefined = 0x2,
+ Null = 0x4,
+ Boolean = 0x8,
+ AnyInt = 0x10,
+ Number = 0x20,
+ String = 0x40,
+ Object = 0x80,
+ Symbol = 0x100,
+ BigInt = 0x200,
+
+ _,
+};
+
+pub const ZigStackFrameCode = enum(u8) {
+ None = 0,
+ // 🏃
+ Eval = 1,
+ // 📦
+ Module = 2,
+ // λ
+ Function = 3,
+ // 🌎
+ Global = 4,
+ // ⚙️
+ Wasm = 5,
+ // 👷
+ Constructor = 6,
+ _,
+
+ pub fn emoji(this: ZigStackFrameCode) u21 {
+ return switch (this) {
+ .Eval => 0x1F3C3,
+ .Module => 0x1F4E6,
+ .Function => 0x03BB,
+ .Global => 0x1F30E,
+ .Wasm => 0xFE0F,
+ .Constructor => 0xF1477,
+ else => ' ',
+ };
+ }
+
+ pub fn ansiColor(this: ZigStackFrameCode) string {
+ return switch (this) {
+ .Eval => "\x1b[31m",
+ .Module => "\x1b[36m",
+ .Function => "\x1b[32m",
+ .Global => "\x1b[35m",
+ .Wasm => "\x1b[37m",
+ .Constructor => "\x1b[33m",
+ else => "",
+ };
+ }
+};
+
+pub const Process = extern struct {
+ pub const shim = Shimmer("Bun", "Process", @This());
+ pub const name = "Process";
+ pub const namespace = shim.namespace;
+ const _bun: string = "bun";
+
+ pub fn getTitle(_: *JSGlobalObject, title: *ZigString) callconv(.C) void {
+ title.* = ZigString.init(_bun);
+ }
+
+ // TODO: https://github.com/nodejs/node/blob/master/deps/uv/src/unix/darwin-proctitle.c
+ pub fn setTitle(globalObject: *JSGlobalObject, _: *ZigString) callconv(.C) JSValue {
+ return ZigString.init(_bun).toValue(globalObject);
+ }
+
+ pub const getArgv = JSC.Node.Process.getArgv;
+ pub const getCwd = JSC.Node.Process.getCwd;
+ pub const setCwd = JSC.Node.Process.setCwd;
+ pub const exit = JSC.Node.Process.exit;
+
+ pub const Export = shim.exportFunctions(.{
+ .@"getTitle" = getTitle,
+ .@"setTitle" = setTitle,
+ .@"getArgv" = getArgv,
+ .@"getCwd" = getCwd,
+ .@"setCwd" = setCwd,
+ .@"exit" = exit,
+ });
+
+ comptime {
+ if (!is_bindgen) {
+ @export(getTitle, .{
+ .name = Export[0].symbol_name,
+ });
+ @export(setTitle, .{
+ .name = Export[1].symbol_name,
+ });
+ @export(getArgv, .{
+ .name = Export[2].symbol_name,
+ });
+ @export(getCwd, .{
+ .name = Export[3].symbol_name,
+ });
+ @export(setCwd, .{
+ .name = Export[4].symbol_name,
+ });
+ @export(exit, .{
+ .name = Export[5].symbol_name,
+ });
+ }
+ }
+};
+
+pub const ZigStackTrace = extern struct {
+ source_lines_ptr: [*c]ZigString,
+ source_lines_numbers: [*c]i32,
+ source_lines_len: u8,
+ source_lines_to_collect: u8,
+
+ frames_ptr: [*c]ZigStackFrame,
+ frames_len: u8,
+
+ pub fn toAPI(
+ this: *const ZigStackTrace,
+ allocator: std.mem.Allocator,
+ root_path: string,
+ origin: ?*const ZigURL,
+ ) !Api.StackTrace {
+ var stack_trace: Api.StackTrace = comptime std.mem.zeroes(Api.StackTrace);
+ {
+ 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;
+ }
+
+ if (count > 0 and source_line_len > 0) {
+ var source_lines = try allocator.alloc(Api.SourceLine, count);
+ 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| {
+ std.mem.copy(u8, remain_buf, source.text);
+ const copied_line = remain_buf[0..source.text.len];
+ remain_buf = remain_buf[source.text.len..];
+ source_lines[i] = .{ .text = copied_line, .line = source.line };
+ i += 1;
+ }
+ stack_trace.source_lines = source_lines;
+ }
+ }
+ {
+ var _frames = this.frames();
+ if (_frames.len > 0) {
+ var stack_frames = try allocator.alloc(Api.StackFrame, _frames.len);
+ stack_trace.frames = stack_frames;
+
+ for (_frames) |frame, i| {
+ stack_frames[i] = try frame.toAPI(
+ root_path,
+ origin,
+ allocator,
+ );
+ }
+ }
+ }
+
+ return stack_trace;
+ }
+
+ pub fn frames(this: *const ZigStackTrace) []const ZigStackFrame {
+ return this.frames_ptr[0..this.frames_len];
+ }
+
+ pub const SourceLineIterator = struct {
+ trace: *const ZigStackTrace,
+ i: i16,
+
+ pub const SourceLine = struct {
+ line: i32,
+ text: string,
+ };
+
+ pub fn untilLast(this: *SourceLineIterator) ?SourceLine {
+ if (this.i < 1) return null;
+ return this.next();
+ }
+
+ pub fn next(this: *SourceLineIterator) ?SourceLine {
+ if (this.i < 0) return null;
+
+ 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(),
+ };
+ this.i -= 1;
+ return result;
+ }
+ };
+
+ pub fn sourceLineIterator(this: *const ZigStackTrace) SourceLineIterator {
+ var i: usize = 0;
+ for (this.source_lines_numbers[0..this.source_lines_len]) |num, j| {
+ if (num > 0) {
+ i = j;
+ }
+ }
+ return SourceLineIterator{ .trace = this, .i = @intCast(i16, i) };
+ }
+};
+
+pub const ZigStackFrame = extern struct {
+ function_name: ZigString,
+ source_url: ZigString,
+ position: ZigStackFramePosition,
+ code_type: ZigStackFrameCode,
+
+ /// This informs formatters whether to display as a blob URL or not
+ remapped: bool = false,
+
+ 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.source_url.len > 0) {
+ frame.file = try std.fmt.allocPrint(allocator, "{any}", .{this.sourceURLFormatter(root_path, origin, true, false)});
+ }
+
+ frame.position.source_offset = this.position.source_offset;
+
+ // For remapped code, we add 1 to the line number
+ frame.position.line = this.position.line + @as(i32, @boolToInt(this.remapped));
+
+ frame.position.line_start = this.position.line_start;
+ frame.position.line_stop = this.position.line_stop;
+ frame.position.column_start = this.position.column_start;
+ frame.position.column_stop = this.position.column_stop;
+ frame.position.expression_start = this.position.expression_start;
+ frame.position.expression_stop = this.position.expression_stop;
+ frame.scope = @intToEnum(Api.StackFrameScope, @enumToInt(this.code_type));
+
+ return frame;
+ }
+
+ pub const SourceURLFormatter = struct {
+ source_url: ZigString,
+ position: ZigStackFramePosition,
+ enable_color: bool,
+ origin: ?*const ZigURL,
+ exclude_line_column: bool = false,
+ remapped: bool = false,
+ root_path: string = "",
+ pub fn format(this: SourceURLFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
+ if (this.enable_color) {
+ try writer.writeAll(Output.prettyFmt("<r><cyan>", true));
+ }
+
+ var source_slice = this.source_url.slice();
+
+ if (!this.remapped) {
+ if (this.origin) |origin| {
+ try writer.writeAll(origin.displayProtocol());
+ try writer.writeAll("://");
+ try writer.writeAll(origin.displayHostname());
+ try writer.writeAll(":");
+ try writer.writeAll(origin.port);
+ try writer.writeAll("/blob:");
+
+ if (strings.startsWith(source_slice, this.root_path)) {
+ source_slice = source_slice[this.root_path.len..];
+ }
+ }
+ }
+
+ try writer.writeAll(source_slice);
+
+ if (this.enable_color) {
+ if (this.position.line > -1) {
+ try writer.writeAll(comptime Output.prettyFmt("<r>", true));
+ } else {
+ try writer.writeAll(comptime Output.prettyFmt("<r>", true));
+ }
+ }
+
+ if (!this.exclude_line_column) {
+ if (this.position.line > -1 and this.position.column_start > -1) {
+ if (this.enable_color) {
+ try std.fmt.format(
+ writer,
+ // :
+ comptime Output.prettyFmt("<d>:<r><yellow>{d}<r><d>:<yellow>{d}<r>", true),
+ .{ this.position.line + 1, this.position.column_start },
+ );
+ } else {
+ try std.fmt.format(writer, ":{d}:{d}", .{ this.position.line + 1, this.position.column_start });
+ }
+ } else if (this.position.line > -1) {
+ if (this.enable_color) {
+ try std.fmt.format(
+ writer,
+ comptime Output.prettyFmt("<d>:<r><yellow>{d}<r>", true),
+ .{
+ this.position.line + 1,
+ },
+ );
+ } else {
+ try std.fmt.format(writer, ":{d}", .{
+ this.position.line + 1,
+ });
+ }
+ }
+ }
+ }
+ };
+
+ pub const NameFormatter = struct {
+ function_name: ZigString,
+ 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();
+
+ switch (this.code_type) {
+ .Eval => {
+ try writer.writeAll("(eval)");
+ },
+ .Module => {
+ // try writer.writeAll("(esm)");
+ },
+ .Function => {
+ if (name.len > 0) {
+ if (this.enable_color) {
+ try std.fmt.format(writer, comptime Output.prettyFmt("<r><b><i>{s}<r>", true), .{name});
+ } else {
+ try std.fmt.format(writer, "{s}", .{name});
+ }
+ }
+ },
+ .Global => {
+ if (name.len > 0) {
+ try std.fmt.format(writer, "globalThis {s}", .{name});
+ } else {
+ try writer.writeAll("globalThis");
+ }
+ },
+ .Wasm => {
+ try std.fmt.format(writer, "WASM {s}", .{name});
+ },
+ .Constructor => {
+ try std.fmt.format(writer, "new {s}", .{name});
+ },
+ else => {},
+ }
+ }
+ };
+
+ pub const Zero: ZigStackFrame = ZigStackFrame{
+ .function_name = ZigString{ .ptr = "", .len = 0 },
+ .code_type = ZigStackFrameCode.None,
+ .source_url = ZigString{ .ptr = "", .len = 0 },
+ .position = ZigStackFramePosition.Invalid,
+ };
+
+ pub fn nameFormatter(this: *const ZigStackFrame, comptime enable_color: bool) NameFormatter {
+ return NameFormatter{ .function_name = this.function_name, .code_type = this.code_type, .enable_color = enable_color };
+ }
+
+ pub fn sourceURLFormatter(this: *const ZigStackFrame, root_path: string, origin: ?*const ZigURL, exclude_line_column: bool, comptime enable_color: bool) SourceURLFormatter {
+ return SourceURLFormatter{
+ .source_url = this.source_url,
+ .exclude_line_column = exclude_line_column,
+ .origin = origin,
+ .root_path = root_path,
+ .position = this.position,
+ .enable_color = enable_color,
+ .remapped = this.remapped,
+ };
+ }
+};
+
+pub const ZigStackFramePosition = extern struct {
+ source_offset: i32,
+ line: i32,
+ line_start: i32,
+ line_stop: i32,
+ column_start: i32,
+ column_stop: i32,
+ expression_start: i32,
+ expression_stop: i32,
+
+ pub const Invalid = ZigStackFramePosition{
+ .source_offset = -1,
+ .line = -1,
+ .line_start = -1,
+ .line_stop = -1,
+ .column_start = -1,
+ .column_stop = -1,
+ .expression_start = -1,
+ .expression_stop = -1,
+ };
+ pub fn isInvalid(this: *const ZigStackFramePosition) bool {
+ return std.mem.eql(u8, std.mem.asBytes(this), std.mem.asBytes(&Invalid));
+ }
+};
+
+pub const ZigException = extern struct {
+ code: JSErrorCode,
+ runtime_type: JSRuntimeType,
+
+ /// SystemError only
+ errno: c_int = 0,
+ /// SystemError only
+ syscall: ZigString = ZigString.Empty,
+ /// SystemError only
+ system_code: ZigString = ZigString.Empty,
+ /// SystemError only
+ path: ZigString = ZigString.Empty,
+
+ name: ZigString,
+ message: ZigString,
+ stack: ZigStackTrace,
+
+ exception: ?*anyopaque,
+
+ remapped: bool = false,
+
+ pub const shim = Shimmer("Zig", "Exception", @This());
+ pub const name = "ZigException";
+ pub const namespace = shim.namespace;
+
+ pub const Holder = extern struct {
+ const frame_count = 24;
+ pub const source_lines_count = 6;
+ source_line_numbers: [source_lines_count]i32,
+ source_lines: [source_lines_count]ZigString,
+ frames: [frame_count]ZigStackFrame,
+ loaded: bool,
+ zig_exception: ZigException,
+
+ pub const Zero: Holder = Holder{
+ .frames = brk: {
+ var _frames: [frame_count]ZigStackFrame = undefined;
+ std.mem.set(ZigStackFrame, &_frames, ZigStackFrame.Zero);
+ break :brk _frames;
+ },
+ .source_line_numbers = brk: {
+ var lines: [source_lines_count]i32 = undefined;
+ std.mem.set(i32, &lines, -1);
+ break :brk lines;
+ },
+
+ .source_lines = brk: {
+ var lines: [source_lines_count]ZigString = undefined;
+ std.mem.set(ZigString, &lines, ZigString.Empty);
+ break :brk lines;
+ },
+ .zig_exception = undefined,
+ .loaded = false,
+ };
+
+ pub fn init() Holder {
+ return Holder.Zero;
+ }
+
+ pub fn zigException(this: *Holder) *ZigException {
+ if (!this.loaded) {
+ this.zig_exception = ZigException{
+ .code = @intToEnum(JSErrorCode, 255),
+ .runtime_type = JSRuntimeType.Nothing,
+ .name = ZigString.Empty,
+ .message = ZigString.Empty,
+ .exception = null,
+ .stack = ZigStackTrace{
+ .source_lines_ptr = &this.source_lines,
+ .source_lines_numbers = &this.source_line_numbers,
+ .source_lines_len = source_lines_count,
+ .source_lines_to_collect = source_lines_count,
+ .frames_ptr = &this.frames,
+ .frames_len = this.frames.len,
+ },
+ };
+ this.loaded = true;
+ }
+
+ return &this.zig_exception;
+ }
+ };
+
+ pub fn fromException(exception: *Exception) ZigException {
+ return shim.cppFn("fromException", .{exception});
+ }
+
+ pub fn addToErrorList(
+ this: *ZigException,
+ error_list: *std.ArrayList(Api.JsException),
+ root_path: string,
+ origin: ?*const ZigURL,
+ ) !void {
+ const _name: string = @field(this, "name").slice();
+ const message: string = @field(this, "message").slice();
+
+ var is_empty = true;
+ var api_exception = Api.JsException{
+ .runtime_type = @enumToInt(this.runtime_type),
+ .code = @enumToInt(this.code),
+ };
+
+ if (_name.len > 0) {
+ api_exception.name = try error_list.allocator.dupe(u8, _name);
+ is_empty = false;
+ }
+
+ if (message.len > 0) {
+ api_exception.message = try error_list.allocator.dupe(u8, message);
+ is_empty = false;
+ }
+
+ if (this.stack.frames_len > 0) {
+ api_exception.stack = try this.stack.toAPI(error_list.allocator, root_path, origin);
+ is_empty = false;
+ }
+
+ if (!is_empty) {
+ try error_list.append(api_exception);
+ }
+ }
+
+ pub const Extern = [_][]const u8{"fromException"};
+};
+
+pub const ErrorableResolvedSource = Errorable(ResolvedSource);
+pub const ErrorableZigString = Errorable(ZigString);
+pub const ErrorableJSValue = Errorable(JSValue);
+
+pub const ZigConsoleClient = struct {
+ pub const shim = Shimmer("Zig", "ConsoleClient", @This());
+ pub const Type = *anyopaque;
+ pub const name = "Zig::ConsoleClient";
+ pub const include = "\"ZigConsoleClient.h\"";
+ pub const namespace = shim.namespace;
+ pub const Counter = struct {
+ // if it turns out a hash table is a better idea we'll do that later
+ pub const Entry = struct {
+ hash: u32,
+ count: u32,
+
+ pub const List = std.MultiArrayList(Entry);
+ };
+ counts: Entry.List,
+ allocator: std.mem.Allocator,
+ };
+ const BufferedWriter = std.io.BufferedWriter(4096, Output.WriterType);
+ error_writer: BufferedWriter,
+ writer: BufferedWriter,
+
+ pub fn init(error_writer: Output.WriterType, writer: Output.WriterType) ZigConsoleClient {
+ return ZigConsoleClient{
+ .error_writer = BufferedWriter{ .unbuffered_writer = error_writer },
+ .writer = BufferedWriter{ .unbuffered_writer = writer },
+ };
+ }
+
+ pub const MessageLevel = enum(u32) {
+ Log = 0,
+ Warning = 1,
+ Error = 2,
+ Debug = 3,
+ Info = 4,
+ _,
+ };
+
+ pub const MessageType = enum(u32) {
+ Log = 0,
+ Dir = 1,
+ DirXML = 2,
+ Table = 3,
+ Trace = 4,
+ StartGroup = 5,
+ StartGroupCollapsed = 6,
+ EndGroup = 7,
+ Clear = 8,
+ Assert = 9,
+ Timing = 10,
+ Profile = 11,
+ ProfileEnd = 12,
+ Image = 13,
+ _,
+ };
+
+ /// https://console.spec.whatwg.org/#formatter
+ pub fn messageWithTypeAndLevel(
+ //console_: ZigConsoleClient.Type,
+ _: ZigConsoleClient.Type,
+ message_type: MessageType,
+ //message_level: u32,
+ level: MessageLevel,
+ global: *JSGlobalObject,
+ vals: [*]JSValue,
+ len: usize,
+ ) callconv(.C) void {
+ if (comptime is_bindgen) {
+ return;
+ }
+
+ var console = JS.VirtualMachine.vm.console;
+
+ if (message_type == .Clear) {
+ Output.resetTerminal();
+ return;
+ }
+
+ if (message_type == .Assert and len == 0) {
+ const text = if (Output.enable_ansi_colors_stderr)
+ Output.prettyFmt("<r><red>Assertion failed<r>\n", true)
+ else
+ "Assertion failed\n";
+ console.error_writer.unbuffered_writer.writeAll(text) catch unreachable;
+ return;
+ }
+
+ const enable_colors = if (level == .Warning or level == .Error)
+ Output.enable_ansi_colors_stderr
+ else
+ Output.enable_ansi_colors_stdout;
+
+ var buffered_writer = if (level == .Warning or level == .Error)
+ console.error_writer
+ else
+ console.writer;
+ var writer = buffered_writer.writer();
+
+ const Writer = @TypeOf(writer);
+ if (len > 0)
+ format(
+ level,
+ global,
+ vals,
+ len,
+ @TypeOf(buffered_writer.unbuffered_writer.context),
+ Writer,
+ writer,
+ enable_colors,
+ true,
+ true,
+ )
+ else if (message_type != .Trace)
+ writer.writeAll("undefined\n") catch unreachable;
+
+ if (message_type == .Trace) {
+ writeTrace(Writer, writer, global);
+ buffered_writer.flush() catch unreachable;
+ }
+ }
+
+ pub fn writeTrace(comptime Writer: type, writer: Writer, global: *JSGlobalObject) void {
+ var holder = ZigException.Holder.init();
+
+ var exception = holder.zigException();
+ var err = ZigString.init("trace output").toErrorInstance(global);
+ err.toZigException(global, exception);
+ JS.VirtualMachine.vm.remapZigException(exception, err, null);
+
+ if (Output.enable_ansi_colors_stderr)
+ JS.VirtualMachine.printStackTrace(
+ Writer,
+ writer,
+ exception.stack,
+ true,
+ ) catch unreachable
+ else
+ JS.VirtualMachine.printStackTrace(
+ Writer,
+ writer,
+ exception.stack,
+ false,
+ ) catch unreachable;
+ }
+
+ pub fn format(
+ level: MessageLevel,
+ global: *JSGlobalObject,
+ vals: [*]const JSValue,
+ len: usize,
+ comptime RawWriter: type,
+ comptime Writer: type,
+ writer: Writer,
+ enable_colors: bool,
+ add_newline: bool,
+ flush: bool,
+ ) void {
+ var fmt: ZigConsoleClient.Formatter = undefined;
+ defer {
+ if (fmt.map_node) |node| {
+ node.data = fmt.map;
+ node.data.clearRetainingCapacity();
+ node.release();
+ }
+ }
+
+ if (len == 1) {
+ fmt = ZigConsoleClient.Formatter{ .remaining_values = &[_]JSValue{}, .globalThis = global };
+ const tag = ZigConsoleClient.Formatter.Tag.get(vals[0], global);
+
+ var unbuffered_writer = if (comptime Writer != RawWriter)
+ writer.context.unbuffered_writer.context.writer()
+ else
+ writer;
+
+ if (tag.tag == .String) {
+ if (enable_colors) {
+ if (level == .Error) {
+ unbuffered_writer.writeAll(comptime Output.prettyFmt("<r><red>", true)) catch unreachable;
+ }
+ fmt.format(
+ tag,
+ @TypeOf(unbuffered_writer),
+ unbuffered_writer,
+ vals[0],
+ global,
+ true,
+ );
+ if (level == .Error) {
+ unbuffered_writer.writeAll(comptime Output.prettyFmt("<r>", true)) catch unreachable;
+ }
+ } else {
+ fmt.format(
+ tag,
+ @TypeOf(unbuffered_writer),
+ unbuffered_writer,
+ vals[0],
+ global,
+ false,
+ );
+ }
+ if (add_newline) _ = unbuffered_writer.write("\n") catch 0;
+ } else {
+ defer {
+ if (comptime Writer != RawWriter) {
+ if (flush) writer.context.flush() catch {};
+ }
+ }
+ if (enable_colors) {
+ fmt.format(
+ tag,
+ Writer,
+ writer,
+ vals[0],
+ global,
+ true,
+ );
+ } else {
+ fmt.format(
+ tag,
+ Writer,
+ writer,
+ vals[0],
+ global,
+ false,
+ );
+ }
+ if (add_newline) _ = writer.write("\n") catch 0;
+ }
+
+ return;
+ }
+
+ defer {
+ if (comptime Writer != RawWriter) {
+ if (flush) writer.context.flush() catch {};
+ }
+ }
+
+ var this_value: JSValue = vals[0];
+ fmt = ZigConsoleClient.Formatter{ .remaining_values = vals[0..len][1..], .globalThis = global };
+ var tag: ZigConsoleClient.Formatter.Tag.Result = undefined;
+
+ var any = false;
+ if (enable_colors) {
+ if (level == .Error) {
+ writer.writeAll(comptime Output.prettyFmt("<r><red>", true)) catch unreachable;
+ }
+ while (true) {
+ if (any) {
+ _ = writer.write(" ") catch 0;
+ }
+ any = true;
+
+ tag = ZigConsoleClient.Formatter.Tag.get(this_value, global);
+ if (tag.tag == .String and fmt.remaining_values.len > 0) {
+ tag.tag = .StringPossiblyFormatted;
+ }
+
+ fmt.format(tag, Writer, writer, this_value, global, true);
+ if (fmt.remaining_values.len == 0) {
+ break;
+ }
+
+ this_value = fmt.remaining_values[0];
+ fmt.remaining_values = fmt.remaining_values[1..];
+ }
+ if (level == .Error) {
+ writer.writeAll(comptime Output.prettyFmt("<r>", true)) catch unreachable;
+ }
+ } else {
+ while (true) {
+ if (any) {
+ _ = writer.write(" ") catch 0;
+ }
+ any = true;
+ tag = ZigConsoleClient.Formatter.Tag.get(this_value, global);
+ if (tag.tag == .String and fmt.remaining_values.len > 0) {
+ tag.tag = .StringPossiblyFormatted;
+ }
+
+ fmt.format(tag, Writer, writer, this_value, global, false);
+ if (fmt.remaining_values.len == 0)
+ break;
+
+ this_value = fmt.remaining_values[0];
+ fmt.remaining_values = fmt.remaining_values[1..];
+ }
+ }
+
+ if (add_newline) _ = writer.write("\n") catch 0;
+ }
+
+ pub const Formatter = struct {
+ remaining_values: []const JSValue = &[_]JSValue{},
+ map: Visited.Map = undefined,
+ map_node: ?*Visited.Pool.Node = null,
+ hide_native: bool = false,
+ globalThis: *JSGlobalObject,
+ indent: u32 = 0,
+ quote_strings: bool = false,
+
+ pub const ZigFormatter = struct {
+ formatter: *ZigConsoleClient.Formatter,
+ global: *JSGlobalObject,
+ value: JSValue,
+
+ pub const WriteError = error{UhOh};
+ pub fn format(self: ZigFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
+ self.formatter.remaining_values = &[_]JSValue{self.value};
+ defer {
+ self.formatter.remaining_values = &[_]JSValue{};
+ }
+ self.formatter.globalThis = self.global;
+ self.formatter.format(
+ Tag.get(self.value, self.global),
+ @TypeOf(writer),
+ writer,
+ self.value,
+ self.formatter.globalThis,
+ false,
+ );
+ }
+ };
+
+ // For detecting circular references
+ pub const Visited = struct {
+ const ObjectPool = @import("../../pool.zig").ObjectPool;
+ pub const Map = std.AutoHashMap(JSValue.Type, void);
+ pub const Pool = ObjectPool(
+ Map,
+ struct {
+ pub fn init(allocator: std.mem.Allocator) anyerror!Map {
+ return Map.init(allocator);
+ }
+ }.init,
+ true,
+ 16,
+ );
+ };
+
+ pub const Tag = enum {
+ StringPossiblyFormatted,
+ String,
+ Undefined,
+ Double,
+ Integer,
+ Null,
+ Boolean,
+ Array,
+ Object,
+ Function,
+ Class,
+ Error,
+ TypedArray,
+ Map,
+ Set,
+ Symbol,
+ BigInt,
+
+ GlobalObject,
+ Private,
+ Promise,
+
+ JSON,
+ NativeCode,
+ ArrayBuffer,
+
+ JSX,
+
+ pub inline fn canHaveCircularReferences(tag: Tag) bool {
+ return tag == .Array or tag == .Object or tag == .Map or tag == .Set;
+ }
+
+ const Result = struct {
+ tag: Tag,
+ cell: JSValue.JSType = JSValue.JSType.Cell,
+ };
+
+ pub fn get(value: JSValue, globalThis: *JSGlobalObject) Result {
+ switch (@enumToInt(value)) {
+ 0, 0xa => return Result{
+ .tag = .Undefined,
+ },
+ 0x2 => return Result{
+ .tag = .Null,
+ },
+ else => {},
+ }
+
+ if (value.isInt32()) {
+ return .{
+ .tag = .Integer,
+ };
+ } else if (value.isNumber()) {
+ return .{
+ .tag = .Double,
+ };
+ } else if (value.isBoolean()) {
+ return .{
+ .tag = .Boolean,
+ };
+ } else if (value.isSymbol()) {
+ return .{
+ .tag = .Symbol,
+ .cell = .Symbol,
+ };
+ }
+
+ const js_type = value.jsType();
+
+ if (js_type.isHidden()) return .{
+ .tag = .NativeCode,
+ .cell = js_type,
+ };
+
+ // Cell is the "unknown" type
+ // if we call JSObjectGetPrivate, it can segfault
+ if (js_type == .Cell) {
+ return .{
+ .tag = .NativeCode,
+ .cell = js_type,
+ };
+ }
+
+ if (CAPI.JSObjectGetPrivate(value.asObjectRef()) != null)
+ return .{
+ .tag = .Private,
+ .cell = js_type,
+ };
+
+ // If we check an Object has a method table and it does not
+ // it will crash
+ const callable = js_type != .Object and value.isCallable(globalThis.vm());
+
+ if (value.isClass(globalThis) and !callable) {
+ // Temporary workaround
+ // console.log(process.env) shows up as [class JSCallbackObject]
+ // We want to print it like an object
+ if (CAPI.JSValueIsObjectOfClass(globalThis.ref(), value.asObjectRef(), JSC.API.Bun.EnvironmentVariables.Class.get().?[0])) {
+ return .{
+ .tag = .Object,
+ .cell = js_type,
+ };
+ }
+
+ return .{
+ .tag = .Object,
+ .cell = js_type,
+ };
+ }
+
+ if (callable) {
+ return .{
+ .tag = .Function,
+ .cell = js_type,
+ };
+ }
+
+ // Is this a react element?
+ if (js_type.isObject()) {
+ if (value.get(globalThis, "$$typeof")) |typeof_symbol| {
+ var reactElement = ZigString.init("react.element");
+ var react_fragment = ZigString.init("react.fragment");
+
+ if (JSValue.isSameValue(typeof_symbol, JSValue.symbolFor(globalThis, &reactElement), globalThis) or JSValue.isSameValue(typeof_symbol, JSValue.symbolFor(globalThis, &react_fragment), globalThis)) {
+ return .{ .tag = .JSX, .cell = js_type };
+ }
+ }
+
+ if (value.as(JSC.DOMURL) != null) {
+ return .{ .tag = .String, .cell = js_type };
+ }
+ }
+
+ return .{
+ .tag = switch (js_type) {
+ JSValue.JSType.ErrorInstance => .Error,
+ JSValue.JSType.NumberObject => .Double,
+ JSValue.JSType.DerivedArray, JSValue.JSType.Array => .Array,
+ JSValue.JSType.DerivedStringObject, JSValue.JSType.String, JSValue.JSType.StringObject => .String,
+ JSValue.JSType.RegExpObject,
+ JSValue.JSType.Symbol,
+ => .String,
+ JSValue.JSType.BooleanObject => .Boolean,
+ JSValue.JSType.JSFunction => .Function,
+ JSValue.JSType.JSWeakMap, JSValue.JSType.JSMap => .Map,
+ JSValue.JSType.JSWeakSet, JSValue.JSType.JSSet => .Set,
+ JSValue.JSType.JSDate => .JSON,
+ JSValue.JSType.JSPromise => .Promise,
+ JSValue.JSType.Object, JSValue.JSType.FinalObject => .Object,
+
+ JSValue.JSType.Int8Array,
+ JSValue.JSType.Uint8Array,
+ JSValue.JSType.Uint8ClampedArray,
+ JSValue.JSType.Int16Array,
+ JSValue.JSType.Uint16Array,
+ JSValue.JSType.Int32Array,
+ JSValue.JSType.Uint32Array,
+ JSValue.JSType.Float32Array,
+ JSValue.JSType.Float64Array,
+ JSValue.JSType.BigInt64Array,
+ JSValue.JSType.BigUint64Array,
+ => .TypedArray,
+
+ .HeapBigInt => .BigInt,
+
+ // None of these should ever exist here
+ // But we're going to check anyway
+ .GetterSetter,
+ .CustomGetterSetter,
+ .APIValueWrapper,
+ .NativeExecutable,
+ .ProgramExecutable,
+ .ModuleProgramExecutable,
+ .EvalExecutable,
+ .FunctionExecutable,
+ .UnlinkedFunctionExecutable,
+ .UnlinkedProgramCodeBlock,
+ .UnlinkedModuleProgramCodeBlock,
+ .UnlinkedEvalCodeBlock,
+ .UnlinkedFunctionCodeBlock,
+ .CodeBlock,
+ .JSImmutableButterfly,
+ .JSSourceCode,
+ .JSScriptFetcher,
+ .JSScriptFetchParameters,
+ .JSCallee,
+ .GlobalLexicalEnvironment,
+ .LexicalEnvironment,
+ .ModuleEnvironment,
+ .StrictEvalActivation,
+ .WithScope,
+ => .NativeCode,
+
+ else => .JSON,
+ },
+ .cell = js_type,
+ };
+ }
+ };
+
+ const CellType = CAPI.CellType;
+ threadlocal var name_buf: [512]u8 = undefined;
+
+ fn writeWithFormatting(
+ this: *ZigConsoleClient.Formatter,
+ comptime Writer: type,
+ writer_: Writer,
+ comptime Slice: type,
+ slice_: Slice,
+ globalThis: *JSGlobalObject,
+ comptime enable_ansi_colors: bool,
+ ) void {
+ var writer = WrappedWriter(Writer){ .ctx = writer_ };
+ var slice = slice_;
+ var i: u32 = 0;
+ var len: u32 = @truncate(u32, slice.len);
+ while (i < len) : (i += 1) {
+ switch (slice[i]) {
+ '%' => {
+ i += 1;
+ if (i >= len)
+ break;
+
+ const token = switch (slice[i]) {
+ 's' => Tag.String,
+ 'f' => Tag.Double,
+ 'o' => Tag.Undefined,
+ 'O' => Tag.Object,
+ 'd', 'i' => Tag.Integer,
+ else => continue,
+ };
+
+ // Flush everything up to the %
+ const end = slice[0 .. i - 1];
+ writer.writeAll(end);
+ slice = slice[@minimum(slice.len, i + 1)..];
+ i = 0;
+ len = @truncate(u32, slice.len);
+ const next_value = this.remaining_values[0];
+ this.remaining_values = this.remaining_values[1..];
+ switch (token) {
+ Tag.String => this.printAs(Tag.String, Writer, writer_, next_value, next_value.jsType(), enable_ansi_colors),
+ Tag.Double => this.printAs(Tag.Double, Writer, writer_, next_value, next_value.jsType(), enable_ansi_colors),
+ Tag.Object => this.printAs(Tag.Object, Writer, writer_, next_value, next_value.jsType(), enable_ansi_colors),
+ Tag.Integer => this.printAs(Tag.Integer, Writer, writer_, next_value, next_value.jsType(), enable_ansi_colors),
+
+ // undefined is overloaded to mean the '%o" field
+ Tag.Undefined => this.format(Tag.get(next_value, globalThis), Writer, writer_, next_value, globalThis, enable_ansi_colors),
+
+ else => unreachable,
+ }
+ if (this.remaining_values.len == 0) break;
+ },
+ '\\' => {
+ i += 1;
+ if (i >= len)
+ break;
+ if (slice[i] == '%') i += 2;
+ },
+ else => {},
+ }
+ }
+
+ if (slice.len > 0) writer.writeAll(slice);
+ }
+
+ pub fn WrappedWriter(comptime Writer: type) type {
+ return struct {
+ ctx: Writer,
+
+ pub fn print(self: *@This(), comptime fmt: string, args: anytype) void {
+ self.ctx.print(fmt, args) catch unreachable;
+ }
+
+ pub inline fn writeAll(self: *@This(), buf: []const u8) void {
+ self.ctx.writeAll(buf) catch unreachable;
+ }
+ };
+ }
+
+ pub fn writeIndent(
+ this: *ZigConsoleClient.Formatter,
+ comptime Writer: type,
+ writer: Writer,
+ ) !void {
+ const indent = @minimum(this.indent, 8);
+ var buf = [_]u8{' '} ** 32;
+ var total_remain: usize = indent;
+ while (total_remain > 0) {
+ const written = @minimum(16, total_remain);
+ try writer.writeAll(buf[0 .. written * 2]);
+ total_remain -|= written;
+ }
+ }
+
+ pub fn printComma(_: *ZigConsoleClient.Formatter, comptime Writer: type, writer: Writer, comptime enable_ansi_colors: bool) !void {
+ try writer.writeAll(comptime Output.prettyFmt("<r><d>,<r>", enable_ansi_colors));
+ }
+
+ pub fn MapIterator(comptime Writer: type, comptime enable_ansi_colors: bool) type {
+ return struct {
+ formatter: *ZigConsoleClient.Formatter,
+ writer: Writer,
+ pub fn forEach(_: [*c]JSC.VM, globalObject: [*c]JSGlobalObject, ctx: ?*anyopaque, nextValue: JSValue) callconv(.C) void {
+ var this: *@This() = bun.cast(*@This(), ctx orelse return);
+ const key = JSC.JSObject.getIndex(nextValue, globalObject, 0);
+ const value = JSC.JSObject.getIndex(nextValue, globalObject, 1);
+ this.formatter.writeIndent(Writer, this.writer) catch unreachable;
+ const key_tag = Tag.get(key, globalObject);
+
+ this.formatter.format(
+ key_tag,
+ Writer,
+ this.writer,
+ key,
+ this.formatter.globalThis,
+ enable_ansi_colors,
+ );
+ this.writer.writeAll(": ") catch unreachable;
+ const value_tag = Tag.get(value, globalObject);
+ this.formatter.format(
+ value_tag,
+ Writer,
+ this.writer,
+ value,
+ this.formatter.globalThis,
+ enable_ansi_colors,
+ );
+ this.formatter.printComma(Writer, this.writer, enable_ansi_colors) catch unreachable;
+ this.writer.writeAll("\n") catch unreachable;
+ }
+ };
+ }
+
+ pub fn SetIterator(comptime Writer: type, comptime enable_ansi_colors: bool) type {
+ return struct {
+ formatter: *ZigConsoleClient.Formatter,
+ writer: Writer,
+ pub fn forEach(_: [*c]JSC.VM, globalObject: [*c]JSGlobalObject, ctx: ?*anyopaque, nextValue: JSValue) callconv(.C) void {
+ var this: *@This() = bun.cast(*@This(), ctx orelse return);
+ this.formatter.writeIndent(Writer, this.writer) catch {};
+ const key_tag = Tag.get(nextValue, globalObject);
+ this.formatter.format(
+ key_tag,
+ Writer,
+ this.writer,
+ nextValue,
+ this.formatter.globalThis,
+ enable_ansi_colors,
+ );
+
+ this.formatter.printComma(Writer, this.writer, enable_ansi_colors) catch unreachable;
+ this.writer.writeAll("\n") catch unreachable;
+ }
+ };
+ }
+
+ pub fn printAs(
+ this: *ZigConsoleClient.Formatter,
+ comptime Format: ZigConsoleClient.Formatter.Tag,
+ comptime Writer: type,
+ writer_: Writer,
+ value: JSValue,
+ jsType: JSValue.JSType,
+ comptime enable_ansi_colors: bool,
+ ) void {
+ var writer = WrappedWriter(Writer){ .ctx = writer_ };
+
+ if (comptime Format.canHaveCircularReferences()) {
+ if (this.map_node == null) {
+ this.map_node = Visited.Pool.get(default_allocator);
+ this.map_node.?.data.clearRetainingCapacity();
+ this.map = this.map_node.?.data;
+ }
+
+ var entry = this.map.getOrPut(@enumToInt(value)) catch unreachable;
+ if (entry.found_existing) {
+ writer.writeAll(comptime Output.prettyFmt("<r><cyan>[Circular]<r>", enable_ansi_colors));
+ return;
+ }
+ }
+
+ switch (comptime Format) {
+ .StringPossiblyFormatted => {
+ var str = ZigString.init("");
+ value.toZigString(&str, this.globalThis);
+
+ if (!str.is16Bit()) {
+ const slice = str.slice();
+ this.writeWithFormatting(Writer, writer_, @TypeOf(slice), slice, this.globalThis, enable_ansi_colors);
+ } else {
+ // TODO: UTF16
+ writer.print("{}", .{str});
+ }
+ },
+ .String => {
+ var str = ZigString.init("");
+ value.toZigString(&str, this.globalThis);
+
+ if (this.quote_strings and jsType != .RegExpObject) {
+ if (str.len == 0) {
+ writer.writeAll("\"\"");
+ return;
+ }
+
+ if (comptime enable_ansi_colors) {
+ writer.writeAll(Output.prettyFmt("<r><green>", true));
+ }
+
+ defer if (comptime enable_ansi_colors)
+ writer.writeAll(Output.prettyFmt("<r>", true));
+
+ if (str.is16Bit()) {
+ this.printAs(.JSON, Writer, writer_, value, .StringObject, enable_ansi_colors);
+ return;
+ }
+
+ JSPrinter.writeJSONString(str.slice(), Writer, writer_, false) catch unreachable;
+
+ return;
+ }
+
+ if (jsType == .RegExpObject) {
+ writer.print(comptime Output.prettyFmt("<r><red>", enable_ansi_colors), .{});
+ }
+
+ writer.print("{}", .{str});
+
+ if (jsType == .RegExpObject) {
+ writer.print(comptime Output.prettyFmt("<r>", enable_ansi_colors), .{});
+ }
+ },
+ .Integer => {
+ writer.print(comptime Output.prettyFmt("<r><yellow>{d}<r>", enable_ansi_colors), .{value.toInt64()});
+ },
+ .BigInt => {
+ var out_str = value.getZigString(this.globalThis).slice();
+ writer.print(comptime Output.prettyFmt("<r><yellow>{s}n<r>", enable_ansi_colors), .{out_str});
+ },
+ .Double => {
+ writer.print(comptime Output.prettyFmt("<r><yellow>{d}n<r>", enable_ansi_colors), .{value.asNumber()});
+ },
+ .Undefined => {
+ writer.print(comptime Output.prettyFmt("<r><d>undefined<r>", enable_ansi_colors), .{});
+ },
+ .Null => {
+ writer.print(comptime Output.prettyFmt("<r><yellow>null<r>", enable_ansi_colors), .{});
+ },
+ .Symbol => {
+ var description = value.getDescription(this.globalThis);
+
+ if (description.len > 0) {
+ var slice = description.toSlice(default_allocator);
+ defer if (slice.allocated) slice.deinit();
+ writer.print(comptime Output.prettyFmt("<r><cyan>Symbol<r><d>(<green>{}<r><d>)<r>", enable_ansi_colors), .{
+ JSPrinter.formatJSONString(slice.slice()),
+ });
+ } else {
+ writer.print(comptime Output.prettyFmt("<r><cyan>Symbol<r>", enable_ansi_colors), .{});
+ }
+ },
+ .Error => {
+ JS.VirtualMachine.vm.printErrorlikeObject(
+ value,
+ null,
+ null,
+
+ Writer,
+ writer_,
+ enable_ansi_colors,
+ );
+ },
+ .Class => {
+ var printable = ZigString.init(&name_buf);
+ value.getClassName(this.globalThis, &printable);
+ if (printable.len == 0) {
+ writer.print(comptime Output.prettyFmt("[class]", enable_ansi_colors), .{});
+ } else {
+ writer.print(comptime Output.prettyFmt("[class <cyan>{}<r>]", enable_ansi_colors), .{printable});
+ }
+ },
+ .Function => {
+ var printable = ZigString.init(&name_buf);
+ value.getNameProperty(this.globalThis, &printable);
+
+ if (printable.len == 0) {
+ writer.print(comptime Output.prettyFmt("<cyan>[Function]<r>", enable_ansi_colors), .{});
+ } else {
+ writer.print(comptime Output.prettyFmt("<cyan>[Function<d>:<r> <cyan>{}]<r>", enable_ansi_colors), .{printable});
+ }
+ },
+ .Array => {
+ const len = value.getLengthOfArray(this.globalThis);
+ if (len == 0) {
+ writer.writeAll("[]");
+ return;
+ }
+
+ writer.writeAll("[ ");
+ var i: u32 = 0;
+ var ref = value.asObjectRef();
+
+ var prev_quote_strings = this.quote_strings;
+ this.quote_strings = true;
+ defer this.quote_strings = prev_quote_strings;
+ while (i < len) : (i += 1) {
+ if (i > 0) {
+ this.printComma(Writer, writer_, enable_ansi_colors) catch unreachable;
+ writer.writeAll(" ");
+ }
+
+ const element = JSValue.fromRef(CAPI.JSObjectGetPropertyAtIndex(this.globalThis.ref(), ref, i, null));
+ const tag = Tag.get(element, this.globalThis);
+
+ this.format(tag, Writer, writer_, element, this.globalThis, enable_ansi_colors);
+
+ if (tag.cell.isStringLike()) {
+ if (comptime enable_ansi_colors) {
+ writer.writeAll(comptime Output.prettyFmt("<r>", true));
+ }
+ }
+ }
+
+ writer.writeAll(" ]");
+ },
+ .Private => {
+ if (CAPI.JSObjectGetPrivate(value.asRef())) |private_data_ptr| {
+ const priv_data = JSPrivateDataPtr.from(private_data_ptr);
+ switch (priv_data.tag()) {
+ .BuildError => {
+ const build_error = priv_data.as(JS.BuildError);
+ build_error.msg.writeFormat(writer_, enable_ansi_colors) catch {};
+ return;
+ },
+ .ResolveError => {
+ const resolve_error = priv_data.as(JS.ResolveError);
+ resolve_error.msg.writeFormat(writer_, enable_ansi_colors) catch {};
+ return;
+ },
+ .Response => {
+ var response = priv_data.as(JSC.WebCore.Response);
+ response.writeFormat(this, writer_, enable_ansi_colors) catch {};
+ return;
+ },
+ .Request => {
+ this.printAs(.JSON, Writer, writer_, value, .Object, enable_ansi_colors);
+ return;
+ },
+ else => {},
+ }
+ }
+
+ writer.writeAll("[native code]");
+ },
+ .NativeCode => {
+ writer.writeAll("[native code]");
+ },
+ .Promise => {
+ writer.writeAll("Promise { " ++ comptime Output.prettyFmt("<r><cyan>", enable_ansi_colors));
+
+ switch (JSPromise.status(@ptrCast(*JSPromise, value.asObjectRef().?), this.globalThis.vm())) {
+ JSPromise.Status.Pending => {
+ writer.writeAll("<pending>");
+ },
+ JSPromise.Status.Fulfilled => {
+ writer.writeAll("<resolved>");
+ },
+ JSPromise.Status.Rejected => {
+ writer.writeAll("<rejected>");
+ },
+ }
+
+ writer.writeAll(comptime Output.prettyFmt("<r>", enable_ansi_colors) ++ " }");
+ },
+ .Boolean => {
+ if (value.toBoolean()) {
+ writer.writeAll(comptime Output.prettyFmt("<r><yellow>true<r>", enable_ansi_colors));
+ } else {
+ writer.writeAll(comptime Output.prettyFmt("<r><yellow>false<r>", enable_ansi_colors));
+ }
+ },
+ .GlobalObject => {
+ writer.writeAll(comptime Output.prettyFmt("<cyan>[this.globalThis]<r>", enable_ansi_colors));
+ },
+ .Map => {
+ this.writeIndent(Writer, writer_) catch {};
+ const length_value = value.get(this.globalThis, "size") orelse JSC.JSValue.jsNumberFromInt32(0);
+ const length = length_value.toInt32();
+
+ const prev_quote_strings = this.quote_strings;
+ this.quote_strings = true;
+ defer this.quote_strings = prev_quote_strings;
+
+ if (length == 0) {
+ return writer.writeAll("Map {}");
+ }
+
+ writer.print("Map({d}) {{\n", .{length});
+ {
+ this.indent += 1;
+ defer this.indent -|= 1;
+ var iter = MapIterator(Writer, enable_ansi_colors){
+ .formatter = this,
+ .writer = writer_,
+ };
+ value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach);
+ }
+ this.writeIndent(Writer, writer_) catch {};
+ writer.writeAll("}");
+ },
+ .Set => {
+ const length_value = value.get(this.globalThis, "size") orelse JSC.JSValue.jsNumberFromInt32(0);
+ const length = length_value.toInt32();
+
+ const prev_quote_strings = this.quote_strings;
+ this.quote_strings = true;
+ defer this.quote_strings = prev_quote_strings;
+
+ this.writeIndent(Writer, writer_) catch {};
+ if (length == 0) {
+ return writer.writeAll("Set {}");
+ }
+ writer.print("Set({d}) {{\n", .{length});
+ {
+ this.indent += 1;
+ defer this.indent -|= 1;
+ var iter = SetIterator(Writer, enable_ansi_colors){
+ .formatter = this,
+ .writer = writer_,
+ };
+ value.forEach(this.globalThis, &iter, @TypeOf(iter).forEach);
+ }
+ this.writeIndent(Writer, writer_) catch {};
+ writer.writeAll("}");
+ },
+ .JSON => {
+ var str = ZigString.init("");
+ value.jsonStringify(this.globalThis, this.indent, &str);
+ if (jsType == JSValue.JSType.JSDate) {
+ // in the code for printing dates, it never exceeds this amount
+ var iso_string_buf: [36]u8 = undefined;
+ var out_buf: []const u8 = std.fmt.bufPrint(&iso_string_buf, "{}", .{str}) catch "";
+ if (out_buf.len > 2) {
+ // trim the quotes
+ out_buf = out_buf[1 .. out_buf.len - 1];
+ }
+
+ writer.print(comptime Output.prettyFmt("<r><magenta>{s}<r>", enable_ansi_colors), .{out_buf});
+ return;
+ }
+
+ writer.print("{}", .{str});
+ },
+ .JSX => {
+ writer.writeAll(comptime Output.prettyFmt("<r>", enable_ansi_colors));
+
+ writer.writeAll("<");
+
+ var needs_space = false;
+ var tag_name_str = ZigString.init("");
+
+ var tag_name_slice: ZigString.Slice = ZigString.Slice.empty;
+ var is_tag_kind_primitive = false;
+
+ defer if (tag_name_slice.allocated) tag_name_slice.deinit();
+
+ if (value.get(this.globalThis, "type")) |type_value| {
+ const _tag = Tag.get(type_value, this.globalThis);
+
+ if (_tag.cell == .Symbol) {} else if (_tag.cell.isStringLike()) {
+ type_value.toZigString(&tag_name_str, this.globalThis);
+ is_tag_kind_primitive = true;
+ } else if (_tag.cell.isObject() or type_value.isCallable(this.globalThis.vm())) {
+ type_value.getNameProperty(this.globalThis, &tag_name_str);
+ if (tag_name_str.len == 0) {
+ tag_name_str = ZigString.init("NoName");
+ }
+ } else {
+ type_value.toZigString(&tag_name_str, this.globalThis);
+ }
+
+ tag_name_slice = tag_name_str.toSlice(default_allocator);
+ needs_space = true;
+ } else {
+ tag_name_slice = ZigString.init("unknown").toSlice(default_allocator);
+
+ needs_space = true;
+ }
+
+ if (!is_tag_kind_primitive)
+ writer.writeAll(comptime Output.prettyFmt("<cyan>", enable_ansi_colors))
+ else
+ writer.writeAll(comptime Output.prettyFmt("<green>", enable_ansi_colors));
+ writer.writeAll(tag_name_slice.slice());
+ if (enable_ansi_colors) writer.writeAll(comptime Output.prettyFmt("<r>", enable_ansi_colors));
+
+ if (value.get(this.globalThis, "key")) |key_value| {
+ if (!key_value.isUndefinedOrNull()) {
+ if (needs_space)
+ writer.writeAll(" key=")
+ else
+ writer.writeAll("key=");
+
+ const old_quote_strings = this.quote_strings;
+ this.quote_strings = true;
+ defer this.quote_strings = old_quote_strings;
+
+ this.format(Tag.get(key_value, this.globalThis), Writer, writer_, key_value, this.globalThis, enable_ansi_colors);
+
+ needs_space = true;
+ }
+ }
+
+ if (value.get(this.globalThis, "props")) |props| {
+ const prev_quote_strings = this.quote_strings;
+ this.quote_strings = true;
+ defer this.quote_strings = prev_quote_strings;
+ var array = CAPI.JSObjectCopyPropertyNames(this.globalThis.ref(), props.asObjectRef());
+ defer CAPI.JSPropertyNameArrayRelease(array);
+ const count_ = CAPI.JSPropertyNameArrayGetCount(array);
+ var children_prop = props.get(this.globalThis, "children");
+ if (count_ > 0) {
+ {
+ var i: usize = 0;
+ this.indent += 1;
+ defer this.indent -|= 1;
+ const count_without_children = count_ - @as(usize, @boolToInt(children_prop != null));
+
+ while (i < count_) : (i += 1) {
+ var property_name_ref = CAPI.JSPropertyNameArrayGetNameAtIndex(array, i);
+ const prop_len = CAPI.JSStringGetLength(property_name_ref);
+ if (prop_len == 0) continue;
+ var prop = CAPI.JSStringGetCharacters8Ptr(property_name_ref)[0..prop_len];
+ if (strings.eqlComptime(prop, "children")) {
+ CAPI.JSStringRelease(property_name_ref);
+ continue;
+ }
+
+ defer CAPI.JSStringRelease(property_name_ref);
+
+ var property_value = CAPI.JSObjectGetProperty(this.globalThis.ref(), props.asObjectRef(), property_name_ref, null);
+ const tag = Tag.get(JSValue.fromRef(property_value), this.globalThis);
+
+ if (tag.cell.isHidden()) continue;
+
+ if (needs_space) writer.writeAll(" ");
+ needs_space = false;
+
+ writer.print(
+ comptime Output.prettyFmt("<r><blue>{s}<d>=<r>", enable_ansi_colors),
+ .{prop[0..@minimum(prop.len, 128)]},
+ );
+
+ if (tag.cell.isStringLike()) {
+ if (comptime enable_ansi_colors) {
+ writer.writeAll(comptime Output.prettyFmt("<r><green>", true));
+ }
+ }
+
+ this.format(tag, Writer, writer_, JSValue.fromRef(property_value), this.globalThis, enable_ansi_colors);
+
+ if (tag.cell.isStringLike()) {
+ if (comptime enable_ansi_colors) {
+ writer.writeAll(comptime Output.prettyFmt("<r>", true));
+ }
+ }
+
+ if (
+ // count_without_children is necessary to prevent printing an extra newline
+ // if there are children and one prop and the child prop is the last prop
+ i + 1 < count_without_children and
+ // 3 is arbitrary but basically
+ // <input type="text" value="foo" />
+ // ^ should be one line
+ // <input type="text" value="foo" bar="true" baz={false} />
+ // ^ should be multiple lines
+ i > 3)
+ {
+ writer.writeAll("\n");
+ this.writeIndent(Writer, writer_) catch unreachable;
+ } else if (i + 1 < count_without_children) {
+ writer.writeAll(" ");
+ }
+ }
+ }
+
+ if (children_prop) |children| {
+ const tag = Tag.get(children, this.globalThis);
+
+ const print_children = switch (tag.tag) {
+ .String, .JSX, .Array => true,
+ else => false,
+ };
+
+ if (print_children) {
+ print_children: {
+ switch (tag.tag) {
+ .String => {
+ var children_slice = children.toSlice(this.globalThis, default_allocator);
+ defer if (children_slice.allocated) children_slice.deinit();
+ if (children_slice.len == 0) break :print_children;
+ if (comptime enable_ansi_colors) writer.writeAll(comptime Output.prettyFmt("<r>", true));
+
+ writer.writeAll(">");
+ if (children_slice.len < 128) {
+ writer.writeAll(children_slice.slice());
+ } else {
+ this.indent += 1;
+ writer.writeAll("\n");
+ this.writeIndent(Writer, writer_) catch unreachable;
+ this.indent -|= 1;
+ writer.writeAll(children_slice.slice());
+ writer.writeAll("\n");
+ this.writeIndent(Writer, writer_) catch unreachable;
+ }
+ },
+ .JSX => {
+ writer.writeAll(">\n");
+
+ {
+ this.indent += 1;
+ this.writeIndent(Writer, writer_) catch unreachable;
+ defer this.indent -|= 1;
+ this.format(Tag.get(children, this.globalThis), Writer, writer_, children, this.globalThis, enable_ansi_colors);
+ }
+
+ writer.writeAll("\n");
+ this.writeIndent(Writer, writer_) catch unreachable;
+ },
+ .Array => {
+ const length = children.getLengthOfArray(this.globalThis);
+ if (length == 0) break :print_children;
+ writer.writeAll(">\n");
+
+ {
+ this.indent += 1;
+ this.writeIndent(Writer, writer_) catch unreachable;
+ const _prev_quote_strings = this.quote_strings;
+ this.quote_strings = false;
+ defer this.quote_strings = _prev_quote_strings;
+
+ defer this.indent -|= 1;
+
+ var j: usize = 0;
+ while (j < length) : (j += 1) {
+ const child = JSC.JSObject.getIndex(children, this.globalThis, @intCast(u32, j));
+ this.format(Tag.get(child, this.globalThis), Writer, writer_, child, this.globalThis, enable_ansi_colors);
+ if (j + 1 < length) {
+ writer.writeAll("\n");
+ this.writeIndent(Writer, writer_) catch unreachable;
+ }
+ }
+ }
+
+ writer.writeAll("\n");
+ this.writeIndent(Writer, writer_) catch unreachable;
+ },
+ else => unreachable,
+ }
+
+ writer.writeAll("</");
+ if (!is_tag_kind_primitive)
+ writer.writeAll(comptime Output.prettyFmt("<r><cyan>", enable_ansi_colors))
+ else
+ writer.writeAll(comptime Output.prettyFmt("<r><green>", enable_ansi_colors));
+ writer.writeAll(tag_name_slice.slice());
+ if (enable_ansi_colors) writer.writeAll(comptime Output.prettyFmt("<r>", enable_ansi_colors));
+ writer.writeAll(">");
+ }
+
+ return;
+ }
+ }
+ }
+ }
+
+ writer.writeAll(" />");
+ },
+ .Object => {
+ var object = value.asObjectRef();
+
+ {
+ var array = CAPI.JSObjectCopyPropertyNames(this.globalThis.ref(), object);
+ defer CAPI.JSPropertyNameArrayRelease(array);
+ const count_ = CAPI.JSPropertyNameArrayGetCount(array);
+ var i: usize = 0;
+
+ const prev_quote_strings = this.quote_strings;
+ this.quote_strings = true;
+ defer this.quote_strings = prev_quote_strings;
+
+ var name_str = ZigString.init("");
+ value.getPrototype(this.globalThis).getNameProperty(this.globalThis, &name_str);
+
+ if (name_str.len > 0 and !strings.eqlComptime(name_str.slice(), "Object")) {
+ writer.print("{} ", .{name_str});
+ } else {
+ value.getNameProperty(this.globalThis, &name_str);
+ if (name_str.len > 0 and !strings.eqlComptime(name_str.slice(), "Object")) {
+ writer.print("{} ", .{name_str});
+ }
+ }
+
+ if (count_ == 0) {
+ writer.writeAll("{ }");
+ return;
+ }
+
+ writer.writeAll("{ ");
+
+ while (i < count_) : (i += 1) {
+ var property_name_ref = CAPI.JSPropertyNameArrayGetNameAtIndex(array, i);
+ defer CAPI.JSStringRelease(property_name_ref);
+ const len = CAPI.JSStringGetLength(property_name_ref);
+ if (len == 0) continue;
+ var prop = CAPI.JSStringGetCharacters8Ptr(property_name_ref)[0..len];
+
+ var property_value = CAPI.JSObjectGetProperty(this.globalThis.ref(), object, property_name_ref, null);
+ const tag = Tag.get(JSValue.fromRef(property_value), this.globalThis);
+
+ if (tag.cell.isHidden()) continue;
+
+ const key = prop[0..@minimum(prop.len, 128)];
+
+ // TODO: make this one pass?
+ if (JSLexer.isLatin1Identifier(@TypeOf(key), key)) {
+ writer.print(
+ comptime Output.prettyFmt("{s}<d>:<r> ", enable_ansi_colors),
+ .{key},
+ );
+ } else {
+ writer.print(
+ comptime Output.prettyFmt("{s}<d>:<r> ", enable_ansi_colors),
+ .{JSPrinter.formatJSONString(key)},
+ );
+ }
+
+ if (tag.cell.isStringLike()) {
+ if (comptime enable_ansi_colors) {
+ writer.writeAll(comptime Output.prettyFmt("<r><green>", true));
+ }
+ }
+
+ this.format(tag, Writer, writer_, JSValue.fromRef(property_value), this.globalThis, enable_ansi_colors);
+
+ if (tag.cell.isStringLike()) {
+ if (comptime enable_ansi_colors) {
+ writer.writeAll(comptime Output.prettyFmt("<r>", true));
+ }
+ }
+
+ if (i + 1 < count_) {
+ this.printComma(Writer, writer_, enable_ansi_colors) catch unreachable;
+ writer.writeAll(" ");
+ }
+ }
+ }
+
+ writer.writeAll(" }");
+ },
+ .TypedArray => {
+ const len = value.getLengthOfArray(this.globalThis);
+ if (len == 0) {
+ writer.writeAll("[]");
+ return;
+ }
+
+ writer.writeAll("[ ");
+ var i: u32 = 0;
+ var buffer = JSC.Buffer.fromJS(this.globalThis, value, null).?;
+ const slice = buffer.slice();
+ while (i < len) : (i += 1) {
+ if (i > 0) {
+ this.printComma(Writer, writer_, enable_ansi_colors) catch unreachable;
+ writer.writeAll(" ");
+ }
+
+ writer.print(comptime Output.prettyFmt("<r><yellow>{d}<r>", enable_ansi_colors), .{slice[i]});
+ }
+
+ writer.writeAll(" ]");
+ },
+ else => {},
+ }
+ }
+
+ pub fn format(this: *ZigConsoleClient.Formatter, result: Tag.Result, comptime Writer: type, writer: Writer, value: JSValue, globalThis: *JSGlobalObject, comptime enable_ansi_colors: bool) void {
+ if (comptime is_bindgen) {
+ return;
+ }
+ var prevGlobalThis = this.globalThis;
+ defer this.globalThis = prevGlobalThis;
+ this.globalThis = globalThis;
+
+ // This looks incredibly redudant. We make the ZigConsoleClient.Formatter.Tag a
+ // comptime var so we have to repeat it here. The rationale there is
+ // it _should_ limit the stack usage because each version of the
+ // function will be relatively small
+ return switch (result.tag) {
+ .StringPossiblyFormatted => this.printAs(.StringPossiblyFormatted, Writer, writer, value, result.cell, enable_ansi_colors),
+ .String => this.printAs(.String, Writer, writer, value, result.cell, enable_ansi_colors),
+ .Undefined => this.printAs(.Undefined, Writer, writer, value, result.cell, enable_ansi_colors),
+ .Double => this.printAs(.Double, Writer, writer, value, result.cell, enable_ansi_colors),
+ .Integer => this.printAs(.Integer, Writer, writer, value, result.cell, enable_ansi_colors),
+ .Null => this.printAs(.Null, Writer, writer, value, result.cell, enable_ansi_colors),
+ .Boolean => this.printAs(.Boolean, Writer, writer, value, result.cell, enable_ansi_colors),
+ .Array => this.printAs(.Array, Writer, writer, value, result.cell, enable_ansi_colors),
+ .Object => this.printAs(.Object, Writer, writer, value, result.cell, enable_ansi_colors),
+ .Function => this.printAs(.Function, Writer, writer, value, result.cell, enable_ansi_colors),
+ .Class => this.printAs(.Class, Writer, writer, value, result.cell, enable_ansi_colors),
+ .Error => this.printAs(.Error, Writer, writer, value, result.cell, enable_ansi_colors),
+ .TypedArray => this.printAs(.TypedArray, Writer, writer, value, result.cell, enable_ansi_colors),
+ .Map => this.printAs(.Map, Writer, writer, value, result.cell, enable_ansi_colors),
+ .Set => this.printAs(.Set, Writer, writer, value, result.cell, enable_ansi_colors),
+ .Symbol => this.printAs(.Symbol, Writer, writer, value, result.cell, enable_ansi_colors),
+ .BigInt => this.printAs(.BigInt, Writer, writer, value, result.cell, enable_ansi_colors),
+ .GlobalObject => this.printAs(.GlobalObject, Writer, writer, value, result.cell, enable_ansi_colors),
+ .Private => this.printAs(.Private, Writer, writer, value, result.cell, enable_ansi_colors),
+ .Promise => this.printAs(.Promise, Writer, writer, value, result.cell, enable_ansi_colors),
+ .JSON => this.printAs(.JSON, Writer, writer, value, result.cell, enable_ansi_colors),
+ .NativeCode => this.printAs(.NativeCode, Writer, writer, value, result.cell, enable_ansi_colors),
+ .ArrayBuffer => this.printAs(.ArrayBuffer, Writer, writer, value, result.cell, enable_ansi_colors),
+ .JSX => this.printAs(.JSX, Writer, writer, value, result.cell, enable_ansi_colors),
+ };
+ }
+ };
+
+ pub fn count(
+ // console
+ _: ZigConsoleClient.Type,
+ // global
+ _: *JSGlobalObject,
+ // chars
+ _: [*]const u8,
+ // len
+ _: usize,
+ ) callconv(.C) void {}
+ pub fn countReset(
+ // console
+ _: ZigConsoleClient.Type,
+ // global
+ _: *JSGlobalObject,
+ // chars
+ _: [*]const u8,
+ // len
+ _: usize,
+ ) callconv(.C) void {}
+
+ const PendingTimers = std.AutoHashMap(u64, ?std.time.Timer);
+ threadlocal var pending_time_logs: PendingTimers = undefined;
+ threadlocal var pending_time_logs_loaded = false;
+
+ pub fn time(
+ // console
+ _: ZigConsoleClient.Type,
+ // global
+ _: *JSGlobalObject,
+ chars: [*]const u8,
+ len: usize,
+ ) callconv(.C) void {
+ const id = std.hash.Wyhash.hash(0, chars[0..len]);
+ if (!pending_time_logs_loaded) {
+ pending_time_logs = PendingTimers.init(default_allocator);
+ pending_time_logs_loaded = true;
+ }
+
+ var result = pending_time_logs.getOrPut(id) catch unreachable;
+
+ if (!result.found_existing or (result.found_existing and result.value_ptr.* == null)) {
+ result.value_ptr.* = std.time.Timer.start() catch unreachable;
+ }
+ }
+ pub fn timeEnd(
+ // console
+ _: ZigConsoleClient.Type,
+ // global
+ _: *JSGlobalObject,
+ chars: [*]const u8,
+ len: usize,
+ ) callconv(.C) void {
+ if (!pending_time_logs_loaded) {
+ return;
+ }
+
+ const id = std.hash.Wyhash.hash(0, chars[0..len]);
+ var result = (pending_time_logs.fetchPut(id, null) catch null) orelse return;
+ var value: std.time.Timer = result.value orelse return;
+ // get the duration in microseconds
+ // then display it in milliseconds
+ Output.printElapsed(@intToFloat(f64, value.read() / std.time.ns_per_us) / std.time.us_per_ms);
+ switch (len) {
+ 0 => Output.printErrorln("\n", .{}),
+ else => Output.printErrorln(" {s}", .{chars[0..len]}),
+ }
+
+ Output.flush();
+ }
+
+ pub fn timeLog(
+ // console
+ _: ZigConsoleClient.Type,
+ // global
+ _: *JSGlobalObject,
+ // chars
+ _: [*]const u8,
+ // len
+ _: usize,
+ // args
+ _: *ScriptArguments,
+ ) callconv(.C) void {}
+ pub fn profile(
+ // console
+ _: ZigConsoleClient.Type,
+ // global
+ _: *JSGlobalObject,
+ // chars
+ _: [*]const u8,
+ // len
+ _: usize,
+ ) callconv(.C) void {}
+ pub fn profileEnd(
+ // console
+ _: ZigConsoleClient.Type,
+ // global
+ _: *JSGlobalObject,
+ // chars
+ _: [*]const u8,
+ // len
+ _: usize,
+ ) callconv(.C) void {}
+ pub fn takeHeapSnapshot(
+ // console
+ _: ZigConsoleClient.Type,
+ // global
+ globalThis: *JSGlobalObject,
+ // chars
+ _: [*]const u8,
+ // len
+ _: usize,
+ ) callconv(.C) void {
+ // TODO: this does an extra JSONStringify and we don't need it to!
+ var snapshot: [1]JSValue = .{globalThis.generateHeapSnapshot()};
+ ZigConsoleClient.messageWithTypeAndLevel(undefined, MessageType.Log, MessageLevel.Debug, globalThis, &snapshot, 1);
+ }
+ pub fn timeStamp(
+ // console
+ _: ZigConsoleClient.Type,
+ // global
+ _: *JSGlobalObject,
+ // args
+ _: *ScriptArguments,
+ ) callconv(.C) void {}
+ pub fn record(
+ // console
+ _: ZigConsoleClient.Type,
+ // global
+ _: *JSGlobalObject,
+ // args
+ _: *ScriptArguments,
+ ) callconv(.C) void {}
+ pub fn recordEnd(
+ // console
+ _: ZigConsoleClient.Type,
+ // global
+ _: *JSGlobalObject,
+ // args
+ _: *ScriptArguments,
+ ) callconv(.C) void {}
+ pub fn screenshot(
+ // console
+ _: ZigConsoleClient.Type,
+ // global
+ _: *JSGlobalObject,
+ // args
+ _: *ScriptArguments,
+ ) callconv(.C) void {}
+
+ pub const Export = shim.exportFunctions(.{
+ .@"messageWithTypeAndLevel" = messageWithTypeAndLevel,
+ .@"count" = count,
+ .@"countReset" = countReset,
+ .@"time" = time,
+ .@"timeLog" = timeLog,
+ .@"timeEnd" = timeEnd,
+ .@"profile" = profile,
+ .@"profileEnd" = profileEnd,
+ .@"takeHeapSnapshot" = takeHeapSnapshot,
+ .@"timeStamp" = timeStamp,
+ .@"record" = record,
+ .@"recordEnd" = recordEnd,
+ .@"screenshot" = screenshot,
+ });
+
+ comptime {
+ @export(messageWithTypeAndLevel, .{
+ .name = Export[0].symbol_name,
+ });
+ @export(count, .{
+ .name = Export[1].symbol_name,
+ });
+ @export(countReset, .{
+ .name = Export[2].symbol_name,
+ });
+ @export(time, .{
+ .name = Export[3].symbol_name,
+ });
+ @export(timeLog, .{
+ .name = Export[4].symbol_name,
+ });
+ @export(timeEnd, .{
+ .name = Export[5].symbol_name,
+ });
+ @export(profile, .{
+ .name = Export[6].symbol_name,
+ });
+ @export(profileEnd, .{
+ .name = Export[7].symbol_name,
+ });
+ @export(takeHeapSnapshot, .{
+ .name = Export[8].symbol_name,
+ });
+ @export(timeStamp, .{
+ .name = Export[9].symbol_name,
+ });
+ @export(record, .{
+ .name = Export[10].symbol_name,
+ });
+ @export(recordEnd, .{
+ .name = Export[11].symbol_name,
+ });
+ @export(screenshot, .{
+ .name = Export[12].symbol_name,
+ });
+ }
+};
+
+// pub const CommonJSModuleConstructor = struct {
+// pub const shim = Shimmer("Zig", "CommonJSModuleConstructor", @This());
+// pub const name = "Zig::CommonJSModuleConstructor";
+// pub const include = "\"CommonJSModule.h\"";
+// pub const namespace = shim.namespace;
+
+// pub fn construct(global: *JSGlobalObject, module: *CommonJSModule) callconv(.C) ErrorableJSValue {}
+// };
+
+// pub const CommonJSModulePrototype = struct {
+// pub const shim = Shimmer("Zig", "CommonJSModulePrototype", @This());
+// pub const name = "Zig::CommonJSModulePrototype";
+// pub const include = "\"CommonJSModule.h\"";
+// pub const namespace = shim.namespace;
+
+// bytes: shim.Bytes,
+// };
+
+// pub const CommonJSModule = struct {
+// pub const shim = Shimmer("Zig", "CommonJSModule", @This());
+// pub const Type = *anyopaque;
+// pub const name = "Zig::CommonJSModule";
+// pub const include = "\"CommonJSModule.h\"";
+// pub const namespace = shim.namespace;
+
+// path: Fs.Path,
+// reload_pending: bool = false,
+
+// exports: JSValue,
+// instance: *CommonJSModulePrototype,
+// loaded: bool = false,
+
+// pub fn finishLoading(module: *CommonJSModule, global: *JSGlobalObject, exports: JSValue, instance: *CommonJSModulePrototype) callconv(.C) ErrorableJSValue {
+// module.loaded = true;
+// module.instance = instance;
+// module.exports = exports;
+// }
+
+// pub fn onCallRequire(module: *CommonJSModule, global: *JSGlobalObject, input: []const u8) callconv(.C) ErrorableJSValue {
+// const resolve = ModuleLoader.resolve(global, input, module) catch |err| {
+// return ErrorableJSValue.errFmt(
+// err,
+// "ResolveError: {s} while resolving \"{s}\"\nfrom \"{s}\"",
+// .{
+// @errorName(err),
+// input,
+// module.path.pretty,
+// },
+// );
+// };
+
+// const hash = ModuleLoader.hashid(resolve.path_pair.primary.text);
+// var reload_pending = false;
+// if (ModuleLoader.require_cache.get(hash)) |obj| {
+// reload_pending = obj.reload_pending;
+
+// return ErrorableJSValue.ok(obj.exports);
+// }
+
+// const result = ModuleLoader.load(global, resolve) catch |err| {
+// return ErrorableJSValue.errFmt(
+// err,
+// "LoadError: {s} while loading \"{s}\"",
+// .{
+// @errorName(err),
+// input,
+// module.path.pretty,
+// },
+// );
+// };
+
+// switch (result) {
+// .value => |value| {
+// return value;
+// },
+// .module => |mod| {
+// return ErrorableJSValue.ok(mod.exports);
+// },
+// .bundled_module_export => |bundled_module_export| {
+// return ErrorableJSValue.ok(bundled_module_export);
+// },
+// .path => |path| {
+// return ErrorableJSValue.ok(ZigString.init(path.text).toJSValue(global));
+// },
+// }
+// }
+// };
+
+pub inline fn toGlobalContextRef(ptr: *JSGlobalObject) CAPI.JSGlobalContextRef {
+ return @ptrCast(CAPI.JSGlobalContextRef, ptr);
+}
+
+comptime {
+ @export(ErrorCode.ParserError, .{ .name = "Zig_ErrorCodeParserError" });
+ @export(ErrorCode.JSErrorObject, .{ .name = "Zig_ErrorCodeJSErrorObject" });
+}
+
+const Bun = @import("../api/bun.zig");
+pub const BunTimer = Bun.Timer;
+pub const Formatter = ZigConsoleClient.Formatter;
+pub const HTTPServerRequestContext = JSC.API.Server.RequestContext;
+pub const HTTPSSLServerRequestContext = JSC.API.SSLServer.RequestContext;
+pub const HTTPDebugServerRequestContext = JSC.API.DebugServer.RequestContext;
+pub const HTTPDebugSSLServerRequestContext = JSC.API.DebugSSLServer.RequestContext;
+
+comptime {
+ WebSocketHTTPClient.shim.ref();
+ WebSocketHTTSPClient.shim.ref();
+ WebSocketClient.shim.ref();
+ WebSocketClientTLS.shim.ref();
+
+ HTTPServerRequestContext.shim.ref();
+ HTTPSSLServerRequestContext.shim.ref();
+ HTTPDebugServerRequestContext.shim.ref();
+ HTTPDebugSSLServerRequestContext.shim.ref();
+
+ if (!is_bindgen) {
+ _ = Process.getTitle;
+ _ = Process.setTitle;
+ _ = Zig__getAPIGlobals;
+ _ = Zig__getAPIConstructors;
+ NodeReadableStream.shim.ref();
+ Bun.Timer.shim.ref();
+ NodeWritableStream.shim.ref();
+ NodePath.shim.ref();
+ JSReadableStreamBlob.shim.ref();
+ JSArrayBufferSink.shim.ref();
+
+ JSReadableStreamFile.shim.ref();
+ _ = ZigString__free;
+ _ = ZigString__free_global;
+ }
+}