xbintsc 0.5.36 → 0.5.38
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/dist/src/cli/help.d.ts +1 -1
- package/dist/src/codegen/generator/state.js +1 -0
- package/dist/src/codegen/generator/state.js.map +1 -1
- package/dist/src/codegen/generator/tables.js +1 -0
- package/dist/src/codegen/generator/tables.js.map +1 -1
- package/dist/src/driver/bundler/deferred.d.ts +63 -0
- package/dist/src/driver/bundler/deferred.js +279 -0
- package/dist/src/driver/bundler/deferred.js.map +1 -0
- package/dist/src/driver/bundler/merge.js +214 -2
- package/dist/src/driver/bundler/merge.js.map +1 -1
- package/dist/src/driver/runtime-objects.d.ts +1 -1
- package/dist/src/driver/runtime-objects.js +1 -0
- package/dist/src/driver/runtime-objects.js.map +1 -1
- package/dist/src/driver/version.d.ts +1 -1
- package/dist/src/driver/version.js +1 -1
- package/dist/src/extensions/gui/html.js +89 -13
- package/dist/src/extensions/gui/html.js.map +1 -1
- package/dist/src/extensions/gui/index.js +13 -0
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/gui/three.d.ts +4 -3
- package/dist/src/extensions/gui/three.js +4 -3
- package/dist/src/extensions/gui/three.js.map +1 -1
- package/dist/tests/e2e/gui-browser.test.js +65 -0
- package/dist/tests/e2e/gui-browser.test.js.map +1 -1
- package/dist/tests/e2e/gui-canvas-args.test.d.ts +6 -0
- package/dist/tests/e2e/gui-canvas-args.test.js +217 -0
- package/dist/tests/e2e/gui-canvas-args.test.js.map +1 -0
- package/dist/tests/e2e/gui-canvas.test.js.map +1 -1
- package/dist/tests/e2e/gui-dom.test.js +215 -0
- package/dist/tests/e2e/gui-dom.test.js.map +1 -1
- package/dist/tests/e2e/gui-events.test.js +112 -0
- package/dist/tests/e2e/gui-events.test.js.map +1 -1
- package/dist/tests/e2e/gui-script-import-order.test.d.ts +10 -0
- package/dist/tests/e2e/gui-script-import-order.test.js +161 -0
- package/dist/tests/e2e/gui-script-import-order.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-shadow.test.d.ts +10 -0
- package/dist/tests/e2e/gui-webgl2-shadow.test.js +108 -0
- package/dist/tests/e2e/gui-webgl2-shadow.test.js.map +1 -0
- package/dist/tests/e2e/url.test.d.ts +6 -0
- package/dist/tests/e2e/url.test.js +114 -0
- package/dist/tests/e2e/url.test.js.map +1 -0
- package/dist/tests/extensions/gui.test.js +22 -10
- package/dist/tests/extensions/gui.test.js.map +1 -1
- package/doc/gui/api.md +38 -9
- package/doc/gui/canvas.md +49 -18
- package/doc/gui/dom.md +51 -4
- package/doc/gui/webgl.md +20 -10
- package/doc/gui-scripts.md +19 -19
- package/doc/gui.md +10 -8
- package/doc/implemented/fetch.md +5 -0
- package/doc/implemented/modules.md +13 -0
- package/doc/implemented/stdlib.md +17 -0
- package/doc/unimplemented/deviations.md +1 -0
- package/doc/zh-CN/gui/api.md +33 -4
- package/doc/zh-CN/gui/canvas.md +44 -19
- package/doc/zh-CN/gui/dom.md +45 -3
- package/doc/zh-CN/gui/webgl.md +3 -3
- package/doc/zh-CN/gui-scripts.md +14 -13
- package/doc/zh-CN/gui.md +7 -6
- package/doc/zh-CN/implemented/fetch.md +4 -0
- package/doc/zh-CN/implemented/modules.md +10 -0
- package/doc/zh-CN/implemented/stdlib.md +15 -0
- package/doc/zh-CN/unimplemented/deviations.md +1 -0
- package/package.json +7 -7
- package/runtime/ext_gui/browser.cpp +34 -49
- package/runtime/ext_gui/browser_abort.cpp +249 -0
- package/runtime/ext_gui/browser_dialogs.cpp +76 -0
- package/runtime/ext_gui/browser_media.cpp +176 -0
- package/runtime/ext_gui/browser_navigation.cpp +130 -0
- package/runtime/ext_gui/canvas.cpp +88 -30
- package/runtime/ext_gui/canvas.h +74 -9
- package/runtime/ext_gui/canvas_image_data.cpp +143 -0
- package/runtime/ext_gui/canvas_internal.h +8 -5
- package/runtime/ext_gui/canvas_pattern.cpp +90 -0
- package/runtime/ext_gui/canvas_raster.cpp +31 -9
- package/runtime/ext_gui/canvas_style.cpp +4 -2
- package/runtime/ext_gui/dom.h +4 -0
- package/runtime/ext_gui/dom_api.cpp +1 -0
- package/runtime/ext_gui/dom_api_canvas.cpp +120 -114
- package/runtime/ext_gui/dom_api_canvas_extra.cpp +57 -2
- package/runtime/ext_gui/dom_api_canvas_image.cpp +239 -0
- package/runtime/ext_gui/dom_api_canvas_paths.cpp +179 -0
- package/runtime/ext_gui/dom_api_computed_style.cpp +124 -0
- package/runtime/ext_gui/dom_api_dataset.cpp +154 -0
- package/runtime/ext_gui/dom_api_document.cpp +58 -5
- package/runtime/ext_gui/dom_api_events.cpp +93 -17
- package/runtime/ext_gui/dom_api_internal.h +55 -2
- package/runtime/ext_gui/dom_api_mutation.cpp +159 -0
- package/runtime/ext_gui/dom_api_node.cpp +40 -19
- package/runtime/ext_gui/dom_api_node_read.cpp +37 -1
- package/runtime/ext_gui/dom_api_path2d.cpp +358 -0
- package/runtime/ext_gui/dom_api_proto.cpp +35 -0
- package/runtime/ext_gui/dom_api_style.cpp +223 -13
- package/runtime/ext_gui/dom_api_webgl.cpp +10 -0
- package/runtime/ext_gui/dom_api_webgl2.cpp +33 -1
- package/runtime/ext_gui/gui.cpp +59 -5
- package/runtime/ext_gui/gui_engine.h +49 -0
- package/runtime/ext_gui/gui_events.cpp +80 -9
- package/runtime/ext_gui/listener_options.h +43 -0
- package/runtime/ext_gui/paint.cpp +28 -0
- package/runtime/ext_gui/paint.h +4 -0
- package/runtime/ext_gui/script.cpp +31 -0
- package/runtime/ext_gui/webgl_glsl.h +3 -0
- package/runtime/ext_gui/webgl_glsl_unroll.cpp +283 -0
- package/runtime/ext_gui/webgl_msl.cpp +4 -0
- package/runtime/ext_gui/webgl_shader.cpp +12 -6
- package/runtime/ext_gui/window.cpp +14 -65
- package/runtime/ext_gui/window_events.cpp +125 -0
- package/runtime/rt.h +29 -0
- package/runtime/rt_internal.h +4 -0
- package/runtime/xt_builtins.c +0 -21
- package/runtime/xt_containers/access.inc +94 -2
- package/runtime/xt_containers/objects.inc +29 -31
- package/runtime/xt_fetch/async.inc +60 -0
- package/runtime/xt_url_object.c +463 -0
- package/src/codegen/generator/state.ts +1 -0
- package/src/codegen/generator/tables.ts +1 -0
- package/src/driver/bundler/deferred.ts +351 -0
- package/src/driver/bundler/merge.ts +219 -2
- package/src/driver/runtime-objects.ts +1 -0
- package/src/driver/version.ts +1 -1
- package/src/extensions/gui/html.ts +91 -15
- package/src/extensions/gui/index.ts +13 -0
- package/src/extensions/gui/three.ts +4 -3
package/doc/gui/webgl.md
CHANGED
|
@@ -23,8 +23,11 @@ display.
|
|
|
23
23
|
Both **WebGL 1.0** and **WebGL 2.0** are available. A canvas keeps the first
|
|
24
24
|
context kind it asks for: after `getContext("webgl2")` a later
|
|
25
25
|
`getContext("webgl")` answers `null`, and the other way round. A WebGL 2 context
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
has its own `WebGL2RenderingContext` prototype (with a copy of the WebGL 1
|
|
27
|
+
constants and methods), so `gl instanceof WebGL2RenderingContext` is true while
|
|
28
|
+
`gl instanceof WebGLRenderingContext` is false, like a browser — libraries such
|
|
29
|
+
as three.js use exactly that check to pick their WebGL 2 path. `gl.constructor.name`
|
|
30
|
+
reports the type as well.
|
|
28
31
|
|
|
29
32
|
## How a frame reaches the screen
|
|
30
33
|
|
|
@@ -54,8 +57,9 @@ format, so the engine ships two statically linked translators:
|
|
|
54
57
|
|
|
55
58
|
- **glslang** compiles the rewritten GLSL to SPIR-V, which the Vulkan backend
|
|
56
59
|
consumes directly;
|
|
57
|
-
- **SPIRV-Cross** cross-compiles that same SPIR-V to Metal Shading Language
|
|
58
|
-
which the Metal backend
|
|
60
|
+
- **SPIRV-Cross** cross-compiles that same SPIR-V to Metal Shading Language 2.0
|
|
61
|
+
text (needed for arrays of textures/samplers), which the Metal backend
|
|
62
|
+
compiles at run time.
|
|
59
63
|
|
|
60
64
|
Both live in `gui.a` / `gui.lib`; the Metal path reuses the SPIR-V module rather
|
|
61
65
|
than growing a second GLSL front end, so both backends accept exactly the same
|
|
@@ -96,9 +100,13 @@ reflected offsets; `uniform1i` on a sampler stores the texture unit. The block
|
|
|
96
100
|
is pushed with the dynamic uniform-buffer API on every draw.
|
|
97
101
|
|
|
98
102
|
Limits of the translator: struct-typed uniforms, user uniform blocks, uniform
|
|
99
|
-
arrays whose size is not resolved by the preprocessor,
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
arrays whose size is not resolved by the preprocessor, and a sampler array
|
|
104
|
+
indexed by a non-constant expression are rejected (the link/shader info log
|
|
105
|
+
says so). A `#pragma unroll_loop_start` loop is expanded before rewriting, so
|
|
106
|
+
the `sampler2D shadowMap[ NUM_DIR_LIGHT_SHADOWS ]` / `shadowMap[ i ]` shape
|
|
107
|
+
three.js emits becomes constant-indexed. Shader code inside `#ifdef` is fine;
|
|
108
|
+
non-sampler uniform declarations are moved to the enclosing top-level position
|
|
109
|
+
so the block stays unconditional.
|
|
102
110
|
|
|
103
111
|
### GLSL ES 3.00 (WebGL 2)
|
|
104
112
|
|
|
@@ -299,9 +307,11 @@ same assertions as the SPIR-V one.
|
|
|
299
307
|
|
|
300
308
|
## three.js
|
|
301
309
|
|
|
302
|
-
The
|
|
303
|
-
|
|
304
|
-
|
|
310
|
+
The shader rewriter expands three.js's `#pragma unroll_loop_start` loops into
|
|
311
|
+
constant indices (its sampler arrays would otherwise fail Vulkan GLSL), and the
|
|
312
|
+
`.js` asset loader keeps the renderer's own unroller out of the way.
|
|
313
|
+
`WebGLRenderer` runs unchanged on this engine's real WebGL 2 backend, so **no
|
|
314
|
+
Canvas2D fallback is bundled any more**. Verified with three.js r160 through SDL_GPU:
|
|
305
315
|
`MeshBasicMaterial`, `MeshStandardMaterial` and `MeshPhongMaterial`,
|
|
306
316
|
`CanvasTexture`, linear fog, ambient/directional/point/spot/hemisphere lights,
|
|
307
317
|
`Sprite`, `Line`, `Points` and `InstancedMesh`.
|
package/doc/gui-scripts.md
CHANGED
|
@@ -155,17 +155,18 @@ export default __html;
|
|
|
155
155
|
### 2b. External `<script src>`
|
|
156
156
|
|
|
157
157
|
`<script src="./app.ts">` is read relative to the HTML file, parsed, and split:
|
|
158
|
-
its top-level `import`/`export … from` statements are
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
158
|
+
its top-level `import`/`export … from` statements are removed from the body, and
|
|
159
|
+
the remaining statements are wrapped in the script function. Relative imports
|
|
160
|
+
are **deferred**, like a browser module script: the loader emits a synthetic
|
|
161
|
+
`__xt_deferred_module` marker and the generated script calls the module wrapper
|
|
162
|
+
at `loadHTML` time. The bundler wraps the whole local import graph in functions
|
|
163
|
+
that return their exports (memoised by `__xt_defer`), so top-level module code
|
|
164
|
+
runs after the document exists and two scripts importing the same module share
|
|
165
|
+
one instance. Bare specifiers (`gui`, a package) stay eager.
|
|
166
|
+
|
|
167
|
+
A missing `src` file is still a clear error (turned into a bundler diagnostic),
|
|
168
|
+
and `src` URLs (`https://…`, `data:…`, `//host`) are left untouched — they are
|
|
169
|
+
not compile-time assets and never run.
|
|
169
170
|
|
|
170
171
|
`src` URLs (`https://…`, `data:…`, `//host`) are left untouched — they are not
|
|
171
172
|
compile-time assets and never run.
|
|
@@ -302,11 +303,11 @@ legacy `target` field over the handle.
|
|
|
302
303
|
- **M9b** ✅ — gui `.html` loader (`src/extensions/gui/html.ts`), the
|
|
303
304
|
`__registerScript` builtin, the script registry (`runtime/ext_gui/script.cpp`),
|
|
304
305
|
`loadHTML` execution and `DOMContentLoaded`/`load`; e2e coverage.
|
|
305
|
-
- **M9c** ✅ — `<script src>` files are read
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
306
|
+
- **M9c** ✅ — `<script src>` files are read and their body is wrapped and
|
|
307
|
+
registered; relative imports are deferred and evaluated by a memoised
|
|
308
|
+
module wrapper at `loadHTML` time, so the import graph sees a parsed
|
|
309
|
+
document and shares one instance per module. Missing files surface as
|
|
310
|
+
diagnostics. All scripts run in document order. e2e coverage.
|
|
310
311
|
- **M9d** *(optional)* — detect inline HTML in template literals passed to
|
|
311
312
|
`win.loadHTML(...)` and transform them too (fragile; deferred).
|
|
312
313
|
- **M10 — polish** ✅ — `requestAnimationFrame`/`cancelAnimationFrame` on the
|
|
@@ -330,9 +331,8 @@ legacy `target` field over the handle.
|
|
|
330
331
|
network fetches) do not run. Documented.
|
|
331
332
|
- **Template-literal HTML** passed to `win.loadHTML(…)` is not transformed in
|
|
332
333
|
M9b (only imported assets are). M9d addresses this if needed.
|
|
333
|
-
- **
|
|
334
|
-
|
|
335
|
-
is possible later.
|
|
334
|
+
- **Top-level `await`** inside a deferred `<script src>` module is not
|
|
335
|
+
supported: the module body is wrapped in a synchronous init function.
|
|
336
336
|
- **Assets.** `<script src>` is resolved relative to the HTML asset; URL `src`
|
|
337
337
|
values are ignored. There is no fetch/network loading.
|
|
338
338
|
|
package/doc/gui.md
CHANGED
|
@@ -219,10 +219,11 @@ engine were Rust.
|
|
|
219
219
|
registered through the `__registerScript` builtin and replaced by
|
|
220
220
|
`<script data-xt-id="<hash>">` markers; `win.loadHTML` runs the matching
|
|
221
221
|
functions after parsing and fires `DOMContentLoaded` then `load`.
|
|
222
|
-
- **M9c** ✅ — `<script src>` files are read relative to the HTML
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
222
|
+
- **M9c** ✅ — `<script src>` files are read relative to the HTML and their
|
|
223
|
+
body is wrapped/registered; relative imports are deferred to `loadHTML`
|
|
224
|
+
through a memoised module wrapper, so imported modules see the parsed
|
|
225
|
+
document and share state. Missing files become diagnostics. Everything
|
|
226
|
+
runs in document order.
|
|
226
227
|
10. **M10 — polish** ✅
|
|
227
228
|
- `win.requestAnimationFrame(fn)` / `win.cancelAnimationFrame(id)`; callbacks
|
|
228
229
|
run at the top of each frame with the frame timestamp and may mutate the
|
|
@@ -387,10 +388,11 @@ engine were Rust.
|
|
|
387
388
|
bodies into AOT functions registered at startup and run by `win.loadHTML`
|
|
388
389
|
(before first layout; `DOMContentLoaded` then `load`). Unit tests in
|
|
389
390
|
`tests/extensions/gui.test.ts`, e2e in `tests/e2e/gui-*.test.ts`.
|
|
390
|
-
- **M9c** ✅ external `<script src>` files are read
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
caught by `loadGraph`
|
|
391
|
+
- **M9c** ✅ external `<script src>` files are read and their body
|
|
392
|
+
wrapped/registered; relative imports are deferred to `loadHTML` through a
|
|
393
|
+
memoised module wrapper (so module-level DOM work sees the parsed document),
|
|
394
|
+
while missing files are diagnostics. Loader errors are caught by `loadGraph`
|
|
395
|
+
and reported as build errors.
|
|
394
396
|
- **M10** ✅ `requestAnimationFrame`/`cancelAnimationFrame` on window handles
|
|
395
397
|
(callbacks run with the frame timestamp before layout each frame) plus
|
|
396
398
|
`offsetWidth`/`offsetHeight`/`contains` on element handles; e2e coverage in
|
package/doc/implemented/fetch.md
CHANGED
|
@@ -13,6 +13,11 @@ Location: `runtime/xt_fetch.c`, `runtime/xt_fetch/async.inc`, `runtime/xt_async_
|
|
|
13
13
|
exchange, up to 20 redirects, and a 301/302/303 switches POST to GET.
|
|
14
14
|
- It accepts `http://` URLs only — `https://` rejects with a `TypeError` because
|
|
15
15
|
no TLS backend is linked.
|
|
16
|
+
- A reference with **no scheme** (a relative path) and `file://` URLs read a
|
|
17
|
+
local file, so a compiled program can load an asset from disk without an HTTP
|
|
18
|
+
server. Relative paths resolve against the working directory; `GET` / `HEAD`
|
|
19
|
+
are supported. On Windows the standard `file:///C:/dir/file` spelling and
|
|
20
|
+
`file://C:/dir/file` / `file://C:\dir\file` all name the same file.
|
|
16
21
|
- Options: `method`, `headers` (plain object or `Headers`), `body` and `redirect`
|
|
17
22
|
(`follow` / `manual` / `error`).
|
|
18
23
|
- The resolved `Response`-shaped object exposes `ok` / `status` / `statusText` /
|
|
@@ -19,6 +19,19 @@ Location: `src/parser/parser.ts` (syntax), `src/driver/modules.ts` (bundling),
|
|
|
19
19
|
- Imported bindings and namespace members are snapshots at module-evaluation time (no live bindings) — see [Unimplemented: module system](../unimplemented/modules.md).
|
|
20
20
|
- Type-only imports and re-exports (`import type { T } from "..."`, `import { type T } from "..."`, `export type { T } from "..."`) are erased. They are **not** module edges: the target is not loaded or bundled, and a type-only cycle between modules is not a circular dependency. Use a side-effect import (`import "./mod"`) when a module must be evaluated without binding a name.
|
|
21
21
|
|
|
22
|
+
## Deferred evaluation
|
|
23
|
+
|
|
24
|
+
- The `gui` `.html` asset loader marks relative `<script src>` imports with a
|
|
25
|
+
synthetic `__xt_deferred_module` binding. The bundler then wraps that module
|
|
26
|
+
and its local import graph in functions that return their exports, and the
|
|
27
|
+
generated script calls them after `loadHTML` (`__xt_defer` memoises each
|
|
28
|
+
module). This matches a browser module script, where the graph is evaluated
|
|
29
|
+
once the document exists.
|
|
30
|
+
- Modules also reachable through a normal (non-marker) import stay eager and get
|
|
31
|
+
a thin wrapper over their already-initialised exports.
|
|
32
|
+
- The wrapper body is synchronous: top-level `await` inside a deferred script
|
|
33
|
+
module is not supported.
|
|
34
|
+
|
|
22
35
|
## import.meta
|
|
23
36
|
|
|
24
37
|
- `import.meta.url` / `.dirname` / `.filename`, resolved from the running executable's path.
|
|
@@ -55,6 +55,23 @@ own pages: [Collections](./collections.md), [Typed arrays and binary data](./typ
|
|
|
55
55
|
- `Symbol(description)` primitives (`XT_OBJECT_KIND_SYMBOL`), the 13 well-known symbols (`Symbol.iterator`, `Symbol.asyncIterator`, `Symbol.match`, ...), `Symbol.for` / `Symbol.keyFor` global registry, `symbol.description` / `toString()` / `valueOf()`.
|
|
56
56
|
- Symbols are valid property keys (`Object.getOwnPropertySymbols`, symbol keyed `get`/`set`/`in`/`delete`), are skipped by `Object.keys` / `values` / `entries` / `for...in` / `JSON.stringify`, and print as `Symbol(desc)`.
|
|
57
57
|
|
|
58
|
+
## URL
|
|
59
|
+
|
|
60
|
+
- `URL` is implemented in `runtime/xt_url_object.c`: `new URL(input)` and
|
|
61
|
+
`new URL(input, base)` (the base may be another `URL`), resolving relative
|
|
62
|
+
references against a hierarchical `scheme://authority/path` base.
|
|
63
|
+
- A reference with **no scheme is a filesystem path**: `new URL("./model.glb")`
|
|
64
|
+
resolves against the working directory and yields a `file:` URL (an explicit
|
|
65
|
+
base is still honoured, so `new URL("./x", import.meta.url)` works too).
|
|
66
|
+
- Read-only `href`, `protocol`, `origin`, `host`, `hostname`, `port`,
|
|
67
|
+
`pathname`, `search`, `hash`, `searchParams` and `toString()` / `toJSON()`;
|
|
68
|
+
absolute inputs are kept as written, except that the Windows spellings of a
|
|
69
|
+
`file:` URL (`file://C:/dir` and `file://C:\dir`) are canonicalized to
|
|
70
|
+
`file:///C:/dir`, matching Node.
|
|
71
|
+
- Not a full WHATWG parser: path percent-encoding, IDNA, setters and live
|
|
72
|
+
`searchParams` synchronisation are not implemented — see
|
|
73
|
+
[Runtime deviations](../unimplemented/deviations.md).
|
|
74
|
+
|
|
58
75
|
## URLSearchParams
|
|
59
76
|
|
|
60
77
|
- `URLSearchParams` is implemented in `runtime/xt_url.c`.
|
|
@@ -8,6 +8,7 @@ These features **compile and run**, but the result does not fully match ECMAScri
|
|
|
8
8
|
| --- | --- |
|
|
9
9
|
| RegExp byte-oriented matching | The engine matches UTF-8 bytes: literal multi-byte text works, but `.` and character classes consume one byte per repetition (`\d` / `\w` stay ASCII). Offsets returned by `exec` / `search` / replacement callbacks are converted to UTF-16 code units |
|
|
10
10
|
| Global RegExp `lastIndex` | `test` / `exec` do not advance or honour a caller-set `lastIndex` for `/g` / `/y` regexes |
|
|
11
|
+
| `URL` parser | Read-only WHATWG subset: no path percent-encoding, IDNA, setters or live `searchParams`; a reference with no scheme resolves against the working directory as a `file:` URL |
|
|
11
12
|
| String `normalize` | Not implemented |
|
|
12
13
|
| First-class built-in methods | Implemented as unbound method values (see [Functions](./functions.md)); `fn.toString()` returns a placeholder rather than source text |
|
|
13
14
|
| `for...in` | Enumerates own keys of objects / arrays / strings; does not include prototype-chain properties |
|
package/doc/zh-CN/gui/api.md
CHANGED
|
@@ -22,10 +22,38 @@ run(); // 驱动主循环,直到所有窗口
|
|
|
22
22
|
`getHTML` / `setBackground` / `close` / `isOpen` / `on` / `off`,以及
|
|
23
23
|
`driver()`——它报告当前使用的 SDL_GPU 后端(`"vulkan"`、`"direct3d12"`、
|
|
24
24
|
`"metal"` 等,由 SDL 挑选设备支持的最佳后端)。同时也提供 Web 写法:
|
|
25
|
-
`addEventListener` / `removeEventListener`
|
|
26
|
-
`
|
|
25
|
+
`addEventListener` / `removeEventListener` 接受标准的选项对象(`capture`、
|
|
26
|
+
`once`、`passive`、`signal`),`closed` getter 对应 `isOpen()`,因此按浏览器
|
|
27
27
|
API 编写的文档可以原样运行。
|
|
28
28
|
|
|
29
|
+
元素监听器支持同一组选项:`{ once }` 在首次调用后移除监听器,`{ passive: true }`
|
|
30
|
+
使 `preventDefault()` 变成无操作,`{ signal }`(来自 `new AbortController()` 的
|
|
31
|
+
`AbortSignal`)在 abort 时移除监听器,包括添加时就已经 abort 的信号。
|
|
32
|
+
`element.dispatchEvent(event)` 派发的就是**同一个**事件对象(身份可观察),并填充
|
|
33
|
+
`target` / `currentTarget` / `eventPhase`、记录路径供 `event.composedPath()` 使用。
|
|
34
|
+
`new Event(...)`、`new CustomEvent(...)`、`new MouseEvent(...)`、
|
|
35
|
+
`new KeyboardEvent(...)`、`new PointerEvent(...)`、`new WheelEvent(...)`、
|
|
36
|
+
`new FocusEvent(...)`、`new InputEvent(...)` 与 `new SubmitEvent(...)` 会保留 `init`
|
|
37
|
+
对象的全部字段(`detail`、`composed`、鼠标/键盘成员等)。窗口监听器接受同一组
|
|
38
|
+
选项(`capture` 参与监听器身份匹配;窗口投递没有捕获阶段)。
|
|
39
|
+
|
|
40
|
+
窗口导航是真实实现的:`scrollTo(x, y)` / `scrollTo({ left, top })` /
|
|
41
|
+
`scrollBy(...)` 移动页面视口(会按内容边界夹取,绘制与命中测试随之偏移),
|
|
42
|
+
`scrollX` / `scrollY` / `pageXOffset` / `pageYOffset` 报告偏移量。`focus()`
|
|
43
|
+
提升操作系统窗口并置位 `document.hasFocus()`,`blur()` 清除它。事件:
|
|
44
|
+
`ready`(首帧呈现后)、`load`、`close`、`resize`、`scroll`、`focus`、`blur`,
|
|
45
|
+
以及输入事件 `mousemove`、`mousedown`、`mouseup`、`click`、`wheel`、
|
|
46
|
+
`keydown`、`keyup`。
|
|
47
|
+
|
|
48
|
+
`createWindow(options)` 除标题与尺寸外还支持:`{ title, width, height,
|
|
49
|
+
highDensity, resizable, borderless, alwaysOnTop, hidden, fullscreen, x, y,
|
|
50
|
+
opacity, maximized, minimized }`,它们会映射到对应的 SDL 窗口标志/调用,而不是
|
|
51
|
+
被忽略。
|
|
52
|
+
|
|
53
|
+
`window.confirm(message)` / `window.prompt(message, defaultValue)` 不会再丢弃
|
|
54
|
+
参数:设置 `XT_GUI_DIALOGS=1` 且存在窗口时显示原生消息框;否则把消息写到 stderr
|
|
55
|
+
并返回文档化的默认值(`confirm` → `false`,`prompt` → `defaultValue` 或 `""`)。
|
|
56
|
+
|
|
29
57
|
在 Windows 上,GUI 程序会被链接为 **Windows 子系统**可执行文件,因此启动时不会闪出控制台
|
|
30
58
|
窗口;这也意味着从资源管理器启动时 stdout/stderr 无处可去,调试时可在
|
|
31
59
|
`xbintsc.config.json` 里设置 `app.console: true` 保留控制台子系统。
|
|
@@ -60,12 +88,13 @@ requestAnimationFrame(frame);
|
|
|
60
88
|
| `navigator` | `userAgent`(以 `xbintsc` 结尾的桌面 Chrome 字符串)、`platform`、`vendor`、`language(s)`、`hardwareConcurrency`、`maxTouchPoints`、`onLine`、`vibrate()` |
|
|
61
89
|
| `localStorage` | 内存中的 `getItem` / `setItem` / `removeItem` / `clear` / `key` / `length` |
|
|
62
90
|
| `AudioContext`、`webkitAudioContext` | 带真实混音器与解码器的 Web Audio 图(见下) |
|
|
63
|
-
| `Event`、`CustomEvent`、`ProgressEvent`
|
|
91
|
+
| `Event`、`CustomEvent`、`ProgressEvent`、`MouseEvent`、`KeyboardEvent`、`PointerEvent`、`WheelEvent`、`FocusEvent`、`InputEvent`、`SubmitEvent` | 事件构造器;`init` 参数按原样保留(`detail`、`composed`、鼠标/键盘字段等) |
|
|
92
|
+
| `AbortController`、`AbortSignal` | 真实的 controller/signal 对,用于 `{ signal }` 移除监听器,支持 `abort()`、`aborted`、`reason`、`onabort` 与 `throwIfAborted()` |
|
|
64
93
|
| `HTMLCanvasElement`、`HTMLImageElement`、`WebGLRenderingContext`、`WebGL2RenderingContext`、`WebGLBuffer`/`WebGLTexture`/`WebGLShader`/`WebGLProgram`/`WebGLFramebuffer`/`WebGLRenderbuffer`/`WebGLUniformLocation`/`WebGLActiveInfo`/`WebGLVertexArrayObject`/`WebGLSampler`/`WebGLQuery`/`WebGLSync`/`WebGLTransformFeedback` | 真实的构造函数值。`canvas.getContext("webgl")` 与 `getContext("webgl2")` 返回 GPU 上下文(见 [WebGL](./webgl.md))。 |
|
|
65
94
|
| `ImageBitmap`、`createImageBitmap(source)` | 由已解码像素支撑的不可变位图(`<img>`、`<canvas>`、`<video>` 帧与 `ImageData` 形状);promise 立即 settle,`texImage2D` 可直接接受该对象 |
|
|
66
95
|
| `ImageData`、`OffscreenCanvas`、`XRWebGL*`、`Request`、`Headers`、`Response`、`ReadableStream`、`DOMParser` | `typeof` 探测返回 `"undefined"`(没有 XR/fetch/流式后端),让页面走自己的“不支持”分支,而不是调用空壳。Three.js 页面在本后端上使用真实渲染器(见[已知问题](./known-issues.md))。 |
|
|
67
96
|
| `requestAnimationFrame` / `cancelAnimationFrame` | 排入窗口的动画帧列表,见[运行时集成](./runtime.md) |
|
|
68
|
-
| `alert` / `confirm` / `prompt`、`matchMedia`、`getComputedStyle`、`escape` |
|
|
97
|
+
| `alert` / `confirm` / `prompt`、`matchMedia`、`getComputedStyle`、`escape` | 宿主实现。`matchMedia` 返回**实时**列表(按查询缓存):`matches` 在窗口尺寸变化时重新求值,翻转时触发 `change` 监听器。`confirm`/`prompt` 仅在 `XT_GUI_DIALOGS=1` 时使用原生对话框,否则把消息写到 stderr 并返回文档化的默认值(Annex B `escape` 按 UTF-16 码元编码,与 `decodeURIComponent(escape(bytes))` 一致) |
|
|
69
98
|
|
|
70
99
|
`getElementById` / `querySelector` 在 `loadHTML` 之前也能回答:此时得到的是**挂起**句柄,
|
|
71
100
|
首次使用时才绑定到真实节点,因此在模块初始化阶段缓存 `document.querySelector("#id")`
|
package/doc/zh-CN/gui/canvas.md
CHANGED
|
@@ -31,12 +31,19 @@ const ctx = canvas.getContext("2d"); // 或 "webgl" 取得 GPU 上下文
|
|
|
31
31
|
元素上,因此每次都返回**同一个**对象,绘制状态(变换、样式、路径)按 canvas 而非按调用
|
|
32
32
|
保存。`ctx.canvas` 是所属元素的句柄。
|
|
33
33
|
|
|
34
|
+
`getContext("2d", attributes)` 在首次调用时会尊重 `alpha`:传入 `{ alpha: false }`
|
|
35
|
+
时位图以不透明黑色初始化(清除也回到不透明黑)。其余属性由
|
|
36
|
+
`getContextAttributes()` 按规范默认值报告(`antialias: true`、`depth: true`、
|
|
37
|
+
`stencil: false`、`premultipliedAlpha: true`、`preserveDrawingBuffer: false`、
|
|
38
|
+
`colorSpace: "srgb"` 等),特性探测因此能得到诚实的答案。
|
|
39
|
+
|
|
34
40
|
## 绘制模型
|
|
35
41
|
|
|
36
42
|
光栅器刻意保持精简且为自研(不依赖 Skia/Cairo)。它按每条像素行 **4 条垂直子扫描线**
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
进行抗锯齿,并做一次**水平解析覆盖率**计算;路径默认采用**非零环绕规则**填充(因此当弧线
|
|
44
|
+
以相反方向环绕时能形成空洞),`fill("evenodd")` 则改用奇偶规则。轴对齐矩形(变换中
|
|
45
|
+
`b == 0 && c == 0`)走直接的覆盖率快速路径。混合为非预乘 source-over,并按
|
|
46
|
+
`globalAlpha` 缩放。
|
|
40
47
|
|
|
41
48
|
填充或描边可以使用纯色,也可以使用 **`CanvasGradient`**。渐变的坐标属于用户空间,
|
|
42
49
|
因此光栅器会先用当前变换的逆矩阵把每个设备像素映射回用户空间再采样——形状被平移、
|
|
@@ -50,9 +57,11 @@ Canvas 像素**不参与垃圾回收**:canvas 由窗口拥有、以 DOM 节点
|
|
|
50
57
|
## 支持的 API
|
|
51
58
|
|
|
52
59
|
状态与变换:`save` / `restore`(会恢复变换、线宽、透明度、字体/文本设置**以及**
|
|
53
|
-
填充/描边样式)、`translate`、`rotate`、`scale`、`transform(a,b,c,d,e,f)
|
|
54
|
-
`setTransform
|
|
55
|
-
|
|
60
|
+
填充/描边样式)、`translate`、`rotate`、`scale`、`transform(a,b,c,d,e,f)` /
|
|
61
|
+
`transform(matrix)`、`setTransform(a,b,c,d,e,f)` / `setTransform(matrix)`、
|
|
62
|
+
`resetTransform`、`getTransform`(返回带 `a`…`f` 与 `is2D` 的对象)。矩阵可以是
|
|
63
|
+
`{ a, b, c, d, e, f }` 对象或六元素数组。变换按 canvas 的顺序组合:
|
|
64
|
+
`translate(x, y); rotate(a)` 围绕平移后的原点旋转。
|
|
56
65
|
|
|
57
66
|
样式与设置:`fillStyle` / `strokeStyle`(层叠所用的颜色解析器能识别的 CSS 颜色,或
|
|
58
67
|
`CanvasGradient`)、`lineWidth`、`globalAlpha`、`lineCap`(`butt`/`round`/`square`)、
|
|
@@ -70,20 +79,27 @@ Canvas 像素**不参与垃圾回收**:canvas 由窗口拥有、以 DOM 节点
|
|
|
70
79
|
会忽略 `x0`/`y0`——请使用同心圆(`x0 == x1`、`y0 == y1`)。
|
|
71
80
|
|
|
72
81
|
路径:`beginPath`、`closePath`、`moveTo`、`lineTo`、`rect`、`roundRect`、`arc`、
|
|
73
|
-
`ellipse`、`quadraticCurveTo`、`bezierCurveTo`,然后
|
|
74
|
-
`
|
|
75
|
-
|
|
82
|
+
`ellipse`、`quadraticCurveTo`、`bezierCurveTo`,然后
|
|
83
|
+
`fill(fillRule?)` / `fill(path, fillRule?)`(多环;`"nonzero"` 或 `"evenodd"`)或
|
|
84
|
+
`stroke(path?)`。贝塞尔与二次曲线段会被展平为线段;弧线与椭圆同样被展平。
|
|
85
|
+
`roundRect` 接受单个半径数字,或 CSS 半径列表(`[all]`、`[tl, br]`、
|
|
86
|
+
`[tl, tr, br]`、`[tl, tr, br, bl]`,元素为数字或 `{ x, y }` 对;圆角按圆弧绘制)。
|
|
87
|
+
|
|
88
|
+
`Path2D` 支持同一组路径命令(`moveTo`、`lineTo`、`closePath`、`rect`、
|
|
89
|
+
`roundRect`、`arc`、`ellipse`、`quadraticCurveTo`、`bezierCurveTo`、`addPath`),
|
|
90
|
+
并可传给 `fill`/`stroke`,因此一次构建的路径可以在不同变换下重复使用。
|
|
76
91
|
|
|
77
92
|
矩形:`clearRect`、`fillRect`、`strokeRect`。
|
|
78
93
|
|
|
79
94
|
虚线:`setLineDash(segments)` / `getLineDash()` / `lineDashOffset` 实现标准规则
|
|
80
95
|
(奇数长度列表会复制一遍,负数/非有限值会被忽略,全零列表表示实线)。
|
|
81
96
|
|
|
82
|
-
文本:`measureText(text)`(返回 `{ width }`)、`fillText(text, x, y)` 与
|
|
83
|
-
`strokeText(text, x, y)`。文本经 HarfBuzz 排版、FreeType 光栅化(与 HTML
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
97
|
+
文本:`measureText(text)`(返回 `{ width }`)、`fillText(text, x, y, maxWidth?)` 与
|
|
98
|
+
`strokeText(text, x, y, maxWidth?)`。文本经 HarfBuzz 排版、FreeType 光栅化(与 HTML
|
|
99
|
+
文本相同的技术栈),按变换的近似缩放绘制。正的 `maxWidth` 会按比例压缩步进与字形位图,
|
|
100
|
+
使文本宽度不超过该值(与 canvas API 一致),而不是忽略该参数。**仅支持平移与均匀
|
|
101
|
+
缩放**——旋转或斜切变换仍会把每个字形放到其变换后的基线点,但不会旋转字形位图。
|
|
102
|
+
`strokeText` 目前用描边样式执行填充,而非生成轮廓。
|
|
87
103
|
|
|
88
104
|
图像:`drawImage(source, …)` 支持 3 参数(`dx, dy`)、5 参数(`dx, dy, dw, dh`)与
|
|
89
105
|
9 参数(本引擎为**目标优先**:`dx, dy, dw, dh, sx, sy, sw, sh`)。完整的仿射变换
|
|
@@ -95,12 +111,21 @@ Canvas 像素**不参与垃圾回收**:canvas 由窗口拥有、以 DOM 节点
|
|
|
95
111
|
测试钩子:`getImageData(x, y, w, h)` 把区域复制为 `{ width, height, data }`,其中
|
|
96
112
|
`data` 是按行主序的 RGBA8 字节数组。越界像素为透明。
|
|
97
113
|
|
|
114
|
+
图案:`createPattern(source, repetition?)` 接受 `<img>` 或另一个 `<canvas>`,在用户
|
|
115
|
+
空间中平铺(`repeat`、`repeat-x`、`repeat-y`、`no-repeat`),因此平铺会跟随当前
|
|
116
|
+
变换。把结果赋给 `fillStyle`/`strokeStyle`;重新赋颜色会替换掉图案。
|
|
117
|
+
|
|
118
|
+
图像数据与导出:`createImageData(width, height)` 分配一个空的
|
|
119
|
+
`{ width, height, data }`,`putImageData(imageData, dx, dy[, dirtyX, dirtyY,
|
|
120
|
+
dirtyWidth, dirtyHeight])` 直接把字节写入位图(不受变换、混合或 `globalAlpha`
|
|
121
|
+
影响)。`canvas.toDataURL(type?)` 导出 PNG data URL,`canvas.toBlob(callback,
|
|
122
|
+
type?)` 从微任务中交付 Blob 形状的 `{ type, size }`(字节在
|
|
123
|
+
`__xt_gui_blob_data` 上;本运行时没有 `URL.createObjectURL`)。
|
|
124
|
+
|
|
98
125
|
## 尚未实现
|
|
99
126
|
|
|
100
|
-
|
|
101
|
-
`
|
|
102
|
-
|
|
103
|
-
CSS `background-image`,以及离屏画布(`OffscreenCanvas`、
|
|
104
|
-
`transferControlToOffscreen`)。`roundRect` 只接受单个半径,径向渐变会忽略内圆偏移。
|
|
127
|
+
阴影、`clip()`、`globalCompositeOperation`、`isPointInPath`、可切换图像平滑的
|
|
128
|
+
`drawImage`、把 `<canvas>` 用作 CSS `background-image`,以及离屏画布
|
|
129
|
+
(`OffscreenCanvas`、`transferControlToOffscreen`)。径向渐变会忽略内圆偏移。
|
|
105
130
|
|
|
106
131
|
另见[媒体](./media.md):`drawImage` 与纹理上传所共享的图像/视频/音频解码栈。
|
package/doc/zh-CN/gui/dom.md
CHANGED
|
@@ -68,17 +68,59 @@ created.textContent = "added";
|
|
|
68
68
|
box.appendChild(created);
|
|
69
69
|
box.removeChild(created);
|
|
70
70
|
|
|
71
|
+
// 父子变更辅助方法可在同一次调用中混用节点与字符串。
|
|
72
|
+
box.append("text", doc.createElement("span"));
|
|
73
|
+
box.prepend(doc.createElement("b"));
|
|
74
|
+
box.insertAdjacentHTML("beforeend", "<i>tail</i>"); // beforebegin/afterbegin/beforeend/afterend
|
|
75
|
+
box.replaceChildren("fresh", doc.createElement("em"));
|
|
76
|
+
|
|
77
|
+
// 命名空间会被记录;外部(SVG)元素名保留大小写。
|
|
78
|
+
const gradient = doc.createElementNS("http://www.w3.org/2000/svg", "svg:linearGradient");
|
|
79
|
+
console.log(gradient.namespaceURI, gradient.localName, gradient.prefix);
|
|
80
|
+
|
|
71
81
|
inner.addEventListener("click", (e) => console.log(e.target.id, e.currentTarget.id));
|
|
72
82
|
inner.click(); // 在该元素处合成一次点击
|
|
73
83
|
console.log(box.offsetWidth, box.offsetHeight); // 取整后的边框盒
|
|
74
84
|
console.log(box.contains(inner)); // 后代判断
|
|
75
85
|
```
|
|
76
86
|
|
|
87
|
+
### style 属性、dataset、计算样式与几何
|
|
88
|
+
|
|
89
|
+
内联 `style` 对象是一个 CSSOM 声明块。以属性名赋值/读取的是与 `setProperty`
|
|
90
|
+
相同的声明块(`el.style.display = "none"`、`el.style.backgroundColor = "#f00"`,
|
|
91
|
+
驼峰名会映射到 CSS 拼写,`el.style["--accent"]` 用于自定义属性);
|
|
92
|
+
`setProperty(name, value, priority)` 在 `priority` 为 `"important"` 时以
|
|
93
|
+
`!important` 保存该声明(其他优先级值会让本次调用成为无操作,空值则移除该属性)。
|
|
94
|
+
`getPropertyValue` / `getPropertyPriority` 读回声明,`removeProperty` 返回旧值,
|
|
95
|
+
`cssText` 读取或整体替换声明块,`style.length` / `style.item(i)` 枚举声明块,
|
|
96
|
+
未设置的属性返回 `""`。
|
|
97
|
+
|
|
98
|
+
`el.dataset` 是元素 `data-*` 属性之上的实时 `DOMStringMap`:
|
|
99
|
+
`dataset.fooBar` 读取 `data-foo-bar`,赋值写入属性,`delete` 移除属性,
|
|
100
|
+
`Object.keys(dataset)` / `for...in` 只列出 data 键。
|
|
101
|
+
|
|
102
|
+
`getComputedStyle(el, pseudoElt)` 从**层叠结果**读取——UA 样式表、作者规则、
|
|
103
|
+
继承和内联声明——而不是回显内联块,因此写在样式表里的规则同样可见。它支持
|
|
104
|
+
`getPropertyValue`、`getPropertyPriority` 与命名属性(`cs.width`、
|
|
105
|
+
`cs.backgroundColor`、`cs["--accent"]`)。传入 `"::before"` 或 `"::after"`
|
|
106
|
+
可读取生成内容盒;其他伪元素返回空值。每次读取都会先结算待处理的重新样式,
|
|
107
|
+
因此早先创建的句柄在后续变更后仍然有效。
|
|
108
|
+
|
|
109
|
+
`getBoundingClientRect()` 在 `x` / `y` / `width` / `height` 之外还带有旧式的
|
|
110
|
+
`top` / `right` / `bottom` / `left` 成员;`document.title = …` 写入文档的
|
|
111
|
+
`<title>`(页面没有该元素时会创建它以及 `<head>`)。
|
|
112
|
+
|
|
77
113
|
变更操作会把文档标记为脏;引擎会延迟地(在下一次读取或下一帧之前)重新计算
|
|
78
114
|
样式并重新布局。`inner = …`/`innerHTML = …` **不会**执行脚本。元素事件支持
|
|
79
|
-
捕获与冒泡阶段、`stopPropagation`、`once
|
|
80
|
-
|
|
81
|
-
|
|
115
|
+
捕获与冒泡阶段、`stopPropagation`、`once`、`passive` 与 `signal`(`AbortController`
|
|
116
|
+
的信号会在 abort 时移除监听器),并向上冒泡到 `document`/`window`。
|
|
117
|
+
`dispatchEvent` 派发同一个事件对象,并填充 `target`/`currentTarget`/`eventPhase`/
|
|
118
|
+
`composedPath()`。旧式 `win.on(type, fn)` 负载保留其**字符串** `e.target`
|
|
119
|
+
(`div#id.class`);元素 `Event.target` 是一个句柄,其描述符与同一字符串匹配。
|
|
120
|
+
|
|
121
|
+
`element.focus()` 会把元素滚动到可见区域(传入 `{ preventScroll: true }` 则保持
|
|
122
|
+
当前页面偏移);`document.hasFocus()` 报告由 `window.focus()` / `window.blur()`
|
|
123
|
+
切换的窗口焦点状态。
|
|
82
124
|
|
|
83
125
|
### 节点生命周期
|
|
84
126
|
|
package/doc/zh-CN/gui/webgl.md
CHANGED
|
@@ -16,7 +16,7 @@ if (gl == null) {
|
|
|
16
16
|
|
|
17
17
|
2D 上下文把图形光栅化到 CPU 位图再上传为纹理;WebGL 上下文则**在 GPU 上渲染**:顶点变换、光照、纹理采样、深度测试与混合全部在 SDL_GPU 管线中执行(Windows/Linux 上是 Vulkan,macOS 上是 Metal)。页面直接合成该上下文的颜色纹理,因此显示时不需要把像素读回 CPU。
|
|
18
18
|
|
|
19
|
-
同时提供 **WebGL 1.0** 与 **WebGL 2.0**。一个 canvas 会固定为它第一次申请的上下文类型:先调用 `getContext("webgl2")` 之后,`getContext("webgl")` 返回 `null`,反之亦然。WebGL 2
|
|
19
|
+
同时提供 **WebGL 1.0** 与 **WebGL 2.0**。一个 canvas 会固定为它第一次申请的上下文类型:先调用 `getContext("webgl2")` 之后,`getContext("webgl")` 返回 `null`,反之亦然。WebGL 2 上下文拥有自己的 `WebGL2RenderingContext` 原型(其中复制了 WebGL 1 的常量与方法),因此 `gl instanceof WebGL2RenderingContext` 为真,而 `gl instanceof WebGLRenderingContext` 为假,与浏览器一致——three.js 等库正是据此选择 WebGL 2 路径。`gl.constructor.name` 也会报告对应类型名。
|
|
20
20
|
|
|
21
21
|
## 一帧如何到达屏幕
|
|
22
22
|
|
|
@@ -53,7 +53,7 @@ SDL_GPU 不能在运行时编译 GLSL,且每个后端只消费自己的格式
|
|
|
53
53
|
| `gl_FragData[0]` | `xt_FragColor` |
|
|
54
54
|
| 缺少 `#version` / `#version 100` | `#version 310 es` |
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
实现限制:结构体 uniform、用户 uniform 块、预处理阶段无法确定长度的 uniform 数组,以及用非常量表达式索引的采样器数组会被拒绝(shader/link info log 会说明)。`#pragma unroll_loop_start` 循环会在改写前展开,因此 three.js 生成的 `sampler2D shadowMap[ NUM_DIR_LIGHT_SHADOWS ]` / `shadowMap[ i ]` 会变成常量索引。`#ifdef` 内的着色器代码可用;非采样器 uniform 声明会被移动到顶层,保证块保持无条件。两个阶段的非采样器 uniform 会合并成同一个块,并在每个阶段各声明一次(顶点 set 1、片元 set 3),与 SDL_GPU 的 Vulkan 描述符布局一致。在 Metal 上同一批声明会变成 `[[buffer(0)]]` 与 `[[texture(N)]]`/`[[sampler(N)]]`,正是 SDL_GPU Metal 后端绑定的槽位。`uniformMatrix4fv` 按列主序写入反射出的偏移;对采样器调用 `uniform1i` 时记录纹理单元。每次绘制都用动态 uniform 缓冲接口推送该块。
|
|
57
57
|
|
|
58
58
|
翻译器的限制:结构体 uniform、用户 uniform 块、预处理后仍无法确定长度的 uniform 数组、采样器数组与采样器类型不匹配的声明会被拒绝(着色器/链接日志会说明)。`#ifdef` 内的代码没问题;非采样器 uniform 声明会被移到外层顶层位置,保证块是无条件的。
|
|
59
59
|
|
|
@@ -116,6 +116,6 @@ transform feedback(入口为空操作)与 MSAA/采样缓冲(SDL_GPU 的 Me
|
|
|
116
116
|
|
|
117
117
|
## three.js
|
|
118
118
|
|
|
119
|
-
|
|
119
|
+
着色器改写器会把 three.js 的 `#pragma unroll_loop_start` 循环展开为常量索引(否则其采样器数组无法通过 Vulkan GLSL),`.js` 资源加载器则避免渲染器自带的展开器重复处理。`WebGLRenderer` 在本引擎真正的 WebGL 2 后端上原样运行,**不再打包 Canvas2D 回退**。已用 three.js r160 通过 SDL_GPU 验证:`MeshBasicMaterial`、`MeshStandardMaterial`、`MeshPhongMaterial`、`CanvasTexture`、线性雾、环境光/平行光/点光/聚光/半球光、`Sprite`、`Line`、`Points` 与 `InstancedMesh`。
|
|
120
120
|
|
|
121
121
|
本引擎子集之外的能力仍无法模拟:transform feedback 与 MSAA;立方体贴图/环境贴图、深度纹理、HDR/浮点渲染目标与压缩纹理已经可用。需要这些能力的场景无法正确渲染;此前 Canvas2D 回退能显示的内容现在全部走 GPU。
|
package/doc/zh-CN/gui-scripts.md
CHANGED
|
@@ -146,15 +146,16 @@ export default __html;
|
|
|
146
146
|
### 2b. 外部 `<script src>`
|
|
147
147
|
|
|
148
148
|
`<script src="./app.ts">` 相对 HTML 文件读取、解析并拆分:其顶层
|
|
149
|
-
`import`/`export … from`
|
|
150
|
-
|
|
151
|
-
`
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
149
|
+
`import`/`export … from` 语句从主体中移除,其余语句被包装进脚本函数。相对
|
|
150
|
+
import 会像浏览器的模块脚本一样**延迟**:loader 生成一个合成的
|
|
151
|
+
`__xt_deferred_module` 标记,生成的脚本在 `loadHTML` 时调用模块包装函数。
|
|
152
|
+
bundler 把整个本地 import 图包装成返回各自导出的函数(由 `__xt_defer`
|
|
153
|
+
记忆化),因此模块顶层代码在文档就绪后才运行,且两个脚本导入同一模块时共享
|
|
154
|
+
同一个实例。裸说明符(`gui`、npm 包)仍然立即加载。
|
|
155
|
+
|
|
156
|
+
缺失的 `src` 文件仍会抛出清晰的错误(被转换为 bundler 诊断);
|
|
157
|
+
`src` URL(`https://…`、`data:…`、`//host`)保持原样 —— 它们不是编译期资产,
|
|
158
|
+
永不运行。
|
|
158
159
|
|
|
159
160
|
`src` URL(`https://…`、`data:…`、`//host`)保持原样 —— 它们不是编译期资产,
|
|
160
161
|
永不运行。
|
|
@@ -283,10 +284,10 @@ Event 的 `target` 是句柄,其描述符(`toString`)与同一 `div#id.cla
|
|
|
283
284
|
- **M9b** ✅ —— gui `.html` 加载器(`src/extensions/gui/html.ts`)、
|
|
284
285
|
`__registerScript` 内置函数、脚本注册表(`runtime/ext_gui/script.cpp`)、
|
|
285
286
|
`loadHTML` 执行与 `DOMContentLoaded`/`load`;e2e 覆盖。
|
|
286
|
-
- **M9c** ✅ —— 读取 `<script src>`
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
覆盖。
|
|
287
|
+
- **M9c** ✅ —— 读取 `<script src>` 文件,其主体被包装并注册;相对 import
|
|
288
|
+
通过带记忆化的模块包装函数延迟到 `loadHTML` 求值,因此 import 图能看到
|
|
289
|
+
已解析的文档,且同一模块只实例化一次。缺失文件作为诊断浮现。所有脚本按
|
|
290
|
+
文档顺序运行。e2e 覆盖。
|
|
290
291
|
- **M9d** *(可选)* —— 检测传给 `win.loadHTML(...)` 的模板字面量中的内联
|
|
291
292
|
HTML 并同样转换它们(脆弱;推迟)。
|
|
292
293
|
- **M10 — 打磨** ✅ —— 窗口上的
|
package/doc/zh-CN/gui.md
CHANGED
|
@@ -167,9 +167,10 @@ FFmpeg `7.1`(供可选的 `media` 归档使用;可用 `SDL3_TAG` /
|
|
|
167
167
|
`__registerScript` 内置函数注册,并替换为
|
|
168
168
|
`<script data-xt-id="<hash>">` 标记;`win.loadHTML` 在解析后运行匹配的
|
|
169
169
|
函数并触发 `DOMContentLoaded` 然后是 `load`。
|
|
170
|
-
- **M9c** ✅ —— `<script src>` 文件相对 HTML
|
|
171
|
-
|
|
172
|
-
|
|
170
|
+
- **M9c** ✅ —— `<script src>` 文件相对 HTML 读取,其主体被包装/注册;
|
|
171
|
+
相对 import 通过带记忆化的模块包装函数延迟到 `loadHTML` 求值,因此被导入
|
|
172
|
+
模块能看到已解析的文档并共享状态。缺失文件会成为诊断。一切都按文档顺序
|
|
173
|
+
运行。
|
|
173
174
|
10. **M10 — 打磨** ✅
|
|
174
175
|
- `win.requestAnimationFrame(fn)` / `win.cancelAnimationFrame(id)`;回调
|
|
175
176
|
在每帧顶部以帧时间戳运行,并可修改 DOM
|
|
@@ -317,9 +318,9 @@ FFmpeg `7.1`(供可选的 `media` 归档使用;可用 `SDL3_TAG` /
|
|
|
317
318
|
编译为启动时注册、由 `win.loadHTML` 运行的 AOT 函数(在首次布局之前;
|
|
318
319
|
`DOMContentLoaded` 然后是 `load`)。`tests/extensions/gui.test.ts` 中的单元
|
|
319
320
|
测试,`tests/e2e/gui-*.test.ts` 中的 e2e。
|
|
320
|
-
- **M9c** ✅ 外部 `<script src>`
|
|
321
|
-
|
|
322
|
-
|
|
321
|
+
- **M9c** ✅ 外部 `<script src>` 文件被读取,其主体被包装/注册;相对 import
|
|
322
|
+
通过带记忆化的模块包装函数延迟到 `loadHTML`(模块级 DOM 工作因此能看到已解析
|
|
323
|
+
文档);缺失文件会成为诊断。加载器错误被 `loadGraph` 捕获并报告为构建错误。
|
|
323
324
|
- **M10** ✅ 窗口句柄上的 `requestAnimationFrame`/`cancelAnimationFrame`
|
|
324
325
|
(回调在每帧布局之前以帧时间戳运行),以及元素句柄上的
|
|
325
326
|
`offsetWidth`/`offsetHeight`/`contains`;e2e 覆盖在
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
- 全局 `fetch(input, init)` 是 HTTP/1.1 客户端。阻塞的套接字交换(`getaddrinfo`、connect、send、receive)运行在异步 I/O 工作线程池上,因此进行中的请求**不会**卡住事件循环:定时器、套接字与其他 `await` 继续运行,promise 在 reactor 派发完成结果时 settle。
|
|
8
8
|
- 重定向在主线程上处理:每一跳是一次 offload 交换,最多 20 次;301/302/303 会把 POST 改成 GET。
|
|
9
9
|
- 只接受 `http://` URL —— 由于未链接 TLS 后端,`https://` 会以 `TypeError` 拒绝。
|
|
10
|
+
- **没有协议的引用**(相对路径)与 `file://` URL 会读取本地文件,因此编译后的程序
|
|
11
|
+
无需 HTTP 服务即可加载磁盘资源。相对路径相对工作目录解析;支持 `GET` / `HEAD`。
|
|
12
|
+
在 Windows 上,标准写法 `file:///C:/dir/file` 与 `file://C:/dir/file` /
|
|
13
|
+
`file://C:\dir\file` 都指向同一个文件。
|
|
10
14
|
- 选项:`method`、`headers`(普通对象或 `Headers`)、`body` 与 `redirect`(`follow` / `manual` / `error`)。
|
|
11
15
|
- 解析出的 `Response` 形状对象暴露 `ok` / `status` / `statusText` / `url` / `headers` 以及 `text()` / `json()` / `arrayBuffer()` / `bytes()` / `clone()`。响应体在 promise settle 前已完整缓冲;不支持流式响应体。
|
|
12
16
|
- `Headers` 大小写不敏感,提供 `get` / `has` / `set` / `append` / `delete` / `keys` / `values` / `entries` / `forEach` / `getSetCookie`。
|
|
@@ -19,6 +19,16 @@
|
|
|
19
19
|
- 导入绑定与命名空间成员是模块求值时的快照(无实时绑定)—— 见[未实现:模块系统](../unimplemented/modules.md)。
|
|
20
20
|
- 纯类型导入与再导出(`import type { T } from "..."`、`import { type T } from "..."`、`export type { T } from "..."`)会被擦除,**不构成模块依赖边**:目标模块不会被加载或打包,模块之间的纯类型循环也不属于循环依赖。若需要仅求值一个模块而不绑定名字,请使用副作用导入(`import "./mod"`)。
|
|
21
21
|
|
|
22
|
+
## 延迟求值
|
|
23
|
+
|
|
24
|
+
- `gui` 的 `.html` 资产加载器用合成的 `__xt_deferred_module` 绑定标记相对的
|
|
25
|
+
`<script src>` import。bundler 会把该模块及其本地 import 图包装成返回各自
|
|
26
|
+
导出的函数,生成的脚本在 `loadHTML` 之后调用它们(`__xt_defer` 对每个模块
|
|
27
|
+
做记忆化)。这与浏览器的模块脚本一致:文档就绪后才求值 import 图。
|
|
28
|
+
- 同时被普通(非标记)import 引用的模块保持立即求值,并获得一个返回已初始化
|
|
29
|
+
导出的薄包装。
|
|
30
|
+
- 包装体是同步的:延迟脚本模块中的顶层 `await` 不受支持。
|
|
31
|
+
|
|
22
32
|
## import.meta
|
|
23
33
|
|
|
24
34
|
- `import.meta.url` / `.dirname` / `.filename`,由正在运行的可执行文件路径解析。
|
|
@@ -53,6 +53,21 @@
|
|
|
53
53
|
- `Symbol(description)` 原始值(`XT_OBJECT_KIND_SYMBOL`)、13 个著名符号(`Symbol.iterator`、`Symbol.asyncIterator`、`Symbol.match` 等)、`Symbol.for` / `Symbol.keyFor` 全局注册表、`symbol.description` / `toString()` / `valueOf()`。
|
|
54
54
|
- symbol 可作为属性键(`Object.getOwnPropertySymbols`,symbol 键的 `get`/`set`/`in`/`delete`),会被 `Object.keys` / `values` / `entries` / `for...in` / `JSON.stringify` 跳过,打印为 `Symbol(desc)`。
|
|
55
55
|
|
|
56
|
+
## URL
|
|
57
|
+
|
|
58
|
+
- `URL` 实现在 `runtime/xt_url_object.c`:支持 `new URL(input)` 与
|
|
59
|
+
`new URL(input, base)`(base 也可以是另一个 `URL`),并按层级式
|
|
60
|
+
`scheme://authority/path` base 解析相对引用。
|
|
61
|
+
- **没有协议的引用按文件路径处理**:`new URL("./model.glb")` 相对工作目录解析,
|
|
62
|
+
得到 `file:` URL(显式 base 仍然生效,因此 `new URL("./x", import.meta.url)`
|
|
63
|
+
也可用)。
|
|
64
|
+
- 只读属性 `href`、`protocol`、`origin`、`host`、`hostname`、`port`、
|
|
65
|
+
`pathname`、`search`、`hash`、`searchParams` 以及 `toString()` / `toJSON()`;
|
|
66
|
+
绝对输入按原样保留,但 `file:` URL 的 Windows 写法(`file://C:/dir` 与
|
|
67
|
+
`file://C:\dir`)会规范化为 `file:///C:/dir`,与 Node 一致。
|
|
68
|
+
- 不是完整的 WHATWG 解析器:未实现路径百分号编码、IDNA、setter 与
|
|
69
|
+
`searchParams` 的实时同步 —— 见[运行时偏差](../unimplemented/deviations.md)。
|
|
70
|
+
|
|
56
71
|
## URLSearchParams
|
|
57
72
|
|
|
58
73
|
- `URLSearchParams` 实现在 `runtime/xt_url.c`。
|