Skip to content

feat(js): export module/namespace consts and enums - #73

Open
nazarhussain wants to merge 3 commits into
mainfrom
nh/feat-pub-const
Open

feat(js): export module/namespace consts and enums#73
nazarhussain wants to merge 3 commits into
mainfrom
nh/feat-pub-const

Conversation

@nazarhussain

Copy link
Copy Markdown
Contributor

Motivation

While porting @chainsafe/swap-or-not-shuffle into lodestar-z (ChainSafe/lodestar-z#559), scalar pub const decls and enums inside exported modules were silently skipped by js.exportModule's reflection — the binding had to assign constants like SHUFFLE_ROUNDS_MAINNET and ByteCount on the JS side. Classes already auto-export such consts as statics (applyStaticFields); this extends the same behavior to namespaces and the module root.

Changes

  • Const export: scalar/string pub const decls (int, float, bool, []const u8, string literals) export as enumerable value properties at the module root and inside namespaces, reusing wrap_class.isStaticValueType/createStaticFieldValue (now pub). A namespace containing only consts now exports too.
  • Enum export: pub const X = enum {...} exports as a frozen plain object mapping each tag name (verbatim, no case conversion) to its integer value, mirroring napi-rs #[napi] pub enum. Signed tag values preserved.
  • Docs: TypedArray.fromExternal doc now states it copies (pointing at OwnedTypedArray.fromOwnedSlice/intoValue for ownership transfer) and warns it panics outside DSL callbacks. New README "Constants and Enums" section.

Decisions

  • Consts are enumerable (setNamedProperty), matching namespace function properties. Verified class statics are also enumerable, so the two paths are consistent.
  • Enum objects are frozen — safer semantics for constants; napi-rs leaves them mutable.
  • Other const shapes (struct values, arrays) remain skipped; the .register hook stays the escape hatch.

Testing

10 new vitest cases in examples/js_dsl (root/namespace consts, const-only namespace, enumerability, verbatim enum tags, signed values, frozen-object semantics), written first and watched fail. Full suite: zig build test:zapi + 130 vitest tests green.

Consumer cleanup

Once released, lodestar-z deletes its bindings.js constant assignments and declares the consts/enum in bindings/napi/shuffle.zig (guarded by its "should expose the reference constants" test).

🤖 Generated with Claude Code

Scalar/string `pub const` decls were silently skipped by exportModule's
reflection; only class statics exported. Export them as enumerable
properties at the module root and inside namespaces, and export
`pub const` enums as frozen plain objects with verbatim tag names,
mirroring napi-rs.

Needed by lodestar-z's swap-or-not-shuffle binding to drop its JS-side
constant assignments.

Also document that TypedArray.fromExternal copies and panics outside
DSL callbacks (use owned typed arrays for ownership transfer).
@nazarhussain nazarhussain changed the title feat: export module/namespace consts and enums feat(js): export module/namespace consts and enums Aug 17, 2026
spiral-ladder
spiral-ladder previously approved these changes Aug 17, 2026
Comment thread src/js/typed_arrays.zig Outdated
- `pub var` decls are never exported: the value would be a stale
  registration-time snapshot, and inside a DSL class the comptime
  `@field` read in analyzeClass broke compilation outright
  (pre-existing on main)
- class-level enums export as frozen objects, matching namespaces
- integer consts and enum tags outside i64 range now fail with a
  compile error naming the decl instead of a cryptic `@intCast`
  failure
- pin skipped shapes (arrays, struct values) with tests
Co-authored-by: bing <spiralladder@fastmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants