xbintsc 0.3.46 → 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.
- package/AGENTS.md +95 -0
- package/README.md +25 -0
- package/README.zh-CN.md +23 -0
- package/dist/src/cli/hints.d.ts +54 -0
- package/dist/src/cli/hints.js +165 -0
- package/dist/src/cli/hints.js.map +1 -0
- package/dist/src/cli/main.js +73 -9
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/codegen/generator/tables.d.ts +26 -0
- package/dist/src/codegen/generator/tables.js +64 -12
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/diagnostics/source-text.d.ts +22 -0
- package/dist/src/diagnostics/source-text.js +76 -0
- package/dist/src/diagnostics/source-text.js.map +1 -0
- package/dist/src/driver/bundler/graph.js +2 -1
- package/dist/src/driver/bundler/graph.js.map +1 -1
- package/dist/src/driver/compiler.js +3 -2
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/lexer/scanner/strings.js +16 -3
- package/dist/src/lexer/scanner/strings.js.map +1 -1
- package/dist/tests/cli/hints.test.d.ts +9 -0
- package/dist/tests/cli/hints.test.js +143 -0
- package/dist/tests/cli/hints.test.js.map +1 -0
- package/dist/tests/cli/main.test.js +6 -4
- package/dist/tests/cli/main.test.js.map +1 -1
- package/dist/tests/codegen/llvm.test.js +17 -2
- package/dist/tests/codegen/llvm.test.js.map +1 -1
- package/dist/tests/helpers.js +3 -2
- package/dist/tests/helpers.js.map +1 -1
- package/dist/tests/lexer/strings.test.js +14 -2
- package/dist/tests/lexer/strings.test.js.map +1 -1
- package/doc/DESIGN.md +117 -0
- package/doc/ai/README.md +63 -0
- package/doc/ai/build-recipe.md +137 -0
- package/doc/ai/cli.md +142 -0
- package/doc/ai/contributing.md +196 -0
- package/doc/ai/extensions.md +148 -0
- package/doc/ai/language-support.md +152 -0
- package/doc/ai/troubleshooting.md +163 -0
- package/doc/ai/zh-CN/README.md +56 -0
- package/doc/ai/zh-CN/build-recipe.md +132 -0
- package/doc/ai/zh-CN/cli.md +127 -0
- package/doc/ai/zh-CN/contributing.md +173 -0
- package/doc/ai/zh-CN/extensions.md +139 -0
- package/doc/ai/zh-CN/language-support.md +147 -0
- package/doc/ai/zh-CN/troubleshooting.md +150 -0
- package/doc/gui-scripts.md +350 -0
- package/doc/gui.md +646 -0
- package/doc/icon.md +265 -0
- package/doc/implemented.md +373 -0
- package/doc/node-implemented.md +588 -0
- package/doc/node-unimplemented.md +167 -0
- package/doc/post/announce.md +43 -0
- package/doc/requirements.md +145 -0
- package/doc/unimplemented.md +286 -0
- package/doc/xbintsc.config.schema.json +67 -0
- package/doc/zh-CN/DESIGN.md +104 -0
- package/doc/zh-CN/gui-scripts.md +329 -0
- package/doc/zh-CN/gui.md +588 -0
- package/doc/zh-CN/icon.md +241 -0
- package/doc/zh-CN/implemented.md +365 -0
- package/doc/zh-CN/node-implemented.md +533 -0
- package/doc/zh-CN/node-unimplemented.md +141 -0
- package/doc/zh-CN/plan-require-node-modules.md +284 -0
- package/doc/zh-CN/post/announce.md +47 -0
- package/doc/zh-CN/requirements.md +134 -0
- package/doc/zh-CN/unimplemented.md +247 -0
- package/llms.txt +45 -0
- package/package.json +4 -1
- package/runtime/ext_gui/gui.cpp +3 -1
- package/runtime/ext_gui/renderer.cpp +13 -11
- package/runtime/ext_gui/renderer_image.cpp +12 -8
- package/runtime/ext_gui/renderer_shaders.h +131 -4
- package/runtime/ext_gui/renderer_shaders_data.h +1809 -0
- package/runtime/ext_gui/renderer_text.cpp +12 -8
- package/runtime/ext_gui/shaders.hlsl +98 -0
- package/runtime/ext_gui/spirv/fill.frag +19 -0
- package/runtime/ext_gui/spirv/fill.vert +42 -0
- package/runtime/ext_gui/spirv/image.frag +16 -0
- package/runtime/ext_gui/spirv/quad.vert +30 -0
- package/runtime/ext_gui/spirv/text.frag +16 -0
- package/scripts/build-gui-shaders.mjs +204 -0
- package/scripts/build-gui.ts +35 -0
- package/scripts/check-file-length.ts +5 -1
- package/src/cli/hints.ts +194 -0
- package/src/cli/main.ts +82 -9
- package/src/codegen/generator/tables.ts +60 -14
- package/src/diagnostics/source-text.ts +78 -0
- package/src/driver/bundler/graph.ts +2 -1
- package/src/driver/compiler.ts +3 -2
- package/src/lexer/scanner/strings.ts +16 -3
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
# xbintsc Node Extension Implemented Features
|
|
2
|
+
|
|
3
|
+
This document was compiled by checking the Node extension source
|
|
4
|
+
(`src/extensions/node/`) and the C runtime (`runtime/ext_node/`) file by file,
|
|
5
|
+
and lists the features and interfaces that the **Node extension actually
|
|
6
|
+
provides today**.
|
|
7
|
+
|
|
8
|
+
> Related documents:
|
|
9
|
+
> - Core language capabilities: [implemented.md](./implemented.md) / [unimplemented.md](./unimplemented.md)
|
|
10
|
+
> - Unimplemented parts of the Node extension: [node-unimplemented.md](./node-unimplemented.md)
|
|
11
|
+
|
|
12
|
+
> Language: **English** | [简体中文](./zh-CN/node-implemented.md)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 1. Extension mechanism (implemented)
|
|
17
|
+
|
|
18
|
+
Location: `src/extensions/node/index.ts`, `src/extensions/node/module.ts`, `src/extensions/registry.ts`
|
|
19
|
+
|
|
20
|
+
- The Node extension plugs in through the uniform `Extension` object; its C sources are compiled and linked only when it is registered.
|
|
21
|
+
- Enable it via the CLI:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
xbintsc run examples/node/read.ts --ext node
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
- Modular organisation: one subdirectory per Node module, in one-to-one correspondence with its C implementation:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
src/extensions/node/ runtime/ext_node/
|
|
31
|
+
index.ts # nodeExtension fs/read_file.c
|
|
32
|
+
module.ts # NodeModule iface fs/write_file.c
|
|
33
|
+
fs/index.ts fs/fs_ops.c
|
|
34
|
+
fs/read-file.ts fs/fs_common.h
|
|
35
|
+
fs/write-file.ts fs/promises.c
|
|
36
|
+
fs/fs-ops.ts fs/streams.c
|
|
37
|
+
fs/streams.ts fs/fd_ops.c
|
|
38
|
+
path/index.ts fs/meta_ops.c
|
|
39
|
+
os/index.ts fs/link_ops.c
|
|
40
|
+
process/index.ts fs/copy_ops.c
|
|
41
|
+
buffer/index.ts fs/dir.c
|
|
42
|
+
stream/index.ts fs/glob.c
|
|
43
|
+
net/index.ts fs/watch.c
|
|
44
|
+
dgram/index.ts fs/constants.c
|
|
45
|
+
http/index.ts path/path.c
|
|
46
|
+
fs-promises/index.ts os/os.c
|
|
47
|
+
crypto/index.ts process/process.c
|
|
48
|
+
url/index.ts buffer/buffer.c
|
|
49
|
+
child_process/index.ts stream/stream.c
|
|
50
|
+
events/index.ts net/net.c
|
|
51
|
+
util/index.ts dgram/dgram.c
|
|
52
|
+
querystring/index.ts http/http.c
|
|
53
|
+
assert/index.ts node_common.h (event emitter / encoding helpers)
|
|
54
|
+
test/index.ts crypto/crypto.c
|
|
55
|
+
zlib/index.ts url/url.c
|
|
56
|
+
stream-promises/index.ts child_process/child_process.c
|
|
57
|
+
worker_threads/index.ts events/events.c
|
|
58
|
+
util/util.c
|
|
59
|
+
querystring/querystring.c
|
|
60
|
+
assert/assert.c
|
|
61
|
+
test/test.c
|
|
62
|
+
zlib/zlib.c
|
|
63
|
+
stream/pipeline.c
|
|
64
|
+
worker_threads/worker_threads.c
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- Core event loop: `runtime/xt_loop.c` (a `select(2)` reactor). The generated module's `main` calls `xt_run_event_loop()` after draining microtasks; it returns immediately when no fds or timers are registered, so pure-computation programs are unaffected.
|
|
68
|
+
|
|
69
|
+
- The `NodeModule` interface:
|
|
70
|
+
- `name`: the module name (e.g. `fs`)
|
|
71
|
+
- `runtimeSources()`: the module's C sources
|
|
72
|
+
- `builtins()`: global identifier → runtime symbol mapping (`fs` returns its exports here; `path` / `os` / `process` dispatch through namespaces, so they return an empty table)
|
|
73
|
+
- `namespace` / `exports()`: the module's importable namespace and named exports (`import { join } from "path"`, `import path from "path"`)
|
|
74
|
+
- `resolveFrom(importMetaUrl, relative)`: resolves a path relative to the current module's directory into an absolute path, used to locate C sources.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## 2. The `fs` module (implemented, synchronous API only)
|
|
79
|
+
|
|
80
|
+
Location: `src/extensions/node/fs/*.ts`, `runtime/ext_node/fs/*.c`
|
|
81
|
+
|
|
82
|
+
### 2.1 Available functions (imported from `fs`)
|
|
83
|
+
|
|
84
|
+
| Imported function | Runtime symbol | Notes |
|
|
85
|
+
| --- | --- | --- |
|
|
86
|
+
| `readFileSync(path[, options])` | `xt_node_read_text_file` | synchronously read a file, returns a string; supports encoding options |
|
|
87
|
+
| `readTextFile(path)` | `xt_node_read_text_file` | alias of `readFileSync` (same symbol) |
|
|
88
|
+
| `writeFileSync(path, data[, options])` | `xt_node_write_file` | overwrite write; accepts a string or a `Buffer` |
|
|
89
|
+
| `appendFileSync(path, data[, options])` | `xt_node_append_file` | append write; accepts a string or a `Buffer` |
|
|
90
|
+
| `existsSync(path)` | `xt_node_exists` | whether it exists, returns a boolean |
|
|
91
|
+
| `readdirSync(path[, options])` | `xt_node_read_dir` | directory entry names; `{ withFileTypes: true }` returns `Dirent`s, `{ recursive: true }` recurses |
|
|
92
|
+
| `mkdirSync(path[, options])` | `xt_node_mkdir` | create a directory; `{ recursive: true }` creates recursively, `{ mode }` is honoured |
|
|
93
|
+
| `rmSync(path[, options])` | `xt_node_rm` | delete a file/directory; `{ recursive: true }` deletes recursively |
|
|
94
|
+
| `rmdirSync(path[, options])` | `xt_node_rmdir` | delete an empty directory |
|
|
95
|
+
| `unlinkSync(path)` | `xt_node_unlink` | delete a file |
|
|
96
|
+
| `renameSync(oldPath, newPath)` | `xt_node_rename` | rename / move |
|
|
97
|
+
| `copyFileSync(src, dest[, flags])` | `xt_node_copy_file` | copy a file; honours `COPYFILE_EXCL` |
|
|
98
|
+
| `cpSync(src, dest[, options])` | `xt_node_cp` | recursive copy; `recursive`, `force`, `errorOnExist`, `dereference`, `preserveTimestamps` |
|
|
99
|
+
| `realpathSync(path)` | `xt_node_realpath` | resolve to an absolute path |
|
|
100
|
+
| `statSync(path)` | `xt_node_stat` | file metadata object (follows symlinks) |
|
|
101
|
+
| `lstatSync(path)` | `xt_node_lstat` | file metadata object (does not follow symlinks) |
|
|
102
|
+
| `statfsSync(path)` | `xt_node_statfs` | filesystem statistics (`bsize`, `blocks`, `bfree`, …) |
|
|
103
|
+
| `accessSync(path[, mode])` | `xt_node_access` | check accessibility |
|
|
104
|
+
| `chmodSync(path, mode)` | `xt_node_chmod` | change permissions |
|
|
105
|
+
| `lchmodSync(path, mode)` | `xt_node_lchmod` | change symlink permissions |
|
|
106
|
+
| `chownSync(path, uid, gid)` | `xt_node_chown` | change ownership |
|
|
107
|
+
| `lchownSync(path, uid, gid)` | `xt_node_lchown` | change symlink ownership |
|
|
108
|
+
| `truncateSync(path[, len])` | `xt_node_truncate` | truncate a file |
|
|
109
|
+
| `utimesSync(path, atime, mtime)` | `xt_node_utimes` | set access/modification time (number of seconds or a `Date`) |
|
|
110
|
+
| `lutimesSync(path, atime, mtime)` | `xt_node_lutimes` | set symlink times |
|
|
111
|
+
| `mkdtempSync(prefix)` | `xt_node_mkdtemp` | create a unique temporary directory |
|
|
112
|
+
| `linkSync(existing, newPath)` | `xt_node_link` | hard link |
|
|
113
|
+
| `symlinkSync(target, path[, type])` | `xt_node_symlink` | symbolic link |
|
|
114
|
+
| `readlinkSync(path)` | `xt_node_readlink` | read a symbolic link target |
|
|
115
|
+
| `opendirSync(path[, options])` | `xt_node_opendir` | returns a `Dir` (`readSync` / `closeSync` / `read` / `close`) |
|
|
116
|
+
| `globSync(pattern[, options])` | `xt_node_glob` | glob matching (`*`, `?`, `[...]`, `**`), `{ cwd, withFileTypes }` |
|
|
117
|
+
| `openSync(path[, flags[, mode]])` | `xt_node_open` | open a file descriptor |
|
|
118
|
+
| `closeSync(fd)` | `xt_node_close` | close a descriptor |
|
|
119
|
+
| `readSync(fd, buffer, offset, length, position)` | `xt_node_read` | read into a `Buffer` |
|
|
120
|
+
| `writeSync(fd, data[, offset[, length[, position]]])` | `xt_node_write` | write a string / `Buffer` |
|
|
121
|
+
| `readvSync(fd, buffers[, position])` | `xt_node_readv` | scatter read |
|
|
122
|
+
| `writevSync(fd, buffers[, position])` | `xt_node_writev` | gather write |
|
|
123
|
+
| `fstatSync(fd)` | `xt_node_fstat` | `stat` for a descriptor |
|
|
124
|
+
| `fsyncSync(fd)` / `fdatasyncSync(fd)` | `xt_node_fsync` / `xt_node_fdatasync` | flush a descriptor |
|
|
125
|
+
| `ftruncateSync(fd[, len])` | `xt_node_ftruncate` | truncate a descriptor |
|
|
126
|
+
| `fchmodSync(fd, mode)` | `xt_node_fchmod` | `chmod` for a descriptor |
|
|
127
|
+
| `fchownSync(fd, uid, gid)` | `xt_node_fchown` | `chown` for a descriptor |
|
|
128
|
+
| `futimesSync(fd, atime, mtime)` | `xt_node_futimes` | `utimes` for a descriptor |
|
|
129
|
+
| `watch(filename[, options][, listener])` | `xt_node_watch` | returns an emitter-shaped watcher (never fires; see §2.6) |
|
|
130
|
+
| `watchFile(filename[, options], listener)` | `xt_node_watch_file` | polling-shaped `StatWatcher` (never fires) |
|
|
131
|
+
| `unwatchFile(filename[, listener])` | `xt_node_unwatch_file` | stop watching |
|
|
132
|
+
| `constants` | `xt_fs_constants` | `F_OK` / `R_OK` / `W_OK` / `X_OK`, `COPYFILE_*`, `O_*`, `S_IF*` (host values) |
|
|
133
|
+
| `promises` | `xt_fs_promises` | the `fs/promises` facade (see §11) |
|
|
134
|
+
|
|
135
|
+
### 2.2 Encoding support
|
|
136
|
+
|
|
137
|
+
The `options` of `readFileSync` / `writeFileSync` / `appendFileSync` may be an
|
|
138
|
+
encoding string or `{ encoding: "..." }`:
|
|
139
|
+
|
|
140
|
+
| Encoding | Read | Write |
|
|
141
|
+
| --- | --- | --- |
|
|
142
|
+
| default / `utf8` / `utf-8` / `ascii` / `latin1` / `binary` | raw UTF-8 text | write as text bytes |
|
|
143
|
+
| `hex` | lowercase hex string | parse hex then write |
|
|
144
|
+
| `base64` | Base64 string | parse Base64 then write |
|
|
145
|
+
| `base64url` | Base64url string | parse Base64url then write |
|
|
146
|
+
| `utf16le` / `ucs2` | raw bytes read as text (no UTF-16 decoding) | write as UTF-8 text |
|
|
147
|
+
|
|
148
|
+
> `readFileSync` still returns a **string** by default rather than a `Buffer`,
|
|
149
|
+
> even though the `Buffer` class exists, so that `console.log(readFileSync(p))`
|
|
150
|
+
> keeps printing text.
|
|
151
|
+
|
|
152
|
+
### 2.3 `statSync` return structure
|
|
153
|
+
|
|
154
|
+
Returns a plain object with numeric properties: `size`, `mode`, `uid`, `gid`, `dev`, `ino`, `nlink`, `rdev`, `blksize`, `blocks`, `atimeMs`, `mtimeMs`, `ctimeMs`, `birthtimeMs`.
|
|
155
|
+
Methods (native closures, callable): `isFile()`, `isDirectory()`, `isSymbolicLink()`, `isFIFO()`, `isSocket()`, `isBlockDevice()`, `isCharacterDevice()`.
|
|
156
|
+
|
|
157
|
+
### 2.4 How to call
|
|
158
|
+
|
|
159
|
+
`fs` exports are reached through an `import` (or the `node:fs` alias), not as bare
|
|
160
|
+
globals:
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
164
|
+
|
|
165
|
+
const text = readFileSync("examples/data.txt");
|
|
166
|
+
writeFileSync("/tmp/out.txt", text);
|
|
167
|
+
console.log(existsSync("/tmp/out.txt"));
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### 2.5 Error handling
|
|
171
|
+
|
|
172
|
+
On failure the functions **throw** a Node-shaped `Error` object carrying
|
|
173
|
+
`name` (`Error`), `message`, `code` (e.g. `ENOENT`), `errno` (the numeric
|
|
174
|
+
`errno`), `syscall` and `path`. `existsSync` still returns a boolean and never
|
|
175
|
+
throws.
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
import { readFileSync } from "fs";
|
|
179
|
+
try {
|
|
180
|
+
readFileSync("/does/not/exist");
|
|
181
|
+
} catch (error) {
|
|
182
|
+
console.log((error as any).code); // ENOENT
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### 2.6 Deviations from Node
|
|
187
|
+
|
|
188
|
+
- **No asynchronous I/O scheduler** (the event loop is a `select(2)` reactor
|
|
189
|
+
with timers and sockets but no callback-style `fs` backend), so the
|
|
190
|
+
callback-style `fs` functions (`readFile`, `writeFile`, `open`, …) are *not*
|
|
191
|
+
provided; use `fs/promises` or the `*Sync` forms.
|
|
192
|
+
- `watch` / `watchFile` / `unwatchFile` return API-shaped emitter objects whose
|
|
193
|
+
`.close()` / `.on()` methods exist but which **never emit** events.
|
|
194
|
+
- `Dir.read(cb)` / `Dir.close(cb)` invoke the callback **synchronously**.
|
|
195
|
+
- `readFileSync` returns a string by default instead of a `Buffer`.
|
|
196
|
+
- `utf16le` / `ucs2` are treated as raw bytes on read (no UTF-16 decoding).
|
|
197
|
+
- `mkdtempSync` appends 6 random characters to the prefix regardless of whether
|
|
198
|
+
it ends in `XXXXXX`.
|
|
199
|
+
- `globSync` supports `*`, `?`, `[...]` and `**` but not the `exclude` callback
|
|
200
|
+
or `follow`; `**` does not descend through symlinks (matching Node's default).
|
|
201
|
+
- `cpSync` is implemented on top of the synchronous helpers; symlinks are copied
|
|
202
|
+
as symlinks unless `dereference: true` is set.
|
|
203
|
+
- **Windows**: `readlinkSync` raises `ENOSYS`; `chmodSync` / `lchmodSync` /
|
|
204
|
+
`chownSync` / `lchownSync` / `fchmodSync` / `fchownSync` are no-ops;
|
|
205
|
+
`statfsSync` returns zeroed fields.
|
|
206
|
+
- **macOS / Windows**: `lutimesSync` falls back to `utimesSync`.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## 3. The `path` module (implemented)
|
|
211
|
+
|
|
212
|
+
Location: `src/extensions/node/path/index.ts`, `runtime/ext_node/path/path.c`
|
|
213
|
+
|
|
214
|
+
Uses `path.<name>(...)` namespace calls, which the compiler lowers to
|
|
215
|
+
`xt_path_static(<name>, argc, argv)`. Results are produced with the POSIX `/`
|
|
216
|
+
separator on every platform (Windows accepts `/`), while inputs may use native
|
|
217
|
+
Windows separators: on Windows both `/` and `\` are recognised and drive
|
|
218
|
+
prefixes (`C:`) are preserved, so the self-hosted compiler resolves
|
|
219
|
+
drive-letter paths correctly.
|
|
220
|
+
Import the module as a namespace (`import path from "path"` / `import * as path
|
|
221
|
+
from "path"`) or pull in individual methods (`import { join } from "path"`).
|
|
222
|
+
|
|
223
|
+
| Method | Notes |
|
|
224
|
+
| --- | --- |
|
|
225
|
+
| `path.join(...parts)` | join and normalize |
|
|
226
|
+
| `path.resolve(...parts)` | resolve to an absolute path |
|
|
227
|
+
| `path.normalize(path)` | normalize |
|
|
228
|
+
| `path.dirname(path)` | directory name |
|
|
229
|
+
| `path.basename(path[, ext])` | file name, optionally without extension |
|
|
230
|
+
| `path.extname(path)` | extension |
|
|
231
|
+
| `path.isAbsolute(path)` | whether it is an absolute path |
|
|
232
|
+
| `path.relative(from, to)` | relative path |
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
import path from "path";
|
|
236
|
+
import { basename } from "path";
|
|
237
|
+
|
|
238
|
+
console.log(path.join("a", "b", "..", "c")); // a/c
|
|
239
|
+
console.log(basename("/x/y/z.txt")); // z.txt
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## 4. The `os` module (implemented)
|
|
245
|
+
|
|
246
|
+
Location: `src/extensions/node/os/index.ts`, `runtime/ext_node/os/os.c`
|
|
247
|
+
|
|
248
|
+
Uses `os.<name>(...)` namespace calls, lowered to `xt_os_static(<name>, argc, argv)`.
|
|
249
|
+
Import the module as a namespace (`import os from "os"`) or pull in individual
|
|
250
|
+
functions (`import { platform } from "os"`).
|
|
251
|
+
|
|
252
|
+
| Method | Notes |
|
|
253
|
+
| --- | --- |
|
|
254
|
+
| `os.platform()` | `darwin` / `linux` / `win32` / ... |
|
|
255
|
+
| `os.arch()` | `x64` / `arm64` / `ia32` / `arm` |
|
|
256
|
+
| `os.type()` | `Darwin` / `Linux` / `Windows_NT` / ... |
|
|
257
|
+
| `os.release()` | kernel version |
|
|
258
|
+
| `os.endianness()` | `LE` / `BE` |
|
|
259
|
+
| `os.homedir()` | user home directory |
|
|
260
|
+
| `os.tmpdir()` | temporary directory |
|
|
261
|
+
| `os.hostname()` | hostname |
|
|
262
|
+
| `os.totalmem()` / `os.freemem()` | total / free memory (bytes) |
|
|
263
|
+
| `os.cpus()` | array of CPU entries (`model` / `speed` placeholders) |
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## 5. The `process` object (implemented)
|
|
268
|
+
|
|
269
|
+
Location: `src/extensions/node/process/index.ts`, `runtime/ext_node/process/process.c`
|
|
270
|
+
|
|
271
|
+
Method calls lower to `xt_process_call(<name>, argc, argv)`, property access to `xt_process_get(<name>)`.
|
|
272
|
+
Import the object (`import process from "process"`) to reach these.
|
|
273
|
+
|
|
274
|
+
| Method / property | Notes |
|
|
275
|
+
| --- | --- |
|
|
276
|
+
| `process.cwd()` | current working directory |
|
|
277
|
+
| `process.exit([code])` | exit the process |
|
|
278
|
+
| `process.uptime()` | process uptime (seconds) |
|
|
279
|
+
| `process.hrtime()` | `[seconds, nanoseconds]` array |
|
|
280
|
+
| `process.getuid()` | user ID (returns 0 on Windows) |
|
|
281
|
+
| `process.platform` / `process.arch` | platform / architecture |
|
|
282
|
+
| `process.pid` / `process.ppid` | process ID / parent process ID |
|
|
283
|
+
| `process.argv` | argument array (`argv[0]` is the executable) |
|
|
284
|
+
| `process.env` | environment variable object |
|
|
285
|
+
| `process.version` / `process.title` | placeholder strings |
|
|
286
|
+
|
|
287
|
+
> `argv` is captured by the generated `main` via `xt_set_program_args` and provided to the runtime.
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## 6. The `buffer` module (implemented)
|
|
292
|
+
|
|
293
|
+
Location: `src/extensions/node/buffer/index.ts`, `runtime/ext_node/buffer/buffer.c`
|
|
294
|
+
|
|
295
|
+
xbintsc has no native binary value type, so `Buffer` is represented as a
|
|
296
|
+
**plain object**: each byte is a numeric property `"0".."n-1"`, plus a `length`
|
|
297
|
+
property, sharing the `xt_buffer_proto()` prototype that provides instance
|
|
298
|
+
methods. `xt_node_is_buffer` / `xt_node_buffer_bytes` let other modules access
|
|
299
|
+
bytes across modules.
|
|
300
|
+
|
|
301
|
+
| Static method | Notes |
|
|
302
|
+
| --- | --- |
|
|
303
|
+
| `Buffer.from(value[, encoding])` | construct from a string (hex / base64 / utf8), array or Buffer |
|
|
304
|
+
| `Buffer.alloc(size[, fill])` | allocate and fill |
|
|
305
|
+
| `Buffer.allocUnsafe(size)` | allocate |
|
|
306
|
+
| `Buffer.isBuffer(value)` | test |
|
|
307
|
+
| `Buffer.byteLength(value[, encoding])` | byte length |
|
|
308
|
+
| `Buffer.concat(list[, totalLength])` | concatenate |
|
|
309
|
+
| `Buffer.compare(a, b)` | compare |
|
|
310
|
+
|
|
311
|
+
Instance methods: `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()`, plus `readUInt8/UInt16LE/UInt16BE/UInt32LE/UInt32BE`, `writeUInt8/UInt16LE/UInt16BE/UInt32LE/UInt32BE`.
|
|
312
|
+
|
|
313
|
+
```ts
|
|
314
|
+
const buf = Buffer.from("hello");
|
|
315
|
+
console.log(buf.toString(), buf.length); // hello 5
|
|
316
|
+
console.log(Buffer.alloc(4, 65).toString()); // AAAA
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## 7. The `stream` module (implemented)
|
|
322
|
+
|
|
323
|
+
Location: `src/extensions/node/stream/index.ts`, `runtime/ext_node/stream/stream.c`
|
|
324
|
+
|
|
325
|
+
`Readable` / `Writable` / `Duplex` / `Transform` / `PassThrough` are used as
|
|
326
|
+
**global constructors** (`new Readable()` etc.); statics such as
|
|
327
|
+
`stream.Readable.from(...)` are resolved through the `stream` namespace. Streams
|
|
328
|
+
are EventEmitters with a **synchronous event model**: `on('data')` flushes the
|
|
329
|
+
`push` buffer, and `write` delivers immediately.
|
|
330
|
+
|
|
331
|
+
| Method | Notes |
|
|
332
|
+
| --- | --- |
|
|
333
|
+
| `push(chunk)` / `read([n])` | Readable side |
|
|
334
|
+
| `write(chunk)` / `end([chunk])` | Writable side |
|
|
335
|
+
| `pipe(destination)` | forward data |
|
|
336
|
+
| `on('data' / 'end' / 'finish')` | events |
|
|
337
|
+
| `pause()` / `resume()` / `setEncoding(enc)` / `destroy()` | flow control |
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## 8. The `net` module (implemented)
|
|
342
|
+
|
|
343
|
+
Location: `src/extensions/node/net/index.ts`, `runtime/ext_node/net/net.c`
|
|
344
|
+
|
|
345
|
+
TCP server and client, built on the core event loop.
|
|
346
|
+
|
|
347
|
+
| API | Notes |
|
|
348
|
+
| --- | --- |
|
|
349
|
+
| `net.createServer([connectionListener])` | create a TCP server (equivalent to the `Server` constructor) |
|
|
350
|
+
| `net.connect(...)` / `net.createConnection(...)` | connect (blocking connect, then registers with the event loop) |
|
|
351
|
+
| `net.isIP(s)` / `net.isIPv4(s)` / `net.isIPv6(s)` | address test |
|
|
352
|
+
|
|
353
|
+
`Server`: `listen(port[, host][, cb])`, `close([cb])`, `address()`, `getConnections(cb)`, events `listening` / `connection` / `close`.
|
|
354
|
+
|
|
355
|
+
`Socket`: `write(data[, cb])`, `end([data])`, `destroy()`, `address()`, `setEncoding(enc)`, `pause()` / `resume()`, events `data` / `end` / `close` / `connect` / `error`.
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## 9. The `dgram` module (implemented)
|
|
360
|
+
|
|
361
|
+
Location: `src/extensions/node/dgram/index.ts`, `runtime/ext_node/dgram/dgram.c`
|
|
362
|
+
|
|
363
|
+
UDP sockets. `dgram.createSocket(type | options[, cb])` returns an EventEmitter.
|
|
364
|
+
|
|
365
|
+
| Method | Notes |
|
|
366
|
+
| --- | --- |
|
|
367
|
+
| `bind([port][, address][, cb])` | bind (`send` auto-binds if unbound) |
|
|
368
|
+
| `send(msg[, offset, length,] port[, address][, cb])` | send a datagram |
|
|
369
|
+
| `close([cb])` / `address()` | close / query address |
|
|
370
|
+
| `setBroadcast(b)` / `setTTL(n)` / `setMulticastTTL(n)` | socket options |
|
|
371
|
+
| `on('message', (msg, rinfo) => ...)` | receive a datagram; `rinfo` has `address` / `port` / `family` / `size` |
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## 10. The `http` module (implemented)
|
|
376
|
+
|
|
377
|
+
Location: `src/extensions/node/http/index.ts`, `runtime/ext_node/http/http.c`
|
|
378
|
+
|
|
379
|
+
The server wraps a `net` server: each connection accumulates bytes until a
|
|
380
|
+
complete request (request line + headers + `Content-Length` body) is available,
|
|
381
|
+
then invokes the `request` listener with `req`/`res`. The client wraps a `net`
|
|
382
|
+
socket, writes an HTTP/1.1 request and parses the response after the connection
|
|
383
|
+
closes.
|
|
384
|
+
|
|
385
|
+
| API | Notes |
|
|
386
|
+
| --- | --- |
|
|
387
|
+
| `http.createServer([requestListener])` | create an HTTP server |
|
|
388
|
+
| `http.request(options[, cb])` | create a `ClientRequest` (`write` / `end` / `setHeader`) |
|
|
389
|
+
| `http.get(url[, cb])` | issue a GET |
|
|
390
|
+
|
|
391
|
+
`IncomingMessage` (`req` / response): `method`, `url`, `httpVersion`, `headers`, `statusCode`, `data` / `end` events, `setEncoding`.
|
|
392
|
+
|
|
393
|
+
`ServerResponse` (`res`): `writeHead(status[, message][, headers])`, `setHeader` / `getHeader` / `removeHeader` / `getHeaders`, `write(chunk)`, `end([chunk])`, events `finish` / `close`. Responses always carry `Connection: close` (no keep-alive).
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## 11. The `fs/promises` module (implemented)
|
|
398
|
+
|
|
399
|
+
Location: `src/extensions/node/fs-promises/index.ts`, `runtime/ext_node/fs/promises.c`
|
|
400
|
+
|
|
401
|
+
There is no asynchronous I/O scheduler, so each function wraps the corresponding
|
|
402
|
+
synchronous `fs` implementation in an **already-settled Promise**. Failures
|
|
403
|
+
**reject** with the same Node-shaped `Error` (with `code` / `errno` / `syscall` /
|
|
404
|
+
`path`) that the synchronous form throws. `fs.promises` is also reachable from
|
|
405
|
+
the `fs` module (`import { promises as fsp } from "fs"`), and both namespaces
|
|
406
|
+
expose a `constants` object.
|
|
407
|
+
|
|
408
|
+
Promise exports: `readFile`, `writeFile`, `appendFile`, `mkdir`, `readdir`,
|
|
409
|
+
`rm`, `unlink`, `rmdir`, `rename`, `copyFile`, `cp`, `realpath`, `stat`,
|
|
410
|
+
`lstat`, `statfs`, `access`, `open`, `chmod`, `lchmod`, `chown`, `lchown`,
|
|
411
|
+
`truncate`, `utimes`, `lutimes`, `link`, `symlink`, `readlink`, `mkdtemp`,
|
|
412
|
+
`opendir`, `glob`, `watch`.
|
|
413
|
+
|
|
414
|
+
`open(...)` resolves to a **`FileHandle`** with:
|
|
415
|
+
`read`, `write`, `readFile`, `writeFile`, `appendFile`, `close`, `stat`,
|
|
416
|
+
`truncate`, `chmod`, `chown`, `utimes`, `sync`, `datasync`.
|
|
417
|
+
|
|
418
|
+
```ts
|
|
419
|
+
import { readFile, writeFile, open } from "fs/promises";
|
|
420
|
+
|
|
421
|
+
async function main(): Promise<void> {
|
|
422
|
+
await writeFile("/tmp/a.txt", "hi");
|
|
423
|
+
console.log(await readFile("/tmp/a.txt"));
|
|
424
|
+
const handle = await open("/tmp/a.txt", "r");
|
|
425
|
+
console.log(await handle.readFile("utf8"));
|
|
426
|
+
await handle.close();
|
|
427
|
+
}
|
|
428
|
+
main();
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
### 11.1 Deviations from Node
|
|
432
|
+
|
|
433
|
+
- Because I/O is synchronous, the Promise settles before the returned value is
|
|
434
|
+
awaited (the event loop does not yield).
|
|
435
|
+
- `FileHandle.appendFile` behaves like `writeFile` (it writes at the current
|
|
436
|
+
file position rather than appending).
|
|
437
|
+
- `FileHandle.readFile()` reads from the current file-descriptor offset.
|
|
438
|
+
- `Dir.read` / `Dir.close` (both the sync and promise/callback forms) complete
|
|
439
|
+
immediately.
|
|
440
|
+
- `watch` resolves to the same never-emitting watcher object as `fs.watch`.
|
|
441
|
+
|
|
442
|
+
---
|
|
443
|
+
|
|
444
|
+
## 12. The `child_process` module (implemented)
|
|
445
|
+
|
|
446
|
+
Location: `src/extensions/node/child_process/index.ts`, `runtime/ext_node/child_process/child_process.c`
|
|
447
|
+
|
|
448
|
+
`spawnSync(command, args[, options])` runs a program to completion and returns
|
|
449
|
+
`{ status, stdout, stderr }`. `options.cwd` sets the working directory and
|
|
450
|
+
`options.stdio: "inherit"` hands the child the parent's stdout/stderr (used by
|
|
451
|
+
`xbintsc run`, so a compiled program's output streams live); otherwise
|
|
452
|
+
stdout/stderr are captured as UTF-8 strings.
|
|
453
|
+
|
|
454
|
+
| Option | Notes |
|
|
455
|
+
| --- | --- |
|
|
456
|
+
| `cwd` | working directory for the child |
|
|
457
|
+
| `stdio: "inherit"` | share the parent's stdout/stderr instead of capturing |
|
|
458
|
+
| `encoding` | accepted and ignored (output is always decoded as UTF-8) |
|
|
459
|
+
|
|
460
|
+
```ts
|
|
461
|
+
import { spawnSync } from "child_process";
|
|
462
|
+
|
|
463
|
+
const result = spawnSync("clang", ["--version"], { encoding: "utf8" });
|
|
464
|
+
console.log(result.status, result.stdout.split("\n")[0]);
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
## 13. The `events` module (implemented)
|
|
470
|
+
|
|
471
|
+
Location: `src/extensions/node/events/index.ts`, `runtime/ext_node/events/events.c`
|
|
472
|
+
|
|
473
|
+
Provides a standalone `EventEmitter`, available both as a **global constructor**
|
|
474
|
+
(`new EventEmitter()`) and as a named export
|
|
475
|
+
(`import { EventEmitter } from "events"`). Instances share the runtime emitter
|
|
476
|
+
used by `stream` / `net` / `http` (listeners live in an internal `__xt_events`
|
|
477
|
+
property), with the fuller `events` surface layered on top:
|
|
478
|
+
|
|
479
|
+
| Method | Notes |
|
|
480
|
+
| --- | --- |
|
|
481
|
+
| `on(name, fn)` / `addListener(name, fn)` | append a listener |
|
|
482
|
+
| `once(name, fn)` | fire at most once, then remove itself |
|
|
483
|
+
| `prependListener(name, fn)` / `prependOnceListener(name, fn)` | insert at the front |
|
|
484
|
+
| `off(name, fn)` / `removeListener(name, fn)` | remove a listener |
|
|
485
|
+
| `removeAllListeners([name])` | clear one event (or all events) |
|
|
486
|
+
| `emit(name[, ...args])` | invoke listeners |
|
|
487
|
+
| `listeners(name)` / `rawListeners(name)` | listener array |
|
|
488
|
+
| `listenerCount(name)` | number of listeners |
|
|
489
|
+
| `eventNames()` | names that currently have listeners |
|
|
490
|
+
| `setMaxListeners(n)` / `getMaxListeners()` | bookkeeping (default 10) |
|
|
491
|
+
|
|
492
|
+
Statics reachable through the namespace (`import ee from "events"`):
|
|
493
|
+
`listenerCount`, `getEventListeners`, `getMaxListeners`, `setMaxListeners`,
|
|
494
|
+
`once`, `addAbortListener`.
|
|
495
|
+
|
|
496
|
+
```ts
|
|
497
|
+
import { EventEmitter } from "events";
|
|
498
|
+
|
|
499
|
+
const em = new EventEmitter();
|
|
500
|
+
em.once("ready", () => console.log("ready"));
|
|
501
|
+
em.emit("ready"); // ready
|
|
502
|
+
em.emit("ready"); // nothing: the listener already ran
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
## 14. The `util` module (implemented)
|
|
508
|
+
|
|
509
|
+
Location: `src/extensions/node/util/index.ts`, `runtime/ext_node/util/util.c`
|
|
510
|
+
|
|
511
|
+
Both named imports (`import { format } from "util"`) and namespace calls
|
|
512
|
+
(`import util from "util"` / `import * as util from "util"`) are supported.
|
|
513
|
+
|
|
514
|
+
| Function | Notes |
|
|
515
|
+
| --- | --- |
|
|
516
|
+
| `format(fmt, ...args)` | `%s` `%d` `%i` `%f` `%j` `%o` `%O` `%c` `%%` placeholders |
|
|
517
|
+
| `formatWithOptions(opts, fmt, ...args)` | options accepted and ignored |
|
|
518
|
+
| `inspect(value)` | recursive printer (depth-limited, strings quoted) |
|
|
519
|
+
| `isDeepStrictEqual(a, b)` | structural comparison (`NaN` equals `NaN`) |
|
|
520
|
+
| `inherits(ctor, superCtor)` | prototype wiring |
|
|
521
|
+
| `deprecate(fn, msg)` | returns `fn` unchanged (there is no warning channel) |
|
|
522
|
+
| `promisify(fn)` | wraps a trailing-callback function into a `Promise` |
|
|
523
|
+
| `isString` `isNumber` `isBoolean` `isUndefined` `isNull` `isFunction` `isArray` `isObject` `isBuffer` `isDate` `isRegExp` `isPromise` `isError` | type predicates |
|
|
524
|
+
|
|
525
|
+
```ts
|
|
526
|
+
import { format, promisify } from "util";
|
|
527
|
+
|
|
528
|
+
console.log(format("%s=%d", "n", 3)); // n=3
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
---
|
|
532
|
+
|
|
533
|
+
## 15. The `querystring` module (implemented)
|
|
534
|
+
|
|
535
|
+
Location: `src/extensions/node/querystring/index.ts`, `runtime/ext_node/querystring/querystring.c`
|
|
536
|
+
|
|
537
|
+
| Function | Notes |
|
|
538
|
+
| --- | --- |
|
|
539
|
+
| `parse(str[, sep[, eq]])` / `decode` | parse into an object; repeated keys become arrays |
|
|
540
|
+
| `stringify(obj[, sep[, eq]])` / `encode` | serialize; spaces become `+`, arrays repeat the key |
|
|
541
|
+
| `escape(str)` / `unescape(str)` | percent-encode / decode (`+` decodes to a space) |
|
|
542
|
+
|
|
543
|
+
Defaults: `sep = "&"`, `eq = "="`.
|
|
544
|
+
|
|
545
|
+
```ts
|
|
546
|
+
import { parse, stringify } from "querystring";
|
|
547
|
+
|
|
548
|
+
const q = parse("a=1&b=2&b=3"); // { a: "1", b: ["2", "3"] }
|
|
549
|
+
console.log(stringify({ x: "a b" })); // x=a+b
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
## 16. Implemented Node capabilities quick reference
|
|
555
|
+
|
|
556
|
+
| Category | Contents |
|
|
557
|
+
| --- | --- |
|
|
558
|
+
| Extension registration | `nodeExtension` (`--ext node`), `NodeModule` interface, `resolveFrom` utility |
|
|
559
|
+
| fs read | `readFileSync`, `readTextFile` (`xt_node_read_text_file`), supports hex / base64 / base64url |
|
|
560
|
+
| fs write | `writeFileSync`, `appendFileSync`, supports hex / base64 / base64url; string or `Buffer` |
|
|
561
|
+
| fs directories | `readdirSync` (`withFileTypes` / `recursive`), `mkdirSync`, `rmSync`, `unlinkSync`, `rmdirSync`, `opendirSync` (`Dir`), `globSync`, `mkdtempSync` |
|
|
562
|
+
| fs other | `existsSync`, `renameSync`, `copyFileSync`, `cpSync`, `realpathSync`, `statSync`, `lstatSync`, `statfsSync`, `accessSync`, `chmodSync`, `chownSync`, `lchmodSync`, `lchownSync`, `truncateSync`, `utimesSync`, `lutimesSync`, `linkSync`, `symlinkSync`, `readlinkSync`, `watch`, `watchFile`, `unwatchFile` |
|
|
563
|
+
| fs descriptors | `openSync`, `closeSync`, `readSync`, `writeSync`, `readvSync`, `writevSync`, `fstatSync`, `fsyncSync`, `fdatasyncSync`, `ftruncateSync`, `fchmodSync`, `fchownSync`, `futimesSync` |
|
|
564
|
+
| fs constants | `constants` (`F_OK`, `R_OK`, `W_OK`, `X_OK`, `COPYFILE_*`, `O_*`, `S_IF*`) |
|
|
565
|
+
| path | `join` `resolve` `normalize` `dirname` `basename` `extname` `isAbsolute` `relative` |
|
|
566
|
+
| os | `platform` `arch` `type` `release` `endianness` `homedir` `tmpdir` `hostname` `totalmem` `freemem` `cpus` |
|
|
567
|
+
| process | `cwd` `exit` `uptime` `hrtime` `getuid`; `platform` `arch` `pid` `ppid` `argv` `env` `version` `title` |
|
|
568
|
+
| buffer | `Buffer.from/alloc/allocUnsafe/isBuffer/byteLength/concat/compare`; instances `toString/toJSON/slice/.../readUInt32BE/writeUInt32BE` |
|
|
569
|
+
| stream | `Readable` `Writable` `Duplex` `Transform` `PassThrough`; `push/read/write/end/pipe/on` |
|
|
570
|
+
| net | `createServer` `connect` `createConnection` `isIP/isIPv4/isIPv6`; `Server` `Socket` |
|
|
571
|
+
| dgram | `createSocket`; `bind/send/close/address/setBroadcast/setTTL` |
|
|
572
|
+
| http | `createServer` `request` `get`; `ClientRequest`, `IncomingMessage`, `ServerResponse` |
|
|
573
|
+
| child_process | `spawnSync(command, args[, {cwd, stdio}])` returning `status` / `stdout` / `stderr` |
|
|
574
|
+
| assert | `ok/equal/notEqual/strictEqual/notStrictEqual/deepStrictEqual/notDeepStrictEqual/throws/doesNotThrow/ifError/match/doesNotMatch/fail` (`import assert from "node:assert"`) |
|
|
575
|
+
| test | `test(name, fn)` / `it` / `describe` / `skip` / `todo` (`import test from "node:test"`), TAP output, non-zero exit on failure |
|
|
576
|
+
| zlib | `createGzip()` (consumed by `stream/promises` pipeline) |
|
|
577
|
+
| stream/promises | `pipeline(...)` (synchronous drain, returns a resolved Promise) |
|
|
578
|
+
| worker_threads | `Worker`, `isMainThread`, `workerData`, `parentPort` (re-executes the binary as a child process) |
|
|
579
|
+
| events | `EventEmitter` (global + named); `on/once/off/emit/listeners/listenerCount/eventNames`; statics `listenerCount/getEventListeners/getMaxListeners/setMaxListeners/once/addAbortListener` |
|
|
580
|
+
| util | `format` `formatWithOptions` `inspect` `isDeepStrictEqual` `inherits` `deprecate` `promisify`; `isString/isNumber/isBoolean/isUndefined/isNull/isFunction/isArray/isObject/isBuffer/isDate/isRegExp/isPromise/isError` |
|
|
581
|
+
| querystring | `parse`/`decode` `stringify`/`encode` `escape` `unescape` |
|
|
582
|
+
| crypto | `createHash(algorithm)` with `update`/`digest` and the streaming API (`setEncoding`/`write`/`end`/`read`); SHA-1 and SHA-256 |
|
|
583
|
+
| globals | `btoa` / `atob` base64 helpers; timers `setTimeout` / `clearTimeout` / `setInterval` / `clearInterval` (numeric ids, no `Timeout` object) |
|
|
584
|
+
| url | `pathToFileURL` `fileURLToPath` |
|
|
585
|
+
| 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` |
|
|
586
|
+
| Event loop | `xt_loop` (`select` reactor), `xt_run_event_loop()`, `xt_loop_add/update/remove`, timer queue (`xt_set_timeout` / `xt_set_interval` / `xt_clear_*`) |
|
|
587
|
+
| Calling convention | uniform `(argc, argv)` ABI, returns `xt_value` |
|
|
588
|
+
| Linking | after registration, compiles `runtime/ext_node/**` and links it with the runtime |
|