Skip to content

Releases: pocket-nexus/pocketjs

v0.15.0 — One runtime per console runs any game's .pocket, and `pocket` installs the toolchains and selects the target it builds for

Choose a tag to compare

@github-actions github-actions released this 20 Oct 08:18
96e5f40

One runtime per console runs any game's .pocket, and pocket installs the toolchains and selects the target it builds for.
The PSP, PS Vita, Nintendo 3DS, iPod touch 4 and Android each get a generic
runtime built once, and a TypeScript repack writes a game's console package
from it. The CLI runs on Bun, creates standalone projects and resolves
targets from one catalog. MicroTS gains a site and a playground, and the
Nintendo 3DS gains the Pocket Link to a Mac.

  • A generic runtime per console, and repacks in TypeScript.
    bun tools/runtime.ts <target> builds a runtime with no game in it;
    bun tools/repack.ts --target <target> turns it and a game's .pocket
    into a .3dsx, a PSP Memory Stick zip, a .vpk, an .ipa or an APK. At
    boot each runtime reads app.pocket, checks its footer hash, its variant
    and its host ABI, and takes the surfaces and raster density from the plan.
    The .3dsx and PARAM.SFO writers are byte-identical to 3dsxtool and
    vita-mksfoex for the same inputs. The Android repack rewrites the binary
    manifest and resource table, aligns as zipalign -p 4 does and signs v1 +
    v2 with Web Crypto, with no SDK tool. tools/repack/index.ts gives Pocket
    Studio's Worker one row per target.
  • pocket selects targets from one catalog. tools/targets/index.ts
    lists the eighteen targets by the names commands use. A verb acts on the
    first of +<id>, --target or --host-profile, POCKET_TARGET, a
    directory override, the first of targets in pocket.config.ts, and the
    user default, and prints the target and its source. pocket build --all
    builds every project target.
  • pocket target add|list|remove installs the pinned toolchains. Pins
    live in tools/targets/<id>.toolchain.json; each component is checked
    against its SHA-256 and stored under its digest, so equal pins share one
    entry. pocket doctor checks the framework's pins instead of the CLI's.
  • Breaking: the CLI runs on Bun. @pocketjs/cli declares
    #!/usr/bin/env bun and engines.bun; under Node it prints the install
    hint and exits. pocket create writes a standalone project outside a
    checkout, with --framework solid|vue-vapor|octane, and derives the
    manifest of an ESP-IDF project from its host contract.
  • Builds write nothing under the framework directory. The style module is
    served from memory and copied to <outdir>/<output>.styles.ts; the
    transform cache moves to transforms/ under the PocketJS cache root. A
    read-only node_modules and concurrent builds work.
  • The guest runtime's dependencies are exact versions. solid-js,
    @solid-primitives/keyed, the Babel presets, opentype.js and
    babel-plugin-jsx-dom-expressions are pinned to the versions the goldens
    use, and the build checks the application's installed copy.
  • Layout regions and build-time rects. contain-strict (prop 33) makes a
    definite-size node its own solver root, so a change reconciles and solves
    only its region. layout-baked asserts every rect in a subtree is a
    build-time constant; MicroTS solves it once in the no_std core and emits
    the rects into the mount code. Readback rounds with Taffy's round_layout
    on unrounded origins, so a region yields the bits the full tree would.
  • The compiler reports class literals it drops. Each JSX class literal
    with unsupported tokens is reported with file, line and column; it is an
    error under --strict-classes. The simulator boots any built bundle.
  • The Nintendo 3DS links to a Mac. @pocketjs/framework/link and Pocket
    Companion on the Mac carry net requests and the Mac's clock
    (companionNow()), beside the Wi-Fi and QR camera modules. Pocket Home and
    a Hacker News app run on it, and their lists scroll at 58 to 61 fps on an
    Old 3DS through fixed row slots in contain-strict regions.
  • Pocket3D games ship as content-addressed packs and play in one browser
    player.
    A game's packs are pieces named by their bytes under one
    manifest for every device, and a 3DS fetches the pieces it lacks over the
    LAN. The browser player shows each handheld in its shell, speaks English
    and Japanese, keeps the interface's alpha over the scene, and offers
    Download and Remix in a dock a host may draw. Every Pocket3D game shows
    the Pocket3D icon in each console's launcher. See
    Introducing Pocket3D.
  • MicroTS has a site and a playground, and drives two more devices.
    microts.pocket.nexus carries its docs and a browser playground drawn as the
    real devices. The GBA sprite presenter is generated from the layout and
    paint plan. MicroTS Hero runs as a Rockbox plugin on the iPod nano 2G.
  • Breaking: the iPod nano music player is removed (apps/ipod-nano, the
    Pocket Stage audio-playlist@1 service and its tracks); the iPod package
    runs Hero.
  • Android builds one APK for any plan, with a Redmi 1S profile
    (360x640 at density 2) carrying armeabi-v7a and arm64-v8a, and a release
    build.
  • The browser realm draws glyphs at runtime. text.glyphs.runtime draws
    codepoints no atlas holds with the browser and adds them to the atlases.
  • Device fixes. The PSP's GE display list gets cache lines of its own; a
    shared line's write-back had replaced the first commands of the first list
    and drawn 16-bit pixels into the 32-bit display. The PS Vita keeps a font
    atlas as one byte a texel, 1 MiB instead of 4 MiB for the 36 px page.

npm: @pocketjs/framework@0.15.0 · @pocketjs/cli@0.15.0 · full changelog

v0.14.0 — Pocket3D gets a homepage, a title card and its own license, and the PS Vita and Nintendo 3DS replace native builds over their development connections

Choose a tag to compare

@github-actions github-actions released this 05 Oct 02:55
cba5933

Pocket3D gets a homepage, a title card and its own license, and the PS Vita and Nintendo 3DS replace native builds over their development connections.
The repository now names three technologies: PocketJS, Pocket3D and MicroTS.
The core steps 2D physics, builds without std on every target and keeps its
layout tree across structural updates. Pocket Nexus runs on the Old 3DS, the
iPod touch 4 and the Nokia E7.

  • Pocket3D has a homepage and entry points in the repository.
    3d.pocket.nexus presents it with frames captured
    on consoles. pocket3d/README.md states its design and maps its code
    (devices/, engine/pocket3d/, site/pocket3d/); microts/README.md does
    the same for MicroTS, and the README gains an "In this repository" table.
  • A Pocket3D game shows a title card at launch. pocket3d-title draws the
    mark and the name into a console's frame buffer before the game starts
    its renderer
    , for 144 ticks at 60 Hz, with no GPU: vita::play() on the
    PS Vita, play(surface, present) on the PSP, pocket3d_title_play() in a C
    header on the Nintendo 3DS and playTitle() in a browser. The three
    drawers produce the same frames; the crate's tests record their hashes and
    the C header and the browser module are held to them.
  • Breaking: Pocket3D moves from the MIT License to the Pocket3D License
    1.0.
    pocket3d/, devices/ and engine/pocket3d/ keep the MIT License's
    grant and add one condition: a distributed product that draws 3D scenes
    with Pocket3D shows the title card each time it starts. The PocketJS hosts,
    and software that reaches Pocket3D only through them to draw PocketJS
    interfaces, are exempt. A separate written license waives the condition
    (support@pocket.nexus). PocketJS and MicroTS stay MIT; the npm package's
    license is now (MIT AND LicenseRef-Pocket3D-1.0) and ships
    pocket3d/LICENSE. Copies published before this release stay MIT.
  • Breaking: the handheld device kernels are shared, and BSP code moved to
    OpenStrike.
    devices/vita/pocket-vita-gxm, devices/psp/pocket-psp-ge
    and devices/3ds/pocket-3ds-pica hold GPU memory, patching and texture
    storage for every caller. pocket3d::bsp, pocket3d::collide and
    WorldModel::from_bsp left this repository; OpenStrike owns them. The GXM
    kernel gains float and normalized data targets and aligns owned GXP storage
    on the ARM ABI.
  • PS Vita development runs in Pocket Devkit. The Devkit app waits for a
    build over USB: vita:dev push replaces its JS/PAK guest and
    vita:dev native runs another project's native build from the inactive
    slot. Native apps publish renderer telemetry under engine in each status
    receipt, and the USB host closes descriptors idle for 30 s, which ends the
    "filedescriptor out of range" stop after about 40 minutes.
  • The Nintendo 3DS installs and starts .3dsx files over the dev
    connection.
    The Runtime stages an upload, checks its length, CRC-32 and
    3DSX magic, keeps the replaced file as native-previous.3dsx and hands the
    new one to hb:ldr.
  • ui.physics steps 2D jelly bodies inside Ui::tick. Ops 52..56 run a
    fixed-step simulation and write each body's pose into its views as
    paint-only props; a skewX transform prop joins rotate and scale. The wasm
    core, the 3DS host, the iPod touch 4 host and the Nokia E7 host bind it.
  • The core builds without std on hosts and devices, and keeps its layout
    tree.
    Layout rounding at half boundaries no longer differs by one pixel
    between a host test and a device. Inserting, removing or reordering nodes
    reconciles a retained Taffy tree: unchanged nodes keep their handles,
    styles and text measurements.
  • Pocket Nexus fits the Old 3DS frame budget and runs on two more
    devices.
    On an Old 3DS it went from 34.6 ms a frame to 16.7 to 17.0 ms.
    It ships as a standalone iPod touch 4 app and installs on the Nokia E7
    beside Pocket Clear. The iPod touch 4 host runs native games with a depth
    buffer and bundled assets.
  • MicroTS admits imperative code in compiled models. State modules,
    assignable places with in-place array operations, while, do-while,
    break, continue, general for loops, numeric conversions, float math
    and static constant arrays compile to Rust; element reads of stored arrays
    index them in place.
  • Device sessions take leases. Tools that drive a console take a named
    lease, so two sessions do not drive one device, and validation evidence is
    bound to the build that produced it.
  • Breaking: every pocket-stack identifier is pocket-nexus. App ids
    are dev.pocket-nexus.*, the Android package and its JNI symbols follow,
    and the toolchain cache is ~/.cache/pocket-nexus. The canonical origin is
    pocketjs.pocket.nexus; pocketjs.dev keeps working.
  • DevTools and touch fixes. Replay input survives a pause, the touch
    recorder compacts its history and releases empty pages, retired console
    bridges detach on init, guest trace retention is off by default, and
    native touch captures are released before new contacts are assigned.
  • Sites. pocket.nexus is the Pocket Nexus
    homepage, and the PocketJS site takes the candy arcade style.

npm: @pocketjs/framework@0.14.0 · @pocketjs/cli@0.14.0 · full changelog

v0.13.0 — MicroTS compiles Solid and Vue TypeScript apps to native Rust, and the PS Vita gains a wired development runtime

Choose a tag to compare

@github-actions github-actions released this 26 Sep 11:05
900e183

MicroTS compiles Solid and Vue TypeScript apps to native Rust, and the PS Vita gains a wired development runtime.
MicroTS turns an admitted TypeScript view and model into a no_std Rust
application that runs without a guest engine, down to a Game Boy Advance
cartridge. The PS Vita reloads JavaScript and native code over USB. Nokia E7
rendering reaches 60 fps in Pocket Shell, and Pocket3D and the PSP arena
carry larger worlds.

  • MicroTS compiles Solid TSX and Vue SFC views, plus a TypeScript model, to
    Rust.
    With app.aot: true and app.model: "compiled", state seeds,
    methods, memos, effects and async tasks are generated from the TypeScript
    implementation; the default "rust" mode keeps an application-provided
    Rust model behind the same generated trait. Solid and Vue share typed View
    IR format 1; Model IR format 1 records model bodies, dependencies, schedules
    and coroutine states. Admission errors report source locations and there is
    no fallback to another implementation. The package exports new
    solid/std, vue-vapor/std, solid/reactive, vue-vapor/reactive,
    model/tasks, model/animation and net/model entries. See the
    MicroTS guide.
  • MicroTS reaches motion sensors and targets without atomic CAS. A native
    motion driver publishes one fused MotionState per estimate at gravity,
    inertial or geomagnetic level; <MotionHandler> in Solid and @update in
    Vue receive it, and board admission rejects a board below the level a value
    requires. On targets such as ARMv4T, MicroTS and heapless select
    portable-atomic. bun hosts/gba/build.ts builds a 656,316-byte Hero ROM
    that boots in mGBA with a 60,268-byte peak heap.
  • The shared Hero runs one view and model in JavaScript guests and
    generated Rust.
    The standalone hero-vue-sfc and hero-vue-vapor apps
    are removed; Vue Vapor and Octane variants remain inside apps/hero, and
    the npm package ships the Solid Hero sources.
  • PS Vita builds include a wired development runtime. L + R + SELECT
    opens a native menu; bun run vita:dev reloads JS and resources over USB,
    replaces the native SELF through A/B slots with checksum readback, and
    captures the 960 × 544 GXM framebuffer. A failed reload restores the previous
    bundle in a fresh realm. --no-usb-debug omits the USB driver. See
    docs/VITA-USB.md.
  • Nokia E7 rendering reaches 60 fps in Pocket Shell. QuickJS builds at
    -O2 and the Rust core at opt-level=3, both with VFPv2. The GLES backend
    drops per-frame error queries, merges adjacent draws, shares glyph coverage
    pages between full-size and scaled text, and bounds border masks and text
    placement caches. The portrait switcher went from 31.70 to 60.31 fps.
    Installed apps stay resident behind a shared return gesture and release
    their EGL resources while in the background.
  • Pocket3D and the PSP carry larger worlds. BSP maps build spatial draw
    groups once per map, cache PVS membership, cull cooked faces and collision
    hulls, and submit bounded triangle strips; a 28,243-triangle map holds
    59.9 fps on a physical PSP. arena::alloc_permanent reserves process-lifetime
    buffers without power-of-two rounding, and the PSP host exposes QuickJS
    allocator counters and an arena free-space snapshot.
  • ESP-IDF sets the guest heap limit through Kconfig.
    CONFIG_POCKETJS_GUEST_HEAP_LIMIT defaults to 4 MiB; an explicit
    config.heap_limit takes precedence.
  • Breaking: the BlackBerry Classic Android Runtime host and the
    blackberry-android script are removed; the native QNX host remains. The
    early vapor/ compiler experiment moved to a standalone repository, taking
    its vapor:* scripts with it.
  • Tape assertions reject malformed, partial and repeated entries, and the
    suite covers previously omitted tests. The iPod touch 4 installer rejects
    failed digest checks. The site is also served at
    pocket.nexus.

npm: @pocketjs/framework@0.13.0 · @pocketjs/cli@0.13.0 · full changelog

v0.12.0 — Whole-text CJK loading, background resources, and device-aware presentations

Choose a tag to compare

@github-actions github-actions released this 17 Sep 04:27
d3f0be0

Whole-text CJK loading, background resources, and device-aware presentations.
PSPMAN's Japanese text feedback helped shape this release's CJK work.
PocketJS can keep common characters in memory, load uncommon characters in
the background, and show an animated skeleton until an entire text is ready.
Dynamic content such as song titles and book chapters can appear together,
without characters arriving a few at a time.

  • Prepared text reserves every required glyph before loading begins.
    openFontArchive configures common-character residency and memory limits;
    prepareText returns a resource for the complete text. Live resources pin
    their glyphs, including while offscreen, and overlapping texts share cells.
    Solid's Text consumes the resource through the existing resource boundary
    with loading and error fallbacks. A batch that exceeds capacity or contains
    an unavailable glyph reports an error instead of displaying partial text.
  • Font I/O runs through companion or PSP storage workers. Both providers
    use io.offload with bounded requests, retries and session checks. Streamed
    source bitmaps share a 2 MiB native ceiling; closing an archive releases its
    allocations, and failed index-page reads cannot poison later cache hits.
    The Text Lab demonstrates a music list and chapter reader with animated
    skeletons. Regression coverage includes 1,000 runtime song titles, uncommon
    characters, eviction, pinned content and reloads; the PSP build was checked
    on hardware. The implementation is available on PSP and through WASM host
    operations. Other native hosts need the batch operations before enabling it.
  • External fonts are generated assets with an explicit migration path.
    Font tooling builds PJFA archives from application-supplied font files and
    can derive coverage from text files or Unicode ranges. Full font sources
    and generated archives stay outside Git. Downstream apps using custom
    formats, including PSPMAN's PJPF, must regenerate archives and adopt the
    prepared-text lifecycle. This release supplies that framework path; it does
    not migrate PSPMAN itself. See the
    dynamic text guide.
  • Shared resources and offload queues separate I/O from frame work.
    Scoped demand, reactive reads and cache ownership connect visibility to
    resource lifetime. Bounded worker mailboxes carry provider requests and
    results without socket or storage calls on the UI thread. Shared companion
    sessions add reconnect and backpressure for stateful services. A bounded
    Rust prediction module reconciles simulation state without rewinding UI or
    repeating external effects.
  • Applications select presentations from device input and display facts.
    Manifest presentations can target screen count, touch location and control
    availability. Shared actions express confirm, back and media intents;
    keyboards choose layouts for buttons or touch surfaces. Classic controls
    add shared lists, footers, skeletons and sprite spinners, while the system
    sheet exposes application actions and return-to-launcher behavior.
  • Media and text services cover more application flows. Native 3DS
    playback uses the shared media provider with audio-clock timing and bounded
    buffering. Media support adds local downloads and timed captions. Clear's
    companion input uses reusable glyph resources, revision-checked candidate
    windows and text layouts that preserve cached characters across edits.
  • Desktop rendering and native integrations expand. Desktop hosts gain
    portable GPU rendering and offloaded text. ESP-IDF integrations provide
    separate package, guest, UI and renderer components for ESP32-P4 and S3.
    The 3DS runtime isolates application state, returns to the Homebrew Launcher,
    and acquires native sources without PSP dependencies. Legacy iPod touch
    installs use removable user applications.
  • Pocket3D shares geometry across rendering and simulation. Handheld
    animation uses shared skin bindings and indexed PICA skinning. Collision
    geometry also governs water transport; contact-based locomotion, occluder
    fading and themed PocketJS control overlays extend the shared world.
    The site adds handheld application demos, updated use cases and restored
    mobile documentation navigation.

npm: @pocketjs/framework@0.12.0 · @pocketjs/cli@0.12.0 · full changelog

v0.11.0 — Two more device families run PocketJS, a second backend class paints through gpui and measures text on the host, and a paired Nintendo 3DS takes new guests over Wi-Fi

Choose a tag to compare

@github-actions github-actions released this 30 Aug 01:42

Two more device families run PocketJS, a second backend class paints through gpui and measures text on the host, and a paired Nintendo 3DS takes new guests over Wi-Fi.
0.11.0 adds the Nintendo 3DS and the BlackBerry Classic to the host set, a
backend class that hands text measurement to the platform instead of a baked
atlas, and a System that supervises several guests behind one compositor on
macOS, Linux and the browser. Both new device profiles remain private
development targets: each records an exact hardware and firmware tuple, and
neither advertises a production capability from a build alone.

  • The Nintendo 3DS runs a QuickJS guest on both screens. The split follows
    hosts/iphone2g rather than hosts/psp: citro3d is mostly static inline,
    so C owns the GPU while a no_std Rust staticlib built for the built-in
    armv6k-nintendo-3ds target owns the core and exports the DrawList. The top
    screen is a fixed 400×240 viewport and the touch screen a 320×240 auxiliary
    surface; touch arrives on the auxiliary surface alone. 3ds-dev is host ABI
    8. The demo splits one classic iPhone Contacts app across the two: a
    10,000-row virtual list, its section index and its scrubber below, and the
    detail card the phone had to push a navigation level to reach above. Goldens
    run the same PICA200 code path under Azahar and match hardware.
  • Pocket Runtime accepts a new guest over Wi-Fi. bun run 3ds:dev pair
    installs a 32-byte key once through ftpd; after that a paired TCP connection
    carries .pocket updates and dual-screen RGB8 captures as bounded binary
    frames that never enter QuickJS, and bun run 3ds:dev dev bridges the
    existing DevTools protocol to the panel. Updates reuse the Runtime's target
    and ABI admission, immutable package storage, retired-frame acceptance and
    rollback path. L+R+SELECT opens a Runtime-owned menu on the bottom screen
    with the device's IP, pairing and connection state, generation and package
    hash. The pairing key authenticates but does not encrypt the LAN connection,
    and the channel updates guests only: a new .3dsx or CIA still requires
    deployment and a restart.
  • The BlackBerry Classic runs two hosts over one shared contract.
    hosts/blackberry-qnx is a BB10 Core Native host (libscreen, BPS,
    EGL/GLES2) built and packaged as an unsigned development BAR inside the
    digest-pinned BBNDK image and installed on a rooted Classic;
    hosts/blackberry-android is an Android Runtime (API 18) host whose
    v1-signed APK drives the same QuickJS bridge and Rust core through a JNI
    armeabi-v7a library. Both register at 720×720 physical, 360×360 logical at
    density 2, host ABI 9. First device run recorded on an SQC100-4 at
    10.3.3.3216; the port follows both routes onto
    the same square screen.
  • A second backend class paints through gpui and measures text on the
    host.
    The portable family (wgpu, software raster, PPA, GLES2) keeps
    executing the DrawList against compile-time baked font atlases.
    engine/backends/gpui paints through Zed's gpui/Metal renderer instead, and
    text::MeasureFn plus DRAW_OP.TEXT_RUN route measurement and shaping to
    CoreText when an app opts in — a styleHash word keeps identical word
    streams pixel-identical, so demand-render hashes stay truthful. The
    macos-app target ships with it, together with a wrapText host op and a
    Notepad whose word wrap, hit-testing, caret movement, selection and
    undo/redo all read one visual-segment layout, so reflow on resize falls out
    of the reactive width.
  • A System supervises several guests behind one compositor. Pocket System
    resolution, role-scoped compositor surfaces and isolated AppInstance
    supervision arrive with a product-neutral macOS compositor host, and Linux
    and browser System hosts run the same resolved plan.
  • The manifest and the resolved plan carry companion adapters and viewport
    policy.
    app.companions names the exact svcOpen service names an app's
    adapters speak, and the plan carries companions and viewport.policy, so
    a host derives every boot flag from one artifact instead of re-reading the
    raw manifest and matching on the application's name.
  • The gesture layer is framework-neutral and recognizes pinch. The
    recognizer machinery and the kinetic scroller move into gesture-core.ts
    and kinetics-core.ts behind per-framework shims, so the Vue Vapor entry
    runs the same touch pipeline as Solid: contacts latch with their
    host-resolved hit facts, the gesture pump runs before app frame hooks, and
    the tap-to-press recognizer installs at mount. A two-contact pinch
    recognizer measures span on the locked axis and claims both contacts when
    the span change beats pinchSlop and the centroid travel. The legacy UIKit
    runtime replaces its single-contact globals with an eight-slot touch table.
    Pocket Clear on the iPod touch 4 is the demo the layer was built against.
  • via-* adds a middle gradient stop, and vertical gradients point the
    right way on the 3DS.
    The core draws a three-stop gradient as two ordinary
    two-stop boxes, so every backend still sees GRAD_RECT and clipping stays
    where it was. hosts/3ds/src/gfx.c copies the spec's GradDir ordinals
    into C by hand and had ToTop and ToBottom swapped, which inverted every
    vertical gradient on the one backend that does not read the generated Rust
    enum. The gpui raster fallback renders the full viewport and composites
    transparently, and the compiler's path handling is portable on Windows
    again.
  • PocketJS 98 and a desktop benchmark measure the gpui host. apps/desk98
    is a Windows 98 desktop as one guest — draggable, resizable, z-ordered
    windows, taskbar, Start menu, Notepad, Minesweeper and the classic
    shortcuts — with window moves riding paint-only transform props so a drag
    never relayouts and the idle desktop holds the demand-render governor at a
    few frames a second. tools/bench-desktop.ts measures byte-identical web
    editors shelled by Tauri v2 and Electron against the Pocket note on the same
    host; the numbers and their fairness caveats ship with the report.
  • The site is one design system across a nine-chapter homepage. Shared
    tokens, chrome and base stylesheets replace the per-page CSS, the landing
    carries compatibility receipts, and an icon family covers every surface from
    the favicon to the Safari bookmark and the iOS home screen. A new post
    derives the agent-native runtime for embedded
    systems
    .

npm: @pocketjs/framework@0.11.0 · @pocketjs/cli@0.11.0 · full changelog

v0.10.1 — Three more physical phones run PocketJS, Pocket Vapor compiles a smaller reactive graph, and Pocket3D gains a deterministic systemic world

Choose a tag to compare

@github-actions github-actions released this 16 Aug 00:24
66e7bdc

Three more physical phones run PocketJS, Pocket Vapor compiles a smaller reactive graph, and Pocket3D gains a deterministic systemic world.
0.10.1 carries the connected-device work completed after 0.10.0 together with
the compiler, renderer and tooling fixes those devices exposed. The new phone
profiles remain private development targets: each one records an exact
hardware and firmware tuple, and none advertises a production capability from
a build or upload alone.

  • Windows CE runs a real Solid guest on the Meizu M8. One ARM executable
    embeds QuickJS, the app and its assets, and the Rust software renderer; the
    native host copies a 480×720 BGRA framebuffer to the LCD through GDI without
    stretching. The host turns WinCE messages into wide touch coordinates,
    closes cleanly on Home or Escape, registers a build-qualified MiniOneShell
    icon, and deploys over the phone's ActiveSync serial function through PPP
    and RAPI. Status requires advancing guest frames, successful GDI composites
    and matching logical and physical viewports; acceptance additionally
    requires a completed touch and changed application action. The
    field report follows the port from the first
    clipped 320×480 frame to the native, readable result.
  • The sixth-generation iPod touch has a transactional native host. The
    tested iPod7,1 on iOS 12.5.8 runs an arm64 UIKit application at a 320×568
    logical viewport and density 2. Each deploy re-identifies the device, opens
    a fresh UDID-scoped USB tunnel, verifies the staged bundle byte by byte, and
    keeps a rollback copy until SpringBoard registration succeeds. Wide touch
    words preserve the bottom of the 568-point surface, while the device receipt
    proves a live process, advancing frames, completed release and hero_tap.
  • The iPhone 4S runs the retained UI through OpenGL ES 1.1 at Retina
    density.
    The private iOS 6.1.3 host builds an ARMv7 bundle against locally
    derived, hash-pinned linker stubs and requires the physical runtime to report
    a 640×960 GLES1 drawable for its 320×480 logical viewport. Transaction leases,
    staged file hashes, signature checks and rollback keep a failed install from
    replacing the working application; the captured device frame comes from the
    actual Retina renderbuffer.
  • The modern iOS shell's 120 Hz path is complete. Its NativeScript plugin
    pin moves to @nativescript/pocketjs 0.2.1, whose native bridge publishes the
    requested tick rate before guest evaluation. This closes 0.10.0's known
    limitation: a 120 Hz bundle and host now establish the same mount invariant
    instead of refusing the unpublished 0.2.0 bridge.
  • Pocket Vapor removes work that static analysis proves unreachable. A
    sparse conditional constant-propagation pass folds constant ref reads,
    selects decidable branches, and removes their dead dependencies and ROM.
    Frame-local view and bounded-string temporaries now share statically colored
    overlay slots when their generated owners cannot be live together, reducing
    permanent RAM and stack pressure on the NES and Game Boy. Linux parity runs
    can supply MGBA_PREFIX and CC65_LIB without changing the macOS defaults.
  • pocket3d-world is a renderer-independent fixed-step simulation. Stable
    entity IDs, seeded randomness and ordered phases cover sphere and capsule
    bodies, attachments, structural damage, retained water, heat, fuel and
    combustion. Inputs, initial state and configuration replay to a stable state
    hash; shared collision and reaction laws are tested as general invariants,
    while concrete material recipes remain application-owned. Pocket3D model
    sockets and the optional stylized scene path present that state without
    moving simulation policy into the renderer.
  • Font and desktop-host regressions are closed. The font baker now closes
    implicitly closed CFF contours before scanline filling, retaining their final
    edge, and the Note and widget launchers resolve their Cargo outputs from the
    current engine/ workspace rather than the retired nested path.
  • Release automation runs on the current Node 24-backed GitHub Actions. The
    checkout, cache and setup-node upgrades preserve the existing OIDC trusted
    publishing, build gates and deployment behavior.

npm: @pocketjs/framework@0.10.1 · @pocketjs/cli@0.10.1 · full changelog

v0.10.0 — Apps reach the network, a database and their own files, and a realm declares the rate its virtual time runs at

Choose a tag to compare

@github-actions github-actions released this 14 Aug 17:06
b9a2da7

Apps reach the network, a database and their own files, and a realm declares the rate its virtual time runs at.
0.10.0 adds three modules — net, db and fs — each behind its own
append-only op spec, a deterministic sim host and a reference Rust core, and
turns the core's fixed 1/60 s step into a per-realm constant chosen before the
first tick. Every default remains 60 and the 60 Hz path is the identical
expression throughout, so existing bundles, tapes and frame-hash goldens are
byte-for-byte unchanged.

  • net — bounded whole-response HTTP. fetch() and globalThis.net over
    five ops (start, take, cancel, poll, lastError), with the bounds in
    the spec rather than in each host: 2 in flight, 64 KB of request,
    128 KB of response by default and 256 KB at most, 32 headers. The
    transport never calls into QuickJS — completions are staged to tick
    boundaries and drained one batch per tick — so a network answer cannot land
    in the middle of a frame. Transport adapters stay host-owned; the browser dev
    host, the sim and engine/crates/pocket-net exercise the contract without
    granting network access to every host.
  • db — SQLite behind five synchronous ops. open, close, exec,
    query, lastError, with rows arriving as one JSON line per query() call
    rather than a cursor: at most 4 databases per app, 4096 rows per
    result, names matched against a fixed pattern, and storage the host confines
    to the app. :memory: is spelled the same as SQLite spells it.
  • fs — a per-app file tree behind nine ops. read, write, remove,
    list, stat, mkdir, rename, usage, lastError, plus a
    readFileSync/writeFileSync surface for code that expects one. Every
    path is confined to the app's own data root
    — apps cannot name, let alone
    reach, each other's trees — and the shape of a path is bounded too: 160
    bytes
    , 8 levels, 64 bytes per segment.
  • No stock target advertises the three capabilities yet. net.http,
    data.sqlite and data.fs are registered ahead of any console host shipping
    them, exactly as audio.pcm was: the sim host and the reference cores
    implement the whole contract, so an app can declare the requirement today,
    run against the sim (and, for net, the browser dev host), and fail
    admission cleanly where the module is absent. A device target appends the id
    to its profile when its native host ships the module — not before.
  • A realm declares its tick rate before its first tick. Ui::set_tick_rate
    threads dt through the spring integrators and every ms-to-frame conversion,
    keeping exact integer hz alongside it so frame counts stay integers;
    tools/build.ts --hz bakes the same rate into the bundle, and clock,
    kinetics, input, deepzoom and the styles.bin ANIM TABLE all derive their
    per-tick constants from it. The rate is fixed for the whole run — a
    realm's frame content stays a pure function of its frame index, which is what
    keeps goldens byte-exact.
  • A bundle refuses a host that drives another rate. The host publishes its
    rate as ui.__tickHz and the bundle checks it where it already checks target
    and host ABI. An absent __tickHz means 60, so every host that predates
    per-realm rates keeps mounting every bundle built the ordinary way. Without
    this a 120-baked bundle mounted on a 60-stepped core and ran at half speed
    silently; it now fails at mount with both rates named.
  • Modern iOS runs guests, as a transitional target. pocket ios doctor|build|stage|play builds against an ios-dev plan and launches inside
    a NativeScript shell on an arm64 simulator, over the pocket-apple crate:
    one guest realm, one UI surface, and the software rasterizer driven
    incrementally through a damage tracker behind a small C ABI, with a UIKit
    view compositing only what changed. The profile stays out of
    POCKET_TARGETS
    until it has device-level acceptance, following the same
    convention the iPhone 2G target used. Known limitation: the 120 Hz path
    needs @nativescript/pocketjs 0.2.1, which is not published yet — against
    the current 0.2.0 plugin a 120 Hz bundle refuses to mount (loudly, by the
    rule above) while 60 Hz is unaffected.
  • Hosts choose the guest allocator, so an embedder with its own arena no
    longer has to accept the default one.
  • Site: the landing page leads with a machine collage and per-audience
    /for/ pages, the in-browser playground reuses the landing PSP model, and
    every playground demo is validated and restored on build.

npm: @pocketjs/framework@0.10.0 · @pocketjs/cli@0.10.0 · full changelog

v0.9.3 — The PSP arena no longer strands the memory a QuickJS boot needs

Choose a tag to compare

@github-actions github-actions released this 08 Aug 07:11
c7bd537

The PSP arena no longer strands the memory a QuickJS boot needs.
A guest whose boot parses a megabyte of JSON could exhaust the heap while
megabytes sat free, because the arena's power-of-two size classes never hand a
block to a different class. 0.9.3 closes that, and
Pocket Voxel boots on a real
PSP-2000 at the default arena size again.

  • realloc keeps the pointer when the new size stays inside the block's
    class.
    The arena rounds every request up to a power of two, so a grow that
    stays in class already owns those bytes. QuickJS grows its string and array
    builders geometrically, and the previous allocator answered every one of those
    grows with an allocate, a copy, and a free that put the old block into a class
    nothing asked for again. A boot parsing 1.15 MB of game data stranded
    megabytes this way.
  • arena::alloc splits a larger free block when the bump is spent, halving
    down to the class it needs. It runs last on purpose: a heap with room behaves
    exactly as it did in 0.9.2, and large blocks stay whole for the callers that
    want them.
  • A null exception object is an out-of-memory signature. [PocketJS js error] null followed by JS_Eval threw means QuickJS could not allocate an
    Error to throw, so the guest source is not the suspect. The same halt line
    covers every eval failure, which is what made this one read as a code bug for
    a day.
  • globalThis.audio mounts without the ui surface. register_audio is
    split out of register, so a host that owns its own surface can still offer
    the audio.pcm capability. The credit mirror also decays with the hardware
    stream: poll() never subtracted what write() accepted, so a ring the mixer
    drained completely between two polls sent no credit and the guest went
    permanently silent after a couple of seconds.

Measured on the hardware that found it. The same guest bundle peaks at
12.3 MB under desktop QuickJS and needed more than 15.5 MB on the device
before this release; it now boots inside the 14.3 MB an XMB launch leaves
after a 32 MB pak, with the emulator journey green at 11 of 11 marks and
frame-hash goldens byte-identical at both quality rungs.


npm: @pocketjs/framework@0.9.3 · @pocketjs/cli@0.9.3 · full changelog

v0.9.2 — A locked 60 fps on a 2007 iPhone, because the composite was the only stage that was never damage-limited

Choose a tag to compare

@github-actions github-actions released this 06 Aug 11:26
9aa5eb5

A locked 60 fps on a 2007 iPhone, because the composite was the only stage that was never damage-limited.
PocketJS 0.9.2 makes the software rasterizer scope its screen composite to the
damaged rectangle, which takes the original iPhone from 22–26 fps to 59.99,
and exposes the damage statistics that made the diagnosis possible. The
deep dive has the numbers.

  • The composite now follows the damage plan. The rasterizer was always
    incremental; the composite was not. The tick called setNeedsDisplay on the
    whole view and drawRect: discarded the dirty rectangle UIKit passes, so every
    frame rebuilt a CGImage over all 320×480 — 22–27 ms. An empty plan now
    invalidates nothing (626 of 961 frames in one sample), and a non-empty plan
    goes to setNeedsDisplayInRect: with drawRect: clipping to what it is
    handed. The composite costs 0.26 ms, and the frame 7.63 ms of a
    16.67 ms budget. No preservation guarantee is relied on: when UIKit discards
    the backing store it passes full bounds and the full frame is drawn.
  • Damage is observable. engine/symbian was discarding the DamagePlan the
    incremental rasterizer returns. Six new C ABI accessors expose attempts,
    failures, policy-chosen full redraws, region count, pixel area and union
    bounds, and four of them ride in the device record. damage_failures is the
    one that matters:
    planning that errors silently draws a complete frame, and
    without a counter that is indistinguishable from a slow machine. A
    composites counter sits beside it, because a scoped invalidation that never
    fires looks exactly like a very fast one.
  • The software rasterizer is now the default on this target, and the OpenGL
    ES 1.1 backend is opt-in. The GL path is correct and pixel-verified but costs
    17.2–19.7 ms and delivers 48.6–50.7 fps, because it re-submits and re-fills
    the entire DrawList every frame. This supersedes rather than corrects
    0.9.1:
    the GPU path really was faster than the CPU path as that code stood;
    the CPU path then got an optimization the GPU path still lacks.
  • Both paths can be captured and diffed. The capture works on the software
    path too, which is the test that matters for a damage-limited rasterizer —
    the framebuffer persists and only damaged spans are rewritten, so
    under-reported damage would accumulate as staleness. After 2,581 frames:
    mean absolute channel difference 0.039 of 255, with the only residue inside
    the animating spinner's own 40×40 box. Note the two captures disagree about
    format — glReadPixels is R,G,B,A bottom-up, the core's ARGB32 words are
    B,G,R,A top-down — and comparing the software one unswapped reports a
    convincing 9.3/255 failure that is entirely in the comparison.

npm: @pocketjs/framework@0.9.2 · @pocketjs/cli@0.9.2 · full changelog

v0.9.1 — The GPU path on the original iPhone was never losing; three stacked measurement bugs said it was

Choose a tag to compare

@github-actions github-actions released this 06 Aug 10:41
41a8f87

The GPU path on the original iPhone was never losing; three stacked measurement bugs said it was.
PocketJS 0.9.1 corrects the central performance claim of 0.9.0, fixes the two
real defects that produced it, and adds the instrument that settled it — the
device's own framebuffer, read back and diffed against the reference
rasterizer. The rewritten deep
dive
tells it in order.

  • Correction to 0.9.0. That release reported the OpenGL ES 1.1 path as
    2.4× slower than the software rasterizer on the original iPhone. It is
    1.8–2× faster: 46.7–49.4 fps against 21.9–26.5, and 19.4–20.5 ms per
    frame against 33.9–40.8. The old comparison timed GL's rasterize and
    present against software's rasterize only, because the software
    composite runs in drawRect: later in the run loop.
  • Fixed: the software fallback never composited. +layerClass returned
    CAEAGLLayer unconditionally, and a GL-backed layer never receives
    drawRect:. The documented fallback — the one the host drops to whenever GL
    fails — computed frames that could not reach the screen. The layer class now
    agrees with the selected renderer.
  • Fixed: the GPU drew colour blocks. In OpenGL ES 1.1 texturing is a
    per-unit enable, and glEnable(GL_TEXTURE_2D) was missing, so every fragment
    took only its vertex colour: flat fills looked right while all text, images
    and font-atlas content silently vanished. ES 2 has no equivalent, which is
    exactly why deriving the ES 1 pipeline from the ES 2 one hid it. Also states
    GL_MODULATE, glShadeModel(GL_SMOOTH) and an identity texture matrix, with
    a test pinning all four.
  • Pixel parity, off the device. A one-shot glReadPixels capture writes the
    phone's framebuffer to a file the host pulls over USB. Against the same guest
    rendered by the reference core: mean absolute channel difference 0.04 of
    255
    , no channel off by more than 32, worst single channel 7 — the residue
    being antialiased glyph edges. First PocketJS host verified by reading pixels
    back off physical hardware.
  • A frame rate you can trust. The device now reports window_frames and
    window_us, so the rate is computed from exact on-device counters instead of
    differencing two status records with one-second timestamps — the ±4 fps of
    slop that let the original discrepancy hide.

npm: @pocketjs/framework@0.9.1 · @pocketjs/cli@0.9.1 · full changelog