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 // TODO(petamoriken): enable prefer-primordials for node polyfills
// deno-lint-ignore-file prefer-primordials // 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 { initializeDebugEnv } from "ext:deno_node/internal/util/debuglog.ts";
import { import {
op_getegid, op_getegid,
@ -17,9 +17,14 @@ import { warnNotImplemented } from "ext:deno_node/_utils.ts";
import { EventEmitter } from "node:events"; import { EventEmitter } from "node:events";
import Module, { getBuiltinModule } from "node:module"; import Module, { getBuiltinModule } from "node:module";
import { report } from "ext:deno_node/internal/process/report.ts"; 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 { import {
ERR_INVALID_ARG_TYPE, ERR_INVALID_ARG_TYPE,
ERR_INVALID_ARG_VALUE_RANGE,
ERR_OUT_OF_RANGE, ERR_OUT_OF_RANGE,
ERR_UNKNOWN_SIGNAL, ERR_UNKNOWN_SIGNAL,
errnoException, 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 { buildAllowedFlags } from "ext:deno_node/internal/process/per_thread.mjs";
import { setProcess } from "ext:deno_node/_events.mjs"; import { setProcess } from "ext:deno_node/_events.mjs";
const { NumberMAX_SAFE_INTEGER } = primordials;
const notImplementedEvents = [ const notImplementedEvents = [
"multipleResolves", "multipleResolves",
"worker", "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( function createWarningObject(
warning: string, warning: string,
type: string, type: string,
@ -574,9 +623,7 @@ process.config = {
}, },
}; };
process.cpuUsage = function () { process.cpuUsage = cpuUsage;
return Deno.cpuUsage();
};
/** https://nodejs.org/api/process.html#process_process_cwd */ /** https://nodejs.org/api/process.html#process_process_cwd */
process.cwd = cwd; process.cwd = cwd;

View file

@ -6,6 +6,7 @@ import process, {
arch as importedArch, arch as importedArch,
argv, argv,
argv0 as importedArgv0, argv0 as importedArgv0,
cpuUsage as importedCpuUsage,
env, env,
execArgv as importedExecArgv, execArgv as importedExecArgv,
execPath as importedExecPath, execPath as importedExecPath,
@ -1145,9 +1146,56 @@ Deno.test(function importedExecPathTest() {
}); });
Deno.test("process.cpuUsage()", () => { Deno.test("process.cpuUsage()", () => {
assert(process.cpuUsage.length === 1);
const cpuUsage = process.cpuUsage(); const cpuUsage = process.cpuUsage();
assert(typeof cpuUsage.user === "number"); assert(typeof cpuUsage.user === "number");
assert(typeof cpuUsage.system === "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", () => { Deno.test("process.stdout.columns writable", () => {