xbintsc 0.3.79 → 0.3.87
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/README.md +13 -5
- package/README.zh-CN.md +13 -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/invocation.js +5 -1
- 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 +5 -2
- 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 -0
- package/dist/src/codegen/generator/module.js +76 -6
- 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 +5 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/statements/control-flow.js +1 -1
- 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 +7 -0
- package/dist/src/codegen/generator/tables.js +25 -0
- 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 +22 -3
- package/dist/src/driver/compiler.js +49 -58
- 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/extensions/gui/index.js +10 -2
- package/dist/src/extensions/gui/index.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/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/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/gui-example-svg.test.d.ts +21 -0
- package/dist/tests/e2e/gui-example-svg.test.js +105 -0
- package/dist/tests/e2e/gui-example-svg.test.js.map +1 -0
- package/dist/tests/e2e/gui-transform.test.d.ts +7 -0
- package/dist/tests/e2e/gui-transform.test.js +198 -0
- package/dist/tests/e2e/gui-transform.test.js.map +1 -0
- 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/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 +7 -0
- package/doc/ai/contributing.md +7 -1
- package/doc/ai/extensions.md +5 -1
- package/doc/ai/language-support.md +4 -4
- package/doc/ai/troubleshooting.md +39 -2
- package/doc/ai/zh-CN/cli.md +2 -0
- package/doc/ai/zh-CN/contributing.md +6 -2
- package/doc/ai/zh-CN/extensions.md +5 -1
- package/doc/ai/zh-CN/language-support.md +4 -4
- package/doc/ai/zh-CN/troubleshooting.md +35 -2
- package/doc/gui/animation.md +53 -2
- package/doc/gui/api.md +1 -1
- package/doc/gui/dom.md +6 -1
- package/doc/gui/input.md +4 -1
- package/doc/gui/known-issues.md +16 -4
- package/doc/gui/layout.md +36 -0
- package/doc/gui/rendering.md +15 -0
- package/doc/gui.md +32 -3
- package/doc/implemented.md +4 -4
- package/doc/requirements.md +13 -4
- package/doc/unimplemented.md +11 -10
- package/doc/zh-CN/DESIGN.md +15 -9
- package/doc/zh-CN/gui/animation.md +49 -2
- package/doc/zh-CN/gui/api.md +1 -1
- package/doc/zh-CN/gui/dom.md +6 -1
- package/doc/zh-CN/gui/input.md +2 -0
- package/doc/zh-CN/gui/known-issues.md +12 -2
- package/doc/zh-CN/gui/layout.md +31 -0
- package/doc/zh-CN/gui/rendering.md +11 -0
- package/doc/zh-CN/gui.md +28 -3
- package/doc/zh-CN/implemented.md +4 -4
- package/doc/zh-CN/requirements.md +12 -3
- package/doc/zh-CN/unimplemented.md +10 -9
- package/package.json +3 -1
- package/runtime/ext_gui/document.cpp +21 -3
- package/runtime/ext_gui/document.h +4 -1
- package/runtime/ext_gui/dom_api_node.cpp +6 -4
- package/runtime/ext_gui/layout.cpp +78 -1
- package/runtime/ext_gui/layout.h +21 -0
- package/runtime/ext_gui/paint.cpp +48 -15
- package/runtime/ext_gui/paint.h +8 -2
- package/runtime/ext_gui/renderer.cpp +4 -2
- package/runtime/ext_gui/renderer_image.cpp +2 -1
- package/runtime/ext_gui/renderer_internal.h +6 -1
- package/runtime/ext_gui/renderer_text.cpp +37 -15
- package/runtime/ext_gui/style.h +10 -0
- package/runtime/ext_gui/style_print.cpp +6 -0
- package/runtime/ext_gui/style_values.cpp +43 -0
- package/runtime/ext_gui/transform.cpp +412 -0
- package/runtime/ext_gui/transform.h +112 -0
- package/runtime/ext_gui/window.cpp +6 -4
- 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 +17 -1
- package/runtime/rt_internal.h +47 -4
- package/runtime/xt_alloc.c +14 -2
- package/runtime/xt_bigint/conversions.inc +1 -1
- package/runtime/xt_builtins.c +136 -14
- package/runtime/xt_containers/access.inc +17 -16
- package/runtime/xt_containers/objects.inc +4 -3
- package/runtime/xt_io/exception.inc +171 -2
- package/runtime/xt_io/inspect.inc +15 -13
- package/runtime/xt_io.c +5 -0
- package/runtime/xt_stdlib/arrays.inc +2 -2
- package/runtime/xt_stdlib/dispatch.inc +2 -2
- package/runtime/xt_stdlib/strings.inc +33 -21
- package/runtime/xt_stdlib2/array-statics.inc +2 -1
- package/runtime/xt_stdlib2/arrays.inc +1 -1
- package/runtime/xt_stdlib2/error.inc +22 -6
- package/runtime/xt_stdlib2/json.inc +3 -2
- package/runtime/xt_stdlib2/number-string-statics.inc +3 -1
- package/runtime/xt_stdlib2/regexp-match.inc +48 -33
- package/runtime/xt_stdlib2/strings.inc +23 -14
- package/runtime/xt_symbol.c +1 -1
- package/runtime/xt_values/comparison.inc +2 -2
- package/runtime/xt_values/constructors.inc +10 -5
- package/runtime/xt_values/conversions.inc +4 -3
- package/runtime/xt_values/strings.inc +78 -4
- 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/invocation.ts +5 -0
- 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 +5 -2
- package/src/codegen/generator/generator.ts +18 -2
- package/src/codegen/generator/module.ts +78 -6
- package/src/codegen/generator/numeric.ts +158 -0
- package/src/codegen/generator/state.ts +22 -0
- package/src/codegen/generator/statements/control-flow.ts +1 -1
- package/src/codegen/generator/statements/dispatch.ts +3 -0
- package/src/codegen/generator/statements/variables.ts +8 -2
- package/src/codegen/generator/tables.ts +26 -0
- package/src/driver/bundler/merge.ts +39 -5
- package/src/driver/compiler.ts +68 -56
- package/src/driver/fingerprint.ts +85 -0
- package/src/driver/toolchain-provider.ts +17 -16
- package/src/driver/toolchain.ts +210 -21
- package/src/extensions/gui/index.ts +10 -2
- package/src/parser/expressions.ts +20 -1
package/doc/DESIGN.md
CHANGED
|
@@ -41,16 +41,21 @@ xt_value fn(xt_value env, int32_t argc, xt_value *argv);
|
|
|
41
41
|
|
|
42
42
|
`env` threads captured variables by reference through boxes, so direct calls and
|
|
43
43
|
closure calls share a single code path. JavaScript semantics that are awkward to
|
|
44
|
-
inline (`+` coercion,
|
|
45
|
-
|
|
44
|
+
inline (`+` coercion, property access, inspection) are delegated to `@xt_*`
|
|
45
|
+
runtime calls. Numeric arithmetic and comparison are the exception: codegen emits
|
|
46
|
+
the double fast path inline (`numeric.ts`) and calls the runtime for the coercing
|
|
47
|
+
cases.
|
|
46
48
|
|
|
47
49
|
### Runtime
|
|
48
50
|
|
|
49
|
-
`runtime
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
stay
|
|
51
|
+
`runtime/` implements strings, objects, arrays, closures, arithmetic, comparison,
|
|
52
|
+
exceptions and Node-like `console.log` inspection. It is split by concern into
|
|
53
|
+
translation units (`xt_values.c`, `xt_containers.c`, `xt_stdlib.c`,
|
|
54
|
+
`xt_builtins.c`, `xt_io.c`, `xt_alloc.c`, …), each `#include`-ing its
|
|
55
|
+
implementation fragments (`.inc`) so files stay small without changing the link
|
|
56
|
+
surface. It uses a non-moving mark-sweep collector behind `xt_alloc` (explicit
|
|
57
|
+
roots, subsystem root providers and a conservative C-stack scan), so the
|
|
58
|
+
collector's internals stay isolated from the compiler.
|
|
54
59
|
|
|
55
60
|
### Replacing llc
|
|
56
61
|
|
|
@@ -103,15 +108,18 @@ found on `PATH` (the MSVC ABI when LLVM + the Visual Studio C++ build tools are
|
|
|
103
108
|
installed), and each manifest declares any platform-specific linker flags. See
|
|
104
109
|
`examples/extensions/` and `runtime/xt_ext.h` / `runtime/xt_ext.rs`.
|
|
105
110
|
|
|
106
|
-
## Self-hosting
|
|
111
|
+
## Self-hosting
|
|
107
112
|
|
|
108
|
-
The compiler itself
|
|
109
|
-
|
|
110
|
-
|
|
113
|
+
The compiler compiles itself: `xbintsc build src/cli/main.ts --ext node` produces
|
|
114
|
+
a working `xbintsc` binary, and the emitted IR is a fixpoint from the first
|
|
115
|
+
generation onward. CI builds those binaries for every supported platform and
|
|
116
|
+
checks the fixpoint. The runtime stays in C; rewriting it in TypeScript is an
|
|
117
|
+
option for later, not a prerequisite for self-hosting.
|
|
111
118
|
|
|
112
119
|
## Tests
|
|
113
120
|
|
|
114
121
|
Organised by module: `tests/lexer`, `tests/parser`, `tests/binder`,
|
|
115
122
|
`tests/codegen`, `tests/driver`, `tests/extensions`, `tests/cli`, `tests/e2e`.
|
|
116
|
-
When
|
|
123
|
+
When a supported clang (16+, the same version gate `build` applies) is present,
|
|
124
|
+
e2e tests really compile and run binaries; otherwise
|
|
117
125
|
they are skipped automatically.
|
package/doc/ai/cli.md
CHANGED
|
@@ -36,6 +36,8 @@ unknown command prints an error plus the help text and exits 1.
|
|
|
36
36
|
--app-id <id> macOS bundle identifier (e.g. com.example.demo)
|
|
37
37
|
--force Ignore the incremental cache
|
|
38
38
|
--verbose Print progress information
|
|
39
|
+
--time Print per-phase build timings
|
|
40
|
+
--debug Emit debug info (DWARF/CodeView) and keep frame pointers
|
|
39
41
|
```
|
|
40
42
|
|
|
41
43
|
Parsing details that occasionally surprise:
|
|
@@ -46,6 +48,11 @@ Parsing details that occasionally surprise:
|
|
|
46
48
|
`run`, or is a positional for the other commands.
|
|
47
49
|
- `-o` consumes the next argument unconditionally; the other value flags leave
|
|
48
50
|
the value unset when the next argument starts with `-`.
|
|
51
|
+
- `-o`/`output` may name a directory that does not exist yet: the driver creates
|
|
52
|
+
the parent directories of the output path. (`--out` likewise creates its
|
|
53
|
+
directory.) Without that, an explicit path such as `-o dist/app.exe` where
|
|
54
|
+
`dist/` was missing used to fail inside the linker, since clang — not xbintsc —
|
|
55
|
+
is what writes the executable.
|
|
49
56
|
|
|
50
57
|
## Project config
|
|
51
58
|
|
package/doc/ai/contributing.md
CHANGED
|
@@ -38,6 +38,7 @@ it. Release tags are created by `release.yml`, never by the hook.
|
|
|
38
38
|
| `npm run test:watch` | vitest in watch mode |
|
|
39
39
|
| `npm run coverage` | V8 coverage of the TypeScript compiler (`src/`) |
|
|
40
40
|
| `npm run coverage:runtime` | LLVM coverage of the C runtime (`runtime/`) |
|
|
41
|
+
| `npm run bench` | build and time the fixed benchmark suite (optionally vs Node) |
|
|
41
42
|
|
|
42
43
|
Unit tests live one directory per module under `tests/` (`lexer`, `parser`,
|
|
43
44
|
`binder`, `codegen`, `driver`, `extensions`, `cli`, `e2e`) and mirror the source
|
|
@@ -103,7 +104,12 @@ diff scratch/ref.ll scratch/gen2.ll
|
|
|
103
104
|
in [../../src/codegen/values.ts](../../src/codegen/values.ts) and
|
|
104
105
|
[../../runtime/rt.h](../../runtime/rt.h); change both together or not at all.
|
|
105
106
|
- Awkward JS semantics (`+` coercion, relational comparison, property access,
|
|
106
|
-
inspection) are delegated to `@xt_*` runtime calls
|
|
107
|
+
inspection) are delegated to `@xt_*` runtime calls. Numeric arithmetic and
|
|
108
|
+
comparison are the exception: codegen inlines the two-double fast path
|
|
109
|
+
(`src/codegen/generator/numeric.ts`) and calls the runtime for everything else.
|
|
110
|
+
- String literals are interned: each distinct literal is materialised once in
|
|
111
|
+
`main`, stored in a GC-rooted global, and loaded at each use. Property names
|
|
112
|
+
therefore never allocate per access.
|
|
107
113
|
- The GC is a non-moving mark-sweep collector: new heap objects go through
|
|
108
114
|
`xt_alloc`, and a value must be reachable from an explicit root slot, a
|
|
109
115
|
registered root provider (the event loop, the microtask queue) or the
|
package/doc/ai/extensions.md
CHANGED
|
@@ -76,7 +76,11 @@ with elements and CSS (see `examples/gui/media.ts`). Video frames and audio PCM
|
|
|
76
76
|
are decoded on the main thread. `<canvas>` is supported too: `getContext("2d")`
|
|
77
77
|
returns a context whose fills, paths, text and `drawImage` are rasterised by a
|
|
78
78
|
self-written CPU rasteriser, and element handles expose `canvas` drawing plus
|
|
79
|
-
`width`/`height`.
|
|
79
|
+
`width`/`height`. CSS `transform`/`transform-origin` work as paint-time
|
|
80
|
+
effects, so a box (and the text, images and children in it) can be translated,
|
|
81
|
+
scaled and rotated without reflowing anything — animate it per frame from
|
|
82
|
+
`requestAnimationFrame` or with `transition: transform` (see
|
|
83
|
+
`examples/gui/pelican-svg`). If that archive is missing for
|
|
80
84
|
your platform, the build fails with an actionable message; design and roadmap
|
|
81
85
|
live in [../gui.md](../gui.md) (overview; the engine is documented by function
|
|
82
86
|
under [`doc/gui/`](../gui/)), and the scripting surface in
|
|
@@ -45,8 +45,8 @@ Canonical detail (always current, much longer):
|
|
|
45
45
|
| Destructuring (bindings, parameters, nested) | ✅ | defaults + rest supported |
|
|
46
46
|
| `delete`, `in`, `instanceof`, `typeof` | ✅ | |
|
|
47
47
|
| Comma operator, `void` | ✅ | |
|
|
48
|
-
| `new.target` | 🚫 |
|
|
49
|
-
| `import.meta` |
|
|
48
|
+
| `new.target` | 🚫 | parsed, then rejected with a clear `UnsupportedFeature` |
|
|
49
|
+
| `import.meta` | ✅ | `url`, `dirname`, `filename` (resolved from the executable path) |
|
|
50
50
|
| `super` | ⚠️ | single-level inheritance correct; depth > 1 may be inaccurate |
|
|
51
51
|
|
|
52
52
|
## Functions, classes, objects
|
|
@@ -103,7 +103,7 @@ URI functions.
|
|
|
103
103
|
| Missing or different | Status |
|
|
104
104
|
| --- | --- |
|
|
105
105
|
| `String.prototype.normalize`, `structuredClone` | 🚫 |
|
|
106
|
-
| `Error.stack` capture |
|
|
106
|
+
| `Error.stack` capture | ⚠️ function-level frames (name/file/line), no columns; generator bodies are omitted |
|
|
107
107
|
| `Object.getPrototypeOf({})` | ⚠️ returns `undefined`, not `Object.prototype` |
|
|
108
108
|
| Global RegExp `lastIndex` | ⚠️ `test`/`exec` ignore it for `/g` and `/y` |
|
|
109
109
|
| Sparse array holes, array out-of-bounds | ⚠️ holes are not tracked distinctly; out-of-bounds reads give `undefined` |
|
|
@@ -122,7 +122,7 @@ See section 3 of [../unimplemented.md](../unimplemented.md) for the full list.
|
|
|
122
122
|
| `require()` / CommonJS | 🚫 | rejected with a hint to use `import` |
|
|
123
123
|
| Circular dependencies | 🚫 | |
|
|
124
124
|
| Live bindings | ⚠️ | imports and namespace members are snapshots |
|
|
125
|
-
| `
|
|
125
|
+
| `__dirname`, `__filename` | 🚫 | use `import.meta.dirname` / `import.meta.filename` |
|
|
126
126
|
|
|
127
127
|
## Strings, numbers, memory
|
|
128
128
|
|
|
@@ -22,8 +22,12 @@ D:\...\build\app.ll:382:37: error: '@.str.0' defined with type '[6 x i8]*' but e
|
|
|
22
22
|
|
|
23
23
|
The compiler emits LLVM IR that relies on opaque pointers; typed pointers were
|
|
24
24
|
removed in LLVM 16 ([LLVM release notes](https://github.com/llvm/llvm-project/blob/release/15.x/llvm/docs/ReleaseNotes.rst#changes-to-the-llvm-ir)).
|
|
25
|
-
|
|
26
|
-
newer
|
|
25
|
+
`xbintsc build`/`run` check the version up front and stop with "reports clang
|
|
26
|
+
15.0.2, but xbintsc requires clang 16 or newer", and `xbintsc doctor` prints
|
|
27
|
+
`status : ok` or `status : too old` (exiting non-zero in the latter case). The
|
|
28
|
+
search prefers a supported clang — including the LLVM bundled with Visual Studio
|
|
29
|
+
on Windows — so an old `/usr/bin/clang` is skipped when a newer one is installed.
|
|
30
|
+
To choose one explicitly:
|
|
27
31
|
|
|
28
32
|
```bash
|
|
29
33
|
export xbintsc_CLANG=/usr/lib/llvm-18/bin/clang # PowerShell: $env:xbintsc_CLANG = "C:\Program Files\LLVM\bin\clang.exe"
|
|
@@ -118,6 +122,39 @@ described in [../gui.md](../gui.md).
|
|
|
118
122
|
Windows, embedding a PE icon needs `llvm-rc` or `windres`; `doctor` reports which
|
|
119
123
|
one was found, and a missing one is only fatal when an icon was requested.
|
|
120
124
|
|
|
125
|
+
## Reading a stack trace
|
|
126
|
+
|
|
127
|
+
`Error.stack` is captured by codegen, not from the C runtime's native frames:
|
|
128
|
+
every non-generator function pushes `{name, file, line}` on entry and pops it
|
|
129
|
+
before returning. Frames look like
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
Error: boom
|
|
133
|
+
at inner (app.ts:12)
|
|
134
|
+
at module (app.ts:3)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Lines are function declaration lines, except that the innermost frame is moved
|
|
138
|
+
to the `new Error(...)` line; there are no column numbers. Generator bodies are
|
|
139
|
+
not tracked because they switch stacks. A fatal native signal prints
|
|
140
|
+
`xbintsc: fatal signal …` followed by the same frames, so a crash without a
|
|
141
|
+
debugger still shows which JavaScript functions were running.
|
|
142
|
+
|
|
143
|
+
## Debugging with gdb / lldb / WinDbg
|
|
144
|
+
|
|
145
|
+
`xbintsc build app.ts --debug` emits LLVM debug metadata and passes `-g
|
|
146
|
+
-fno-omit-frame-pointer` to clang, so the object carries DWARF (Linux/macOS) or
|
|
147
|
+
CodeView (Windows) line tables. Function symbols keep their source names
|
|
148
|
+
(`xt_fn_3_add`) and every statement has a line location:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
xbintsc build app.ts --debug
|
|
152
|
+
gdb ./build/app # or: lldb ./build/app, or open the .exe in WinDbg
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The binary is larger and is cached separately from a normal build (the debug
|
|
156
|
+
flag is part of the cache key). `Error.stack` works without `--debug`.
|
|
157
|
+
|
|
121
158
|
## Build behaviour that looks wrong but is not
|
|
122
159
|
|
|
123
160
|
### The build printed `(cached)` and did nothing
|
package/doc/ai/zh-CN/cli.md
CHANGED
|
@@ -35,6 +35,7 @@ git config core.hooksPath .githooks
|
|
|
35
35
|
| `npm run test:watch` | vitest 监听模式 |
|
|
36
36
|
| `npm run coverage` | TypeScript 编译器(`src/`)的 V8 覆盖率 |
|
|
37
37
|
| `npm run coverage:runtime` | C 运行时(`runtime/`)的 LLVM 覆盖率 |
|
|
38
|
+
| `npm run bench` | 构建并计时固定基准套件(可与 Node 对比) |
|
|
38
39
|
|
|
39
40
|
单元测试在 `tests/` 下按模块一个目录(`lexer`、`parser`、`binder`、`codegen`、
|
|
40
41
|
`driver`、`extensions`、`cli`、`e2e`),与源码树镜像对应。边界用例放在它覆盖的模块
|
|
@@ -90,8 +91,11 @@ diff scratch/ref.ll scratch/gen2.ll
|
|
|
90
91
|
- 每个值都是一个 64 位字:double 不装箱,其余都是带标签指针(16 位标签 + 48 位载荷)。
|
|
91
92
|
该表示只定义一次:[../../../src/codegen/values.ts](../../../src/codegen/values.ts) 与
|
|
92
93
|
[../../../runtime/rt.h](../../../runtime/rt.h);要改就一起改,否则别动。
|
|
93
|
-
- 别扭的 JS 语义(`+` 强转、关系比较、属性访问、打印)委托给 `@xt_*`
|
|
94
|
-
|
|
94
|
+
- 别扭的 JS 语义(`+` 强转、关系比较、属性访问、打印)委托给 `@xt_*` 运行时调用。
|
|
95
|
+
数值算术与比较是例外:codegen 内联双 double 快路径
|
|
96
|
+
(`src/codegen/generator/numeric.ts`),其余情况调用运行时。
|
|
97
|
+
- 字符串字面量会被驻留:每个不同字面量只在 `main` 中创建一次,存入 GC 根全局,
|
|
98
|
+
每次使用只做一次 load;属性名因此不再逐次分配。
|
|
95
99
|
- GC 是非移动标记清扫:新堆对象走 `xt_alloc`;值存活期间必须能从显式根槽、已注册的
|
|
96
100
|
根提供者(事件循环、微任务队列)或 C 栈保守扫描到达。只存在于未被扫描的 C 局部
|
|
97
101
|
变量里的值就是 bug。
|
|
@@ -69,7 +69,11 @@ import { createWindow, run } from "gui";
|
|
|
69
69
|
`loadedmetadata`/`play`/`pause`/`ended`/`timeupdate`/`error` 事件可让程序驱动播放。
|
|
70
70
|
没有内置控件——用元素和 CSS 自绘控件(见 `examples/gui/media.ts`);视频帧与音频 PCM
|
|
71
71
|
都在主线程解码。也支持 `<canvas>`:`getContext("2d")` 返回的上下文,其填充、路径、
|
|
72
|
-
文本与 `drawImage` 由自研 CPU 光栅器处理,元素句柄还暴露 `width`/`height
|
|
72
|
+
文本与 `drawImage` 由自研 CPU 光栅器处理,元素句柄还暴露 `width`/`height`。CSS
|
|
73
|
+
`transform`/`transform-origin` 作为绘制期效果可用,因此一个盒子(以及其中的文本、
|
|
74
|
+
图像与子元素)可以被平移、缩放与旋转而不触发任何重排——可以用
|
|
75
|
+
`requestAnimationFrame` 逐帧驱动,或写成 `transition: transform`(见
|
|
76
|
+
`examples/gui/pelican-svg`)。因为主体是 C++,它以各平台预编译的 `gui.a`/`gui.lib` 形式分发。如果该
|
|
73
77
|
平台的归档不存在,构建会以明确的提示失败;设计与路线图见 [../../zh-CN/gui.md](../../zh-CN/gui.md)(总览;引擎按功能拆分在 [`doc/zh-CN/gui/`](../../zh-CN/gui/) 下),
|
|
74
78
|
脚本接口见 [../../zh-CN/gui-scripts.md](../../zh-CN/gui-scripts.md)。媒体播放是
|
|
75
79
|
Windows 唯一不支持的:Windows 的 `gui.a` 不构建 FFmpeg,媒体槽位为空操作。Canvas API
|
|
@@ -42,8 +42,8 @@ xbintsc 编译 TypeScript 的一个**实用子集**。本页用来判断你能
|
|
|
42
42
|
| 解构(绑定、参数、嵌套) | ✅ | 支持默认值与剩余 |
|
|
43
43
|
| `delete`、`in`、`instanceof`、`typeof` | ✅ | |
|
|
44
44
|
| 逗号运算符、`void` | ✅ | |
|
|
45
|
-
| `new.target` | 🚫 |
|
|
46
|
-
| `import.meta` |
|
|
45
|
+
| `new.target` | 🚫 | 能解析,但会给出明确的 `UnsupportedFeature` |
|
|
46
|
+
| `import.meta` | ✅ | `url`、`dirname`、`filename`(由可执行文件路径解析) |
|
|
47
47
|
| `super` | ⚠️ | 单层继承正确;继承深度 > 1 可能不准 |
|
|
48
48
|
|
|
49
49
|
## 函数、类与对象
|
|
@@ -98,7 +98,7 @@ xbintsc 编译 TypeScript 的一个**实用子集**。本页用来判断你能
|
|
|
98
98
|
| 缺失或行为不同 | 状态 |
|
|
99
99
|
| --- | --- |
|
|
100
100
|
| `String.prototype.normalize`、`structuredClone` | 🚫 |
|
|
101
|
-
| `Error.stack` 采集 |
|
|
101
|
+
| `Error.stack` 采集 | ⚠️ 函数级帧(名称/文件/行号),没有列号;生成器函数体不产生帧 |
|
|
102
102
|
| `Object.getPrototypeOf({})` | ⚠️ 返回 `undefined`,而非 `Object.prototype` |
|
|
103
103
|
| 全局 RegExp `lastIndex` | ⚠️ `/g`、`/y` 下 `test`/`exec` 忽略它 |
|
|
104
104
|
| 稀疏数组空洞、数组越界 | ⚠️ 不区分空洞;越界读得 `undefined` |
|
|
@@ -117,7 +117,7 @@ xbintsc 编译 TypeScript 的一个**实用子集**。本页用来判断你能
|
|
|
117
117
|
| `require()` / CommonJS | 🚫 | 被拒绝,并提示改用 `import` |
|
|
118
118
|
| 循环依赖 | 🚫 | |
|
|
119
119
|
| 实时绑定 | ⚠️ | 导入与命名空间成员都是快照 |
|
|
120
|
-
| `
|
|
120
|
+
| `__dirname`、`__filename` | 🚫 | 请使用 `import.meta.dirname` / `import.meta.filename` |
|
|
121
121
|
|
|
122
122
|
## 字符串、数字与内存
|
|
123
123
|
|
|
@@ -21,8 +21,11 @@ D:\...\build\app.ll:382:37: error: '@.str.0' defined with type '[6 x i8]*' but e
|
|
|
21
21
|
|
|
22
22
|
编译器生成的 LLVM IR 依赖不透明指针(opaque pointers),而有类型指针在 LLVM 16
|
|
23
23
|
中被移除([LLVM 发布说明](https://github.com/llvm/llvm-project/blob/release/15.x/llvm/docs/ReleaseNotes.rst#changes-to-the-llvm-ir))。
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
`xbintsc build`/`run` 现在会先检查版本,直接停止并提示 "reports clang 15.0.2,
|
|
25
|
+
but xbintsc requires clang 16 or newer";`xbintsc doctor` 会打印
|
|
26
|
+
`status : ok` 或 `status : too old`(后者以非零码退出)。搜索工具链时会优先选择受支持
|
|
27
|
+
的 clang——包括 Windows 上 Visual Studio 自带的 LLVM——所以装了新版时旧的
|
|
28
|
+
`/usr/bin/clang` 会被跳过。也可以显式指定:
|
|
26
29
|
|
|
27
30
|
```powershell
|
|
28
31
|
$env:xbintsc_CLANG = "C:\Program Files\LLVM\bin\clang.exe"
|
|
@@ -110,6 +113,36 @@ clang 自身失败。抛出的消息包含完整的 clang 命令与 stderr——
|
|
|
110
113
|
`llvm-rc` 或 `windres`;`doctor` 会报告找到了哪个,只有在确实请求了图标时缺失才是
|
|
111
114
|
致命错误。
|
|
112
115
|
|
|
116
|
+
## 怎么看堆栈
|
|
117
|
+
|
|
118
|
+
`Error.stack` 由 codegen 采集,而不是依赖 C 运行时的原生帧:每个非生成器函数
|
|
119
|
+
在入口压入 `{名称, 文件, 行号}`,返回前弹出。帧形如
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
Error: boom
|
|
123
|
+
at inner (app.ts:12)
|
|
124
|
+
at module (app.ts:3)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
行号取函数声明行;最内层帧会更新为 `new Error(...)` 所在行。没有列号;生成器
|
|
128
|
+
函数体因为会切换栈而不记录。原生致命信号会先打印 `xbintsc: fatal signal …`,
|
|
129
|
+
再打印同一组帧,所以即使没有调试器也能看出崩溃时正在运行哪些 JS 函数。
|
|
130
|
+
|
|
131
|
+
## 用 gdb / lldb / WinDbg 调试
|
|
132
|
+
|
|
133
|
+
`xbintsc build app.ts --debug` 会生成 LLVM 调试元数据,并把 `-g
|
|
134
|
+
-fno-omit-frame-pointer` 传给 clang,因此目标文件带有 DWARF(Linux/macOS)或
|
|
135
|
+
CodeView(Windows)行号表。函数符号保留源码名(如 `xt_fn_3_add`),每条语句都有
|
|
136
|
+
对应的行位置:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
xbintsc build app.ts --debug
|
|
140
|
+
gdb ./build/app # 或 lldb ./build/app,Windows 用 WinDbg 打开 .exe
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
调试版二进制更大,并且与普通构建分开缓存(debug 标志参与缓存键)。`Error.stack`
|
|
144
|
+
不需要 `--debug` 也能工作。
|
|
145
|
+
|
|
113
146
|
## 看起来不对、其实正常的构建行为
|
|
114
147
|
|
|
115
148
|
### 构建打印了 `(cached)` 并什么都没做
|
package/doc/gui/animation.md
CHANGED
|
@@ -31,8 +31,10 @@ the engine advances the clock with real frame deltas (`XtDocument::advance`),
|
|
|
31
31
|
and `win.advance(ms)` lets tests step it deterministically.
|
|
32
32
|
|
|
33
33
|
- Supported properties: `background-color`, `color`, `border-color`,
|
|
34
|
-
`border-radius`; `transition: all` covers them.
|
|
35
|
-
|
|
34
|
+
`border-radius` and `transform`; `transition: all` covers them. A
|
|
35
|
+
layout-affecting property (width, position, …) is still not animated — that
|
|
36
|
+
would reflow every frame — but `transform` is paint-time, so animating it costs
|
|
37
|
+
one matrix per animated box per frame ([Layout](./layout.md#transforms-m15)).
|
|
36
38
|
- Both the `transition` shorthand and the `transition-property` / `-duration` /
|
|
37
39
|
`-delay` / `-timing-function` longhands are parsed; time values accept `s` and
|
|
38
40
|
`ms`; timing functions are `linear`, `ease`, `ease-in`, `ease-out` and
|
|
@@ -42,5 +44,54 @@ and `win.advance(ms)` lets tests step it deterministically.
|
|
|
42
44
|
- `computedStyle()` reports the displayed (interpolated) value, so transitions
|
|
43
45
|
are directly observable in tests.
|
|
44
46
|
|
|
47
|
+
`transform` lists interpolate **element-wise** (`document.cpp`,
|
|
48
|
+
`xt_transform_interpolate`), which is what makes the common pair
|
|
49
|
+
`translateY(-4px) rotate(-0.35deg)` <-> `none` glide instead of jumping: the
|
|
50
|
+
missing side is filled with identity ops of the same kind. Two lists whose shapes
|
|
51
|
+
or units do not line up (`rotate(10deg)` vs `rotate(10rad)`, or a different number
|
|
52
|
+
of functions) are not interpolated at all — the transition snaps to the target,
|
|
53
|
+
which is CSS's discrete fallback rather than a wrong-looking sweep.
|
|
54
|
+
|
|
55
|
+
## CSS transforms (M15)
|
|
56
|
+
|
|
57
|
+
`transform` and `transform-origin` are supported as *paint-time* effects
|
|
58
|
+
(`translate`/`translate3d`/`translateX`/`translateY`,
|
|
59
|
+
`scale`/`scale3d`/`scaleX`/`scaleY`, `rotate`/`rotateZ`, `matrix`; the `3d`
|
|
60
|
+
spellings' `z` argument is parsed and dropped, since the engine is 2D;
|
|
61
|
+
`deg`/`rad`/`grad`/`turn`; `%`, `px`, `em`, `rem`, `vw`, `vh`). Layout
|
|
62
|
+
is not affected: geometry stays where flow put it, and only the painted result
|
|
63
|
+
moves, so a size, a scroll position or a sibling's position never depends on an
|
|
64
|
+
animation frame. See [Layout](./layout.md#transforms-m15) for the composition
|
|
65
|
+
rules and [Rendering](./rendering.md) for how it reaches the GPU.
|
|
66
|
+
|
|
67
|
+
Two ways to drive one:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
// 1. Per frame — a pose from the frame clock. Nothing reflows: the string is
|
|
71
|
+
// parsed into matrices and the display list picks them up in the same frame.
|
|
72
|
+
const tick = (t: number): void => {
|
|
73
|
+
const s = t / 1000;
|
|
74
|
+
art.style.setProperty(
|
|
75
|
+
"transform",
|
|
76
|
+
"translateY(" + (Math.sin(s * 2.4) * 5).toFixed(2) + "px) " +
|
|
77
|
+
"rotate(" + (Math.sin(s * 1.15) * 1.1).toFixed(2) + "deg)",
|
|
78
|
+
);
|
|
79
|
+
win.requestAnimationFrame(tick);
|
|
80
|
+
};
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```css
|
|
84
|
+
/* 2. From a state change — a transitioned transform, like any other property. */
|
|
85
|
+
#caption {
|
|
86
|
+
transform-origin: 50% 100%;
|
|
87
|
+
transition: transform 260ms ease-out;
|
|
88
|
+
}
|
|
89
|
+
#caption:hover { transform: translateY(-2px) scale(1.03); }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Both are exercised by `examples/gui/pelican-svg` (per-frame sway plus a
|
|
93
|
+
hover transition on the caption) and pinned by
|
|
94
|
+
`tests/e2e/gui-transform.test.ts`.
|
|
95
|
+
|
|
45
96
|
Still to do for animation: `@keyframes` animations and `cubic-bezier(...)`.
|
|
46
97
|
|
package/doc/gui/api.md
CHANGED
|
@@ -60,7 +60,7 @@ exposes read-only hooks:
|
|
|
60
60
|
```ts
|
|
61
61
|
win.computedStyle(selector, property) // e.g. ("#main", "width") -> "60%"
|
|
62
62
|
win.queryCount(selector) // number of matching elements
|
|
63
|
-
win.getBoundingClientRect(selector) // { x, y, width, height } (border box)
|
|
63
|
+
win.getBoundingClientRect(selector) // { x, y, width, height } (border box, transformed)
|
|
64
64
|
win.documentTree() // serialized DOM (debugging)
|
|
65
65
|
win.layoutTree() // serialized layout boxes (debugging)
|
|
66
66
|
win.paintCount() // number of shapes in the display list
|
package/doc/gui/dom.md
CHANGED
|
@@ -20,7 +20,12 @@ pseudo-classes `:first-child`, `:last-child`, `:only-child`, `:empty`,
|
|
|
20
20
|
stateful `:hover` and `:focus` (see [Input](./input.md)). Values:
|
|
21
21
|
lengths (`px`, `%`, `em`, `rem`, `vw`, `vh`, `pt`, `pc`, `in`, `cm`, `mm`, `q`),
|
|
22
22
|
colors (hex, `rgb()`/`rgba()`, a named subset), numbers, keywords and shorthands
|
|
23
|
-
(`margin`/`padding`/`border`/`flex`).
|
|
23
|
+
(`margin`/`padding`/`border`/`flex`). `transform` (`translate`/`translate3d`/
|
|
24
|
+
`translateX`/`translateY`, `scale`/`scale3d`/`scaleX`/`scaleY`, `rotate`/
|
|
25
|
+
`rotateZ`, `matrix`; the `3d` spellings' `z` argument is dropped) and
|
|
26
|
+
`transform-origin` are parsed into the computed style as a list of operations
|
|
27
|
+
plus two (unresolved) origin lengths; an unsupported function invalidates the
|
|
28
|
+
whole declaration ([Layout](./layout.md#transforms-m15)).
|
|
24
29
|
|
|
25
30
|
**Cascade & computed style** (`runtime/ext_gui/style.{h,cpp}`): a small built-in
|
|
26
31
|
UA stylesheet, author rules sorted by `(!important, specificity, source order)`,
|
package/doc/gui/input.md
CHANGED
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
|
|
7
7
|
`LayoutTree::hitTest` returns the deepest box containing a point (probing later
|
|
8
8
|
siblings first so the topmost element wins), and `xt_dom_describe` turns the
|
|
9
|
-
element into the `div#id.class` descriptor carried by event payloads.
|
|
9
|
+
element into the `div#id.class` descriptor carried by event payloads. A
|
|
10
|
+
transformed box maps the point through its inverse matrix first, so a rotated,
|
|
11
|
+
scaled or translated element is hit exactly where it is drawn — and `:hover`
|
|
12
|
+
follows the artwork, not the box flow left behind.
|
|
10
13
|
|
|
11
14
|
- SDL pointer/wheel/key events are routed to the owning window, hit tested, and
|
|
12
15
|
delivered to the handlers registered with `on`. `mousedown` also moves focus.
|
package/doc/gui/known-issues.md
CHANGED
|
@@ -48,11 +48,23 @@
|
|
|
48
48
|
rectangles/text/images, so `<svg>` subtrees would need a whole second
|
|
49
49
|
geometry+paint path. Vector art therefore has to arrive as an SVG/PNG file or
|
|
50
50
|
be drawn from boxes, as `examples/gui/pelican-bike` does.
|
|
51
|
+
- **Windows: the C++ runtime must not be named on the link line.** `gui.lib` is
|
|
52
|
+
built with the *static* CRT (`CMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded`) and
|
|
53
|
+
every engine object records `libcpmt` as a dependent library, which is also
|
|
54
|
+
clang's Windows default and what the xbintsc runtime objects use
|
|
55
|
+
(`scripts/build-gui.ts`). Asking for the DLL runtime as well — the gui
|
|
56
|
+
extension used to pass `-lmsvcprt` — makes the two copies of the same symbols
|
|
57
|
+
collide: `LNK2038: mismatch detected for 'RuntimeLibrary'` plus a wall of
|
|
58
|
+
`LNK2005: already defined`, surfaced as `clang: linker command failed with exit
|
|
59
|
+
code 1169`. `src/extensions/gui/index.ts` now lists only the OS libraries
|
|
60
|
+
(`user32`, `gdi32`, `d3d12`, …). A Windows link is also the only place the
|
|
61
|
+
MSVC environment matters, so build from an x64 Native Tools prompt.
|
|
51
62
|
- Windows: an MSVC-compatible `gui.lib` (COFF objects + `ar -M`/`llvm-ar`) is
|
|
52
|
-
produced by `scripts/build-gui.ts
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
63
|
+
produced by `scripts/build-gui.ts` but is not validated in CI, so the Windows
|
|
64
|
+
step is provisional (the job stays green) and `package` skips it. Building and
|
|
65
|
+
running `examples/gui/pelican-svg` and `examples/gui/pelican-bike` on a
|
|
66
|
+
developer machine works. It also needs an SDL3 build with the D3D12/DXIL
|
|
67
|
+
backend (DXIL requires `dxc`).
|
|
56
68
|
- **Media on Windows:** the media decoders (FFmpeg) are only built and merged
|
|
57
69
|
into the POSIX `gui.a`; the Windows `gui.lib` is produced without them, so
|
|
58
70
|
`<video>`/`<audio>` are inert there (failures fire `error`). Enabling it needs
|
package/doc/gui/layout.md
CHANGED
|
@@ -66,6 +66,42 @@ flex items from non-whitespace text, full `z-index` stacking contexts, and
|
|
|
66
66
|
`float` affecting block children (only inline content wraps; a block must
|
|
67
67
|
`clear`).
|
|
68
68
|
|
|
69
|
+
## Transforms (M15)
|
|
70
|
+
|
|
71
|
+
`transform` and `transform-origin` are a **paint-time** effect: the box model
|
|
72
|
+
above is untouched (nothing reflows, no geometry is recomputed), and a second
|
|
73
|
+
pass after `xt_layout_run` gives every `LayoutBox` a `Matrix2D world` — the
|
|
74
|
+
transform of the whole ancestor chain — plus its `inverse`:
|
|
75
|
+
|
|
76
|
+
- **Only element boxes contribute.** A text box shares its parent element's
|
|
77
|
+
`style` pointer, so letting both contribute would apply the element's list
|
|
78
|
+
twice; the pass composes an element's own list, its ancestors', and nothing
|
|
79
|
+
else.
|
|
80
|
+
- **`transform-origin` is resolved here**, not in the cascade: the computed style
|
|
81
|
+
keeps the two (possibly `%`) `Length`s (default `50% 50%`) and layout resolves
|
|
82
|
+
them against the *border box*, applying `T(origin) · M · T(-origin)`. That is
|
|
83
|
+
why `computedStyle(el, "transform-origin")` still reports `50% 92%`. The
|
|
84
|
+
keywords are positional as in CSS: `top` alone is `center top`, and the
|
|
85
|
+
keyword pair may be given in either order (`bottom right` = `right bottom`).
|
|
86
|
+
- **Lengths resolve against the box**: `%` in `translate()` is a share of the
|
|
87
|
+
border box's width/height, `em`/`rem` against the root font size (16px), and
|
|
88
|
+
`vw`/`vh` against the viewport.
|
|
89
|
+
- **Composition order** follows CSS: the list applies right to left, so
|
|
90
|
+
`rotate(90deg) translate(10px)` moves the box *down* the screen, not right.
|
|
91
|
+
|
|
92
|
+
Everything downstream follows the matrices:
|
|
93
|
+
|
|
94
|
+
| Consumer | Behaviour |
|
|
95
|
+
| --- | --- |
|
|
96
|
+
| Paint | each op carries the matrix (see [Rendering](./rendering.md#paint-and-display-list-m4am4b)); a clipped subtree clips to the bounding box of its padding box through the matrix |
|
|
97
|
+
| Hit testing | `hitTestBox` maps the point through each box's inverse before the containment test, so a rotated or scaled element is clickable where it is *drawn* |
|
|
98
|
+
| `getBoundingClientRect` | the axis-aligned bounding box of the **transformed** border box (`xt_layout_transformed_bounds`) |
|
|
99
|
+
| Layout geometry | unchanged — `layoutTree()` and `offsetWidth`/`offsetHeight` keep reporting the untransformed box |
|
|
100
|
+
|
|
101
|
+
Unsupported transform functions (`skew`, `perspective`, …) invalidate the whole
|
|
102
|
+
declaration, so a box is either correctly transformed or not transformed at all
|
|
103
|
+
rather than partially applied.
|
|
104
|
+
|
|
69
105
|
**Document** (`runtime/ext_gui/document.{h,cpp}`): owns the DOM tree, gathers
|
|
70
106
|
`<style>` text into one stylesheet, computes styles and layout for a viewport and
|
|
71
107
|
offers `querySelector`/`querySelectorAll`/`styleOf`/`boxOf`.
|
package/doc/gui/rendering.md
CHANGED
|
@@ -54,6 +54,21 @@ its own GPU scissor rectangle (scaled to device pixels), so painter order and
|
|
|
54
54
|
- Geometry is uploaded only when the document or viewport changes
|
|
55
55
|
(`geometry.dirty`), so steady-state frames are bind-and-draw.
|
|
56
56
|
|
|
57
|
+
Each op also carries the `Matrix2D` of the box it came from
|
|
58
|
+
(`runtime/ext_gui/transform.h`, `PaintRect::transform` and friends). It is
|
|
59
|
+
applied while the vertex buffer is built, not in the shader: `pushRect` maps its
|
|
60
|
+
four corners through the matrix (the distance-field `local`/half-extent/radius
|
|
61
|
+
fields stay in the *box* frame, so a rounded corner stays round after a
|
|
62
|
+
rotation), and `pushQuad`/`pushGlyph` map the glyph or image quad the same way.
|
|
63
|
+
That kept the MSL/SPIR-V/DXIL shaders and the pipelines untouched — a transform
|
|
64
|
+
costs a few multiplies per vertex and nothing per pixel. A clip rectangle of a
|
|
65
|
+
transformed box is the bounding box of the transformed padding box, because the
|
|
66
|
+
GPU scissor is axis aligned. Text is the one case that needs more than
|
|
67
|
+
multiplying corners: a scaling transform would magnify an atlas raster, so the
|
|
68
|
+
atlas is asked for glyphs at the device scale **times the matrix's
|
|
69
|
+
magnification** (clamped to 0.5–4x, since the atlas is finite) and the quad is
|
|
70
|
+
divided back into logical units, exactly the way HiDPI scaling already worked.
|
|
71
|
+
|
|
57
72
|
The window background (`setBackground`) is the render-pass clear colour.
|
|
58
73
|
|
|
59
74
|
Still to do in M4: gradients.
|
package/doc/gui.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# xbintsc GUI extension (self-hosted HTML/CSS renderer)
|
|
2
2
|
|
|
3
|
-
Status: **
|
|
3
|
+
Status: **M15** — features (M1–M14) are complete: HTML parsing, CSS selector
|
|
4
4
|
matching, the cascade, computed styles and layout (block, inline, Flexbox and
|
|
5
5
|
CSS positioning) are
|
|
6
6
|
in place, and the engine *paints*: it builds a display list of rectangles, images
|
|
@@ -24,7 +24,13 @@ video frames go through the image texture path and audio to an SDL stream, with
|
|
|
24
24
|
the DOM media API exposing `play`/`pause`/`currentTime`/… and media events.
|
|
25
25
|
**M14** adds `<canvas>` with a self-written 2D software rasteriser (anti-aliased
|
|
26
26
|
fills, paths, text and `drawImage`) uploaded through the image texture path —
|
|
27
|
-
see [Canvas](./gui/canvas.md).
|
|
27
|
+
see [Canvas](./gui/canvas.md). **M15** adds CSS `transform` /
|
|
28
|
+
`transform-origin`: a composited `Matrix2D` per layout box that the display list
|
|
29
|
+
carries into the renderer, so boxes (and the text, images and children inside
|
|
30
|
+
them) can be translated, scaled and rotated without reflowing anything — and
|
|
31
|
+
`transition: transform`, so those poses animate. See
|
|
32
|
+
[Layout](./gui/layout.md#transforms-m15) and
|
|
33
|
+
[Animation](./gui/animation.md#css-transforms-m15).
|
|
28
34
|
This overview records the locked decisions, the architecture, the milestone plan
|
|
29
35
|
and the current progress; the engine itself is documented by function in the
|
|
30
36
|
pages above.
|
|
@@ -38,7 +44,7 @@ pages above.
|
|
|
38
44
|
- [Media](./gui/media.md) — images, SVG, video and audio
|
|
39
45
|
- [Canvas](./gui/canvas.md) — `<canvas>` and the 2D context
|
|
40
46
|
- [Input](./gui/input.md) — hit testing, events and `:hover`/`:focus`
|
|
41
|
-
- [Animation](./gui/animation.md) — `requestAnimationFrame
|
|
47
|
+
- [Animation](./gui/animation.md) — `requestAnimationFrame`, CSS transitions and transforms
|
|
42
48
|
- [Runtime integration](./gui/runtime.md) — event loop, native bridge and memory
|
|
43
49
|
- [Packaging and build](./gui/build.md) — building `gui.a` and running examples
|
|
44
50
|
- [Known issues and open questions](./gui/known-issues.md)
|
|
@@ -240,6 +246,16 @@ engine were Rust.
|
|
|
240
246
|
GPU texture through the image path (`renderer_image.cpp`) and the display
|
|
241
247
|
list carries a `canvas_id` (`paint.*`). See [Canvas](./gui/canvas.md);
|
|
242
248
|
e2e in `tests/e2e/gui-canvas.test.ts`.
|
|
249
|
+
15. **M15 — CSS `transform`** ✅
|
|
250
|
+
- `transform`/`transform-origin` parse into a `TransformOp` list
|
|
251
|
+
(`transform.{h,cpp}`, `style.*`), transition like any other paint
|
|
252
|
+
property (`document.*`), and are composed into a per-box `world` matrix
|
|
253
|
+
(plus its inverse) after layout (`layout.*`). Paint carries the matrix on
|
|
254
|
+
every op and the renderer maps quad corners through it, so the shaders are
|
|
255
|
+
untouched. Hit testing and `getBoundingClientRect` follow. See
|
|
256
|
+
[Layout](./gui/layout.md#transforms-m15) and
|
|
257
|
+
[Animation](./gui/animation.md#css-transforms-m15); e2e in
|
|
258
|
+
`tests/e2e/gui-transform.test.ts` and `tests/e2e/gui-example-svg.test.ts`.
|
|
243
259
|
|
|
244
260
|
## Progress log
|
|
245
261
|
|
|
@@ -325,4 +341,17 @@ engine were Rust.
|
|
|
325
341
|
image texture path (`renderer_image.cpp`) and the display list carries a
|
|
326
342
|
`canvas_id` (`paint.*`). See [Canvas](./gui/canvas.md); e2e in
|
|
327
343
|
`tests/e2e/gui-canvas.test.ts`.
|
|
344
|
+
- **M15** ✅ CSS `transform` / `transform-origin`. A new translation unit
|
|
345
|
+
(`transform.{h,cpp}`) parses `translate`/`translateX`/`translateY`/`scale`/
|
|
346
|
+
`scaleX`/`scaleY`/`rotate`/`matrix` (plus `translate3d`/`scale3d`, whose `z`
|
|
347
|
+
argument is dropped) into a `Matrix2D` list, reports them back through
|
|
348
|
+
`computedStyle`, and interpolates them for transitions (a shape or unit change
|
|
349
|
+
snaps). Layout composes a `world` matrix and its inverse per box after the
|
|
350
|
+
normal pass (`applyTransforms`), resolving `transform-origin` against the
|
|
351
|
+
border box — so layout geometry, and therefore flow, never changes. Paint
|
|
352
|
+
attaches the matrix to every shape/text/image op and the renderer maps quad
|
|
353
|
+
corners through it (no shader or uniform change), hit testing maps the point
|
|
354
|
+
through the inverse, and `getBoundingClientRect` returns the transformed AABB.
|
|
355
|
+
`examples/gui/pelican-svg` animates its artwork with it; e2e in
|
|
356
|
+
`tests/e2e/gui-transform.test.ts` and `tests/e2e/gui-example-svg.test.ts`.
|
|
328
357
|
|