Skip to content

fs.constants / os.constants / crypto.constants namespace tables missing #649

Description

@proggeramlug

Repro

import * as fs from "node:fs";
import * as os from "node:os";
import * as crypto from "node:crypto";

console.log("fs.constants type:", typeof fs.constants);
console.log("fs.constants.F_OK:", fs.constants?.F_OK);
console.log("fs.constants.O_RDONLY:", fs.constants?.O_RDONLY);

console.log("os.constants type:", typeof os.constants);
console.log("os.constants.signals.SIGINT:", os.constants?.signals?.SIGINT);
console.log("os.constants.errno.ENOENT:", os.constants?.errno?.ENOENT);
console.log("os.constants.priority.PRIORITY_NORMAL:", os.constants?.priority?.PRIORITY_NORMAL);
console.log("os.constants.dlopen.RTLD_LAZY:", os.constants?.dlopen?.RTLD_LAZY);

console.log("crypto.constants type:", typeof crypto.constants);
console.log("crypto.constants.RSA_PKCS1_PADDING:", crypto.constants?.RSA_PKCS1_PADDING);

Actual (Perry)

fs.constants type: undefined
fs.constants.F_OK: undefined
fs.constants.O_RDONLY: undefined
os.constants type: undefined
os.constants.signals.SIGINT: undefined
os.constants.errno.ENOENT: undefined
os.constants.priority.PRIORITY_NORMAL: undefined
os.constants.dlopen.RTLD_LAZY: undefined
crypto.constants type: undefined
crypto.constants.RSA_PKCS1_PADDING: undefined

Expected (Node)

fs.constants type: object
fs.constants.F_OK: 0
fs.constants.O_RDONLY: 0
os.constants type: object
os.constants.signals.SIGINT: 2
os.constants.errno.ENOENT: 2
os.constants.priority.PRIORITY_NORMAL: 0
os.constants.dlopen.RTLD_LAZY: 5
crypto.constants type: object
crypto.constants.RSA_PKCS1_PADDING: 1

Impact

These three constant tables are ubiquitous in Node ecosystem code:

  • fs.constants.F_OK / R_OK / W_OK / X_OK — used by fs.access(path, fs.constants.R_OK) and similar permission probes. ~50 entries total (file mode bits, open flags, copyfile flags, dirent type tags).
  • os.constants.signals.* — every signal name to number (SIGINT, SIGTERM, SIGHUP, etc.); used by process.kill(pid, signal) and process.on('SIGINT') setups. ~30 entries on POSIX.
  • os.constants.errno.* — POSIX errno codes (ENOENT, EACCES, etc.); used to compare err.errno in error handlers. ~80 entries.
  • os.constants.priority.* — process priority levels (PRIORITY_NORMAL, PRIORITY_LOW, etc.) used by os.setPriority.
  • os.constants.dlopen.* — dlopen flags (RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL, etc.).
  • crypto.constants.* — RSA padding, SSL_OP_, ENGINE_METHOD_ used by every cipher/sign/verify code path. ~100 entries.

All three are pure static value tables — no runtime logic, no platform branching beyond what's already in crates/perry-runtime. Filling them is mechanical: define the constant maps once, expose them as namespace-keyed lookups when the user imports the parent module.

Currently every consumer that imports node:fs/os/crypto and references .constants.X gets undefined and silently mis-behaves (e.g. fs.access(path, fs.constants.R_OK) becomes fs.access(path, undefined), which Node treats as F_OK).

The signal-name → number table is also blocking test_parity_os from running its full surface — when os.constants.signals is undefined, the next Object.keys(...) call short-circuits the whole test through the catch arm, masking real signal-handling bugs.

Acceptance

The 11-line repro above prints output byte-identical to Node.

Related

Surfaced via test-files/test_parity_fs.ts (fs.constants entirely absent — accounts for ~44 of the test's 409 diff lines), test_parity_os.ts (the test only completes 15 of 60 lines because the constants table is missing), and test_parity_crypto.ts (135 of 199 lines short — partly because crypto.constants.* is referenced throughout the cipher/sign/verify probes).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions