Sign In

@applitools/utils

Package Overview
Dependencies
Maintainers
47
Versions
95
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@applitools/utils - npm Package Compare versions

Comparing version
1.14.5
to
1.15.0
+72
dist/process-tree.js
"use strict";
// Pure, platform-agnostic helpers for computing the resident memory of a process
// tree. No Node imports — safe to use from both the Node and browser entry points.
// The OS-specific data collection (reading /proc, spawning `ps`/PowerShell) lives
// in `process.ts`; these functions only PARSE that data and sum the tree.
Object.defineProperty(exports, "__esModule", { value: true });
exports.sumTreeRss = exports.parseWindowsCimJson = exports.parsePosixPsOutput = exports.parseLinuxStatus = void 0;
/** Parse a single `/proc/<pid>/status` blob (linux). VmRSS is reported in kB. */
function parseLinuxStatus(statusText) {
const ppidMatch = statusText.match(/^PPid:\s+(\d+)/m);
const rssMatch = statusText.match(/^VmRSS:\s+(\d+)\s*kB/m);
if (!ppidMatch)
return null;
return { ppid: Number(ppidMatch[1]), rss: rssMatch ? Number(rssMatch[1]) * 1024 : 0 };
}
exports.parseLinuxStatus = parseLinuxStatus;
/** Parse `ps -A -o pid=,ppid=,rss=` output (macOS / posix). rss is reported in kB. */
function parsePosixPsOutput(stdout) {
const table = new Map();
for (const line of stdout.split('\n')) {
const match = line.trim().match(/^(\d+)\s+(\d+)\s+(\d+)$/);
if (!match)
continue;
table.set(Number(match[1]), { ppid: Number(match[2]), rss: Number(match[3]) * 1024 });
}
return table;
}
exports.parsePosixPsOutput = parsePosixPsOutput;
/** Parse `Get-CimInstance Win32_Process | ConvertTo-Json` output (windows). WorkingSetSize is bytes. */
function parseWindowsCimJson(stdout) {
const parsed = JSON.parse(stdout);
const rows = Array.isArray(parsed) ? parsed : [parsed];
const table = new Map();
for (const row of rows) {
if (!row || row.ProcessId == null)
continue;
table.set(Number(row.ProcessId), {
ppid: Number(row.ParentProcessId),
rss: Number(row.WorkingSetSize) || 0,
});
}
return table;
}
exports.parseWindowsCimJson = parseWindowsCimJson;
/** Sum rss (bytes) of `rootPid` and all transitive descendants. Cycle-safe. */
function sumTreeRss(table, rootPid) {
const childrenOf = new Map();
for (const [pid, { ppid }] of table) {
if (!childrenOf.has(ppid))
childrenOf.set(ppid, []);
childrenOf.get(ppid).push(pid);
}
let total = 0;
const seen = new Set();
const stack = [rootPid];
while (stack.length) {
const pid = stack.pop();
if (seen.has(pid))
continue;
seen.add(pid);
const info = table.get(pid);
if (info)
total += info.rss;
const kids = childrenOf.get(pid);
if (kids)
for (const kid of kids)
if (!seen.has(kid))
stack.push(kid);
}
return total;
}
exports.sumTreeRss = sumTreeRss;
export type ProcessTableEntry = {
ppid: number;
rss: number;
};
export type ProcessTable = Map<number, ProcessTableEntry>;
/** Parse a single `/proc/<pid>/status` blob (linux). VmRSS is reported in kB. */
export declare function parseLinuxStatus(statusText: string): ProcessTableEntry | null;
/** Parse `ps -A -o pid=,ppid=,rss=` output (macOS / posix). rss is reported in kB. */
export declare function parsePosixPsOutput(stdout: string): ProcessTable;
/** Parse `Get-CimInstance Win32_Process | ConvertTo-Json` output (windows). WorkingSetSize is bytes. */
export declare function parseWindowsCimJson(stdout: string): ProcessTable;
/** Sum rss (bytes) of `rootPid` and all transitive descendants. Cycle-safe. */
export declare function sumTreeRss(table: ProcessTable, rootPid: number): number;
+7
-0
# Changelog
## [1.15.0](https://github.com/Applitools-Dev/sdk/compare/js/utils@1.14.5...js/utils@1.15.0) (2026-06-18)
### Features
* one-time per-execution summary logEvent in storybook | AD-14305 ([#3911](https://github.com/Applitools-Dev/sdk/issues/3911)) ([59e3a5d](https://github.com/Applitools-Dev/sdk/commit/59e3a5dccf74aa1ac1158024316bd305e3515afa))
## [1.14.5](https://github.com/Applitools-Dev/sdk/compare/js/utils@1.14.4...js/utils@1.14.5) (2026-05-26)

@@ -4,0 +11,0 @@

+7
-1
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sh = exports.executeProcess = exports.executeAndControlProcess = exports.execute = void 0;
exports.sampleProcessTreeMemory = exports.sh = exports.executeProcess = exports.executeAndControlProcess = exports.execute = void 0;
const executionOutput = {

@@ -32,1 +32,7 @@ stdout: '',

exports.sh = sh;
// A browser cannot read OS process trees — always resolves "unknown".
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async function sampleProcessTreeMemory(_rootPid, _options = {}) {
return null;
}
exports.sampleProcessTreeMemory = sampleProcessTreeMemory;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.execute = exports.sh = exports.executeProcess = exports.executeAndControlProcess = void 0;
exports.sampleProcessTreeMemory = exports.execute = exports.sh = exports.executeProcess = exports.executeAndControlProcess = void 0;
const child_process_1 = require("child_process");
const fs_1 = require("fs");
const util_1 = require("util");
const process_tree_1 = require("./process-tree");
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
const PROCESS_TABLE_EXEC_OPTS = { timeout: 10000, maxBuffer: 16 * 1024 * 1024, windowsHide: true };
function makeError(error, properties) {

@@ -80,1 +84,74 @@ if (typeof error === 'string') {

exports.execute = execute;
/**
* Best-effort resident memory (bytes) of `rootPid` and all of its descendant
* processes — approximates the real RAM a multi-process app (e.g. a Chromium
* browser: browser + renderers + GPU) consumes, which the V8 JS heap does NOT.
*
* Purely additive observability: resolves to `null` on ANY failure (unsupported
* platform, parse/permission error, missing tools, root process already gone).
* Never throws to the caller. Browser builds always resolve `null`.
*/
async function sampleProcessTreeMemory(rootPid, options = {}) {
var _a;
if (!rootPid || !Number.isInteger(rootPid))
return null;
try {
const table = await getProcessTable();
if (!table || table.size === 0)
return null;
// root gone (e.g. browser already closed) → report "unknown", not a misleading 0
if (!table.has(rootPid))
return null;
return (0, process_tree_1.sumTreeRss)(table, rootPid);
}
catch (err) {
(_a = options.logger) === null || _a === void 0 ? void 0 : _a.log(`[process-tree-memory] failed to sample: ${err && err.message}`);
return null;
}
}
exports.sampleProcessTreeMemory = sampleProcessTreeMemory;
async function getProcessTable() {
switch (process.platform) {
case 'linux':
return getProcessTableLinux();
case 'win32':
return getProcessTableWindows();
case 'darwin':
return getProcessTablePosixPs();
default:
// best-effort: assume a posix-like `ps` on any other platform
return getProcessTablePosixPs();
}
}
// Linux: read /proc/<pid>/status for PPid + VmRSS. No subprocess spawn.
async function getProcessTableLinux() {
const table = new Map();
const entries = await fs_1.promises.readdir('/proc');
await Promise.all(entries.map(async (entry) => {
const pid = Number(entry);
if (!Number.isInteger(pid) || pid <= 0)
return;
try {
const parsed = (0, process_tree_1.parseLinuxStatus)(await fs_1.promises.readFile(`/proc/${pid}/status`, 'utf8'));
if (parsed)
table.set(pid, parsed);
}
catch {
// process may have exited between readdir and readFile — ignore it
}
}));
return table;
}
// macOS / other posix: `ps -A -o pid=,ppid=,rss=` (rss in kB).
async function getProcessTablePosixPs() {
const { stdout } = await execFileAsync('ps', ['-A', '-o', 'pid=,ppid=,rss='], PROCESS_TABLE_EXEC_OPTS);
return (0, process_tree_1.parsePosixPsOutput)(stdout);
}
// Windows: PowerShell + CIM (WorkingSetSize is bytes). Works where wmic is removed.
async function getProcessTableWindows() {
const psCommand = 'Get-CimInstance Win32_Process | ' +
'Select-Object ProcessId,ParentProcessId,WorkingSetSize | ' +
'ConvertTo-Json -Compress';
const { stdout } = await execFileAsync('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', psCommand], PROCESS_TABLE_EXEC_OPTS);
return (0, process_tree_1.parseWindowsCimJson)(stdout);
}
+1
-1
{
"name": "@applitools/utils",
"version": "1.14.5",
"version": "1.15.0",
"keywords": [

@@ -5,0 +5,0 @@ "applitools",

@@ -35,1 +35,6 @@ /// <reference types="node" />

}>;
export declare function sampleProcessTreeMemory(_rootPid: number, _options?: {
logger?: {
log: (...args: any[]) => void;
};
}): Promise<number | null>;

@@ -23,1 +23,15 @@ /// <reference types="node" />

}>;
/**
* Best-effort resident memory (bytes) of `rootPid` and all of its descendant
* processes — approximates the real RAM a multi-process app (e.g. a Chromium
* browser: browser + renderers + GPU) consumes, which the V8 JS heap does NOT.
*
* Purely additive observability: resolves to `null` on ANY failure (unsupported
* platform, parse/permission error, missing tools, root process already gone).
* Never throws to the caller. Browser builds always resolve `null`.
*/
export declare function sampleProcessTreeMemory(rootPid: number, options?: {
logger?: {
log: (...args: any[]) => void;
};
}): Promise<number | null>;