xbintsc 0.3.12 → 0.3.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -3
- package/README.zh-CN.md +18 -3
- package/dist/src/codegen/generator/calls/access.js +13 -0
- package/dist/src/codegen/generator/calls/access.js.map +1 -1
- package/dist/src/codegen/generator/calls/invocation.js +8 -2
- package/dist/src/codegen/generator/calls/invocation.js.map +1 -1
- package/dist/src/codegen/generator/context.d.ts +23 -0
- package/dist/src/codegen/generator/context.js +91 -17
- package/dist/src/codegen/generator/context.js.map +1 -1
- package/dist/src/codegen/generator/expressions/primary.js +5 -0
- package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
- package/dist/src/driver/compiler.d.ts +7 -0
- package/dist/src/driver/compiler.js +41 -5
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/modules.d.ts +1 -1
- package/dist/src/driver/modules.js +235 -25
- package/dist/src/driver/modules.js.map +1 -1
- package/dist/src/extensions/node/fs/fs-ops.d.ts +5 -2
- package/dist/src/extensions/node/fs/fs-ops.js +45 -6
- package/dist/src/extensions/node/fs/fs-ops.js.map +1 -1
- package/dist/src/extensions/node/fs/index.d.ts +6 -2
- package/dist/src/extensions/node/fs/index.js +22 -3
- package/dist/src/extensions/node/fs/index.js.map +1 -1
- package/dist/src/extensions/node/fs-promises/index.d.ts +4 -3
- package/dist/src/extensions/node/fs-promises/index.js +31 -3
- package/dist/src/extensions/node/fs-promises/index.js.map +1 -1
- package/dist/tests/cli/main.test.js +17 -0
- package/dist/tests/cli/main.test.js.map +1 -1
- package/dist/tests/driver/compiler.test.js +93 -2
- package/dist/tests/driver/compiler.test.js.map +1 -1
- package/dist/tests/driver/modules.test.js +91 -4
- package/dist/tests/driver/modules.test.js.map +1 -1
- package/dist/tests/e2e/compile-node.test.js +240 -0
- package/dist/tests/e2e/compile-node.test.js.map +1 -1
- package/dist/tests/e2e/compile.test.js +12 -0
- package/dist/tests/e2e/compile.test.js.map +1 -1
- package/dist/tests/e2e/harness.js +11 -8
- package/dist/tests/e2e/harness.js.map +1 -1
- package/dist/tests/e2e/node-modules.test.js +1 -1
- package/dist/tests/e2e/node-modules.test.js.map +1 -1
- package/dist/tests/e2e/npm-modules.test.d.ts +9 -0
- package/dist/tests/e2e/npm-modules.test.js +55 -0
- package/dist/tests/e2e/npm-modules.test.js.map +1 -0
- package/dist/tests/e2e/runtime-coverage.test.d.ts +11 -0
- package/dist/tests/e2e/runtime-coverage.test.js +646 -0
- package/dist/tests/e2e/runtime-coverage.test.js.map +1 -0
- package/package.json +3 -2
- package/runtime/ext_node/buffer/parts/prototype.inc +7 -0
- package/runtime/ext_node/buffer/parts/search.inc +8 -4
- package/runtime/ext_node/child_process/child_process.c +5 -0
- package/runtime/ext_node/fs/constants.c +113 -0
- package/runtime/ext_node/fs/copy_ops.c +145 -0
- package/runtime/ext_node/fs/dir.c +101 -0
- package/runtime/ext_node/fs/fd_ops.c +405 -0
- package/runtime/ext_node/fs/fs_common.h +388 -5
- package/runtime/ext_node/fs/fs_ops.c +100 -139
- package/runtime/ext_node/fs/glob.c +232 -0
- package/runtime/ext_node/fs/link_ops.c +91 -0
- package/runtime/ext_node/fs/meta_ops.c +403 -0
- package/runtime/ext_node/fs/promises.c +275 -60
- package/runtime/ext_node/fs/read_file.c +8 -4
- package/runtime/ext_node/fs/watch.c +52 -0
- package/runtime/ext_node/fs/write_file.c +20 -11
- package/runtime/ext_node/stream/stream.c +19 -2
- package/runtime/rt.h +9 -0
- package/runtime/xt_io.c +21 -0
- package/scripts/coverage-runtime.ts +338 -0
- package/src/codegen/generator/calls/access.ts +15 -0
- package/src/codegen/generator/calls/invocation.ts +8 -2
- package/src/codegen/generator/context.ts +112 -21
- package/src/codegen/generator/expressions/primary.ts +5 -0
- package/src/driver/compiler.ts +42 -5
- package/src/driver/modules.ts +251 -26
- package/src/extensions/node/fs/fs-ops.ts +48 -6
- package/src/extensions/node/fs/index.ts +25 -3
- package/src/extensions/node/fs-promises/index.ts +33 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xbintsc",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.14",
|
|
4
4
|
"description": "xbintsc - a TypeScript binary compiler (TypeScript -> LLVM IR -> native binary)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
"test": "vitest run",
|
|
43
43
|
"test:watch": "vitest",
|
|
44
44
|
"test:e2e": "vitest run tests/e2e",
|
|
45
|
-
"coverage": "vitest run --coverage"
|
|
45
|
+
"coverage": "vitest run --coverage",
|
|
46
|
+
"coverage:runtime": "tsx scripts/coverage-runtime.ts"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
48
49
|
"@eslint/js": "^9.39.5",
|
|
@@ -52,3 +52,10 @@ unsigned char *xt_node_buffer_bytes(xt_value value, size_t *outLength) {
|
|
|
52
52
|
*outLength = length;
|
|
53
53
|
return bytes;
|
|
54
54
|
}
|
|
55
|
+
|
|
56
|
+
/* Cross-module helpers used by the fs module to fill/read Buffer objects. */
|
|
57
|
+
uint32_t xt_node_buffer_length(xt_value value) { return xt_buffer_length(value); }
|
|
58
|
+
|
|
59
|
+
void xt_node_buffer_set(xt_value value, uint32_t index, unsigned char byte) {
|
|
60
|
+
xt_buffer_put(value, index, byte);
|
|
61
|
+
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/* -- search --------------------------------------------------------------- */
|
|
2
2
|
|
|
3
3
|
static const unsigned char *xt_buffer_search_needle(xt_value value, const char *encoding, size_t *length,
|
|
4
|
-
unsigned char *single) {
|
|
4
|
+
unsigned char *single, int *heapAllocated) {
|
|
5
5
|
if (XT_IS_NUMBER(value)) {
|
|
6
6
|
*single = (unsigned char)((int32_t)xt_to_number(value) & 0xff);
|
|
7
7
|
*length = 1;
|
|
8
|
+
*heapAllocated = 0;
|
|
8
9
|
return single;
|
|
9
10
|
}
|
|
11
|
+
*heapAllocated = 1;
|
|
10
12
|
if (xt_buffer_is(value)) {
|
|
11
13
|
uint32_t n = xt_buffer_length(value);
|
|
12
14
|
unsigned char *bytes = (unsigned char *)malloc(n ? n : 1);
|
|
@@ -28,13 +30,15 @@ static xt_value xt_buffer_method_index_of(xt_value thisValue, xt_value env, int3
|
|
|
28
30
|
const char *encoding = argc > 2 ? xt_node_encoding(argv[2]) : NULL;
|
|
29
31
|
size_t needleLength = 0;
|
|
30
32
|
unsigned char single = 0;
|
|
31
|
-
|
|
33
|
+
int needleOnHeap = 0;
|
|
34
|
+
const unsigned char *needle =
|
|
35
|
+
xt_buffer_search_needle(xt_arg_at(argc, argv, 0), encoding, &needleLength, &single, &needleOnHeap);
|
|
32
36
|
uint32_t length = xt_buffer_length(thisValue);
|
|
33
37
|
int32_t start = argc > 1 ? (int32_t)xt_to_number(argv[1]) : (reverse ? (int32_t)length - 1 : 0);
|
|
34
38
|
if (start < 0) start += (int32_t)length;
|
|
35
39
|
if (start < 0) start = 0;
|
|
36
40
|
if (needleLength == 0 || needleLength > length) {
|
|
37
|
-
if (
|
|
41
|
+
if (needleOnHeap) free((void *)needle);
|
|
38
42
|
return xt_number(-1);
|
|
39
43
|
}
|
|
40
44
|
int found = -1;
|
|
@@ -68,7 +72,7 @@ static xt_value xt_buffer_method_index_of(xt_value thisValue, xt_value env, int3
|
|
|
68
72
|
}
|
|
69
73
|
}
|
|
70
74
|
}
|
|
71
|
-
if (
|
|
75
|
+
if (needleOnHeap) free((void *)needle);
|
|
72
76
|
return xt_number((double)found);
|
|
73
77
|
}
|
|
74
78
|
|
|
@@ -112,6 +112,11 @@ xt_value xt_child_process_spawn_sync(int32_t argc, xt_value *argv) {
|
|
|
112
112
|
return make_result(-1, "", "could not create temporary files");
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
/* Flush anything the parent has already buffered on stdout/stderr before
|
|
116
|
+
* redirecting the descriptors; otherwise that pending output would be
|
|
117
|
+
* flushed into the child's capture file (and lost from the real stdout). */
|
|
118
|
+
fflush(stdout);
|
|
119
|
+
fflush(stderr);
|
|
115
120
|
int saved_out = _dup(_fileno(stdout));
|
|
116
121
|
int saved_err = _dup(_fileno(stderr));
|
|
117
122
|
_dup2(_fileno(out_file), _fileno(stdout));
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* `fs.constants` for xbintsc.
|
|
3
|
+
*
|
|
4
|
+
* The numeric values mirror the host platform's `<fcntl.h>` / `<sys/stat.h>`
|
|
5
|
+
* (which is what Node reports on that platform). Constants a platform does not
|
|
6
|
+
* define are omitted rather than faked.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#include "../node_common.h"
|
|
10
|
+
#include "fs_common.h"
|
|
11
|
+
|
|
12
|
+
#include <sys/stat.h>
|
|
13
|
+
|
|
14
|
+
#if defined(_WIN32)
|
|
15
|
+
#include <fcntl.h>
|
|
16
|
+
#endif
|
|
17
|
+
|
|
18
|
+
#ifndef F_OK
|
|
19
|
+
#define F_OK 0
|
|
20
|
+
#endif
|
|
21
|
+
#ifndef R_OK
|
|
22
|
+
#define R_OK 4
|
|
23
|
+
#endif
|
|
24
|
+
#ifndef W_OK
|
|
25
|
+
#define W_OK 2
|
|
26
|
+
#endif
|
|
27
|
+
#ifndef X_OK
|
|
28
|
+
#define X_OK 1
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
#define XT_FS_CONST(name, value) xt_object_set(object, xt_string_from_cstr(name), xt_number((double)(value)))
|
|
32
|
+
|
|
33
|
+
xt_value xt_fs_constants(void) {
|
|
34
|
+
xt_value object = xt_object_new();
|
|
35
|
+
|
|
36
|
+
XT_FS_CONST("F_OK", F_OK);
|
|
37
|
+
XT_FS_CONST("R_OK", R_OK);
|
|
38
|
+
XT_FS_CONST("W_OK", W_OK);
|
|
39
|
+
XT_FS_CONST("X_OK", X_OK);
|
|
40
|
+
|
|
41
|
+
XT_FS_CONST("COPYFILE_EXCL", 1);
|
|
42
|
+
XT_FS_CONST("COPYFILE_FICLONE", 2);
|
|
43
|
+
XT_FS_CONST("COPYFILE_FICLONE_FORCE", 4);
|
|
44
|
+
|
|
45
|
+
#ifdef O_RDONLY
|
|
46
|
+
XT_FS_CONST("O_RDONLY", O_RDONLY);
|
|
47
|
+
#endif
|
|
48
|
+
#ifdef O_WRONLY
|
|
49
|
+
XT_FS_CONST("O_WRONLY", O_WRONLY);
|
|
50
|
+
#endif
|
|
51
|
+
#ifdef O_RDWR
|
|
52
|
+
XT_FS_CONST("O_RDWR", O_RDWR);
|
|
53
|
+
#endif
|
|
54
|
+
#ifdef O_CREAT
|
|
55
|
+
XT_FS_CONST("O_CREAT", O_CREAT);
|
|
56
|
+
#elif defined(_O_CREAT)
|
|
57
|
+
XT_FS_CONST("O_CREAT", _O_CREAT);
|
|
58
|
+
#endif
|
|
59
|
+
#ifdef O_EXCL
|
|
60
|
+
XT_FS_CONST("O_EXCL", O_EXCL);
|
|
61
|
+
#elif defined(_O_EXCL)
|
|
62
|
+
XT_FS_CONST("O_EXCL", _O_EXCL);
|
|
63
|
+
#endif
|
|
64
|
+
#ifdef O_TRUNC
|
|
65
|
+
XT_FS_CONST("O_TRUNC", O_TRUNC);
|
|
66
|
+
#elif defined(_O_TRUNC)
|
|
67
|
+
XT_FS_CONST("O_TRUNC", _O_TRUNC);
|
|
68
|
+
#endif
|
|
69
|
+
#ifdef O_APPEND
|
|
70
|
+
XT_FS_CONST("O_APPEND", O_APPEND);
|
|
71
|
+
#elif defined(_O_APPEND)
|
|
72
|
+
XT_FS_CONST("O_APPEND", _O_APPEND);
|
|
73
|
+
#endif
|
|
74
|
+
#ifdef O_NOCTTY
|
|
75
|
+
XT_FS_CONST("O_NOCTTY", O_NOCTTY);
|
|
76
|
+
#endif
|
|
77
|
+
#ifdef O_DIRECTORY
|
|
78
|
+
XT_FS_CONST("O_DIRECTORY", O_DIRECTORY);
|
|
79
|
+
#endif
|
|
80
|
+
#ifdef O_NOFOLLOW
|
|
81
|
+
XT_FS_CONST("O_NOFOLLOW", O_NOFOLLOW);
|
|
82
|
+
#endif
|
|
83
|
+
#ifdef O_SYNC
|
|
84
|
+
XT_FS_CONST("O_SYNC", O_SYNC);
|
|
85
|
+
#endif
|
|
86
|
+
#ifdef O_DSYNC
|
|
87
|
+
XT_FS_CONST("O_DSYNC", O_DSYNC);
|
|
88
|
+
#endif
|
|
89
|
+
#ifdef O_NONBLOCK
|
|
90
|
+
XT_FS_CONST("O_NONBLOCK", O_NONBLOCK);
|
|
91
|
+
#endif
|
|
92
|
+
#ifdef O_SYMLINK
|
|
93
|
+
XT_FS_CONST("O_SYMLINK", O_SYMLINK);
|
|
94
|
+
#endif
|
|
95
|
+
|
|
96
|
+
#if defined(_WIN32)
|
|
97
|
+
XT_FS_CONST("S_IFMT", _S_IFMT);
|
|
98
|
+
XT_FS_CONST("S_IFREG", _S_IFREG);
|
|
99
|
+
XT_FS_CONST("S_IFDIR", _S_IFDIR);
|
|
100
|
+
XT_FS_CONST("S_IFCHR", _S_IFCHR);
|
|
101
|
+
#else
|
|
102
|
+
XT_FS_CONST("S_IFMT", S_IFMT);
|
|
103
|
+
XT_FS_CONST("S_IFREG", S_IFREG);
|
|
104
|
+
XT_FS_CONST("S_IFDIR", S_IFDIR);
|
|
105
|
+
XT_FS_CONST("S_IFCHR", S_IFCHR);
|
|
106
|
+
XT_FS_CONST("S_IFBLK", S_IFBLK);
|
|
107
|
+
XT_FS_CONST("S_IFIFO", S_IFIFO);
|
|
108
|
+
XT_FS_CONST("S_IFLNK", S_IFLNK);
|
|
109
|
+
XT_FS_CONST("S_IFSOCK", S_IFSOCK);
|
|
110
|
+
#endif
|
|
111
|
+
|
|
112
|
+
return object;
|
|
113
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Node.js `fs.cpSync` for xbintsc.
|
|
3
|
+
*
|
|
4
|
+
* Copies files, symbolic links and (with `recursive: true`) directories.
|
|
5
|
+
* Supported options: `recursive`, `force`, `errorOnExist`, `dereference`,
|
|
6
|
+
* `preserveTimestamps`. Other Node options are ignored (documented).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#include "../node_common.h"
|
|
10
|
+
#include "fs_common.h"
|
|
11
|
+
|
|
12
|
+
#if !defined(_WIN32)
|
|
13
|
+
#include <sys/time.h>
|
|
14
|
+
#include <unistd.h>
|
|
15
|
+
#endif
|
|
16
|
+
|
|
17
|
+
static int xt_fs_option_bool(xt_value options, const char *key, int fallback) {
|
|
18
|
+
if (!XT_IS_OBJECT(options)) return fallback;
|
|
19
|
+
xt_value value = xt_object_get_cstr(options, key);
|
|
20
|
+
if (XT_IS_UNDEFINED(value) || XT_IS_NULL(value)) return fallback;
|
|
21
|
+
return xt_truthy(value);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static void xt_fs_copy_file_bytes(const char *from, const char *to) {
|
|
25
|
+
FILE *source = fopen(from, "rb");
|
|
26
|
+
if (!source) {
|
|
27
|
+
xt_fs_error("open", from);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
FILE *destination = fopen(to, "wb");
|
|
31
|
+
if (!destination) {
|
|
32
|
+
fclose(source);
|
|
33
|
+
xt_fs_error("open", to);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
char buffer[8192];
|
|
37
|
+
size_t read;
|
|
38
|
+
while ((read = fread(buffer, 1, sizeof(buffer), source)) > 0) fwrite(buffer, 1, read, destination);
|
|
39
|
+
fclose(source);
|
|
40
|
+
fclose(destination);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static char *xt_fs_join(const char *dir, const char *name) {
|
|
44
|
+
size_t size = strlen(dir) + strlen(name) + 2;
|
|
45
|
+
char *path = (char *)malloc(size);
|
|
46
|
+
if (!path) return NULL;
|
|
47
|
+
snprintf(path, size, "%s/%s", dir, name);
|
|
48
|
+
return path;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static void xt_fs_copy_any(const char *src, const char *dest, xt_value options, int recursive) {
|
|
52
|
+
xt_fs_stat_t info;
|
|
53
|
+
if (xt_fs_lstat_fn(src, &info) != 0) {
|
|
54
|
+
xt_fs_raise_path("lstat", src);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
int force = xt_fs_option_bool(options, "force", 1);
|
|
58
|
+
int errorOnExist = xt_fs_option_bool(options, "errorOnExist", 0);
|
|
59
|
+
int dereference = xt_fs_option_bool(options, "dereference", 0);
|
|
60
|
+
|
|
61
|
+
if (S_ISDIR(info.st_mode)) {
|
|
62
|
+
if (!recursive) {
|
|
63
|
+
xt_fs_raise_errno(EISDIR, "cp", src);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (xt_fs_mkdir_mode(dest, (int)(info.st_mode & 0777)) != 0 && errno != EEXIST) {
|
|
67
|
+
xt_fs_raise_path("mkdir", dest);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
xt_fs_dir dir;
|
|
71
|
+
if (!xt_fs_dir_open(&dir, src)) {
|
|
72
|
+
xt_fs_error("open directory", src);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
while (xt_fs_dir_next(&dir)) {
|
|
76
|
+
const char *name = xt_fs_dir_name(&dir);
|
|
77
|
+
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) continue;
|
|
78
|
+
char *childSrc = xt_fs_join(src, name);
|
|
79
|
+
char *childDest = xt_fs_join(dest, name);
|
|
80
|
+
if (childSrc && childDest) xt_fs_copy_any(childSrc, childDest, options, recursive);
|
|
81
|
+
free(childSrc);
|
|
82
|
+
free(childDest);
|
|
83
|
+
}
|
|
84
|
+
xt_fs_dir_close(&dir);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (xt_fs_access(dest, F_OK) == 0) {
|
|
89
|
+
if (!force) {
|
|
90
|
+
if (errorOnExist) xt_fs_raise_errno(EEXIST, "cp", dest);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
#if !defined(_WIN32)
|
|
96
|
+
if (S_ISLNK(info.st_mode) && !dereference) {
|
|
97
|
+
size_t capacity = 256;
|
|
98
|
+
for (;;) {
|
|
99
|
+
char *target = (char *)malloc(capacity);
|
|
100
|
+
if (!target) return;
|
|
101
|
+
ssize_t length = readlink(src, target, capacity);
|
|
102
|
+
if (length < 0) {
|
|
103
|
+
free(target);
|
|
104
|
+
xt_fs_raise_path("readlink", src);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if ((size_t)length < capacity) {
|
|
108
|
+
target[length] = '\0';
|
|
109
|
+
if (symlink(target, dest) != 0) xt_fs_raise_path("symlink", dest);
|
|
110
|
+
free(target);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
free(target);
|
|
114
|
+
capacity *= 2;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
#endif
|
|
118
|
+
|
|
119
|
+
xt_fs_copy_file_bytes(src, dest);
|
|
120
|
+
|
|
121
|
+
if (xt_fs_option_bool(options, "preserveTimestamps", 0)) {
|
|
122
|
+
#if !defined(_WIN32)
|
|
123
|
+
struct timeval times[2];
|
|
124
|
+
times[0].tv_sec = info.st_atime;
|
|
125
|
+
times[0].tv_usec = 0;
|
|
126
|
+
times[1].tv_sec = info.st_mtime;
|
|
127
|
+
times[1].tv_usec = 0;
|
|
128
|
+
utimes(dest, times);
|
|
129
|
+
#endif
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
xt_value xt_node_cp(int32_t argc, xt_value *argv) {
|
|
134
|
+
if (argc < 2) return xt_undefined();
|
|
135
|
+
const char *src = xt_node_cstr(argv[0]);
|
|
136
|
+
const char *dest = xt_node_cstr(argv[1]);
|
|
137
|
+
if (!src || !dest) {
|
|
138
|
+
xt_fs_raise_errno(EINVAL, "cp", NULL);
|
|
139
|
+
return xt_undefined();
|
|
140
|
+
}
|
|
141
|
+
xt_value options = argc > 2 ? argv[2] : XT_UNDEFINED;
|
|
142
|
+
int recursive = xt_fs_option_bool(options, "recursive", 0);
|
|
143
|
+
xt_fs_copy_any(src, dest, options, recursive);
|
|
144
|
+
return xt_undefined();
|
|
145
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* `fs.opendirSync` / the `Dir` object for xbintsc.
|
|
3
|
+
*
|
|
4
|
+
* The runtime has no asynchronous thread pool, so `read`/`close` invoke their
|
|
5
|
+
* callbacks immediately (Node would defer them). `readSync`/`closeSync` are the
|
|
6
|
+
* fully synchronous equivalents. `Dir` is a plain object (there is no shared
|
|
7
|
+
* `Dir` prototype yet), so `dir instanceof Dir` is not supported.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
#include "../node_common.h"
|
|
11
|
+
#include "fs_common.h"
|
|
12
|
+
|
|
13
|
+
static xt_fs_dir *xt_fs_dir_handle(xt_value thisValue) {
|
|
14
|
+
xt_value handle = xt_object_get_cstr(thisValue, "__xt_dir");
|
|
15
|
+
return (xt_fs_dir *)(uintptr_t)xt_to_number(handle);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static xt_value xt_fs_dir_read_entry(xt_value thisValue) {
|
|
19
|
+
xt_fs_dir *dir = xt_fs_dir_handle(thisValue);
|
|
20
|
+
if (!dir) return xt_null();
|
|
21
|
+
const char *path = xt_node_cstr(xt_object_get_cstr(thisValue, "path"));
|
|
22
|
+
while (xt_fs_dir_next(dir)) {
|
|
23
|
+
const char *name = xt_fs_dir_name(dir);
|
|
24
|
+
if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) continue;
|
|
25
|
+
return xt_node_dirent_result(path ? path : "", name);
|
|
26
|
+
}
|
|
27
|
+
return xt_null();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static xt_value xt_fs_dir_read_sync(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
31
|
+
(void)env;
|
|
32
|
+
(void)argc;
|
|
33
|
+
(void)argv;
|
|
34
|
+
return xt_fs_dir_read_entry(thisValue);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
static xt_value xt_fs_dir_close_sync(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
38
|
+
(void)env;
|
|
39
|
+
(void)argc;
|
|
40
|
+
(void)argv;
|
|
41
|
+
xt_fs_dir *dir = xt_fs_dir_handle(thisValue);
|
|
42
|
+
if (dir) {
|
|
43
|
+
xt_fs_dir_close(dir);
|
|
44
|
+
free(dir);
|
|
45
|
+
xt_object_set(thisValue, xt_string_from_cstr("__xt_dir"), xt_number(0));
|
|
46
|
+
}
|
|
47
|
+
return xt_undefined();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static xt_value xt_fs_dir_read_async(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
51
|
+
(void)env;
|
|
52
|
+
xt_value callback = xt_arg(argc, argv, 0);
|
|
53
|
+
xt_value dirent = xt_fs_dir_read_entry(thisValue);
|
|
54
|
+
if (XT_IS_FUNCTION(callback)) {
|
|
55
|
+
xt_value args[2];
|
|
56
|
+
args[0] = xt_null();
|
|
57
|
+
args[1] = dirent;
|
|
58
|
+
xt_call_with_this(callback, xt_undefined(), 2, args);
|
|
59
|
+
}
|
|
60
|
+
return xt_undefined();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
static xt_value xt_fs_dir_close_async(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
64
|
+
(void)env;
|
|
65
|
+
xt_value callback = xt_arg(argc, argv, 0);
|
|
66
|
+
xt_fs_dir_close_sync(thisValue, env, 0, NULL);
|
|
67
|
+
if (XT_IS_FUNCTION(callback)) {
|
|
68
|
+
xt_value args[1];
|
|
69
|
+
args[0] = xt_null();
|
|
70
|
+
xt_call_with_this(callback, xt_undefined(), 1, args);
|
|
71
|
+
}
|
|
72
|
+
return xt_undefined();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
xt_value xt_node_opendir(int32_t argc, xt_value *argv) {
|
|
76
|
+
if (argc < 1) return xt_undefined();
|
|
77
|
+
const char *path = xt_node_cstr(argv[0]);
|
|
78
|
+
if (!path) {
|
|
79
|
+
xt_fs_raise_errno(EINVAL, "opendir", NULL);
|
|
80
|
+
return xt_undefined();
|
|
81
|
+
}
|
|
82
|
+
xt_fs_dir *dir = (xt_fs_dir *)malloc(sizeof(xt_fs_dir));
|
|
83
|
+
if (!dir) {
|
|
84
|
+
xt_fs_raise_errno(ENOMEM, "opendir", path);
|
|
85
|
+
return xt_undefined();
|
|
86
|
+
}
|
|
87
|
+
if (!xt_fs_dir_open(dir, path)) {
|
|
88
|
+
free(dir);
|
|
89
|
+
xt_fs_error("open directory", path);
|
|
90
|
+
return xt_undefined();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
xt_value object = xt_object_new();
|
|
94
|
+
xt_node_set(object, "path", xt_string_from_cstr(path));
|
|
95
|
+
xt_node_set(object, "__xt_dir", xt_number((double)(uintptr_t)dir));
|
|
96
|
+
xt_node_define_method(object, "readSync", (void *)xt_fs_dir_read_sync);
|
|
97
|
+
xt_node_define_method(object, "closeSync", (void *)xt_fs_dir_close_sync);
|
|
98
|
+
xt_node_define_method(object, "read", (void *)xt_fs_dir_read_async);
|
|
99
|
+
xt_node_define_method(object, "close", (void *)xt_fs_dir_close_async);
|
|
100
|
+
return object;
|
|
101
|
+
}
|