Skip to content

Support fs.promises.rm options already handled by rmSync #1615

Closed

Description

@jlucaso1

fs.promises.rm(path, { recursive: true, force: true }) fails to compile even though the synchronous options form already has lowering and runtime support. This is a request to extend the promise API's supported overloads, not a claim that scriptc promises full Node compatibility.

The original investigation reproduced this with scriptc 0.4.0 and an unmodified source build of main at 94aa7065f17fdeeb31094ffcb71885b0d671b5ba. Platform: Linux x86_64, Debian glibc 2.41, Node 24.19.0. The reproduction uses no application dependencies or network connection at runtime.

Reproduction

In an empty directory, create these files.

package.json:

{
	"private": true,
	"type": "module",
	"devDependencies": {
		"scriptc": "0.4.0",
		"@types/node": "26.1.1"
	}
}

tsconfig.json:

{
	"compilerOptions": {
		"strict": true,
		"target": "ESNext",
		"module": "ESNext",
		"moduleResolution": "Bundler"
	}
}

repro.ts:

import { rm } from 'node:fs/promises'
await rm('missing', { recursive: true, force: true })
console.log('ok')

Run:

npm install
node repro.ts
./node_modules/.bin/scriptc --version
./node_modules/.bin/scriptc build repro.ts --emit ir -o repro.ir.json

Node prints ok and exits 0. scriptc reports version 0.4.0, then exits 1 with:

SC2020: 'rm with 2 arguments' is part of the standard library types but has no scriptc lowering yet
hint: the supported form takes 1 argument (no options objects)

Using IR output avoids requiring a linker. The expected behavior is to support this overload and preserve recursive and force, including rejection of filesystem failures. Dropping the options or replacing the call with synchronous removal would not be equivalent. The Node 24 API defines both options.

For the original main check, the investigation installed the workspace with pnpm install --frozen-lockfile --ignore-scripts, ran pnpm -r build, and used:

node /path/to/scriptc/packages/cli/dist/main.js build repro.ts --emit ir -o main.ir.json

It reports the same SC2020 in the clean reproduction directory.

Cause and proposed implementation

At the tested main commit:

  • surfaces.ts gives fs/promises.rm one parameter. The generic arity gate rejects the second argument.
  • module-calls.ts routes the options parser only for fs.rmSync.
  • scr_fsp_rm wraps only the one-argument operation. The option-aware removal and retry functions already exist in scr_lib.c.

A local prototype routes the promise form through the existing literal options parser, adds fsp.rmOpts and fsp.rmRetry signatures and LLVM symbol mappings, and wraps the option-aware runtime operations with scr_promise_settled_void(). That last step matters: a pending filesystem exception must become a rejected promise, as it does for the existing fs/promises wrappers.

The runtime wrapper in that prototype is:

ScrPromise *scr_fsp_rm_opts(ScrStr *path, bool recursive, bool force) {
  scr_fs_rm_opts(path, recursive, force);
  return scr_promise_settled_void();
}

In the original investigation, the frontend regression fails without the patch and passes with it, including recursive/force and retry-argument forms. The emitted IR validates, the compiler builds, lint passes, and the added C wrappers pass GCC syntax checking. This is not a fully validated native fix: main requires runtime ABI 23, while the installed 0.4.0 pack is ABI 22. That mismatch was not bypassed. Native differential tests, retry fault injection, fallback declaration updates and compatibility regeneration remain necessary before landing a change.

The publication recheck covered open and closed issues and PRs for fs/promises, rm, rmSync, and recursive removal. Merged #1504 implements an fs-extra shim with its own removal path; it does not add this Node API overload. No equivalent report or pending fix was found for this case. The original application context is oxidezap/baileyrs#176, but the reproduction above is independent of it.

Verification on 2026-10-21

The isolated publication recheck used Linux x86_64 WSL (Arch Linux, glibc 2.44), Node v26.12.0, scriptc@0.4.0 (tag commit 4bc8a4711c358ca09edaa758f5efd296bc6d2730) and @types/node@26.1.1. An unmodified source build of main at 4dd62802c85f77739f7b69dc491758c4cda6f3e5 confirmed the same filesystem diagnostic. It was installed with pnpm 11.28.6 using pnpm install --frozen-lockfile --ignore-scripts and built with pnpm -r build; it still reports version 0.4.0, so the SHA identifies it.

Earlier results at 94aa7065f come from the pinned investigation. The prototype results described above are from that investigation; the patch was not reapplied during publication. Its lowering checks do not establish native parity, and no patched native runtime was executed.

Activity

  1. added a commit that references this issue on Oct 21, 2026
    973884e
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