feat(desktop): add windows-app stock target - #419
Open
jnhu76 wants to merge 4 commits into
Open
Conversation
Admit Windows as the third stock target of the portable desktop host: - contracts/spec/platforms.ts: register windows-app at hostAbi 4, platform windows, form window, rasterDensity 2, dynamic viewport 240x180..4096x4096 with acceptsFixed, and the portable desktop capability set (input.buttons, display.viewport.live, text.glyphs.baked, io.offload, text.layout.offload; the systemUI role adds ui.compositor-surfaces) - hosts/desktop/src/plan.rs: map target_os = "windows" to the windows-app HOST_ID and extend the compile-time platform guard - tests/platform-contracts.test.ts, tests/symbian-runtime.test.ts: include windows-app in the stock-target inventories and pin the profile - .github/workflows/desktop-windows.yml: windows-latest CI that runs the target-registry contract tests, resolves and builds the note against windows-app, and runs fmt, clippy, tests and the release host build. The two registry suites run scoped to the target-registry blocks: the unscoped files carry pre-existing Windows path defects (file:// URL pathnames concatenated into /C:/... paths, CRLF byte-exact fixture compares) that fail on every Windows machine; recorded, not repaired here. Local Windows 11 acceptance on the release host (AMD Radeon iGPU): winit creates a real window, wgpu initializes Vulkan with a Bgra8Unorm surface, the note guest reaches the first presented frame, real pointer and keyboard events enter the native event loop, a maximize relayouts live, and CloseRequested exits 0. docs/BACKENDS.md and site/content/docs/platform-contracts.md enumerate windows-app. The platform-contracts target table now reads its capability cells from the registry: the macos-app and web-app rows named text.layout.native and omitted the offload ids.
jnhu76
marked this pull request as ready for review
September 12, 2026 15:23
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR completes Windows stock-target admission for the existing portable
hosts/desktophost by addingwindows-appalongsidemacos-appandlinux-app.It does not add a second Windows desktop architecture, renderer, guest ABI, framework contract, or Windows-specific UI stack.
windows-appuses the existing portable desktop path:The scope rule used throughout this change is:
This is therefore a target-admission and portable-host parity change, not a repository-wide Windows portability campaign.
What this adds
windows-appstock targetcontracts/spec/platforms.tsnow registerswindows-appwith:hostAbi: 4platform: "windows"form: "window"1440 × 960720 × 480240 × 180 … 4096 × 4096rasterDensity: 2Advertised capabilities:
input.buttonsdisplay.viewport.livetext.glyphs.bakedio.offloadtext.layout.offloadSystem-UI role:
ui.compositor-surfacesThe profile follows the existing portable desktop contract rather than introducing Windows-specific semantics.
Portable desktop host admission
hosts/desktop/src/plan.rsnow admits Windows as the third stock target of the same host family:The existing host-plan identity check remains authoritative. A plan whose target id or ABI does not match the compiled host identity is rejected.
No Windows-specific renderer, guest runtime, service protocol, or alternate host architecture is introduced.
Why
hostAbi: 4is correctWindows uses the same host ABI generation already consumed by the portable macOS/Linux desktop host.
This PR adds no:
The change is host admission, not protocol expansion.
Capability closure
The Windows profile does not merely copy capability names. Each advertised capability was traced through its implementation path:
input.buttonsdisplay.viewport.livetext.glyphs.bakedpocket-textpath → desktop DrawList renderingio.offloadhosts/desktop→pocket-ui-surface::OffloadWorkertext.layout.offloadtext_worker→OffloadWorker→pocket-text::Engineui.compositor-surfacesThere is no separate Windows implementation of these semantics.
Why
text-offloadis built in Windows CIwindows-appadvertises bothio.offloadandtext.layout.offload.A registry entry alone would not prove those capabilities participate in a real Windows build. The Windows workflow therefore resolves and builds
apps/text-offloadagainstwindows-app; that app explicitly requires both capabilities.A validated Windows plan contains:
The ordinary
noteguest is also resolved and built against the same target.Stock target vs
pocket buildbackendwindows-appbecoming a stock target does not mean this PR adds apocket buildtarget backend.Today
tools/pocket.tshas backend dispatch entries forpsp,vita, andpocketbook. Desktop targets are not uniformly dispatched through that table:macos-apphas its own desktop tooling, whilelinux-app,windows-app, andweb-appcurrently have nopocket buildbackend entry.So this PR establishes:
tools/build.ts;It intentionally does not add a new
tools/pocket.tsbackend for Windows. The existing documentation insite/content/docs/platform-contracts.mdcalls this split out explicitly.This boundary matters because stock target admission and CLI backend dispatch are separate concerns in the current repository.
Windows CI
This PR adds
.github/workflows/desktop-windows.ymlonwindows-latest.It validates:
noteresolution and compilation againstwindows-app;text-offloadresolution and compilation againstwindows-app;hosts/desktopfmt, clippy, and unit tests;pocket-ui-surfacetests;pocket-texttests;Workflow permissions are limited to:
CI trigger boundary
The workflow path filters intentionally cover the code it actually consumes, including target/contracts, manifest/compiler code,
tools/build.ts, the two guest fixtures, desktop/native crates, workspace manifests/locks, and the workflow itself.This avoids a misleading state where Windows CI exists but a change to the Windows build/compiler closure does not trigger it.
The workflow still does not claim that unrelated PSP/Vita/Symbian/site tooling works on Windows.
Native Windows acceptance
The production
windows-apppath was exercised on real Windows hardware.Environment:
Observed using the production desktop host and production
noteguest:CloseRequested;The real-GPU ignored desktop test
retained_targets_bound_leases_and_survive_resizewas also executed locally and passed.Later commits after physical acceptance changed only CI/workflow policy, not production/runtime/contracts/docs semantics, so that physical acceptance remains applicable to the current implementation.
Why GitHub Windows CI does not run the ignored GPU test
This PR deliberately does not add Windows-specific CI graphics infrastructure such as WARP, Mesa, DXC setup, Agility SDK setup, or a software-GPU acceptance layer merely to run the GPU-dependent ignored test on
windows-latest.The evidence boundary is explicit:
The GitHub workflow does not claim GPU presentation acceptance.
Windows filesystem-path audit
While validating this work, existing repository code using patterns such as:
was observed. On Windows, treating a file-URL pathname directly as a filesystem path can produce forms such as
/C:/Users/...and fail when passed to native filesystem consumers.This PR intentionally does not turn that observation into a repository-wide cleanup.
Instead, the execution closure required by
windows-appwas traced:No blocking
URL.pathname → filesystem pathdefect was found inside that required closure.In particular:
tools/build.tsconverts its repository file URL withfileURLToPath(...);canonicalize;URL.pathnamevalue remains in URL-pathname space for prefix comparison, whileBun.filereceives the URL itself rather than that pathname string.Both
noteandtext-offloadsuccessfully resolve and compile aswindows-appon Windows through this production path.Why unrelated path bugs are not fixed here
Other existing pathname assumptions remain in device/site tooling, including historical paths associated with PSP/Symbian launchers and site/build utilities.
The rule used here is:
This is not justified by the weaker argument that “base and branch fail the same way.” A pre-existing defect would still block this PR if
windows-appdepended on it.Why some registry tests are scoped on Windows
The complete registry-oriented test files also execute unrelated device/tooling paths. Some currently encounter the pre-existing Windows pathname assumptions described above, while local
core.autocrlf=truecheckouts also expose byte-exact fixture differences.Rather than weakening those tests or repairing unrelated tooling, the Windows workflow executes the target-inventory blocks changed by this PR and separately runs the portable services that
windows-appactually advertises. Production Windows guest builds provide an additional end-to-end check of the target/compiler boundary.This PR does not change
.gitattributes, repository line-ending policy, unrelated fixtures, or historical device tooling.CRLF policy
The local Windows validation checkout used
core.autocrlf=true, which exposed existing byte-exact fixture differences in some full test files.No CRLF-only changes were committed. The branch diff remains LF-normalized.
This PR intentionally does not introduce repository-wide line-ending policy as part of Windows target admission.
rasterDensity: 2is not a claim that Windows always runs at 200% DPIrasterDensityis a PocketJS target-owned rendering fact.For the stock Windows profile:
This does not mean every Windows monitor has scale factor 2. The desktop host continues to consume the live window scale reported by winit for runtime window/input/resize behavior. Profile raster density and live OS window scale are separate concepts.
This PR does not claim or implement Per-Monitor DPI V2, cross-monitor DPI migration, dynamic density rebaking, or a Windows DPI application-manifest policy.
Scope extraction
The implementation contains only the PocketJS semantics needed for Windows desktop admission:
It does not carry image-viewer-specific or experimental image-resource work. It adds no native image-resource APIs, image-specific guest ABI, WIC, large-image semantics, additional DrawList opcodes, or Windows-specific compositor code.
Validation
Physical/runtime validation was performed against production semantics at
4082abcb3a0302553be8f87241c787e1c196fc16.The current head adds only the CI trigger-boundary corrective; it does not change production/runtime/contracts/docs semantics.
Local closeout results before opening this PR:
The PR remains Draft until the current head's
windows-latestworkflow completes successfully upstream.What this PR intentionally does not do
This PR does not:
pocket buildWindows backend;URL.pathnamefilesystem assumption;.gitattributes;Those are separate changes if and when their own consumers require them.
Review focus
windows-appa truthful stock profile for the existing portable desktop host?hostAbi: 4the correct identity for that unchanged portable ABI?pocket buildbackend dispatch clear and truthful?The updated Windows workflow is green on the current head; this PR is ready for maintainer review.