// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. // TODO(petamoriken): enable prefer-primordials for node polyfills // deno-lint-ignore-file prefer-primordials const core = globalThis.__bootstrap.core; import { validateIntegerRange } from "ext:deno_node/_utils.ts"; import process from "node:process"; import { isWindows, osType } from "ext:deno_node/_util/os.ts"; import { ERR_OS_NO_HOMEDIR } from "ext:deno_node/internal/errors.ts"; import { os } from "ext:deno_node/internal_binding/constants.ts"; import { osUptime } from "ext:runtime/30_os.js"; import { Buffer } from "ext:deno_node/internal/buffer.mjs"; const ops = core.ops; export const constants = os; interface CPUTimes { /** The number of milliseconds the CPU has spent in user mode */ user: number; /** The number of milliseconds the CPU has spent in nice mode */ nice: number; /** The number of milliseconds the CPU has spent in sys mode */ sys: number; /** The number of milliseconds the CPU has spent in idle mode */ idle: number; /** The number of milliseconds the CPU has spent in irq mode */ irq: number; } interface CPUCoreInfo { model: string; /** in MHz */ speed: number; times: CPUTimes; } interface NetworkAddress { /** The assigned IPv4 or IPv6 address */ address: string; /** The IPv4 or IPv6 network mask */ netmask: string; family: "IPv4" | "IPv6"; /** The MAC address of the network interface */ mac: string; /** true if the network interface is a loopback or similar interface that is not remotely accessible; otherwise false */ internal: boolean; /** The numeric IPv6 scope ID (only specified when family is IPv6) */ scopeid?: number; /** The assigned IPv4 or IPv6 address with the routing prefix in CIDR notation. If the netmask is invalid, this property is set to null. */ cidr: string; } interface NetworkInterfaces { [key: string]: NetworkAddress[]; } export interface UserInfoOptions { encoding: string; } interface UserInfo { username: string; uid: number; gid: number; shell: string | null; homedir: string | null; } export function arch(): string { return process.arch; } // deno-lint-ignore no-explicit-any (availableParallelism as any)[Symbol.toPrimitive] = (): number => availableParallelism(); // deno-lint-ignore no-explicit-any (arch as any)[Symbol.toPrimitive] = (): string => process.arch; // deno-lint-ignore no-explicit-any (endianness as any)[Symbol.toPrimitive] = (): string => endianness(); // deno-lint-ignore no-explicit-any (freemem as any)[Symbol.toPrimitive] = (): number => freemem(); // deno-lint-ignore no-explicit-any (homedir as any)[Symbol.toPrimitive] = (): string | null => homedir(); // deno-lint-ignore no-explicit-any (hostname as any)[Symbol.toPrimitive] = (): string | null => hostname(); // deno-lint-ignore no-explicit-any (platform as any)[Symbol.toPrimitive] = (): string => platform(); // deno-lint-ignore no-explicit-any (release as any)[Symbol.toPrimitive] = (): string => release(); // deno-lint-ignore no-explicit-any (version as any)[Symbol.toPrimitive] = (): string => version(); // deno-lint-ignore no-explicit-any (totalmem as any)[Symbol.toPrimitive] = (): number => totalmem(); // deno-lint-ignore no-explicit-any (type as any)[Symbol.toPrimitive] = (): string => type(); // deno-lint-ignore no-explicit-any (uptime as any)[Symbol.toPrimitive] = (): number => uptime(); // deno-lint-ignore no-explicit-any (machine as any)[Symbol.toPrimitive] = (): string => machine(); export function cpus(): CPUCoreInfo[] { return ops.op_cpus(); } /** * Returns a string identifying the endianness of the CPU for which the Deno * binary was compiled. Possible values are 'BE' for big endian and 'LE' for * little endian. */ export function endianness(): "BE" | "LE" { // Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView#Endianness const buffer = new ArrayBuffer(2); new DataView(buffer).setInt16(0, 256, true /* littleEndian */); // Int16Array uses the platform's endianness. return new Int16Array(buffer)[0] === 256 ? "LE" : "BE"; } /** Return free memory amount */ export function freemem(): number { if (Deno.build.os === "linux" || Deno.build.os == "android") { // On linux, use 'available' memory // https://github.com/libuv/libuv/blob/a5c01d4de3695e9d9da34cfd643b5ff0ba582ea7/src/unix/linux.c#L2064 return Deno.systemMemoryInfo().available; } else { // Use 'free' memory on other platforms return Deno.systemMemoryInfo().free; } } /** Not yet implemented */ export function getPriority(pid = 0): number { validateIntegerRange(pid, "pid"); return core.ops.op_node_os_get_priority(pid); } /** Returns the string path of the current user's home directory. */ export function homedir(): string | null { // Note: Node/libuv calls getpwuid() / GetUserProfileDirectory() when the // environment variable isn't set but that's the (very uncommon) fallback // path. IMO, it's okay to punt on that for now. switch (osType) { case "windows": return Deno.env.get("USERPROFILE") || null; case "linux": case "android": case "darwin": case "freebsd": case "openbsd": return Deno.env.get("HOME") || null; default: throw Error("unreachable"); } } /** Returns the host name of the operating system as a string. */ export function hostname(): string { return Deno.hostname(); } /** Returns an array containing the 1, 5, and 15 minute load averages */ export function loadavg(): number[] { if (isWindows) { return [0, 0, 0]; } return Deno.loadavg(); } /** Returns an object containing network interfaces that have been assigned a network address. * Each key on the returned object identifies a network interface. The associated value is an array of objects that each describe an assigned network address. */ export function networkInterfaces(): NetworkInterfaces { const interfaces: NetworkInterfaces = {}; for ( const { name, address, netmask, family, mac, scopeid, cidr } of Deno .networkInterfaces() ) { const addresses = interfaces[name] ||= []; const networkAddress: NetworkAddress = { address, netmask, family, mac, internal: (family === "IPv4" && isIPv4LoopbackAddr(address)) || (family === "IPv6" && isIPv6LoopbackAddr(address)), cidr, }; if (family === "IPv6") { networkAddress.scopeid = scopeid!; } addresses.push(networkAddress); } return interfaces; } function isIPv4LoopbackAddr(addr: string) { return addr.startsWith("127"); } function isIPv6LoopbackAddr(addr: string) { return addr === "::1" || addr === "fe80::1"; } /** Returns the a string identifying the operating system platform. The value is set at compile time. Possible values are 'darwin', 'linux', and 'win32'. */ export function platform(): string { return process.platform; } /** Returns the operating system as a string */ export function release(): string { return Deno.osRelease(); } /** Returns a string identifying the kernel version */ export function version(): string { // TODO(kt3k): Temporarily uses Deno.osRelease(). // Revisit this if this implementation is insufficient for any npm module return Deno.osRelease(); } /** Returns the machine type as a string */ export function machine(): string { if (Deno.build.arch == "aarch64") { return "arm64"; } return Deno.build.arch; } /** Not yet implemented */ export function setPriority(pid: number, priority?: number) { /* The node API has the 'pid' as the first parameter and as optional. This makes for a problematic implementation in Typescript. */ if (priority === undefined) { priority = pid; pid = 0; } validateIntegerRange(pid, "pid"); validateIntegerRange(priority, "priority", -20, 19); core.ops.op_node_os_set_priority(pid, priority); } /** Returns the operating system's default directory for temporary files as a string. */ export function tmpdir(): string | null { /* This follows the node js implementation, but has a few differences: * On windows, if none of the environment variables are defined, we return null. * On unix we use a plain Deno.env.get, instead of safeGetenv, which special cases setuid binaries. * Node removes a single trailing / or \, we remove all. */ if (isWindows) { const temp = Deno.env.get("TEMP") || Deno.env.get("TMP"); if (temp) { return temp.replace(/(?