fix(ext/node): support the optional previousValue parameter for process.cpuUsage() (#28550)

This commit is contained in:
Jake Champion 2025-04-01 12:48:09 +01:00 committed by GitHub
parent b880087668
commit 0f40ee7ff4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 100 additions and 5 deletions

View file

@ -4,7 +4,7 @@
// TODO(petamoriken): enable prefer-primordials for node polyfills
// deno-lint-ignore-file prefer-primordials
import { core, internals } from "ext:core/mod.js";
import { core, internals, primordials } from "ext:core/mod.js";
import { initializeDebugEnv } from "ext:deno_node/internal/util/debuglog.ts";
import {
op_getegid,
@ -17,9 +17,14 @@ import { warnNotImplemented } from "ext:deno_node/_utils.ts";
import { EventEmitter } from "node:events";
import Module, { getBuiltinModule } from "node:module";
import { report } from "ext:deno_node/internal/process/report.ts";
import { validateString } from "ext:deno_node/internal/validators.mjs";
import {
validateNumber,
validateObject,
validateString,
} from "ext:deno_node/internal/validators.mjs";
import {
ERR_INVALID_ARG_TYPE,
ERR_INVALID_ARG_VALUE_RANGE,
ERR_OUT_OF_RANGE,
ERR_UNKNOWN_SIGNAL,
errnoException,
@ -79,6 +84,8 @@ import type { BindingName } from "ext:deno_node/internal_binding/mod.ts";
import { buildAllowedFlags } from "ext:deno_node/internal/process/per_thread.mjs";
import { setProcess } from "ext:deno_node/_events.mjs";
const { NumberMAX_SAFE_INTEGER } = primordials;
const notImplementedEvents = [
"multipleResolves",
"worker",
@ -144,6 +151,48 @@ function addReadOnlyProcessAlias(
}
}
interface CpuUsage {
user: number;
system: number;
}
// Ensure that a previously passed in value is valid. Currently, the native
// implementation always returns numbers <= Number.MAX_SAFE_INTEGER.
function previousCpuUsageValueIsValid(num) {
return typeof num === "number" && num >= 0 && num <= NumberMAX_SAFE_INTEGER;
}
export function cpuUsage(previousValue?: CpuUsage): CpuUsage {
const cpuValues = Deno.cpuUsage(previousValue);
if (previousValue) {
if (!previousCpuUsageValueIsValid(previousValue.user)) {
validateObject(previousValue, "previousValue");
validateNumber(previousValue.user, "previousValue.user");
throw new ERR_INVALID_ARG_VALUE_RANGE(
"previousValue.user",
previousValue.user,
);
}
if (!previousCpuUsageValueIsValid(previousValue.system)) {
validateNumber(previousValue.system, "previousValue.system");
throw new ERR_INVALID_ARG_VALUE_RANGE(
"previousValue.system",
previousValue.system,
);
}
return {
user: cpuValues.user - previousValue.user,
system: cpuValues.system - previousValue.system,
};
}
return cpuValues;
}
function createWarningObject(
warning: string,
type: string,
@ -574,9 +623,7 @@ process.config = {
},
};
process.cpuUsage = function () {
return Deno.cpuUsage();
};
process.cpuUsage = cpuUsage;
/** https://nodejs.org/api/process.html#process_process_cwd */
process.cwd = cwd;

View file

@ -6,6 +6,7 @@ import process, {
arch as importedArch,
argv,
argv0 as importedArgv0,
cpuUsage as importedCpuUsage,
env,
execArgv as importedExecArgv,
execPath as importedExecPath,
@ -1145,9 +1146,56 @@ Deno.test(function importedExecPathTest() {
});
Deno.test("process.cpuUsage()", () => {
assert(process.cpuUsage.length === 1);
const cpuUsage = process.cpuUsage();
assert(typeof cpuUsage.user === "number");
assert(typeof cpuUsage.system === "number");
const a = process.cpuUsage();
const b = process.cpuUsage(a);
assert(a.user > b.user);
assert(a.system > b.system);
assertThrows(
() => {
// @ts-ignore TS2322
process.cpuUsage({});
},
TypeError,
);
assertThrows(
() => {
// @ts-ignore TS2322
process.cpuUsage({ user: "1", system: 2 });
},
TypeError,
);
assertThrows(
() => {
// @ts-ignore TS2322
process.cpuUsage({ user: 1, system: "2" });
},
TypeError,
);
for (const invalidNumber of [-1, -Infinity, Infinity, NaN]) {
assertThrows(
() => {
process.cpuUsage({ user: invalidNumber, system: 2 });
},
RangeError,
);
assertThrows(
() => {
process.cpuUsage({ user: 2, system: invalidNumber });
},
RangeError,
);
}
});
Deno.test("importedCpuUsage", () => {
assert(importedCpuUsage === process.cpuUsage);
});
Deno.test("process.stdout.columns writable", () => {