mirror of
https://github.com/oven-sh/bun
synced 2026-02-11 11:29:02 +00:00
* Implement os.cpus() for Linux `os.cpus()` currently returns an empty array for all platforms. This PR implements full functionality for Linux and has been tested on x86-64. Other OSes will continue to return an empty array. Note that Linux on Arm64 may report the CPU model differently; if this is the case the CPU model will currently be reported as "unknown". As I do not have Arm64 hardware to verify and develop against, a todo has been left in the code. * resolve issues from review
454 lines
22 KiB
Zig
454 lines
22 KiB
Zig
const std = @import("std");
|
|
const builtin = @import("builtin");
|
|
const bun = @import("bun");
|
|
const C = bun.C;
|
|
const string = bun.string;
|
|
const strings = bun.strings;
|
|
const JSC = @import("bun").JSC;
|
|
const Environment = bun.Environment;
|
|
const Global = bun.Global;
|
|
const is_bindgen: bool = std.meta.globalOption("bindgen", bool) orelse false;
|
|
const heap_allocator = bun.default_allocator;
|
|
const constants = @import("./os/constants.zig");
|
|
|
|
pub const Os = struct {
|
|
pub const name = "Bun__Os";
|
|
pub const code = @embedFile("../os.exports.js");
|
|
|
|
pub fn create(globalObject: *JSC.JSGlobalObject) callconv(.C) JSC.JSValue {
|
|
const module = JSC.JSValue.createEmptyObject(globalObject, 20);
|
|
|
|
module.put(globalObject, JSC.ZigString.static("arch"), JSC.NewFunction(globalObject, JSC.ZigString.static("arch"), 0, arch, true));
|
|
module.put(globalObject, JSC.ZigString.static("cpus"), JSC.NewFunction(globalObject, JSC.ZigString.static("cpus"), 0, cpus, true));
|
|
module.put(globalObject, JSC.ZigString.static("endianness"), JSC.NewFunction(globalObject, JSC.ZigString.static("endianness"), 0, endianness, true));
|
|
module.put(globalObject, JSC.ZigString.static("freemem"), JSC.NewFunction(globalObject, JSC.ZigString.static("freemem"), 0, freemem, true));
|
|
module.put(globalObject, JSC.ZigString.static("getPriority"), JSC.NewFunction(globalObject, JSC.ZigString.static("getPriority"), 1, getPriority, true));
|
|
module.put(globalObject, JSC.ZigString.static("homedir"), JSC.NewFunction(globalObject, JSC.ZigString.static("homedir"), 0, homedir, true));
|
|
module.put(globalObject, JSC.ZigString.static("hostname"), JSC.NewFunction(globalObject, JSC.ZigString.static("hostname"), 0, hostname, true));
|
|
module.put(globalObject, JSC.ZigString.static("loadavg"), JSC.NewFunction(globalObject, JSC.ZigString.static("loadavg"), 0, loadavg, true));
|
|
module.put(globalObject, JSC.ZigString.static("networkInterfaces"), JSC.NewFunction(globalObject, JSC.ZigString.static("networkInterfaces"), 0, networkInterfaces, true));
|
|
module.put(globalObject, JSC.ZigString.static("platform"), JSC.NewFunction(globalObject, JSC.ZigString.static("platform"), 0, platform, true));
|
|
module.put(globalObject, JSC.ZigString.static("release"), JSC.NewFunction(globalObject, JSC.ZigString.static("release"), 0, release, true));
|
|
module.put(globalObject, JSC.ZigString.static("setPriority"), JSC.NewFunction(globalObject, JSC.ZigString.static("setPriority"), 2, setPriority, true));
|
|
module.put(globalObject, JSC.ZigString.static("tmpdir"), JSC.NewFunction(globalObject, JSC.ZigString.static("tmpdir"), 0, tmpdir, true));
|
|
module.put(globalObject, JSC.ZigString.static("totalmem"), JSC.NewFunction(globalObject, JSC.ZigString.static("totalmem"), 0, totalmem, true));
|
|
module.put(globalObject, JSC.ZigString.static("type"), JSC.NewFunction(globalObject, JSC.ZigString.static("type"), 0, Os.type, true));
|
|
module.put(globalObject, JSC.ZigString.static("uptime"), JSC.NewFunction(globalObject, JSC.ZigString.static("uptime"), 0, uptime, true));
|
|
module.put(globalObject, JSC.ZigString.static("userInfo"), JSC.NewFunction(globalObject, JSC.ZigString.static("userInfo"), 0, userInfo, true));
|
|
module.put(globalObject, JSC.ZigString.static("version"), JSC.NewFunction(globalObject, JSC.ZigString.static("version"), 0, version, true));
|
|
|
|
module.put(globalObject, JSC.ZigString.static("devNull"), JSC.ZigString.init(devNull).withEncoding().toValue(globalObject));
|
|
module.put(globalObject, JSC.ZigString.static("EOL"), JSC.ZigString.init(EOL).withEncoding().toValue(globalObject));
|
|
|
|
module.put(globalObject, JSC.ZigString.static("constants"), constants.create(globalObject));
|
|
|
|
return module;
|
|
}
|
|
|
|
pub const EOL = if (Environment.isWindows) "\r\n" else "\n";
|
|
pub const devNull = if (Environment.isWindows) "\\\\.\nul" else "/dev/null";
|
|
|
|
pub fn arch(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
|
|
return JSC.ZigString.init(Global.arch_name).withEncoding().toValue(globalThis);
|
|
}
|
|
|
|
const CPU = struct {
|
|
model: JSC.ZigString = JSC.ZigString.init("unknown"),
|
|
speed: u64 = 0,
|
|
times: struct {
|
|
user: u64 = 0,
|
|
nice: u64 = 0,
|
|
sys: u64 = 0,
|
|
idle: u64 = 0,
|
|
irq: u64 = 0,
|
|
} = .{}
|
|
};
|
|
|
|
pub fn cpus(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
|
|
var cpu_buffer: [8192]CPU = undefined;
|
|
const cpus_or_error = if (comptime Environment.isLinux)
|
|
cpusImplLinux(&cpu_buffer)
|
|
else
|
|
@as(anyerror![]CPU, cpu_buffer[0..0]); // unsupported platform -> empty array
|
|
|
|
if (cpus_or_error) |list| {
|
|
// Convert the CPU list to a JS Array
|
|
const values = JSC.JSValue.createEmptyArray(globalThis, list.len);
|
|
for (list) |cpu, cpu_index| {
|
|
const obj = JSC.JSValue.createEmptyObject(globalThis, 3);
|
|
obj.put(globalThis, JSC.ZigString.static("model"), cpu.model.withEncoding().toValueGC(globalThis));
|
|
obj.put(globalThis, JSC.ZigString.static("speed"), JSC.JSValue.jsNumberFromUint64(cpu.speed));
|
|
|
|
const timesFields = comptime std.meta.fieldNames(@TypeOf(cpu.times));
|
|
const times = JSC.JSValue.createEmptyObject(globalThis, 5);
|
|
inline for (timesFields) |fieldName| {
|
|
times.put(globalThis, JSC.ZigString.static(fieldName),
|
|
JSC.JSValue.jsNumberFromUint64(@field(cpu.times, fieldName)));
|
|
}
|
|
obj.put(globalThis, JSC.ZigString.static("times"), times);
|
|
values.putIndex(globalThis, @intCast(u32, cpu_index), obj);
|
|
}
|
|
return values;
|
|
|
|
} else |zig_err| {
|
|
const msg = switch (zig_err) {
|
|
error.too_many_cpus => "Too many CPUs or malformed /proc/cpuinfo file",
|
|
error.eol => "Malformed /proc/stat file",
|
|
else => "An error occurred while fetching cpu information",
|
|
};
|
|
//TODO more suitable error type?
|
|
const err = JSC.SystemError{
|
|
.message = JSC.ZigString.init(msg),
|
|
};
|
|
globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis));
|
|
return JSC.JSValue.jsUndefined();
|
|
}
|
|
}
|
|
|
|
fn cpusImplLinux(cpu_buffer: []CPU) ![]CPU {
|
|
// Use a large line buffer because the /proc/stat file can have a very long list of interrupts
|
|
var line_buffer: [1024*8]u8 = undefined;
|
|
var num_cpus: usize = 0;
|
|
|
|
// Read /proc/stat to get number of CPUs and times
|
|
if (std.fs.openFileAbsolute("/proc/stat", .{})) |file| {
|
|
defer file.close();
|
|
var reader = file.reader();
|
|
|
|
// Skip the first line (aggregate of all CPUs)
|
|
try reader.skipUntilDelimiterOrEof('\n');
|
|
|
|
// Read each CPU line
|
|
while (try reader.readUntilDelimiterOrEof(&line_buffer, '\n')) |line| {
|
|
|
|
if (num_cpus >= cpu_buffer.len) return error.too_many_cpus;
|
|
|
|
// CPU lines are formatted as `cpu0 user nice sys idle iowait irq softirq`
|
|
var toks = std.mem.tokenize(u8, line, " \t");
|
|
const cpu_name = toks.next();
|
|
if (cpu_name == null or !std.mem.startsWith(u8, cpu_name.?, "cpu")) break; // done with CPUs
|
|
|
|
// Default initialize the CPU to ensure that we never return uninitialized fields
|
|
cpu_buffer[num_cpus] = CPU{};
|
|
|
|
//NOTE: libuv assumes this is fixed on Linux, not sure that's actually the case
|
|
const scale = 10;
|
|
cpu_buffer[num_cpus].times.user = scale * try std.fmt.parseInt(u64, toks.next() orelse return error.eol, 10);
|
|
cpu_buffer[num_cpus].times.nice = scale * try std.fmt.parseInt(u64, toks.next() orelse return error.eol, 10);
|
|
cpu_buffer[num_cpus].times.sys = scale * try std.fmt.parseInt(u64, toks.next() orelse return error.eol, 10);
|
|
cpu_buffer[num_cpus].times.idle = scale * try std.fmt.parseInt(u64, toks.next() orelse return error.eol, 10);
|
|
_ = try (toks.next() orelse error.eol); // skip iowait
|
|
cpu_buffer[num_cpus].times.irq = scale * try std.fmt.parseInt(u64, toks.next() orelse return error.eol, 10);
|
|
|
|
num_cpus += 1;
|
|
}
|
|
} else |_| {
|
|
return error.cannot_open_proc_stat;
|
|
}
|
|
|
|
const slice = cpu_buffer[0..num_cpus];
|
|
|
|
// Read /proc/cpuinfo to get model information (optional)
|
|
if (std.fs.openFileAbsolute("/proc/cpuinfo", .{})) |file| {
|
|
defer file.close();
|
|
var reader = file.reader();
|
|
const key_processor = "processor\t: ";
|
|
const key_model_name = "model name\t: ";
|
|
|
|
var cpu_index: usize = 0;
|
|
while (try reader.readUntilDelimiterOrEof(&line_buffer, '\n')) |line| {
|
|
|
|
if (std.mem.startsWith(u8, line, key_processor)) {
|
|
// If this line starts a new processor, parse the index from the line
|
|
const digits = std.mem.trim(u8, line[key_processor.len..], " \t\n");
|
|
cpu_index = try std.fmt.parseInt(usize, digits, 10);
|
|
if (cpu_index >= slice.len) return error.too_may_cpus;
|
|
|
|
} else if (std.mem.startsWith(u8, line, key_model_name)) {
|
|
// If this is the model name, extract it and store on the current cpu
|
|
const model_name = line[key_model_name.len..];
|
|
slice[cpu_index].model = JSC.ZigString.init(model_name);
|
|
}
|
|
//TODO: special handling for ARM64 (no model name)?
|
|
}
|
|
} else |_| {
|
|
// Do nothing: CPU default initializer has set model name to "unknown"
|
|
}
|
|
|
|
// Read /sys/devices/system/cpu/cpu{}/cpufreq/scaling_cur_freq to get current frequency (optional)
|
|
for (slice) |*cpu, cpu_index| {
|
|
var path_buf: [128]u8 = undefined;
|
|
const path = try std.fmt.bufPrint(&path_buf, "/sys/devices/system/cpu/cpu{}/cpufreq/scaling_cur_freq", .{cpu_index});
|
|
if (std.fs.openFileAbsolute(path, .{})) |file| {
|
|
defer file.close();
|
|
|
|
const bytes_read = try file.readAll(&line_buffer);
|
|
const digits = std.mem.trim(u8, line_buffer[0..bytes_read], " \n");
|
|
cpu.speed = try std.fmt.parseInt(u64, digits, 10) / 1000;
|
|
} else |_| {
|
|
// Do nothing: CPU default initializer has set speed to 0
|
|
}
|
|
}
|
|
|
|
return slice;
|
|
}
|
|
|
|
pub fn endianness(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
|
|
switch (comptime builtin.target.cpu.arch.endian()) {
|
|
.Big => {
|
|
return JSC.ZigString.init("BE").withEncoding().toValue(globalThis);
|
|
},
|
|
.Little => {
|
|
return JSC.ZigString.init("LE").withEncoding().toValue(globalThis);
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn freemem(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
|
|
return JSC.JSValue.jsNumberFromUint64(C.getFreeMemory());
|
|
}
|
|
|
|
pub fn getPriority(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
|
|
var args_ = callframe.arguments(1);
|
|
const arguments: []const JSC.JSValue = args_.ptr[0..args_.len];
|
|
|
|
if (arguments.len > 0 and !arguments[0].isNumber()) {
|
|
const err = JSC.toTypeError(
|
|
JSC.Node.ErrorCode.ERR_INVALID_ARG_TYPE,
|
|
"getPriority() expects a number",
|
|
.{},
|
|
globalThis,
|
|
);
|
|
globalThis.vm().throwError(globalThis, err);
|
|
return JSC.JSValue.jsUndefined();
|
|
}
|
|
|
|
const pid = if (arguments.len > 0) arguments[0].asInt32() else 0;
|
|
|
|
const priority = C.getProcessPriority(pid);
|
|
if (priority == -1) {
|
|
//const info = JSC.JSValue.createEmptyObject(globalThis, 4);
|
|
//info.put(globalThis, JSC.ZigString.static("errno"), JSC.JSValue.jsNumberFromInt32(-3));
|
|
//info.put(globalThis, JSC.ZigString.static("code"), JSC.ZigString.init("ESRCH").withEncoding().toValueGC(globalThis));
|
|
//info.put(globalThis, JSC.ZigString.static("message"), JSC.ZigString.init("no such process").withEncoding().toValueGC(globalThis));
|
|
//info.put(globalThis, JSC.ZigString.static("syscall"), JSC.ZigString.init("uv_os_getpriority").withEncoding().toValueGC(globalThis));
|
|
|
|
const err = JSC.SystemError{
|
|
.message = JSC.ZigString.init("A system error occurred: uv_os_getpriority returned ESRCH (no such process)"),
|
|
.code = JSC.ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))),
|
|
//.info = info,
|
|
.errno = -3,
|
|
.syscall = JSC.ZigString.init("uv_os_getpriority"),
|
|
};
|
|
|
|
globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis));
|
|
return JSC.JSValue.jsUndefined();
|
|
}
|
|
|
|
return JSC.JSValue.jsNumberFromInt32(priority);
|
|
}
|
|
|
|
pub fn homedir(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
|
|
var dir: string = "unknown";
|
|
if (comptime Environment.isWindows)
|
|
dir = bun.getenvZ("USERPROFILE") orelse "unknown"
|
|
else
|
|
dir = bun.getenvZ("HOME") orelse "unknown";
|
|
|
|
return JSC.ZigString.init(dir).withEncoding().toValueGC(globalThis);
|
|
}
|
|
|
|
pub fn hostname(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
|
|
var name_buffer: [std.os.HOST_NAME_MAX]u8 = undefined;
|
|
|
|
return JSC.ZigString.init(std.os.gethostname(&name_buffer) catch "unknown").withEncoding().toValueGC(globalThis);
|
|
}
|
|
|
|
pub fn loadavg(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
|
|
const result = C.getSystemLoadavg();
|
|
return JSC.JSArray.from(globalThis, &.{
|
|
JSC.JSValue.jsDoubleNumber(result[0]),
|
|
JSC.JSValue.jsDoubleNumber(result[1]),
|
|
JSC.JSValue.jsDoubleNumber(result[2]),
|
|
});
|
|
}
|
|
|
|
pub fn networkInterfaces(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
|
|
// TODO:
|
|
return JSC.JSValue.createEmptyObject(globalThis, 0);
|
|
}
|
|
|
|
pub fn platform(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
|
|
return JSC.ZigString.init(Global.os_name).withEncoding().toValueGC(globalThis);
|
|
}
|
|
|
|
pub fn release(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
var name_buffer: [std.os.HOST_NAME_MAX]u8 = undefined;
|
|
return JSC.ZigString.init(C.getRelease(&name_buffer)).withEncoding().toValueGC(globalThis);
|
|
}
|
|
|
|
pub fn setPriority(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
|
|
var args_ = callframe.arguments(2);
|
|
var arguments: []const JSC.JSValue = args_.ptr[0..args_.len];
|
|
|
|
if (arguments.len == 0) {
|
|
const err = JSC.toTypeError(
|
|
JSC.Node.ErrorCode.ERR_INVALID_ARG_TYPE,
|
|
"The \"priority\" argument must be of type number. Received undefined",
|
|
.{},
|
|
globalThis,
|
|
);
|
|
globalThis.vm().throwError(globalThis, err);
|
|
return JSC.JSValue.jsUndefined();
|
|
}
|
|
|
|
const pid = if (arguments.len == 2) arguments[0].coerce(i32, globalThis) else 0;
|
|
const priority = if (arguments.len == 2) arguments[1].coerce(i32, globalThis) else arguments[0].coerce(i32, globalThis);
|
|
|
|
if (priority < -20 or priority > 19) {
|
|
const err = JSC.toTypeError(
|
|
JSC.Node.ErrorCode.ERR_OUT_OF_RANGE,
|
|
"The value of \"priority\" is out of range. It must be >= -20 && <= 19",
|
|
.{},
|
|
globalThis,
|
|
);
|
|
globalThis.vm().throwError(globalThis, err);
|
|
return JSC.JSValue.jsUndefined();
|
|
}
|
|
|
|
const errcode = C.setProcessPriority(pid, priority);
|
|
switch (errcode) {
|
|
.SRCH => {
|
|
const err = JSC.SystemError{
|
|
.message = JSC.ZigString.init("A system error occurred: uv_os_setpriority returned ESRCH (no such process)"),
|
|
.code = JSC.ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))),
|
|
//.info = info,
|
|
.errno = -3,
|
|
.syscall = JSC.ZigString.init("uv_os_setpriority"),
|
|
};
|
|
|
|
globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis));
|
|
return JSC.JSValue.jsUndefined();
|
|
},
|
|
.ACCES => {
|
|
const err = JSC.SystemError{
|
|
.message = JSC.ZigString.init("A system error occurred: uv_os_setpriority returned EACCESS (permission denied)"),
|
|
.code = JSC.ZigString.init(@as(string, @tagName(JSC.Node.ErrorCode.ERR_SYSTEM_ERROR))),
|
|
//.info = info,
|
|
.errno = -13,
|
|
.syscall = JSC.ZigString.init("uv_os_setpriority"),
|
|
};
|
|
|
|
globalThis.vm().throwError(globalThis, err.toErrorInstance(globalThis));
|
|
return JSC.JSValue.jsUndefined();
|
|
},
|
|
else => {},
|
|
}
|
|
|
|
return JSC.JSValue.jsUndefined();
|
|
}
|
|
|
|
pub fn tmpdir(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
|
|
var dir: string = "unknown";
|
|
if (comptime Environment.isWindows) {
|
|
if (bun.getenvZ("TEMP") orelse bun.getenvZ("TMP")) |tmpdir_| {
|
|
dir = tmpdir_;
|
|
}
|
|
|
|
if (bun.getenvZ("SYSTEMROOT") orelse bun.getenvZ("WINDIR")) |systemdir_| {
|
|
dir = systemdir_ + "\\temp";
|
|
}
|
|
|
|
dir = "unknown";
|
|
} else {
|
|
dir = bun.getenvZ("TMPDIR") orelse bun.getenvZ("TMP") orelse bun.getenvZ("TEMP") orelse "/tmp";
|
|
}
|
|
|
|
return JSC.ZigString.init(dir).withEncoding().toValueGC(globalThis);
|
|
}
|
|
|
|
pub fn totalmem(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
|
|
return JSC.JSValue.jsNumberFromUint64(C.getTotalMemory());
|
|
}
|
|
|
|
pub fn @"type"(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
|
|
if (comptime Environment.isWindows)
|
|
return JSC.ZigString.static("Windows_NT").toValue(globalThis)
|
|
else if (comptime Environment.isMac)
|
|
return JSC.ZigString.static("Darwin").toValue(globalThis)
|
|
else if (comptime Environment.isLinux)
|
|
return JSC.ZigString.static("Linux").toValue(globalThis);
|
|
|
|
return JSC.ZigString.init(Global.os_name).withEncoding().toValueGC(globalThis);
|
|
}
|
|
|
|
pub fn uptime(_: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
|
|
return JSC.JSValue.jsNumberFromUint64(C.getSystemUptime());
|
|
}
|
|
|
|
pub fn userInfo(globalThis: *JSC.JSGlobalObject, callframe: *JSC.CallFrame) JSC.JSValue {
|
|
const result = JSC.JSValue.createEmptyObject(globalThis, 5);
|
|
|
|
result.put(globalThis, JSC.ZigString.static("homedir"), homedir(globalThis, callframe));
|
|
|
|
if (comptime Environment.isWindows) {
|
|
result.put(globalThis, JSC.ZigString.static("username"), JSC.ZigString.init(bun.getenvZ("USERNAME") orelse "unknown").withEncoding().toValueGC(globalThis));
|
|
result.put(globalThis, JSC.ZigString.static("uid"), JSC.JSValue.jsNumber(-1));
|
|
result.put(globalThis, JSC.ZigString.static("gid"), JSC.JSValue.jsNumber(-1));
|
|
result.put(globalThis, JSC.ZigString.static("shell"), JSC.JSValue.jsNull());
|
|
} else {
|
|
const username = bun.getenvZ("USER") orelse "unknown";
|
|
|
|
result.put(globalThis, JSC.ZigString.static("username"), JSC.ZigString.init(username).withEncoding().toValueGC(globalThis));
|
|
result.put(globalThis, JSC.ZigString.static("shell"), JSC.ZigString.init(bun.getenvZ("SHELL") orelse "unknown").withEncoding().toValueGC(globalThis));
|
|
|
|
if (comptime Environment.isLinux) {
|
|
result.put(globalThis, JSC.ZigString.static("uid"), JSC.JSValue.jsNumber(std.os.linux.getuid()));
|
|
result.put(globalThis, JSC.ZigString.static("gid"), JSC.JSValue.jsNumber(std.os.linux.getgid()));
|
|
} else {
|
|
result.put(globalThis, JSC.ZigString.static("uid"), JSC.JSValue.jsNumber(C.darwin.getuid()));
|
|
result.put(globalThis, JSC.ZigString.static("gid"), JSC.JSValue.jsNumber(C.darwin.getgid()));
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
pub fn version(globalThis: *JSC.JSGlobalObject, _: *JSC.CallFrame) callconv(.C) JSC.JSValue {
|
|
JSC.markBinding(@src());
|
|
var name_buffer: [std.os.HOST_NAME_MAX]u8 = undefined;
|
|
return JSC.ZigString.init(C.getVersion(&name_buffer)).withEncoding().toValueGC(globalThis);
|
|
}
|
|
};
|