MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

add more standard fs operations

+543 -2
+30
examples/spec/fs.js
··· 45 45 test('unlinkSync removes file', fs.existsSync(testFile), false); 46 46 47 47 fs.unlinkSync(renameFile); 48 + 49 + const fdFile = path.join(testDir, 'fd_test.txt'); 50 + const fd = fs.openSync(fdFile, 'w'); 51 + test('openSync returns fd', typeof fd, 'number'); 52 + 53 + const written = fs.writeSync(fd, 'hello fd'); 54 + test('writeSync returns bytes written', written, 8); 55 + 56 + const buf = new Uint8Array([33]); 57 + const bufWritten = fs.writeSync(fd, buf); 58 + test('writeSync buffer returns bytes written', bufWritten, 1); 59 + 60 + fs.closeSync(fd); 61 + 62 + const fdContent = fs.readFileSync(fdFile, 'utf8'); 63 + test('writeSync wrote correct data', fdContent, 'hello fd!'); 64 + 65 + fs.unlinkSync(fdFile); 66 + 67 + const wvFile = path.join(testDir, 'writev_test.txt'); 68 + const wvFd = fs.openSync(wvFile, 'w'); 69 + const bufs = [new Uint8Array([65, 66]), new Uint8Array([67, 68])]; 70 + const wvWritten = fs.writevSync(wvFd, bufs); 71 + test('writevSync returns total bytes', wvWritten, 4); 72 + fs.closeSync(wvFd); 73 + 74 + const wvContent = fs.readFileSync(wvFile, 'utf8'); 75 + test('writevSync wrote correct data', wvContent, 'ABCD'); 76 + fs.unlinkSync(wvFile); 77 + 48 78 fs.rmdirSync(testDir); 49 79 test('rmdirSync removes dir', fs.existsSync(testDir), false); 50 80
+72
examples/spec/fs_async.js
··· 1 + import { test, summary } from './helpers.js'; 2 + import fs from 'ant:fs'; 3 + import path from 'ant:path'; 4 + 5 + console.log('FS Async Tests\n'); 6 + 7 + async function run() { 8 + const testDir = '/tmp/ant-spec-test-async'; 9 + const testFile = path.join(testDir, 'test.txt'); 10 + 11 + await fs.mkdir(testDir); 12 + test('mkdir creates dir', await fs.exists(testDir), true); 13 + 14 + await fs.writeFile(testFile, 'hello world'); 15 + test('writeFile creates file', await fs.exists(testFile), true); 16 + 17 + const content = await fs.readFile(testFile, 'utf8'); 18 + test('readFile content', content, 'hello world'); 19 + 20 + const stat = await fs.stat(testFile); 21 + test('stat isFile', stat.isFile(), true); 22 + test('stat isDirectory', stat.isDirectory(), false); 23 + test('stat size', stat.size > 0, true); 24 + 25 + const dirStat = await fs.stat(testDir); 26 + test('stat dir isDirectory', dirStat.isDirectory(), true); 27 + 28 + const files = await fs.readdir(testDir); 29 + test('readdir length', files.length >= 1, true); 30 + test('readdir includes test.txt', files.includes('test.txt'), true); 31 + 32 + await fs.unlink(testFile); 33 + test('unlink removes file', await fs.exists(testFile), false); 34 + 35 + // fd-based open/write/close 36 + const fdFile = path.join(testDir, 'fd_test.txt'); 37 + const fd = await fs.open(fdFile, 'w'); 38 + test('open returns fd', typeof fd, 'number'); 39 + 40 + const written = await fs.write(fd, 'hello fd'); 41 + test('write returns bytes written', written, 8); 42 + 43 + const buf = new Uint8Array([33]); 44 + const bufWritten = await fs.write(fd, buf); 45 + test('write buffer returns bytes written', bufWritten, 1); 46 + 47 + await fs.close(fd); 48 + 49 + const fdContent = fs.readFileSync(fdFile, 'utf8'); 50 + test('write wrote correct data', fdContent, 'hello fd!'); 51 + 52 + await fs.unlink(fdFile); 53 + 54 + // writev 55 + const wvFile = path.join(testDir, 'writev_test.txt'); 56 + const wvFd = await fs.open(wvFile, 'w'); 57 + const bufs = [new Uint8Array([65, 66]), new Uint8Array([67, 68])]; 58 + const wvWritten = await fs.writev(wvFd, bufs); 59 + test('writev returns total bytes', wvWritten, 4); 60 + await fs.close(wvFd); 61 + 62 + const wvContent = fs.readFileSync(wvFile, 'utf8'); 63 + test('writev wrote correct data', wvContent, 'ABCD'); 64 + await fs.unlink(wvFile); 65 + 66 + await fs.rmdir(testDir); 67 + test('rmdir removes dir', await fs.exists(testDir), false); 68 + 69 + summary(); 70 + } 71 + 72 + void run();
+441 -2
src/modules/fs.c
··· 135 135 FS_OP_READ_BYTES, 136 136 FS_OP_EXISTS, 137 137 FS_OP_READDIR, 138 - FS_OP_ACCESS 138 + FS_OP_ACCESS, 139 + FS_OP_WRITE_FD, 140 + FS_OP_OPEN, 141 + FS_OP_CLOSE 139 142 } fs_op_type_t; 140 143 141 144 typedef struct fs_request_s { ··· 1327 1330 return req->promise; 1328 1331 } 1329 1332 1333 + static void on_write_fd_complete(uv_fs_t *uv_req) { 1334 + fs_request_t *req = (fs_request_t *)uv_req->data; 1335 + 1336 + if (uv_req->result < 0) { 1337 + req->failed = 1; 1338 + req->error_msg = strdup(uv_strerror((int)uv_req->result)); 1339 + req->completed = 1; 1340 + complete_request(req); 1341 + return; 1342 + } 1343 + 1344 + req->completed = 1; 1345 + js_resolve_promise(req->js, req->promise, js_mknum((double)uv_req->result)); 1346 + remove_pending_request(req); 1347 + free_fs_request(req); 1348 + } 1349 + 1350 + static jsval_t builtin_fs_writeSync(struct js *js, jsval_t *args, int nargs) { 1351 + if (nargs < 2) return js_mkerr(js, "writeSync() requires fd and data arguments"); 1352 + if (vtype(args[0]) != T_NUM) return js_mkerr(js, "writeSync() fd must be a number"); 1353 + 1354 + int fd = (int)js_getnum(args[0]); 1355 + 1356 + if (vtype(args[1]) == T_STR) { 1357 + size_t str_len; 1358 + const char *str = js_getstr(js, args[1], &str_len); 1359 + if (!str) return js_mkerr(js, "Failed to get string"); 1360 + 1361 + int64_t position = -1; 1362 + if (nargs >= 3 && vtype(args[2]) == T_NUM) 1363 + position = (int64_t)js_getnum(args[2]); 1364 + 1365 + uv_fs_t req; 1366 + uv_buf_t buf = uv_buf_init((char *)str, (unsigned int)str_len); 1367 + int result = uv_fs_write(uv_default_loop(), &req, fd, &buf, 1, position, NULL); 1368 + uv_fs_req_cleanup(&req); 1369 + 1370 + if (result < 0) return js_mkerr(js, "writeSync failed: %s", uv_strerror(result)); 1371 + return js_mknum((double)result); 1372 + } 1373 + 1374 + jsval_t ta_data_val = js_get_slot(js, args[1], SLOT_BUFFER); 1375 + TypedArrayData *ta_data = (TypedArrayData *)js_gettypedarray(ta_data_val); 1376 + if (!ta_data || !ta_data->buffer || !ta_data->buffer->data) 1377 + return js_mkerr(js, "writeSync() second argument must be a Buffer, TypedArray, DataView, or string"); 1378 + 1379 + uint8_t *buf_data = ta_data->buffer->data + ta_data->byte_offset; 1380 + size_t buf_len = ta_data->byte_length; 1381 + size_t offset = 0; 1382 + size_t length = buf_len; 1383 + int64_t position = -1; 1384 + 1385 + if (nargs >= 3) { 1386 + if (vtype(args[2]) == T_OBJ) { 1387 + jsval_t off_val = js_get(js, args[2], "offset"); 1388 + jsval_t len_val = js_get(js, args[2], "length"); 1389 + jsval_t pos_val = js_get(js, args[2], "position"); 1390 + if (vtype(off_val) == T_NUM) offset = (size_t)js_getnum(off_val); 1391 + if (vtype(len_val) == T_NUM) length = (size_t)js_getnum(len_val); 1392 + else length = buf_len - offset; 1393 + if (vtype(pos_val) == T_NUM) position = (int64_t)js_getnum(pos_val); 1394 + } else if (vtype(args[2]) == T_NUM) { 1395 + offset = (size_t)js_getnum(args[2]); 1396 + length = buf_len - offset; 1397 + if (nargs >= 4 && vtype(args[3]) == T_NUM) length = (size_t)js_getnum(args[3]); 1398 + if (nargs >= 5 && vtype(args[4]) == T_NUM) position = (int64_t)js_getnum(args[4]); 1399 + } 1400 + } 1401 + 1402 + if (offset > buf_len) return js_mkerr(js, "offset is out of bounds"); 1403 + if (offset + length > buf_len) return js_mkerr(js, "length extends beyond buffer"); 1404 + 1405 + uv_fs_t req; 1406 + uv_buf_t buf = uv_buf_init((char *)(buf_data + offset), (unsigned int)length); 1407 + int result = uv_fs_write(uv_default_loop(), &req, fd, &buf, 1, position, NULL); 1408 + uv_fs_req_cleanup(&req); 1409 + 1410 + if (result < 0) return js_mkerr(js, "writeSync failed: %s", uv_strerror(result)); 1411 + return js_mknum((double)result); 1412 + } 1413 + 1414 + static jsval_t builtin_fs_write_fd(struct js *js, jsval_t *args, int nargs) { 1415 + if (nargs < 2) return js_mkerr(js, "write() requires fd and data arguments"); 1416 + if (vtype(args[0]) != T_NUM) return js_mkerr(js, "write() fd must be a number"); 1417 + 1418 + int fd = (int)js_getnum(args[0]); 1419 + const char *write_data; 1420 + size_t write_len; 1421 + int64_t position = -1; 1422 + 1423 + if (vtype(args[1]) == T_STR) { 1424 + size_t str_len; 1425 + const char *str = js_getstr(js, args[1], &str_len); 1426 + if (!str) return js_mkerr(js, "Failed to get string"); 1427 + 1428 + if (nargs >= 3 && vtype(args[2]) == T_NUM) 1429 + position = (int64_t)js_getnum(args[2]); 1430 + 1431 + write_data = str; 1432 + write_len = str_len; 1433 + } else { 1434 + jsval_t ta_data_val = js_get_slot(js, args[1], SLOT_BUFFER); 1435 + TypedArrayData *ta_data = (TypedArrayData *)js_gettypedarray(ta_data_val); 1436 + if (!ta_data || !ta_data->buffer || !ta_data->buffer->data) 1437 + return js_mkerr(js, "write() second argument must be a Buffer, TypedArray, DataView, or string"); 1438 + 1439 + uint8_t *buf_data = ta_data->buffer->data + ta_data->byte_offset; 1440 + size_t buf_len = ta_data->byte_length; 1441 + size_t offset = 0; 1442 + size_t length = buf_len; 1443 + 1444 + if (nargs >= 3) { 1445 + if (vtype(args[2]) == T_OBJ) { 1446 + jsval_t off_val = js_get(js, args[2], "offset"); 1447 + jsval_t len_val = js_get(js, args[2], "length"); 1448 + jsval_t pos_val = js_get(js, args[2], "position"); 1449 + if (vtype(off_val) == T_NUM) offset = (size_t)js_getnum(off_val); 1450 + if (vtype(len_val) == T_NUM) length = (size_t)js_getnum(len_val); 1451 + else length = buf_len - offset; 1452 + if (vtype(pos_val) == T_NUM) position = (int64_t)js_getnum(pos_val); 1453 + } else if (vtype(args[2]) == T_NUM) { 1454 + offset = (size_t)js_getnum(args[2]); 1455 + length = buf_len - offset; 1456 + if (nargs >= 4 && vtype(args[3]) == T_NUM) length = (size_t)js_getnum(args[3]); 1457 + if (nargs >= 5 && vtype(args[4]) == T_NUM) position = (int64_t)js_getnum(args[4]); 1458 + } 1459 + } 1460 + 1461 + if (offset > buf_len) return js_mkerr(js, "offset is out of bounds"); 1462 + if (offset + length > buf_len) return js_mkerr(js, "length extends beyond buffer"); 1463 + 1464 + write_data = (const char *)(buf_data + offset); 1465 + write_len = length; 1466 + } 1467 + 1468 + fs_request_t *req = calloc(1, sizeof(fs_request_t)); 1469 + if (!req) return js_mkerr(js, "Out of memory"); 1470 + 1471 + req->js = js; 1472 + req->op_type = FS_OP_WRITE_FD; 1473 + req->promise = js_mkpromise(js); 1474 + req->fd = fd; 1475 + req->data = malloc(write_len); 1476 + if (!req->data) { 1477 + free(req); 1478 + return js_mkerr(js, "Out of memory"); 1479 + } 1480 + memcpy(req->data, write_data, write_len); 1481 + req->data_len = write_len; 1482 + req->uv_req.data = req; 1483 + 1484 + utarray_push_back(pending_requests, &req); 1485 + 1486 + uv_buf_t buf = uv_buf_init(req->data, (unsigned int)req->data_len); 1487 + int result = uv_fs_write(uv_default_loop(), &req->uv_req, req->fd, &buf, 1, position, on_write_fd_complete); 1488 + 1489 + if (result < 0) { 1490 + req->failed = 1; 1491 + req->error_msg = strdup(uv_strerror(result)); 1492 + req->completed = 1; 1493 + complete_request(req); 1494 + } 1495 + 1496 + return req->promise; 1497 + } 1498 + 1499 + static jsval_t builtin_fs_writevSync(struct js *js, jsval_t *args, int nargs) { 1500 + if (nargs < 2) return js_mkerr(js, "writevSync() requires fd and buffers arguments"); 1501 + if (vtype(args[0]) != T_NUM) return js_mkerr(js, "writevSync() fd must be a number"); 1502 + 1503 + int fd = (int)js_getnum(args[0]); 1504 + jsoff_t arr_len = js_arr_len(js, args[1]); 1505 + if (arr_len == 0) return js_mknum(0); 1506 + 1507 + int64_t position = -1; 1508 + if (nargs >= 3 && vtype(args[2]) == T_NUM) 1509 + position = (int64_t)js_getnum(args[2]); 1510 + 1511 + uv_buf_t *bufs = calloc((size_t)arr_len, sizeof(uv_buf_t)); 1512 + if (!bufs) return js_mkerr(js, "Out of memory"); 1513 + 1514 + for (jsoff_t i = 0; i < arr_len; i++) { 1515 + jsval_t item = js_arr_get(js, args[1], i); 1516 + jsval_t ta_val = js_get_slot(js, item, SLOT_BUFFER); 1517 + TypedArrayData *ta = (TypedArrayData *)js_gettypedarray(ta_val); 1518 + if (!ta || !ta->buffer || !ta->buffer->data) { 1519 + free(bufs); 1520 + return js_mkerr(js, "writevSync() buffers must contain ArrayBufferViews"); 1521 + } 1522 + bufs[i] = uv_buf_init((char *)(ta->buffer->data + ta->byte_offset), (unsigned int)ta->byte_length); 1523 + } 1524 + 1525 + uv_fs_t req; 1526 + int result = uv_fs_write(uv_default_loop(), &req, fd, bufs, (unsigned int)arr_len, position, NULL); 1527 + uv_fs_req_cleanup(&req); 1528 + free(bufs); 1529 + 1530 + if (result < 0) return js_mkerr(js, "writevSync failed: %s", uv_strerror(result)); 1531 + return js_mknum((double)result); 1532 + } 1533 + 1534 + static jsval_t builtin_fs_writev_fd(struct js *js, jsval_t *args, int nargs) { 1535 + if (nargs < 2) return js_mkerr(js, "writev() requires fd and buffers arguments"); 1536 + if (vtype(args[0]) != T_NUM) return js_mkerr(js, "writev() fd must be a number"); 1537 + 1538 + int fd = (int)js_getnum(args[0]); 1539 + jsoff_t arr_len = js_arr_len(js, args[1]); 1540 + 1541 + if (arr_len == 0) { 1542 + jsval_t promise = js_mkpromise(js); 1543 + js_resolve_promise(js, promise, js_mknum(0)); 1544 + return promise; 1545 + } 1546 + 1547 + int64_t position = -1; 1548 + if (nargs >= 3 && vtype(args[2]) == T_NUM) 1549 + position = (int64_t)js_getnum(args[2]); 1550 + 1551 + size_t total_len = 0; 1552 + for (jsoff_t i = 0; i < arr_len; i++) { 1553 + jsval_t item = js_arr_get(js, args[1], i); 1554 + jsval_t ta_val = js_get_slot(js, item, SLOT_BUFFER); 1555 + TypedArrayData *ta = (TypedArrayData *)js_gettypedarray(ta_val); 1556 + if (!ta || !ta->buffer || !ta->buffer->data) 1557 + return js_mkerr(js, "writev() buffers must contain ArrayBufferViews"); 1558 + total_len += ta->byte_length; 1559 + } 1560 + 1561 + fs_request_t *req = calloc(1, sizeof(fs_request_t)); 1562 + if (!req) return js_mkerr(js, "Out of memory"); 1563 + 1564 + req->data = malloc(total_len); 1565 + if (!req->data) { 1566 + free(req); 1567 + return js_mkerr(js, "Out of memory"); 1568 + } 1569 + 1570 + size_t off = 0; 1571 + for (jsoff_t i = 0; i < arr_len; i++) { 1572 + jsval_t item = js_arr_get(js, args[1], i); 1573 + jsval_t ta_val = js_get_slot(js, item, SLOT_BUFFER); 1574 + TypedArrayData *ta = (TypedArrayData *)js_gettypedarray(ta_val); 1575 + memcpy(req->data + off, ta->buffer->data + ta->byte_offset, ta->byte_length); 1576 + off += ta->byte_length; 1577 + } 1578 + 1579 + req->js = js; 1580 + req->op_type = FS_OP_WRITE_FD; 1581 + req->promise = js_mkpromise(js); 1582 + req->fd = fd; 1583 + req->data_len = total_len; 1584 + req->uv_req.data = req; 1585 + 1586 + utarray_push_back(pending_requests, &req); 1587 + 1588 + uv_buf_t buf = uv_buf_init(req->data, (unsigned int)total_len); 1589 + int result = uv_fs_write(uv_default_loop(), &req->uv_req, req->fd, &buf, 1, position, on_write_fd_complete); 1590 + 1591 + if (result < 0) { 1592 + req->failed = 1; 1593 + req->error_msg = strdup(uv_strerror(result)); 1594 + req->completed = 1; 1595 + complete_request(req); 1596 + } 1597 + 1598 + return req->promise; 1599 + } 1600 + 1601 + static int parse_open_flags(struct js *js, jsval_t arg) { 1602 + if (vtype(arg) == T_NUM) return (int)js_getnum(arg); 1603 + if (vtype(arg) != T_STR) return O_RDONLY; 1604 + 1605 + size_t len; 1606 + const char *str = js_getstr(js, arg, &len); 1607 + if (!str) return O_RDONLY; 1608 + 1609 + if (len == 1 && str[0] == 'r') return O_RDONLY; 1610 + if (len == 2 && memcmp(str, "r+", 2) == 0) return O_RDWR; 1611 + if (len == 1 && str[0] == 'w') return O_WRONLY | O_CREAT | O_TRUNC; 1612 + if (len == 2 && memcmp(str, "wx", 2) == 0) return O_WRONLY | O_CREAT | O_TRUNC | O_EXCL; 1613 + if (len == 2 && memcmp(str, "w+", 2) == 0) return O_RDWR | O_CREAT | O_TRUNC; 1614 + if (len == 3 && memcmp(str, "wx+", 3) == 0) return O_RDWR | O_CREAT | O_TRUNC | O_EXCL; 1615 + if (len == 1 && str[0] == 'a') return O_WRONLY | O_CREAT | O_APPEND; 1616 + if (len == 2 && memcmp(str, "ax", 2) == 0) return O_WRONLY | O_CREAT | O_APPEND | O_EXCL; 1617 + if (len == 2 && memcmp(str, "a+", 2) == 0) return O_RDWR | O_CREAT | O_APPEND; 1618 + if (len == 3 && memcmp(str, "ax+", 3) == 0) return O_RDWR | O_CREAT | O_APPEND | O_EXCL; 1619 + 1620 + return O_RDONLY; 1621 + } 1622 + 1623 + static jsval_t builtin_fs_openSync(struct js *js, jsval_t *args, int nargs) { 1624 + if (nargs < 1) return js_mkerr(js, "openSync() requires a path argument"); 1625 + if (vtype(args[0]) != T_STR) return js_mkerr(js, "openSync() path must be a string"); 1626 + 1627 + size_t path_len; 1628 + char *path = js_getstr(js, args[0], &path_len); 1629 + if (!path) return js_mkerr(js, "Failed to get path string"); 1630 + 1631 + int flags = (nargs >= 2) ? parse_open_flags(js, args[1]) : O_RDONLY; 1632 + int mode = (nargs >= 3 && vtype(args[2]) == T_NUM) ? (int)js_getnum(args[2]) : 0666; 1633 + 1634 + char *path_cstr = strndup(path, path_len); 1635 + if (!path_cstr) return js_mkerr(js, "Out of memory"); 1636 + 1637 + uv_fs_t req; 1638 + int result = uv_fs_open(uv_default_loop(), &req, path_cstr, flags, mode, NULL); 1639 + uv_fs_req_cleanup(&req); 1640 + free(path_cstr); 1641 + 1642 + if (result < 0) return js_mkerr(js, "openSync failed: %s", uv_strerror(result)); 1643 + return js_mknum((double)result); 1644 + } 1645 + 1646 + static jsval_t builtin_fs_closeSync(struct js *js, jsval_t *args, int nargs) { 1647 + if (nargs < 1) return js_mkerr(js, "closeSync() requires a fd argument"); 1648 + if (vtype(args[0]) != T_NUM) return js_mkerr(js, "closeSync() fd must be a number"); 1649 + 1650 + int fd = (int)js_getnum(args[0]); 1651 + 1652 + uv_fs_t req; 1653 + int result = uv_fs_close(uv_default_loop(), &req, fd, NULL); 1654 + uv_fs_req_cleanup(&req); 1655 + 1656 + if (result < 0) return js_mkerr(js, "closeSync failed: %s", uv_strerror(result)); 1657 + return js_mkundef(); 1658 + } 1659 + 1660 + static void on_open_fd_complete(uv_fs_t *uv_req) { 1661 + fs_request_t *req = (fs_request_t *)uv_req->data; 1662 + 1663 + if (uv_req->result < 0) { 1664 + req->failed = 1; 1665 + req->error_msg = strdup(uv_strerror((int)uv_req->result)); 1666 + req->completed = 1; 1667 + complete_request(req); 1668 + return; 1669 + } 1670 + 1671 + req->completed = 1; 1672 + js_resolve_promise(req->js, req->promise, js_mknum((double)uv_req->result)); 1673 + remove_pending_request(req); 1674 + free_fs_request(req); 1675 + } 1676 + 1677 + static jsval_t builtin_fs_open_fd(struct js *js, jsval_t *args, int nargs) { 1678 + if (nargs < 1) return js_mkerr(js, "open() requires a path argument"); 1679 + if (vtype(args[0]) != T_STR) return js_mkerr(js, "open() path must be a string"); 1680 + 1681 + size_t path_len; 1682 + char *path = js_getstr(js, args[0], &path_len); 1683 + if (!path) return js_mkerr(js, "Failed to get path string"); 1684 + 1685 + int flags = (nargs >= 2) ? parse_open_flags(js, args[1]) : O_RDONLY; 1686 + int mode = (nargs >= 3 && vtype(args[2]) == T_NUM) ? (int)js_getnum(args[2]) : 0666; 1687 + 1688 + fs_request_t *req = calloc(1, sizeof(fs_request_t)); 1689 + if (!req) return js_mkerr(js, "Out of memory"); 1690 + 1691 + req->js = js; 1692 + req->op_type = FS_OP_OPEN; 1693 + req->promise = js_mkpromise(js); 1694 + req->path = strndup(path, path_len); 1695 + req->uv_req.data = req; 1696 + 1697 + utarray_push_back(pending_requests, &req); 1698 + int result = uv_fs_open(uv_default_loop(), &req->uv_req, req->path, flags, mode, on_open_fd_complete); 1699 + 1700 + if (result < 0) { 1701 + req->failed = 1; 1702 + req->error_msg = strdup(uv_strerror(result)); 1703 + req->completed = 1; 1704 + complete_request(req); 1705 + } 1706 + 1707 + return req->promise; 1708 + } 1709 + 1710 + static void on_close_fd_complete(uv_fs_t *uv_req) { 1711 + fs_request_t *req = (fs_request_t *)uv_req->data; 1712 + 1713 + if (uv_req->result < 0) { 1714 + req->failed = 1; 1715 + req->error_msg = strdup(uv_strerror((int)uv_req->result)); 1716 + req->completed = 1; 1717 + complete_request(req); 1718 + return; 1719 + } 1720 + 1721 + req->completed = 1; 1722 + js_resolve_promise(req->js, req->promise, js_mkundef()); 1723 + remove_pending_request(req); 1724 + free_fs_request(req); 1725 + } 1726 + 1727 + static jsval_t builtin_fs_close_fd(struct js *js, jsval_t *args, int nargs) { 1728 + if (nargs < 1) return js_mkerr(js, "close() requires a fd argument"); 1729 + if (vtype(args[0]) != T_NUM) return js_mkerr(js, "close() fd must be a number"); 1730 + 1731 + int fd = (int)js_getnum(args[0]); 1732 + 1733 + fs_request_t *req = calloc(1, sizeof(fs_request_t)); 1734 + if (!req) return js_mkerr(js, "Out of memory"); 1735 + 1736 + req->js = js; 1737 + req->op_type = FS_OP_CLOSE; 1738 + req->promise = js_mkpromise(js); 1739 + req->fd = fd; 1740 + req->uv_req.data = req; 1741 + 1742 + utarray_push_back(pending_requests, &req); 1743 + int result = uv_fs_close(uv_default_loop(), &req->uv_req, req->fd, on_close_fd_complete); 1744 + 1745 + if (result < 0) { 1746 + req->failed = 1; 1747 + req->error_msg = strdup(uv_strerror(result)); 1748 + req->completed = 1; 1749 + complete_request(req); 1750 + } 1751 + 1752 + return req->promise; 1753 + } 1754 + 1330 1755 void init_fs_module(void) { 1331 1756 utarray_new(pending_requests, &ut_ptr_icd); 1332 1757 ··· 1354 1779 js_set(js, lib, "readFile", js_mkfun(builtin_fs_readFile)); 1355 1780 js_set(js, lib, "readFileSync", js_mkfun(builtin_fs_readFileSync)); 1356 1781 js_set(js, lib, "stream", js_mkfun(builtin_fs_readBytes)); 1357 - js_set(js, lib, "open", js_mkfun(builtin_fs_readBytesSync)); 1782 + js_set(js, lib, "open", js_mkfun(builtin_fs_open_fd)); 1783 + js_set(js, lib, "openSync", js_mkfun(builtin_fs_openSync)); 1784 + js_set(js, lib, "close", js_mkfun(builtin_fs_close_fd)); 1785 + js_set(js, lib, "closeSync", js_mkfun(builtin_fs_closeSync)); 1358 1786 js_set(js, lib, "writeFile", js_mkfun(builtin_fs_writeFile)); 1359 1787 js_set(js, lib, "writeFileSync", js_mkfun(builtin_fs_writeFileSync)); 1788 + js_set(js, lib, "write", js_mkfun(builtin_fs_write_fd)); 1789 + js_set(js, lib, "writeSync", js_mkfun(builtin_fs_writeSync)); 1790 + js_set(js, lib, "writev", js_mkfun(builtin_fs_writev_fd)); 1791 + js_set(js, lib, "writevSync", js_mkfun(builtin_fs_writevSync)); 1360 1792 js_set(js, lib, "appendFileSync", js_mkfun(builtin_fs_appendFileSync)); 1361 1793 js_set(js, lib, "copyFileSync", js_mkfun(builtin_fs_copyFileSync)); 1362 1794 js_set(js, lib, "renameSync", js_mkfun(builtin_fs_renameSync)); ··· 1381 1813 js_set(js, constants, "R_OK", js_mknum(R_OK)); 1382 1814 js_set(js, constants, "W_OK", js_mknum(W_OK)); 1383 1815 js_set(js, constants, "X_OK", js_mknum(X_OK)); 1816 + js_set(js, constants, "O_RDONLY", js_mknum(O_RDONLY)); 1817 + js_set(js, constants, "O_WRONLY", js_mknum(O_WRONLY)); 1818 + js_set(js, constants, "O_RDWR", js_mknum(O_RDWR)); 1819 + js_set(js, constants, "O_CREAT", js_mknum(O_CREAT)); 1820 + js_set(js, constants, "O_EXCL", js_mknum(O_EXCL)); 1821 + js_set(js, constants, "O_TRUNC", js_mknum(O_TRUNC)); 1822 + js_set(js, constants, "O_APPEND", js_mknum(O_APPEND)); 1384 1823 js_set(js, lib, "constants", constants); 1385 1824 1386 1825 return lib;