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.
Files changed (100) hide show
  1. package/AGENTS.md +5 -3
  2. package/dist/src/driver/compiler.js +1 -1
  3. package/dist/src/driver/compiler.js.map +1 -1
  4. package/dist/src/driver/runtime-objects.d.ts +1 -1
  5. package/dist/src/driver/runtime-objects.js +1 -0
  6. package/dist/src/driver/runtime-objects.js.map +1 -1
  7. package/dist/src/driver/version.d.ts +1 -1
  8. package/dist/src/driver/version.js +1 -1
  9. package/dist/src/extensions/node/fs/index.d.ts +4 -3
  10. package/dist/src/extensions/node/fs/index.js +12 -3
  11. package/dist/src/extensions/node/fs/index.js.map +1 -1
  12. package/dist/src/extensions/node/fs-promises/index.d.ts +5 -5
  13. package/dist/src/extensions/node/fs-promises/index.js +15 -6
  14. package/dist/src/extensions/node/fs-promises/index.js.map +1 -1
  15. package/dist/tests/e2e/async-await.test.js +1 -1
  16. package/dist/tests/e2e/async-fs.test.d.ts +9 -0
  17. package/dist/tests/e2e/async-fs.test.js +119 -0
  18. package/dist/tests/e2e/async-fs.test.js.map +1 -0
  19. package/dist/tests/e2e/fetch.test.js +24 -0
  20. package/dist/tests/e2e/fetch.test.js.map +1 -1
  21. package/dist/tests/e2e/gui-inline-svg.test.d.ts +11 -0
  22. package/dist/tests/e2e/gui-inline-svg.test.js +160 -0
  23. package/dist/tests/e2e/gui-inline-svg.test.js.map +1 -0
  24. package/doc/ai/contributing.md +2 -1
  25. package/doc/ai/extensions.md +4 -3
  26. package/doc/ai/language-support.md +2 -1
  27. package/doc/ai/zh-CN/contributing.md +1 -1
  28. package/doc/ai/zh-CN/extensions.md +4 -3
  29. package/doc/ai/zh-CN/language-support.md +2 -1
  30. package/doc/gui/api.md +8 -0
  31. package/doc/gui/known-issues.md +10 -9
  32. package/doc/gui/media.md +32 -3
  33. package/doc/gui.md +24 -2
  34. package/doc/implemented/async.md +16 -3
  35. package/doc/implemented/fetch.md +38 -6
  36. package/doc/implemented/node/fs-promises.md +19 -8
  37. package/doc/implemented/node.md +1 -1
  38. package/doc/implemented.md +1 -1
  39. package/doc/unimplemented/deviations.md +1 -1
  40. package/doc/unimplemented/node/async.md +6 -3
  41. package/doc/unimplemented/node/fs-promises.md +10 -6
  42. package/doc/unimplemented/node/fs.md +7 -8
  43. package/doc/unimplemented/node.md +2 -2
  44. package/doc/unimplemented/toolchain.md +1 -1
  45. package/doc/zh-CN/gui/api.md +7 -0
  46. package/doc/zh-CN/gui/known-issues.md +8 -7
  47. package/doc/zh-CN/gui/media.md +26 -2
  48. package/doc/zh-CN/gui.md +18 -1
  49. package/doc/zh-CN/implemented/async.md +13 -2
  50. package/doc/zh-CN/implemented/fetch.md +23 -4
  51. package/doc/zh-CN/implemented/node/fs-promises.md +6 -3
  52. package/doc/zh-CN/implemented/node.md +1 -1
  53. package/doc/zh-CN/implemented.md +1 -1
  54. package/doc/zh-CN/unimplemented/deviations.md +1 -1
  55. package/doc/zh-CN/unimplemented/node/async.md +6 -3
  56. package/doc/zh-CN/unimplemented/node/fs-promises.md +4 -4
  57. package/doc/zh-CN/unimplemented/node/fs.md +2 -2
  58. package/doc/zh-CN/unimplemented/node.md +2 -2
  59. package/doc/zh-CN/unimplemented/toolchain.md +1 -1
  60. package/package.json +1 -1
  61. package/runtime/ext_gui/inline_svg.cpp +219 -0
  62. package/runtime/ext_gui/inline_svg.h +41 -0
  63. package/runtime/ext_gui/layout.cpp +18 -0
  64. package/runtime/ext_gui/layout.h +7 -0
  65. package/runtime/ext_gui/layout_flow.cpp +4 -3
  66. package/runtime/ext_gui/paint.cpp +14 -0
  67. package/runtime/ext_gui/paint.h +5 -1
  68. package/runtime/ext_gui/renderer_image.cpp +53 -25
  69. package/runtime/ext_gui/style_ua.cpp +3 -0
  70. package/runtime/ext_gui/svg.cpp +122 -39
  71. package/runtime/ext_gui/svg.h +14 -3
  72. package/runtime/ext_gui/window.cpp +28 -0
  73. package/runtime/ext_node/fs/async_api.c +314 -0
  74. package/runtime/ext_node/fs/async_complete.c +99 -0
  75. package/runtime/ext_node/fs/async_fh.c +206 -0
  76. package/runtime/ext_node/fs/async_job.c +81 -0
  77. package/runtime/ext_node/fs/async_job.h +132 -0
  78. package/runtime/ext_node/fs/async_worker.c +534 -0
  79. package/runtime/ext_node/fs/async_worker_dir.c +439 -0
  80. package/runtime/ext_node/fs/async_worker_dir.h +33 -0
  81. package/runtime/ext_node/fs/async_worker_fd.c +74 -0
  82. package/runtime/ext_node/fs/dir.c +60 -15
  83. package/runtime/ext_node/fs/fs_common.h +9 -0
  84. package/runtime/ext_node/fs/fs_ops.c +18 -29
  85. package/runtime/ext_node/fs/parts/builtins.inc +34 -0
  86. package/runtime/ext_node/fs/parts/platform.inc +66 -0
  87. package/runtime/ext_node/fs/promises.c +44 -234
  88. package/runtime/rt_internal.h +2 -0
  89. package/runtime/xt_async_io.c +333 -0
  90. package/runtime/xt_async_io.h +47 -0
  91. package/runtime/xt_fetch/async.inc +295 -0
  92. package/runtime/xt_fetch/request.inc +6 -183
  93. package/runtime/xt_fetch/socket.inc +5 -4
  94. package/runtime/xt_fetch.c +6 -4
  95. package/runtime/xt_loop.c +44 -3
  96. package/src/driver/compiler.ts +1 -1
  97. package/src/driver/runtime-objects.ts +1 -0
  98. package/src/driver/version.ts +1 -1
  99. package/src/extensions/node/fs/index.ts +12 -3
  100. package/src/extensions/node/fs-promises/index.ts +15 -6
@@ -2,15 +2,19 @@
2
2
 
3
3
  > Part of [Node extension: unimplemented](../node.md) · [简体中文](../../zh-CN/unimplemented/node/fs-promises.md)
4
4
 
5
- `fs/promises` wraps each synchronous `fs` call in an already-settled promise
6
- (the implemented surface is in
7
- [implemented: `fs/promises`](../../implemented/node/fs-promises.md)).
5
+ `fs/promises` now offloads its blocking I/O to the async I/O pool (the
6
+ implemented surface is in
7
+ [implemented: `fs/promises`](../../implemented/node/fs-promises.md)); the
8
+ remaining differences are behavioural:
8
9
 
9
- - I/O is synchronous: the promise is settled before it is awaited, so awaiting
10
- it does not yield to the event loop.
11
10
  - `FileHandle.appendFile` behaves like `writeFile` (it writes at the current
12
11
  file position instead of appending).
13
12
  - `FileHandle.readFile()` reads from the current file-descriptor offset.
14
- - `Dir.read` / `Dir.close` (sync and promise forms) complete immediately.
13
+ - `Dir.read` / `Dir.close` (sync and promise forms) complete their callbacks
14
+ immediately; `Dir.readSync` / `closeSync` remain synchronous.
15
15
  - `watch` resolves to the same never-emitting watcher as `fs.watch`; there is no
16
16
  real file-watching backend.
17
+ - Reads and writes are whole-file/one-shot operations; there are no streaming
18
+ `FileHandle` variants and no `AbortSignal` cancellation.
19
+ - The pool has four workers; very many simultaneous operations queue behind
20
+ them (they still do not block the event loop).
@@ -2,14 +2,13 @@
2
2
 
3
3
  > Part of [Node extension: unimplemented](../node.md) · [简体中文](../../zh-CN/unimplemented/node/fs.md)
4
4
 
5
- `fs` now implements the **synchronous** API surface (files, directories,
6
- descriptors, metadata, links, `cp`, `glob`, `Dir`, `constants`) and
7
- `fs/promises` wraps each synchronous function in an already-settled Promise
5
+ `fs` implements the **synchronous** API surface (files, directories,
6
+ descriptors, metadata, links, `cp`, `glob`, `Dir`, `constants`), and
7
+ `fs/promises` runs every file/descriptor operation on the asynchronous I/O pool
8
8
  (see [implemented: `fs`](../../implemented/node/fs.md) and
9
- [implemented: `fs/promises`](../../implemented/node/fs-promises.md)). The rest is still
10
- unimplemented because xbintsc has **no asynchronous I/O scheduler** for file
11
- operations (the `fs` module has no reactor backend; the core event loop does
12
- provide timers and sockets):
9
+ [implemented: `fs/promises`](../../implemented/node/fs-promises.md)). What is
10
+ still missing is mostly about APIs that need a different backend or callback
11
+ plumbing:
13
12
 
14
13
  | Unimplemented API | Category |
15
14
  | --- | --- |
@@ -24,7 +23,7 @@ provide timers and sockets):
24
23
  - `readFileSync` supports encoding options (default/`utf8`/`ascii`/`latin1`/`binary`/ `hex`/`base64`/`base64url`), but **does not return a `Buffer`** by default: even though `Buffer` exists (simulated as a plain object), `readFileSync` still returns a string. Pass a `Buffer`-producing path or read raw bytes explicitly.
25
24
  - `utf16le` / `ucs2` decoding is not implemented (the bytes are returned as text).
26
25
  - `watch` / `watchFile` / `unwatchFile` return API-shaped emitter objects whose `.close()` / `.on()` methods exist but which **never fire** events.
27
- - `Dir.read(cb)` / `Dir.close(cb)` and the async form of `FileHandle` methods complete **synchronously** (the callback/Promise is invoked immediately).
26
+ - `Dir.read(cb)` / `Dir.close(cb)` complete **synchronously** (the callback is invoked immediately); `FileHandle` methods do return real promises now.
28
27
  - `mkdtempSync` always appends 6 random characters to the prefix (it does not require a trailing `XXXXXX`).
29
28
  - `globSync` supports `*`, `?`, `[...]` and `**` but not the `exclude` callback or `follow`; `**` does not descend through symlinks (matching Node's default).
30
29
  - `cpSync` symlink handling follows Node for the common cases but `verbatimSymlinks` is not supported.
@@ -10,10 +10,10 @@ is missing or differs from Node.
10
10
  ## Contents
11
11
 
12
12
  - [`fs`](./node/fs.md) — callback-style async operations, real file watching, option callbacks
13
- - [`fs/promises`](./node/fs-promises.md) — synchronous I/O behind a settled promise, `FileHandle` deviations
13
+ - [`fs/promises`](./node/fs-promises.md) — `FileHandle` append/read offsets, immediate `Dir` callbacks, inert `watch`, no cancellation
14
14
  - [Fully unimplemented modules](./node/modules.md) — `https`, `readline`, `tls`, `cluster`, `vm`, ...
15
15
  - [Global objects and namespaces](./node/globals.md) — `global`, `__dirname`, `require` outside `node_modules`
16
- - [Async and the event-loop model](./node/async.md) — no asynchronous I/O scheduler, blocking `connect`, no keep-alive
16
+ - [Async and the event-loop model](./node/async.md) — blocked file watching, blocking `net.connect`, no keep-alive, fixed-size offload pool
17
17
  - [The Bun extension](./node/bun.md) — design example only
18
18
 
19
19
  A module's implemented page links to its limitation page; when a limitation is
@@ -9,6 +9,6 @@
9
9
  | Type checker | ✗ only diagnostic codes are defined; no checker |
10
10
  | Full standard library | partial: Math / JSON / Date / Map / Set / RegExp / `Error` / `BigInt` / `Symbol` / `structuredClone` implemented; String.normalize missing |
11
11
  | Multi-file module bundling | partial: relative-path `.ts` bundling, ESM `node_modules` packages, namespace imports and bare-specifier extension module imports implemented; CommonJS is handled only inside `node_modules`; circular dependencies / live bindings are not implemented |
12
- | Real async runtime | ✓ `async`/`await` suspends on pending promises on the `select(2)` reactor: timers, TCP sockets and promise callbacks resume the coroutine. Still missing: truly asynchronous I/O scheduling (`fs/promises` blocks before settling), a non-blocking `fetch` and worker threads (workers are child processes) |
12
+ | Real async runtime | ✓ `async`/`await` suspends on pending promises on the `select(2)` reactor: timers, TCP sockets, offloaded file/HTTP work and promise callbacks resume the coroutine. Still missing: real OS-level file watching, non-blocking `net.connect`, TLS for `fetch`, and user-visible worker threads (`worker_threads` uses child processes) |
13
13
  | Windows binary artifact verification | adapted at the build layer (`.exe` suffix, link flag branch), verified in CI |
14
14
  | Precise ECMAScript number / string / comparison semantics | partial, see [Runtime deviations](./deviations.md) |
@@ -64,6 +64,7 @@ win.documentTree() // 序列化的 DOM(调试用)
64
64
  win.layoutTree() // 序列化的布局盒(调试用)
65
65
  win.paintCount() // 显示列表中图形的数量
66
66
  win.paintList() // 序列化的显示列表(调试用)
67
+ win.inlineSvg(selector) // 序列化的内联 <svg>:{ markup, width, height, shapes }
67
68
  win.measureText(text, fontSize?, family?) // 整形后的推进宽度(像素)
68
69
  win.fontMetrics(fontSize?, family?) // { ascent, descent, lineHeight, ready }
69
70
  win.hitTest(x, y) // 最深的元素描述符,或 ""
@@ -72,6 +73,12 @@ win.advance(ms) // 推进 CSS transition 时钟(测试
72
73
  win.stats() // 引擎/运行时计数器(内存排查用)
73
74
  ```
74
75
 
76
+ `win.inlineSvg(selector)` 返回引擎为第一个匹配 `selector` 的 `<svg>` 元素构建的
77
+ 独立 SVG 文档(`markup`),以及 NanoSVG 从它解析出的固有尺寸与图形数量;没有
78
+ 匹配或元素不是 `<svg>` 时返回 `undefined`。它让序列化器的规范大小写
79
+ (`viewBox`、`linearGradient`、`gradientUnits` 等)无需 GPU 即可测试——HTML
80
+ 解析器会把它们全部小写化。
81
+
75
82
  `win.stats()` 返回 `{ heapBytes, heapAllocations, treeNodes, detachedRoots,`
76
83
  `detachedNodes, handles, handleSlots, listeners }`:运行时存活堆、DOM 树规模、
77
84
  分离节点池(detached pool)以及元素句柄表。稳定状态下它们都应保持常量——若
@@ -23,13 +23,14 @@
23
23
  `tests/e2e/gui-example-browser.test.ts` 中。
24
24
  - **`display: none -> flex` 的重排。** 通过类名切换让隐藏元素显示在 flex 容器上时,也曾观察
25
25
  到同样的崩溃;`examples/gui/pelican-bike` 改用 `opacity` 显示游戏结束遮罩。
26
- - **SVG:** 支持 SVG *文件*,经图像加载器处理(`<img src="logo.svg">`):
27
- `runtime/ext_gui/svg.cpp` 封装 vendored **NanoSVG** 解析/光栅化器,
28
- `image.{h,cpp}` 把 SVG 视为矢量图像并按绘制像素尺寸光栅化。文档中的内联
29
- `<svg>` **子树**仍不支持:HTML 解析器只认识元素与属性,布局只认识盒子,
30
- 绘制只认识矩形/文本/图像;`<svg>` 子树需要另一套几何与绘制路径。因此矢量
31
- 美术要么以 SVG/PNG 文件形式提供,要么像 `examples/gui/pelican-bike` 那样用
32
- 盒子绘制。
26
+ - **SVG 是 NanoSVG 的子集。** SVG *文件*(`<img src="logo.svg">`)与内联
27
+ `<svg>` 子树共用 vendored 的 NanoSVG 解析/光栅化器(`runtime/ext_gui/svg.cpp`、
28
+ `inline_svg.cpp`),它会渲染 `path`/`rect`/`circle`/`ellipse`/`line`/
29
+ `polyline`/`polygon`、组、`defs` 渐变以及基于 `class` 的 `<style>` 规则。
30
+ `<text>`、`<use>`、滤镜、遮罩与裁剪路径不会渲染,文档层叠的 CSS 也不会进入
31
+ 图像内部(这里的 `fill`/`stroke` 是 SVG 表现属性,不是 CSS 属性)。需要这些
32
+ 能力的矢量美术必须预先光栅化、用盒子绘制,或限制在受支持的语法内。参见
33
+ [媒体](./media.md#图像m6a)。
33
34
 
34
35
  ## 待决问题
35
36
 
@@ -12,7 +12,8 @@ PNG/JPEG/BMP/GIF/TGA 解码为 RGBA8,并带有解码缓存与仅头文件的
12
12
  `runtime/ext_gui/svg.{h,cpp}` 在其上增加 SVG:它封装 vendored **NanoSVG**
13
13
  库(解析 + 抗锯齿扫描线光栅化),按扩展名或内容识别 SVG,并产出与既有管线
14
14
  相同的 RGBA8 `Image`。`stb_image` 无法解码 SVG,这正是
15
- `<img src="logo.svg">` 能工作的原因。
15
+ `<img src="logo.svg">` 能工作的原因。内联 `<svg>` 子树会先被序列化成一个
16
+ 独立文档(`inline_svg.{h,cpp}`),再交给同一个解析器。
16
17
 
17
18
  - `<img>` 是一个替换元素(`display: inline-block`):设置了 CSS 尺寸时布局
18
19
  采用该尺寸,否则采用固有像素尺寸;当只约束一个轴时保持宽高比。构建盒树时
@@ -23,11 +24,34 @@ PNG/JPEG/BMP/GIF/TGA 解码为 RGBA8,并带有解码缓存与仅头文件的
23
24
  **位图**按固有分辨率解码并按路径缓存;**矢量图**(SVG)按设备像素下的绘制
24
25
  尺寸(逻辑尺寸 × 窗口像素密度)光栅化并保持 viewBox 宽高比,再按该尺寸缓存,
25
26
  因此缩放或 HiDPI 得到的是清晰渲染而非放大的位图。
27
+ - **内联** `<svg>` 元素与 `<img>` 一样是替换元素,但它的来源就是 DOM 子树
28
+ 本身。`runtime/ext_gui/inline_svg.{h,cpp}` 把该子树序列化回独立 SVG 文档,
29
+ 还原 HTML 解析器会小写掉的、NanoSVG 又按大小写精确匹配的拼写(`viewBox`、
30
+ `preserveAspectRatio`、`linearGradient`、`gradientUnits` 等)。布局先取
31
+ `width`/`height` 属性、其次 `viewBox`、最后 300x150 作为固有尺寸;绘制把
32
+ markup 挂在图像 op 上,渲染器按绘制设备像素尺寸,通过与 SVG 文件相同的
33
+ NanoSVG 缓存解析并光栅化。DOM 变更会在下一次布局时重新序列化(因此
34
+ `setAttribute` 与 `innerHTML` 都会重绘图像),markup 缓存有界
35
+ (最近最少使用),动画文档不会让它无限增长。
26
36
  - 解析结果按路径缓存;解析与光栅化器状态在 `xt_svg_shutdown`
27
37
  (`xt_image_shutdown`)中释放。
28
38
 
39
+ 文档 CSS 只作用于 `<svg>` **盒子**——尺寸、外边距、背景、边框、`transform`、
40
+ opacity、`display`——与任何其他元素一样。盒子内部的艺术内容保持 SVG 语义:
41
+ 表现属性与 SVG `<style>` 中基于 `class` 的规则由 NanoSVG 读取,而不是 HTML
42
+ 层叠,所以这里的 `fill`/`stroke` 不是 CSS 属性。对布局、绘制、命中测试与事件
43
+ 而言整个 `<svg>` 就是一个替换盒:其子元素没有 DOM 盒,因此点击的 `e.target`
44
+ 是 `<svg>` 元素而不是某个 `<rect>`。渲染器按 markup 与尺寸缓存纹理,所以每帧
45
+ 重写艺术内容的程序会为每个变体保留一张纹理;更好的做法是用 `transform`、
46
+ `opacity` 给盒子做动画,或在一小组文档之间切换。
47
+
29
48
  图像仍需完成:CSS `background-image: url(...)`、`data:` URI、`object-fit`、
30
- 九宫格边框与内联 `<svg>` 元素(仅支持 SVG *文件*,参见[待决问题](./known-issues.md))。
49
+ 九宫格边框。
50
+
51
+ 两种 SVG 都受限于 NanoSVG 的子集:`path`、`rect`、`circle`、`ellipse`、
52
+ `line`、`polyline`、`polygon`、组(`g`)、带线性/径向渐变的 `defs` 以及基于
53
+ `class` 的 `<style>` 规则会被光栅化;`<text>`、`<use>`、滤镜、遮罩与裁剪路径
54
+ 不会渲染(见[已知问题](./known-issues.md))。
31
55
 
32
56
  ## 视频与音频(M13)
33
57
 
package/doc/zh-CN/gui.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 语言 / Language:[English](../gui.md) | **简体中文**
4
4
 
5
- 状态:**M15** —— 功能(M1–M14)已全部完成:HTML 解析、CSS 选择器匹配、层叠(cascade)、计算样式与布局(块级、行内、Flexbox 与 CSS 定位)均已就位,引擎还会**绘制**:它构建一个由矩形、图像与排版后的文本 run 组成的显示列表,并通过 SDL_GPU 渲染。输入事件会经过命中测试并投递给原生 TS 处理器,`:hover`/`:focus` 会被动态匹配,`<img>` 依据其固有尺寸确定大小并从纹理绘制——位图(PNG/JPEG/…)与 SVG 文件皆可,后者按绘制尺寸光栅化,因此矢量图保持清晰——CSS transition 会为绘制属性做动画。**M8** 增加了交互式 DOM:具有稳定标识的元素句柄、变更操作(`appendChild`、`textContent`、`classList`、`style` 等)以及支持捕获/冒泡的元素级事件。**M9** 会提前编译 `<script>` 主体(内联与 `<script src>`)——参见 `gui-scripts.md`。**M10** 增加 `requestAnimationFrame` 以及若干 DOM 辅助方法。**M11** 增加 `position: relative`/`absolute`/`fixed` 及其偏移,`examples/gui/pelican-bike`(一个可玩的 2D 游戏)就构建在它之上。**M12** 明确了 DOM 节点生命周期(哪些变更释放、哪些保留),并让引擎内存有界:参见[节点生命周期](./gui/dom.md)与[内存与 GC](./gui/runtime.md)。**M13** 真正播放
5
+ 状态:**M16** —— 功能(M1–M15)已全部完成:HTML 解析、CSS 选择器匹配、层叠(cascade)、计算样式与布局(块级、行内、Flexbox 与 CSS 定位)均已就位,引擎还会**绘制**:它构建一个由矩形、图像与排版后的文本 run 组成的显示列表,并通过 SDL_GPU 渲染。输入事件会经过命中测试并投递给原生 TS 处理器,`:hover`/`:focus` 会被动态匹配,`<img>` 依据其固有尺寸确定大小并从纹理绘制——位图(PNG/JPEG/…)与 SVG 文件皆可,后者按绘制尺寸光栅化,因此矢量图保持清晰——CSS transition 会为绘制属性做动画。**M16** 让内联 `<svg>` 子树获得同样的处理:子树被序列化回 SVG 文档,并按绘制设备尺寸光栅化,因此图标不再需要单独的文件。**M8** 增加了交互式 DOM:具有稳定标识的元素句柄、变更操作(`appendChild`、`textContent`、`classList`、`style` 等)以及支持捕获/冒泡的元素级事件。**M9** 会提前编译 `<script>` 主体(内联与 `<script src>`)——参见 `gui-scripts.md`。**M10** 增加 `requestAnimationFrame` 以及若干 DOM 辅助方法。**M11** 增加 `position: relative`/`absolute`/`fixed` 及其偏移,`examples/gui/pelican-bike`(一个可玩的 2D 游戏)就构建在它之上。**M12** 明确了 DOM 节点生命周期(哪些变更释放、哪些保留),并让引擎内存有界:参见[节点生命周期](./gui/dom.md)与[内存与 GC](./gui/runtime.md)。**M13** 真正播放
6
6
  `<video>`/`<audio>`——一个 vendored 的最小 FFmpeg 在主线程解码,视频帧走图像
7
7
  纹理路径、音频进入 SDL 流,DOM 媒体 API 暴露 `play`/`pause`/`currentTime`/…
8
8
  与媒体事件。**M14** 增加了 `<canvas>`,配一个自研的 2D 软件光栅器(抗锯齿
@@ -212,6 +212,16 @@ FFmpeg `7.1`(可用 `SDL3_TAG` / `FREETYPE_VERSION` / `HARFBUZZ_VERSION` /
212
212
  [布局](./gui/layout.md#变换m15)与[动画](./gui/animation.md#css-transformm15);
213
213
  e2e 见 `tests/e2e/gui-transform.test.ts` 与
214
214
  `tests/e2e/gui-example-svg.test.ts`。
215
+ 16. **M16 — 内联 `<svg>`** ✅
216
+ - `<svg>` 是替换元素(`layout.*`):固有尺寸先取 `width`/`height` 属性,
217
+ 其次 `viewBox`,最后 300x150;常规盒树遍历不再进入其子元素。
218
+ - `inline_svg.{h,cpp}` 把子树序列化为独立 SVG 文档,并还原 HTML 解析器
219
+ 小写掉的、区分大小写的名称(`viewBox`、`preserveAspectRatio`、
220
+ `linearGradient`、`gradientUnits` 等)。
221
+ - 绘制把 markup 挂在图像 op 上(`PaintImage::svg`),渲染器按绘制设备尺寸、
222
+ 通过与 SVG 文件相同的 NanoSVG 缓存(`svg.{h,cpp}`)解析并光栅化;markup
223
+ 缓存有界,DOM 变更会在下一次布局时重新序列化。e2e 见
224
+ `tests/e2e/gui-inline-svg.test.ts`。
215
225
 
216
226
  ## 进度日志
217
227
 
@@ -299,4 +309,11 @@ FFmpeg `7.1`(可用 `SDL3_TAG` / `FREETYPE_VERSION` / `HARFBUZZ_VERSION` /
299
309
  `getBoundingClientRect` 返回变换后的包围盒。`examples/gui/pelican-svg` 用它
300
310
  为自己的画做动画;e2e 见 `tests/e2e/gui-transform.test.ts` 与
301
311
  `tests/e2e/gui-example-svg.test.ts`。
312
+ - **M16** ✅ 内联 `<svg>`。`buildBoxTree` 把 `<svg>` 元素当作替换盒(固有尺寸
313
+ 依次取 `width`/`height`、`viewBox`、300x150)并停止下探,
314
+ `inline_svg.{h,cpp}` 以规范 SVG 大小写序列化子树,绘制把 markup 放进
315
+ `PaintImage::svg`,`renderer_image.cpp` 通过 NanoSVG 缓存(`svg.{h,cpp}`,
316
+ markup 采用有界 LRU)按绘制设备像素尺寸光栅化。`win.inlineSvg` 诊断钩子
317
+ 暴露序列化文档,`tests/e2e/gui-inline-svg.test.ts` 固定了尺寸、命中测试、
318
+ 渐变、CSS 盒样式与 DOM 变更。
302
319
 
@@ -3,7 +3,8 @@
3
3
  > 属于[已实现语法与功能](../implemented.md) · [English](../../implemented/async.md)
4
4
 
5
5
  实现位置:`runtime/xt_async.c`、`runtime/xt_coroutine.c`、`runtime/xt_promise.c`、
6
- `runtime/xt_generator.c`、`runtime/xt_loop.c`、`runtime/xt_performance.c`。
6
+ `runtime/xt_generator.c`、`runtime/xt_loop.c`、`runtime/xt_async_io.c`、
7
+ `runtime/xt_performance.c`。
7
8
 
8
9
  ## async / await
9
10
 
@@ -35,4 +36,14 @@
35
36
  - `setTimeout` / `clearTimeout` / `setInterval` / `clearInterval` / `setImmediate` / `clearImmediate` / `queueMicrotask` 与 `performance.now`(单调递增的小数毫秒)。
36
37
  - 定时器使用数字 id;未实现 `Timeout` / `Immediate` 对象。
37
38
  - 定时器 settle 的 promise 可以被 await:async 函数体在 pending promise 上挂起,定时器触发时恢复。套接字与服务端(`net`、`http`、`dgram`)的回调在同一事件循环上投递。
38
- - `fetch` 是阻塞的,`fs/promises` 在 settle 前同步完成 I/O —— 见[运行时偏差](../unimplemented/deviations.md)。异步生成器清理限制也在同一页列出。
39
+ - `fetch` 与 `fs/promises` 由 reactor 驱动而不是阻塞 —— 见下一节。
40
+
41
+ ## 异步 I/O offload
42
+
43
+ - `runtime/xt_async_io.c` 维护一个小型工作线程池(默认 4 个,惰性创建)。每个 job 分成两半:worker 上的 `run` 只能访问纯 C 内存;主线程上的 `complete` 才构造值并 settle promise。这个拆分让回收器与值模型保持单线程。
44
+ - job 完成后通过自管道(POSIX)或回环 UDP 套接字(Windows)唤醒 `select(2)`;reactor 也会轮询线程池,因此唤醒失败只会退化为短暂等待,而不会挂起。
45
+ - job 排队或运行期间,每个 job 最多四个值(promise;对 `fetch` 还有 headers 对象)保存在 job 的 root 槽中,由回收器扫描。
46
+ - `fetch` 把每一跳请求/重定向作为 job 执行;`fs/promises` 把每个文件与描述符操作作为 job 执行。两者都不会阻塞定时器、套接字或其他 `await`。
47
+ - 仍有 job 未完成时事件循环保持存活(`xt_loop_has_work`),线程池空闲后退出。
48
+
49
+ 异步表面的已知限制(`fetch` 无 TLS/流式、`fs.watch` 不触发、线程池固定 4 个 worker)列在[运行时偏差](../unimplemented/deviations.md)与各 Node 页面。
@@ -2,11 +2,30 @@
2
2
 
3
3
  > 属于[已实现语法与功能](../implemented.md) · [English](../../implemented/fetch.md)
4
4
 
5
- 实现位置:`runtime/xt_fetch.c`。
5
+ 实现位置:`runtime/xt_fetch.c`、`runtime/xt_fetch/async.inc`、`runtime/xt_async_io.c`。
6
6
 
7
- - 全局 `fetch(input, init)` 是阻塞式 HTTP/1.1 客户端,返回的 promise 已经 settle(交换同步完成,不经过 reactor 调度)。
7
+ - 全局 `fetch(input, init)` 是 HTTP/1.1 客户端。阻塞的套接字交换(`getaddrinfo`、connect、send、receive)运行在异步 I/O 工作线程池上,因此进行中的请求**不会**卡住事件循环:定时器、套接字与其他 `await` 继续运行,promise 在 reactor 派发完成结果时 settle。
8
+ - 重定向在主线程上处理:每一跳是一次 offload 交换,最多 20 次;301/302/303 会把 POST 改成 GET。
8
9
  - 只接受 `http://` URL —— 由于未链接 TLS 后端,`https://` 会以 `TypeError` 拒绝。
9
- - 选项:`method`、`headers`(普通对象或 `Headers`)、`body` 与 `redirect`(`follow` / `manual` / `error`);最多跟随 20 次重定向,并在 301/302/303 时将 POST 改为 GET。
10
- - 解析出的 `Response` 形状对象暴露 `ok` / `status` / `statusText` / `url` / `headers` 以及 `text()` / `json()` / `arrayBuffer()` / `bytes()` / `clone()`。
10
+ - 选项:`method`、`headers`(普通对象或 `Headers`)、`body` 与 `redirect`(`follow` / `manual` / `error`)。
11
+ - 解析出的 `Response` 形状对象暴露 `ok` / `status` / `statusText` / `url` / `headers` 以及 `text()` / `json()` / `arrayBuffer()` / `bytes()` / `clone()`。响应体在 promise settle 前已完整缓冲;不支持流式响应体。
11
12
  - `Headers` 大小写不敏感,提供 `get` / `has` / `set` / `append` / `delete` / `keys` / `values` / `entries` / `forEach` / `getSetCookie`。
12
13
  - 非法 URL 与网络失败会以 `TypeError` 拒绝。
14
+
15
+ ```ts
16
+ async function main(): Promise<void> {
17
+ const response = await fetch("http://127.0.0.1:8080/status");
18
+ console.log(response.status, await response.text());
19
+ }
20
+ main();
21
+ ```
22
+
23
+ 在请求完成前安排的定时器会在交换仍在进行时触发:
24
+
25
+ ```ts
26
+ const pending = fetch("http://127.0.0.1:8080/slow");
27
+ setTimeout(() => console.log("timer"), 10); // 会在 150ms 的响应之前运行
28
+ await pending;
29
+ ```
30
+
31
+ 已知限制(仅 `http://`、无 TLS、响应体整体缓冲)列在[运行时偏差](../unimplemented/deviations.md)。
@@ -2,13 +2,15 @@
2
2
 
3
3
  > 属于[Node 扩展:已实现](../node.md) · [English](../../../implemented/node/fs-promises.md)
4
4
 
5
- 实现位置:`src/extensions/node/fs-promises/index.ts`、`runtime/ext_node/fs/promises.c`
5
+ 实现位置:`src/extensions/node/fs-promises/index.ts`、`runtime/ext_node/fs/async_*.c`、`runtime/ext_node/fs/promises.c`
6
6
 
7
- 无异步 I/O 调度器,故每个函数把对应的同步 `fs` 实现包进**已 settle 的 Promise**。失败时会以同步形式抛出的同构 Node `Error`(含 `code` / `errno` / `syscall` / `path`)**reject**。`fs.promises` 也可从 `fs` 模块访问(`import { promises as fsp } from "fs"`),两个命名空间都暴露 `constants` 对象。
7
+ 每个函数都会向运行时的异步 I/O 线程池(`runtime/xt_async_io.c`)提交一个 job:阻塞的系统调用在 worker 线程上执行,promise 在事件循环上 settle。因此 `await` 在大文件读取、慢速网络文件系统或描述符操作进行期间会让出,`then` / `catch` 保持标准 Promise 语义。失败时会以与同步形式相同的 Node `Error`(含 `code` / `errno` / `syscall` / `path`)**reject**。
8
+
9
+ `fs.promises` 也可从 `fs` 模块访问(`import { promises as fsp } from "fs"`),两个命名空间都暴露 `constants` 对象。
8
10
 
9
11
  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`。
10
12
 
11
- `open(...)` 解析为 **`FileHandle`**,带有:`read`、`write`、`readFile`、`writeFile`、`appendFile`、`close`、`stat`、`truncate`、`chmod`、`chown`、`utimes`、`sync`、`datasync`。
13
+ `open(...)` 解析为 **`FileHandle`**,带有:`read`、`write`、`readFile`、`writeFile`、`appendFile`、`close`、`stat`、`truncate`、`chmod`、`chown`、`utimes`、`sync`、`datasync`。这些方法同样会 offload;`read(buffer, …)` 会在 worker 完成后填充调用方的 `Buffer`。
12
14
 
13
15
  ```ts
14
16
  import { readFile, writeFile, open } from "fs/promises";
@@ -23,5 +25,6 @@ async function main(): Promise<void> {
23
25
  main();
24
26
  ```
25
27
 
28
+ 工作由固定的小型线程池(4 个 worker)执行,完成结果按每个 worker 的提交顺序派发;相互独立的操作可以重叠。任何 job 都不会阻塞其他 `await`、定时器或套接字回调。
26
29
 
27
30
  已知偏差见[未实现:`fs/promises`](../../unimplemented/node/fs-promises.md)。
@@ -17,7 +17,7 @@ TypeScript 导出与 C 实现一一对应。新增模块不需要改动核心编
17
17
  | 模块 | 页面 | 说明 |
18
18
  | --- | --- | --- |
19
19
  | `fs` | [fs](./node/fs.md) | 仅同步 API |
20
- | `fs/promises` | [fs/promises](./node/fs-promises.md) | 把同步 API 包进已 settle 的 Promise |
20
+ | `fs/promises` | [fs/promises](./node/fs-promises.md) | 由 reactor 驱动、跑在异步 I/O 线程池上的文件与 `FileHandle` 操作 |
21
21
  | `path` | [path](./node/path.md) | `path.<name>(...)` 命名空间调用 |
22
22
  | `os` | [os](./node/os.md) | `os.<name>(...)` 命名空间调用 |
23
23
  | `process` | [process](./node/process.md) | 对象:方法与属性 |
@@ -31,7 +31,7 @@
31
31
  - [集合](./implemented/collections.md) —— Map、Set、WeakMap、WeakSet、WeakRef、迭代
32
32
  - [类型化数组与二进制数据](./implemented/typed-arrays.md) —— 类型化数组、ArrayBuffer、DataView
33
33
  - [异步、Promise 与生成器](./implemented/async.md) —— async/await、异步生成器、Promise、定时器
34
- - [fetch](./implemented/fetch.md) —— 阻塞式 HTTP/1.1 客户端与 Headers
34
+ - [fetch](./implemented/fetch.md) —— 由 reactor 驱动的 HTTP/1.1 客户端与 Headers
35
35
 
36
36
  ### 模块与工具
37
37
 
@@ -14,7 +14,7 @@
14
14
  | 数组越界 / 稀疏 | 越界访问返回 `undefined`;对 `arr.length` 赋值会截断 / 扩展,但不区分稀疏空洞 |
15
15
  | 内存管理 | 非移动标记-清扫回收器(在 `xt_alloc` 之后):显式根、子系统根提供者与保守 C 栈扫描。单线程、stop-the-world;无移动/压缩与分代 |
16
16
  | 函数 `arity` / 调用参数个数 | 无参数个数校验;`fn.length` 报告声明的 arity,但调用不做校验 |
17
- | `async` / `await` | 已在栈式协程上真实挂起;`await` 总会排入一次微任务(非 Promise 与已 settle 的 Promise 也一样),因此与 pending `.then` 回调的交错顺序符合规范。顶层 `await` 会阻塞事件循环等待,而不是让出模块主体。`fs/promises` 仍在 settle 前同步完成 I/O;`fetch` 是阻塞的。异步生成器可在 `await` 与 `yield` 处挂起,`for await...of` 每次迭代等待一步 |
17
+ | `async` / `await` | 已在栈式协程上真实挂起;`await` 总会排入一次微任务(非 Promise 与已 settle 的 Promise 也一样),因此与 pending `.then` 回调的交错顺序符合规范。顶层 `await` 会阻塞事件循环等待,而不是让出模块主体。`fs/promises` 与 `fetch` 把阻塞工作 offload 到 4 线程池并在 reactor 上 settle。异步生成器可在 `await` 与 `yield` 处挂起,`for await...of` 每次迭代等待一步 |
18
18
  | 异步生成器清理 | `for await...of` 提前退出时不会调用迭代器的 `return()`。异步生成器中的 `yield*` 只委托同步可迭代对象。在挂起的 `yield` 处调用 `.return()` 会直接完成而不执行 `finally`(与同步生成器相同的限制) |
19
19
  | `super` | `super.x` / `super(...)` 取 `this` 原型的原型;单级继承正确,继承深度 > 1 时可能不准确 |
20
20
  | `Error.stack` | 仅函数级帧:每帧为 `at 名称 (文件:行)`,行号取自函数声明(最内层帧会更新为错误构造处);没有列号,生成器 / `async` 函数体不产生帧(它们会切换栈) |
@@ -5,13 +5,16 @@
5
5
  已实现部分:
6
6
 
7
7
  - 核心事件循环 `runtime/xt_loop.c`(`select(2)` 反应堆),`net` / `dgram` / `http` 均构建于其上。
8
- - `Promise`、`async` / `await` 已可用(见核心文档),`fs/promises` 返回 Promise。
8
+ - 异步 I/O offload `runtime/xt_async_io.c`:阻塞的文件与 HTTP 客户端工作在 4 个工作线程上执行,并在 reactor 上完成,因此 `fs/promises` 与 `fetch` 不会卡住定时器或套接字。
9
+ - `Promise`、`async` / `await` 已可用(见核心文档),`fs/promises` 返回从 reactor settle 的 Promise。
9
10
  - 定时器已作为全局函数提供:`setTimeout` / `clearTimeout` / `setInterval` / `clearInterval` 运行在核心反应堆上,并在仍有定时器时保持进程存活。
10
11
  - 提供独立的 `EventEmitter`(`events` 模块,同时也是全局构造函数);流与套接字额外具备内部发射器方法(`on` / `addListener` / `once` / `off` / `removeListener` / `emit`)。
11
12
 
12
13
  仍未实现:
13
14
 
14
15
  - Node 的 `Timeout` 对象(`setTimeout` 返回数字 id;`setImmediate` 与 `queueMicrotask` 已作为全局函数提供)。
15
- - 真正的异步 I/O 调度:`fs/promises` 实质是同步操作的即时 settle 包装,不会在等待 I/O 时让出。
16
+ - 文件监听:`fs.watch` / `fs/promises.watch` 返回惰性对象;没有 inotify/kqueue/ReadDirectoryChangesW 后端。
17
+ - `Dir.read` / `Dir.close` 立即调用回调,回调式 `fs.readFile` / `fs.writeFile` / … 仍不支持(请用 `fs/promises` 或 `*Sync` 形式)。
16
18
  - 流与套接字的内置 `once` 等同 `on`(不具「触发一次后移除」语义);`events` 模块的 `EventEmitter` 实现了真正的 `once`。
17
- - `net` 的 `connect` 为阻塞式;HTTP 响应要求 `Connection: close`,不做 keep-alive / 分块传输 / 流水线复用。
19
+ - `net` 的 `connect` 仍是在套接字加入 reactor 之前执行的阻塞 `connect(2)`;HTTP 响应要求 `Connection: close`,不做 keep-alive / 分块传输 / 流水线复用。`fetch` 没有 TLS,且在 resolve 前缓冲整个响应体。
20
+ - offload 线程池固定为 4 个 worker;没有线程池大小选项,也不支持对排队 job 的 `AbortSignal` 取消。
@@ -2,11 +2,11 @@
2
2
 
3
3
  > 属于[Node 扩展:未实现](../node.md) · [English](../../../unimplemented/node/fs-promises.md)
4
4
 
5
- `fs/promises` 把每个同步 `fs` 调用包进一个已 settle 的 Promise(已实现表面见
6
- [已实现:`fs/promises`](../../implemented/node/fs-promises.md))。
5
+ `fs/promises` 现在把阻塞 I/O offload 到异步 I/O 线程池(已实现表面见[已实现:`fs/promises`](../../implemented/node/fs-promises.md));剩余差异主要是行为层面的:
7
6
 
8
- - I/O 是同步的:Promise 在 `await` 之前就已 settle,因此 await 它不会让出事件循环。
9
7
  - `FileHandle.appendFile` 行为等同 `writeFile`(按当前文件位置写入,而不是追加)。
10
8
  - `FileHandle.readFile()` 从当前描述符偏移读取。
11
- - `Dir.read` / `Dir.close`(同步与 Promise 形式)立即完成。
9
+ - `Dir.read` / `Dir.close`(同步与 Promise 形式)立即调用回调;`Dir.readSync` / `closeSync` 仍是同步的。
12
10
  - `watch` resolve 为与 `fs.watch` 相同的、永不触发的 watcher;没有真正的文件监听后端。
11
+ - 读写是一次性整体操作;没有流式 `FileHandle` 变体,也不支持 `AbortSignal` 取消。
12
+ - 线程池固定为 4 个 worker;大量并发操作会排队(但仍不会阻塞事件循环)。
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 属于[Node 扩展:未实现](../node.md) · [English](../../../unimplemented/node/fs.md)
4
4
 
5
- `fs` 现在实现了**同步** API 表面(文件、目录、描述符、元数据、链接、`cp`、`glob`、`Dir`、`constants`),`fs/promises` 将每个同步函数包进已 settle 的 Promise(见[已实现:`fs`](../../implemented/node/fs.md)与[已实现:`fs/promises`](../../implemented/node/fs-promises.md))。其余仍未实现,因为 xbintsc 的 `fs` **没有异步 I/O 调度器后端**(核心事件循环已提供定时器与套接字):
5
+ `fs` 实现了**同步** API 表面(文件、目录、描述符、元数据、链接、`cp`、`glob`、`Dir`、`constants`),`fs/promises` 则把每个文件/描述符操作跑在异步 I/O 线程池上(见[已实现:`fs`](../../implemented/node/fs.md)与[已实现:`fs/promises`](../../implemented/node/fs-promises.md))。仍缺少的主要是需要不同后端或回调管线的 API:
6
6
 
7
7
  | 未实现 API | 类别 |
8
8
  | --- | --- |
@@ -17,7 +17,7 @@
17
17
  - `readFileSync` 支持编码选项(默认/`utf8`/`ascii`/`latin1`/`binary`/`hex`/`base64`/`base64url`),但默认**不返回 `Buffer`**:即使提供了 `Buffer`(以普通对象模拟),`readFileSync` 仍以字符串返回。要读取原始字节请显式指定。
18
18
  - 未实现 `utf16le` / `ucs2` 解码(按文本返回字节)。
19
19
  - `watch` / `watchFile` / `unwatchFile` 返回 API 形态的发射器对象,`.close()` / `.on()` 方法存在但**不会触发**事件。
20
- - `Dir.read(cb)` / `Dir.close(cb)` 与 `FileHandle` 异步方法都会**同步**完成(回调/Promise 立即被调用)。
20
+ - `Dir.read(cb)` / `Dir.close(cb)` 会**同步**完成(回调立即被调用);`FileHandle` 方法现在返回真正的 Promise。
21
21
  - `mkdtempSync` 总是向前缀追加 6 个随机字符(不要求以 `XXXXXX` 结尾)。
22
22
  - `globSync` 支持 `*`、`?`、`[...]`、`**`,但不支持 `exclude` 回调与 `follow`;`**` 不跟随符号链接(与 Node 默认一致)。
23
23
  - `cpSync` 的符号链接处理在常见场景下与 Node 一致,但不支持 `verbatimSymlinks`。
@@ -8,10 +8,10 @@ Node 扩展实现了 21 个模块以及事件循环集成;已实现表面按
8
8
  ## 目录
9
9
 
10
10
  - [`fs`](./node/fs.md) —— 回调式异步操作、真正的文件监听、选项回调
11
- - [`fs/promises`](./node/fs-promises.md) —— 已 settle 的 Promise 背后仍是同步 I/O、`FileHandle` 偏差
11
+ - [`fs/promises`](./node/fs-promises.md) —— `FileHandle` 追加/读取偏移、`Dir` 回调立即完成、`watch` 不触发、无取消
12
12
  - [完全未实现的模块](./node/modules.md) —— `https`、`readline`、`tls`、`cluster`、`vm` 等
13
13
  - [全局对象与命名空间](./node/globals.md) —— `global`、`__dirname`、`node_modules` 之外的 `require`
14
- - [异步与事件循环模型](./node/async.md) —— 无异步 I/O 调度、阻塞式 `connect`、无 keep-alive
14
+ - [异步与事件循环模型](./node/async.md) —— 文件监听缺失、阻塞式 `net.connect`、无 keep-alive、固定大小线程池
15
15
  - [Bun 扩展](./node/bun.md) —— 仅为设计示例
16
16
 
17
17
  模块的已实现页面会链接到对应限制页;限制解除后,把条目移到
@@ -9,6 +9,6 @@
9
9
  | 类型检查器 | ✗ 仅定义诊断码,无 checker |
10
10
  | 完整标准库 | 部分:Math / JSON / Date / Map / Set / RegExp / `Error` / `BigInt` / `Symbol` / `structuredClone` 已实现;String.normalize 缺失 |
11
11
  | 多文件模块打包 | 部分:相对路径 `.ts` 打包、ESM `node_modules` 包、命名空间导入、裸说明符扩展模块导入已实现;CommonJS 仅在 `node_modules` 内处理;循环依赖 / 实时绑定未实现 |
12
- | 异步运行时 | ✓ `async`/`await` 在 `select(2)` reactor 上对 pending promise 挂起:定时器、TCP 套接字与 promise 回调都能恢复协程。仍缺:真正的异步 I/O 调度(`fs/promises` 会先阻塞完成 I/O 再 settle)、非阻塞 `fetch` 与 worker 线程(worker 是子进程) |
12
+ | 异步运行时 | ✓ `async`/`await` 在 `select(2)` reactor 上对 pending promise 挂起:定时器、TCP 套接字、offload 的文件/HTTP 工作与 promise 回调都能恢复协程。仍缺:真正的 OS 级文件监听、非阻塞 `net.connect`、`fetch` 的 TLS,以及用户可见的 worker 线程(`worker_threads` 仍用子进程) |
13
13
  | Windows 二进制产物验证 | 构建层已适配(`.exe` 后缀、链接参数分支),并在 CI 中验证 |
14
14
  | 精确的 ECMAScript 数值 / 字符串 / 比较语义 | 部分,见[运行时偏差](./deviations.md) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "xbintsc",
3
- "version": "0.5.20",
3
+ "version": "0.5.21",
4
4
  "description": "xbintsc - a TypeScript binary compiler (TypeScript -> LLVM IR -> native binary)",
5
5
  "type": "module",
6
6
  "license": "MIT",