Skip to content

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

Merged
nazarhussain merged 4 commits into
mainfrom
nh/feat-pub-const
Aug 18, 2026
Merged

feat(js): export module/namespace consts and enums#73
nazarhussain merged 4 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>
@GrapeBaBa

Copy link
Copy Markdown
Contributor

Checked with my codex, these two edge cases seems not works correct.

  • module exports name like that
  pub const @"__proto__" = enum(u8) {
      inherited = 7,
  };
  • property name like that
  pub const SpecialTags = enum(u8) {
      @"__proto__" = 1,
      normal = 2,
  };

@nazarhussain

Copy link
Copy Markdown
Contributor Author

Checked with my codex, these two edge cases seems not works correct.

  • module exports name like that
  pub const @"__proto__" = enum(u8) {
      inherited = 7,
  };
  • property name like that
  pub const SpecialTags = enum(u8) {
      @"__proto__" = 1,
      normal = 2,
  };

@GrapeBaBa These seems very narrow edge cases, can we open an issue for it and proceed with this PR as it is?

@spiral-ladder

Copy link
Copy Markdown
Member

+1 that it's a very narrow edge case, can only be encountered according to the consumer's usage patterns, in which case i dont think we do?

spiral-ladder
spiral-ladder previously approved these changes Aug 18, 2026
Comment thread src/js/export_module.zig Outdated
}
}
} else if (@typeInfo(InnerType) == .@"enum") {
// Enum → frozen plain object mapping tag name (verbatim) to

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: which Nico found in my PR before, the arrow which AI used is a bit wired, suggest to use some alternatives which could input using keyboard

GrapeBaBa
GrapeBaBa previously approved these changes Aug 18, 2026

@GrapeBaBa GrapeBaBa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good

@nazarhussain
nazarhussain dismissed stale reviews from GrapeBaBa and spiral-ladder via 6490283 August 18, 2026 15:31
@nazarhussain
nazarhussain merged commit 76dc0db into main Aug 18, 2026
5 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Lodestar Team Coordination Aug 18, 2026
@nazarhussain
nazarhussain deleted the nh/feat-pub-const branch August 18, 2026 15:34
nazarhussain pushed a commit that referenced this pull request Aug 18, 2026
🤖 I have created a release *beep* *boop*
---


##
[4.0.0](zapi-v3.1.0...zapi-v4.0.0)
(2026-08-18)


### ⚠ BREAKING CHANGES

* isolate DSL class tags across addons
([#67](#67))
* manage external buffer lifetime
([#66](#66))
* require writable external buffer storage
([#58](#58))

### Features

* add owned typed arrays
([#68](#68))
([b92c2de](b92c2de))
* **js:** add exact u32 conversion
([#71](#71))
([d6b21e1](d6b21e1))
* **js:** add typed array toArray
([#70](#70))
([ab42ab0](ab42ab0))
* **js:** export module/namespace consts and enums
([#73](#73))
([76dc0db](76dc0db))


### Bug Fixes

* **dsl:** support class pointer arguments
([#50](#50))
([9dd2111](9dd2111))
* harden N-API boundary against JS-triggerable memory bugs
([#60](#60))
([fff76f3](fff76f3))
* isolate DSL class tags across addons
([#67](#67))
([3ab8c11](3ab8c11))
* manage external buffer lifetime
([#66](#66))
([d134a6a](d134a6a))
* **napi:** receive raw pointer out parameters
([#57](#57))
([fde4a9a](fde4a9a))
* remove redundant platform check from musl detection
([#64](#64))
([0d4829c](0d4829c))
* require writable external buffer storage
([#58](#58))
([8fd898f](8fd898f))
* restore registerDecls on Zig 0.16
([#59](#59))
([7f3af3e](7f3af3e))


### Code Refactoring

* **js:** unify env lifecycle refcounting
([#53](#53))
([d3d5056](d3d5056))


### Miscellaneous Chores

* define changelog sections for release-please
([#54](#54))
([1c5e7b4](1c5e7b4))
* update dev deps ([#74](#74))
([5121590](5121590))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
nazarhussain added a commit to ChainSafe/lodestar-z that referenced this pull request Aug 19, 2026
zapi 4.0.0 (ChainSafe/zapi#73) auto-exports namespace-level consts and
enums, so SHUFFLE_ROUNDS_MAINNET/MINIMAL and ByteCount move next to the
functions that use them and the JS loader shim in bindings.js is gone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants