Skip to content

feat(stdlib): PixiJS binding restart (bindings #1) - #429

Merged
hyperpolymath merged 1 commit into
mainfrom
feat/pixijs-restart-deno-esm
May 28, 2026
Merged

feat(stdlib): PixiJS binding restart (bindings #1)#429
hyperpolymath merged 1 commit into
mainfrom
feat/pixijs-restart-deno-esm

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Restarts bindings #1 (PixiJS core) on the Deno-ESM pattern. The prior affinescript-pixijs/ scaffold was broken across three axes (old .as extension, AGPL-3.0-or-later headers, Zig→C→WASM-import architecture incompatible with the Deno-ESM emitter).

What this PR does

  • Deletes affinescript-pixijs/ (4 broken files)
  • Adds stdlib/Pixi.affine — 7 opaque types + 25 extern fns covering Application init / Container hierarchy / Sprite+Texture / Graphics path+fill+clear / Text mutation / Ticker
  • Adds 26 __as_pixi* helpers + lowering entries in lib/codegen_deno.ml (consumer-provided globalThis.__as_pixi = PIXI)
  • Adds test fixture tests/codegen-deno/pixi_smoke.{affine,harness.mjs} — 11 assertions covering async init + sprite flow + graphics flow
  • Updates docs/bindings-roadmap.adoc row ci: Bump actions/setup-node from 4.0.2 to 6.3.0 #1 status scaffold → partial

Best-judgement call: restart not revive

The scaffold was unsalvageable. Restarting on the proven wasmCall/motion pattern was faster than triple-rebasing.

Test plan

  • codegen-deno suite: 8/8 harnesses green (was 7/7; +pixi_smoke)
  • dune build bin/main.exe clean
  • All new files carry SPDX MPL-2.0 headers
  • No .as files added; no AGPL / PMPL headers anywhere

🤖 Generated with Claude Code

…raphics/Text/Texture/Ticker (bindings #1)

Restarts bindings #1 (PixiJS core) on the Deno-ESM pattern proven by
wasmCall + motion. The prior `affinescript-pixijs/` scaffold was
broken across three axes that compounded into an unmaintainable state:

1. *Extension*: `src/pixi.as` used the obsolete `.as` extension (no
   longer accepted by the current AffineScript compiler — files must
   be `.affine`).
2. *License*: SPDX headers carried AGPL-3.0-or-later in three files
   (Pixi.idr, main.zig, package.json), inconsistent with the
   estate-wide MPL-2.0 stance documented in `standards/CLAUDE.md`.
3. *Architecture*: the scaffold targeted a Zig→C→WASM-import pattern
   (`extern fn js_pixi_init` + `export fn as_pixi_init`) that conflicts
   with how the Deno-ESM emitter actually lowers extern fns. The
   wasmCall (PR #422) and motion (PR #422 bundle) bindings established
   that `extern fn`s lower directly to JS host calls via
   `lib/codegen_deno.ml`'s `deno_builtins` lowering table — no Zig
   intermediary required.

Restart approach (best-judgement call per the user's directive):

- Delete `affinescript-pixijs/` entirely (4 files: pixi.as, Pixi.idr,
  main.zig, package.json).
- Add `stdlib/Pixi.affine` with the MVP surface: 7 opaque types
  (Application, Container, Sprite, Graphics, Text, Texture, Ticker)
  + 25 extern fns covering Application init, Container hierarchy,
  Sprite+Texture, Graphics path+fill+clear, Text mutation, Ticker
  start/stop/add.
- Add 26 `__as_pixi*` runtime helpers + lowering-table entries in
  `lib/codegen_deno.ml`. Consumer sets `globalThis.__as_pixi = PIXI`
  at module-init (mirrors the motion `__as_motion` pattern).
- Add `tests/codegen-deno/pixi_smoke.{affine,harness.mjs}` — 11
  assertions covering async init, sprite flow (texture → sprite →
  upcast → addChild → position → visibility), and graphics flow
  (new → rect → fill → upcast → addChild).
- Update `docs/bindings-roadmap.adoc` row #1: status `◐` scaffold →
  `◑` partial; package home now `stdlib/Pixi.affine`; rationale
  notes the restart + follow-ups (Container accessors, FederatedEvent,
  Point/Rectangle/Circle).

PixiJS 8.x class-hierarchy note: Sprite, Graphics, and Text are real
Container subclasses. AffineScript has no subtype polymorphism, so
the binding exposes explicit upcasts (`pixiSpriteAsContainer`,
`pixiGraphicsAsContainer`, `pixiTextAsContainer`). These are
zero-cost identity lowerings — the underlying JS object is the same.

Test plan:

- [x] codegen-deno suite: 8/8 harnesses green (was 7/7; +pixi_smoke)
- [x] `dune build bin/main.exe` clean
- [x] All new files carry SPDX `MPL-2.0` headers
- [x] No `.as` files added; no AGPL / PMPL headers anywhere

Out of scope (deferred):

- Full PixiJS 8.x accessor surface (anchor, scale, pivot, parent,
  zIndex, eventMode, filters, hitArea, worldVisible, etc.) — listed
  in row #1's follow-ups.
- FederatedEvent + on/off pointer-event subscription surface.
- Point / Rectangle / Circle helper types.
- Sprite atlases and texture-pack support.
- Moving from `stdlib/` to a separate `affinescript-pixijs` repo per
  the SNIFs / typed-wasm precedent (additive, source-compatible).

Companion estate sweep: a follow-up PR set will rename `.as` →
`.affine` across the rest of the estate (session-sentinel,
git-reticulator, candy-crash, developer-ecosystem, burble) and
upgrade their per-file SPDX headers to MPL-2.0 where the existing
license is AGPL / PMPL — not bundled here so this PR stays scoped
to the affinescript repo's pixijs revival.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 81 issues detected

Severity Count
🔴 Critical 4
🟠 High 10
🟡 Medium 67

⚠️ Action Required: Critical security issues found!

View findings
[
  {
    "reason": "Action actions/checkout@v6 needs attention",
    "type": "unpinned_action",
    "file": "publish-jsr.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Action denoland/setup-deno@v2 needs attention",
    "type": "unpinned_action",
    "file": "publish-jsr.yml",
    "action": "pin_sha",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in affine-vscode-publish.yml",
    "type": "unknown",
    "file": "affine-vscode-publish.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in casket-pages.yml",
    "type": "unknown",
    "file": "casket-pages.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in casket-pages.yml",
    "type": "unknown",
    "file": "casket-pages.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "unknown",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "unknown",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "unknown",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "unknown",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  },
  {
    "reason": "Issue in ci.yml",
    "type": "unknown",
    "file": "ci.yml",
    "action": "flag",
    "rule_module": "workflow_audit",
    "severity": "medium"
  }
]

Powered by Hypatia Neurosymbolic CI/CD Intelligence

@hyperpolymath
hyperpolymath merged commit 51a73b8 into main May 28, 2026
25 of 26 checks passed
@hyperpolymath
hyperpolymath deleted the feat/pixijs-restart-deno-esm branch May 28, 2026 13:14
hyperpolymath added a commit that referenced this pull request May 28, 2026
Pure rename of the Vite-plugin example file from `.as` → `.affine`
(current AffineScript extension). Part of the estate-wide sweep
companion to #429.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit to hyperpolymath/developer-ecosystem that referenced this pull request May 28, 2026
Pure rename of 5 AffineScript example files `.as` → `.affine`. Companion
to hyperpolymath/affinescript#429.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit to hyperpolymath/session-sentinel that referenced this pull request May 28, 2026
…t ext fix) (#23)

The `.as` extension is the obsolete pre-rename AffineScript file
extension; the current compiler accepts `.affine` only. This commit
renames the 7 files under `src/core/` accordingly. Pure rename — no
content changes; SPDX headers already MPL-2.0.

Part of the estate-wide .as → .affine sweep companion to
hyperpolymath/affinescript#429 (PixiJS binding restart).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit to hyperpolymath/git-reticulator that referenced this pull request May 28, 2026
The `.as` extension is the obsolete pre-rename AffineScript file
extension; the current compiler accepts `.affine` only. Renames the
3 lattice sources + 1 test file accordingly, plus adds MPL-2.0
SPDX headers (matching the repo's existing LICENSE).

Part of the estate-wide .as → .affine sweep companion to
hyperpolymath/affinescript#429.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit to hyperpolymath/candy-crash that referenced this pull request May 28, 2026
Pure rename of frontend/src/{Main,Safety}.as → .affine to match
the current AffineScript extension. MIT SPDX preserved (per repo
LICENSE; estate MPL-2.0 directive applies to AGPL→MPL-2.0
migrations, not MIT).

Companion to hyperpolymath/affinescript#429.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request May 28, 2026
Adds an MVP @pixi/ui surface for idaptik's HUD + menu layer
(`src/bindings/PixiUI.res`), following the Deno-ESM pattern proven by
wasmCall (#422) / motion (#422 bundle) / Pixi (#429 / open).

Coverage in this version (row #3 status `○` -> `◐` scaffold):

- 5 opaque host types: `Button`, `FancyButton`, `Slider`, `Switch`,
  `Container` (the last re-declared opaque so this module can be
  consumed without a hard dependency on `stdlib/Pixi.affine`; the JS
  values coincide at runtime because @pixi/ui's components are real
  PIXI.Container subclasses).
- 11 extern fns: `new`-style constructor + primary event-callback
  registrar + zero-cost `AsContainer` upcast for each component
  (Input + ScrollBox deferred to follow-up — see row #3).
- 11 `__as_pixiUi*` runtime helpers + lowering-table entries in
  `lib/codegen_deno.ml`. Consumer sets `globalThis.__as_pixi_ui =
  PixiUI` at module-init (mirrors the motion `__as_motion` pattern
  and the prospective Pixi `__as_pixi` pattern).
- `tests/codegen-deno/pixiui_smoke.{affine,harness.mjs}` — 17
  assertions covering ctor-options round-trip, callback-identity
  preservation through `.connect()`, and identity upcast for all
  four components.
- `docs/bindings-roadmap.adoc` row #3 updated: status, package home
  set to `stdlib/PixiUI.affine`, deferred follow-ups enumerated.

Test plan:

- [x] codegen-deno suite: 9/9 harnesses green (was 8/8; +pixiui_smoke)
- [x] `dune build bin/main.exe` clean
- [x] All new files carry SPDX `MPL-2.0` headers
- [x] No `.as` files added; no AGPL / PMPL headers anywhere

Out of scope (deferred):

- `Input` (text-entry, focus, blur, value accessor)
- `ScrollBox` (scroll position, content add/remove, viewport)
- Full event surface (onHover / onOut / onDown / onUp beyond the one
  primary callback per component)
- FancyButton textures-per-state accessors
- Slider min/max/step accessors
- Migration from `stdlib/` to a separate `affinescript-pixijs`
  sub-module per the eventual Pixi #1 split (additive,
  source-compatible).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request May 28, 2026
## Summary

Adds an MVP `@pixi/ui` binding (`stdlib/PixiUI.affine` + Deno-ESM
codegen lowerings) so idaptik's HUD + menu layer
(`src/bindings/PixiUI.res`) can move off ReScript. Follows the pattern
proven by wasmCall (#422) / motion (#422 bundle) / Pixi (#429 open).

Row #3 in `docs/bindings-roadmap.adoc` moves `○` -> `◐` scaffold.

## Surface

- 5 opaque host types: `Button`, `FancyButton`, `Slider`, `Switch`,
`Container` (re-declared opaque so this module can be consumed without a
hard dependency on `stdlib/Pixi.affine`).
- 11 extern fns: ctor + primary event-callback registrar + zero-cost
`AsContainer` upcast for each component.
- 11 `__as_pixiUi*` runtime helpers + `deno_builtins` table entries in
`lib/codegen_deno.ml`.
- Consumer sets `globalThis.__as_pixi_ui = PixiUI` once at module-init.

## Deferred (follow-ups)

- `Input` (text-entry + focus + value)
- `ScrollBox` (scroll position + viewport)
- Full event surface (onHover / onOut / onDown / onUp)
- FancyButton textures-per-state, Slider min/max/step accessors

## Test plan

- [x] `dune build bin/main.exe` clean
- [x] `bash tools/run_codegen_deno_tests.sh` — 9/9 harnesses green (was
8/8; +pixiui_smoke with 17 assertions)
- [x] All new files MPL-2.0 SPDX; no `.as` / AGPL / PMPL
- [ ] Hypatia security scan: no new findings (delta-only — pre-existing
baselines ignored per repo CLAUDE.md)

Note: pre-existing flaky E2E Node-CJS Codegen tests #4/#5 unrelated.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath added a commit that referenced this pull request May 31, 2026
…ngs #1) (#502)

## Summary

Extends the Tier-1 PixiJS binding (#446 row #1) with the 11
most-load-bearing accessors + on/off pointer-event registration. This is
the **largest single chunk** of idaptik's `src/bindings/Pixi.res`
surface still not bound — 215 `src/app/*.res` files depend on Container
transforms and FederatedPointerEvent handlers, so this PR is a forward
unblocker for the ReScript→AffineScript migration.

## What lands

`stdlib/Pixi.affine` (+46 lines): 11 new `extern fn`s.

| Surface | Externs |
|---|---|
| Container transforms | `pixiContainerSetScale`, `SetPivot`,
`SetRotation`, `SetAlpha`, `SetZIndex`, `SetSortableChildren`,
`SetEventMode`, `SetCursor` |
| FederatedPointerEvent registration | `pixiContainerOn`,
`pixiContainerOff` |
| Sprite | `pixiSpriteSetAnchor` |

`lib/codegen_deno.ml` (+22 lines): 11 `__as_*` prelude helpers + 11
entries in the existing `deno_builtins` dispatch block, matching the
existing wasmCall/motion/pixi pattern.

`tests/codegen-deno/pixi_smoke.{affine,harness.mjs}` (+80 lines
combined): new `smokeAccessorsFlow` exercises every new extern via the
existing harness pattern. `MockContainer` grows `scale`/`pivot` Point
mocks + handler `Map` + the new fields; asserts handler identity is
preserved across `on(...)` → `off(...)`.

`docs/bindings-roadmap.adoc` row #1 status note expanded — Container 8.x
transform-and-event surface promoted from "deferred" to "landed";
remaining deferred items (typed `FederatedPointerEvent` accessors,
`parent` read accessor with Option-null handling, Point/Rectangle/Circle
helper types, sprite atlases, filters, hitArea) listed explicitly.

## Design notes

**Why `pub extern fn pixiContainerSetEventMode(c, mode: String)` rather
than a sum type?** Pixi 8's `eventMode` values are open strings
(`"static"` / `"dynamic"` / `"passive"` / `"none"` / `"auto"`). A sum
type would either freeze the set or require codegen-tagged-variant
lowering that doesn't yet exist on the Deno-ESM backend (deferred to
json.affine v0.3, mirroring the `WasmValue` decision in #467). Matches
the existing pattern in `stdlib/PixiUI.affine` for `slider.orientation`.

**Why `handler: Json`?** The `FederatedPointerEvent` reaches the handler
as a JS object; AffineScript-side code uses existing `Json` accessors to
read `e.global.x`, `e.target`, etc. A typed `FederatedPointerEvent`
extern type with dedicated accessor `extern fn`s is the natural
follow-up — captured in the roadmap row as a deferred item, not in this
PR's scope. The Json handler avoids forcing every caller through a typed
surface they may not want.

**Anchor is on Sprite, not Container.** Pixi 8 keeps the same split as
7.x — `Container` has no `anchor`. The binding mirrors that with
`pixiSpriteSetAnchor` rather than putting it on
`pixiContainerSetAnchor`.

## Test plan

- [x] `dune build bin/main.exe` — clean (only the expected parser
warnings)
- [x] `dune runtest` — 354 tests pass
- [x] `tools/run_codegen_deno_tests.sh` — all 17 harnesses including
extended `pixi_smoke.harness.mjs` OK
- [ ] CI build job
- [ ] CI `tools/run_codegen_deno_tests.sh` job
- [ ] CI governance + Hypatia (known baselines per repo CLAUDE.md may be
red — those are not from this PR)

## Refs

- Umbrella: #446 (Tier 1 — idaptik blockers)
- Tier-1 sub-issue: #450
- Row updated: `docs/bindings-roadmap.adoc` row #1
- Prior PixiJS-related PRs for context: #429 (restart on Deno-ESM), #435
(@pixi/ui MVP), #436 (motion ●), #437 (@pixi/sound)
- Compile-time pattern doc: `docs/specs/zig-ffi-patterns.adoc` (PR #474
— non-conflicting siblings)

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

1 participant