-
Notifications
You must be signed in to change notification settings - Fork 23
Promise and Job Queue API Completion #751
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
b9542e9
193d1bc
142ebbd
ac76cf8
60875f6
5a042f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -110,6 +110,30 @@ func (ctx *Context) Schedule(job func(*Context)) bool { | |
| } | ||
| } | ||
|
|
||
| // EnqueueJob enqueues a job to run on the Context thread. | ||
| func (ctx *Context) EnqueueJob(job func(*Context)) bool { | ||
| return ctx.Schedule(job) | ||
| } | ||
|
|
||
| // EnqueueNativeJob enqueues a callable into the QuickJS native job queue. | ||
| // The callable and all args must belong to the same Context. | ||
| func (ctx *Context) EnqueueNativeJob(fn *Value, args ...*Value) bool { | ||
| if !ctx.hasValidRef() || fn == nil || !fn.belongsTo(ctx) || !fn.IsFunction() { | ||
| return false | ||
| } | ||
|
|
||
| cArgs := make([]C.JSValue, len(args)+1) | ||
| cArgs[0] = fn.ref | ||
| for i, arg := range args { | ||
| if arg == nil || !arg.belongsTo(ctx) { | ||
| return false | ||
| } | ||
| cArgs[i+1] = arg.ref | ||
| } | ||
|
|
||
| return C.EnqueueCallableJob(ctx.ref, C.int(len(cArgs)), &cArgs[0]) == 0 | ||
| } | ||
|
buke marked this conversation as resolved.
|
||
|
|
||
| // ProcessJobs drains all pending scheduled jobs. | ||
| // Call this regularly (e.g., inside Loop or Await) to allow resolve/reject handlers to run. | ||
| func (ctx *Context) ProcessJobs() { | ||
|
|
@@ -1469,3 +1493,45 @@ func (ctx *Context) NewPromise(executor func(resolve, reject func(*Value))) *Val | |
| func (ctx *Context) Promise(executor func(resolve, reject func(*Value))) *Value { | ||
| return ctx.NewPromise(executor) | ||
| } | ||
|
|
||
| // PromiseCapability mirrors QuickJS promise capability tuple. | ||
| type PromiseCapability struct { | ||
| Promise *Value | ||
| Resolve *Value | ||
| Reject *Value | ||
| } | ||
|
|
||
| // NewPromiseCapability creates a promise plus its resolve/reject functions. | ||
| func (ctx *Context) NewPromiseCapability() *PromiseCapability { | ||
| if !ctx.hasValidRef() { | ||
| return nil | ||
| } | ||
|
|
||
| resolving := [2]C.JSValue{C.JS_NewUndefined(), C.JS_NewUndefined()} | ||
| promise := C.JS_NewPromiseCapability(ctx.ref, &resolving[0]) | ||
|
buke marked this conversation as resolved.
|
||
| if bool(C.JS_IsException(promise)) { | ||
| return nil | ||
| } | ||
|
Comment on lines
+1512
to
+1514
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When |
||
| return &PromiseCapability{ | ||
| Promise: &Value{ctx: ctx, ref: promise}, | ||
| Resolve: &Value{ctx: ctx, ref: resolving[0]}, | ||
| Reject: &Value{ctx: ctx, ref: resolving[1]}, | ||
| } | ||
| } | ||
|
|
||
| // NewSettledPromise creates an already-fulfilled or already-rejected promise. | ||
| func (ctx *Context) NewSettledPromise(value *Value, isReject bool) *Value { | ||
| if !ctx.hasValidRef() { | ||
| return nil | ||
| } | ||
|
|
||
| input := C.JS_NewUndefined() | ||
| if value != nil { | ||
| if !value.belongsTo(ctx) { | ||
| return nil | ||
| } | ||
| input = value.ref | ||
| } | ||
|
|
||
| return &Value{ctx: ctx, ref: C.JS_NewSettledPromise(ctx.ref, C.bool(isReject), input)} | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
EnqueueCallableJobfunction does not validate ifargv[0]is actually a function before enqueuing. While the job functionQuickjsGoCallableJobperforms this check during execution, enqueuing a non-callable value will lead to aTypeErrorbeing raised asynchronously in the job queue. It is better to validate this early to provide immediate feedback to the caller.