mirror of
https://github.com/morluto/rea.git
synced 2026-11-06 23:06:18 +00:00
* fix(javascript): emit no fs acquisition for a rejected literal mode
`fs.open`, `fs.openSync` and `fs/promises.open` validate the `mode` in argument 2 before
touching the filesystem, so a mode Node rejects throws synchronously and no descriptor
exists. The guard read only the flag, so a rejected mode kept its acquisition and any
linked release.
Measured on Node 24.22.1:
fs.openSync(p, "r", -1) -> THREW ERR_OUT_OF_RANGE
fs.openSync(p, "r", 1.5) -> THREW ERR_OUT_OF_RANGE
fs.openSync(p, "r", NaN) -> THREW ERR_OUT_OF_RANGE
fs.openSync(p, "r", 1e21) -> THREW ERR_OUT_OF_RANGE
fs.openSync(p, "r", true) -> THREW ERR_INVALID_ARG_TYPE
fs.openSync(p, "r", 0n) -> THREW ERR_INVALID_ARG_TYPE
fs.openSync(p, "r", {}) -> THREW ERR_INVALID_ARG_TYPE
fs.openSync(p, "r", "8") -> THREW ERR_INVALID_ARG_VALUE
fs.openSync(p, "r", "") -> THREW ERR_INVALID_ARG_VALUE
fs.openSync(p, "r", "0o644") -> THREW ERR_INVALID_ARG_VALUE
--- accepted ---
fs.openSync(p, "r", 0o644) -> ok
fs.openSync(p, "r", 2147483647) -> ok
fs.openSync(p, "r", -0) -> ok
fs.openSync(p, "r", "0644") -> ok
fs.openSync(p, "r", null) -> ok
fs.openSync(p, "r", void 0) -> ok
The guard decides only exactly-readable literals. A numeric mode is validated as an
unsigned 32-bit integer; a string mode must be a canonical octal digit string, padded
leading zeros allowed, and its value must stay inside uint32; `null`, `undefined` and
`void <expr>` default the mode and are kept, as is a computed value.
Three boundaries are deliberate:
- Values in `[2^31, 2^32-1]` **abort the Node process** rather than throwing
(`Assertion failed: args[2]->IsInt32()`), so they stay undecided instead of being
claimed as a synchronous throw.
- A spread before the mode slot shifts the runtime position.
- A unary chain is resolved through its innermost readable operand, and a nested
boolean or string result is left undecided rather than applied as a number.
Regressions cover both directions. Full suite here: 5466 passed | 7 skipped.
* fix(javascript): remove the superseded string mode check
Review finding. `rejectsOpenModeLiteral` builds `octal` from a string literal or a
no-expression template and returns inside that branch for every value it matched. A
`StringLiteral` therefore never reaches the later `isStringLiteral` check, which cannot
run and is a second copy of the canonical-octal rule to maintain.
* test(javascript): cover the spread and boundary paths of the mode guard
Review feedback from @greptile-apps: the new mode tests skipped both paths the
guard deliberately leaves undecided. Two spread cases are added:
- `openSync(...args, "r", "0600")`, where a spread in the flag slot shifts the
runtime position of the mode;
- `openSync(p, "r", ...modes)`, where a spread occupies the mode slot itself.
Both must keep the acquisition, because neither establishes the mode value. The
boundary cases were already present: `2147483647` and `2147483648` are keep
cases (`2147483648` aborts the process rather than throwing) and `4294967296` is
the reject case, alongside the octal `37777777777` keep and `40000000000` reject
pair.
127 cases pass in this file.