Files
bun.sh/src/javascript/jsc/bindings/exports.zig
2022-04-01 01:17:36 -07:00

2500 lines
96 KiB
Zig

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;
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(ptr: [*]const u8, len: usize, allocator_: ?*anyopaque) void {
var allocator: std.mem.Allocator = @ptrCast(*std.mem.Allocator, @alignCast(@alignOf(*std.mem.Allocator), allocator_ orelse return)).*;
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, _: usize) void {
if (comptime Environment.allow_assert) {
std.debug.assert(Mimalloc.mi_check_owned(ptr));
}
Mimalloc.mi_free(@intToPtr(*anyopaque, @ptrToInt(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 };
}
}
}
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,
// 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.toInt32()});
},
.Double => {
writer.print(comptime Output.prettyFmt("<r><yellow>{d}<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});
}
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;
comptime {
if (!is_bindgen) {
_ = Process.getTitle;
_ = Process.setTitle;
_ = Zig__getAPIGlobals;
_ = Zig__getAPIConstructors;
std.testing.refAllDecls(NodeReadableStream);
std.testing.refAllDecls(Bun.Timer);
std.testing.refAllDecls(NodeWritableStream);
std.testing.refAllDecls(NodePath);
_ = ZigString__free;
_ = ZigString__free_global;
}
}