xbintsc 0.5.20 → 0.5.21
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/AGENTS.md +5 -3
- package/dist/src/driver/compiler.js +1 -1
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/runtime-objects.d.ts +1 -1
- package/dist/src/driver/runtime-objects.js +1 -0
- package/dist/src/driver/runtime-objects.js.map +1 -1
- package/dist/src/driver/version.d.ts +1 -1
- package/dist/src/driver/version.js +1 -1
- package/dist/src/extensions/node/fs/index.d.ts +4 -3
- package/dist/src/extensions/node/fs/index.js +12 -3
- package/dist/src/extensions/node/fs/index.js.map +1 -1
- package/dist/src/extensions/node/fs-promises/index.d.ts +5 -5
- package/dist/src/extensions/node/fs-promises/index.js +15 -6
- package/dist/src/extensions/node/fs-promises/index.js.map +1 -1
- package/dist/tests/e2e/async-await.test.js +1 -1
- package/dist/tests/e2e/async-fs.test.d.ts +9 -0
- package/dist/tests/e2e/async-fs.test.js +119 -0
- package/dist/tests/e2e/async-fs.test.js.map +1 -0
- package/dist/tests/e2e/fetch.test.js +24 -0
- package/dist/tests/e2e/fetch.test.js.map +1 -1
- package/dist/tests/e2e/gui-inline-svg.test.d.ts +11 -0
- package/dist/tests/e2e/gui-inline-svg.test.js +160 -0
- package/dist/tests/e2e/gui-inline-svg.test.js.map +1 -0
- package/doc/ai/contributing.md +2 -1
- package/doc/ai/extensions.md +4 -3
- package/doc/ai/language-support.md +2 -1
- package/doc/ai/zh-CN/contributing.md +1 -1
- package/doc/ai/zh-CN/extensions.md +4 -3
- package/doc/ai/zh-CN/language-support.md +2 -1
- package/doc/gui/api.md +8 -0
- package/doc/gui/known-issues.md +10 -9
- package/doc/gui/media.md +32 -3
- package/doc/gui.md +24 -2
- package/doc/implemented/async.md +16 -3
- package/doc/implemented/fetch.md +38 -6
- package/doc/implemented/node/fs-promises.md +19 -8
- package/doc/implemented/node.md +1 -1
- package/doc/implemented.md +1 -1
- package/doc/unimplemented/deviations.md +1 -1
- package/doc/unimplemented/node/async.md +6 -3
- package/doc/unimplemented/node/fs-promises.md +10 -6
- package/doc/unimplemented/node/fs.md +7 -8
- package/doc/unimplemented/node.md +2 -2
- package/doc/unimplemented/toolchain.md +1 -1
- package/doc/zh-CN/gui/api.md +7 -0
- package/doc/zh-CN/gui/known-issues.md +8 -7
- package/doc/zh-CN/gui/media.md +26 -2
- package/doc/zh-CN/gui.md +18 -1
- package/doc/zh-CN/implemented/async.md +13 -2
- package/doc/zh-CN/implemented/fetch.md +23 -4
- package/doc/zh-CN/implemented/node/fs-promises.md +6 -3
- package/doc/zh-CN/implemented/node.md +1 -1
- package/doc/zh-CN/implemented.md +1 -1
- package/doc/zh-CN/unimplemented/deviations.md +1 -1
- package/doc/zh-CN/unimplemented/node/async.md +6 -3
- package/doc/zh-CN/unimplemented/node/fs-promises.md +4 -4
- package/doc/zh-CN/unimplemented/node/fs.md +2 -2
- package/doc/zh-CN/unimplemented/node.md +2 -2
- package/doc/zh-CN/unimplemented/toolchain.md +1 -1
- package/package.json +1 -1
- package/runtime/ext_gui/inline_svg.cpp +219 -0
- package/runtime/ext_gui/inline_svg.h +41 -0
- package/runtime/ext_gui/layout.cpp +18 -0
- package/runtime/ext_gui/layout.h +7 -0
- package/runtime/ext_gui/layout_flow.cpp +4 -3
- package/runtime/ext_gui/paint.cpp +14 -0
- package/runtime/ext_gui/paint.h +5 -1
- package/runtime/ext_gui/renderer_image.cpp +53 -25
- package/runtime/ext_gui/style_ua.cpp +3 -0
- package/runtime/ext_gui/svg.cpp +122 -39
- package/runtime/ext_gui/svg.h +14 -3
- package/runtime/ext_gui/window.cpp +28 -0
- package/runtime/ext_node/fs/async_api.c +314 -0
- package/runtime/ext_node/fs/async_complete.c +99 -0
- package/runtime/ext_node/fs/async_fh.c +206 -0
- package/runtime/ext_node/fs/async_job.c +81 -0
- package/runtime/ext_node/fs/async_job.h +132 -0
- package/runtime/ext_node/fs/async_worker.c +534 -0
- package/runtime/ext_node/fs/async_worker_dir.c +439 -0
- package/runtime/ext_node/fs/async_worker_dir.h +33 -0
- package/runtime/ext_node/fs/async_worker_fd.c +74 -0
- package/runtime/ext_node/fs/dir.c +60 -15
- package/runtime/ext_node/fs/fs_common.h +9 -0
- package/runtime/ext_node/fs/fs_ops.c +18 -29
- package/runtime/ext_node/fs/parts/builtins.inc +34 -0
- package/runtime/ext_node/fs/parts/platform.inc +66 -0
- package/runtime/ext_node/fs/promises.c +44 -234
- package/runtime/rt_internal.h +2 -0
- package/runtime/xt_async_io.c +333 -0
- package/runtime/xt_async_io.h +47 -0
- package/runtime/xt_fetch/async.inc +295 -0
- package/runtime/xt_fetch/request.inc +6 -183
- package/runtime/xt_fetch/socket.inc +5 -4
- package/runtime/xt_fetch.c +6 -4
- package/runtime/xt_loop.c +44 -3
- package/src/driver/compiler.ts +1 -1
- package/src/driver/runtime-objects.ts +1 -0
- package/src/driver/version.ts +1 -1
- package/src/extensions/node/fs/index.ts +12 -3
- package/src/extensions/node/fs-promises/index.ts +15 -6
|
@@ -33,6 +33,22 @@ xt_value xt_node_exists(int32_t argc, xt_value *argv) {
|
|
|
33
33
|
`readdirSync(path, { withFileTypes: true })` reuse the same closures. */
|
|
34
34
|
static void xt_fs_define_stat_method(xt_value object, const char *name, unsigned int mode);
|
|
35
35
|
|
|
36
|
+
/* Build the Node `Dirent`-shaped object from an already-known mode. The async
|
|
37
|
+
promise layer collects the mode on its worker so it does not have to `stat`
|
|
38
|
+
the entry again on the main thread. */
|
|
39
|
+
xt_value xt_node_dirent_named(const char *name, unsigned int mode) {
|
|
40
|
+
xt_value object = xt_object_new();
|
|
41
|
+
xt_object_set(object, xt_string_from_cstr("name"), xt_string_from_cstr(name));
|
|
42
|
+
xt_fs_define_stat_method(object, "isFile", mode);
|
|
43
|
+
xt_fs_define_stat_method(object, "isDirectory", mode);
|
|
44
|
+
xt_fs_define_stat_method(object, "isSymbolicLink", mode);
|
|
45
|
+
xt_fs_define_stat_method(object, "isFIFO", mode);
|
|
46
|
+
xt_fs_define_stat_method(object, "isSocket", mode);
|
|
47
|
+
xt_fs_define_stat_method(object, "isBlockDevice", mode);
|
|
48
|
+
xt_fs_define_stat_method(object, "isCharacterDevice", mode);
|
|
49
|
+
return object;
|
|
50
|
+
}
|
|
51
|
+
|
|
36
52
|
/* Build the Node `Dirent`-shaped object (`name` plus stat predicates) for a
|
|
37
53
|
single directory entry. Types come from `lstat`, matching Node's `d_type`
|
|
38
54
|
based `Dirent` (a symlink reports `isSymbolicLink()` true). */
|
|
@@ -46,17 +62,7 @@ xt_value xt_node_dirent_result(const char *dir, const char *name) {
|
|
|
46
62
|
if (xt_fs_lstat_fn(full, &info) == 0) mode = (unsigned int)info.st_mode;
|
|
47
63
|
free(full);
|
|
48
64
|
}
|
|
49
|
-
|
|
50
|
-
xt_value object = xt_object_new();
|
|
51
|
-
xt_object_set(object, xt_string_from_cstr("name"), xt_string_from_cstr(name));
|
|
52
|
-
xt_fs_define_stat_method(object, "isFile", mode);
|
|
53
|
-
xt_fs_define_stat_method(object, "isDirectory", mode);
|
|
54
|
-
xt_fs_define_stat_method(object, "isSymbolicLink", mode);
|
|
55
|
-
xt_fs_define_stat_method(object, "isFIFO", mode);
|
|
56
|
-
xt_fs_define_stat_method(object, "isSocket", mode);
|
|
57
|
-
xt_fs_define_stat_method(object, "isBlockDevice", mode);
|
|
58
|
-
xt_fs_define_stat_method(object, "isCharacterDevice", mode);
|
|
59
|
-
return object;
|
|
65
|
+
return xt_node_dirent_named(name, mode);
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
/* Entries accumulate in an `xt_array`, not a raw `xt_value` buffer: the
|
|
@@ -149,24 +155,7 @@ static int xt_fs_recursive(xt_value options) {
|
|
|
149
155
|
}
|
|
150
156
|
|
|
151
157
|
static int xt_fs_mkdir_recursive(const char *path, int mode) {
|
|
152
|
-
|
|
153
|
-
char *copy = (char *)malloc(length + 1);
|
|
154
|
-
if (!copy) return -1;
|
|
155
|
-
memcpy(copy, path, length + 1);
|
|
156
|
-
|
|
157
|
-
while (length > 1 && copy[length - 1] == '/') copy[--length] = '\0';
|
|
158
|
-
for (size_t i = 1; i <= length; i++) {
|
|
159
|
-
if (copy[i] != '/' && copy[i] != '\0') continue;
|
|
160
|
-
char saved = copy[i];
|
|
161
|
-
copy[i] = '\0';
|
|
162
|
-
if (xt_fs_mkdir_mode(copy, mode) != 0 && errno != EEXIST) {
|
|
163
|
-
free(copy);
|
|
164
|
-
return -1;
|
|
165
|
-
}
|
|
166
|
-
copy[i] = saved;
|
|
167
|
-
}
|
|
168
|
-
free(copy);
|
|
169
|
-
return 0;
|
|
158
|
+
return xt_fs_mkdir_parents(path, mode);
|
|
170
159
|
}
|
|
171
160
|
|
|
172
161
|
xt_value xt_node_mkdir(int32_t argc, xt_value *argv) {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
xt_value xt_node_stat_result(const xt_fs_stat_t *info);
|
|
4
4
|
xt_value xt_node_dirent_result(const char *dir, const char *name);
|
|
5
|
+
xt_value xt_node_dirent_named(const char *name, unsigned int mode);
|
|
5
6
|
|
|
6
7
|
/* -- synchronous fs builtins (one translation unit per group) ------------- */
|
|
7
8
|
|
|
@@ -64,6 +65,39 @@ xt_value xt_node_watch(int32_t argc, xt_value *argv);
|
|
|
64
65
|
xt_value xt_node_watch_file(int32_t argc, xt_value *argv);
|
|
65
66
|
xt_value xt_node_unwatch_file(int32_t argc, xt_value *argv);
|
|
66
67
|
|
|
68
|
+
/* async_api.c — promise-returning counterparts, backed by the async I/O pool */
|
|
69
|
+
xt_value xt_node_p_read_file(int32_t argc, xt_value *argv);
|
|
70
|
+
xt_value xt_node_p_write_file(int32_t argc, xt_value *argv);
|
|
71
|
+
xt_value xt_node_p_append_file(int32_t argc, xt_value *argv);
|
|
72
|
+
xt_value xt_node_p_mkdir(int32_t argc, xt_value *argv);
|
|
73
|
+
xt_value xt_node_p_readdir(int32_t argc, xt_value *argv);
|
|
74
|
+
xt_value xt_node_p_rm(int32_t argc, xt_value *argv);
|
|
75
|
+
xt_value xt_node_p_unlink(int32_t argc, xt_value *argv);
|
|
76
|
+
xt_value xt_node_p_rmdir(int32_t argc, xt_value *argv);
|
|
77
|
+
xt_value xt_node_p_rename(int32_t argc, xt_value *argv);
|
|
78
|
+
xt_value xt_node_p_copy_file(int32_t argc, xt_value *argv);
|
|
79
|
+
xt_value xt_node_p_cp(int32_t argc, xt_value *argv);
|
|
80
|
+
xt_value xt_node_p_realpath(int32_t argc, xt_value *argv);
|
|
81
|
+
xt_value xt_node_p_stat(int32_t argc, xt_value *argv);
|
|
82
|
+
xt_value xt_node_p_lstat(int32_t argc, xt_value *argv);
|
|
83
|
+
xt_value xt_node_p_statfs(int32_t argc, xt_value *argv);
|
|
84
|
+
xt_value xt_node_p_access(int32_t argc, xt_value *argv);
|
|
85
|
+
xt_value xt_node_p_open(int32_t argc, xt_value *argv);
|
|
86
|
+
xt_value xt_node_p_chmod(int32_t argc, xt_value *argv);
|
|
87
|
+
xt_value xt_node_p_lchmod(int32_t argc, xt_value *argv);
|
|
88
|
+
xt_value xt_node_p_chown(int32_t argc, xt_value *argv);
|
|
89
|
+
xt_value xt_node_p_lchown(int32_t argc, xt_value *argv);
|
|
90
|
+
xt_value xt_node_p_truncate(int32_t argc, xt_value *argv);
|
|
91
|
+
xt_value xt_node_p_utimes(int32_t argc, xt_value *argv);
|
|
92
|
+
xt_value xt_node_p_lutimes(int32_t argc, xt_value *argv);
|
|
93
|
+
xt_value xt_node_p_link(int32_t argc, xt_value *argv);
|
|
94
|
+
xt_value xt_node_p_symlink(int32_t argc, xt_value *argv);
|
|
95
|
+
xt_value xt_node_p_readlink(int32_t argc, xt_value *argv);
|
|
96
|
+
xt_value xt_node_p_mkdtemp(int32_t argc, xt_value *argv);
|
|
97
|
+
xt_value xt_node_p_opendir(int32_t argc, xt_value *argv);
|
|
98
|
+
xt_value xt_node_p_glob(int32_t argc, xt_value *argv);
|
|
99
|
+
xt_value xt_node_p_watch(int32_t argc, xt_value *argv);
|
|
100
|
+
|
|
67
101
|
/* constants.c */
|
|
68
102
|
xt_value xt_fs_constants(void);
|
|
69
103
|
xt_value xt_fs_promises(void);
|
|
@@ -84,3 +84,69 @@ typedef struct stat xt_fs_stat_t;
|
|
|
84
84
|
#define XT_FS_READ read
|
|
85
85
|
#define XT_FS_WRITE write
|
|
86
86
|
#endif
|
|
87
|
+
|
|
88
|
+
/* -- recursive directory creation ----------------------------------------- */
|
|
89
|
+
/* `mkdir -p` splits a path at its separators and creates every prefix. A
|
|
90
|
+
* Windows volume prefix must be skipped: `_mkdir("C:")` is not "the C: root" but
|
|
91
|
+
* a drive-relative path that resolves against that drive's current directory,
|
|
92
|
+
* so it fails with EACCES. Creating the prefixes of `C:\...` (e.g. anything
|
|
93
|
+
* under %TEMP%) used to abort on that first component while paths on the
|
|
94
|
+
* process's current drive appeared to work. */
|
|
95
|
+
|
|
96
|
+
static inline int xt_fs_is_sep(char c) {
|
|
97
|
+
#if defined(_WIN32)
|
|
98
|
+
return c == '/' || c == '\\';
|
|
99
|
+
#else
|
|
100
|
+
return c == '/';
|
|
101
|
+
#endif
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Byte index of the first directory component that may be created: 0 for a
|
|
105
|
+
* relative or POSIX path, past `C:` / `\\server\share` on Windows. */
|
|
106
|
+
static inline size_t xt_fs_path_root(const char *path) {
|
|
107
|
+
#if defined(_WIN32)
|
|
108
|
+
if ((path[0] == '\\' || path[0] == '/') && (path[1] == '\\' || path[1] == '/')) {
|
|
109
|
+
size_t i = 2;
|
|
110
|
+
for (int separators = 0; separators < 2 && path[i]; ) {
|
|
111
|
+
if (xt_fs_is_sep(path[i])) separators++;
|
|
112
|
+
i++;
|
|
113
|
+
}
|
|
114
|
+
return i;
|
|
115
|
+
}
|
|
116
|
+
if (path[0] != '\0' && path[1] == ':') {
|
|
117
|
+
size_t i = 2;
|
|
118
|
+
while (xt_fs_is_sep(path[i])) i++;
|
|
119
|
+
return i;
|
|
120
|
+
}
|
|
121
|
+
#endif
|
|
122
|
+
return 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/* Create `path` and every missing ancestor, tolerating existing directories.
|
|
126
|
+
* Returns 0 or -1 with `errno` set by the failed `mkdir`. */
|
|
127
|
+
static inline int xt_fs_mkdir_parents(const char *path, int mode) {
|
|
128
|
+
size_t length = strlen(path);
|
|
129
|
+
char *copy = (char *)malloc(length + 1);
|
|
130
|
+
if (!copy) return -1;
|
|
131
|
+
memcpy(copy, path, length + 1);
|
|
132
|
+
while (length > 1 && xt_fs_is_sep(copy[length - 1])) copy[--length] = '\0';
|
|
133
|
+
|
|
134
|
+
int status = 0;
|
|
135
|
+
size_t start = xt_fs_path_root(copy);
|
|
136
|
+
if (start < length) {
|
|
137
|
+
/* A driver prefix is already consumed; otherwise index 0 is a separator
|
|
138
|
+
* for absolute paths and the first byte for relative ones. */
|
|
139
|
+
for (size_t i = start > 0 ? start : 1; i <= length; i++) {
|
|
140
|
+
if (!xt_fs_is_sep(copy[i]) && copy[i] != '\0') continue;
|
|
141
|
+
char saved = copy[i];
|
|
142
|
+
copy[i] = '\0';
|
|
143
|
+
if (xt_fs_mkdir_mode(copy, mode) != 0 && errno != EEXIST) {
|
|
144
|
+
status = -1;
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
copy[i] = saved;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
free(copy);
|
|
151
|
+
return status;
|
|
152
|
+
}
|
|
@@ -1,244 +1,54 @@
|
|
|
1
1
|
/*
|
|
2
|
-
*
|
|
2
|
+
* `fs.promises` facade for xbintsc.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* `open()` resolves to a `FileHandle`-shaped object (a plain object with an
|
|
11
|
-
* `fd` property and the usual methods); there is no shared prototype yet, so
|
|
12
|
-
* `handle instanceof FileHandle` is not supported.
|
|
4
|
+
* The individual exports are implemented in async_api.c on top of the async I/O
|
|
5
|
+
* pool: their promises settle when a worker finishes, so awaiting them yields
|
|
6
|
+
* to timers, sockets and other suspending work. This file only builds the
|
|
7
|
+
* `fs.promises` namespace object (reachable as `fs.promises` and as the imported
|
|
8
|
+
* `fs/promises` module).
|
|
13
9
|
*/
|
|
14
10
|
|
|
15
|
-
#include "
|
|
16
|
-
#include "fs_common.h"
|
|
17
|
-
|
|
18
|
-
/* ------------------------------------------------------------------------- */
|
|
19
|
-
/* FileHandle */
|
|
20
|
-
/* ------------------------------------------------------------------------- */
|
|
21
|
-
|
|
22
|
-
static xt_value xt_fh_method(xt_value thisValue, xt_value (*fn)(int32_t, xt_value *), int32_t argc, xt_value *argv,
|
|
23
|
-
int prefix) {
|
|
24
|
-
xt_value args[10];
|
|
25
|
-
int32_t count = 0;
|
|
26
|
-
if (prefix >= 1) args[count++] = xt_object_get_cstr(thisValue, "fd");
|
|
27
|
-
if (prefix >= 2) args[count++] = xt_object_get_cstr(thisValue, "fd2");
|
|
28
|
-
for (int32_t i = 0; i < argc && count < 10; i++) args[count++] = argv[i];
|
|
29
|
-
return xt_fs_promisify(fn, count, args);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
static xt_value xt_fh_read(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
33
|
-
(void)env;
|
|
34
|
-
return xt_fh_method(thisValue, xt_node_read, argc, argv, 1);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
static xt_value xt_fh_write(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
38
|
-
(void)env;
|
|
39
|
-
return xt_fh_method(thisValue, xt_node_write, argc, argv, 1);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
static xt_value xt_fh_close(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
43
|
-
(void)env;
|
|
44
|
-
return xt_fh_method(thisValue, xt_node_close, argc, argv, 1);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
static xt_value xt_fh_stat(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
48
|
-
(void)env;
|
|
49
|
-
return xt_fh_method(thisValue, xt_node_fstat, argc, argv, 1);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
static xt_value xt_fh_truncate(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
53
|
-
(void)env;
|
|
54
|
-
return xt_fh_method(thisValue, xt_node_ftruncate, argc, argv, 1);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
static xt_value xt_fh_chmod(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
58
|
-
(void)env;
|
|
59
|
-
return xt_fh_method(thisValue, xt_node_fchmod, argc, argv, 1);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
static xt_value xt_fh_chown(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
63
|
-
(void)env;
|
|
64
|
-
return xt_fh_method(thisValue, xt_node_fchown, argc, argv, 1);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
static xt_value xt_fh_utimes(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
68
|
-
(void)env;
|
|
69
|
-
return xt_fh_method(thisValue, xt_node_futimes, argc, argv, 1);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
static xt_value xt_fh_sync(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
73
|
-
(void)env;
|
|
74
|
-
return xt_fh_method(thisValue, xt_node_fsync, argc, argv, 1);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
static xt_value xt_fh_datasync(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
78
|
-
(void)env;
|
|
79
|
-
return xt_fh_method(thisValue, xt_node_fdatasync, argc, argv, 1);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/* Read from the handle's current position to EOF; caller frees. */
|
|
83
|
-
static unsigned char *xt_fh_slurp(int fd, size_t *outLength) {
|
|
84
|
-
size_t capacity = 8192;
|
|
85
|
-
size_t length = 0;
|
|
86
|
-
unsigned char *bytes = (unsigned char *)malloc(capacity);
|
|
87
|
-
if (!bytes) return NULL;
|
|
88
|
-
for (;;) {
|
|
89
|
-
if (length == capacity) {
|
|
90
|
-
capacity *= 2;
|
|
91
|
-
unsigned char *grown = (unsigned char *)realloc(bytes, capacity);
|
|
92
|
-
if (!grown) {
|
|
93
|
-
free(bytes);
|
|
94
|
-
return NULL;
|
|
95
|
-
}
|
|
96
|
-
bytes = grown;
|
|
97
|
-
}
|
|
98
|
-
ssize_t bytesRead = XT_FS_READ(fd, bytes + length, capacity - length);
|
|
99
|
-
if (bytesRead < 0) {
|
|
100
|
-
free(bytes);
|
|
101
|
-
return NULL;
|
|
102
|
-
}
|
|
103
|
-
if (bytesRead == 0) break;
|
|
104
|
-
length += (size_t)bytesRead;
|
|
105
|
-
}
|
|
106
|
-
*outLength = length;
|
|
107
|
-
return bytes;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
static xt_value xt_fh_read_all(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
111
|
-
(void)env;
|
|
112
|
-
int fd = (int)xt_to_number(xt_object_get_cstr(thisValue, "fd"));
|
|
113
|
-
const char *encoding = argc > 0 ? xt_fs_encoding(argv[0]) : NULL;
|
|
114
|
-
size_t length = 0;
|
|
115
|
-
unsigned char *bytes = xt_fh_slurp(fd, &length);
|
|
116
|
-
if (!bytes) return xt_promise_reject(xt_fs_error_object(errno, "read", NULL));
|
|
117
|
-
xt_value result = xt_fs_encode_bytes(bytes, length, encoding);
|
|
118
|
-
free(bytes);
|
|
119
|
-
return xt_promise_resolve(result);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
static xt_value xt_fh_write_all(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv) {
|
|
123
|
-
(void)env;
|
|
124
|
-
xt_value args[2];
|
|
125
|
-
args[0] = xt_object_get_cstr(thisValue, "fd");
|
|
126
|
-
args[1] = argc > 0 ? argv[0] : XT_UNDEFINED;
|
|
127
|
-
return xt_fs_promisify(xt_node_write, 2, args);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
static xt_value xt_fh_new(xt_value fdValue) {
|
|
131
|
-
xt_value handle = xt_object_new();
|
|
132
|
-
xt_node_set(handle, "fd", fdValue);
|
|
133
|
-
xt_node_define_method(handle, "read", (void *)xt_fh_read);
|
|
134
|
-
xt_node_define_method(handle, "write", (void *)xt_fh_write);
|
|
135
|
-
xt_node_define_method(handle, "readFile", (void *)xt_fh_read_all);
|
|
136
|
-
xt_node_define_method(handle, "writeFile", (void *)xt_fh_write_all);
|
|
137
|
-
xt_node_define_method(handle, "appendFile", (void *)xt_fh_write_all);
|
|
138
|
-
xt_node_define_method(handle, "close", (void *)xt_fh_close);
|
|
139
|
-
xt_node_define_method(handle, "stat", (void *)xt_fh_stat);
|
|
140
|
-
xt_node_define_method(handle, "truncate", (void *)xt_fh_truncate);
|
|
141
|
-
xt_node_define_method(handle, "chmod", (void *)xt_fh_chmod);
|
|
142
|
-
xt_node_define_method(handle, "chown", (void *)xt_fh_chown);
|
|
143
|
-
xt_node_define_method(handle, "utimes", (void *)xt_fh_utimes);
|
|
144
|
-
xt_node_define_method(handle, "sync", (void *)xt_fh_sync);
|
|
145
|
-
xt_node_define_method(handle, "datasync", (void *)xt_fh_datasync);
|
|
146
|
-
return handle;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/* ------------------------------------------------------------------------- */
|
|
150
|
-
/* Promise wrappers */
|
|
151
|
-
/* ------------------------------------------------------------------------- */
|
|
152
|
-
|
|
153
|
-
#define XT_FS_PROMISE(name, fn) \
|
|
154
|
-
xt_value name(int32_t argc, xt_value *argv) { return xt_fs_promisify((fn), argc, argv); }
|
|
155
|
-
|
|
156
|
-
XT_FS_PROMISE(xt_node_p_read_file, xt_node_read_text_file)
|
|
157
|
-
XT_FS_PROMISE(xt_node_p_write_file, xt_node_write_file)
|
|
158
|
-
XT_FS_PROMISE(xt_node_p_append_file, xt_node_append_file)
|
|
159
|
-
XT_FS_PROMISE(xt_node_p_mkdir, xt_node_mkdir)
|
|
160
|
-
XT_FS_PROMISE(xt_node_p_readdir, xt_node_read_dir)
|
|
161
|
-
XT_FS_PROMISE(xt_node_p_rm, xt_node_rm)
|
|
162
|
-
XT_FS_PROMISE(xt_node_p_unlink, xt_node_unlink)
|
|
163
|
-
XT_FS_PROMISE(xt_node_p_rmdir, xt_node_rmdir)
|
|
164
|
-
XT_FS_PROMISE(xt_node_p_rename, xt_node_rename)
|
|
165
|
-
XT_FS_PROMISE(xt_node_p_copy_file, xt_node_copy_file)
|
|
166
|
-
XT_FS_PROMISE(xt_node_p_realpath, xt_node_realpath)
|
|
167
|
-
XT_FS_PROMISE(xt_node_p_stat, xt_node_stat)
|
|
168
|
-
XT_FS_PROMISE(xt_node_p_lstat, xt_node_lstat)
|
|
169
|
-
XT_FS_PROMISE(xt_node_p_access, xt_node_access)
|
|
170
|
-
XT_FS_PROMISE(xt_node_p_cp, xt_node_cp)
|
|
171
|
-
XT_FS_PROMISE(xt_node_p_chmod, xt_node_chmod)
|
|
172
|
-
XT_FS_PROMISE(xt_node_p_chown, xt_node_chown)
|
|
173
|
-
XT_FS_PROMISE(xt_node_p_lchmod, xt_node_lchmod)
|
|
174
|
-
XT_FS_PROMISE(xt_node_p_lchown, xt_node_lchown)
|
|
175
|
-
XT_FS_PROMISE(xt_node_p_truncate, xt_node_truncate)
|
|
176
|
-
XT_FS_PROMISE(xt_node_p_utimes, xt_node_utimes)
|
|
177
|
-
XT_FS_PROMISE(xt_node_p_lutimes, xt_node_lutimes)
|
|
178
|
-
XT_FS_PROMISE(xt_node_p_link, xt_node_link)
|
|
179
|
-
XT_FS_PROMISE(xt_node_p_symlink, xt_node_symlink)
|
|
180
|
-
XT_FS_PROMISE(xt_node_p_readlink, xt_node_readlink)
|
|
181
|
-
XT_FS_PROMISE(xt_node_p_mkdtemp, xt_node_mkdtemp)
|
|
182
|
-
XT_FS_PROMISE(xt_node_p_statfs, xt_node_statfs)
|
|
183
|
-
XT_FS_PROMISE(xt_node_p_opendir, xt_node_opendir)
|
|
184
|
-
XT_FS_PROMISE(xt_node_p_glob, xt_node_glob)
|
|
185
|
-
XT_FS_PROMISE(xt_node_p_watch, xt_node_watch)
|
|
186
|
-
|
|
187
|
-
xt_value xt_node_p_open(int32_t argc, xt_value *argv) {
|
|
188
|
-
void *frame = xt_try_enter();
|
|
189
|
-
if (xt_try_setjmp(frame) == 0) {
|
|
190
|
-
xt_value fdValue = xt_node_open(argc, argv);
|
|
191
|
-
xt_try_leave(frame);
|
|
192
|
-
return xt_promise_resolve(xt_fh_new(fdValue));
|
|
193
|
-
}
|
|
194
|
-
xt_value exception = xt_try_exception(frame);
|
|
195
|
-
xt_try_leave(frame);
|
|
196
|
-
return xt_promise_reject(exception);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/* ------------------------------------------------------------------------- */
|
|
200
|
-
/* `fs.promises` facade */
|
|
201
|
-
/* ------------------------------------------------------------------------- */
|
|
11
|
+
#include "async_job.h"
|
|
202
12
|
|
|
203
|
-
#define XT_FS_PROMISES_FACADE(name
|
|
204
|
-
static xt_value xt_fs_promises_facade_##name(xt_value thisValue, xt_value env, int32_t argc,
|
|
205
|
-
xt_value *argv) {
|
|
206
|
-
(void)thisValue;
|
|
207
|
-
(void)env;
|
|
208
|
-
return name(argc, argv);
|
|
13
|
+
#define XT_FS_PROMISES_FACADE(name) \
|
|
14
|
+
static xt_value xt_fs_promises_facade_##name(xt_value thisValue, xt_value env, int32_t argc, \
|
|
15
|
+
xt_value *argv) { \
|
|
16
|
+
(void)thisValue; \
|
|
17
|
+
(void)env; \
|
|
18
|
+
return name(argc, argv); \
|
|
209
19
|
}
|
|
210
20
|
|
|
211
|
-
XT_FS_PROMISES_FACADE(xt_node_p_read_file
|
|
212
|
-
XT_FS_PROMISES_FACADE(xt_node_p_write_file
|
|
213
|
-
XT_FS_PROMISES_FACADE(xt_node_p_append_file
|
|
214
|
-
XT_FS_PROMISES_FACADE(xt_node_p_mkdir
|
|
215
|
-
XT_FS_PROMISES_FACADE(xt_node_p_readdir
|
|
216
|
-
XT_FS_PROMISES_FACADE(xt_node_p_rm
|
|
217
|
-
XT_FS_PROMISES_FACADE(xt_node_p_unlink
|
|
218
|
-
XT_FS_PROMISES_FACADE(xt_node_p_rmdir
|
|
219
|
-
XT_FS_PROMISES_FACADE(xt_node_p_rename
|
|
220
|
-
XT_FS_PROMISES_FACADE(xt_node_p_copy_file
|
|
221
|
-
XT_FS_PROMISES_FACADE(xt_node_p_realpath
|
|
222
|
-
XT_FS_PROMISES_FACADE(xt_node_p_stat
|
|
223
|
-
XT_FS_PROMISES_FACADE(xt_node_p_lstat
|
|
224
|
-
XT_FS_PROMISES_FACADE(xt_node_p_access
|
|
225
|
-
XT_FS_PROMISES_FACADE(xt_node_p_cp
|
|
226
|
-
XT_FS_PROMISES_FACADE(xt_node_p_chmod
|
|
227
|
-
XT_FS_PROMISES_FACADE(xt_node_p_chown
|
|
228
|
-
XT_FS_PROMISES_FACADE(xt_node_p_lchmod
|
|
229
|
-
XT_FS_PROMISES_FACADE(xt_node_p_lchown
|
|
230
|
-
XT_FS_PROMISES_FACADE(xt_node_p_truncate
|
|
231
|
-
XT_FS_PROMISES_FACADE(xt_node_p_utimes
|
|
232
|
-
XT_FS_PROMISES_FACADE(xt_node_p_lutimes
|
|
233
|
-
XT_FS_PROMISES_FACADE(xt_node_p_link
|
|
234
|
-
XT_FS_PROMISES_FACADE(xt_node_p_symlink
|
|
235
|
-
XT_FS_PROMISES_FACADE(xt_node_p_readlink
|
|
236
|
-
XT_FS_PROMISES_FACADE(xt_node_p_mkdtemp
|
|
237
|
-
XT_FS_PROMISES_FACADE(xt_node_p_statfs
|
|
238
|
-
XT_FS_PROMISES_FACADE(xt_node_p_opendir
|
|
239
|
-
XT_FS_PROMISES_FACADE(xt_node_p_glob
|
|
240
|
-
XT_FS_PROMISES_FACADE(xt_node_p_watch
|
|
241
|
-
XT_FS_PROMISES_FACADE(xt_node_p_open
|
|
21
|
+
XT_FS_PROMISES_FACADE(xt_node_p_read_file)
|
|
22
|
+
XT_FS_PROMISES_FACADE(xt_node_p_write_file)
|
|
23
|
+
XT_FS_PROMISES_FACADE(xt_node_p_append_file)
|
|
24
|
+
XT_FS_PROMISES_FACADE(xt_node_p_mkdir)
|
|
25
|
+
XT_FS_PROMISES_FACADE(xt_node_p_readdir)
|
|
26
|
+
XT_FS_PROMISES_FACADE(xt_node_p_rm)
|
|
27
|
+
XT_FS_PROMISES_FACADE(xt_node_p_unlink)
|
|
28
|
+
XT_FS_PROMISES_FACADE(xt_node_p_rmdir)
|
|
29
|
+
XT_FS_PROMISES_FACADE(xt_node_p_rename)
|
|
30
|
+
XT_FS_PROMISES_FACADE(xt_node_p_copy_file)
|
|
31
|
+
XT_FS_PROMISES_FACADE(xt_node_p_realpath)
|
|
32
|
+
XT_FS_PROMISES_FACADE(xt_node_p_stat)
|
|
33
|
+
XT_FS_PROMISES_FACADE(xt_node_p_lstat)
|
|
34
|
+
XT_FS_PROMISES_FACADE(xt_node_p_access)
|
|
35
|
+
XT_FS_PROMISES_FACADE(xt_node_p_cp)
|
|
36
|
+
XT_FS_PROMISES_FACADE(xt_node_p_chmod)
|
|
37
|
+
XT_FS_PROMISES_FACADE(xt_node_p_chown)
|
|
38
|
+
XT_FS_PROMISES_FACADE(xt_node_p_lchmod)
|
|
39
|
+
XT_FS_PROMISES_FACADE(xt_node_p_lchown)
|
|
40
|
+
XT_FS_PROMISES_FACADE(xt_node_p_truncate)
|
|
41
|
+
XT_FS_PROMISES_FACADE(xt_node_p_utimes)
|
|
42
|
+
XT_FS_PROMISES_FACADE(xt_node_p_lutimes)
|
|
43
|
+
XT_FS_PROMISES_FACADE(xt_node_p_link)
|
|
44
|
+
XT_FS_PROMISES_FACADE(xt_node_p_symlink)
|
|
45
|
+
XT_FS_PROMISES_FACADE(xt_node_p_readlink)
|
|
46
|
+
XT_FS_PROMISES_FACADE(xt_node_p_mkdtemp)
|
|
47
|
+
XT_FS_PROMISES_FACADE(xt_node_p_statfs)
|
|
48
|
+
XT_FS_PROMISES_FACADE(xt_node_p_opendir)
|
|
49
|
+
XT_FS_PROMISES_FACADE(xt_node_p_glob)
|
|
50
|
+
XT_FS_PROMISES_FACADE(xt_node_p_watch)
|
|
51
|
+
XT_FS_PROMISES_FACADE(xt_node_p_open)
|
|
242
52
|
|
|
243
53
|
xt_value xt_fs_promises(void) {
|
|
244
54
|
static xt_value cached = 0;
|
package/runtime/rt_internal.h
CHANGED
|
@@ -589,4 +589,6 @@ uint8_t xt_array_buffer_get_byte(xt_value buffer, uint32_t index);
|
|
|
589
589
|
void xt_array_buffer_set_byte(xt_value buffer, uint32_t index, uint8_t value);
|
|
590
590
|
xt_value xt_array_buffer_ctor(int32_t argc, xt_value *argv);
|
|
591
591
|
|
|
592
|
+
#include "xt_async_io.h"
|
|
593
|
+
|
|
592
594
|
#endif /* XT_RT_INTERNAL_H */
|