xbintsc 0.3.81 → 0.5.6
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 +8 -4
- package/README.md +16 -5
- package/README.zh-CN.md +14 -6
- package/dist/src/ast/common.d.ts +23 -0
- package/dist/src/cli/main.js +68 -24
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/codegen/generator/calls/access.js +6 -2
- package/dist/src/codegen/generator/calls/access.js.map +1 -1
- package/dist/src/codegen/generator/calls/closures.js +4 -0
- package/dist/src/codegen/generator/calls/closures.js.map +1 -1
- package/dist/src/codegen/generator/calls/invocation.js +9 -4
- package/dist/src/codegen/generator/calls/invocation.js.map +1 -1
- package/dist/src/codegen/generator/context.d.ts +50 -0
- package/dist/src/codegen/generator/context.js +124 -13
- package/dist/src/codegen/generator/context.js.map +1 -1
- package/dist/src/codegen/generator/debug.d.ts +33 -0
- package/dist/src/codegen/generator/debug.js +97 -0
- package/dist/src/codegen/generator/debug.js.map +1 -0
- package/dist/src/codegen/generator/expressions/assignment.js +9 -5
- package/dist/src/codegen/generator/expressions/assignment.js.map +1 -1
- package/dist/src/codegen/generator/expressions/operators.js +35 -9
- package/dist/src/codegen/generator/expressions/operators.js.map +1 -1
- package/dist/src/codegen/generator/expressions/primary.js +11 -3
- package/dist/src/codegen/generator/expressions/primary.js.map +1 -1
- package/dist/src/codegen/generator/generator.d.ts +3 -1
- package/dist/src/codegen/generator/generator.js +3 -1
- package/dist/src/codegen/generator/generator.js.map +1 -1
- package/dist/src/codegen/generator/module.d.ts +1 -1
- package/dist/src/codegen/generator/module.js +82 -12
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/numeric.d.ts +26 -0
- package/dist/src/codegen/generator/numeric.js +127 -0
- package/dist/src/codegen/generator/numeric.js.map +1 -0
- package/dist/src/codegen/generator/state.d.ts +17 -0
- package/dist/src/codegen/generator/state.js +9 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/statements/control-flow.js +2 -4
- package/dist/src/codegen/generator/statements/control-flow.js.map +1 -1
- package/dist/src/codegen/generator/statements/dispatch.js +3 -0
- package/dist/src/codegen/generator/statements/dispatch.js.map +1 -1
- package/dist/src/codegen/generator/statements/variables.js +8 -2
- package/dist/src/codegen/generator/statements/variables.js.map +1 -1
- package/dist/src/codegen/generator/tables.d.ts +16 -0
- package/dist/src/codegen/generator/tables.js +99 -2
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/driver/bundler/merge.js +41 -5
- package/dist/src/driver/bundler/merge.js.map +1 -1
- package/dist/src/driver/compiler.d.ts +23 -4
- package/dist/src/driver/compiler.js +46 -57
- package/dist/src/driver/compiler.js.map +1 -1
- package/dist/src/driver/fingerprint.d.ts +27 -0
- package/dist/src/driver/fingerprint.js +88 -0
- package/dist/src/driver/fingerprint.js.map +1 -0
- package/dist/src/driver/toolchain-provider.d.ts +9 -2
- package/dist/src/driver/toolchain-provider.js +15 -15
- package/dist/src/driver/toolchain-provider.js.map +1 -1
- package/dist/src/driver/toolchain.d.ts +58 -1
- package/dist/src/driver/toolchain.js +169 -22
- package/dist/src/driver/toolchain.js.map +1 -1
- package/dist/src/parser/expressions.js +20 -1
- package/dist/src/parser/expressions.js.map +1 -1
- package/dist/tests/cli/main.test.js +41 -1
- package/dist/tests/cli/main.test.js.map +1 -1
- package/dist/tests/codegen/closures.test.js +8 -0
- package/dist/tests/codegen/closures.test.js.map +1 -1
- package/dist/tests/codegen/expressions.test.js +14 -3
- package/dist/tests/codegen/expressions.test.js.map +1 -1
- package/dist/tests/codegen/llvm.test.js +23 -0
- package/dist/tests/codegen/llvm.test.js.map +1 -1
- package/dist/tests/driver/toolchain-provider.test.js +49 -2
- package/dist/tests/driver/toolchain-provider.test.js.map +1 -1
- package/dist/tests/driver/toolchain.test.js +62 -3
- package/dist/tests/driver/toolchain.test.js.map +1 -1
- package/dist/tests/e2e/async-await.test.d.ts +10 -0
- package/dist/tests/e2e/async-await.test.js +247 -0
- package/dist/tests/e2e/async-await.test.js.map +1 -0
- package/dist/tests/e2e/child-process.test.d.ts +10 -0
- package/dist/tests/e2e/child-process.test.js +59 -0
- package/dist/tests/e2e/child-process.test.js.map +1 -0
- package/dist/tests/e2e/compile-objects-classes.test.js +47 -0
- package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
- package/dist/tests/e2e/error-stack.test.d.ts +9 -0
- package/dist/tests/e2e/error-stack.test.js +94 -0
- package/dist/tests/e2e/error-stack.test.js.map +1 -0
- package/dist/tests/e2e/runtime-coverage-globals.test.js +46 -0
- package/dist/tests/e2e/runtime-coverage-globals.test.js.map +1 -1
- package/dist/tests/e2e/string-concat.test.d.ts +9 -0
- package/dist/tests/e2e/string-concat.test.js +102 -0
- package/dist/tests/e2e/string-concat.test.js.map +1 -0
- package/dist/tests/e2e/string-utf16.test.d.ts +6 -0
- package/dist/tests/e2e/string-utf16.test.js +133 -0
- package/dist/tests/e2e/string-utf16.test.js.map +1 -0
- package/dist/tests/helpers.d.ts +9 -0
- package/dist/tests/helpers.js +26 -3
- package/dist/tests/helpers.js.map +1 -1
- package/dist/tests/parser/expressions.test.js +7 -0
- package/dist/tests/parser/expressions.test.js.map +1 -1
- package/dist/tests/version.test.d.ts +1 -0
- package/dist/tests/version.test.js +24 -0
- package/dist/tests/version.test.js.map +1 -0
- package/doc/DESIGN.md +20 -12
- package/doc/ai/cli.md +2 -0
- package/doc/ai/contributing.md +16 -8
- package/doc/ai/extensions.md +3 -2
- package/doc/ai/language-support.md +15 -12
- package/doc/ai/troubleshooting.md +43 -5
- package/doc/ai/zh-CN/cli.md +2 -0
- package/doc/ai/zh-CN/contributing.md +11 -7
- package/doc/ai/zh-CN/extensions.md +2 -1
- package/doc/ai/zh-CN/language-support.md +15 -12
- package/doc/ai/zh-CN/troubleshooting.md +38 -4
- package/doc/implemented.md +16 -13
- package/doc/requirements.md +13 -4
- package/doc/unimplemented.md +20 -18
- package/doc/zh-CN/DESIGN.md +15 -9
- package/doc/zh-CN/implemented.md +15 -12
- package/doc/zh-CN/requirements.md +12 -3
- package/doc/zh-CN/unimplemented.md +19 -17
- package/package.json +3 -1
- package/runtime/ext_node/buffer/parts/construction.inc +2 -2
- package/runtime/ext_node/buffer/parts/methods.inc +1 -1
- package/runtime/ext_node/buffer/parts/search.inc +1 -1
- package/runtime/ext_node/child_process/child_process.c +25 -0
- package/runtime/ext_node/fs/fd_ops.c +1 -1
- package/runtime/rt.h +49 -1
- package/runtime/rt_internal.h +136 -4
- package/runtime/xt_alloc.c +20 -2
- package/runtime/xt_async.c +197 -0
- package/runtime/xt_bigint/conversions.inc +1 -1
- package/runtime/xt_builtins.c +169 -43
- package/runtime/xt_constructors.c +389 -0
- package/runtime/xt_containers/access.inc +61 -24
- package/runtime/xt_containers/arrays.inc +26 -2
- package/runtime/xt_containers/objects.inc +206 -8
- package/runtime/xt_coroutine.c +212 -0
- package/runtime/xt_generator.c +31 -162
- package/runtime/xt_io/exception.inc +171 -2
- package/runtime/xt_io/inspect.inc +48 -13
- package/runtime/xt_io.c +5 -0
- package/runtime/xt_promise.c +62 -17
- package/runtime/xt_stdlib/arrays.inc +2 -2
- package/runtime/xt_stdlib/dispatch.inc +20 -4
- package/runtime/xt_stdlib/strings.inc +98 -29
- package/runtime/xt_stdlib2/array-statics.inc +3 -2
- package/runtime/xt_stdlib2/arrays.inc +1 -1
- package/runtime/xt_stdlib2/error.inc +33 -6
- package/runtime/xt_stdlib2/json.inc +46 -16
- package/runtime/xt_stdlib2/number-string-statics.inc +24 -13
- package/runtime/xt_stdlib2/objects.inc +1 -1
- package/runtime/xt_stdlib2/regexp-match.inc +50 -35
- package/runtime/xt_stdlib2/set.inc +6 -0
- package/runtime/xt_stdlib2/strings.inc +81 -42
- package/runtime/xt_symbol.c +1 -1
- package/runtime/xt_typed_array/construction.inc +43 -2
- package/runtime/xt_typed_array.c +4 -0
- package/runtime/xt_values/comparison.inc +2 -2
- package/runtime/xt_values/constructors.inc +18 -5
- package/runtime/xt_values/conversions.inc +4 -3
- package/runtime/xt_values/strings.inc +94 -4
- package/runtime/xt_values/utf16.inc +340 -0
- package/runtime/xt_values.c +1 -0
- package/scripts/bench.ts +172 -0
- package/scripts/build-runtime.ts +2 -1
- package/scripts/check-version.ts +53 -0
- package/src/ast/common.ts +23 -0
- package/src/cli/main.ts +68 -26
- package/src/codegen/generator/calls/access.ts +7 -2
- package/src/codegen/generator/calls/closures.ts +3 -0
- package/src/codegen/generator/calls/invocation.ts +9 -3
- package/src/codegen/generator/context.ts +129 -18
- package/src/codegen/generator/debug.ts +132 -0
- package/src/codegen/generator/expressions/assignment.ts +9 -5
- package/src/codegen/generator/expressions/operators.ts +47 -8
- package/src/codegen/generator/expressions/primary.ts +11 -3
- package/src/codegen/generator/generator.ts +18 -2
- package/src/codegen/generator/module.ts +83 -13
- package/src/codegen/generator/numeric.ts +158 -0
- package/src/codegen/generator/state.ts +26 -0
- package/src/codegen/generator/statements/control-flow.ts +2 -3
- package/src/codegen/generator/statements/dispatch.ts +3 -0
- package/src/codegen/generator/statements/variables.ts +8 -2
- package/src/codegen/generator/tables.ts +110 -2
- package/src/driver/bundler/merge.ts +39 -5
- package/src/driver/compiler.ts +65 -55
- package/src/driver/fingerprint.ts +85 -0
- package/src/driver/toolchain-provider.ts +17 -16
- package/src/driver/toolchain.ts +210 -21
- package/src/parser/expressions.ts +20 -1
package/doc/zh-CN/implemented.md
CHANGED
|
@@ -190,7 +190,7 @@ xt_value fn(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv);
|
|
|
190
190
|
|
|
191
191
|
- `thisValue` 作为首个 ABI 参数线程化(异常安全、支持嵌套);箭头函数从环境额外槽位词法继承 `this`。
|
|
192
192
|
- 闭包通过 `env` 线程化捕获变量(引用传递,box 包装),直接调用与闭包调用共用同一代码路径。
|
|
193
|
-
- `xt_object` 带原型字段,属性查找沿原型链;`xt_function` 带 `prototype`
|
|
193
|
+
- `xt_object` 带原型字段,属性查找沿原型链;`xt_function` 带 `prototype` 与属性包(静态成员)。`xt_array` 也带 `[[Prototype]]`(Array.prototype)。`Object.prototype` 是普通对象的原型根,提供 `hasOwnProperty` / `toString` / `valueOf` / `isPrototypeOf` / `propertyIsEnumerable` / `__proto__`;`Object.getPrototypeOf({}) === Object.prototype`。
|
|
194
194
|
|
|
195
195
|
---
|
|
196
196
|
|
|
@@ -211,12 +211,13 @@ xt_value fn(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv);
|
|
|
211
211
|
- 数组字面量(含展开 `[...]`)、对象字面量(含简写 / 方法 / 对象展开 `{...obj}`)
|
|
212
212
|
- 类型化数组(`Uint8Array`、`Int8Array`、`Uint8ClampedArray`、`Uint16Array`、`Int16Array`、`Uint32Array`、`Int32Array`、`Float32Array`、`Float64Array`):构造(`new X(n)` / `new X(可迭代)` / `X.from` / `X.of`)、`length` / `byteLength` / `byteOffset` / `BYTES_PER_ELEMENT`、按元素类型强制的读写(`ToIntN` / `ToUintN`、`Uint8ClampedArray` 舍入、`Float32` 单精度舍入)以及原型方法 `fill` / `set` / `slice` / `subarray` / `join` / `toString` / `indexOf` / `lastIndexOf` / `includes` / `forEach` / `map` / `filter` / `every` / `some` / `find` / `findIndex` / `reduce` / `reverse` / `sort` / `copyWithin` / `at` / `keys` / `values` / `entries`。有意保留的差异见未实现文档(`subarray` 返回副本、迭代器方法返回数组、无 `ArrayBuffer`/`DataView`)。
|
|
213
213
|
- 属性访问(含 `length` 特判、`Math` 常量)、元素访问、调用
|
|
214
|
+
- 一等公民内建构造器(`const A = Array`、`const M = Map`、`const E = TypeError`、类型化数组):裸引用下降为 `xt_builtin_constructor`,得到带 `name` / `length`、`prototype` 与静态成员(`A.isArray`、`A.from`、`M.prototype` 等)的缓存函数。通过别名调用或 `new` 会分派到同一运行时构造器,`x instanceof A` 沿共享原型链判断。
|
|
214
215
|
- 可选链 `?.` / `?.[]` / `?.()`:以空值判断短路到 `undefined`
|
|
215
216
|
- `delete`、`in`、`instanceof`
|
|
216
217
|
- `this`(保存到函数 `%saved.this`;箭头函数从环境槽读)、`super`(`super.x` / `super(...)`)、`new`、`await`
|
|
217
218
|
- 闭包(箭头函数 / 函数表达式)与捕获环境构建
|
|
218
219
|
- 类:构造器闭包 + 原型对象,存入 LLVM 全局(`@class.<id>`);实例字段在构造器体前初始化;`static` 成员存于构造器属性包;`extends` 设置原型链;`super(...)` 通过原型上的隐藏 `__ctor` 调用。
|
|
219
|
-
- `async
|
|
220
|
+
- `async`:闭包用 `xt_function_set_async` 标记;调用时在栈式协程(`xt_coroutine.c`、`xt_async.c`)上运行函数体并立即返回 promise。函数体同步执行到第一个等待**未 settle** promise 的 `await` 后挂起;promise settle 时排入微任务恢复协程。逃出函数体的异常会让该 promise reject,而不是同步抛出。`await` 非 promise 或已 settle 的值仍走同步快路径,rejection 触发异常。
|
|
220
221
|
- 标准库调用:`console.*`、`Math.*`、`Object.*`、数组 / 字符串方法统一走 `xt_call_method` / `xt_math_call` / `xt_object_*`;`JSON`/`Date`/`Map`/`Set`/`RegExp`/`Promise` 静态与构造走对应 `xt_*`;全局函数(`parseInt` 等)走 `xt_parse_int` 等。
|
|
221
222
|
- 全局字符串池(`@.str.N` 私有常量,UTF-8 转义)。
|
|
222
223
|
- 内置调用:`console.log` / `info` / `warn` / `error`、`Math.*`、`Object.*`、数组 / 字符串方法、全局函数、扩展 builtins(统一 `(argc, argv)` ABI)。
|
|
@@ -228,18 +229,19 @@ xt_value fn(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv);
|
|
|
228
229
|
## 8. C 运行时(Runtime,已实现)
|
|
229
230
|
|
|
230
231
|
实现位置:`runtime/xt_alloc.c`、`runtime/xt_values.c`、`runtime/xt_containers.c`、
|
|
231
|
-
`runtime/xt_stdlib.c`、`runtime/xt_stdlib2.c`、`runtime/xt_promise.c`、`runtime/
|
|
232
|
+
`runtime/xt_stdlib.c`、`runtime/xt_stdlib2.c`、`runtime/xt_promise.c`、`runtime/xt_async.c`、
|
|
233
|
+
`runtime/xt_coroutine.c`、`runtime/xt_builtins.c`、
|
|
232
234
|
`runtime/xt_io.c`,共享私有头 `runtime/rt_internal.h`;公开 ABI 见 `runtime/rt.h`。
|
|
233
235
|
|
|
234
236
|
- 分配器:`xt_alloc` 背后的非移动标记-清扫回收器(显式根、子系统根提供者与保守 C 栈扫描)。
|
|
235
237
|
- 值构造:`xt_undefined/xt_null/xt_bool/xt_number/xt_string_new/xt_string_from_cstr`。
|
|
236
|
-
- 字符串:UTF-8
|
|
238
|
+
- 字符串:UTF-8 存储,对外呈现 JavaScript 的 UTF-16 视图(`length`、索引、`slice`、`indexOf`、`split`、`padStart`、`codePointAt` 按码元计数;`for...of` 与 `Array.from` 按码点计数;孤立代理项以 WTF-8 保存,并在拼接时重新组合)、惰性 cons 节点拼接(首次观察时才扁平化,因此循环追加保持线性复杂度)、相等比较、格式化数字转字符串。`xt_string_length` 供 I/O 使用,返回字节数;`xt_string_utf16_length` 返回 JavaScript 长度。
|
|
237
239
|
- 类型转换:`xt_truthy`、`xt_to_number`、`xt_to_string`、`xt_typeof`。
|
|
238
240
|
- 算术:`add/sub/mul/div/mod/pow/neg/pos`。
|
|
239
241
|
- 位运算:`and/or/xor/not/shl/shr/ushr`(含 `ToInt32` 语义)。
|
|
240
242
|
- 比较:`lt/le/gt/ge`、宽松 / 严格相等、`not`、`is_nullish`。
|
|
241
243
|
- 对象:线性属性列表,`object_new/get/set/has/keys/values/entries/assign/spread`。
|
|
242
|
-
- 数组:`array_new/get/set/push/length/spread`;对 `arr.length` 赋值会截断 / 扩展(与 JS 一致);`iter_length` / `iter_value`
|
|
244
|
+
- 数组:`array_new/get/set/push/length/spread`;对 `arr.length` 赋值会截断 / 扩展(与 JS 一致);`iter_length` / `iter_value` 为数组、字符串(按码点)、`Map`、`Set` 提供统一迭代视图。
|
|
243
245
|
- 类型化数组(`xt_typed_array.c`):以属性包对象表示,每种元素类型一个原型;读取返回已存值,写入按元素类型强制转换;提供 `from` / `of` 静态方法与完整原型方法集;`subarray` 返回副本。
|
|
244
246
|
- Symbol(`xt_symbol.c`):`Symbol(description)` 原始值(`XT_OBJECT_KIND_SYMBOL`)、13 个著名符号(`Symbol.iterator`、`Symbol.asyncIterator`、`Symbol.match` 等)、`Symbol.for` / `Symbol.keyFor` 全局注册表、`symbol.description` / `toString()` / `valueOf()`;symbol 可作为属性键(`Object.getOwnPropertySymbols`,symbol 键的 `get`/`set`/`in`/`delete`),会被 `Object.keys` / `values` / `entries` / `for...in` / `JSON.stringify` 跳过,打印为 `Symbol(desc)`。
|
|
245
247
|
- 通用成员访问:`xt_get` / `xt_set`(对数组 / 对象 / 字符串分发)。
|
|
@@ -247,12 +249,13 @@ xt_value fn(xt_value thisValue, xt_value env, int32_t argc, xt_value *argv);
|
|
|
247
249
|
- 运算符辅助:`xt_in`(`in`)、`xt_delete`(`delete`)、`xt_rest_args`(剩余参数 / `arguments`)。
|
|
248
250
|
- Box:`box_new/get/set`(用于闭包捕获变量)。
|
|
249
251
|
- 函数与闭包:`arg`、`closure_new/call/env/arity`。
|
|
250
|
-
- 异常:`xt_try_enter` / `xt_try_exception` / `xt_try_leave` 维护 `_setjmp` 帧栈;`xt_throw` 在存在帧时长跳到最近 `try`,否则打印 `Uncaught ...` 后退出。
|
|
252
|
+
- 异常:`xt_try_enter` / `xt_try_exception` / `xt_try_leave` 维护 `_setjmp` 帧栈;`xt_throw` 在存在帧时长跳到最近 `try`,否则打印 `Uncaught ...` 后退出。codegen 还会维护一条影子调用栈(函数名、源文件、行号):`Error.stack` 用它生成堆栈,原生崩溃时致命信号处理器也会打印同一组帧。`--debug` 还会生成 `!DICompileUnit` / `!DISubprogram` / `!DILocation` 元数据,并用 `-g -fno-omit-frame-pointer` 编译,因此 gdb/lldb/WinDbg 可以把指令映射回源码行。
|
|
251
253
|
- 输出:`xt_print/xt_println/xt_console_log/info/warn/error`(Node 风格 inspect:数组 `[ a, b ]`、对象 `{ k: v }`;`info`/`log` 到 stdout,`warn`/`error` 到 stderr),以及 `dir/trace/assert/count/countReset/group/groupEnd/table/time/timeEnd/timeLog`。
|
|
252
|
-
- 对象 / 函数:`xt_object` 带原型链,`xt_function` 带属性包(静态成员与 `prototype`);`xt_new`(实例化)、`xt_instance_of`(原型链)、`xt_object_freeze/is_frozen/from_entries
|
|
254
|
+
- 对象 / 函数:`xt_object` 带原型链,`xt_function` 带属性包(静态成员与 `prototype`);`xt_new`(实例化)、`xt_instance_of`(原型链)、`xt_object_freeze/is_frozen/from_entries`;`xt_constructors.c` 保存一等公民构造器缓存、构造器原型与静态值分派。
|
|
253
255
|
- 标准库扩展(`xt_stdlib2.c`):数组 / 字符串 / 数字 / 对象的扩展方法;`Object` / `Array` / `Number` / `String` 静态方法;`JSON.parse` / `JSON.stringify`;`Map` / `Set`;`Date`(`gmtime_r`);`RegExp`(POSIX ERE `regcomp`/`regexec` 的 `test`/`exec`)。
|
|
254
|
-
- Promise(`xt_promise.c
|
|
255
|
-
-
|
|
256
|
+
- Promise(`xt_promise.c`):微任务队列(`xt_microtasks`);`xt_promise_ctor/resolve/reject/static`、实例 `then/catch/finally`;`xt_drain_microtasks` 在程序结束时清空队列,事件循环也会在回调之间清空它。`xt_await`(位于 `xt_async.c`)对已 settle 的值同步返回,对 pending promise 则挂起当前 async 协程并登记等待者。
|
|
257
|
+
- 异步协程(`xt_async.c`)复用共享的栈式协程运行时(`xt_coroutine.c`,POSIX `ucontext` / Windows fiber):每次 `async` 调用拥有私有栈,切换异常帧栈与 GC 栈区间,因此 `await` 可跨越 `try`/`finally`、循环与闭包。由定时器、套接字回调或另一个协程 settle 的 promise 会在微任务队列上恢复挂起的函数体。
|
|
258
|
+
- Fetch(`xt_fetch.c`):全局 `fetch(input, init)` 是阻塞式 HTTP/1.1 客户端,返回的 promise 已经 settle(交换同步完成,不经过 reactor 调度)。只接受 `http://` URL——由于未链接 TLS 后端,`https://` 会以 `TypeError` 拒绝——支持 `method`、`headers`(普通对象或 `Headers`)、`body` 与 `redirect`(`follow` / `manual` / `error`),最多跟随 20 次重定向,并在 301/302/303 时将 POST 改为 GET。解析出的 `Response` 形状对象暴露 `ok` / `status` / `statusText` / `url` / `headers` 以及 `text()` / `json()` / `arrayBuffer()` / `bytes()` / `clone()`;`Headers` 大小写不敏感,提供 `get` / `has` / `set` / `append` / `delete` / `keys` / `values` / `entries` / `forEach` / `getSetCookie`。非法 URL 与网络失败会以 `TypeError` 拒绝。
|
|
256
259
|
|
|
257
260
|
---
|
|
258
261
|
|
|
@@ -338,7 +341,7 @@ const result = build("program.ts", { emit: "exe", outDir: "build" });
|
|
|
338
341
|
实现位置:`tests/`(`lexer` / `parser` / `binder` / `codegen` / `driver` / `extensions` / `cli` / `e2e`)
|
|
339
342
|
|
|
340
343
|
- 各模块单元测试;e2e 在存在 `clang` 时真正编译并运行二进制,否则自动跳过。
|
|
341
|
-
- e2e 覆盖:算术与打印、递归函数、循环 / 数组 / 字符串拼接、闭包按引用捕获、对象 / 数组 JS 风格打印、Node `fs` 扩展(经 `import`)、`switch` 穿透、数组 / 字符串方法、`Math` 与全局函数与 `console` 各等级、默认 / 剩余参数与 `arguments`、`Object` 助手与展开与 `in`/`delete`、`for...in` 对象键枚举、`try/catch/finally`、可选链、类与 `new`/`this`/`static`/`extends`/`super`/`instanceof`、`async`/`await` 与 `Promise
|
|
344
|
+
- e2e 覆盖:算术与打印、递归函数、循环 / 数组 / 字符串拼接、闭包按引用捕获、对象 / 数组 JS 风格打印、Node `fs` 扩展(经 `import`)、`switch` 穿透、数组 / 字符串方法、`Math` 与全局函数与 `console` 各等级、默认 / 剩余参数与 `arguments`、`Object` 助手与展开与 `in`/`delete`、`for...in` 对象键枚举、`try/catch/finally`、可选链、类与 `new`/`this`/`static`/`extends`/`super`/`instanceof`、`async`/`await` 与 `Promise`、真实 await 挂起(定时器、TCP 套接字与 `fs/promises` 跨事件循环轮次、恢复后的 rejection 与 `finally`)、`Map`/`Set`/`JSON` 与扩展标准库、`Map`/`Set` 的 `for...of`、数组 `length` 赋值与可迭代展开、多文件 `import`/`export`、类型化数组(元素强制转换、`from`/`of`、迭代与原型方法)、对象 rest 解构与内建 `instanceof`,一等公民内建构造器与 `Object.prototype`(别名、静态成员、`getPrototypeOf`、`hasOwnProperty.call`),以及全局 `fetch`(HTTP GET/POST、请求头、重定向、JSON/文本/二进制响应体与 `TypeError` 拒绝)。
|
|
342
345
|
|
|
343
346
|
---
|
|
344
347
|
|
|
@@ -352,11 +355,11 @@ const result = build("program.ts", { emit: "exe", outDir: "build" });
|
|
|
352
355
|
| 运算符 | 算术、比较、相等、逻辑、位运算、移位、一元(含 `typeof`/`void`)、前后缀增减、复合赋值、逻辑赋值、`in`、`delete`、`instanceof` |
|
|
353
356
|
| 函数 | 默认参数、剩余参数、捕获闭包、`this` 绑定、箭头函数词法 `this`、`call`/`apply`/`bind`、`name`/`length` |
|
|
354
357
|
| 类 / OO | 构造函数、实例字段、方法、`static`、继承 `extends`/`super`、原型链、`instanceof` |
|
|
355
|
-
| 异步 | `async`/`await
|
|
358
|
+
| 异步 | `async`/`await` 具备真实的栈式协程挂起(pending promise 会暂停函数体,直到定时器/套接字/其他协程将其 settle)、`Promise`(`then/catch/finally`、`resolve/reject/all/allSettled/race`) |
|
|
356
359
|
| 模块 | `import`/`export`(具名 / 默认 / 再导出 / `export *`),相对路径多文件打包(`.js` 系列说明符解析到对应 `.ts` 源码,省略后缀时优先 TypeScript 后缀而非同名的 JavaScript 文件;纯 `.js` / `.jsx` / `.mjs` / `.cjs` 源码也可直接打包)与 `node_modules` 包(`exports` / `module` / `main`、作用域包与子路径),裸说明符解析到扩展模块;`node_modules` 内的 CommonJS 包会被降级(`require` / `module.exports` / `exports`),用户代码中的 `require()` 报错并提示改用 `import` |
|
|
357
360
|
| 标准库 | 数组 / 字符串 / 数字 / 对象扩展方法、类型化数组、`Math`、`JSON`、`Date`、`RegExp`、`Map`、`Set`、`Symbol`、`Error` 家族、`Object/Array/Number/String/Symbol` 静态、`console.*` |
|
|
358
361
|
| 值模型 | 64 位 NaN-boxing、统一函数 ABI(含 `this`)、闭包环境、对象原型链 |
|
|
359
|
-
| 运行时 | 字符串 / 对象 / 数组 / 类型化数组 / 闭包 / 算术 / 比较 / 可捕获异常 / Promise / 集合 / symbol / 生成器 / `fetch` / `console` |
|
|
362
|
+
| 运行时 | 字符串 / 对象 / 数组 / 类型化数组 / 闭包 / 算术 / 比较 / 可捕获异常 / Promise / 异步协程 / 集合 / symbol / 生成器 / `fetch` / `console` |
|
|
360
363
|
| 扩展 | 扩展注册表、`core`(print)、`node`(fs / path / os / process / buffer / stream / net / dgram / http,按说明符导入) |
|
|
361
364
|
| GUI(`gui` 扩展) | 自托管 HTML/CSS 渲染器窗口(SDL3 + SDL_GPU):DOM/CSS/布局、CSS `transform`/`transform-origin`、`<img>`/SVG、`<video>`/`<audio>`、`<canvas>` 2D、事件、transition(含 `transform`) |
|
|
362
365
|
| 工具链 | clang 编译 IR/C、链接、增量缓存 |
|
|
@@ -19,9 +19,18 @@ build/app.ll:382:37: error: '@.str.0' defined with type '[6 x i8]*' but expected
|
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
有类型指针在 LLVM 16 中被移除([发布说明](https://github.com/llvm/llvm-project/blob/release/15.x/llvm/docs/ReleaseNotes.rst#changes-to-the-llvm-ir)),
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
所以 xbintsc 现在**在编译任何东西之前先检查版本**:
|
|
23
|
+
|
|
24
|
+
- `xbintsc build` / `run` 一旦发现解析到的驱动低于 16 就立即停止,并给出可操作的错误,
|
|
25
|
+
而不是生成无法编译的 IR。
|
|
26
|
+
- `xbintsc doctor` 会打印 `status : ok` 或 `status : too old`,在工具链无法构建二进制时
|
|
27
|
+
以非零码退出,脚本和 CI 可以把它当作预检。
|
|
28
|
+
- 搜索时会优先选择 16+ 的 clang:Windows 上即使 `PATH` 里靠前的是旧 clang,
|
|
29
|
+
也能找到 Visual Studio 自带的 LLVM
|
|
30
|
+
(`<VS 安装目录>\VC\Tools\Llvm\x64\bin\clang.exe`)。可以用 `xbintsc_CLANG` 覆盖;
|
|
31
|
+
显式指定的旧版本会得到 "too old" 错误,而不是被静默忽略。
|
|
32
|
+
|
|
33
|
+
把 IR 拿到别处编译来绕过该限制是不受支持的。
|
|
25
34
|
|
|
26
35
|
## 总览
|
|
27
36
|
|
|
@@ -40,7 +40,8 @@
|
|
|
40
40
|
|
|
41
41
|
> 标记模板已实现,含 raw 字符串与 `String.raw`。生成器(`function*`、`yield`、`yield*`)
|
|
42
42
|
> 基于有栈协程实现,支持 `next`/`throw`/`return`、`for...of`、展开与委托;
|
|
43
|
-
> `import.meta`
|
|
43
|
+
> `import.meta` 提供 `url`、`dirname`、`filename`,由正在运行的可执行文件路径解析。
|
|
44
|
+
> `async function*` 现在会以 `UnsupportedFeature` **明确拒绝**,不再静默产出同步生成器。
|
|
44
45
|
|
|
45
46
|
### 2.2 解析器不支持
|
|
46
47
|
|
|
@@ -50,7 +51,7 @@
|
|
|
50
51
|
|
|
51
52
|
| 运算符 | 现状 | 说明 |
|
|
52
53
|
| --- | --- | --- |
|
|
53
|
-
| `new.target` | ✗ |
|
|
54
|
+
| `new.target` | ✗ | 已解析,但以 `UnsupportedFeature` 明确拒绝(无 `new.target` 语义) |
|
|
54
55
|
| `typeof` / `void` / `in` / `delete` / `instanceof` | ✓ | 映射到运行时辅助函数(`xt_typeof`、`xt_in`、`xt_delete`、`xt_instance_of`) |
|
|
55
56
|
|
|
56
57
|
---
|
|
@@ -71,6 +72,7 @@
|
|
|
71
72
|
- `JSON.parse` / `JSON.stringify`
|
|
72
73
|
- `Date`、`RegExp`(POSIX ERE 子集,支持捕获组)、`Map`、`Set`、`Promise`、`BigInt`
|
|
73
74
|
- `Array` 静态(`isArray/of/from`)、`Object` 静态、`Number` 静态、`String` 静态(`fromCharCode` / `fromCodePoint` / `raw`)
|
|
75
|
+
- 一等公民内建构造器(`const A = Array`、`new A(...)`、`A.isArray`、`x instanceof A`)与 `Object.prototype`(`hasOwnProperty`、`toString`、`valueOf`、`isPrototypeOf`、`propertyIsEnumerable`、`__proto__`),且 `Object.getPrototypeOf({}) === Object.prototype`
|
|
74
76
|
- `Error` 家族(`Error`、`TypeError`、`RangeError`、`SyntaxError`、`ReferenceError`、`EvalError`、`URIError`、`AggregateError`):支持 `new`、`instanceof`、`extends`、`String(err)` / `err.toString()` 与 `.stack`
|
|
75
77
|
|
|
76
78
|
### 3.3 仍未实现
|
|
@@ -84,7 +86,7 @@
|
|
|
84
86
|
| `AggregateError` 构造器 | ✓ `new AggregateError(errors, message)`;`Promise.any` 现以其作为 rejection |
|
|
85
87
|
| 迭代器协议 / `Symbol.iterator` / `for...of` 自定义可迭代 | ✓ 数组、字符串、`Map`、`Set`、生成器以及任何暴露 `[Symbol.iterator]()` 的对象均可在 `for...of` / 展开中使用 |
|
|
86
88
|
| 生成器(`function*`、`yield`、`yield*`、`next`/`throw`/`return`) | ✓ 基于有栈协程实现;支持 `for...of`、展开与委托。`return()` 直接结束,不执行 `finally` |
|
|
87
|
-
| 定时器 | ✓ 核心事件循环提供 `setTimeout` / `clearTimeout` / `setInterval` / `clearInterval`(返回数字 id,无 `Timeout` 对象;无 `setImmediate` / `queueMicrotask
|
|
89
|
+
| 定时器 | ✓ 核心事件循环提供 `setTimeout` / `clearTimeout` / `setInterval` / `clearInterval`(返回数字 id,无 `Timeout` 对象;无 `setImmediate` / `queueMicrotask`)。定时器 settle 的 promise 可以被 await:async 函数体在 pending promise 上挂起,定时器触发时恢复 |
|
|
88
90
|
| I/O / 进程等宿主 API | 仅通过扩展(如 Node `fs`)提供 |
|
|
89
91
|
|
|
90
92
|
### 3.4 类型化数组
|
|
@@ -103,7 +105,7 @@
|
|
|
103
105
|
| `keys` / `values` / `entries` | ~ 返回数组,而非迭代器对象 |
|
|
104
106
|
| `ArrayBuffer` / `DataView` / `.buffer` / `.byteOffset` 语义 | ✗ 无底层缓冲区类型;`.byteOffset` 恒为 0 |
|
|
105
107
|
| `BigInt64Array` / `BigUint64Array` | ✗ 未实现 |
|
|
106
|
-
| `instanceof
|
|
108
|
+
| `instanceof` 内建构造器 | ✓ `instanceof Array` / `Object` / `Map` / `Set` / `Date` / `RegExp` / `Promise` / `Error` 家族 / 类型化数组都能按名字识别,**也能通过一等公民构造器值判断**(`const A = Array; x instanceof A`);构造器可保存、传参、取别名、调用与 `new` |
|
|
107
109
|
| 基于 `Buffer` / `ArrayBuffer` 的类型化数组视图 | ✗ 构造器仅能从长度 / 数组样 / 类型化数组复制 |
|
|
108
110
|
|
|
109
111
|
---
|
|
@@ -136,13 +138,14 @@
|
|
|
136
138
|
| 解构参数 / 解构绑定 | ✓ | ✓ 已实现 |
|
|
137
139
|
| `arguments` 对象 | ✓(隐式) | ✓ 已实现(箭头函数取的是自身参数,而非外层函数的 `arguments`,与 JS 不同) |
|
|
138
140
|
| `this` 绑定 / 方法调用语义 | ✓ | ✓ 已实现(`this` 作为函数首个 ABI 参数线程化;箭头函数词法继承) |
|
|
139
|
-
| `async` / `await` / Promise | ✓ | ✓
|
|
140
|
-
| `new.target` | ✗ |
|
|
141
|
-
| 生成器 / 迭代器 / `yield` | ✓ 已实现 | `function*`、`yield`、`yield*`、`.next/.throw/.return
|
|
141
|
+
| `async` / `await` / Promise | ✓ | ✓ 已实现:基于栈式协程的真实挂起;等待 pending promise 会暂停函数体并由事件循环恢复(剩余差异见偏差表) |
|
|
142
|
+
| `new.target` | ✗ | 已解析,但以 `UnsupportedFeature` 明确拒绝(无 `new.target` 语义) |
|
|
143
|
+
| 生成器 / 迭代器 / `yield` | ✓ 已实现 | `function*`、`yield`、`yield*`、`.next/.throw/.return`;异步生成器以 `UnsupportedFeature` 拒绝 |
|
|
142
144
|
| 闭包 `arity` | — | `xt_closure_arity` 恒为 -1,未填充 |
|
|
143
145
|
| `fn.call` / `fn.apply` / `fn.bind` | ✓ | ✓ 已实现(绑定闭包不跟踪部分参数的 `length`) |
|
|
144
146
|
| `fn.name` / `fn.length` | ✓ | ✓ 已实现(从声明 / 赋值 / 属性键推断;绑定函数为 `"bound ..."` 并调整 arity) |
|
|
145
147
|
| 内置方法一等公民(`typeof arr.map`、`const f = arr.push`、`obj.method?.()`) | ✓ | ✓ 作为**未绑定**方法值实现:读取 `arr.map` 得到函数,`arr.map?.(cb)` 与 `obj.method?.()` 会把接收者作为 `this` 绑定,脱离接收者调用(`const f = arr.map; f(cb)`)会像 JavaScript 一样抛错。方法的 `name`/`length` 也一并暴露 |
|
|
148
|
+
| 内建构造器一等公民(`const A = Array`、`new A(...)`、`typeof Map`) | ✓ | ✓ 构造器是普通函数值,带 `name`/`length`、`prototype`、静态成员(`A.isArray`)与完整的 `instanceof` 协议 |
|
|
146
149
|
| `fn.toString()` | ~ | 返回原生占位字符串(`function name() { [native code] }`),而非原始源码文本 |
|
|
147
150
|
|
|
148
151
|
---
|
|
@@ -188,8 +191,7 @@
|
|
|
188
191
|
|
|
189
192
|
| 项 | 偏差 |
|
|
190
193
|
| --- | --- |
|
|
191
|
-
|
|
|
192
|
-
| `Object.getPrototypeOf({})` | 返回 `undefined`,而非 `Object.prototype` 对象 |
|
|
194
|
+
| 正则按字节匹配 | 引擎按 UTF-8 字节匹配:多字节字面量仍可匹配,但 `.` 与字符类每次只消费一个字节(`\d`/`\w` 仍是 ASCII)。`exec` / `search` / 替换回调返回的偏移会转换为 UTF-16 码元 |
|
|
193
195
|
| 全局正则 `lastIndex` | `/g`、`/y` 正则的 `test` / `exec` 不推进也不读取调用方设置的 `lastIndex` |
|
|
194
196
|
| `String.normalize` / `structuredClone` | 未实现 |
|
|
195
197
|
| 内置方法一等公民 | 以未绑定方法值实现(见第 5 节);`fn.toString()` 返回占位字符串而非源码文本 |
|
|
@@ -197,11 +199,11 @@
|
|
|
197
199
|
| 数组越界 / 稀疏 | 越界访问返回 `undefined`;对 `arr.length` 赋值会截断 / 扩展,但不区分稀疏空洞 |
|
|
198
200
|
| 内存管理 | 非移动标记-清扫回收器(在 `xt_alloc` 之后):显式根、子系统根提供者与保守 C 栈扫描。单线程、stop-the-world;无移动/压缩与分代 |
|
|
199
201
|
| 函数 `arity` / 调用参数个数 | 无参数个数校验;`fn.length` 报告声明的 arity,但调用不做校验 |
|
|
200
|
-
| `async` / `await` |
|
|
202
|
+
| `async` / `await` | 已在栈式协程上真实挂起;但对**已 settle** 的值 `await` 会同步继续,而不是像规范要求那样排入微任务,因此与 pending `.then` 回调的交错顺序可能不同。顶层 `await` 会阻塞事件循环等待,而不是让出模块主体。`fs/promises` 仍在 settle 前同步完成 I/O;`fetch` 是阻塞的;不支持 `async` 生成器 |
|
|
201
203
|
| `super` | `super.x` / `super(...)` 取 `this` 原型的原型;单级继承正确,继承深度 > 1 时可能不准确 |
|
|
202
|
-
| `Error.stack` |
|
|
204
|
+
| `Error.stack` | 仅函数级帧:每帧为 `at 名称 (文件:行)`,行号取自函数声明(最内层帧会更新为错误构造处);没有列号,生成器 / `async` 函数体不产生帧(它们会切换栈) |
|
|
203
205
|
| 模块实时绑定 | 命名空间导入与导入绑定为快照(见第 4 节) |
|
|
204
|
-
| `import.meta` |
|
|
206
|
+
| `import.meta` | ✓ `import.meta.url` / `.dirname` / `.filename`,由可执行文件路径解析 |
|
|
205
207
|
|
|
206
208
|
> 数字格式化、宽松相等、`+` / 关系运算 `ToPrimitive`、整链可选链、`finally` 提前退出、对象键顺序等均已对齐 Node,并由差分测试覆盖,故不再列为偏差。
|
|
207
209
|
|
|
@@ -216,7 +218,7 @@
|
|
|
216
218
|
| 类型检查器 | ✗ 仅定义诊断码,无 checker |
|
|
217
219
|
| 完整标准库 | 部分:Math / JSON / Date / Map / Set / RegExp / `Error` / `BigInt` / `Symbol` 已实现;String.normalize / structuredClone 缺失 |
|
|
218
220
|
| 多文件模块打包 | 部分:相对路径 `.ts` 打包、ESM `node_modules` 包、命名空间导入、裸说明符扩展模块导入已实现;循环依赖 / CommonJS / 实时绑定未实现 |
|
|
219
|
-
|
|
|
221
|
+
| 异步运行时 | ✓ `async`/`await` 在 `select(2)` reactor 上对 pending promise 挂起:定时器、TCP 套接字与 promise 回调都能恢复协程。仍缺:真正的异步 I/O 调度(`fs/promises` 会先阻塞完成 I/O 再 settle)、非阻塞 `fetch` 与 worker 线程(worker 是子进程) |
|
|
220
222
|
| Windows 二进制产物验证 | 构建层已适配(`.exe` 后缀、链接参数分支),并在 CI 中验证 |
|
|
221
223
|
| 精确的 ECMAScript 数值 / 字符串 / 比较语义 | 部分,见第 8 节 |
|
|
222
224
|
|
|
@@ -227,9 +229,9 @@
|
|
|
227
229
|
```
|
|
228
230
|
未实现(语句):namespace/module 声明
|
|
229
231
|
|
|
230
|
-
未实现(表达式):new.target
|
|
232
|
+
未实现(表达式):new.target(会给出明确的 UnsupportedFeature)
|
|
231
233
|
|
|
232
|
-
未实现(函数):`fn.toString()`
|
|
234
|
+
未实现(函数):`fn.toString()` 源码文本、异步生成器(已明确拒绝)
|
|
233
235
|
|
|
234
236
|
未实现(类/面向对象):abstract/implements、访问控制、父子类 #x 同名
|
|
235
237
|
|
|
@@ -240,8 +242,8 @@
|
|
|
240
242
|
|
|
241
243
|
未实现(类型系统):类型检查、泛型实例化、断言语义、可选链类型窄化
|
|
242
244
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
+
未实现(运行时):异步 I/O 调度、
|
|
246
|
+
全局正则 lastIndex
|
|
245
247
|
|
|
246
248
|
未实现(工程):类型检查器
|
|
247
249
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xbintsc",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.6",
|
|
4
4
|
"description": "xbintsc - a TypeScript binary compiler (TypeScript -> LLVM IR -> native binary)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -41,6 +41,8 @@
|
|
|
41
41
|
"runtime:clean": "node -e \"require('fs').rmSync('build/runtime-obj',{recursive:true,force:true});require('fs').rmSync('runtime/lib',{recursive:true,force:true})\"",
|
|
42
42
|
"xbintsc": "tsx src/cli/main.ts",
|
|
43
43
|
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
44
|
+
"check:version": "tsx scripts/check-version.ts",
|
|
45
|
+
"bench": "tsx scripts/bench.ts",
|
|
44
46
|
"lint": "eslint . && tsx scripts/check-file-length.ts",
|
|
45
47
|
"test": "vitest run",
|
|
46
48
|
"test:watch": "vitest",
|
|
@@ -25,7 +25,7 @@ static xt_value xt_buffer_from(xt_value value, const char *encoding) {
|
|
|
25
25
|
xt_value text = xt_to_string(value);
|
|
26
26
|
xt_string *string = xt_as_string(text);
|
|
27
27
|
size_t decoded = 0;
|
|
28
|
-
unsigned char *bytes = xt_node_decode(string
|
|
28
|
+
unsigned char *bytes = xt_node_decode(xt_string_bytes(string), string->length, encoding, &decoded);
|
|
29
29
|
if (!bytes) return xt_buffer_new(0, NULL);
|
|
30
30
|
xt_value result = xt_buffer_from_bytes(bytes, decoded);
|
|
31
31
|
free(bytes);
|
|
@@ -49,7 +49,7 @@ static xt_value xt_buffer_alloc(uint32_t size, xt_value fill, const char *encodi
|
|
|
49
49
|
xt_value text = xt_to_string(fill);
|
|
50
50
|
xt_string *string = xt_as_string(text);
|
|
51
51
|
size_t decoded = 0;
|
|
52
|
-
unsigned char *bytes = xt_node_decode(string
|
|
52
|
+
unsigned char *bytes = xt_node_decode(xt_string_bytes(string), string->length, encoding, &decoded);
|
|
53
53
|
if (!bytes || decoded == 0) {
|
|
54
54
|
free(bytes);
|
|
55
55
|
return buffer;
|
|
@@ -93,7 +93,7 @@ static xt_value xt_buffer_method_write(xt_value thisValue, xt_value env, int32_t
|
|
|
93
93
|
uint32_t offset = argc > 1 ? (uint32_t)xt_to_number(argv[1]) : 0;
|
|
94
94
|
const char *encoding = argc > 3 ? xt_node_encoding(argv[3]) : NULL;
|
|
95
95
|
size_t decoded = 0;
|
|
96
|
-
unsigned char *bytes = xt_node_decode(string
|
|
96
|
+
unsigned char *bytes = xt_node_decode(xt_string_bytes(string), string->length, encoding, &decoded);
|
|
97
97
|
uint32_t available = xt_buffer_length(thisValue);
|
|
98
98
|
uint32_t written = 0;
|
|
99
99
|
for (size_t i = 0; i < decoded && offset + written < available; i++) {
|
|
@@ -19,7 +19,7 @@ static const unsigned char *xt_buffer_search_needle(xt_value value, const char *
|
|
|
19
19
|
xt_value text = xt_to_string(value);
|
|
20
20
|
xt_string *string = xt_as_string(text);
|
|
21
21
|
size_t decoded = 0;
|
|
22
|
-
unsigned char *bytes = xt_node_decode(string
|
|
22
|
+
unsigned char *bytes = xt_node_decode(xt_string_bytes(string), string->length, encoding, &decoded);
|
|
23
23
|
*length = decoded;
|
|
24
24
|
return bytes;
|
|
25
25
|
}
|
|
@@ -82,6 +82,27 @@ static char *read_temp(FILE *file) {
|
|
|
82
82
|
return buffer;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
/*
|
|
86
|
+
* MSVC's `_spawnvp` builds the child command line from argv without quoting
|
|
87
|
+
* argv[0]. When the executable path contains a space — the default install
|
|
88
|
+
* location is "C:\Program Files\…" — the child sees the path split into several
|
|
89
|
+
* arguments ("Files\Microsoft", "Visual", …). Quote argv[0] ourselves. Returns
|
|
90
|
+
* NULL when no quoting is needed (the caller keeps the original pointer).
|
|
91
|
+
*/
|
|
92
|
+
static char *quote_argv0(char **child_argv) {
|
|
93
|
+
const char *arg = child_argv[0];
|
|
94
|
+
if (arg == NULL || strchr(arg, ' ') == NULL) return NULL;
|
|
95
|
+
size_t length = strlen(arg);
|
|
96
|
+
char *quoted = (char *)malloc(length + 3);
|
|
97
|
+
if (!quoted) return NULL;
|
|
98
|
+
quoted[0] = '"';
|
|
99
|
+
memcpy(quoted + 1, arg, length);
|
|
100
|
+
quoted[length + 1] = '"';
|
|
101
|
+
quoted[length + 2] = 0;
|
|
102
|
+
child_argv[0] = quoted;
|
|
103
|
+
return quoted;
|
|
104
|
+
}
|
|
105
|
+
|
|
85
106
|
xt_value xt_child_process_spawn_sync(int32_t argc, xt_value *argv) {
|
|
86
107
|
const char *command = argc > 0 ? xt_string_data(xt_to_string(argv[0])) : NULL;
|
|
87
108
|
if (!command) command = "";
|
|
@@ -91,6 +112,7 @@ xt_value xt_child_process_spawn_sync(int32_t argc, xt_value *argv) {
|
|
|
91
112
|
int count = 0;
|
|
92
113
|
char **child_argv = (char **)build_argv(command, args, &count);
|
|
93
114
|
if (!child_argv) return make_result(-1, "", "out of memory");
|
|
115
|
+
char *quoted_command = quote_argv0(child_argv);
|
|
94
116
|
|
|
95
117
|
char previous[4096];
|
|
96
118
|
int had_cwd = cwd && _getcwd(previous, sizeof(previous)) != NULL;
|
|
@@ -99,6 +121,7 @@ xt_value xt_child_process_spawn_sync(int32_t argc, xt_value *argv) {
|
|
|
99
121
|
if (cwd) _chdir(cwd);
|
|
100
122
|
intptr_t inherit_rc = _spawnvp(_P_WAIT, command, (const char *const *)child_argv);
|
|
101
123
|
if (had_cwd) _chdir(previous);
|
|
124
|
+
free(quoted_command);
|
|
102
125
|
free(child_argv);
|
|
103
126
|
return make_result(inherit_rc < 0 ? -1 : (double)inherit_rc, "", "");
|
|
104
127
|
}
|
|
@@ -106,6 +129,7 @@ xt_value xt_child_process_spawn_sync(int32_t argc, xt_value *argv) {
|
|
|
106
129
|
FILE *out_file = tmpfile();
|
|
107
130
|
FILE *err_file = tmpfile();
|
|
108
131
|
if (!out_file || !err_file) {
|
|
132
|
+
free(quoted_command);
|
|
109
133
|
free(child_argv);
|
|
110
134
|
if (out_file) fclose(out_file);
|
|
111
135
|
if (err_file) fclose(err_file);
|
|
@@ -136,6 +160,7 @@ xt_value xt_child_process_spawn_sync(int32_t argc, xt_value *argv) {
|
|
|
136
160
|
char *err = read_temp(err_file);
|
|
137
161
|
fclose(out_file);
|
|
138
162
|
fclose(err_file);
|
|
163
|
+
free(quoted_command);
|
|
139
164
|
free(child_argv);
|
|
140
165
|
|
|
141
166
|
xt_value result = make_result(rc < 0 ? -1 : (double)rc, out, err);
|
|
@@ -76,7 +76,7 @@ static unsigned char *xt_fs_value_bytes(xt_value value, size_t *outLength) {
|
|
|
76
76
|
*outLength = 0;
|
|
77
77
|
return NULL;
|
|
78
78
|
}
|
|
79
|
-
if (length > 0) memcpy(bytes, string
|
|
79
|
+
if (length > 0) memcpy(bytes, xt_string_bytes(string), length);
|
|
80
80
|
*outLength = length;
|
|
81
81
|
return bytes;
|
|
82
82
|
}
|
package/runtime/rt.h
CHANGED
|
@@ -92,9 +92,14 @@ xt_value xt_bool(int b);
|
|
|
92
92
|
xt_value xt_number(double d);
|
|
93
93
|
xt_value xt_string_new(const char *data, size_t len);
|
|
94
94
|
xt_value xt_string_from_cstr(const char *data);
|
|
95
|
-
/** Raw UTF-8 bytes of a string value (NULL for non-strings); not NUL-safe.
|
|
95
|
+
/** Raw UTF-8 bytes of a string value (NULL for non-strings); not NUL-safe.
|
|
96
|
+
* Materialises a lazily concatenated string, so the returned pointer is stable
|
|
97
|
+
* until the string is collected. */
|
|
96
98
|
const char *xt_string_data(xt_value value);
|
|
99
|
+
/** Byte length of the UTF-8 storage (what I/O and C extensions consume). */
|
|
97
100
|
int32_t xt_string_length_value(xt_value value);
|
|
101
|
+
/** JavaScript `String.prototype.length`: UTF-16 code units. */
|
|
102
|
+
int32_t xt_string_utf16_length_value(xt_value value);
|
|
98
103
|
|
|
99
104
|
/* -- bigint -------------------------------------------------------------- */
|
|
100
105
|
xt_value xt_bigint_from_string(const char *data, size_t len);
|
|
@@ -119,8 +124,14 @@ xt_value xt_function_set_metadata(xt_value fn, xt_value name, int32_t arity);
|
|
|
119
124
|
xt_value xt_this(void);
|
|
120
125
|
xt_value xt_new(xt_value ctor, int32_t argc, xt_value *argv);
|
|
121
126
|
xt_value xt_instance_of(xt_value value, xt_value ctor);
|
|
127
|
+
/** `value instanceof <built-in constructor>`; id from `BUILTIN_INSTANCEOF`. */
|
|
128
|
+
xt_value xt_instance_of_builtin(xt_value value, int32_t id);
|
|
122
129
|
xt_value xt_function_set_prototype(xt_value fn, xt_value proto);
|
|
123
130
|
xt_value xt_function_get_prototype(xt_value fn);
|
|
131
|
+
/** Mark a closure as a generator so calling it creates a suspended generator. */
|
|
132
|
+
xt_value xt_function_set_generator(xt_value fn);
|
|
133
|
+
/** Mark a closure as an `async` function so calling it starts a coroutine. */
|
|
134
|
+
xt_value xt_function_set_async(xt_value fn);
|
|
124
135
|
|
|
125
136
|
/* -- conversions ---------------------------------------------------------- */
|
|
126
137
|
int xt_truthy(xt_value v);
|
|
@@ -159,6 +170,10 @@ xt_value xt_not(xt_value a);
|
|
|
159
170
|
/* -- objects -------------------------------------------------------------- */
|
|
160
171
|
xt_value xt_object_new(void);
|
|
161
172
|
xt_value xt_object_new_with_proto(xt_value proto);
|
|
173
|
+
/** The shared `Object.prototype` object (root of the ordinary object chain). */
|
|
174
|
+
xt_value xt_object_prototype(void);
|
|
175
|
+
/** The shared `Function.prototype` object. */
|
|
176
|
+
xt_value xt_function_prototype(void);
|
|
162
177
|
xt_value xt_object_get(xt_value obj, xt_value key);
|
|
163
178
|
xt_value xt_object_get_prototype(xt_value obj);
|
|
164
179
|
xt_value xt_object_set_prototype(xt_value obj, xt_value proto);
|
|
@@ -177,6 +192,8 @@ xt_value xt_object_values(xt_value obj);
|
|
|
177
192
|
xt_value xt_object_entries(xt_value obj);
|
|
178
193
|
xt_value xt_object_assign(int32_t argc, xt_value *argv);
|
|
179
194
|
xt_value xt_object_spread(xt_value target, xt_value source);
|
|
195
|
+
/** Own enumerable properties of `source` except the keys in `argv` (object rest). */
|
|
196
|
+
xt_value xt_object_rest(xt_value source, int32_t argc, xt_value *argv);
|
|
180
197
|
|
|
181
198
|
/* -- symbols -------------------------------------------------------------- */
|
|
182
199
|
/** Implements `Symbol(description)`. */
|
|
@@ -187,6 +204,17 @@ xt_value xt_symbol_static(xt_value name, int32_t argc, xt_value *argv);
|
|
|
187
204
|
xt_value xt_symbol_get(xt_value name);
|
|
188
205
|
|
|
189
206
|
/* -- standard library dispatch -------------------------------------------- */
|
|
207
|
+
/* -- built-in constructors as first-class values -------------------------- */
|
|
208
|
+
/** The first-class value of a built-in constructor (`Array`, `Map`, ...). */
|
|
209
|
+
xt_value xt_builtin_constructor(xt_value name);
|
|
210
|
+
/** A static method/value of a first-class constructor (`A.isArray`, ...). */
|
|
211
|
+
xt_value xt_builtin_static_value(xt_value ctor, xt_value key);
|
|
212
|
+
/** The constructor prototype for a runtime object kind (`Map` -> Map.prototype). */
|
|
213
|
+
xt_value xt_builtin_prototype_for_kind(int32_t kind);
|
|
214
|
+
/** `Array(...)` / `new Array(...)`. */
|
|
215
|
+
xt_value xt_array_ctor(int32_t argc, xt_value *argv);
|
|
216
|
+
/** `Object(...)` / `new Object(...)`. */
|
|
217
|
+
xt_value xt_object_ctor(int32_t argc, xt_value *argv);
|
|
190
218
|
/** Call `target[name](...)`, falling back to built-in Array/String methods. */
|
|
191
219
|
xt_value xt_call_method(xt_value target, xt_value name, int32_t argc, xt_value *argv);
|
|
192
220
|
/** Implements `Math.<name>(...)`; the name is interned by the compiler. */
|
|
@@ -201,6 +229,14 @@ xt_value xt_object_static(xt_value name, int32_t argc, xt_value *argv);
|
|
|
201
229
|
/** Implements `Number.<name>(...)` / `String.<name>(...)` statics. */
|
|
202
230
|
xt_value xt_number_static(xt_value name, int32_t argc, xt_value *argv);
|
|
203
231
|
xt_value xt_string_static(xt_value name, int32_t argc, xt_value *argv);
|
|
232
|
+
/** Typed-array constructor/static/prototype dispatch by constructor name. */
|
|
233
|
+
xt_value xt_typed_array_ctor_by_name(xt_value name, int32_t argc, xt_value *argv);
|
|
234
|
+
xt_value xt_typed_array_static_by_name(xt_value name, xt_value method, int32_t argc, xt_value *argv);
|
|
235
|
+
xt_value xt_typed_array_prototype(xt_value name);
|
|
236
|
+
/** Error-family construction and prototype lookup by constructor name. */
|
|
237
|
+
xt_value xt_error_ctor_by_name(xt_value name, int32_t argc, xt_value *argv);
|
|
238
|
+
xt_value xt_error_prototype(xt_value name);
|
|
239
|
+
xt_value xt_error_constructor(xt_value name);
|
|
204
240
|
/** Map / Set constructors and dispatch. */
|
|
205
241
|
xt_value xt_map_ctor(int32_t argc, xt_value *argv);
|
|
206
242
|
xt_value xt_set_ctor(int32_t argc, xt_value *argv);
|
|
@@ -308,6 +344,8 @@ extern char **xt_program_argv;
|
|
|
308
344
|
|
|
309
345
|
/* -- arrays --------------------------------------------------------------- */
|
|
310
346
|
xt_value xt_array_new(int32_t count, xt_value *items);
|
|
347
|
+
/** The shared `Array.prototype` array. */
|
|
348
|
+
xt_value xt_array_prototype(void);
|
|
311
349
|
xt_value xt_array_get(xt_value arr, xt_value index);
|
|
312
350
|
xt_value xt_array_set(xt_value arr, xt_value index, xt_value value);
|
|
313
351
|
xt_value xt_array_push(xt_value arr, xt_value value);
|
|
@@ -340,6 +378,16 @@ void xt_throw(xt_value v);
|
|
|
340
378
|
void *xt_try_enter(void);
|
|
341
379
|
xt_value xt_try_exception(void *frame);
|
|
342
380
|
void xt_try_leave(void *frame);
|
|
381
|
+
/**
|
|
382
|
+
* JavaScript-level shadow stack. Generated code pushes `(name, file, line)` on
|
|
383
|
+
* function entry and pops before returning; `Error` construction walks it to
|
|
384
|
+
* build `.stack`, and a fatal native signal dumps it. The strings are static
|
|
385
|
+
* module data, so the runtime never owns them.
|
|
386
|
+
*/
|
|
387
|
+
void xt_stack_push(const char *name, const char *file, int32_t line);
|
|
388
|
+
void xt_stack_pop(void);
|
|
389
|
+
/** Set the innermost frame's line (called just before `new Error(...)`). */
|
|
390
|
+
void xt_stack_set_line(int32_t line);
|
|
343
391
|
void xt_console_log(int32_t argc, xt_value *argv);
|
|
344
392
|
void xt_console_info(int32_t argc, xt_value *argv);
|
|
345
393
|
void xt_console_warn(int32_t argc, xt_value *argv);
|