feat(js): export module/namespace consts and enums - #73
Merged
Conversation
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).
spiral-ladder
previously approved these changes
Aug 17, 2026
- `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>
Contributor
|
Checked with my codex, these two edge cases seems not works correct.
pub const @"__proto__" = enum(u8) {
inherited = 7,
};
pub const SpecialTags = enum(u8) {
@"__proto__" = 1,
normal = 2,
}; |
Contributor
Author
@GrapeBaBa These seems very narrow edge cases, can we open an issue for it and proceed with this PR as it is? |
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
previously approved these changes
Aug 18, 2026
GrapeBaBa
reviewed
Aug 18, 2026
| } | ||
| } | ||
| } else if (@typeInfo(InnerType) == .@"enum") { | ||
| // Enum → frozen plain object mapping tag name (verbatim) to |
Contributor
There was a problem hiding this comment.
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
nazarhussain
dismissed stale reviews from GrapeBaBa and spiral-ladder
via
August 18, 2026 15:31
6490283
spiral-ladder
approved these changes
Aug 18, 2026
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
While porting
@chainsafe/swap-or-not-shuffleinto lodestar-z (ChainSafe/lodestar-z#559), scalarpub constdecls and enums inside exported modules were silently skipped byjs.exportModule's reflection — the binding had to assign constants likeSHUFFLE_ROUNDS_MAINNETandByteCounton the JS side. Classes already auto-export such consts as statics (applyStaticFields); this extends the same behavior to namespaces and the module root.Changes
pub constdecls (int, float, bool,[]const u8, string literals) export as enumerable value properties at the module root and inside namespaces, reusingwrap_class.isStaticValueType/createStaticFieldValue(nowpub). A namespace containing only consts now exports too.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.TypedArray.fromExternaldoc now states it copies (pointing atOwnedTypedArray.fromOwnedSlice/intoValuefor ownership transfer) and warns it panics outside DSL callbacks. New README "Constants and Enums" section.Decisions
setNamedProperty), matching namespace function properties. Verified class statics are also enumerable, so the two paths are consistent..registerhook 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.jsconstant assignments and declares the consts/enum inbindings/napi/shuffle.zig(guarded by its "should expose the reference constants" test).🤖 Generated with Claude Code