From 7a3bc31181b4ac711d6db4ee50e2734e93f555cb Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Fri, 21 Jul 2023 07:35:36 -0700 Subject: [PATCH 1/2] Add dependency on foreign --- bower.json | 1 + 1 file changed, 1 insertion(+) diff --git a/bower.json b/bower.json index 90b86d6..58d1104 100644 --- a/bower.json +++ b/bower.json @@ -14,6 +14,7 @@ "dependencies": { "purescript-effect": "^4.0.0", "purescript-foreign-object": "^4.0.0", + "purescript-foreign": "^7.0.0", "purescript-maybe": "^6.0.0", "purescript-node-streams": "^7.0.0", "purescript-posix-types": "^6.0.0", From e48a01622ee08bb1a39f746cc7e6a0147e094918 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Fri, 21 Jul 2023 07:44:49 -0700 Subject: [PATCH 2/2] Implement missing APIs; break 'exit' --- CHANGELOG.md | 49 ++++++ src/Node/Process.js | 43 ++++- src/Node/Process.purs | 364 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 430 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ac22e80..9ea5fec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,16 +5,65 @@ Notable changes to this project are documented in this file. The format is based ## [Unreleased] Breaking changes: +- Breaking changes to `exit` (#39 by @JordanMartinez) + + The `exit` API provides two versions: + - unspecified exit code: `process.exit();` + - specified exit code: `process.exit(1);` + + Previously, the type signature of `exit` only allowed + the second usage. This change supports both. + Followin the pattern used in other Node libraries + of a `'` (prime) character indicating a + variant of the function that takes a callback or optons + are, the type signature of `exit` has changed: + + ```purs + -- before: + exit :: forall a. Int -> Effect a + + -- after: + exit :: forall a. Effect a + + exit' :: forall a. Int -> Effect a + ``` New features: +- Add missing APIs (#39 by @JordanMartinez) + + - Process-related things + - `abort` + - `setExitCode` + - `getExitCode` + - `kill`/`killStr`/`kilInt` + - `nextTick'` + - `ppid` + - Uncaught exception capture callback + - `hasUncaughtExceptionCaptureCallback` + - `setUncaughtExceptionCaptureCallback` + - `clearUncaughtExceptionCaptureCallback` + - `getTitle`/`setTitle` + - ChildProcess-related things + - `channelRef`/`channelUnref` + - `connected` + - `unsafeSend`/`unsafeSendOpts`/`unsafeSendCb`/`unsafeSendOptsCb` + - Diagnostic-related things + - `config` + - `cpuUsage`/`cpuUsageDiff` + - `debugPort` + - `memoryUsage`/`memoryUsageRss` + - `resourceUsage` + - `uptime` Bugfixes: +- Docs: discourage `exit` in favor of `setExitCode` (#39 by @JordanMartinez) Other improvements: - Bumped CI's node version to `lts/*` (#37 by @JordanMartinez) - Updated CI `actions/checkout` and `actions/setup-nodee` to `v3` (#37 by @JordanMartinez) - Format codebase & enforce formatting in CI via purs-tidy (#37 by @JordanMartinez) - Use uncurried FFI (#38 by @JordanMartinez) +- Reordered export list (#39 by @JordanMartinez) ## [v10.0.0](https://github.com/purescript-node/purescript-node-process/releases/tag/v10.0.0) - 2022-04-29 diff --git a/src/Node/Process.js b/src/Node/Process.js index 0d5babf..7a7c178 100644 --- a/src/Node/Process.js +++ b/src/Node/Process.js @@ -36,12 +36,19 @@ export function onSignalImpl(signal) { }; } -export const nextTickImpl = (cb) => process.nextTick(cb); +export const abortImpl = process.abort ? () => process.abort() : null; export const argv = () => process.argv.slice(); -export const execArgv = () => process.execArgv.slice(); -export const execPath = () => process.execPath; +export const argv0 = () => process.argv0; +export const channelRefImpl = process.channel.ref ? () => process.channel.ref() : null; +export const channelUnrefImpl = process.channel.unref ? () => process.channel.unref() : null; export const chdirImpl = (dir) => process.chdir(dir); +export const config = () => Object.assign({}, process.config); +export const connected = () => process.connected; +export const cpuUsage = () => process.cpuUsage(); +export const cpuUsageDiffImpl = (prevVal) => process.cpuUsage(prevVal); export const cwd = () => process.cwd; +export const debugPort = process.debugPort; +export const disconnectImpl = process.disconnect ? () => process.disconnect() : null; export const getEnv = () => Object.assign({}, process.env); export const unsafeGetEnv = () => process.env; export const setEnvImpl = (key, val) => { @@ -50,14 +57,42 @@ export const setEnvImpl = (key, val) => { export const unsetEnvImpl = (key) => { delete process.env[key]; }; +export const execArgv = () => process.execArgv.slice(); +export const execPath = () => process.execPath; +export const exit = () => process.exit(); +export const exitImpl = (code) => process.exit(code); +export const setExitCodeImpl = (code) => { + process.exitCode = code; +}; +export const getExitCodeImpl = () => process.exitCode; +export const hasUncaughtExceptionCaptureCallback = () => process.hasUncaughtExceptionCaptureCallback; +export const killImpl = (pid) => process.kill(pid); +export const killStrImpl = (pid, sig) => process.kill(pid, sig); +export const killIntImpl = (pid, int) => process.kill(pid, int); +export const memoryUsage = () => process.memoryUsage(); +export const memoryUsageRss = () => process.memoryUsage.rss(); +export const nextTickImpl = (cb) => process.nextTick(cb); +export const nextTickCbImpl = (cb, args) => process.nextTick(cb, args); export const pid = process.pid; export const platformStr = process.platform; -export const exitImpl = (code) => process.exit(code); +export const ppid = process.ppid; +export const resourceUsage = () => process.resourceUsage; +export const sendImpl = (msg, handle) => process.send(msg, handle); +export const sendOptsImpl = (msg, handle, opts) => process.send(msg, handle, opts); +export const sendCbImpl = (msg, handle, cb) => process.send(msg, handle, cb); +export const sendOptsCbImpl = (msg, handle, opts, cb) => process.send(msg, handle, opts, cb); +export const setUncaughtExceptionCaptureCallbackImpl = (cb) => process.setUncaughtExceptionCaptureCallback(cb); +export const clearUncaughtExceptionCaptureCallback = () => process.setUncaughtExceptionCaptureCallback(null); export const stdin = process.stdin; export const stdout = process.stdout; export const stderr = process.stderr; export const stdinIsTTY = process.stdinIsTTY; export const stdoutIsTTY = process.stdoutIsTTY; export const stderrIsTTY = process.stderrIsTTY; +export const getTitle = () => process.title; +export const setTitleImpl = (v) => { + process.title = v; +}; +export const uptime = () => process.uptime(); export const version = process.version; diff --git a/src/Node/Process.purs b/src/Node/Process.purs index 991c2cb..0484cca 100644 --- a/src/Node/Process.purs +++ b/src/Node/Process.purs @@ -5,41 +5,81 @@ module Node.Process , onSignal , onUncaughtException , onUnhandledRejection - , nextTick + , abort , argv - , execArgv - , execPath + , argv0 + , channelRef + , channelUnref , chdir + , config + , connected + , CpuUsage + , cpuUsageToRecord + , cpuUsage + , cpuUsageDiff , cwd + , debugPort + , disconnect , getEnv , lookupEnv , setEnv , unsetEnv + , execArgv + , execPath + , exit + , exit' + , setExitCode + , getExitCode + , hasUncaughtExceptionCaptureCallback + , kill + , killStr + , killInt + , MemoryUsage + , memoryUsage + , memoryUsageRss + , nextTick + , nextTick' , pid , platform - , exit + , platformStr + , ppid + , ResourceUsage + , resourceUsage + , unsafeSend + , JsSendOptions + , unsafeSendOpts + , unsafeSendCb + , unsafeSendOptsCb + , setUncaughtExceptionCaptureCallback + , clearUncaughtExceptionCaptureCallback , stdin , stdout , stderr , stdinIsTTY , stdoutIsTTY , stderrIsTTY + , getTitle + , setTitle + , uptime , version ) where import Prelude import Data.Maybe (Maybe) +import Data.Nullable (Nullable, toMaybe) import Data.Posix (Pid) import Data.Posix.Signal (Signal) import Data.Posix.Signal as Signal import Effect (Effect) import Effect.Exception (Error) -import Effect.Uncurried (EffectFn1, EffectFn2, runEffectFn1, runEffectFn2) +import Effect.Uncurried (EffectFn1, EffectFn2, EffectFn3, EffectFn4, mkEffectFn1, runEffectFn1, runEffectFn2, runEffectFn3, runEffectFn4) +import Foreign (Foreign) import Foreign.Object as FO import Node.Platform (Platform) import Node.Platform as Platform import Node.Stream (Readable, Writable) +import Prim.Row as Row -- | Register a callback to be performed when the event loop empties, and -- | Node.js is about to exit. Asynchronous calls can be made in the callback, @@ -77,22 +117,41 @@ foreign import onSignalImpl :: String -> Effect Unit -> Effect Unit onSignal :: Signal -> Effect Unit -> Effect Unit onSignal sig = onSignalImpl (Signal.toString sig) --- | Register a callback to run as soon as the current event loop runs to --- | completion. -nextTick :: Effect Unit -> Effect Unit -nextTick cb = runEffectFn1 nextTickImpl cb +-- | The `process.abort()` method causes the Node.js process to exit immediately and generate a core file. +-- | This feature is not available in Worker threads. +abort :: Maybe (Effect Unit) +abort = toMaybe abortImpl -foreign import nextTickImpl :: EffectFn1 (Effect Unit) (Unit) +foreign import abortImpl :: Nullable (Effect Unit) -- | Get a copy of the array containing the command line arguments. foreign import argv :: Effect (Array String) --- | Get a copy of the Node-specific options passed to the `node` executable. -foreign import execArgv :: Effect (Array String) +-- | The process.argv0 property stores a read-only copy of the original value of argv[0] passed when Node.js starts. +foreign import argv0 :: Effect String --- | The absolute pathname of the `node` executable that started the --- | process. -foreign import execPath :: Effect (String) +-- | This method makes the IPC channel keep the event loop of the process running if .unref() has been called before. +-- | Typically, this is managed through the number of 'disconnect' and 'message' listeners on the process object. +-- | However, this method can be used to explicitly request a specific behavior. +-- | +-- | Context: if the Node.js process was spawned with an IPC channel (see the Child Process documentation), +-- | the process.channel property is a reference to the IPC channel. If no IPC channel exists, this property is undefined. +channelRef :: Maybe (Effect Unit) +channelRef = toMaybe channelRefImpl + +foreign import channelRefImpl :: Nullable (Effect Unit) + +-- | This method makes the IPC channel not keep the event loop of the process running, +-- | and lets it finish even while the channel is open. +-- | Typically, this is managed through the number of 'disconnect' and 'message' listeners on the process object. +-- | However, this method can be used to explicitly request a specific behavior. +-- | +-- | Context: if the Node.js process was spawned with an IPC channel (see the Child Process documentation), +-- | the process.channel property is a reference to the IPC channel. If no IPC channel exists, this property is undefined. +channelUnref :: Maybe (Effect Unit) +channelUnref = toMaybe channelUnrefImpl + +foreign import channelUnrefImpl :: Nullable (Effect Unit) -- | Change the current working directory of the process. If the current -- | directory could not be changed, an exception will be thrown. @@ -101,9 +160,45 @@ chdir dir = runEffectFn1 chdirImpl dir foreign import chdirImpl :: EffectFn1 (String) (Unit) +-- | Returns a copy of the Config value. +-- | The process.config property returns an Object containing the JavaScript representation of the configure options used to compile the current Node.js executable. +-- | This is the same as the config.gypi file that was produced when running the ./configure script. +foreign import config :: Effect (Foreign) + +-- | If the Node.js process is spawned with an IPC channel (see the Child Process and Cluster documentation), the process.connected property will return true so long as the IPC channel is connected and will return false after process.disconnect() is called. +-- | Once process.connected is false, it is no longer possible to send messages over the IPC channel using process.send(). +foreign import connected :: Effect (Boolean) + +newtype CpuUsage = CpuUsage { user :: Int, system :: Int } + +derive instance Eq CpuUsage +instance Show CpuUsage where + show (CpuUsage r) = "(CpuUsage " <> show r <> ")" + +cpuUsageToRecord :: CpuUsage -> { user :: Int, system :: Int } +cpuUsageToRecord (CpuUsage r) = r + +foreign import cpuUsage :: Effect (CpuUsage) + +cpuUsageDiff :: CpuUsage -> Effect CpuUsage +cpuUsageDiff prev = runEffectFn1 cpuUsageDiffImpl prev + +foreign import cpuUsageDiffImpl :: EffectFn1 (CpuUsage) (CpuUsage) + -- | Get the current working directory of the process. foreign import cwd :: Effect (String) +foreign import debugPort :: Int + +-- | If the Node.js process is spawned with an IPC channel (see the Child Process and Cluster documentation), the process.disconnect() method will close the IPC channel to the parent process, allowing the child process to exit gracefully once there are no other connections keeping it alive. +-- | The effect of calling process.disconnect() is the same as calling ChildProcess.disconnect() from the parent process. +-- | +-- | If the Node.js process was not spawned with an IPC channel, process.disconnect() will be undefined. +disconnect :: Maybe (Effect Unit) +disconnect = toMaybe disconnectImpl + +foreign import disconnectImpl :: Nullable (Effect Unit) + -- | Get a copy of the current environment. -- | If you only want to look up a value without paying -- | for the overhead of the copy, use `lookupEnv`. @@ -135,6 +230,120 @@ unsetEnv key = runEffectFn1 unsetEnvImpl key foreign import unsetEnvImpl :: EffectFn1 (String) (Unit) +-- | Get a copy of the Node-specific options passed to the `node` executable. +foreign import execArgv :: Effect (Array String) + +-- | The absolute pathname of the `node` executable that started the +-- | process. +foreign import execPath :: Effect (String) + +-- | Cause the process to exit immediately without completing any pending asynchronous operations +-- | including I/O operations to `process.stdout` and `process.stderr`. +-- | Process will exit with the `process.exitCode` value if it has been set +-- | or `0` (i.e. exit successfully) otherwise. +-- | +-- | Rather than using this function to exit, one should set `process.exitCode` and +-- | let Node gracefully exit once all pending asynchronous operations have completed. +-- | If it is necessary to terminate the Node.js process due to an error condition, +-- | throwing an uncaught error and allowing the process to terminate accordingly +-- | is safer than calling process.exit(). +foreign import exit :: forall a. Effect a + +-- | Cause the process to exit immediately without completing any pending asynchronous operations +-- | including I/O operations to `process.stdout` and `process.stderr`. +-- | An exit code of 0 is normally considered successful, and anything else is considered a +-- | failure. +-- | +-- | Rather than using this function to exit, one should set `process.exitCode` and +-- | let Node gracefully exit once all pending asynchronous operations have completed. +-- | If it is necessary to terminate the Node.js process due to an error condition, +-- | throwing an uncaught error and allowing the process to terminate accordingly +-- | is safer than calling process.exit(). +exit' :: forall a. Int -> Effect a +exit' code = runEffectFn1 exitImpl code + +foreign import exitImpl :: forall a. EffectFn1 (Int) (a) + +-- | Sets the exit code to use when the process exits. +-- | An exit code of 0 is normally considered successful, and anything else is considered a +-- | failure. +-- | +-- | In comparison to `exit`/`exit'`, this is the safer way +-- | to exit a Node.js process because any pending asynchronous operations +-- | including I/O operations to `process.stdout` and `process.stderr` +-- | will complete before the `Node.js` process exits. +setExitCode :: Int -> Effect Unit +setExitCode code = runEffectFn1 setExitCodeImpl code + +foreign import setExitCodeImpl :: EffectFn1 (Int) (Unit) + +-- | Gets the currently set exit code. This will be `Nothing` +-- | if the exit code has not been previously set. +getExitCode :: Effect (Maybe Int) +getExitCode = map toMaybe getExitCodeImpl + +foreign import getExitCodeImpl :: Effect (Nullable Int) + +foreign import hasUncaughtExceptionCaptureCallback :: Effect (Boolean) + +kill :: Pid -> Effect Unit +kill p = runEffectFn1 killImpl p + +foreign import killImpl :: EffectFn1 (Pid) (Unit) + +killStr :: Pid -> String -> Effect Unit +killStr p sig = runEffectFn2 killStrImpl p sig + +foreign import killStrImpl :: EffectFn2 (Pid) (String) (Unit) + +killInt :: Pid -> Int -> Effect Unit +killInt p sig = runEffectFn2 killIntImpl p sig + +foreign import killIntImpl :: EffectFn2 (Pid) (Int) (Unit) + +-- | - `heapTotal` and `heapUsed` refer to V8's memory usage. +-- | - `external` refers to the memory usage of C++ objects bound to JavaScript objects managed by V8. +-- | - `rss`, Resident Set Size, is the amount of space occupied in the main memory device (that is a subset of the total allocated memory) for the process, including all C++ and JavaScript objects and code. +-- | - `arrayBuffers` refers to memory allocated for ArrayBuffers and SharedArrayBuffers, including all Node.js Buffers. This is also included in the external value. When Node.js is used as an embedded library, this value may be 0 because allocations for ArrayBuffers may not be tracked in that case. +type MemoryUsage = + { rss :: Int + , heapTotal :: Int + , heapUsed :: Int + , external :: Int + , arrayBuffers :: Int + } + +-- | Returns an object describing the memory usage of the Node.js process measured in bytes. +-- | When using Worker threads, `rss` will be a value that is valid for the entire process, while the other fields will only refer to the current thread. +-- | The process.memoryUsage() method iterates over each page to gather information about memory usage which might be slow depending on the program memory allocations. +-- | +-- | Note: if one just wants the `rss` value, use `memoryUsageRss`, which is faster to compute. +foreign import memoryUsage :: Effect (MemoryUsage) + +-- | The process.memoryUsage.rss() method returns an integer representing the Resident Set Size (RSS) in bytes. +-- | The Resident Set Size, is the amount of space occupied in the main memory device (that is a subset of the total allocated memory) for the process, including all C++ and JavaScript objects and code. +-- | This is the same value as the rss property provided by process.memoryUsage() but process.memoryUsage.rss() is faster. +foreign import memoryUsageRss :: Effect Int + +-- | Register a callback to run as soon as the current event loop runs to +-- | completion. +-- | One should use `queueMicroTask` instead for most situations instead of `nextTick`. +-- | See Node docs for more info. +nextTick :: Effect Unit -> Effect Unit +nextTick cb = runEffectFn1 nextTickImpl cb + +foreign import nextTickImpl :: EffectFn1 (Effect Unit) (Unit) + +-- | Register a callback that will receive the record arg as an argument +-- | to run as soon as the current event loop runs to completion. +-- | One should use `queueMicroTask` instead for most situations instead of `nextTick`. +-- | See Node docs for more info. +nextTick' :: forall r. ({ | r } -> Effect Unit) -> { | r } -> Effect Unit +nextTick' cb args = runEffectFn2 nextTickCbImpl (mkEffectFn1 cb) args + +foreign import nextTickCbImpl :: forall r. EffectFn2 (EffectFn1 { | r } Unit) ({ | r }) (Unit) + +-- | Returns the PID of the current process. foreign import pid :: Pid platform :: Maybe Platform @@ -142,13 +351,100 @@ platform = Platform.fromString platformStr foreign import platformStr :: String --- | Cause the process to exit with the supplied integer code. An exit code --- | of 0 is normally considered successful, and anything else is considered a --- | failure. -exit :: forall a. Int -> Effect a -exit code = runEffectFn1 exitImpl code - -foreign import exitImpl :: forall a. EffectFn1 (Int) (a) +-- | Returns the PID of the parent of the current process. +foreign import ppid :: Pid + +-- | - `userCPUTime` maps to ru_utime computed in microseconds. It is the same value as process.cpuUsage().user. +-- | - `systemCPUTime` maps to ru_stime computed in microseconds. It is the same value as process.cpuUsage().system. +-- | - `maxRSS` maps to ru_maxrss which is the maximum resident set size used in kilobytes. +-- | - `sharedMemorySize` maps to ru_ixrss but is not supported by any platform. +-- | - `unsharedDataSize` maps to ru_idrss but is not supported by any platform. +-- | - `unsharedStackSize` maps to ru_isrss but is not supported by any platform. +-- | - `minorPageFault` maps to ru_minflt which is the number of minor page faults for the process, see this article for more details. +-- | - `majorPageFault` maps to ru_majflt which is the number of major page faults for the process, see this article for more details. This field is not supported on Windows. +-- | - `swappedOut` maps to ru_nswap but is not supported by any platform. +-- | - `fsRead` maps to ru_inblock which is the number of times the file system had to perform input. +-- | - `fsWrite` maps to ru_oublock which is the number of times the file system had to perform output. +-- | - `ipcSent` maps to ru_msgsnd but is not supported by any platform. +-- | - `ipcReceived` maps to ru_msgrcv but is not supported by any platform. +-- | - `signalsCount` maps to ru_nsignals but is not supported by any platform. +-- | - `voluntaryContextSwitches` maps to ru_nvcsw which is the number of times a CPU context switch resulted due to a process voluntarily giving up the processor before its time slice was completed (usually to await availability of a resource). This field is not supported on Windows. +-- | - `involuntaryContextSwitches` maps to ru_nivcsw which is the number of times a CPU context switch resulted due to a higher priority process becoming runnable or because the current process exceeded its time slice. This field is not supported on Windows. + +type ResourceUsage = + { userCPUTime :: Int + , systemCPUTime :: Int + , maxRSS :: Int + , sharedMemorySize :: Int + , unsharedDataSize :: Int + , unsharedStackSize :: Int + , minorPageFault :: Int + , majorPageFault :: Int + , swappedOut :: Int + , fsRead :: Int + , fsWrite :: Int + , ipcSent :: Int + , ipcReceived :: Int + , signalsCount :: Int + , voluntaryContextSwitches :: Int + , involuntaryContextSwitches :: Int + } + +foreign import resourceUsage :: Effect (ResourceUsage) + +-- | Unsafe because child process must be a Node child process and an IPC channel must exist. +unsafeSend :: forall messageRows. { | messageRows } -> Nullable Foreign -> Effect Boolean +unsafeSend msg handle = runEffectFn2 sendImpl msg handle + +foreign import sendImpl :: forall messageRows. EffectFn2 ({ | messageRows }) (Nullable Foreign) (Boolean) + +-- | - `keepAlive` A value that can be used when passing instances of `net.Socket` as the `Handle`. When true, the socket is kept open in the sending process. Default: false. +type JsSendOptions = + ( keepAlive :: Boolean + ) + +-- | Unsafe because process must be a Node child process and an IPC channel must exist. +unsafeSendOpts + :: forall r trash messageRows + . Row.Union r trash JsSendOptions + => { | messageRows } + -> Nullable Foreign + -> { | r } + -> Effect Boolean +unsafeSendOpts msg handle opts = runEffectFn3 sendOptsImpl msg handle opts + +foreign import sendOptsImpl :: forall messageRows r. EffectFn3 ({ | messageRows }) (Nullable Foreign) ({ | r }) (Boolean) + +-- | Unsafe because process must be a Node child process and an IPC channel must exist. +unsafeSendCb + :: forall messageRows + . { | messageRows } + -> Nullable Foreign + -> (Maybe Error -> Effect Unit) + -> Effect Boolean +unsafeSendCb msg handle cb = runEffectFn3 sendCbImpl msg handle $ mkEffectFn1 \err -> cb $ toMaybe err + +foreign import sendCbImpl :: forall messageRows. EffectFn3 ({ | messageRows }) (Nullable Foreign) (EffectFn1 (Nullable Error) Unit) (Boolean) + +-- | Unsafe because process must be a Node child process and an IPC channel must exist. +unsafeSendOptsCb + :: forall r trash messageRows + . Row.Union r trash JsSendOptions + => { | messageRows } + -> Nullable Foreign + -> { | r } + -> (Maybe Error -> Effect Unit) + -> Effect Boolean +unsafeSendOptsCb msg handle opts cb = runEffectFn4 sendOptsCbImpl msg handle opts $ mkEffectFn1 \err -> cb $ toMaybe err + +foreign import sendOptsCbImpl :: forall messageRows r. EffectFn4 ({ | messageRows }) (Nullable Foreign) ({ | r }) (EffectFn1 (Nullable Error) Unit) (Boolean) + +setUncaughtExceptionCaptureCallback :: Effect Unit -> Effect Unit +setUncaughtExceptionCaptureCallback cb = runEffectFn1 setUncaughtExceptionCaptureCallbackImpl cb + +foreign import setUncaughtExceptionCaptureCallbackImpl :: EffectFn1 (Effect Unit) (Unit) + +foreign import clearUncaughtExceptionCaptureCallback :: Effect Unit -- | The standard input stream. Note that this stream will never emit an `end` -- | event, so any handlers attached via `onEnd` will never be called. @@ -176,5 +472,29 @@ foreign import stdoutIsTTY :: Boolean -- | (e.g. for coloured text in the terminal). foreign import stderrIsTTY :: Boolean +-- | The process.title property returns the current process title (i.e. returns the current value of ps). +foreign import getTitle :: Effect (String) + +-- | The process.title property returns the current process title (i.e. returns the current value of ps). +-- | Assigning a new value to process.title modifies the current value of ps. +-- | +-- | When a new value is assigned, different platforms will impose different maximum length restrictions +-- | on the title. Usually such restrictions are quite limited. For instance, on Linux and macOS, +-- | process.title is limited to the size of the binary name plus the length of the command-line arguments +-- | because setting the process.title overwrites the argv memory of the process. +-- | Node.js v0.8 allowed for longer process title strings by also overwriting the environ memory but +-- | that was potentially insecure and confusing in some (rather obscure) cases. +-- | +-- | Assigning a value to process.title might not result in an accurate label within process manager +-- | applications such as macOS Activity Monitor or Windows Services Manager. +setTitle :: String -> Effect Unit +setTitle newTitle = runEffectFn1 setTitleImpl newTitle + +foreign import setTitleImpl :: EffectFn1 (String) (Unit) + +-- | The process.uptime() method returns the number of seconds the current Node.js process has been running. +-- | The return value includes fractions of a second. Use `Data.Int.floor` to get whole seconds. +foreign import uptime :: Effect (Number) + -- | Get the Node.js version. foreign import version :: String