xbintsc 0.5.31 → 0.5.36
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 +25 -16
- package/README.zh-CN.md +10 -8
- package/dist/scripts/check-version.d.ts +27 -0
- package/dist/scripts/check-version.js +71 -0
- package/dist/scripts/check-version.js.map +1 -0
- package/dist/scripts/package-platform.d.ts +58 -0
- package/dist/scripts/package-platform.js +142 -0
- package/dist/scripts/package-platform.js.map +1 -0
- package/dist/scripts/verify-platform-package.d.ts +34 -0
- package/dist/scripts/verify-platform-package.js +161 -0
- package/dist/scripts/verify-platform-package.js.map +1 -0
- package/dist/src/binder/references.js +14 -1
- package/dist/src/binder/references.js.map +1 -1
- package/dist/src/cli/help.d.ts +1 -1
- package/dist/src/cli/main.js +3 -1
- package/dist/src/cli/main.js.map +1 -1
- package/dist/src/codegen/generator/module.d.ts +1 -0
- package/dist/src/codegen/generator/module.js +54 -0
- package/dist/src/codegen/generator/module.js.map +1 -1
- package/dist/src/codegen/generator/statements/variables.js +6 -4
- package/dist/src/codegen/generator/statements/variables.js.map +1 -1
- package/dist/src/driver/runtime-lib.d.ts +29 -4
- package/dist/src/driver/runtime-lib.js +68 -10
- package/dist/src/driver/runtime-lib.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/css.d.ts +26 -0
- package/dist/src/extensions/gui/css.js +100 -0
- package/dist/src/extensions/gui/css.js.map +1 -0
- package/dist/src/extensions/gui/html.js +9 -2
- package/dist/src/extensions/gui/html.js.map +1 -1
- package/dist/src/extensions/gui/index.js +22 -7
- package/dist/src/extensions/gui/index.js.map +1 -1
- package/dist/src/extensions/gui/three.d.ts +16 -0
- package/dist/src/extensions/gui/three.js +22 -0
- package/dist/src/extensions/gui/three.js.map +1 -0
- package/dist/src/extensions/media/index.d.ts +6 -5
- package/dist/src/extensions/media/index.js +15 -16
- package/dist/src/extensions/media/index.js.map +1 -1
- package/dist/src/parser/context.d.ts +41 -0
- package/dist/src/parser/context.js +89 -4
- package/dist/src/parser/context.js.map +1 -1
- package/dist/src/parser/literals.js +6 -12
- package/dist/src/parser/literals.js.map +1 -1
- package/dist/tests/driver/platform-package.test.d.ts +1 -0
- package/dist/tests/driver/platform-package.test.js +49 -0
- package/dist/tests/driver/platform-package.test.js.map +1 -0
- package/dist/tests/driver/runtime-lib.test.js +51 -4
- package/dist/tests/driver/runtime-lib.test.js.map +1 -1
- package/dist/tests/e2e/compile-builtins.test.js +24 -0
- package/dist/tests/e2e/compile-builtins.test.js.map +1 -1
- package/dist/tests/e2e/compile-objects-classes.test.js +23 -0
- package/dist/tests/e2e/compile-objects-classes.test.js.map +1 -1
- package/dist/tests/e2e/gui-audio.test.d.ts +14 -0
- package/dist/tests/e2e/gui-audio.test.js +287 -0
- package/dist/tests/e2e/gui-audio.test.js.map +1 -0
- package/dist/tests/e2e/gui-browser.test.js +1 -1
- package/dist/tests/e2e/gui-browser.test.js.map +1 -1
- package/dist/tests/e2e/gui-effects.test.d.ts +6 -0
- package/dist/tests/e2e/gui-effects.test.js +262 -0
- package/dist/tests/e2e/gui-effects.test.js.map +1 -0
- package/dist/tests/e2e/gui-example-webgl.test.d.ts +10 -0
- package/dist/tests/e2e/gui-example-webgl.test.js +75 -0
- package/dist/tests/e2e/gui-example-webgl.test.js.map +1 -0
- package/dist/tests/e2e/gui-example-webgl2.test.d.ts +8 -0
- package/dist/tests/e2e/gui-example-webgl2.test.js +72 -0
- package/dist/tests/e2e/gui-example-webgl2.test.js.map +1 -0
- package/dist/tests/e2e/gui-helpers.d.ts +7 -0
- package/dist/tests/e2e/gui-helpers.js +1 -0
- package/dist/tests/e2e/gui-helpers.js.map +1 -1
- package/dist/tests/e2e/gui-layout.test.js +48 -0
- package/dist/tests/e2e/gui-layout.test.js.map +1 -1
- package/dist/tests/e2e/gui-media.test.js +83 -4
- package/dist/tests/e2e/gui-media.test.js.map +1 -1
- package/dist/tests/e2e/gui-style.test.js +55 -0
- package/dist/tests/e2e/gui-style.test.js.map +1 -1
- package/dist/tests/e2e/gui-webgl.test.d.ts +11 -0
- package/dist/tests/e2e/gui-webgl.test.js +437 -0
- package/dist/tests/e2e/gui-webgl.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-3d.test.d.ts +4 -0
- package/dist/tests/e2e/gui-webgl2-3d.test.js +264 -0
- package/dist/tests/e2e/gui-webgl2-3d.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-blit.test.d.ts +10 -0
- package/dist/tests/e2e/gui-webgl2-blit.test.js +262 -0
- package/dist/tests/e2e/gui-webgl2-blit.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-formats.test.d.ts +6 -0
- package/dist/tests/e2e/gui-webgl2-formats.test.js +395 -0
- package/dist/tests/e2e/gui-webgl2-formats.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-mrt.test.d.ts +4 -0
- package/dist/tests/e2e/gui-webgl2-mrt.test.js +105 -0
- package/dist/tests/e2e/gui-webgl2-mrt.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2-ubo.test.d.ts +8 -0
- package/dist/tests/e2e/gui-webgl2-ubo.test.js +112 -0
- package/dist/tests/e2e/gui-webgl2-ubo.test.js.map +1 -0
- package/dist/tests/e2e/gui-webgl2.test.d.ts +10 -0
- package/dist/tests/e2e/gui-webgl2.test.js +282 -0
- package/dist/tests/e2e/gui-webgl2.test.js.map +1 -0
- package/dist/tests/extensions/gui-index.test.js +1 -0
- package/dist/tests/extensions/gui-index.test.js.map +1 -1
- package/dist/tests/extensions/gui.test.js +41 -0
- package/dist/tests/extensions/gui.test.js.map +1 -1
- package/dist/tests/extensions/media.test.js +8 -3
- package/dist/tests/extensions/media.test.js.map +1 -1
- package/dist/tests/parser/expressions.test.js +30 -0
- package/dist/tests/parser/expressions.test.js.map +1 -1
- package/dist/tests/platform-tarball.test.d.ts +1 -0
- package/dist/tests/platform-tarball.test.js +111 -0
- package/dist/tests/platform-tarball.test.js.map +1 -0
- package/dist/tests/version.test.js +6 -0
- package/dist/tests/version.test.js.map +1 -1
- package/doc/ai/contributing.md +11 -0
- package/doc/ai/extensions.md +35 -12
- package/doc/ai/troubleshooting.md +17 -11
- package/doc/ai/zh-CN/contributing.md +9 -0
- package/doc/ai/zh-CN/extensions.md +30 -10
- package/doc/ai/zh-CN/troubleshooting.md +14 -8
- package/doc/gui/api.md +63 -14
- package/doc/gui/build.md +79 -16
- package/doc/gui/canvas.md +11 -3
- package/doc/gui/dom.md +35 -17
- package/doc/gui/known-issues.md +57 -24
- package/doc/gui/layout.md +18 -0
- package/doc/gui/media.md +21 -13
- package/doc/gui/rendering.md +50 -3
- package/doc/gui/webgl.md +315 -0
- package/doc/gui.md +113 -18
- package/doc/npm-package.md +59 -29
- package/doc/requirements.md +24 -11
- package/doc/zh-CN/gui/api.md +53 -11
- package/doc/zh-CN/gui/build.md +70 -16
- package/doc/zh-CN/gui/canvas.md +9 -2
- package/doc/zh-CN/gui/dom.md +22 -7
- package/doc/zh-CN/gui/known-issues.md +45 -19
- package/doc/zh-CN/gui/layout.md +14 -0
- package/doc/zh-CN/gui/media.md +18 -11
- package/doc/zh-CN/gui/rendering.md +41 -4
- package/doc/zh-CN/gui/webgl.md +121 -0
- package/doc/zh-CN/gui.md +91 -15
- package/doc/zh-CN/npm-package.md +48 -24
- package/doc/zh-CN/requirements.md +16 -7
- package/llms.txt +2 -0
- package/package.json +17 -1
- package/runtime/ext_gui/audio.cpp +365 -153
- package/runtime/ext_gui/audio_buffer.cpp +166 -0
- package/runtime/ext_gui/audio_buffer.h +37 -0
- package/runtime/ext_gui/audio_decode.cpp +219 -0
- package/runtime/ext_gui/audio_decode.h +39 -0
- package/runtime/ext_gui/audio_device.cpp +87 -0
- package/runtime/ext_gui/audio_effects.cpp +163 -0
- package/runtime/ext_gui/audio_effects.h +25 -0
- package/runtime/ext_gui/audio_internal.h +30 -0
- package/runtime/ext_gui/audio_mixer.cpp +494 -0
- package/runtime/ext_gui/audio_mixer.h +238 -0
- package/runtime/ext_gui/audio_param.cpp +104 -0
- package/runtime/ext_gui/audio_param_object.cpp +155 -0
- package/runtime/ext_gui/browser.cpp +50 -14
- package/runtime/ext_gui/canvas.cpp +3 -18
- package/runtime/ext_gui/canvas_internal.h +10 -0
- package/runtime/ext_gui/canvas_raster.cpp +60 -0
- package/runtime/ext_gui/clip_values.cpp +246 -0
- package/runtime/ext_gui/css.cpp +94 -0
- package/runtime/ext_gui/css.h +22 -1
- package/runtime/ext_gui/css_match.cpp +3 -0
- package/runtime/ext_gui/css_selector.cpp +30 -3
- package/runtime/ext_gui/css_sheet.cpp +89 -45
- package/runtime/ext_gui/document.cpp +4 -1
- package/runtime/ext_gui/document.h +2 -0
- package/runtime/ext_gui/dom.h +16 -0
- package/runtime/ext_gui/dom_api.cpp +1 -0
- package/runtime/ext_gui/dom_api_canvas.cpp +17 -80
- package/runtime/ext_gui/dom_api_canvas_extra.cpp +130 -1
- package/runtime/ext_gui/dom_api_canvas_pending.cpp +41 -0
- package/runtime/ext_gui/dom_api_internal.h +275 -0
- package/runtime/ext_gui/dom_api_webgl.cpp +383 -0
- package/runtime/ext_gui/dom_api_webgl2.cpp +549 -0
- package/runtime/ext_gui/dom_api_webgl2_draw.cpp +269 -0
- package/runtime/ext_gui/dom_api_webgl_buffer.cpp +216 -0
- package/runtime/ext_gui/dom_api_webgl_compressed.cpp +167 -0
- package/runtime/ext_gui/dom_api_webgl_framebuffer.cpp +160 -0
- package/runtime/ext_gui/dom_api_webgl_rt.h +30 -0
- package/runtime/ext_gui/dom_api_webgl_shader.cpp +443 -0
- package/runtime/ext_gui/dom_api_webgl_source.cpp +161 -0
- package/runtime/ext_gui/dom_api_webgl_state.cpp +590 -0
- package/runtime/ext_gui/dom_api_webgl_texture.cpp +485 -0
- package/runtime/ext_gui/dom_api_webgl_ubo.cpp +81 -0
- package/runtime/ext_gui/effect_values.cpp +312 -0
- package/runtime/ext_gui/gradient_values.cpp +476 -0
- package/runtime/ext_gui/grid_values.cpp +230 -0
- package/runtime/ext_gui/gui.cpp +44 -9
- package/runtime/ext_gui/gui_canvas.cpp +50 -2
- package/runtime/ext_gui/gui_engine.h +36 -4
- package/runtime/ext_gui/gui_events.cpp +4 -1
- package/runtime/ext_gui/gui_media.cpp +1 -1
- package/runtime/ext_gui/gui_webgl.cpp +83 -0
- package/runtime/ext_gui/image_bitmap.cpp +28 -0
- package/runtime/ext_gui/image_bitmap.h +26 -0
- package/runtime/ext_gui/image_bitmap_browser.cpp +136 -0
- package/runtime/ext_gui/layout.cpp +21 -0
- package/runtime/ext_gui/layout_flow.cpp +81 -4
- package/runtime/ext_gui/layout_flow_internal.h +31 -0
- package/runtime/ext_gui/layout_grid.cpp +374 -0
- package/runtime/ext_gui/media.cpp +32 -0
- package/runtime/ext_gui/media.h +14 -1
- package/runtime/ext_gui/media_api.h +25 -2
- package/runtime/ext_gui/media_query.cpp +211 -0
- package/runtime/ext_gui/paint.cpp +111 -77
- package/runtime/ext_gui/paint.h +33 -3
- package/runtime/ext_gui/paint_background.cpp +229 -0
- package/runtime/ext_gui/paint_clip.cpp +268 -0
- package/runtime/ext_gui/paint_effects.cpp +324 -0
- package/runtime/ext_gui/paint_internal.h +85 -0
- package/runtime/ext_gui/renderer.cpp +8 -31
- package/runtime/ext_gui/renderer_clip.cpp +196 -0
- package/runtime/ext_gui/renderer_image.cpp +13 -8
- package/runtime/ext_gui/renderer_internal.h +15 -8
- package/runtime/ext_gui/renderer_text.cpp +6 -31
- package/runtime/ext_gui/style.cpp +343 -20
- package/runtime/ext_gui/style.h +144 -3
- package/runtime/ext_gui/style_print.cpp +134 -1
- package/runtime/ext_gui/style_values.cpp +152 -126
- package/runtime/ext_gui/style_values_internal.h +35 -0
- package/runtime/ext_gui/webgl.h +600 -0
- package/runtime/ext_gui/webgl2_constants.h +274 -0
- package/runtime/ext_gui/webgl_blit.cpp +95 -0
- package/runtime/ext_gui/webgl_buffer.cpp +480 -0
- package/runtime/ext_gui/webgl_buffer_objects.cpp +270 -0
- package/runtime/ext_gui/webgl_clear.cpp +142 -0
- package/runtime/ext_gui/webgl_compressed.cpp +180 -0
- package/runtime/ext_gui/webgl_constants.h +317 -0
- package/runtime/ext_gui/webgl_context.cpp +551 -0
- package/runtime/ext_gui/webgl_draw.cpp +560 -0
- package/runtime/ext_gui/webgl_draw_buffers.cpp +75 -0
- package/runtime/ext_gui/webgl_glsl.h +165 -0
- package/runtime/ext_gui/webgl_glsl_compile.cpp +437 -0
- package/runtime/ext_gui/webgl_glsl_rewrite.cpp +367 -0
- package/runtime/ext_gui/webgl_glsl_scan.cpp +590 -0
- package/runtime/ext_gui/webgl_glsl_scan_block.cpp +126 -0
- package/runtime/ext_gui/webgl_glsl_tokens.h +28 -0
- package/runtime/ext_gui/webgl_msl.cpp +62 -0
- package/runtime/ext_gui/webgl_msl.h +33 -0
- package/runtime/ext_gui/webgl_pipeline.cpp +326 -0
- package/runtime/ext_gui/webgl_program_blocks.cpp +58 -0
- package/runtime/ext_gui/webgl_program_internal.h +24 -0
- package/runtime/ext_gui/webgl_shader.cpp +594 -0
- package/runtime/ext_gui/webgl_state.cpp +228 -0
- package/runtime/ext_gui/webgl_texture.cpp +420 -0
- package/runtime/ext_gui/webgl_texture_3d.cpp +215 -0
- package/runtime/ext_gui/webgl_uniform.cpp +167 -0
- package/runtime/ext_gui/webgl_uniform_block.h +31 -0
- package/runtime/ext_gui/webgl_webgl2.cpp +277 -0
- package/runtime/ext_media/decode_audio.cpp +308 -0
- package/runtime/ext_media/media.cpp +1 -1
- package/runtime/ext_media/media_bridge.c +11 -3
- package/runtime/rt.h +17 -0
- package/runtime/rt_internal.h +1 -0
- package/runtime/xt_array_buffer.c +30 -0
- package/runtime/xt_containers/access.inc +8 -0
- package/runtime/xt_regex/api.inc +2 -0
- package/runtime/xt_regex/matcher.inc +16 -3
- package/runtime/xt_regex/parser.inc +8 -2
- package/runtime/xt_regex/types.inc +3 -0
- package/runtime/xt_stdlib2/regexp-match.inc +60 -21
- package/runtime/xt_stdlib2/regexp.inc +1 -0
- package/runtime/xt_typed_array/elements.inc +13 -0
- package/runtime/xt_typed_array.c +1 -1
- package/scripts/build-gui.ts +90 -3
- package/scripts/build-media.ts +335 -62
- package/scripts/build-runtime.ts +21 -16
- package/scripts/check-version.ts +39 -9
- package/scripts/package-platform.ts +183 -0
- package/scripts/set-platform-version.ts +62 -0
- package/scripts/setup-vs-toolchain.ps1 +152 -0
- package/scripts/verify-platform-package.ts +182 -0
- package/src/binder/references.ts +13 -1
- package/src/cli/main.ts +5 -1
- package/src/codegen/generator/module.ts +50 -0
- package/src/codegen/generator/statements/variables.ts +6 -3
- package/src/driver/runtime-lib.ts +73 -9
- package/src/driver/version.ts +1 -1
- package/src/extensions/gui/css.ts +113 -0
- package/src/extensions/gui/html.ts +9 -2
- package/src/extensions/gui/index.ts +22 -7
- package/src/extensions/gui/three.ts +25 -0
- package/src/extensions/media/index.ts +16 -18
- package/src/parser/context.ts +99 -4
- package/src/parser/literals.ts +6 -12
package/README.md
CHANGED
|
@@ -86,8 +86,8 @@ too.
|
|
|
86
86
|
> **Before you start:** check the per-platform prerequisites in
|
|
87
87
|
> [Requirements](./doc/requirements.md). xbintsc does not bundle a compiler, so
|
|
88
88
|
> every platform needs a clang-compatible toolchain installed (macOS: Xcode
|
|
89
|
-
> Command Line Tools; Linux: clang+lld; Windows:
|
|
90
|
-
>
|
|
89
|
+
> Command Line Tools; Linux: clang+lld; Windows: Visual Studio C++ build tools
|
|
90
|
+
> with their bundled LLVM/MSVC).
|
|
91
91
|
|
|
92
92
|
### Prebuilt standalone archives
|
|
93
93
|
|
|
@@ -129,8 +129,9 @@ tar -xf xbintsc-<version>-darwin-arm64.tar.zst
|
|
|
129
129
|
./build/hello
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
-
**Windows example** — install
|
|
133
|
-
[Requirements](./doc/requirements.md)), then download
|
|
132
|
+
**Windows example** — install the Visual Studio C++ build tools (MSVC, MSBuild
|
|
133
|
+
and its bundled LLVM; see [Requirements](./doc/requirements.md)), then download
|
|
134
|
+
an archive from the
|
|
134
135
|
[Releases page](https://github.com/zy445566/xbintsc/releases/latest) (here
|
|
135
136
|
`xbintsc-<version>-win32-x64.tar.zst`; use `-arm64` on Windows on ARM) and run the
|
|
136
137
|
commands below in an **x64 Native Tools Command Prompt for VS 2022** (Windows on
|
|
@@ -171,9 +172,11 @@ npx xbintsc doctor
|
|
|
171
172
|
npx xbintsc build src/main.ts --out build
|
|
172
173
|
```
|
|
173
174
|
|
|
174
|
-
It needs Node.js 22+ and a clang 16+ toolchain. The
|
|
175
|
-
|
|
176
|
-
|
|
175
|
+
It needs Node.js 22+ and a clang 16+ toolchain. The install also brings the
|
|
176
|
+
matching `@xbintsc/<os>-<arch>` package with prebuilt runtime archives (`core`,
|
|
177
|
+
`ext_node`, and `gui`/`media` where the release builds them), so the first build
|
|
178
|
+
links them instead of compiling C. If npm skips that optional package, the
|
|
179
|
+
runtime is compiled from the shipped sources and cached in `.xbintsc/`. See
|
|
177
180
|
[Using xbintsc from npm](./doc/npm-package.md) for a complete guide, CI setup
|
|
178
181
|
and caveats.
|
|
179
182
|
|
|
@@ -287,7 +290,7 @@ run(); // main loop, until every window closes
|
|
|
287
290
|
npm run gui
|
|
288
291
|
npx tsx src/cli/main.ts run examples/gui/hello.ts --ext gui
|
|
289
292
|
|
|
290
|
-
# A
|
|
293
|
+
# A release archive or an npm install already ships the engine:
|
|
291
294
|
xbintsc run app.ts --ext gui
|
|
292
295
|
|
|
293
296
|
# <video>/<audio> playback is a separate opt-in archive, so GUI-only binaries
|
|
@@ -313,13 +316,18 @@ whose document also opens unchanged in a browser.
|
|
|
313
316
|
Platforms and full details: [doc/gui.md](./doc/gui.md) is the engine overview
|
|
314
317
|
(architecture and roadmap); the per-function documents live under
|
|
315
318
|
[doc/gui/](./doc/gui) — API, DOM/CSS, layout, rendering, media, input, animation,
|
|
316
|
-
runtime, build and known issues. Linux and macOS are built and exercised in CI
|
|
317
|
-
|
|
318
|
-
archive (`media.a`)
|
|
319
|
-
(`gui.lib
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
319
|
+
runtime, build and known issues. Linux and macOS are built and exercised in CI;
|
|
320
|
+
their release archives and the optional `@xbintsc/<os>-<arch>` npm packages ship
|
|
321
|
+
the engine (`gui.a`) plus the optional media archive (`media.a`). Windows x64
|
|
322
|
+
gets the same pair (`gui.lib` through SDL_GPU's
|
|
323
|
+
Vulkan backend, and `media.lib` from FFmpeg compiled with clang-cl for the MSVC
|
|
324
|
+
ABI), built in CI with the Visual Studio MSVC + LLVM toolchain a local build
|
|
325
|
+
uses; Windows arm64 still skips them. Running the examples in CI stays
|
|
326
|
+
provisional because hosted runners have no GPU/Vulkan driver. Building
|
|
327
|
+
`media.lib` on Windows needs a POSIX shell and GNU make for FFmpeg's configure
|
|
328
|
+
step: Git for Windows supplies the shell, and make is a native GNU make
|
|
329
|
+
(Chocolatey). See [doc/gui/build.md](./doc/gui/build.md). Without the media archive
|
|
330
|
+
`<video>` and `<audio>` fire `error`.
|
|
323
331
|
|
|
324
332
|
## Incremental compilation
|
|
325
333
|
|
|
@@ -442,7 +450,8 @@ See [Requirements](./doc/requirements.md) for the full, per-platform list.
|
|
|
442
450
|
- Node.js 22+ — to run the compiler from npm or from source; released binaries
|
|
443
451
|
are standalone
|
|
444
452
|
- macOS: the Xcode Command Line Tools (`xcode-select --install`)
|
|
445
|
-
- Windows:
|
|
453
|
+
- Windows: the Visual Studio C++ build tools (MSVC, MSBuild and the bundled
|
|
454
|
+
LLVM; `scripts/setup-vs-toolchain.ps1` imports that exact toolchain)
|
|
446
455
|
- Linux: `clang` and `lld` from your distribution
|
|
447
456
|
- To build a binary yourself: a `clang`-compatible compiler on `PATH`
|
|
448
457
|
(override with `xbintsc_CLANG`)
|
package/README.zh-CN.md
CHANGED
|
@@ -153,9 +153,11 @@ npx xbintsc doctor
|
|
|
153
153
|
npx xbintsc build src/main.ts --out build
|
|
154
154
|
```
|
|
155
155
|
|
|
156
|
-
它需要 Node.js 22+ 与 clang 16+
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
它需要 Node.js 22+ 与 clang 16+ 工具链。安装时还会带上宿主平台对应的
|
|
157
|
+
`@xbintsc/<os>-<arch>` 包,其中包含预编译运行时归档(`core`、`ext_node`,以及
|
|
158
|
+
发布为其构建的 `gui`/`media`),所以首次构建直接链接归档而不编译 C。如果 npm
|
|
159
|
+
跳过了这个可选包,才会从随包源码编译运行时并缓存到 `.xbintsc/`。完整指南、CI
|
|
160
|
+
配置与注意事项见[通过 npm 包使用 xbintsc](./doc/zh-CN/npm-package.md)。
|
|
159
161
|
|
|
160
162
|
### 作为开发者(从源码)
|
|
161
163
|
|
|
@@ -233,7 +235,7 @@ run(); // 主循环,直到所有窗口关闭
|
|
|
233
235
|
npm run gui
|
|
234
236
|
npx tsx src/cli/main.ts run examples/gui/hello.ts --ext gui
|
|
235
237
|
|
|
236
|
-
#
|
|
238
|
+
# 发布包或 npm 安装都已经内含该引擎:
|
|
237
239
|
xbintsc run app.ts --ext gui
|
|
238
240
|
|
|
239
241
|
# <video>/<audio> 播放是单独的可选归档,因此只做界面的二进制不会链接 FFmpeg:
|
|
@@ -256,10 +258,10 @@ xbintsc run examples/gui/media.ts --ext gui,media
|
|
|
256
258
|
平台与完整说明:[doc/zh-CN/gui.md](./doc/zh-CN/gui.md) 是引擎总览(架构与
|
|
257
259
|
路线图);按功能拆分的文档位于 [doc/zh-CN/gui/](./doc/zh-CN/gui) —— API、
|
|
258
260
|
DOM/CSS、布局、绘制、媒体、输入、动画、运行时、构建与已知问题。Linux 与 macOS 已在 CI 中构建
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
261
|
+
并实际运行,其发布包与可选的 `@xbintsc/<os>-<arch>` npm 包内含引擎(`gui.a`)与
|
|
262
|
+
可选的媒体归档(`media.a`);Windows x64 也会随发布包与 npm 平台包提供 `gui.lib`
|
|
263
|
+
(通过 SDL_GPU 的 Vulkan 后端渲染)与 `media.lib`。媒体播放目前仅支持 POSIX:没有
|
|
264
|
+
`media.a` 或在 Windows 上,`<video>` 与 `<audio>` 会触发 `error`。
|
|
263
265
|
|
|
264
266
|
## 增量编译
|
|
265
267
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Verify the release bookkeeping that must agree before a tag is pushed:
|
|
4
|
+
*
|
|
5
|
+
* 1. `COMPILER_VERSION` (reported by `xbintsc version` / `doctor` and embedded
|
|
6
|
+
* in the incremental cache key) matches the version in `package.json`;
|
|
7
|
+
* 2. every `@xbintsc/<os>-<arch>` optional dependency is either the current
|
|
8
|
+
* version (a release checkout) or the published `0.0.0` placeholder (the
|
|
9
|
+
* committed state; release automation rewrites it before `npm publish`).
|
|
10
|
+
*
|
|
11
|
+
* A mismatch means an upgraded compiler can reuse binaries produced by the
|
|
12
|
+
* previous one while presenting the wrong version to bug reports, or that an
|
|
13
|
+
* install would ask npm for a platform package that does not exist.
|
|
14
|
+
*/
|
|
15
|
+
/** The version of the empty `@xbintsc/*` packages created before a release. */
|
|
16
|
+
export declare const PLATFORM_PLACEHOLDER_VERSION = "0.0.0";
|
|
17
|
+
/** Read the version literal from the compiler source. */
|
|
18
|
+
export declare function compilerVersionOf(root: string): string;
|
|
19
|
+
/** Read the published version from package.json. */
|
|
20
|
+
export declare function packageVersionOf(root: string): string;
|
|
21
|
+
/** Returns a human-readable mismatch message, or `undefined` when in sync. */
|
|
22
|
+
export declare function checkCompilerVersion(root: string): string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Returns a message when a platform optional dependency names a version that is
|
|
25
|
+
* neither the release version nor the placeholder, or `undefined` when valid.
|
|
26
|
+
*/
|
|
27
|
+
export declare function checkPlatformVersions(root: string): string | undefined;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Verify the release bookkeeping that must agree before a tag is pushed:
|
|
4
|
+
*
|
|
5
|
+
* 1. `COMPILER_VERSION` (reported by `xbintsc version` / `doctor` and embedded
|
|
6
|
+
* in the incremental cache key) matches the version in `package.json`;
|
|
7
|
+
* 2. every `@xbintsc/<os>-<arch>` optional dependency is either the current
|
|
8
|
+
* version (a release checkout) or the published `0.0.0` placeholder (the
|
|
9
|
+
* committed state; release automation rewrites it before `npm publish`).
|
|
10
|
+
*
|
|
11
|
+
* A mismatch means an upgraded compiler can reuse binaries produced by the
|
|
12
|
+
* previous one while presenting the wrong version to bug reports, or that an
|
|
13
|
+
* install would ask npm for a platform package that does not exist.
|
|
14
|
+
*/
|
|
15
|
+
import { readFileSync } from "node:fs";
|
|
16
|
+
import { dirname, join, resolve } from "node:path";
|
|
17
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
18
|
+
/** The version of the empty `@xbintsc/*` packages created before a release. */
|
|
19
|
+
export const PLATFORM_PLACEHOLDER_VERSION = "0.0.0";
|
|
20
|
+
/** Read the version literal from the compiler source. */
|
|
21
|
+
export function compilerVersionOf(root) {
|
|
22
|
+
const text = readFileSync(join(root, "src", "driver", "version.ts"), "utf8");
|
|
23
|
+
const match = /export const COMPILER_VERSION = "([^"]+)"/.exec(text);
|
|
24
|
+
if (!match)
|
|
25
|
+
throw new Error("COMPILER_VERSION is not declared in src/driver/version.ts");
|
|
26
|
+
return match[1];
|
|
27
|
+
}
|
|
28
|
+
/** Read the published version from package.json. */
|
|
29
|
+
export function packageVersionOf(root) {
|
|
30
|
+
const parsed = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
31
|
+
if (!parsed.version)
|
|
32
|
+
throw new Error("package.json has no version field");
|
|
33
|
+
return parsed.version;
|
|
34
|
+
}
|
|
35
|
+
/** Returns a human-readable mismatch message, or `undefined` when in sync. */
|
|
36
|
+
export function checkCompilerVersion(root) {
|
|
37
|
+
const packageVersion = packageVersionOf(root);
|
|
38
|
+
const compilerVersion = compilerVersionOf(root);
|
|
39
|
+
if (packageVersion === compilerVersion)
|
|
40
|
+
return undefined;
|
|
41
|
+
return (`COMPILER_VERSION is "${compilerVersion}" but package.json is "${packageVersion}".\n` +
|
|
42
|
+
'Update COMPILER_VERSION in src/driver/version.ts (it keys the incremental cache), or fix package.json.');
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Returns a message when a platform optional dependency names a version that is
|
|
46
|
+
* neither the release version nor the placeholder, or `undefined` when valid.
|
|
47
|
+
*/
|
|
48
|
+
export function checkPlatformVersions(root) {
|
|
49
|
+
const parsed = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
50
|
+
for (const [name, spec] of Object.entries(parsed.optionalDependencies ?? {})) {
|
|
51
|
+
if (!name.startsWith("@xbintsc/"))
|
|
52
|
+
continue;
|
|
53
|
+
if (spec === parsed.version || spec === PLATFORM_PLACEHOLDER_VERSION)
|
|
54
|
+
continue;
|
|
55
|
+
return (`optional dependency ${name} is "${spec}", but package.json is "${parsed.version}".\n` +
|
|
56
|
+
`Use "${PLATFORM_PLACEHOLDER_VERSION}" in the committed manifest (release automation rewrites it) ` +
|
|
57
|
+
`or "${parsed.version}" in a release checkout.`);
|
|
58
|
+
}
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
const invokedDirectly = process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
62
|
+
if (invokedDirectly) {
|
|
63
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
64
|
+
const problems = [checkCompilerVersion(root), checkPlatformVersions(root)].filter((problem) => problem !== undefined);
|
|
65
|
+
if (problems.length > 0) {
|
|
66
|
+
process.stderr.write(`xbintsc: version mismatch\n${problems.join("\n")}\n`);
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
process.stdout.write(`xbintsc: version ${compilerVersionOf(root)} matches package.json\n`);
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=check-version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-version.js","sourceRoot":"","sources":["../../scripts/check-version.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Assemble the optional `@xbintsc/<os>-<arch>` npm package for the current host.
|
|
4
|
+
*
|
|
5
|
+
* The package carries the prebuilt archives in the same layout the compiler
|
|
6
|
+
* already searches:
|
|
7
|
+
*
|
|
8
|
+
* package/runtime/lib/<os>-<arch>/{core,ext_node}.{a,lib}
|
|
9
|
+
* package/runtime/lib/<os>-<arch>/gui.{a,lib} (when the release ships it)
|
|
10
|
+
* package/runtime/lib/<os>-<arch>/media.{a,lib} (when the release ships it)
|
|
11
|
+
*
|
|
12
|
+
* `xbintsc` lists these packages in `optionalDependencies`, so npm installs the
|
|
13
|
+
* one matching the host and the driver links its archives instead of compiling
|
|
14
|
+
* the C runtime. Release automation publishes the tarball produced here; see
|
|
15
|
+
* `.github/workflows/release.yml`.
|
|
16
|
+
*
|
|
17
|
+
* Output: `dist/npm-platform/xbintsc-<os>-<arch>-<version>.tgz`.
|
|
18
|
+
*/
|
|
19
|
+
export interface PackageRepository {
|
|
20
|
+
readonly type: string;
|
|
21
|
+
readonly url: string;
|
|
22
|
+
}
|
|
23
|
+
export interface PlatformPackageOptions {
|
|
24
|
+
readonly version: string;
|
|
25
|
+
readonly slug: string;
|
|
26
|
+
readonly repository?: PackageRepository;
|
|
27
|
+
}
|
|
28
|
+
export interface PlatformPackageManifest {
|
|
29
|
+
readonly name: string;
|
|
30
|
+
readonly version: string;
|
|
31
|
+
readonly description: string;
|
|
32
|
+
readonly license: string;
|
|
33
|
+
readonly repository?: PackageRepository;
|
|
34
|
+
readonly os: readonly string[];
|
|
35
|
+
readonly cpu: readonly string[];
|
|
36
|
+
readonly files: readonly string[];
|
|
37
|
+
readonly publishConfig: {
|
|
38
|
+
readonly access: "public";
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/** Every host a release publishes a platform package for. */
|
|
42
|
+
export declare const PLATFORM_SLUGS: readonly ["linux-x64", "linux-arm64", "darwin-x64", "darwin-arm64", "win32-x64", "win32-arm64"];
|
|
43
|
+
/** npm name of the platform package, e.g. `@xbintsc/linux-x64`. */
|
|
44
|
+
export declare function platformPackageName(slug: string): string;
|
|
45
|
+
/**
|
|
46
|
+
* File name `npm pack` gives the platform package, e.g.
|
|
47
|
+
* `xbintsc-linux-x64-1.2.3.tgz` (npm drops the scope from the file name).
|
|
48
|
+
*/
|
|
49
|
+
export declare function platformPackageFileName(slug: string, version: string): string;
|
|
50
|
+
/** Archives every platform package must contain. */
|
|
51
|
+
export declare function requiredArchives(slug: string): string[];
|
|
52
|
+
/** The package manifest written into the staging tree and packed by npm. */
|
|
53
|
+
export declare function platformPackageManifest(options: PlatformPackageOptions): PlatformPackageManifest;
|
|
54
|
+
/**
|
|
55
|
+
* Copy the host's archives into a staging tree, write the manifest and run
|
|
56
|
+
* `npm pack`. Returns the absolute path of the produced `.tgz`.
|
|
57
|
+
*/
|
|
58
|
+
export declare function packagePlatform(root: string, slug?: string): string;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Assemble the optional `@xbintsc/<os>-<arch>` npm package for the current host.
|
|
4
|
+
*
|
|
5
|
+
* The package carries the prebuilt archives in the same layout the compiler
|
|
6
|
+
* already searches:
|
|
7
|
+
*
|
|
8
|
+
* package/runtime/lib/<os>-<arch>/{core,ext_node}.{a,lib}
|
|
9
|
+
* package/runtime/lib/<os>-<arch>/gui.{a,lib} (when the release ships it)
|
|
10
|
+
* package/runtime/lib/<os>-<arch>/media.{a,lib} (when the release ships it)
|
|
11
|
+
*
|
|
12
|
+
* `xbintsc` lists these packages in `optionalDependencies`, so npm installs the
|
|
13
|
+
* one matching the host and the driver links its archives instead of compiling
|
|
14
|
+
* the C runtime. Release automation publishes the tarball produced here; see
|
|
15
|
+
* `.github/workflows/release.yml`.
|
|
16
|
+
*
|
|
17
|
+
* Output: `dist/npm-platform/xbintsc-<os>-<arch>-<version>.tgz`.
|
|
18
|
+
*/
|
|
19
|
+
import { spawnSync } from "node:child_process";
|
|
20
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
21
|
+
import { dirname, join, resolve } from "node:path";
|
|
22
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
23
|
+
import { platformSlug } from "../src/driver/paths.js";
|
|
24
|
+
/** Every host a release publishes a platform package for. */
|
|
25
|
+
export const PLATFORM_SLUGS = [
|
|
26
|
+
"linux-x64",
|
|
27
|
+
"linux-arm64",
|
|
28
|
+
"darwin-x64",
|
|
29
|
+
"darwin-arm64",
|
|
30
|
+
"win32-x64",
|
|
31
|
+
"win32-arm64",
|
|
32
|
+
];
|
|
33
|
+
/** npm name of the platform package, e.g. `@xbintsc/linux-x64`. */
|
|
34
|
+
export function platformPackageName(slug) {
|
|
35
|
+
return `@xbintsc/${slug}`;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* File name `npm pack` gives the platform package, e.g.
|
|
39
|
+
* `xbintsc-linux-x64-1.2.3.tgz` (npm drops the scope from the file name).
|
|
40
|
+
*/
|
|
41
|
+
export function platformPackageFileName(slug, version) {
|
|
42
|
+
return `xbintsc-${slug}-${version}.tgz`;
|
|
43
|
+
}
|
|
44
|
+
/** Split `linux-x64` into its npm `os` and `cpu` constraints. */
|
|
45
|
+
function splitSlug(slug) {
|
|
46
|
+
const dash = slug.lastIndexOf("-");
|
|
47
|
+
if (dash <= 0 || dash === slug.length - 1) {
|
|
48
|
+
throw new Error(`invalid platform slug "${slug}" (expected <os>-<arch>)`);
|
|
49
|
+
}
|
|
50
|
+
return { os: slug.slice(0, dash), arch: slug.slice(dash + 1) };
|
|
51
|
+
}
|
|
52
|
+
/** Archives every platform package must contain. */
|
|
53
|
+
export function requiredArchives(slug) {
|
|
54
|
+
const suffix = slug.startsWith("win32-") ? ".lib" : ".a";
|
|
55
|
+
return [`core${suffix}`, `ext_node${suffix}`];
|
|
56
|
+
}
|
|
57
|
+
/** The package manifest written into the staging tree and packed by npm. */
|
|
58
|
+
export function platformPackageManifest(options) {
|
|
59
|
+
const { os, arch } = splitSlug(options.slug);
|
|
60
|
+
const name = platformPackageName(options.slug);
|
|
61
|
+
return {
|
|
62
|
+
name,
|
|
63
|
+
version: options.version,
|
|
64
|
+
description: `Prebuilt xbintsc C runtime archives for ${options.slug}. Installed automatically by xbintsc.`,
|
|
65
|
+
license: "MIT",
|
|
66
|
+
...(options.repository ? { repository: options.repository } : {}),
|
|
67
|
+
os: [os],
|
|
68
|
+
cpu: [arch],
|
|
69
|
+
files: ["runtime"],
|
|
70
|
+
publishConfig: { access: "public" },
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/** Run npm through the same CLI that invoked this script, when available. */
|
|
74
|
+
function runNpm(args, cwd) {
|
|
75
|
+
const execPath = process.env.npm_execpath;
|
|
76
|
+
const useCli = execPath !== undefined && /\.(cjs|mjs|js)$/.test(execPath);
|
|
77
|
+
const command = useCli ? process.execPath : process.platform === "win32" ? "npm.cmd" : "npm";
|
|
78
|
+
const commandArgs = useCli ? [execPath, ...args] : [...args];
|
|
79
|
+
const result = spawnSync(command, commandArgs, {
|
|
80
|
+
cwd,
|
|
81
|
+
encoding: "utf8",
|
|
82
|
+
shell: !useCli && process.platform === "win32",
|
|
83
|
+
});
|
|
84
|
+
if (result.error)
|
|
85
|
+
throw result.error;
|
|
86
|
+
if (result.status !== 0) {
|
|
87
|
+
throw new Error(`npm ${args.join(" ")} failed (${result.status}):\n${result.stderr}`);
|
|
88
|
+
}
|
|
89
|
+
return { stdout: result.stdout };
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Copy the host's archives into a staging tree, write the manifest and run
|
|
93
|
+
* `npm pack`. Returns the absolute path of the produced `.tgz`.
|
|
94
|
+
*/
|
|
95
|
+
export function packagePlatform(root, slug = platformSlug()) {
|
|
96
|
+
const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
|
|
97
|
+
const libDir = join(root, "runtime", "lib", slug);
|
|
98
|
+
const missing = requiredArchives(slug).filter((name) => !existsSync(join(libDir, name)));
|
|
99
|
+
if (missing.length > 0) {
|
|
100
|
+
throw new Error(`missing ${missing.join(", ")} in ${libDir}; run \`npm run runtime\` first`);
|
|
101
|
+
}
|
|
102
|
+
const stageRoot = join(root, "build", "npm-platform-stage");
|
|
103
|
+
const stage = join(stageRoot, "package");
|
|
104
|
+
rmSync(stageRoot, { recursive: true, force: true });
|
|
105
|
+
mkdirSync(stage, { recursive: true });
|
|
106
|
+
cpSync(libDir, join(stage, "runtime", "lib", slug), { recursive: true });
|
|
107
|
+
const manifest = platformPackageManifest({
|
|
108
|
+
version: pkg.version,
|
|
109
|
+
slug,
|
|
110
|
+
...(pkg.repository ? { repository: pkg.repository } : {}),
|
|
111
|
+
});
|
|
112
|
+
writeFileSync(join(stage, "package.json"), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
113
|
+
writeFileSync(join(stage, "README.md"), `# ${manifest.name}\n\n` +
|
|
114
|
+
`Prebuilt xbintsc runtime archives for \`${slug}\`.\n\n` +
|
|
115
|
+
`This package is installed automatically as an optional dependency of\n` +
|
|
116
|
+
`[\`xbintsc\`](https://www.npmjs.com/package/xbintsc) and is not meant to be\n` +
|
|
117
|
+
`used on its own. The compiler links \`runtime/lib/${slug}/\` from this\n` +
|
|
118
|
+
`package instead of compiling its C runtime on the first build.\n`);
|
|
119
|
+
const license = join(root, "LICENSE");
|
|
120
|
+
if (existsSync(license))
|
|
121
|
+
cpSync(license, join(stage, "LICENSE"));
|
|
122
|
+
const outDir = join(root, "dist", "npm-platform");
|
|
123
|
+
rmSync(outDir, { recursive: true, force: true });
|
|
124
|
+
mkdirSync(outDir, { recursive: true });
|
|
125
|
+
const packed = JSON.parse(runNpm(["pack", "--json", "--pack-destination", outDir], stage).stdout);
|
|
126
|
+
const filename = packed[0]?.filename;
|
|
127
|
+
if (!filename)
|
|
128
|
+
throw new Error("npm pack did not report a tarball name");
|
|
129
|
+
return join(outDir, filename);
|
|
130
|
+
}
|
|
131
|
+
const invokedDirectly = process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
132
|
+
if (invokedDirectly) {
|
|
133
|
+
try {
|
|
134
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
135
|
+
console.log(`xbintsc: wrote ${packagePlatform(root)}`);
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
console.error(`xbintsc: ${error instanceof Error ? error.message : String(error)}`);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=package-platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-platform.js","sourceRoot":"","sources":["../../scripts/package-platform.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Verify the `@xbintsc/<os>-<arch>` npm tarballs staged for a release.
|
|
4
|
+
*
|
|
5
|
+
* `release.yml` publishes one platform package per host before `xbintsc` and
|
|
6
|
+
* then points the main manifest's `optionalDependencies` at exactly those
|
|
7
|
+
* versions, so every tarball has to prove it was packed from this release: its
|
|
8
|
+
* manifest must name `@xbintsc/<slug>@<version>` and it must carry the runtime
|
|
9
|
+
* archives the driver links (`core` and `ext_node`, see `requiredArchives`).
|
|
10
|
+
*
|
|
11
|
+
* This runs in Node on purpose. The check used to be a shell pipeline,
|
|
12
|
+
* `tar -tf x.tgz | grep -q <pattern>`, under `set -o pipefail`: `grep -q` closes
|
|
13
|
+
* the pipe on its first match, so `tar` — still decompressing the tens of
|
|
14
|
+
* megabytes that follow `core.a` — dies of SIGPIPE, and the pipeline reports a
|
|
15
|
+
* perfectly good tarball as "has no core runtime archive". Reading the gzip
|
|
16
|
+
* stream here has no such race, needs no external `tar` and behaves the same on
|
|
17
|
+
* every host.
|
|
18
|
+
*
|
|
19
|
+
* Usage: `npm run verify:platform -- --dir platform-packages [--version x.y.z]`
|
|
20
|
+
*/
|
|
21
|
+
/** One member of a tar archive; `data` is a view into the decompressed stream. */
|
|
22
|
+
export interface TarEntry {
|
|
23
|
+
readonly path: string;
|
|
24
|
+
readonly data: Buffer;
|
|
25
|
+
}
|
|
26
|
+
/** List the regular files of a gzip-compressed tar archive, in archive order. */
|
|
27
|
+
export declare function tarballEntries(tgz: Buffer, source?: string): TarEntry[];
|
|
28
|
+
/**
|
|
29
|
+
* Check one platform tarball's manifest identity and runtime archives.
|
|
30
|
+
* `source` names the tarball in error messages (its path, or a fixture name).
|
|
31
|
+
*/
|
|
32
|
+
export declare function verifyPlatformEntries(entries: readonly TarEntry[], slug: string, version: string, source?: string): void;
|
|
33
|
+
/** Read `tgzPath` and verify it as the platform package for `slug`/`version`. */
|
|
34
|
+
export declare function verifyPlatformPackage(tgzPath: string, slug: string, version: string): TarEntry[];
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Verify the `@xbintsc/<os>-<arch>` npm tarballs staged for a release.
|
|
4
|
+
*
|
|
5
|
+
* `release.yml` publishes one platform package per host before `xbintsc` and
|
|
6
|
+
* then points the main manifest's `optionalDependencies` at exactly those
|
|
7
|
+
* versions, so every tarball has to prove it was packed from this release: its
|
|
8
|
+
* manifest must name `@xbintsc/<slug>@<version>` and it must carry the runtime
|
|
9
|
+
* archives the driver links (`core` and `ext_node`, see `requiredArchives`).
|
|
10
|
+
*
|
|
11
|
+
* This runs in Node on purpose. The check used to be a shell pipeline,
|
|
12
|
+
* `tar -tf x.tgz | grep -q <pattern>`, under `set -o pipefail`: `grep -q` closes
|
|
13
|
+
* the pipe on its first match, so `tar` — still decompressing the tens of
|
|
14
|
+
* megabytes that follow `core.a` — dies of SIGPIPE, and the pipeline reports a
|
|
15
|
+
* perfectly good tarball as "has no core runtime archive". Reading the gzip
|
|
16
|
+
* stream here has no such race, needs no external `tar` and behaves the same on
|
|
17
|
+
* every host.
|
|
18
|
+
*
|
|
19
|
+
* Usage: `npm run verify:platform -- --dir platform-packages [--version x.y.z]`
|
|
20
|
+
*/
|
|
21
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
22
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
23
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
24
|
+
import { gunzipSync } from "node:zlib";
|
|
25
|
+
import { PLATFORM_SLUGS, platformPackageFileName, platformPackageName, requiredArchives, } from "./package-platform.js";
|
|
26
|
+
const BLOCK = 512;
|
|
27
|
+
/** Read a header field, stopping at its NUL padding. */
|
|
28
|
+
function readString(block, offset, length) {
|
|
29
|
+
const field = block.subarray(offset, offset + length);
|
|
30
|
+
const end = field.indexOf(0);
|
|
31
|
+
return field.subarray(0, end === -1 ? field.length : end).toString("utf8");
|
|
32
|
+
}
|
|
33
|
+
/** Decode a numeric header field (octal, or base-256 for very large values). */
|
|
34
|
+
function readNumber(block, offset, length) {
|
|
35
|
+
if ((block[offset] & 0x80) !== 0) {
|
|
36
|
+
let value = block[offset] & 0x7f;
|
|
37
|
+
for (let index = 1; index < length; index += 1)
|
|
38
|
+
value = value * 256 + block[offset + index];
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
const text = readString(block, offset, length).trim();
|
|
42
|
+
return text === "" ? 0 : Number.parseInt(text, 8);
|
|
43
|
+
}
|
|
44
|
+
/** The `path=` record of a pax extended header, when it carries one. */
|
|
45
|
+
function paxPath(data) {
|
|
46
|
+
// Records are `<byte length> <key>=<value>\n`; only the path matters here.
|
|
47
|
+
const match = /(?:^|\n)\d+ path=([^\n]*)\n/.exec(data.toString("utf8"));
|
|
48
|
+
return match?.[1];
|
|
49
|
+
}
|
|
50
|
+
/** List the regular files of a gzip-compressed tar archive, in archive order. */
|
|
51
|
+
export function tarballEntries(tgz, source = "tarball") {
|
|
52
|
+
let tar;
|
|
53
|
+
try {
|
|
54
|
+
tar = gunzipSync(tgz);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
58
|
+
throw new Error(`${source} is not a gzip-compressed tar archive (${reason})`);
|
|
59
|
+
}
|
|
60
|
+
const entries = [];
|
|
61
|
+
let offset = 0;
|
|
62
|
+
let override;
|
|
63
|
+
while (offset + BLOCK <= tar.length) {
|
|
64
|
+
const header = tar.subarray(offset, offset + BLOCK);
|
|
65
|
+
if (header.every((byte) => byte === 0))
|
|
66
|
+
break;
|
|
67
|
+
const size = readNumber(header, 124, 12);
|
|
68
|
+
const type = header[156] === 0 ? "0" : String.fromCharCode(header[156]);
|
|
69
|
+
const dataStart = offset + BLOCK;
|
|
70
|
+
if (dataStart + size > tar.length)
|
|
71
|
+
throw new Error(`${source} is truncated`);
|
|
72
|
+
const data = tar.subarray(dataStart, dataStart + size);
|
|
73
|
+
offset = dataStart + Math.ceil(size / BLOCK) * BLOCK;
|
|
74
|
+
// A long path arrives in its own preceding header: GNU `L` stores it
|
|
75
|
+
// verbatim, pax `x` records it as `path=`. `K` only renames a link target.
|
|
76
|
+
if (type === "L") {
|
|
77
|
+
override = readString(data, 0, data.length);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (type === "x") {
|
|
81
|
+
override = paxPath(data) ?? override;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
if (type === "K")
|
|
85
|
+
continue;
|
|
86
|
+
const prefix = readString(header, 345, 155);
|
|
87
|
+
const name = readString(header, 0, 100);
|
|
88
|
+
const path = override ?? (prefix === "" ? name : `${prefix}/${name}`);
|
|
89
|
+
override = undefined;
|
|
90
|
+
// Only regular files can be the archives checked below; directories and
|
|
91
|
+
// links are skipped instead of being reported by their trailing slash.
|
|
92
|
+
if (type === "0" || type === "7")
|
|
93
|
+
entries.push({ path, data });
|
|
94
|
+
}
|
|
95
|
+
return entries;
|
|
96
|
+
}
|
|
97
|
+
/** Read the manifest out of an already-parsed platform tarball. */
|
|
98
|
+
function manifestOf(entries, source) {
|
|
99
|
+
const manifest = entries.find((entry) => entry.path === "package/package.json");
|
|
100
|
+
if (!manifest)
|
|
101
|
+
throw new Error(`${source} has no package/package.json`);
|
|
102
|
+
try {
|
|
103
|
+
return JSON.parse(manifest.data.toString("utf8"));
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
throw new Error(`${source} has an unreadable package/package.json`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Check one platform tarball's manifest identity and runtime archives.
|
|
111
|
+
* `source` names the tarball in error messages (its path, or a fixture name).
|
|
112
|
+
*/
|
|
113
|
+
export function verifyPlatformEntries(entries, slug, version, source = "platform package") {
|
|
114
|
+
const parsed = manifestOf(entries, source);
|
|
115
|
+
const expectedName = platformPackageName(slug);
|
|
116
|
+
if (parsed.name !== expectedName || parsed.version !== version) {
|
|
117
|
+
throw new Error(`${source} contains ${parsed.name}@${parsed.version}, expected ${expectedName}@${version}`);
|
|
118
|
+
}
|
|
119
|
+
const paths = new Set(entries.map((entry) => entry.path));
|
|
120
|
+
for (const archive of requiredArchives(slug)) {
|
|
121
|
+
const expected = `package/runtime/lib/${slug}/${archive}`;
|
|
122
|
+
if (paths.has(expected))
|
|
123
|
+
continue;
|
|
124
|
+
// Keep the historical wording: `core.a`/`core.lib` is "the core archive".
|
|
125
|
+
const label = archive.replace(/\.(a|lib)$/, "");
|
|
126
|
+
throw new Error(`${source} has no ${label} runtime archive (expected ${expected})`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/** Read `tgzPath` and verify it as the platform package for `slug`/`version`. */
|
|
130
|
+
export function verifyPlatformPackage(tgzPath, slug, version) {
|
|
131
|
+
const entries = tarballEntries(readFileSync(tgzPath), tgzPath);
|
|
132
|
+
verifyPlatformEntries(entries, slug, version, tgzPath);
|
|
133
|
+
return entries;
|
|
134
|
+
}
|
|
135
|
+
/** Value of `--name <value>`, or `undefined` when the flag is absent. */
|
|
136
|
+
function argument(name) {
|
|
137
|
+
const index = process.argv.indexOf(name);
|
|
138
|
+
return index >= 0 ? process.argv[index + 1] : undefined;
|
|
139
|
+
}
|
|
140
|
+
const invokedDirectly = process.argv[1] !== undefined && import.meta.url === pathToFileURL(process.argv[1]).href;
|
|
141
|
+
if (invokedDirectly) {
|
|
142
|
+
try {
|
|
143
|
+
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
144
|
+
const dir = argument("--dir") ?? join(root, "platform-packages");
|
|
145
|
+
const version = argument("--version") ??
|
|
146
|
+
JSON.parse(readFileSync(join(root, "package.json"), "utf8")).version;
|
|
147
|
+
for (const slug of PLATFORM_SLUGS) {
|
|
148
|
+
const file = join(dir, platformPackageFileName(slug, version));
|
|
149
|
+
if (!existsSync(file))
|
|
150
|
+
throw new Error(`Missing npm platform package ${file}.`);
|
|
151
|
+
const entries = verifyPlatformPackage(file, slug, version);
|
|
152
|
+
console.log(`xbintsc: ${basename(file)} carries ${entries.length} files`);
|
|
153
|
+
}
|
|
154
|
+
console.log(`xbintsc: verified ${PLATFORM_SLUGS.length} platform packages at ${version}`);
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
console.error(`xbintsc: ${error instanceof Error ? error.message : String(error)}`);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=verify-platform-package.js.map
|