mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-29 07:04:09 +08:00
Pass results from fs.mkdir, readFile and write callbacks (#1020)
This commit is contained in:
@@ -2,6 +2,6 @@
|
||||
"schemaVersion": 3,
|
||||
"nodeVersion": "24.22.0",
|
||||
"nodeCommit": "f14cd3aa7bf9ca8df2cc5b8bb14beb0f335b1d93",
|
||||
"artifactVersion": "88ef6fabee3e41b50d74",
|
||||
"artifactVersion": "35b26942ca49ff006818",
|
||||
"rowCount": 3880
|
||||
}
|
||||
|
||||
@@ -314,9 +314,9 @@
|
||||
"apiEntries": 280,
|
||||
"static": {
|
||||
"supported": 7,
|
||||
"partial": 98,
|
||||
"partial": 101,
|
||||
"refused": 0,
|
||||
"not-implemented": 175,
|
||||
"not-implemented": 172,
|
||||
"by-design": 0,
|
||||
"unreviewed": 0,
|
||||
"not-applicable": 0
|
||||
@@ -30840,9 +30840,9 @@
|
||||
"inherited": true
|
||||
},
|
||||
"static": {
|
||||
"status": "not-implemented",
|
||||
"detail": "No static compiler lowering is registered for this API yet.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented scriptc module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -31047,9 +31047,9 @@
|
||||
"inherited": true
|
||||
},
|
||||
"static": {
|
||||
"status": "not-implemented",
|
||||
"detail": "No static compiler lowering is registered for this API yet.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented scriptc module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -31484,9 +31484,9 @@
|
||||
"inherited": true
|
||||
},
|
||||
"static": {
|
||||
"status": "not-implemented",
|
||||
"detail": "No static compiler lowering is registered for this API yet.",
|
||||
"verification": "registry-gap"
|
||||
"status": "partial",
|
||||
"detail": "Implemented for the documented scriptc module-loader subset.",
|
||||
"verification": "test-backed"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
"tiers": {
|
||||
"static": {
|
||||
"replace-refusal": 37,
|
||||
"verify-gap": 2472,
|
||||
"audit-partial": 876,
|
||||
"verify-gap": 2469,
|
||||
"audit-partial": 879,
|
||||
"classify": 2,
|
||||
"implement": 85
|
||||
}
|
||||
@@ -27353,12 +27353,14 @@
|
||||
"priority": "high",
|
||||
"tiers": {
|
||||
"static": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "compiler-unmatched:fs",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "compiler-feature:fs.fs.mkdir",
|
||||
"tests": [
|
||||
"tests/corpus/5540-fs-callback-forms.cjs"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -27578,12 +27580,14 @@
|
||||
"priority": "high",
|
||||
"tiers": {
|
||||
"static": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "compiler-unmatched:fs",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "compiler-feature:fs.fs.readFile",
|
||||
"tests": [
|
||||
"tests/corpus/5540-fs-callback-forms.cjs"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -28084,12 +28088,14 @@
|
||||
"priority": "high",
|
||||
"tiers": {
|
||||
"static": {
|
||||
"status": "not-implemented",
|
||||
"action": "verify-gap",
|
||||
"verification": "registry-gap",
|
||||
"confidence": "low",
|
||||
"source": "compiler-unmatched:fs",
|
||||
"tests": []
|
||||
"status": "partial",
|
||||
"action": "audit-partial",
|
||||
"verification": "test-backed",
|
||||
"confidence": "high",
|
||||
"source": "compiler-feature:fs.fs.write",
|
||||
"tests": [
|
||||
"tests/corpus/5540-fs-callback-forms.cjs"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -326,9 +326,9 @@
|
||||
"apiEntries": 280,
|
||||
"static": {
|
||||
"supported": 7,
|
||||
"partial": 98,
|
||||
"partial": 101,
|
||||
"refused": 0,
|
||||
"not-implemented": 175,
|
||||
"not-implemented": 172,
|
||||
"by-design": 0,
|
||||
"unreviewed": 0,
|
||||
"not-applicable": 0
|
||||
@@ -43746,6 +43746,7 @@
|
||||
"tests/corpus/3135-fs-file-handle-controls.ts",
|
||||
"tests/corpus/3136-fs-file-handle-options.ts",
|
||||
"tests/corpus/3137-fs-vector-callbacks.cjs",
|
||||
"tests/corpus/5540-fs-callback-forms.cjs",
|
||||
"tests/corpus/fs-native-realpath.ts",
|
||||
"tests/corpus/fs-read-encodings.ts",
|
||||
"tests/corpus/node24-fs-links-callbacks.cjs",
|
||||
@@ -46098,8 +46099,11 @@
|
||||
"inherited": true
|
||||
},
|
||||
"static": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "compiler-unmatched:fs"
|
||||
"status": "partial",
|
||||
"evidence": "compiler-feature:fs.fs.mkdir",
|
||||
"tests": [
|
||||
"tests/corpus/5540-fs-callback-forms.cjs"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
},
|
||||
@@ -46305,8 +46309,11 @@
|
||||
"inherited": true
|
||||
},
|
||||
"static": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "compiler-unmatched:fs"
|
||||
"status": "partial",
|
||||
"evidence": "compiler-feature:fs.fs.readFile",
|
||||
"tests": [
|
||||
"tests/corpus/5540-fs-callback-forms.cjs"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
},
|
||||
@@ -46918,8 +46925,11 @@
|
||||
"inherited": true
|
||||
},
|
||||
"static": {
|
||||
"status": "not-implemented",
|
||||
"evidence": "compiler-unmatched:fs"
|
||||
"status": "partial",
|
||||
"evidence": "compiler-feature:fs.fs.write",
|
||||
"tests": [
|
||||
"tests/corpus/5540-fs-callback-forms.cjs"
|
||||
]
|
||||
},
|
||||
"anchorSource": "exact"
|
||||
},
|
||||
|
||||
@@ -209,6 +209,7 @@
|
||||
{ "chapter": "fs", "symbols": ["fs.statfs"], "status": "partial", "evidence": ["tests/corpus/node24-fs-statfs-callbacks.cjs", "tests/corpus/node24-fs-statfs-options.cjs", "tests/corpus/node24-fs-statfs-errors.cjs", "tests/fixtures/node-types/fs-statfs.ts"] },
|
||||
{ "chapter": "fs", "symbols": ["fs.StatFs"], "status": "partial", "evidence": ["tests/corpus/node24-fs-statfs.ts", "tests/corpus/node24-fs-statfs-options.cjs", "tests/fixtures/node-types/fs-statfs.ts"] },
|
||||
{ "chapter": "fs", "parent": "Class: `fs.StatFs`", "symbols": ["type", "bsize", "blocks", "bfree", "bavail", "files", "ffree"], "status": "supported", "evidence": ["tests/corpus/node24-fs-statfs.ts", "tests/corpus/node24-fs-statfs-options.cjs", "tests/fixtures/node-types/fs-statfs.ts"] },
|
||||
{ "chapter": "fs", "signatures": ["`fs.mkdir(path[, options], callback)`", "`fs.readFile(path[, options], callback)`", "`fs.write(fd, string[, position[, encoding]], callback)`"], "status": "partial", "evidence": ["tests/corpus/5540-fs-callback-forms.cjs"] },
|
||||
{ "chapter": "fs", "symbols": ["fs.utimes", "fs.futimes", "fs.lutimes"], "status": "partial", "evidence": ["tests/corpus/node24-fs-timestamps-callbacks.cjs", "tests/corpus/node24-fs-timestamps-symlinks.ts", "tests/corpus/node24-fs-timestamps-errors.cjs"] },
|
||||
{ "chapter": "process", "signatures": ["`process.hrtime([time])`", "`process.hrtime.bigint()`"], "status": "partial", "evidence": ["tests/corpus/process-hrtime.js"] },
|
||||
{ "chapter": "errors", "signatures": ["`stackTraceLimit` Type: {number}"], "status": "partial", "evidence": ["tests/corpus/error-stack-limit.ts"] },
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/5540-fs-callback-forms.cjs"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
@@ -794,9 +794,37 @@ static ScrDyn *scr_fs_cb_invoke(ScrStr *member, ScrDyn *const *args, size_t argc
|
||||
const ScrDyn *buffer = NULL;
|
||||
if (!strcmp(op, "readFile")) {
|
||||
const ScrDyn *options = ARG(1);
|
||||
if (options->kind != SCR_DYN_STR && (!scr_fs_cb_signal(options) || scr_fs_cb_refuse_option(options, "flag"))) goto done;
|
||||
if (options->kind != SCR_DYN_STR && !scr_fs_cb_signal(options)) goto done;
|
||||
ScrDyn *encoding = options->kind == SCR_DYN_STR ? scr_dyn_retain((ScrDyn *)options) : scr_fs_cb_option(options, "encoding");
|
||||
if (encoding) result = scr_fs_read_file_sync_dyn(path, encoding);
|
||||
ScrDyn *flag = options->kind == SCR_DYN_STR ? NULL : scr_fs_cb_option(options, "flag");
|
||||
bool reading_flag = !flag || flag->kind == SCR_DYN_UNDEF || flag->kind == SCR_DYN_NULL ||
|
||||
(flag->kind == SCR_DYN_STR && flag->v.str->len == 1 && flag->v.str->data[0] == 'r');
|
||||
if (encoding && reading_flag) result = scr_fs_read_file_sync_dyn(path, encoding);
|
||||
else if (encoding) {
|
||||
/* Node opens the file with options.flag ('w+' truncates first), then
|
||||
* reads the whole descriptor. */
|
||||
double opened = scr_fs_cb_open(path, flag, 0666, "r");
|
||||
if (opened >= 0 && !scr_exc_pending()) {
|
||||
bool text = encoding->kind == SCR_DYN_STR && encoding->v.str->len > 0;
|
||||
if (text) {
|
||||
ScrStr *content = scr_fs_read_fd_encoded(opened, encoding->v.str);
|
||||
if (content) {
|
||||
result = scr_dyn_new_str(content);
|
||||
scr_str_release(content);
|
||||
}
|
||||
} else {
|
||||
ScrBytes *content = scr_fs_read_fd_bytes(opened);
|
||||
if (content) {
|
||||
result = scr_dyn_new_buffer(content);
|
||||
scr_bytes_release(content);
|
||||
}
|
||||
}
|
||||
int saved = errno;
|
||||
close((int)opened);
|
||||
errno = saved;
|
||||
}
|
||||
}
|
||||
scr_dyn_release(flag);
|
||||
scr_dyn_release(encoding);
|
||||
} else if (!strcmp(op, "writeFile") || !strcmp(op, "appendFile")) {
|
||||
const ScrDyn *options = ARG(2);
|
||||
@@ -828,8 +856,13 @@ static ScrDyn *scr_fs_cb_invoke(ScrStr *member, ScrDyn *const *args, size_t argc
|
||||
else if (!strcmp(op, "mkdir")) {
|
||||
const ScrDyn *options = ARG(1);
|
||||
double mode = options->kind == SCR_DYN_NUM ? options->v.num : scr_fs_cb_option_number(options, "mode", 0777);
|
||||
if (scr_fs_cb_option_bool(options->kind == SCR_DYN_NUM ? scr_dyn_undefined() : options, "recursive")) scr_fs_mkdir_recursive_mode(path, mode);
|
||||
else scr_fs_mkdir_mode(path, mode);
|
||||
if (scr_fs_cb_option_bool(options->kind == SCR_DYN_NUM ? scr_dyn_undefined() : options, "recursive")) {
|
||||
/* The callback receives the first directory created (undefined when
|
||||
* the path already existed). */
|
||||
ScrStr *first = scr_fs_mkdir_recursive_first(path, mode);
|
||||
if (first && !scr_exc_pending()) result = scr_fs_cb_string(first);
|
||||
else if (first) scr_str_release(first);
|
||||
} else scr_fs_mkdir_mode(path, mode);
|
||||
} else if (!strcmp(op, "mkdtemp")) result = scr_fs_cb_string(scr_fs_mkdtemp(path));
|
||||
else if (!strcmp(op, "rm")) scr_fs_rm_opts_retry(path, scr_fs_cb_option_bool(ARG(1), "recursive"), scr_fs_cb_option_bool(ARG(1), "force"), scr_fs_cb_option_number(ARG(1), "maxRetries", 0), scr_fs_cb_option_number(ARG(1), "retryDelay", 100));
|
||||
else if (!strcmp(op, "rmdir")) scr_fs_rmdir(path);
|
||||
@@ -892,6 +925,33 @@ static ScrDyn *scr_fs_cb_invoke(ScrStr *member, ScrDyn *const *args, size_t argc
|
||||
#else
|
||||
scr_fs_throw(ENOSYS, "glob", path);
|
||||
#endif
|
||||
} else if (!strcmp(op, "write") && ARG(1)->kind == SCR_DYN_STR) {
|
||||
/* write(fd, string[, position[, encoding]], callback): a non-number
|
||||
* position writes at the current offset; the encoding defaults to
|
||||
* utf8 (unknown names write utf8, as the binding does). */
|
||||
const ScrDyn *string = ARG(1);
|
||||
const ScrDyn *position = count >= 3 ? ARG(2) : scr_dyn_undefined();
|
||||
const ScrDyn *encoding = count >= 4 ? ARG(3) : scr_dyn_undefined();
|
||||
ScrStr *codec = encoding->kind == SCR_DYN_STR && scr_bytes_is_encoding(encoding->v.str)
|
||||
? scr_str_retain(encoding->v.str)
|
||||
: scr_str_new("utf8", 4);
|
||||
if (codec->len == 3 && memcmp(codec->data, "hex", 3) == 0 && string->v.str->len % 2 != 0) {
|
||||
/* validateEncoding throws at the call, before any write. */
|
||||
char reason[64];
|
||||
snprintf(reason, sizeof reason, "is invalid for data of length %zu", (size_t)string->v.str->len);
|
||||
scr_dyn_arg_value_fail("encoding", reason, encoding);
|
||||
scr_str_release(codec);
|
||||
return NULL;
|
||||
} else {
|
||||
ScrBytes *bytes = scr_buffer_from_dyn(string, codec);
|
||||
if (bytes) {
|
||||
double at = position->kind == SCR_DYN_NUM ? position->v.num : -1;
|
||||
result = scr_dyn_new_num(scr_fs_write_sync(fd, bytes, 0, (double)bytes->len, at));
|
||||
scr_bytes_release(bytes);
|
||||
}
|
||||
}
|
||||
scr_str_release(codec);
|
||||
buffer = string;
|
||||
} else if (!strcmp(op, "read") || !strcmp(op, "write")) {
|
||||
bool readOp = !strcmp(op, "read");
|
||||
const ScrDyn *options = ARG(1);
|
||||
@@ -899,8 +959,16 @@ static ScrDyn *scr_fs_cb_invoke(ScrStr *member, ScrDyn *const *args, size_t argc
|
||||
if (readOp && !scr_dyn_bytes_is(options, SCR_BYTES_U8)) { ownedBuffer = scr_fs_cb_option(options, "buffer"); buffer = ownedBuffer; }
|
||||
else buffer = options;
|
||||
ScrBytes *bytes = buffer && buffer->kind == SCR_DYN_BYTES ? scr_dyn_bytes_unbox(buffer) : NULL;
|
||||
if (!bytes) scr_dyn_arg_type_fail("buffer", "an instance of Buffer, TypedArray, or DataView", buffer ? buffer : scr_dyn_undefined());
|
||||
else {
|
||||
if (!bytes) {
|
||||
/* The argument check throws at the call (Node validates before the
|
||||
* request is made). */
|
||||
scr_dyn_arg_type_fail("buffer",
|
||||
readOp ? "an instance of Buffer, TypedArray, or DataView"
|
||||
: "of type string or an instance of Buffer, TypedArray, or DataView",
|
||||
buffer ? buffer : scr_dyn_undefined());
|
||||
scr_dyn_release(ownedBuffer);
|
||||
return NULL;
|
||||
} else {
|
||||
double offset = ownedBuffer ? scr_fs_cb_option_number(options, "offset", 0) : scr_fs_cb_number(ARG(2), "offset", 0);
|
||||
double length = ownedBuffer ? scr_fs_cb_option_number(options, "length", bytes->len - offset) : scr_fs_cb_number(ARG(3), "length", bytes->len - offset);
|
||||
double position = ownedBuffer ? scr_fs_cb_option_number(options, "position", -1) : scr_fs_cb_number(ARG(4), "position", -1);
|
||||
|
||||
@@ -4423,6 +4423,51 @@ void scr_fs_mkdir_recursive_mode(ScrStr *path, double mode) {
|
||||
free(buf);
|
||||
}
|
||||
|
||||
/* mkdir(p, { recursive: true })'s answer, Node's MKDirpSync first path:
|
||||
* the first directory its walk creates, or NULL when the path already
|
||||
* existed. Node tries mkdir on the path and, on ENOENT, on the path cut
|
||||
* before its last separator, repeatedly; the first mkdir that succeeds
|
||||
* (its kernel parent exists) is the answer, spelled as cut. Creates the
|
||||
* path like scr_fs_mkdir_recursive_mode (the exception pending on
|
||||
* failure). */
|
||||
static bool scr_fs_mkdirp_exists(char *buf, size_t len) {
|
||||
char saved = buf[len];
|
||||
buf[len] = 0;
|
||||
struct stat st;
|
||||
int rc = len == 0 ? stat(".", &st) : stat(buf, &st);
|
||||
int e = errno;
|
||||
buf[len] = saved;
|
||||
return rc == 0 || e != ENOENT;
|
||||
}
|
||||
|
||||
ScrStr *scr_fs_mkdir_recursive_first(ScrStr *path, double mode) {
|
||||
char *buf = malloc(path->len + 1);
|
||||
if (!buf) {
|
||||
scr_trap("scriptc: out of memory\n");
|
||||
}
|
||||
memcpy(buf, path->data, path->len + 1);
|
||||
size_t cur = path->len, first = 0;
|
||||
while (cur > 0 && !scr_fs_mkdirp_exists(buf, cur)) {
|
||||
first = cur;
|
||||
/* The kernel's parent: trailing separators dropped, then the last
|
||||
* component and the separators before it ("/" stays). */
|
||||
size_t k = cur;
|
||||
while (k > 1 && scr_fs_sep(buf[k - 1])) k--;
|
||||
while (k > 0 && !scr_fs_sep(buf[k - 1])) k--;
|
||||
while (k > 1 && scr_fs_sep(buf[k - 1])) k--;
|
||||
if (scr_fs_mkdirp_exists(buf, k)) break;
|
||||
/* ENOENT: Node retries with the path cut before its last separator. */
|
||||
size_t cut = cur;
|
||||
while (cut > 0 && !scr_fs_sep(buf[cut - 1])) cut--;
|
||||
if (cut == 0) break;
|
||||
cur = cut - 1;
|
||||
}
|
||||
scr_mkdir_rec(buf, path->len, (mode_t)mode);
|
||||
free(buf);
|
||||
if (scr_exc_pending() || first == 0) return NULL;
|
||||
return scr_str_new(path->data, first);
|
||||
}
|
||||
|
||||
/* First failure of an rm walk, recorded instead of thrown so the retry
|
||||
* form can decide (retryable errno + attempts left → sleep and go again)
|
||||
* before anything reaches the exception cell. `path` is +1 when err != 0;
|
||||
|
||||
@@ -287,6 +287,9 @@ void scr_fs_rename_error(int error, const ScrStr *oldpath, const ScrStr *newpath
|
||||
void scr_fs_write_file_mode(ScrStr *path, ScrStr *data, double mode);
|
||||
void scr_fs_mkdir_mode(ScrStr *path, double mode);
|
||||
void scr_fs_mkdir_recursive_mode(ScrStr *path, double mode);
|
||||
/* The same walk, answering the first directory created (+1) or NULL
|
||||
* when the path already existed (or on failure, the exception pending). */
|
||||
ScrStr *scr_fs_mkdir_recursive_first(ScrStr *path, double mode);
|
||||
|
||||
/* Sequentially consistent integer operations and shared Int32 wait queues. */
|
||||
typedef struct ScrBytes ScrBytes;
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
// fs callback forms that pass results: mkdir with { recursive: true }
|
||||
// gives the first directory it creates (spelled as Node cuts the path, or
|
||||
// undefined when everything exists), readFile honors options.flag
|
||||
// ('w+' truncates, 'a+' and 'r+' read), and write takes a string with an
|
||||
// optional position and encoding, reporting the bytes written and the
|
||||
// string. Invalid data, buffers and encodings throw at the call.
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
const os = require("node:os");
|
||||
|
||||
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "fs-cb-"));
|
||||
process.chdir(dir);
|
||||
|
||||
function step(i) {
|
||||
const steps = [
|
||||
() => fs.mkdir("a/b/c", { recursive: true }, (e, p) => (console.log("mkdir", e, p), step(i + 1))),
|
||||
() => fs.mkdir("a/b/c", { recursive: true }, (e, p) => (console.log("mkdir again", e, p), step(i + 1))),
|
||||
() => fs.mkdir("a/b/d/e/", { recursive: true }, (e, p) => (console.log("trailing", e, p), step(i + 1))),
|
||||
() => fs.mkdir("./x//y", { recursive: true }, (e, p) => (console.log("doubled", e, p), step(i + 1))),
|
||||
() => fs.mkdir(path.join(dir, "abs/q"), { recursive: true }, (e, p) => (console.log("absolute", e, p === path.join(dir, "abs")), step(i + 1))),
|
||||
() => fs.mkdir("plain", (e, p) => (console.log("non-recursive", e, p), step(i + 1))),
|
||||
() => {
|
||||
fs.writeFileSync("f.txt", "file text");
|
||||
fs.mkdir("f.txt/sub", { recursive: true }, (e, p) => (console.log("under a file", e.code, p), step(i + 1)));
|
||||
},
|
||||
() => fs.readFile("f.txt", { encoding: "utf8", flag: "r" }, (e, t) => (console.log("flag r", e, t), step(i + 1))),
|
||||
() => fs.readFile("f.txt", { encoding: "utf8", flag: "a+" }, (e, t) => (console.log("flag a+", e, t), step(i + 1))),
|
||||
() => fs.readFile("f.txt", { flag: "r+" }, (e, b) => (console.log("flag r+", e, b.toString()), step(i + 1))),
|
||||
() => fs.readFile("new.txt", { encoding: "utf8", flag: "a+" }, (e, t) => (console.log("flag a+ creates", e, JSON.stringify(t), fs.existsSync("new.txt")), step(i + 1))),
|
||||
() => fs.readFile("f.txt", { encoding: "utf8", flag: "w+" }, (e, t) => (console.log("flag w+", e, JSON.stringify(t), fs.statSync("f.txt").size), step(i + 1))),
|
||||
() => fs.readFile("missing.txt", { encoding: "utf8", flag: "r+" }, (e) => (console.log("flag r+ missing", e.code), step(i + 1))),
|
||||
() => {
|
||||
const fd = fs.openSync("w.txt", "w+");
|
||||
fs.write(fd, "hello", (e, n, s) => {
|
||||
console.log("write string", e, n, s);
|
||||
fs.write(fd, "WORLD", 0, (e2, n2) => {
|
||||
console.log("write at 0", e2, n2, fs.readFileSync("w.txt", "utf8"));
|
||||
fs.write(fd, "686921", 5, "hex", (e3, n3, s3) => {
|
||||
console.log("write hex", e3, n3, s3, fs.readFileSync("w.txt", "latin1"));
|
||||
fs.write(fd, "é", null, "latin1", (e4, n4) => {
|
||||
console.log("write latin1", e4, n4, fs.readFileSync("w.txt").length);
|
||||
fs.closeSync(fd);
|
||||
step(i + 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
() => {
|
||||
const fd = fs.openSync("w.txt", "r+");
|
||||
try {
|
||||
fs.write(fd, "abc", 0, "hex", () => {});
|
||||
} catch (error) {
|
||||
console.log("odd hex", error.code, error.message);
|
||||
}
|
||||
try {
|
||||
fs.write(fd, 42, () => {});
|
||||
} catch (error) {
|
||||
console.log("bad data", error.code, error.message);
|
||||
}
|
||||
try {
|
||||
fs.read(fd, { buffer: 5 }, () => {});
|
||||
} catch (error) {
|
||||
console.log("bad read buffer", error.code, error.message);
|
||||
}
|
||||
fs.closeSync(fd);
|
||||
step(i + 1);
|
||||
},
|
||||
];
|
||||
if (i < steps.length) steps[i]();
|
||||
else {
|
||||
process.chdir(os.tmpdir());
|
||||
fs.rmSync(dir, { recursive: true });
|
||||
console.log("removed", fs.existsSync(dir));
|
||||
}
|
||||
}
|
||||
step(0);
|
||||
Reference in New Issue
Block a user