Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions crates/perry-runtime/src/object/native_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1789,6 +1789,9 @@ const PROCESS_NAMESPACE_KEYS: &[&[u8]] = &[
b"setSourceMapsEnabled",
b"send",
b"sourceMapsEnabled",
b"stderr",
b"stdin",
b"stdout",
b"title",
b"unref",
b"uptime",
Expand Down Expand Up @@ -1870,6 +1873,9 @@ const PROCESS_DEFAULT_KEYS: &[&[u8]] = &[
b"setSourceMapsEnabled",
b"send",
b"sourceMapsEnabled",
b"stderr",
b"stdin",
b"stdout",
b"title",
b"uptime",
b"version",
Expand Down
17 changes: 17 additions & 0 deletions crates/perry-runtime/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1713,6 +1713,23 @@ fn process_allowed_flags_value() -> f64 {

pub fn process_metadata_property(property: &str) -> Option<f64> {
Some(match property {
// #4987: core value-properties. The bare `process` identifier lowers
// these to codegen intrinsics, but `import process from
// 'node:process'` and `globalThis.process` resolve through the
// native-module runtime dispatcher, which lands here. Serve them from
// the same runtime constructors the intrinsics call so all three
// forms observe the same values (env/stdout are live singletons).
"env" => js_process_env(),
"argv" => f64::from_bits(JSValue::array_ptr(crate::os::js_process_argv()).bits()),
"platform" => f64::from_bits(JSValue::string_ptr(crate::os::js_os_platform()).bits()),
"arch" => f64::from_bits(JSValue::string_ptr(crate::os::js_os_arch()).bits()),
"pid" => crate::os::js_process_pid(),
"ppid" => crate::os::js_process_ppid(),
"version" => f64::from_bits(JSValue::string_ptr(crate::os::js_process_version()).bits()),
"versions" => crate::os::js_process_versions(),
"stdin" => crate::os::js_process_stdin(),
"stdout" => crate::os::js_process_stdout(),
"stderr" => crate::os::js_process_stderr(),
"allowedNodeEnvironmentFlags" => process_allowed_flags_value(),
"argv0" | "execPath" => module_string_value(&process_argv0_string()),
"config" => process_config_value(),
Expand Down
44 changes: 44 additions & 0 deletions test-files/test_gap_process_import_4987.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Issue #4987: `import process from 'node:process'` and `globalThis.process`
// must expose the same fully-populated process object as the bare `process`
// identifier (env/stdout/stderr/stdin/platform/arch/argv/pid/ppid/version/
// versions were undefined on the import + globalThis forms).
// Expected: byte-identical to node --experimental-strip-types
import proc from 'node:process';

// --- minimal repro from the issue ---
console.log(typeof proc.env, typeof proc.stdout, typeof proc.platform);
console.log(typeof process.env);

// --- full member sweep on the default import ---
console.log(typeof proc.env === 'object'); // true
console.log(typeof proc.stdout === 'object'); // true
console.log(typeof proc.stderr === 'object'); // true
console.log(typeof proc.stdin === 'object'); // true
console.log(typeof proc.platform === 'string'); // true
console.log(typeof proc.arch === 'string'); // true
console.log(typeof proc.pid === 'number'); // true
console.log(typeof proc.ppid === 'number'); // true
console.log(typeof proc.version === 'string'); // true
console.log(typeof proc.versions === 'object'); // true
console.log(Array.isArray(proc.argv)); // true
console.log(typeof proc.cwd === 'function'); // true

// --- globalThis.process ---
console.log(typeof globalThis.process.env === 'object'); // true
console.log(typeof globalThis.process.stdout === 'object'); // true
console.log(typeof globalThis.process.platform === 'string'); // true

// --- values agree with the bare identifier ---
console.log(proc.platform === process.platform); // true
console.log(proc.arch === process.arch); // true
console.log(proc.pid === process.pid); // true
console.log(proc.version === process.version); // true
console.log(typeof proc.env.PATH === 'string'); // true
console.log(proc.env.PATH === process.env.PATH); // true

// --- terminal-size shape (the ink #348 wall): destructure off the import ---
const { env, stdout, stderr } = proc;
console.log(typeof env, typeof stdout, typeof stderr); // object object object
// env member reads must not throw (this was the TypeError in terminal-size)
console.log(env.COLUMNS === undefined || typeof env.COLUMNS === 'string'); // true
console.log(typeof stdout.write === 'function'); // true