feat(js): add js.spawn async task DSL - #76
Open
nazarhussain wants to merge 1 commit into
Open
Conversation
Worker-thread async previously meant hand-rolling napi.AsyncWork plus Deferred at every call site, and DSL values were unusable in the completion callback: js.env() panics there because only the sync wrappers establish the thread-local env context. js.spawn takes a comptime duck-typed task (compute/resolve/deinit, with optional errorMessage/reject) and returns a Promise that settles on the JS thread. Its completion callback sets the DSL env context, so resolve can return DSL types, and composes with OwnedTypedArray to hand results to JS without copying. compute deliberately does NOT get the env context — napi calls are illegal on the worker thread, so a panic there is the guard rail. Lifted from lodestar-z bindings/napi/async_task.zig, which was written to be upstreamed and is deleted once this ships.
nazarhussain
marked this pull request as draft
August 18, 2026 17:55
nazarhussain
marked this pull request as ready for review
August 20, 2026 10:26
GrapeBaBa
reviewed
Aug 21, 2026
Comment on lines
+726
to
+729
| // ============================================================================ | ||
| // Section 18: Async Tasks | ||
| // ============================================================================ | ||
|
|
Contributor
There was a problem hiding this comment.
Can we remove this task number comments by AI?
GrapeBaBa
reviewed
Aug 21, 2026
| }); | ||
| }); | ||
|
|
||
| // Section 18: Async Tasks |
Contributor
There was a problem hiding this comment.
Same task number comment
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
No DSL for worker-thread async:
js.Promiseis synchronous-only, so every call site hand-rollsnapi.AsyncWork+napi.Deferred(~100 lines each in lodestar-z). DSL types were unusable in the completion callback becausejs.env()panics there.Description
js.spawn(Task, task, name)runscomputeon the libuv pool and settles a Promise withresolve's value. A task is a comptime duck-typed struct:compute(*Task) !voidresolve(*Task, napi.Env) !TT= DSL type, owned typed array,napi.Value, orvoiddeinit(*Task) voidresolvetransferred ownershiperrorMessage(anyerror) [:0]const u8@errorNamereject(*Task, napi.Env, anyerror) !napi.ValueerrorMessageIf
spawnfails the task isn't consumed (caller frees); if it succeeds ownership transfers anddeinitruns after settling.All logic is in
src/js/async_task.zig— the other files are the export, doc fixes, tests, and README.Two decisions worth checking:
complete()sets the DSL env context, which is what makes DSL returns work.execute()deliberately doesn't: napi calls are illegal on the worker thread, so the panic is the guard rail.src/async_work.zig, so the rawnapilayer keeps no dependency onjs/context.zig.8 new vitest cases; deleting the
setEnvline reproduces the panic, confirming it's load-bearing. Full suite green.