Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
32125e3
Merge pull request #29 from BuddhiLW/staging
BuddhiLW Oct 13, 2026
afd81f6
test(class): defmethod dispatch on the five inspect* seq class symbol…
BuddhiLW Oct 14, 2026
f60306a
fix(vm): raise interop, set! and ctor errors at their form, and check…
BuddhiLW Oct 14, 2026
75d98e3
style(diff): drop em-dashes from the error-location oracle comments
BuddhiLW Oct 14, 2026
012f8ee
fix(runtime): a user class is matched by descriptor identity, never b…
BuddhiLW Oct 14, 2026
ea75de7
fix(analyzer): a bare constructor binds the class of the namespace it…
BuddhiLW Oct 14, 2026
f15ad17
docs(debt): discharge D-587 (ADR-0198, ADR-0201)
BuddhiLW Oct 14, 2026
89fa224
Merge land/class-dispatch-test into land/round7
BuddhiLW Oct 15, 2026
18f4834
Merge land/td-uaf into land/round7
BuddhiLW Oct 15, 2026
e9891f6
Merge land/error-loc into land/round7
BuddhiLW Oct 15, 2026
39f70b9
docs(changelog): record round 7 (type redefinition and identity, VM e…
BuddhiLW Oct 15, 2026
5dadcd1
feat(wasm): wasm/exports lists a core module's exports (ADR-0203)
BuddhiLW Oct 21, 2026
d4c0363
feat(wasm): dot-interop on a core module handle is wasm/call (ADR-0203)
BuddhiLW Oct 21, 2026
0773523
Merge branch 'feat/wasm-dot-interop' into feat/wasm-exports
BuddhiLW Oct 21, 2026
8239bc2
test(wasm): move the ADR-0203 tests into in-process suites
BuddhiLW Oct 21, 2026
7dc4fd1
docs(readme): apply the agora d666cca9 review
BuddhiLW Oct 21, 2026
e5351bf
Merge main (v1.15.0 release merge) back into staging
BuddhiLW Oct 21, 2026
f74d548
Merge remote-tracking branch 'origin/staging' into land/round7
BuddhiLW Oct 21, 2026
0882649
docs(readme): a shorter README led by C-to-Clojure and the graphs
BuddhiLW Oct 21, 2026
6b7f50d
fix(wasm): wasm/exports builds its result inside a fabrication bracket
BuddhiLW Oct 21, 2026
fd388b2
chore(deps): pin zwasm to fork main d74e63b4 (upstream main, 2026-10-21)
BuddhiLW Oct 21, 2026
49e23bf
Merge remote-tracking branch 'origin/staging' into chore/zwasm-main
BuddhiLW Oct 21, 2026
cfa6270
docs: BuddhiLW logo in the README header, changelog for the next release
BuddhiLW Oct 21, 2026
65bb395
Merge remote-tracking branch 'origin/staging' into land/round7
BuddhiLW Oct 21, 2026
e87aba6
docs(readme): use the plain BuddhiLW mark, without the PGB lettering
BuddhiLW Oct 21, 2026
1bcca2a
Merge pull request #60 from BuddhiLW/land/round7
BuddhiLW Oct 21, 2026
99a028b
Merge pull request #67 from BuddhiLW/staging
BuddhiLW Oct 21, 2026
9adabd2
chore(release): v1.15.1
Oct 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 11 additions & 44 deletions .dev/debt.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,50 +24,6 @@
# md-table-align no longer pads it to ~800 KB of whitespace.

active:
- id: "D-587"
status: |-
open (2026-09-09). USE-AFTER-FREE, user-reachable panic. Re-registering a
deftype/defrecord name frees a TypeDescriptor that live instances still
point at. `type_descriptor.zig registerType` keys `rt.types` by the SIMPLE
name, and on re-registration does `fetchRemove(name)` then frees the old
descriptor (each field_layout entry name, the layout slice, fqcn,
defining_ns, method_table entries, protocol_impls, then
`gpa.destroy(old.value)`). Every constructed instance holds
`inst.descriptor` as a raw pointer to it, so `print.zig
printTypedInstance` then reads `field_layout` out of freed memory: the
symptom is `thread panic: integer overflow` (a garbage field index or
layout length), the defect is the free.
Repro (ReleaseSafe v1.14.3): `(ns aaa) (defrecord Point [x y]) (def a
(->Point 1 2)) (ns bbb) (defrecord Point [x y]) (def b (->Point 1 2))
(prn (pr-str aaa/a))` panics; printing `bbb/b` is fine. Variants: two ns
with DIFFERENT names is fine; two ns SAME name panics; SAME ns redefining
the same name panics (this is the ordinary REPL / `require :reload` path
`dev/user.clj` depends on); same name with a different field count panics;
the deftype form raises `WriteFailed` instead, same root.
TWO separable defects: (1) the registry is keyed by simple name, so
`aaa/Point` and `bbb/Point` collide with no redefinition at all (clj gives
each ns its own class); (2) re-registration frees a descriptor live
instances reference.
ADR-0019 forbids a panic on a user-reachable path, and this one is reached
by re-evaluating a defrecord form. It also caps the native-suite migration:
`test/clj/suites/` shares ONE image, so no two suites may define the same
type name (worked around 2026-09-09 by renaming defrecord_test's record to
DPoint; 45 type definitions across 103 suites, no other duplicate today).
Found while migrating phase7_defrecord.sh to a native suite.
Card `[CLJW-TD-UAF]` 20260909211032-6471bc49.
category: "correctness"
quality_floor: "correctness: a user-reachable panic from an ordinary redefine"
barrier: |-
Needs an ADR: the free is deliberate (comments cite row 7.7 cycle 5 and
D-190 / ADR-0068) and exists to avoid leaking on redefine, so removing it
trades the leak back. Candidate shapes: key `rt.types` by the qualified
name when `defining_ns` is present and RETIRE rather than free a replaced
descriptor (a leak bounded by redefinition count, which is what clj does
with the old class), or make descriptors GC-managed so a descriptor dies
only when no instance references it. Devil's-advocate fork is mandatory at
this depth. Not blocked on anything external: the repro is one file and the
owning function is ~70 lines.
last_reviewed: "2026-09-09"
- id: "D-586"
status: |-
open (2026-09-05, ADR-0195 trigger). UPSTREAM: zwasm/D-584. zwasm's JIT
Expand Down Expand Up @@ -7583,6 +7539,17 @@ discharged:
refs: |-
src/runtime/collection/literal.zig (the one literal construction); src/eval/analyzer/analyzer.zig (the constant fold); src/eval/backend/vm/compiler.zig and vm.zig (the extend opcodes); docs/spec/formats/chunk-v12.edn (bytecode format v12).
discharged_at: "2026-10-02"
- id: "D-587"
status: |-
DISCHARGED 2026-10-14 by ADR-0198 plus ADR-0201. Both defects the row named are fixed. (1) rt.types is keyed by <defining_ns>.<Name>, so aaa.Point and bbb.Point are two classes (ADR-0198), and a bare constructor binds the class of the namespace its form was analyzed in ([CLJW-CTOR-ANALYZE-TIME]: a ctor site carries definer_ns, bytecode v13), so `aaa/->Point` builds aaa.Point even after bbb registered a namesake. (2) A displaced descriptor is retired, never freed, until Runtime.deinit (ADR-0198; ADR-0201 Part B makes that the one lifetime rule for every user descriptor). ADR-0201 also made membership descriptor identity: instance?, .isInstance, isa? and multimethod dispatch agree with (= (class x) C) for a redefined record, a namesake in another namespace and a reify class. The original repro prints both records and the narrowed redefine on both backends.
Was: open (2026-09-09), USE-AFTER-FREE, user-reachable panic. Re-registering a deftype/defrecord name freed a TypeDescriptor that live instances still pointed at, and the registry was keyed by the simple name, so two namespaces defining Point collided with no redefinition at all. Symptom `thread panic: integer overflow` from printTypedInstance, or `WriteFailed` for a deftype.
category: "correctness"
barrier: |-
none, discharged. Pinned by test/clj/suites/type_redefine_test.clj (the six scenarios of the former type_descriptor_redefinition e2e, incl. 3000 redefinitions interleaved with reify under a forced collection and the defining-namespace ctor binding), test/clj/suites/user_class_identity_test.clj, the type_redefinition diff corpus, and the class_name.zig / analyzer.zig unit tests. Still open and separate: rt.types_by_simple still exists for the bare-name paths that are not ctor sites (card 20260909231443-1ba4303c), and D-574 (reify mints a descriptor per evaluation).
last_reviewed: "2026-10-14"
refs: |-
ADR-0198, ADR-0201; src/runtime/type_descriptor.zig (registerType retires), src/runtime/class_name.zig (isInstanceOfClass, classIsaOf, descriptorIsa), src/eval/analyzer/special_forms.zig (constructInstance definer_ns lookup), docs/spec/formats/chunk-v13.edn.
discharged_at: "2026-10-14"
conventions: |-
- Category vocabulary is a closed set (guarded by scripts/check_debt_category.sh; synonyms were normalized 2026-10-08: structural->structure, tests/test->testing, numerics->numeric, performance->perf). Allowed: app backend bench bootstrap build clj-parity concurrency correctness debt-hygiene demo discipline distribution docs docs-onboarding ecosystem error-system eval eval-semantics feature gc governance host-surface infra interop isolation license macro meta-reorg missing-ns namespace numeric perf polymorphism process project-flow reader refactor regex robustness runtime scope security structure testing tooling wasm. A new category is added here first, in the same commit as the row that needs it.
- Structure: two top-level lists — `active:` and `discharged:`. Active entries carry id / status / category / barrier (+ optional quality_floor / last_reviewed); discharged entries carry id / discharged_at / resolution. Edit as YAML (no Markdown table to align).
Expand Down
45 changes: 45 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,51 @@ first stable `1.0.0` tag; pre-1.0 `alpha` / `rc` tags may still change surfaces.

## [Unreleased]

## [1.15.1] - 2026-10-21

### Added

- **`wasm/exports` lists a core module's exports.** `(wasm/exports m)` returns
a vector in export order: a function as `{:name "sum_f64" :kind :func
:params [:i32 :i32] :results [:f64]}`, a memory, global or table as
`{:name "memory" :kind :memory}`. Signatures come from the same runtime probe
`wasm/call` uses (ADR-0203).

- **Dot interop on a Wasm module handle.** `(.sum_f64 m buf 4)`,
`(. m sum_f64 buf 4)` and `(. m (sum_f64 buf 4))` call the export named by
the method symbol, verbatim, through `wasm/call`'s own path, so results,
fuel and errors are identical. A C function compiled to Wasm is called like a
host method (ADR-0203).

### Changed

- **zwasm pinned to the fork's `main` (d74e63b4, upstream main of
2026-10-21).** Upstream now carries the component re-export, wasip2
`metadata-hash` and `PreparedWasi` fixes the fork's `cljw` branch existed
for.

- **A shorter README** led by calling C from Clojure, with the architecture,
size and startup charts kept.

### Fixed

- **Redefining a deftype or defrecord is safe, and a user class is matched by
identity, not by name.** Re-registering a type no longer frees a descriptor
live instances still use (the `thread panic: integer overflow` on printing
an old instance is gone). `aaa.Point` and `bbb.Point` are two classes, and
`instance?`, `.isInstance`, class `isa?` and multimethod dispatch agree with
`(= (class x) C)` for a redefined record, a namesake in another namespace
and a reify class. A bare `(Point. x y)` or `->Point` builds the class of the
namespace the form was written in, even after another namespace registered a
namesake of a different shape. Compiled chunks move to format v13.

- **The VM reports errors at their form.** `set!` on an unbound var, an
unresolved or unsupported `.member` call, a static method call, a
constructor arity failure, `import` and `require`/`refer` failures raised on
the VM with no source position (`0:0`) while TreeWalk reported line and
column. Both backends now report the same position, and the dual-backend
test oracle checks it for every failing case.

## [1.15.0] - 2026-10-13

### Added
Expand Down
Loading
Loading