// Files, with promises, on the IO natives (see lib/rt/io.h). They are like // node's `fs.promises`, but only for UTF-8 text: // - `fs.readFile(path)` gives the text of the file // - `fs.writeFile(path, text)` makes or replaces the file // A failure rejects with the negative errno, not an `Error`. A read or a write // that the kernel does not finish in one op is not continued // A promise of what op `h` gives when it completes: its status, its data, or // a number. A result can only be read before the next wait, so these read it // when the op completes function __io_status(h) { return new Promise((resolve) => { __pending[h] = (h) => resolve(__native_io_status(h)); }); } function __io_string(h) { return new Promise((resolve, reject) => { __pending[h] = (h) => { const status = __native_io_status(h); if (status < 0) reject(status); else resolve(__native_io_result_string(h)); }; }); } function __io_number(h) { return new Promise((resolve, reject) => { __pending[h] = (h) => { const status = __native_io_status(h); if (status < 0) reject(status); else resolve(__native_io_result_number(h)); }; }); } // A promise of the status of op `h`, rejected if it failed function __io_ok(h) { return __io_status(h).then((status) => (status < 0 ? Promise.reject(status) : status)); } const fs = { readFile(path) { let fd = -1; let text = ""; return __io_ok(__native_io_queue_open(path, 0, 0)) .then((f) => { fd = f; return __io_number(__native_io_queue_stat(path)); }) .then((size) => __io_string(__native_io_queue_read(fd, size, 0))) .then((s) => { text = s; return __io_ok(__native_io_queue_close(fd)); }) .then(() => text); }, writeFile(path, text) { let fd = -1; // O_WRONLY | O_CREAT | O_TRUNC, mode 0644 return __io_ok(__native_io_queue_open(path, 577, 420)) .then((f) => { fd = f; return __io_ok(__native_io_queue_write(fd, text, 0)); }) .then(() => __io_ok(__native_io_queue_close(fd))) .then(() => undefined); }, };