xbintsc 0.3.35 → 0.3.49

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.
Files changed (130) hide show
  1. package/AGENTS.md +95 -0
  2. package/README.md +31 -3
  3. package/README.zh-CN.md +23 -0
  4. package/dist/src/cli/hints.d.ts +54 -0
  5. package/dist/src/cli/hints.js +165 -0
  6. package/dist/src/cli/hints.js.map +1 -0
  7. package/dist/src/cli/main.js +73 -9
  8. package/dist/src/cli/main.js.map +1 -1
  9. package/dist/src/codegen/generator/module.js +10 -0
  10. package/dist/src/codegen/generator/module.js.map +1 -1
  11. package/dist/src/codegen/generator/state.js +4 -0
  12. package/dist/src/codegen/generator/state.js.map +1 -1
  13. package/dist/src/codegen/generator/tables.d.ts +26 -0
  14. package/dist/src/codegen/generator/tables.js +64 -12
  15. package/dist/src/codegen/generator/tables.js.map +1 -1
  16. package/dist/src/diagnostics/source-text.d.ts +22 -0
  17. package/dist/src/diagnostics/source-text.js +76 -0
  18. package/dist/src/diagnostics/source-text.js.map +1 -0
  19. package/dist/src/driver/bundler/graph.js +2 -1
  20. package/dist/src/driver/bundler/graph.js.map +1 -1
  21. package/dist/src/driver/compiler.js +3 -2
  22. package/dist/src/driver/compiler.js.map +1 -1
  23. package/dist/src/lexer/scanner/strings.js +16 -3
  24. package/dist/src/lexer/scanner/strings.js.map +1 -1
  25. package/dist/tests/cli/hints.test.d.ts +9 -0
  26. package/dist/tests/cli/hints.test.js +143 -0
  27. package/dist/tests/cli/hints.test.js.map +1 -0
  28. package/dist/tests/cli/main.test.js +6 -4
  29. package/dist/tests/cli/main.test.js.map +1 -1
  30. package/dist/tests/codegen/llvm.test.js +17 -2
  31. package/dist/tests/codegen/llvm.test.js.map +1 -1
  32. package/dist/tests/e2e/gc.test.d.ts +1 -0
  33. package/dist/tests/e2e/gc.test.js +168 -0
  34. package/dist/tests/e2e/gc.test.js.map +1 -0
  35. package/dist/tests/e2e/harness.d.ts +2 -0
  36. package/dist/tests/e2e/harness.js +1 -0
  37. package/dist/tests/e2e/harness.js.map +1 -1
  38. package/dist/tests/helpers.js +3 -2
  39. package/dist/tests/helpers.js.map +1 -1
  40. package/dist/tests/lexer/strings.test.js +14 -2
  41. package/dist/tests/lexer/strings.test.js.map +1 -1
  42. package/doc/DESIGN.md +117 -0
  43. package/doc/ai/README.md +63 -0
  44. package/doc/ai/build-recipe.md +137 -0
  45. package/doc/ai/cli.md +142 -0
  46. package/doc/ai/contributing.md +196 -0
  47. package/doc/ai/extensions.md +148 -0
  48. package/doc/ai/language-support.md +152 -0
  49. package/doc/ai/troubleshooting.md +163 -0
  50. package/doc/ai/zh-CN/README.md +56 -0
  51. package/doc/ai/zh-CN/build-recipe.md +132 -0
  52. package/doc/ai/zh-CN/cli.md +127 -0
  53. package/doc/ai/zh-CN/contributing.md +173 -0
  54. package/doc/ai/zh-CN/extensions.md +139 -0
  55. package/doc/ai/zh-CN/language-support.md +147 -0
  56. package/doc/ai/zh-CN/troubleshooting.md +150 -0
  57. package/doc/gui-scripts.md +350 -0
  58. package/doc/gui.md +646 -0
  59. package/doc/icon.md +265 -0
  60. package/doc/implemented.md +373 -0
  61. package/doc/node-implemented.md +588 -0
  62. package/doc/node-unimplemented.md +167 -0
  63. package/doc/post/announce.md +43 -0
  64. package/doc/requirements.md +145 -0
  65. package/doc/unimplemented.md +286 -0
  66. package/doc/xbintsc.config.schema.json +67 -0
  67. package/doc/zh-CN/DESIGN.md +104 -0
  68. package/doc/zh-CN/gui-scripts.md +329 -0
  69. package/doc/zh-CN/gui.md +588 -0
  70. package/doc/zh-CN/icon.md +241 -0
  71. package/doc/zh-CN/implemented.md +365 -0
  72. package/doc/zh-CN/node-implemented.md +533 -0
  73. package/doc/zh-CN/node-unimplemented.md +141 -0
  74. package/doc/zh-CN/plan-require-node-modules.md +284 -0
  75. package/doc/zh-CN/post/announce.md +47 -0
  76. package/doc/zh-CN/requirements.md +134 -0
  77. package/doc/zh-CN/unimplemented.md +247 -0
  78. package/llms.txt +45 -0
  79. package/package.json +6 -2
  80. package/runtime/ext_gui/dom_api_proto.cpp +5 -0
  81. package/runtime/ext_gui/gui.cpp +3 -1
  82. package/runtime/ext_gui/renderer.cpp +13 -11
  83. package/runtime/ext_gui/renderer_image.cpp +12 -8
  84. package/runtime/ext_gui/renderer_shaders.h +131 -4
  85. package/runtime/ext_gui/renderer_shaders_data.h +1809 -0
  86. package/runtime/ext_gui/renderer_text.cpp +12 -8
  87. package/runtime/ext_gui/shaders.hlsl +98 -0
  88. package/runtime/ext_gui/spirv/fill.frag +19 -0
  89. package/runtime/ext_gui/spirv/fill.vert +42 -0
  90. package/runtime/ext_gui/spirv/image.frag +16 -0
  91. package/runtime/ext_gui/spirv/quad.vert +30 -0
  92. package/runtime/ext_gui/spirv/text.frag +16 -0
  93. package/runtime/ext_gui/window.cpp +1 -0
  94. package/runtime/ext_node/buffer/parts/prototype.inc +1 -0
  95. package/runtime/ext_node/dgram/dgram.c +1 -0
  96. package/runtime/ext_node/events/events.c +1 -0
  97. package/runtime/ext_node/fs/fs_ops.c +10 -25
  98. package/runtime/ext_node/fs/glob.c +13 -30
  99. package/runtime/ext_node/fs/promises.c +1 -0
  100. package/runtime/ext_node/http/parts/prototypes.inc +5 -0
  101. package/runtime/ext_node/net/parts/prototypes.inc +2 -0
  102. package/runtime/ext_node/process/process.c +9 -7
  103. package/runtime/ext_node/stream/stream.c +1 -0
  104. package/runtime/ext_node/util/util.c +6 -6
  105. package/runtime/rt.h +10 -0
  106. package/runtime/rt_internal.h +63 -2
  107. package/runtime/xt_alloc.c +442 -5
  108. package/runtime/xt_generator.c +95 -1
  109. package/runtime/xt_loop.c +35 -1
  110. package/runtime/xt_promise.c +46 -0
  111. package/runtime/xt_stdlib2/error.inc +1 -0
  112. package/runtime/xt_stdlib2/regexp-match.inc +8 -7
  113. package/runtime/xt_symbol.c +2 -0
  114. package/runtime/xt_typed_array/construction.inc +142 -0
  115. package/runtime/xt_typed_array/elements.inc +92 -0
  116. package/runtime/xt_typed_array/methods.inc +329 -0
  117. package/runtime/xt_typed_array.c +6 -548
  118. package/runtime/xt_values/number-format.inc +26 -0
  119. package/scripts/build-gui-shaders.mjs +204 -0
  120. package/scripts/build-gui.ts +35 -0
  121. package/scripts/check-file-length.ts +89 -0
  122. package/src/cli/hints.ts +194 -0
  123. package/src/cli/main.ts +82 -9
  124. package/src/codegen/generator/module.ts +10 -0
  125. package/src/codegen/generator/state.ts +4 -0
  126. package/src/codegen/generator/tables.ts +60 -14
  127. package/src/diagnostics/source-text.ts +78 -0
  128. package/src/driver/bundler/graph.ts +2 -1
  129. package/src/driver/compiler.ts +3 -2
  130. package/src/lexer/scanner/strings.ts +16 -3
@@ -0,0 +1,533 @@
1
+ # xbintsc Node 扩展已实现功能
2
+
3
+ > 语言 / Language:[English](../node-implemented.md) | **简体中文**
4
+
5
+ 本文档基于对 Node 扩展源码(`src/extensions/node/`)与 C 运行时(`runtime/ext_node/`)的逐文件核对整理,列出当前 **Node 扩展真正可用** 的功能与接口。
6
+
7
+ > 相关文档:
8
+ > - 核心语言能力见 [implemented.md](implemented.md) / [unimplemented.md](unimplemented.md)
9
+ > - Node 扩展未实现部分见 [node-unimplemented.md](node-unimplemented.md)
10
+
11
+ ---
12
+
13
+ ## 1. 扩展机制(已实现)
14
+
15
+ 实现位置:`src/extensions/node/index.ts`、`src/extensions/node/module.ts`、`src/extensions/registry.ts`
16
+
17
+ - Node 扩展通过统一的 `Extension` 对象接入,仅在注册时编译并链接其 C 源。
18
+ - 通过 CLI 开启:
19
+
20
+ ```bash
21
+ xbintsc run examples/node/read.ts --ext node
22
+ ```
23
+
24
+ - 模块化组织:每个 Node 模块一个子目录,与 C 实现一一对应:
25
+
26
+ ```
27
+ src/extensions/node/ runtime/ext_node/
28
+ index.ts # nodeExtension fs/read_file.c
29
+ module.ts # NodeModule 接口 fs/write_file.c
30
+ fs/index.ts fs/fs_ops.c
31
+ fs/read-file.ts fs/fs_common.h
32
+ fs/write-file.ts fs/promises.c
33
+ fs/fs-ops.ts fs/streams.c
34
+ fs/streams.ts fs/fd_ops.c
35
+ path/index.ts fs/meta_ops.c
36
+ os/index.ts fs/link_ops.c
37
+ process/index.ts fs/copy_ops.c
38
+ buffer/index.ts fs/dir.c
39
+ stream/index.ts fs/glob.c
40
+ net/index.ts fs/watch.c
41
+ dgram/index.ts fs/constants.c
42
+ http/index.ts path/path.c
43
+ fs-promises/index.ts os/os.c
44
+ crypto/index.ts process/process.c
45
+ url/index.ts buffer/buffer.c
46
+ child_process/index.ts stream/stream.c
47
+ events/index.ts net/net.c
48
+ util/index.ts dgram/dgram.c
49
+ querystring/index.ts http/http.c
50
+ assert/index.ts node_common.h(事件发射器 / 编码助手)
51
+ test/index.ts crypto/crypto.c
52
+ zlib/index.ts url/url.c
53
+ stream-promises/index.ts child_process/child_process.c
54
+ worker_threads/index.ts events/events.c
55
+ util/util.c
56
+ querystring/querystring.c
57
+ assert/assert.c
58
+ test/test.c
59
+ zlib/zlib.c
60
+ stream/pipeline.c
61
+ worker_threads/worker_threads.c
62
+ ```
63
+
64
+ - 核心事件循环:`runtime/xt_loop.c`(`select(2)` 反应堆),生成模块的 `main` 在微任务清空后调用 `xt_run_event_loop()`;无可注册 fd 或定时器时立即返回,因此纯计算程序不受影响。
65
+
66
+ - `NodeModule` 接口:
67
+ - `name`:模块名(如 `fs`)
68
+ - `runtimeSources()`:该模块的 C 源
69
+ - `builtins()`:全局标识符 → 运行时符号的映射(`path` / `os` / `process` 通过命名空间分发,故返回空表)
70
+ - `namespace` / `exports()`:该模块的可导入命名空间与命名导出(`import { join } from "path"`、`import path from "path"`)
71
+ - `resolveFrom(importMetaUrl, relative)`:把相对于当前模块目录的路径解析为绝对路径,用于定位 C 源。
72
+
73
+ ---
74
+
75
+ ## 2. `fs` 模块(已实现,仅同步 API)
76
+
77
+ 实现位置:`src/extensions/node/fs/*.ts`、`runtime/ext_node/fs/*.c`
78
+
79
+ ### 2.1 可用函数(从 `fs` 导入)
80
+
81
+ | 导入函数 | 运行时符号 | 说明 |
82
+ | --- | --- | --- |
83
+ | `readFileSync(path[, options])` | `xt_node_read_text_file` | 同步读取文件,返回字符串;支持编码选项 |
84
+ | `readTextFile(path)` | `xt_node_read_text_file` | `readFileSync` 的别名(同一符号) |
85
+ | `writeFileSync(path, data[, options])` | `xt_node_write_file` | 覆盖写入;接受字符串或 `Buffer` |
86
+ | `appendFileSync(path, data[, options])` | `xt_node_append_file` | 追加写入;接受字符串或 `Buffer` |
87
+ | `existsSync(path)` | `xt_node_exists` | 是否存在,返回布尔值 |
88
+ | `readdirSync(path[, options])` | `xt_node_read_dir` | 目录项名称;`{ withFileTypes: true }` 返回 `Dirent`,`{ recursive: true }` 递归 |
89
+ | `mkdirSync(path[, options])` | `xt_node_mkdir` | 创建目录,`{ recursive: true }` 递归创建,`{ mode }` 生效 |
90
+ | `rmSync(path[, options])` | `xt_node_rm` | 删除文件/目录,`{ recursive: true }` 递归删除 |
91
+ | `unlinkSync(path)` | `xt_node_unlink` | 删除文件 |
92
+ | `rmdirSync(path)` | `xt_node_rmdir` | 删除空目录 |
93
+ | `renameSync(oldPath, newPath)` | `xt_node_rename` | 重命名 / 移动 |
94
+ | `copyFileSync(src, dest[, flags])` | `xt_node_copy_file` | 复制文件;支持 `COPYFILE_EXCL` |
95
+ | `cpSync(src, dest[, options])` | `xt_node_cp` | 递归复制;`recursive` / `force` / `errorOnExist` / `dereference` / `preserveTimestamps` |
96
+ | `realpathSync(path)` | `xt_node_realpath` | 解析为绝对路径 |
97
+ | `statSync(path)` | `xt_node_stat` | 文件元信息对象(跟随符号链接) |
98
+ | `lstatSync(path)` | `xt_node_lstat` | 文件元信息对象(不跟随符号链接) |
99
+ | `statfsSync(path)` | `xt_node_statfs` | 文件系统统计(`bsize` / `blocks` / `bfree` …) |
100
+ | `accessSync(path[, mode])` | `xt_node_access` | 检查可访问性 |
101
+ | `chmodSync(path, mode)` | `xt_node_chmod` | 修改权限 |
102
+ | `lchmodSync(path, mode)` | `xt_node_lchmod` | 修改符号链接权限 |
103
+ | `chownSync(path, uid, gid)` | `xt_node_chown` | 修改属主 |
104
+ | `lchownSync(path, uid, gid)` | `xt_node_lchown` | 修改符号链接属主 |
105
+ | `truncateSync(path[, len])` | `xt_node_truncate` | 截断文件 |
106
+ | `utimesSync(path, atime, mtime)` | `xt_node_utimes` | 设置访问/修改时间(秒数或 `Date`) |
107
+ | `lutimesSync(path, atime, mtime)` | `xt_node_lutimes` | 设置符号链接时间 |
108
+ | `mkdtempSync(prefix)` | `xt_node_mkdtemp` | 创建唯一临时目录 |
109
+ | `linkSync(existing, newPath)` | `xt_node_link` | 硬链接 |
110
+ | `symlinkSync(target, path[, type])` | `xt_node_symlink` | 符号链接 |
111
+ | `readlinkSync(path)` | `xt_node_readlink` | 读取符号链接目标 |
112
+ | `opendirSync(path[, options])` | `xt_node_opendir` | 返回 `Dir`(`readSync` / `closeSync` / `read` / `close`) |
113
+ | `globSync(pattern[, options])` | `xt_node_glob` | glob 匹配(`*` / `?` / `[...]` / `**`),`{ cwd, withFileTypes }` |
114
+ | `openSync(path[, flags[, mode]])` | `xt_node_open` | 打开文件描述符 |
115
+ | `closeSync(fd)` | `xt_node_close` | 关闭描述符 |
116
+ | `readSync(fd, buffer, offset, length, position)` | `xt_node_read` | 读入 `Buffer` |
117
+ | `writeSync(fd, data[, offset[, length[, position]]])` | `xt_node_write` | 写入字符串 / `Buffer` |
118
+ | `readvSync(fd, buffers[, position])` | `xt_node_readv` | 分散读 |
119
+ | `writevSync(fd, buffers[, position])` | `xt_node_writev` | 聚集写 |
120
+ | `fstatSync(fd)` | `xt_node_fstat` | 描述符的 `stat` |
121
+ | `fsyncSync(fd)` / `fdatasyncSync(fd)` | `xt_node_fsync` / `xt_node_fdatasync` | 刷新描述符 |
122
+ | `ftruncateSync(fd[, len])` | `xt_node_ftruncate` | 截断描述符 |
123
+ | `fchmodSync(fd, mode)` | `xt_node_fchmod` | 描述符的 `chmod` |
124
+ | `fchownSync(fd, uid, gid)` | `xt_node_fchown` | 描述符的 `chown` |
125
+ | `futimesSync(fd, atime, mtime)` | `xt_node_futimes` | 描述符的 `utimes` |
126
+ | `watch(filename[, options][, listener])` | `xt_node_watch` | 返回发射器形态的 watcher(不会触发,见 §2.6) |
127
+ | `watchFile(filename[, options], listener)` | `xt_node_watch_file` | 轮询形态的 `StatWatcher`(不会触发) |
128
+ | `unwatchFile(filename[, listener])` | `xt_node_unwatch_file` | 停止监听 |
129
+ | `constants` | `xt_fs_constants` | `F_OK` / `R_OK` / `W_OK` / `X_OK`、`COPYFILE_*`、`O_*`、`S_IF*`(宿主值) |
130
+ | `promises` | `xt_fs_promises` | `fs/promises` 门面(见 §11) |
131
+
132
+ ### 2.2 编码支持
133
+
134
+ `readFileSync` / `writeFileSync` / `appendFileSync` 的 `options` 可以是编码字符串,也可以是 `{ encoding: "..." }`:
135
+
136
+ | 编码 | 读取 | 写入 |
137
+ | --- | --- | --- |
138
+ | 默认 / `utf8` / `utf-8` / `ascii` / `latin1` / `binary` | 原始 UTF-8 文本 | 按文本字节写入 |
139
+ | `hex` | 小写十六进制字符串 | 解析十六进制后写入 |
140
+ | `base64` | Base64 字符串 | 解析 Base64 后写入 |
141
+ | `base64url` | Base64url 字符串 | 解析 Base64url 后写入 |
142
+ | `utf16le` / `ucs2` | 按文本直接读取原始字节(不做 UTF-16 解码) | 按 UTF-8 文本写入 |
143
+
144
+ > `readFileSync` 默认仍返回**字符串**而不是 `Buffer`(即使 `Buffer` 类已存在),这样 `console.log(readFileSync(p))` 仍打印文本。
145
+
146
+ ### 2.3 `statSync` 返回结构
147
+
148
+ 返回普通对象,数值属性:`size`、`mode`、`uid`、`gid`、`dev`、`ino`、`nlink`、`rdev`、`blksize`、`blocks`、`atimeMs`、`mtimeMs`、`ctimeMs`、`birthtimeMs`。
149
+ 方法(原生闭包,可调用):`isFile()`、`isDirectory()`、`isSymbolicLink()`、`isFIFO()`、`isSocket()`、`isBlockDevice()`、`isCharacterDevice()`。
150
+
151
+ ### 2.4 调用方式
152
+
153
+ `fs` 的导出通过 `import` 引入(也可用 `node:fs` 别名),不再以裸全局标识符暴露:
154
+
155
+ ```ts
156
+ import { readFileSync, writeFileSync, existsSync } from "fs";
157
+
158
+ const text = readFileSync("examples/data.txt");
159
+ writeFileSync("/tmp/out.txt", text);
160
+ console.log(existsSync("/tmp/out.txt"));
161
+ ```
162
+
163
+ ### 2.5 错误处理
164
+
165
+ 失败时函数会**抛出** Node 形态的 `Error` 对象,带有 `name`(`Error`)、`message`、`code`(如 `ENOENT`)、`errno`(数值 `errno`)、`syscall` 与 `path`。`existsSync` 仍返回布尔值,不会抛出。
166
+
167
+ ```ts
168
+ import { readFileSync } from "fs";
169
+ try {
170
+ readFileSync("/does/not/exist");
171
+ } catch (error) {
172
+ console.log((error as any).code); // ENOENT
173
+ }
174
+ ```
175
+
176
+ ### 2.6 与 Node 的差异
177
+
178
+ - **没有异步 I/O 调度器**(事件循环是配有定时器与套接字、但无回调式 `fs` 后端的 `select(2)` 反应堆),因此不提供回调式 `fs` 函数(`readFile`、`writeFile`、`open` 等);请使用 `fs/promises` 或 `*Sync` 形式。
179
+ - `watch` / `watchFile` / `unwatchFile` 返回 API 形态的发射器对象,`.close()` / `.on()` 方法存在,但**不会触发**事件。
180
+ - `Dir.read(cb)` / `Dir.close(cb)` 会**同步**调用回调。
181
+ - `readFileSync` 默认返回字符串而不是 `Buffer`。
182
+ - `utf16le` / `ucs2` 读取时按原始字节处理(不做 UTF-16 解码)。
183
+ - `mkdtempSync` 无论前缀是否以 `XXXXXX` 结尾,都会追加 6 个随机字符。
184
+ - `globSync` 支持 `*`、`?`、`[...]`、`**`,但不支持 `exclude` 回调与 `follow`;`**` 不跟随符号链接(与 Node 默认一致)。
185
+ - `cpSync` 基于同步助手实现;除非 `dereference: true`,否则符号链接按符号链接复制。
186
+ - **Windows**:`readlinkSync` 抛 `ENOSYS`;`chmodSync` / `lchmodSync` / `chownSync` / `lchownSync` / `fchmodSync` / `fchownSync` 为空操作;`statfsSync` 返回全零字段。
187
+ - **macOS / Windows**:`lutimesSync` 退化为 `utimesSync`。
188
+
189
+ ---
190
+
191
+ ## 3. `path` 模块(已实现)
192
+
193
+ 实现位置:`src/extensions/node/path/index.ts`、`runtime/ext_node/path/path.c`
194
+
195
+ 采用 `path.<name>(...)` 命名空间调用,编译器将其降为 `xt_path_static(<name>, argc, argv)`。结果在所有平台上都以 POSIX `/` 分隔符输出(Windows 也接受 `/`),但输入可以使用 Windows 原生分隔符:在 Windows 上 `/` 与 `\` 都被识别,并保留盘符前缀(`C:`),因此自举后的编译器能正确解析带盘符的路径。以命名空间方式导入(`import path from "path"` / `import * as path from "path"`),或单独导入方法(`import { join } from "path"`)。
196
+
197
+ | 方法 | 说明 |
198
+ | --- | --- |
199
+ | `path.join(...parts)` | 拼接并规范化 |
200
+ | `path.resolve(...parts)` | 解析为绝对路径 |
201
+ | `path.normalize(path)` | 规范化 |
202
+ | `path.dirname(path)` | 目录名 |
203
+ | `path.basename(path[, ext])` | 文件名,可去掉扩展名 |
204
+ | `path.extname(path)` | 扩展名 |
205
+ | `path.isAbsolute(path)` | 是否绝对路径 |
206
+ | `path.relative(from, to)` | 相对路径 |
207
+
208
+ ```ts
209
+ import path from "path";
210
+ import { basename } from "path";
211
+
212
+ console.log(path.join("a", "b", "..", "c")); // a/c
213
+ console.log(basename("/x/y/z.txt")); // z.txt
214
+ ```
215
+
216
+ ---
217
+
218
+ ## 4. `os` 模块(已实现)
219
+
220
+ 实现位置:`src/extensions/node/os/index.ts`、`runtime/ext_node/os/os.c`
221
+
222
+ 采用 `os.<name>(...)` 命名空间调用,降为 `xt_os_static(<name>, argc, argv)`。
223
+ 以命名空间方式导入(`import os from "os"`),或单独导入函数(`import { platform } from "os"`)。
224
+
225
+ | 方法 | 说明 |
226
+ | --- | --- |
227
+ | `os.platform()` | `darwin` / `linux` / `win32` / ... |
228
+ | `os.arch()` | `x64` / `arm64` / `ia32` / `arm` |
229
+ | `os.type()` | `Darwin` / `Linux` / `Windows_NT` / ... |
230
+ | `os.release()` | 内核版本 |
231
+ | `os.endianness()` | `LE` / `BE` |
232
+ | `os.homedir()` | 用户主目录 |
233
+ | `os.tmpdir()` | 临时目录 |
234
+ | `os.hostname()` | 主机名 |
235
+ | `os.totalmem()` / `os.freemem()` | 总内存 / 可用内存(字节) |
236
+ | `os.cpus()` | CPU 条目数组(`model` / `speed` 占位) |
237
+
238
+ ---
239
+
240
+ ## 5. `process` 对象(已实现)
241
+
242
+ 实现位置:`src/extensions/node/process/index.ts`、`runtime/ext_node/process/process.c`
243
+
244
+ 方法调用降为 `xt_process_call(<name>, argc, argv)`,属性访问降为 `xt_process_get(<name>)`。
245
+ 通过 `import process from "process"` 导入后使用。
246
+
247
+ | 方法 / 属性 | 说明 |
248
+ | --- | --- |
249
+ | `process.cwd()` | 当前工作目录 |
250
+ | `process.exit([code])` | 退出进程 |
251
+ | `process.uptime()` | 进程运行时间(秒) |
252
+ | `process.hrtime()` | `[秒, 纳秒]` 数组 |
253
+ | `process.getuid()` | 用户 ID(Windows 返回 0) |
254
+ | `process.platform` / `process.arch` | 平台 / 架构 |
255
+ | `process.pid` / `process.ppid` | 进程 ID / 父进程 ID |
256
+ | `process.argv` | 参数数组(`argv[0]` 为可执行文件) |
257
+ | `process.env` | 环境变量对象 |
258
+ | `process.version` / `process.title` | 占位字符串 |
259
+
260
+ > `argv` 由生成的 `main` 通过 `xt_set_program_args` 捕获后提供给运行时。
261
+
262
+ ---
263
+
264
+ ## 6. `buffer` 模块(已实现)
265
+
266
+ 实现位置:`src/extensions/node/buffer/index.ts`、`runtime/ext_node/buffer/buffer.c`
267
+
268
+ xbintsc 没有原生的二进制值类型,`Buffer` 以**普通对象**表示:每个字节是数字属性 `"0".."n-1"`,再加一个 `length` 属性,并共享 `xt_buffer_proto()` 原型提供实例方法。`xt_node_is_buffer` / `xt_node_buffer_bytes` 供其它模块跨模块访问字节。
269
+
270
+ | 静态方法 | 说明 |
271
+ | --- | --- |
272
+ | `Buffer.from(value[, encoding])` | 从字符串(hex / base64 / utf8)、数组或 Buffer 构造 |
273
+ | `Buffer.alloc(size[, fill])` | 分配并填充 |
274
+ | `Buffer.allocUnsafe(size)` | 分配 |
275
+ | `Buffer.isBuffer(value)` | 判定 |
276
+ | `Buffer.byteLength(value[, encoding])` | 字节长度 |
277
+ | `Buffer.concat(list[, totalLength])` | 拼接 |
278
+ | `Buffer.compare(a, b)` | 比较 |
279
+
280
+ 实例方法:`toString([encoding])`、`toJSON()`、`slice(start, end)`、`subarray(...)`、`equals(other)`、`compare(other)`、`copy(target[, targetStart, sourceStart, sourceEnd])`、`write(string[, offset[, length[, encoding]]])`、`fill(value)`、`reverse()`、`indexOf(value)`、`lastIndexOf(value)`、`includes(value)`、`keys()`、`values()`,以及 `readUInt8/UInt16LE/UInt16BE/UInt32LE/UInt32BE`、`writeUInt8/UInt16LE/UInt16BE/UInt32LE/UInt32BE`。
281
+
282
+ ```ts
283
+ const buf = Buffer.from("hello");
284
+ console.log(buf.toString(), buf.length); // hello 5
285
+ console.log(Buffer.alloc(4, 65).toString()); // AAAA
286
+ ```
287
+
288
+ ---
289
+
290
+ ## 7. `stream` 模块(已实现)
291
+
292
+ 实现位置:`src/extensions/node/stream/index.ts`、`runtime/ext_node/stream/stream.c`
293
+
294
+ `Readable` / `Writable` / `Duplex` / `Transform` / `PassThrough` 作为**全局构造函数**使用(`new Readable()` 等);`stream.Readable.from(...)` 等静态方法通过 `stream` 命名空间解析。流是 EventEmitter,采用**同步事件模型**:`on('data')` 时冲刷 `push` 缓冲,`write` 即时投递。
295
+
296
+ | 方法 | 说明 |
297
+ | --- | --- |
298
+ | `push(chunk)` / `read([n])` | Readable 端 |
299
+ | `write(chunk)` / `end([chunk])` | Writable 端 |
300
+ | `pipe(destination)` | 数据转发 |
301
+ | `on('data' / 'end' / 'finish')` | 事件 |
302
+ | `pause()` / `resume()` / `setEncoding(enc)` / `destroy()` | 流控制 |
303
+
304
+ ---
305
+
306
+ ## 8. `net` 模块(已实现)
307
+
308
+ 实现位置:`src/extensions/node/net/index.ts`、`runtime/ext_node/net/net.c`
309
+
310
+ TCP 服务端与客户端,基于核心事件循环。
311
+
312
+ | API | 说明 |
313
+ | --- | --- |
314
+ | `net.createServer([connectionListener])` | 创建 TCP 服务端(`Server` 构造函数等价) |
315
+ | `net.connect(...)` / `net.createConnection(...)` | 连接(阻塞式 connect,之后注册事件循环) |
316
+ | `net.isIP(s)` / `net.isIPv4(s)` / `net.isIPv6(s)` | 地址判定 |
317
+
318
+ `Server`:`listen(port[, host][, cb])`、`close([cb])`、`address()`、`getConnections(cb)`,事件 `listening` / `connection` / `close`。
319
+
320
+ `Socket`:`write(data[, cb])`、`end([data])`、`destroy()`、`address()`、`setEncoding(enc)`、`pause()` / `resume()`,事件 `data` / `end` / `close` / `connect` / `error`。
321
+
322
+ ---
323
+
324
+ ## 9. `dgram` 模块(已实现)
325
+
326
+ 实现位置:`src/extensions/node/dgram/index.ts`、`runtime/ext_node/dgram/dgram.c`
327
+
328
+ UDP 套接字。`dgram.createSocket(type | options[, cb])` 返回 EventEmitter。
329
+
330
+ | 方法 | 说明 |
331
+ | --- | --- |
332
+ | `bind([port][, address][, cb])` | 绑定(未绑定时 `send` 会自动绑定) |
333
+ | `send(msg[, offset, length,] port[, address][, cb])` | 发送数据报 |
334
+ | `close([cb])` / `address()` | 关闭 / 查询地址 |
335
+ | `setBroadcast(b)` / `setTTL(n)` / `setMulticastTTL(n)` | 套接字选项 |
336
+ | `on('message', (msg, rinfo) => ...)` | 收到数据报,`rinfo` 含 `address` / `port` / `family` / `size` |
337
+
338
+ ---
339
+
340
+ ## 10. `http` 模块(已实现)
341
+
342
+ 实现位置:`src/extensions/node/http/index.ts`、`runtime/ext_node/http/http.c`
343
+
344
+ 服务端包裹一个 `net` 服务端:每个连接累积字节直到完整请求(请求行 + 头 + `Content-Length` body)可用,再以 `req`/`res` 调用 `request` 监听器。客户端包裹一个 `net` 套接字,写出 HTTP/1.1 请求并在连接关闭后解析响应。
345
+
346
+ | API | 说明 |
347
+ | --- | --- |
348
+ | `http.createServer([requestListener])` | 创建 HTTP 服务端 |
349
+ | `http.request(options[, cb])` | 创建 `ClientRequest`(`write` / `end` / `setHeader`) |
350
+ | `http.get(url[, cb])` | 发起 GET |
351
+
352
+ `IncomingMessage`(`req` / 响应):`method`、`url`、`httpVersion`、`headers`、`statusCode`、`data` / `end` 事件、`setEncoding`。
353
+
354
+ `ServerResponse`(`res`):`writeHead(status[, message][, headers])`、`setHeader` / `getHeader` / `removeHeader` / `getHeaders`、`write(chunk)`、`end([chunk])`,事件 `finish` / `close`。响应固定带 `Connection: close`(不做 keep-alive)。
355
+
356
+ ---
357
+
358
+ ## 11. `fs/promises` 模块(已实现)
359
+
360
+ 实现位置:`src/extensions/node/fs-promises/index.ts`、`runtime/ext_node/fs/promises.c`
361
+
362
+ 无异步 I/O 调度器,故每个函数把对应的同步 `fs` 实现包进**已 settle 的 Promise**。失败时会以同步形式抛出的同构 Node `Error`(含 `code` / `errno` / `syscall` / `path`)**reject**。`fs.promises` 也可从 `fs` 模块访问(`import { promises as fsp } from "fs"`),两个命名空间都暴露 `constants` 对象。
363
+
364
+ Promise 导出:`readFile`、`writeFile`、`appendFile`、`mkdir`、`readdir`、`rm`、`unlink`、`rmdir`、`rename`、`copyFile`、`cp`、`realpath`、`stat`、`lstat`、`statfs`、`access`、`open`、`chmod`、`lchmod`、`chown`、`lchown`、`truncate`、`utimes`、`lutimes`、`link`、`symlink`、`readlink`、`mkdtemp`、`opendir`、`glob`、`watch`。
365
+
366
+ `open(...)` 解析为 **`FileHandle`**,带有:`read`、`write`、`readFile`、`writeFile`、`appendFile`、`close`、`stat`、`truncate`、`chmod`、`chown`、`utimes`、`sync`、`datasync`。
367
+
368
+ ```ts
369
+ import { readFile, writeFile, open } from "fs/promises";
370
+
371
+ async function main(): Promise<void> {
372
+ await writeFile("/tmp/a.txt", "hi");
373
+ console.log(await readFile("/tmp/a.txt"));
374
+ const handle = await open("/tmp/a.txt", "r");
375
+ console.log(await handle.readFile("utf8"));
376
+ await handle.close();
377
+ }
378
+ main();
379
+ ```
380
+
381
+ ### 11.1 与 Node 的差异
382
+
383
+ - 由于 I/O 是同步的,Promise 在返回值被 `await` 之前就已 settle(事件循环不会让出)。
384
+ - `FileHandle.appendFile` 行为同 `writeFile`(在当前位置写入而非追加)。
385
+ - `FileHandle.readFile()` 从当前文件描述符偏移处读取。
386
+ - `Dir.read` / `Dir.close`(同步与 Promise/回调两种形式)都会立即完成。
387
+ - `watch` 解析为与 `fs.watch` 相同的不会触发的 watcher 对象。
388
+
389
+ ---
390
+
391
+ ## 12. `child_process` 模块(已实现)
392
+
393
+ 位置:`src/extensions/node/child_process/index.ts`、`runtime/ext_node/child_process/child_process.c`
394
+
395
+ `spawnSync(command, args[, options])` 运行一个程序直到结束,返回
396
+ `{ status, stdout, stderr }`。`options.cwd` 设置子进程工作目录;
397
+ `options.stdio: "inherit"` 让子进程共用父进程的 stdout/stderr(`xbintsc run`
398
+ 用它把被编译程序的输出实时透传),否则 stdout/stderr 会作为 UTF-8 字符串捕获。
399
+
400
+ | 选项 | 说明 |
401
+ | --- | --- |
402
+ | `cwd` | 子进程的工作目录 |
403
+ | `stdio: "inherit"` | 共用父进程的 stdout/stderr,而不是捕获 |
404
+ | `encoding` | 接受但忽略(输出始终按 UTF-8 解码) |
405
+
406
+ ```ts
407
+ import { spawnSync } from "child_process";
408
+
409
+ const result = spawnSync("clang", ["--version"], { encoding: "utf8" });
410
+ console.log(result.status, result.stdout.split("\n")[0]);
411
+ ```
412
+
413
+ ---
414
+
415
+ ## 13. `events` 模块(已实现)
416
+
417
+ 位置:`src/extensions/node/events/index.ts`、`runtime/ext_node/events/events.c`
418
+
419
+ 提供独立的 `EventEmitter`,既可以作为**全局构造函数**使用
420
+ (`new EventEmitter()`),也可以作为命名导出(`import { EventEmitter } from
421
+ "events"`)。实例与 `stream` / `net` / `http` 共用运行时事件发射器(监听器存放
422
+ 在内部的 `__xt_events` 属性上),并在此基础上提供更完整的 `events` 接口:
423
+
424
+ | 方法 | 说明 |
425
+ | --- | --- |
426
+ | `on(name, fn)` / `addListener(name, fn)` | 追加监听器 |
427
+ | `once(name, fn)` | 最多触发一次,然后自行移除 |
428
+ | `prependListener(name, fn)` / `prependOnceListener(name, fn)` | 插入到最前 |
429
+ | `off(name, fn)` / `removeListener(name, fn)` | 移除监听器 |
430
+ | `removeAllListeners([name])` | 清空某个(或全部)事件 |
431
+ | `emit(name[, ...args])` | 触发监听器 |
432
+ | `listeners(name)` / `rawListeners(name)` | 监听器数组 |
433
+ | `listenerCount(name)` | 监听器数量 |
434
+ | `eventNames()` | 当前有监听器的事件名 |
435
+ | `setMaxListeners(n)` / `getMaxListeners()` | 记录(默认 10) |
436
+
437
+ 通过命名空间(`import ee from "events"`)可访问的静态方法:`listenerCount`、
438
+ `getEventListeners`、`getMaxListeners`、`setMaxListeners`、`once`、
439
+ `addAbortListener`。
440
+
441
+ ```ts
442
+ import { EventEmitter } from "events";
443
+
444
+ const em = new EventEmitter();
445
+ em.once("ready", () => console.log("ready"));
446
+ em.emit("ready"); // ready
447
+ em.emit("ready"); // 无输出:监听器已执行过
448
+ ```
449
+
450
+ ---
451
+
452
+ ## 14. `util` 模块(已实现)
453
+
454
+ 位置:`src/extensions/node/util/index.ts`、`runtime/ext_node/util/util.c`
455
+
456
+ 同时支持命名导入(`import { format } from "util"`)与命名空间调用
457
+ (`import util from "util"` / `import * as util from "util"`)。
458
+
459
+ | 函数 | 说明 |
460
+ | --- | --- |
461
+ | `format(fmt, ...args)` | 支持 `%s` `%d` `%i` `%f` `%j` `%o` `%O` `%c` `%%` 占位符 |
462
+ | `formatWithOptions(opts, fmt, ...args)` | 接受选项但忽略 |
463
+ | `inspect(value)` | 递归打印(限制深度,字符串带引号) |
464
+ | `isDeepStrictEqual(a, b)` | 结构比较(`NaN` 等于 `NaN`) |
465
+ | `inherits(ctor, superCtor)` | 连接原型链 |
466
+ | `deprecate(fn, msg)` | 原样返回 `fn`(没有告警通道) |
467
+ | `promisify(fn)` | 把「回调在末尾」的函数包装为 `Promise` |
468
+ | `isString` `isNumber` `isBoolean` `isUndefined` `isNull` `isFunction` `isArray` `isObject` `isBuffer` `isDate` `isRegExp` `isPromise` `isError` | 类型判断 |
469
+
470
+ ```ts
471
+ import { format, promisify } from "util";
472
+
473
+ console.log(format("%s=%d", "n", 3)); // n=3
474
+ ```
475
+
476
+ ---
477
+
478
+ ## 15. `querystring` 模块(已实现)
479
+
480
+ 位置:`src/extensions/node/querystring/index.ts`、`runtime/ext_node/querystring/querystring.c`
481
+
482
+ | 函数 | 说明 |
483
+ | --- | --- |
484
+ | `parse(str[, sep[, eq]])` / `decode` | 解析为对象;重复的键会变成数组 |
485
+ | `stringify(obj[, sep[, eq]])` / `encode` | 序列化;空格变成 `+`,数组会重复键 |
486
+ | `escape(str)` / `unescape(str)` | 百分号编码 / 解码(`+` 解码为空格) |
487
+
488
+ 默认值:`sep = "&"`,`eq = "="`。
489
+
490
+ ```ts
491
+ import { parse, stringify } from "querystring";
492
+
493
+ const q = parse("a=1&b=2&b=3"); // { a: "1", b: ["2", "3"] }
494
+ console.log(stringify({ x: "a b" })); // x=a+b
495
+ ```
496
+
497
+ ---
498
+
499
+ ## 16. 已实现 Node 能力速查
500
+
501
+ | 类别 | 内容 |
502
+ | --- | --- |
503
+ | 扩展注册 | `nodeExtension`(`--ext node`)、`NodeModule` 接口、`resolveFrom` 工具 |
504
+ | fs 读取 | `readFileSync`、`readTextFile`(`xt_node_read_text_file`),支持 hex / base64 / base64url |
505
+ | fs 写入 | `writeFileSync`、`appendFileSync`,支持 hex / base64 / base64url;字符串或 `Buffer` |
506
+ | fs 目录 | `readdirSync`(`withFileTypes` / `recursive`)、`mkdirSync`、`rmSync`、`unlinkSync`、`rmdirSync`、`opendirSync`(`Dir`)、`globSync`、`mkdtempSync` |
507
+ | fs 其它 | `existsSync`、`renameSync`、`copyFileSync`、`cpSync`、`realpathSync`、`statSync`、`lstatSync`、`statfsSync`、`accessSync`、`chmodSync`、`chownSync`、`lchmodSync`、`lchownSync`、`truncateSync`、`utimesSync`、`lutimesSync`、`linkSync`、`symlinkSync`、`readlinkSync`、`watch`、`watchFile`、`unwatchFile` |
508
+ | fs 描述符 | `openSync`、`closeSync`、`readSync`、`writeSync`、`readvSync`、`writevSync`、`fstatSync`、`fsyncSync`、`fdatasyncSync`、`ftruncateSync`、`fchmodSync`、`fchownSync`、`futimesSync` |
509
+ | fs 常量 | `constants`(`F_OK`、`R_OK`、`W_OK`、`X_OK`、`COPYFILE_*`、`O_*`、`S_IF*`) |
510
+ | path | `join` `resolve` `normalize` `dirname` `basename` `extname` `isAbsolute` `relative` |
511
+ | os | `platform` `arch` `type` `release` `endianness` `homedir` `tmpdir` `hostname` `totalmem` `freemem` `cpus` |
512
+ | process | `cwd` `exit` `uptime` `hrtime` `getuid`;`platform` `arch` `pid` `ppid` `argv` `env` `version` `title` |
513
+ | buffer | `Buffer.from/alloc/allocUnsafe/isBuffer/byteLength/concat/compare`;实例 `toString/toJSON/slice/.../readUInt32BE/writeUInt32BE` |
514
+ | stream | `Readable` `Writable` `Duplex` `Transform` `PassThrough`;`push/read/write/end/pipe/on` |
515
+ | net | `createServer` `connect` `createConnection` `isIP/isIPv4/isIPv6`;`Server` `Socket` |
516
+ | dgram | `createSocket`;`bind/send/close/address/setBroadcast/setTTL` |
517
+ | http | `createServer` `request` `get`;`ClientRequest`、`IncomingMessage`、`ServerResponse` |
518
+ | child_process | `spawnSync(command, args[, {cwd, stdio}])`,返回 `status` / `stdout` / `stderr` |
519
+ | assert | `ok/equal/notEqual/strictEqual/notStrictEqual/deepStrictEqual/notDeepStrictEqual/throws/doesNotThrow/ifError/match/doesNotMatch/fail`(`import assert from "node:assert"`) |
520
+ | test | `test(name, fn)` / `it` / `describe` / `skip` / `todo`(`import test from "node:test"`),输出 TAP,失败时以非零码退出 |
521
+ | zlib | `createGzip()`(由 `stream/promises` 的 pipeline 消费) |
522
+ | stream/promises | `pipeline(...)`(同步执行,返回已决议的 Promise) |
523
+ | worker_threads | `Worker`、`isMainThread`、`workerData`、`parentPort`(把当前可执行文件作为子进程重跑) |
524
+ | events | `EventEmitter`(全局 + 命名);`on/once/off/emit/listeners/listenerCount/eventNames`;静态 `listenerCount/getEventListeners/getMaxListeners/setMaxListeners/once/addAbortListener` |
525
+ | util | `format` `formatWithOptions` `inspect` `isDeepStrictEqual` `inherits` `deprecate` `promisify`;`isString/isNumber/isBoolean/isUndefined/isNull/isFunction/isArray/isObject/isBuffer/isDate/isRegExp/isPromise/isError` |
526
+ | querystring | `parse`/`decode` `stringify`/`encode` `escape` `unescape` |
527
+ | crypto | `createHash(algorithm)`,含 `update`/`digest` 与流式 API(`setEncoding`/`write`/`end`/`read`);支持 SHA-1 与 SHA-256 |
528
+ | 全局函数 | `btoa` / `atob` base64 辅助函数;定时器 `setTimeout` / `clearTimeout` / `setInterval` / `clearInterval`(返回数字 id,无 `Timeout` 对象) |
529
+ | url | `pathToFileURL` `fileURLToPath` |
530
+ | fs/promises | `readFile` `writeFile` `appendFile` `mkdir` `readdir` `rm` `unlink` `rmdir` `rename` `copyFile` `cp` `realpath` `stat` `lstat` `statfs` `access` `open` `chmod` `lchmod` `chown` `lchown` `truncate` `utimes` `lutimes` `link` `symlink` `readlink` `mkdtemp` `opendir` `glob` `watch` `constants`;`FileHandle` |
531
+ | 事件循环 | `xt_loop`(`select` 反应堆)、`xt_run_event_loop()`、`xt_loop_add/update/remove`、定时器队列(`xt_set_timeout` / `xt_set_interval` / `xt_clear_*`) |
532
+ | 调用约定 | 统一 `(argc, argv)` ABI,返回 `xt_value` |
533
+ | 链接方式 | 注册后编译 `runtime/ext_node/**` 并随运行时一起链接 |