2023-02-14 11:38:45 -05:00
// Copyright 2018-2023 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.
2023-06-27 02:18:22 -04:00
// TODO(petamoriken): enable prefer-primordials for node polyfills
// deno-lint-ignore-file prefer-primordials
2023-07-31 16:29:09 -04:00
const core = globalThis . __bootstrap . core ;
2023-03-08 06:44:54 -05:00
import { validateIntegerRange } from "ext:deno_node/_utils.ts" ;
2023-07-02 14:19:30 -04:00
import process from "node:process" ;
2023-03-08 06:44:54 -05:00
import { isWindows , osType } from "ext:deno_node/_util/os.ts" ;
2023-07-31 16:29:09 -04:00
import { ERR_OS_NO_HOMEDIR } from "ext:deno_node/internal/errors.ts" ;
2023-03-08 06:44:54 -05:00
import { os } from "ext:deno_node/internal_binding/constants.ts" ;
2023-03-28 08:44:22 -04:00
import { osUptime } from "ext:runtime/30_os.js" ;
2023-07-31 16:29:09 -04:00
import { Buffer } from "ext:deno_node/internal/buffer.mjs" ;
2023-02-14 11:38:45 -05:00
2023-07-31 16:29:09 -04:00
export const constants = os ;
2023-02-14 11:38:45 -05:00
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 ;
2023-07-31 16:29:09 -04:00
shell : string | null ;
homedir : string | null ;
2023-02-14 11:38:45 -05:00
}
export function arch ( ) : string {
return process . arch ;
}
2023-09-30 10:21:06 -04:00
// deno-lint-ignore no-explicit-any
( availableParallelism as any ) [ Symbol . toPrimitive ] = ( ) : number = >
availableParallelism ( ) ;
2023-02-14 11:38:45 -05:00
// 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 ( ) ;
export function cpus ( ) : CPUCoreInfo [ ] {
2023-09-24 05:23:25 -04:00
return Array . from ( Array ( navigator . hardwareConcurrency ) , ( ) = > {
2023-02-14 11:38:45 -05:00
return {
model : "" ,
speed : 0 ,
times : {
user : 0 ,
nice : 0 ,
sys : 0 ,
idle : 0 ,
irq : 0 ,
} ,
} ;
} ) ;
}
/ * *
* 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 {
2023-11-30 08:06:01 -05:00
if ( Deno . build . os === "linux" ) {
// 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 ;
}
2023-02-14 11:38:45 -05:00
}
/** Not yet implemented */
export function getPriority ( pid = 0 ) : number {
validateIntegerRange ( pid , "pid" ) ;
2023-07-31 16:29:09 -04:00
return core . ops . op_node_os_get_priority ( pid ) ;
2023-02-14 11:38:45 -05:00
}
/** 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 "darwin" :
case "freebsd" :
2023-06-12 06:14:27 -04:00
case "openbsd" :
2023-02-14 11:38:45 -05:00
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 ( ) ;
}
/ * * R e t u r n s a n o b j e c t c o n t a i n i n g n e t w o r k i n t e r f a c e s t h a t h a v e b e e n a s s i g n e d a n e t w o r k a d d r e s s .
* 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 ( ) ;
}
/** Not yet implemented */
export function setPriority ( pid : number , priority? : number ) {
/ * T h e n o d e A P I h a s t h e ' p i d ' a s t h e f i r s t p a r a m e t e r a n d a s o p t i o n a l .
This makes for a problematic implementation in Typescript . * /
if ( priority === undefined ) {
priority = pid ;
pid = 0 ;
}
validateIntegerRange ( pid , "pid" ) ;
validateIntegerRange ( priority , "priority" , - 20 , 19 ) ;
2023-07-31 16:29:09 -04:00
core . ops . op_node_os_set_priority ( pid , priority ) ;
2023-02-14 11:38:45 -05:00
}
/** Returns the operating system's default directory for temporary files as a string. */
export function tmpdir ( ) : string | null {
/ * T h i s f o l l o w s t h e n o d e j s i m p l e m e n t a t i o n , b u t h a s a f e w
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 ( /(?<!:)[/\\]*$/ , "" ) ;
}
const base = Deno . env . get ( "SYSTEMROOT" ) || Deno . env . get ( "WINDIR" ) ;
if ( base ) {
return base + "\\temp" ;
}
return null ;
} else { // !isWindows
const temp = Deno . env . get ( "TMPDIR" ) || Deno . env . get ( "TMP" ) ||
Deno . env . get ( "TEMP" ) || "/tmp" ;
return temp . replace ( /(?<!^)\/*$/ , "" ) ;
}
}
/** Return total physical memory amount */
export function totalmem ( ) : number {
return Deno . systemMemoryInfo ( ) . total ;
}
/** Returns operating system type (i.e. 'Windows_NT', 'Linux', 'Darwin') */
export function type ( ) : string {
switch ( Deno . build . os as string ) {
case "windows" :
return "Windows_NT" ;
case "linux" :
return "Linux" ;
case "darwin" :
return "Darwin" ;
case "freebsd" :
return "FreeBSD" ;
2023-06-12 06:14:27 -04:00
case "openbsd" :
return "OpenBSD" ;
2023-02-14 11:38:45 -05:00
default :
throw Error ( "unreachable" ) ;
}
}
/** Returns the Operating System uptime in number of seconds. */
export function uptime ( ) : number {
2023-03-28 08:44:22 -04:00
return osUptime ( ) ;
2023-02-14 11:38:45 -05:00
}
/** Not yet implemented */
export function userInfo (
options : UserInfoOptions = { encoding : "utf-8" } ,
) : UserInfo {
2023-08-16 05:28:49 -04:00
let uid = Deno . uid ( ) ;
let gid = Deno . gid ( ) ;
2023-07-31 16:29:09 -04:00
if ( isWindows ) {
uid = - 1 ;
gid = - 1 ;
}
// TODO(@crowlKats): figure out how to do this correctly:
// The value of homedir returned by os.userInfo() is provided by the operating system.
// This differs from the result of os.homedir(), which queries environment
// variables for the home directory before falling back to the operating system response.
let _homedir = homedir ( ) ;
if ( ! _homedir ) {
throw new ERR_OS_NO_HOMEDIR ( ) ;
}
let shell = isWindows ? ( Deno . env . get ( "SHELL" ) || null ) : null ;
let username = core . ops . op_node_os_username ( ) ;
if ( options ? . encoding === "buffer" ) {
_homedir = _homedir ? Buffer . from ( _homedir ) : _homedir ;
shell = shell ? Buffer . from ( shell ) : shell ;
username = Buffer . from ( username ) ;
}
return {
uid ,
gid ,
homedir : _homedir ,
shell ,
username ,
} ;
2023-02-14 11:38:45 -05:00
}
2023-09-30 10:21:06 -04:00
/* Returns an estimate of the default amount of parallelism a program should use. */
export function availableParallelism ( ) : number {
return navigator . hardwareConcurrency ;
}
2023-02-14 11:38:45 -05:00
export const EOL = isWindows ? "\r\n" : "\n" ;
export const devNull = isWindows ? "\\\\.\\nul" : "/dev/null" ;
export default {
2023-09-30 10:21:06 -04:00
availableParallelism ,
2023-02-14 11:38:45 -05:00
arch ,
cpus ,
endianness ,
freemem ,
getPriority ,
homedir ,
hostname ,
loadavg ,
networkInterfaces ,
platform ,
release ,
setPriority ,
tmpdir ,
totalmem ,
type ,
uptime ,
userInfo ,
version ,
constants ,
EOL ,
devNull ,
} ;