Skip to content

字节码文件后缀 .bin 改为 .jsb(0.9.0) - #29

Merged
HarlonWang merged 5 commits into
mainfrom
feat/bytecode-ext-qjsb
Oct 7, 2026
Merged

HarlonWang merged 5 commits into
mainfrom
feat/bytecode-ext-qjsb

Conversation

@HarlonWang

@HarlonWang HarlonWang commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

背景

F-Droid 的 scanner.py 对源码树里后缀为 .bin 的二进制文件一律判为 prebuilt binary 并中止构建。TrendingAI 提交的内置页面包(pages/subscription.bin)因此自 1.9.0 起过不了 fdroiddata 的构建(HarlonWang/TrendingAI#153)。

改动

  • QuickJS 字节码不变,文件后缀 .bin → .jsb:CLI 产出、payload 路径派生、Bundle / BuildManifest 读取、sample 的资源收集、测试夹具、文档
  • 三个 npm 包与运行时常量升 0.9.0

兼容

Bundle 只认新后缀,旧宿主读不了新包:宿主升到 0.9 时按 docs/updates.md §4.1 加 hostVersion,新包只在新宿主版本下发。tinyui-updates-server 的路径派生另开 PR 同步。

验证

  • pnpm build && pnpm schema:check && pnpm runtime:check && pnpm typecheck && pnpm test 全绿
  • ./gradlew :compose:testAndroidHostTest :compose:apiCheck :updates:testAndroidHostTest :sample:shared:testAndroidHostTest 全绿

🤖 Generated with Claude Code

Summary by Sourcery

Adopt the .jsb bytecode extension and release the coordinated 0.9.0 package and host compatibility updates.

Bug Fixes:

  • Replace .bin bytecode artifacts with .jsb artifacts across build outputs, package loading, update payloads, samples, tests, and documentation to avoid binary-file scanner rejection.

Enhancements:

  • Update bundle compatibility metadata and host version handling for the 0.9.0 artifact format.
  • Record the effective minimum TinyUI version as the newer of the runtime and CLI versions used to build a package.

Build:

  • Bump the CLI, core, and native packages and runtime version constants to 0.9.0.

Documentation:

  • Update build, bundle, hot-update, runtime, and update protocol documentation to describe .jsb artifacts and the revised compatibility requirements.

Tests:

  • Update JVM and TypeScript test fixtures and assertions for .jsb packages and the new host version.

HarlonWang and others added 2 commits October 7, 2026 11:47
F-Droid 的 scanner 对源码树里后缀为 .bin 的二进制文件一律判为 prebuilt binary
并中止构建,宿主仓提交的内置页面包因此过不了(TrendingAI 自 1.9.0 起卡在 fdroiddata)。
QuickJS 字节码本身不变,只换文件名,CLI 产出、manifest 派生路径、Bundle 读取、
sample 的资源收集与文档同步改。

格式变化:tinyui 0.9 的 Bundle 只认 .qjsb,旧宿主读不了新包,宿主升级时须加 hostVersion
(docs/updates.md §4.1);热下发服务端的路径派生另行同步。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

本 PR 将 QuickJS 字节码文件的约定后缀从 .bin 统一改为 .qjsb,贯穿 CLI 产出、manifest/payload 路径、Compose 宿主读取、样例资源、OTA 协议、测试与文档;同时将 CLI、core、native 及运行时版本升级到 0.9.0,并通过 hostVersion 约束新包仅下发给兼容宿主。

Sequence diagram for loading a .qjsb page bundle

sequenceDiagram
    participant Host as Android/iOS Host
    participant Bundle
    participant Files as BundleFiles
    participant QuickJS

    Host->>Bundle: page(name)
    Bundle->>Files: read(BuildManifest.file(name) + .qjsb)
    Files-->>Bundle: bytecode bytes
    Bundle->>QuickJS: runBytecode(bytecode)
    QuickJS-->>Host: loaded page
Loading

Sequence diagram for host-compatible OTA delivery of .qjsb bundles

sequenceDiagram
    participant Host
    participant Updates as Updates Service
    participant Bundle

    Host->>Updates: fetch hostVersion/current.json
    Updates-->>Host: compatible package pointer
    Host->>Updates: fetch manifest.json and pages/*.qjsb
    Host->>Host: verify hashes and install package
    Host->>Bundle: load installed manifest and files
    Bundle-->>Host: page bytecode
Loading

Flow diagram for the .qjsb bytecode build and loading pipeline

flowchart LR
    TSX[TSX page source] --> ESBuild[esbuild]
    ESBuild --> QJSC[qjsc-kmp]
    QJSC --> Artifact[pages/home.qjsb]
    Artifact --> Manifest[manifest.json]
    Manifest --> Payload[payload and OTA paths]
    Payload --> Bundle[Bundle.page]
    Bundle --> QuickJS[QuickJS runBytecode]
Loading

File-Level Changes

Change Details Files
将页面与运行时 QuickJS 字节码产物的文件后缀从 .bin 统一切换为 .qjsb,保持字节码内容和模块命名不变。
  • CLI 编译输出、bundle/payload 文件复制与路径派生改用 .qjsb。
  • Kotlin Bundle、BuildManifest、Compose 资源收集及运行时生成常量改用新后缀。
  • 同步更新构建链、更新协议、ADR、运行时图示和相关注释。
packages/cli/src/build.ts
packages/cli/src/bundle.ts
packages/cli/src/payload.ts
compose/src/commonMain/kotlin/app/tinyui/BuildManifest.kt
compose/src/commonMain/kotlin/app/tinyui/Bundle.kt
compose/src/commonMain/kotlin/app/tinyui/generated/RuntimeBytecode.kt
sample/shared/build.gradle.kts
docs/adr-006-hot-updates.md
docs/build-chain.md
docs/js-runtime.html
docs/updates-plan.md
docs/updates.md
将三项 npm 包及运行时版本统一提升至 0.9.0,以标识不兼容旧字节码包读取逻辑的宿主变更。
  • 更新 CLI、core、native 的 package 版本和运行时 VERSION 常量。
  • 兼容策略要求宿主升级并通过 hostVersion 将新包与旧宿主隔离下发。
packages/cli/package.json
packages/core/package.json
packages/core/src/version.ts
packages/native/package.json
packages/native/src/index.ts
将跨平台测试、样例夹具和 OTA 流程验证全面迁移到 .qjsb 路径。
  • 更新 CLI bundle/publish/pull 测试及字节码夹具、哈希和路径安全校验。
  • 更新 Compose Bundle smoke test、updates 模块测试和样例资源输入。
packages/cli/test/admin.test.ts
packages/cli/test/bundle.test.ts
packages/cli/test/helpers.ts
packages/cli/test/publish.test.ts
packages/cli/test/pull.test.ts
compose/src/androidHostTest/kotlin/app/tinyui/BundleSmokeTest.kt
compose/src/commonTest/kotlin/app/tinyui/BundleTest.kt
updates/src/commonTest/kotlin/app/tinyui/updates/Fixture.kt
updates/src/commonTest/kotlin/app/tinyui/updates/UpdatesTest.kt

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3d7cebc5-2b09-4e08-9465-bc2946f35fe9
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codeseerbot codeseerbot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CodeSeer 审查

结论:批准

摘要

本次改动将页面和运行时 QuickJS 字节码产物的后缀统一从 .bin 切换为 .qjsb,并同步调整了 CLI 构建、打包、Kotlin Bundle 读取、sample 资源收集、测试夹具和文档。运行时与 npm 包版本也同步提升到 0.9.0。给出的改动中,产物生成、清单派生和消费路径保持一致,未发现由此次增量引入的明确问题。

整个 PR 至 8e5b6bb · gpt-5.6-terra

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 3 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="packages/cli/src/payload.ts" line_range="14" />
<code_context>
 export function payload(manifest: PayloadManifest): { path: string; hashKey: string }[] {
     return [
-        ...manifest.pages.map((module) => ({ path: `${manifest.files[module]}.bin`, hashKey: module })),
+        ...manifest.pages.map((module) => ({ path: `${manifest.files[module]}.qjsb`, hashKey: module })),
         ...Object.values(manifest.i18n?.files ?? {}).map((path) => ({ path, hashKey: path })),
     ];
</code_context>
<issue_to_address>
**New packages fail to download**

When a `.qjsb` package is published while the updates server still derives `.bin` paths, the existing updates server still derives bytecode paths with `.bin`, so it does not serve the `.qjsb` path emitted by `payload()` and clients downloading these packages fail. The server-side path update must be deployed before publishing `.qjsb` packages.

Coordinate deployment of the server path change with this release, or make the server serve paths from the package manifest without assuming an extension.
</issue_to_address>

### Comment 2
<location path="packages/cli/src/payload.ts" line_range="14" />
<code_context>
 export function payload(manifest: PayloadManifest): { path: string; hashKey: string }[] {
     return [
-        ...manifest.pages.map((module) => ({ path: `${manifest.files[module]}.bin`, hashKey: module })),
+        ...manifest.pages.map((module) => ({ path: `${manifest.files[module]}.qjsb`, hashKey: module })),
         ...Object.values(manifest.i18n?.files ?? {}).map((path) => ({ path, hashKey: path })),
     ];
</code_context>
<issue_to_address>
**Old hosts cannot fetch updates**

When a `.qjsb` bundle is published under a `hostVersion` still used by 0.8 clients, the old `Bundle` loader requests `.bin` files while the new CLI publishes `.qjsb` files, so those clients cannot fetch the package and updates fail. The bundle command accepts the caller’s `hostVersion` without enforcing a version change for this format transition.

Require a new `hostVersion` for the extension transition, or otherwise keep old and new artifact formats isolated by host version.

Also at `compose/src/commonMain/kotlin/app/tinyui/Bundle.kt:27`.
</issue_to_address>

### Comment 3
<location path="compose/src/commonMain/kotlin/app/tinyui/Bundle.kt" line_range="27" />
<code_context>
     suspend fun page(name: String): LoadedPage {
         require(name in manifest.pages) { "page $name is not in package ${manifest.name}: ${manifest.pages}" }
-        val bytecode = read(manifest.file(name) + ".bin")
+        val bytecode = read(manifest.file(name) + ".qjsb")
         val module = PageModule(name, bytecode, manifest.buildId(name), i18n())
         return LoadedPage(module, sourceMaps(name), this)
</code_context>
<issue_to_address>
**Sample updates remain on old host version**

When the sample’s 0.9.0 package is published using its current host version and snapshot, the sample still declares `HOST_VERSION = "3"` (`sample/shared/src/commonMain/kotlin/app/tinyui/sample/Host.kt:18`), whose frozen snapshot requires TinyUI 0.8.0 (`sample/shared/tinyui-host/3.txt:2`). The new CLI records TinyUI 0.9.0, so `tinyui publish` rejects that package for host version 3; the sample’s snapshot test still passes because 0.9.0 is compatible with the older floor. Sample OTA publishing is blocked.

Increment the sample’s `HOST_VERSION` and add the corresponding host snapshot for the 0.9.0 host before publishing its `.qjsb` packages.
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 3 findings to address first, and the CLI and Kotlin runtime now locate only .qjsb files, so any already-published or installed package containing .bin artifacts will no longer be readable by the new code. Reverting restores the old lookup, but packages produced or deployed with the new extension remain and must be rebuilt or redeployed; the impact is bounded and repairable.

Blocking findings: packages/cli/src/payload.ts:14, packages/cli/src/payload.ts:14, compose/src/commonMain/kotlin/app/tinyui/Bundle.kt:27


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread packages/cli/src/payload.ts Outdated
Comment thread packages/cli/src/payload.ts Outdated
Comment thread compose/src/commonMain/kotlin/app/tinyui/Bundle.kt Outdated
产物布局由 CLI 决定,同版本起的库才读得了:tinyui-cli 0.9 配旧 tinyui-core 时 manifest 只记
core 版本,publish 会放行给 tinyui 0.8 的宿主,旧 Bundle 取 .bin 取不到。sample 的字节码
后缀随之变了,按 docs/updates.md §4.1 加 hostVersion 并生成快照 4。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@codeseerbot codeseerbot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CodeSeer 审查

结论:批准

摘要

本次增量让构建产物的 tinyui 最低版本同时考虑 tinyui-core 与 CLI 版本,并将 sample host version 升至 4 以标识新的产物布局兼容要求。版本选择逻辑与文档描述一致。主要遗留风险是 Manifest 接口字段注释仍沿用旧语义,可能误导后续使用该类型的维护者。

增量 8e5b6bb..bd97357 · gpt-5.6-terra

Comment thread packages/cli/src/build.ts Outdated
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@codeseerbot codeseerbot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CodeSeer 审查

结论:批准

上轮意见:1 条,已处理 1 条,待处理 0 条

摘要

本次增量仅修正了 Manifest.tinyui 的接口注释,使其说明与 tinyuiVersion() 实际取 tinyui-core 和 CLI 较新版本的逻辑一致。未发现由该注释改动引入的新问题。

增量 bd97357..dc5c1d8 · gpt-5.6-terra

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@HarlonWang HarlonWang changed the title 字节码文件后缀 .bin 改为 .qjsb(0.9.0) 字节码文件后缀 .bin 改为 .jsb(0.9.0) Oct 7, 2026

@codeseerbot codeseerbot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CodeSeer 审查

结论:批准

摘要

本次增量将字节码产物后缀从 .qjsb 统一切换为 .jsb,覆盖了 CLI 构建、打包 payload、Kotlin Bundle 加载、示例资源收集以及热更新测试夹具。清单中的文件路径派生、哈希校验和下载/安装路径均与新后缀一致。未发现由本次增量引入的可确认问题。

增量 dc5c1d8..1678fd4 · gpt-5.6-terra

@HarlonWang
HarlonWang merged commit c8b0469 into main Oct 7, 2026
5 checks passed
@HarlonWang
HarlonWang deleted the feat/bytecode-ext-qjsb branch October 7, 2026 04:32
HarlonWang added a commit to tiny-ui/tinyui-updates-server that referenced this pull request Oct 7, 2026
* feat: 字节码文件后缀 .bin 改为 .qjsb(tinyui 0.9.0)

与 tiny-ui/tinyui#29 同步:manifest 派生的页面文件路径由 `<files[module]>.bin` 改为
`<files[module]>.qjsb`,上传校验与发布前核对随之。已存储的旧版本按路径原样投递不受影响;
部署后只有 tinyui-cli 0.9 起能发新包,旧 CLI 的 .bin 上传会被判为缺文件。

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* 字节码后缀定为 .jsb

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant