return NJS_ERROR;
}
- frame->function->context = capability;
-
- ret = njs_function_lambda_call(vm);
+ ret = njs_function_lambda_call(vm, capability, NULL);
if (ret == NJS_OK) {
ret = njs_function_call(vm, njs_function(&capability->resolve),
njs_int_t ret;
njs_value_t **cur_local, **cur_closures, **cur_temp, *value;
njs_frame_t *frame, *async_frame;
- njs_function_t *function;
njs_async_ctx_t *ctx;
njs_native_frame_t *top, *async;
async = &async_frame->native;
async->previous = vm->top_frame;
- function = async->function;
-
cur_local = vm->levels[NJS_LEVEL_LOCAL];
cur_closures = vm->levels[NJS_LEVEL_CLOSURE];
cur_temp = vm->levels[NJS_LEVEL_TEMP];
vm->top_frame->retval = &vm->retval;
- function->context = ctx->capability;
- function->await = ctx;
-
- ret = njs_vmcode_interpreter(vm, ctx->pc);
-
- function->context = NULL;
- function->await = NULL;
+ ret = njs_vmcode_interpreter(vm, ctx->pc, ctx->capability, ctx);
vm->levels[NJS_LEVEL_LOCAL] = cur_local;
vm->levels[NJS_LEVEL_CLOSURE] = cur_closures;
njs_int_t
-njs_function_lambda_call(njs_vm_t *vm)
+njs_function_lambda_call(njs_vm_t *vm, void *promise_cap, void *async_ctx)
{
uint32_t n;
njs_int_t ret;
frame = (njs_frame_t *) vm->top_frame;
function = frame->native.function;
+ njs_assert(function->context == NULL);
+
if (function->global && !function->closure_copied) {
ret = njs_function_capture_global_closures(vm, function);
if (njs_slow_path(ret != NJS_OK)) {
}
}
- ret = njs_vmcode_interpreter(vm, lambda->start);
+ ret = njs_vmcode_interpreter(vm, lambda->start, promise_cap, async_ctx);
/* Restore current level. */
vm->levels[NJS_LEVEL_LOCAL] = cur_local;
return njs_function_native_call(vm);
} else {
- return njs_function_lambda_call(vm);
+ return njs_function_lambda_call(vm, NULL, NULL);
}
}
njs_int_t njs_function_call2(njs_vm_t *vm, njs_function_t *function,
const njs_value_t *this, const njs_value_t *args,
njs_uint_t nargs, njs_value_t *retval, njs_bool_t ctor);
-njs_int_t njs_function_lambda_call(njs_vm_t *vm);
+njs_int_t njs_function_lambda_call(njs_vm_t *vm, void *promise_cap,
+ void *async_ctx);
njs_int_t njs_function_native_call(njs_vm_t *vm);
njs_native_frame_t *njs_function_frame_alloc(njs_vm_t *vm, size_t size);
void njs_function_frame_free(njs_vm_t *vm, njs_native_frame_t *frame);
} u;
void *context;
- void *await;
njs_value_t *bound;
};
return ret;
}
- ret = njs_vmcode_interpreter(vm, vm->start);
+ ret = njs_vmcode_interpreter(vm, vm->start, NULL, NULL);
return (ret == NJS_ERROR) ? NJS_ERROR : NJS_OK;
}
static njs_jump_off_t njs_vmcode_return(njs_vm_t *vm, njs_value_t *invld,
njs_value_t *retval);
-static njs_jump_off_t njs_vmcode_await(njs_vm_t *vm, njs_vmcode_await_t *await);
+static njs_jump_off_t njs_vmcode_await(njs_vm_t *vm, njs_vmcode_await_t *await,
+ njs_promise_capability_t *pcap, njs_async_ctx_t *actx);
static njs_jump_off_t njs_vmcode_try_start(njs_vm_t *vm, njs_value_t *value,
njs_value_t *offset, u_char *pc);
njs_int_t
-njs_vmcode_interpreter(njs_vm_t *vm, u_char *pc)
+njs_vmcode_interpreter(njs_vm_t *vm, u_char *pc, void *promise_cap,
+ void *async_ctx)
{
u_char *catch;
double num, exponent;
case NJS_VMCODE_AWAIT:
await = (njs_vmcode_await_t *) pc;
- return njs_vmcode_await(vm, await);
+ return njs_vmcode_await(vm, await, promise_cap, async_ctx);
case NJS_VMCODE_TRY_START:
ret = njs_vmcode_try_start(vm, value1, value2, pc);
static njs_jump_off_t
-njs_vmcode_await(njs_vm_t *vm, njs_vmcode_await_t *await)
+njs_vmcode_await(njs_vm_t *vm, njs_vmcode_await_t *await,
+ njs_promise_capability_t *pcap, njs_async_ctx_t *ctx)
{
size_t size;
njs_int_t ret;
njs_value_t ctor, val, on_fulfilled, on_rejected, *value;
njs_promise_t *promise;
njs_function_t *fulfilled, *rejected;
- njs_async_ctx_t *ctx;
njs_native_frame_t *active;
active = &vm->active_frame->native;
return NJS_ERROR;
}
- ctx = active->function->await;
-
if (ctx == NULL) {
ctx = njs_mp_alloc(vm->mem_pool, sizeof(njs_async_ctx_t));
if (njs_slow_path(ctx == NULL)) {
}
ctx->await = fulfilled->context;
- ctx->capability = active->function->context;
-
- active->function->context = NULL;
+ ctx->capability = pcap;
ret = njs_function_frame_save(vm, ctx->await, NULL);
if (njs_slow_path(ret != NJS_OK)) {
} njs_vmcode_await_t;
-njs_int_t njs_vmcode_interpreter(njs_vm_t *vm, u_char *pc);
+njs_int_t njs_vmcode_interpreter(njs_vm_t *vm, u_char *pc,
+ void *promise_cap, void *async_ctx);
njs_object_t *njs_function_new_object(njs_vm_t *vm, njs_value_t *constructor);
--- /dev/null
+/*---
+includes: [compareArray.js]
+flags: [async]
+---*/
+
+let stages = [];
+
+async function f(v) {
+ if (v == 3) {
+ return;
+ }
+
+ stages.push(`f>${v}`);
+
+ f(v + 1);
+
+ stages.push(`f<${v}`);
+
+ await "X";
+}
+
+f(0)
+.then(v => {
+ assert.compareArray(stages, ['f>0', 'f>1', 'f>2', 'f<2', 'f<1', 'f<0']);
+})
+.then($DONE, $DONE);
--- /dev/null
+/*---
+includes: [compareArray.js]
+flags: [async]
+---*/
+
+let stages = [];
+
+async function f(v) {
+ if (v == 3) {
+ return;
+ }
+
+ stages.push(`f>${v}`);
+
+ await "X";
+
+ f(v + 1);
+
+ stages.push(`f<${v}`);
+}
+
+f(0)
+.then(v => {
+ assert.compareArray(stages, ['f>0','f>1','f<0','f>2','f<1']);
+})
+.then($DONE, $DONE);