From 687ae870d1e4e856b7ceee0a5511138459c68cb1 Mon Sep 17 00:00:00 2001 From: Daniel Mizerski Date: Fri, 1 Dec 2023 07:36:11 +0100 Subject: [PATCH] fix(ext/node): add stubbed process.report (#21373) Co-authored-by: Yoshiya Hinosawa --- cli/tests/unit_node/process_test.ts | 102 ++++++++++++++++++ ext/node/lib.rs | 1 + ext/node/polyfills/internal/process/report.ts | 84 +++++++++++++++ ext/node/polyfills/process.ts | 5 + tools/core_import_map.json | 1 + 5 files changed, 193 insertions(+) create mode 100644 ext/node/polyfills/internal/process/report.ts diff --git a/cli/tests/unit_node/process_test.ts b/cli/tests/unit_node/process_test.ts index ffb95413aa..e79ff34680 100644 --- a/cli/tests/unit_node/process_test.ts +++ b/cli/tests/unit_node/process_test.ts @@ -825,3 +825,105 @@ Deno.test({ assertEquals(uv.errname(-1), "EPERM"); }, }); + +Deno.test({ + name: "process.report", + fn() { + // The process.report is marked as possibly undefined in node 18 typings + if (!process.report) throw "No process report"; + + assert(typeof process.report.directory === "string"); + assert(typeof process.report.filename === "string"); + assert(typeof process.report.getReport === "function"); + assert(typeof process.report.reportOnFatalError === "boolean"); + assert(typeof process.report.reportOnSignal === "boolean"); + assert(typeof process.report.reportOnUncaughtException === "boolean"); + assert(typeof process.report.signal === "string"); + assert(typeof process.report.writeReport === "function"); + }, +}); + +Deno.test({ + name: "process.report.writeReport unimplemented result", + fn() { + // The process.report is marked as possibly undefined in node 18 typings + if (!process.report) throw "No process report"; + + assertEquals(process.report.writeReport(), ""); + }, +}); + +Deno.test({ + name: "process.report.getReport result", + fn() { + // The process.report is marked as possibly undefined in node 18 typings + if (!process.report) throw "No process report"; + + // deno-lint-ignore no-explicit-any + const result = process.report.getReport() as any; + + // test and remove dynamic parts + assert(typeof result.header.filename === "string"); + delete result.header.filename; + assert(typeof result.header.dumpEventTime === "object"); + delete result.header.dumpEventTime; + assert(typeof result.header.dumpEventTimeStamp === "number"); + delete result.header.dumpEventTimeStamp; + assert(typeof result.header.processId === "number"); + delete result.header.processId; + assert(typeof result.header.cwd === "string"); + delete result.header.cwd; + assert(typeof result.header.nodejsVersion === "string"); + assert(result.header.nodejsVersion.startsWith("v")); + delete result.header.nodejsVersion; + assert(typeof result.header.arch === "string"); + delete result.header.arch; + assert(typeof result.header.platform === "string"); + delete result.header.platform; + assert(typeof result.header.componentVersions === "object"); + delete result.header.componentVersions; + assert(typeof result.header.osName === "string"); + delete result.header.osName; + assert(typeof result.header.osMachine === "string"); + delete result.header.osMachine; + assert(Array.isArray(result.header.cpus)); + delete result.header.cpus; + assert(typeof result.header.networkInterfaces === "object"); + delete result.header.networkInterfaces; + assert(typeof result.header.host === "string"); + delete result.header.host; + + // test hardcoded part + assertEquals(result, { + header: { + reportVersion: 3, + event: "JavaScript API", + trigger: "GetReport", + threadId: 0, + commandLine: ["node"], + glibcVersionRuntime: "2.38", + glibcVersionCompiler: "2.38", + wordSize: 64, + release: { + name: "node", + headersUrl: + "https://nodejs.org/download/release/v21.2.0/node-v21.2.0-headers.tar.gz", + sourceUrl: + "https://nodejs.org/download/release/v21.2.0/node-v21.2.0.tar.gz", + }, + osRelease: undefined, + osVersion: undefined, + }, + javascriptStack: undefined, + javascriptHeap: undefined, + nativeStack: undefined, + resourceUsage: undefined, + uvthreadResourceUsage: undefined, + libuv: undefined, + workers: [], + environmentVariables: undefined, + userLimits: undefined, + sharedObjects: undefined, + }); + }, +}); diff --git a/ext/node/lib.rs b/ext/node/lib.rs index af8aabd1f0..7fa5b893b2 100644 --- a/ext/node/lib.rs +++ b/ext/node/lib.rs @@ -436,6 +436,7 @@ deno_core::extension!(deno_node, "internal/options.ts", "internal/primordials.mjs", "internal/process/per_thread.mjs", + "internal/process/report.ts", "internal/querystring.ts", "internal/readline/callbacks.mjs", "internal/readline/emitKeypressEvents.mjs", diff --git a/ext/node/polyfills/internal/process/report.ts b/ext/node/polyfills/internal/process/report.ts new file mode 100644 index 0000000000..7d178626c9 --- /dev/null +++ b/ext/node/polyfills/internal/process/report.ts @@ -0,0 +1,84 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. + +import { arch, versions } from "ext:deno_node/_process/process.ts"; +import { cpus, hostname, networkInterfaces } from "node:os"; + +const primordials = globalThis.__bootstrap.primordials; +const { + Error, + StringPrototypeToUpperCase, + StringPrototypeCharAt, + StringPrototypeSlice, + Date, + DatePrototypeGetTime, +} = primordials; + +function writeReport(_filename: string, _err: typeof Error) { + return ""; +} + +const todoUndefined = undefined; + +function getReport(_err: typeof Error) { + const dumpEventTime = new Date(); + return { + header: { + reportVersion: 3, + event: "JavaScript API", + trigger: "GetReport", + filename: report.filename, // assumption! + dumpEventTime, + dumpEventTimeStamp: DatePrototypeGetTime(dumpEventTime), + processId: Deno.pid, // I am not sure if it should be Deno.pid or Deno.ppid + threadId: 0, + cwd: Deno.cwd(), + commandLine: ["node"], + nodejsVersion: `v${versions.node}`, + glibcVersionRuntime: "2.38", + glibcVersionCompiler: "2.38", + wordSize: 64, + arch: arch(), + platform: Deno.build.os, + componentVersions: versions, + release: { + name: "node", + headersUrl: + "https://nodejs.org/download/release/v21.2.0/node-v21.2.0-headers.tar.gz", + sourceUrl: + "https://nodejs.org/download/release/v21.2.0/node-v21.2.0.tar.gz", + }, + osName: + StringPrototypeToUpperCase(StringPrototypeCharAt(Deno.build.os, 0)) + + StringPrototypeSlice(Deno.build.os, 1), + osRelease: todoUndefined, + osVersion: todoUndefined, + osMachine: Deno.build.arch, + cpus: cpus(), + networkInterfaces: networkInterfaces(), + host: hostname(), + }, + javascriptStack: todoUndefined, + javascriptHeap: todoUndefined, + nativeStack: todoUndefined, + resourceUsage: todoUndefined, + uvthreadResourceUsage: todoUndefined, + libuv: todoUndefined, + workers: [], + environmentVariables: todoUndefined, + userLimits: todoUndefined, + sharedObjects: todoUndefined, + }; +} + +// https://nodejs.org/api/process.html#processreport +export const report = { + compact: false, + directory: "", + filename: "", + getReport, + reportOnFatalError: false, + reportOnSignal: false, + reportOnUncaughtException: false, + signal: "SIGUSR2", + writeReport, +}; diff --git a/ext/node/polyfills/process.ts b/ext/node/polyfills/process.ts index 860825b3e8..c495a90bb1 100644 --- a/ext/node/polyfills/process.ts +++ b/ext/node/polyfills/process.ts @@ -10,6 +10,7 @@ const { ops } = core; import { notImplemented, warnNotImplemented } from "ext:deno_node/_utils.ts"; import { EventEmitter } from "node:events"; import Module from "node:module"; +import { report } from "ext:deno_node/internal/process/report.ts"; import { validateString } from "ext:deno_node/internal/validators.mjs"; import { ERR_INVALID_ARG_TYPE, @@ -362,6 +363,10 @@ class Process extends EventEmitter { return arch; } + get report() { + return report; + } + get title() { return "deno"; } diff --git a/tools/core_import_map.json b/tools/core_import_map.json index 0f356eb976..b4eed19f0d 100644 --- a/tools/core_import_map.json +++ b/tools/core_import_map.json @@ -138,6 +138,7 @@ "ext:deno_node/internal/options.ts": "../ext/node/polyfills/internal/options.ts", "ext:deno_node/internal/primordials.mjs": "../ext/node/polyfills/internal/primordials.mjs", "ext:deno_node/internal/process/per_thread.mjs": "../ext/node/polyfills/internal/process/per_thread.mjs", + "ext:deno_node/internal/process/report.ts": "../ext/node/polyfills/internal/process/report.ts", "ext:deno_node/internal/querystring.ts": "../ext/node/polyfills/internal/querystring.ts", "ext:deno_node/internal/readline/callbacks.mjs": "../ext/node/polyfills/internal/readline/callbacks.mjs", "ext:deno_node/internal/readline/emitKeypressEvents.mjs": "../ext/node/polyfills/internal/readline/emitKeypressEvents.mjs",