fix(ext/node): expose internal/fs/promises with FileHandle (#34118)
## Summary
Three node compat tests fail with `Cannot find module
'internal/fs/promises'` because Deno never registers that internal
module. This exposes it and reroutes a few `fs.promises` entry points
through `FileHandle` so the tests' monkey-patches on
`FileHandle.prototype.fd` are observed.
- Register `internal/fs/promises` in `01_require.js`. Uses a `Proxy` so
loading is deferred to the first property read — eager loading at
`setupBuiltinModules()` time would re-enter the half-built `node:fs`
namespace (the module calls `lazyFs()` at top level).
- Add `FileHandle` and `constants` as named exports of
`internal/fs/promises.ts`.
- Reroute `fs.promises.{truncate,readFile,writeFile,appendFile}`: when
given a path, open a `FileHandle` and use a new `handleFdClose` helper
that mirrors Node's
[`handleFdClose`](https://github.com/nodejs/node/blob/main/lib/internal/fs/promises.js)
— op-only failure throws the op error, close-only failure throws the
close error, both-failed throws an `AggregateError` carrying
`opError.code`. When given an fd/FileHandle, delegate to the original
raw `promisify(callback)` path to avoid recursing through
`FileHandle.readFile`/`.writeFile`.
- Switch `FileHandle.close`/`#close`/`[kUnref]` to use the private
`#rid` storage rather than `this.fd`. This matches Node's use of
`this[kFd]` for internal cleanup so a user-supplied `fd` getter that
throws can't break close.
- Normalize `FileHandle.read`'s three overload shapes — positional,
`(buffer, options)`, `(options)` — so a nullish `length` falls back to
`buffer.byteLength - offset` instead of being coerced to 0 by `length |=
0` downstream.
- Enable the four file-handle tests in `tests/node_compat/config.jsonc`:
- `test-fs-promises-file-handle-aggregate-errors.js`
- `test-fs-promises-file-handle-close-errors.js`
- `test-fs-promises-file-handle-op-errors.js`
- `test-fs-promises-file-handle-read.js`
Closes denoland/orchid#98
## Test plan
- [x] `cargo build --bin deno`
- [x] All four newly-enabled tests pass
- [x] No regressions in other `test-fs-*` tests already in config
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: divybot <divybot@users.noreply.github.com>