njs_opaque_value_t request;
njs_opaque_value_t request_body;
ngx_str_t redirect_uri;
+ njs_opaque_value_t promise_callbacks[2];
} ngx_http_js_ctx_t;
}
+static njs_int_t
+ngx_http_js_promise_trampoline(njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t unused)
+{
+ njs_function_t *callback;
+ ngx_http_js_ctx_t *ctx;
+ ngx_http_request_t *r;
+
+ r = njs_vm_external(vm, njs_argument(args, 1));
+ ctx = ngx_http_get_module_ctx(r, ngx_http_js_module);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "js subrequest promise trampoline ctx: %p", ctx);
+
+ callback = njs_value_function(njs_value_arg(&ctx->promise_callbacks[0]));
+
+ return njs_vm_call(vm, callback, njs_argument(args, 1), 1);
+}
+
+
static njs_int_t
ngx_http_js_ext_subrequest(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
{
- ngx_int_t rc;
+ ngx_int_t rc, promise;
njs_str_t uri_arg, args_arg, method_name, body_arg;
ngx_uint_t method, methods_max, has_body;
njs_value_t *value, *arg, *options;
r = njs_vm_external(vm, njs_arg(args, nargs, 0));
if (njs_slow_path(r == NULL)) {
+ njs_vm_error(vm, "this is not an external");
return NJS_ERROR;
}
args_arg.length = 0;
args_arg.start = NULL;
has_body = 0;
+ promise = 0;
arg = njs_arg(args, nargs, 2);
}
}
+ if (callback == NULL) {
+ callback = njs_vm_function_alloc(vm, ngx_http_js_promise_trampoline);
+ if (callback == NULL) {
+ goto memory_error;
+ }
+
+ promise = 1;
+ }
+
rc = ngx_http_js_subrequest(r, &uri_arg, &args_arg, callback, &sr);
if (rc != NGX_OK) {
return NJS_ERROR;
sr->method_name.data = method_name.start;
}
- sr->header_only = (sr->method == NGX_HTTP_HEAD) || (callback == NULL);
+ sr->header_only = (sr->method == NGX_HTTP_HEAD);
if (has_body) {
rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
sr->headers_in.chunked = 0;
}
+ if (promise) {
+ ctx = ngx_pcalloc(sr->pool, sizeof(ngx_http_js_ctx_t));
+ if (ctx == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_http_set_ctx(sr, ctx, ngx_http_js_module);
+
+ return njs_vm_promise_create(vm, njs_vm_retval(vm),
+ njs_value_arg(&ctx->promise_callbacks));
+ }
+
return NJS_OK;
memory_error:
ctx = ngx_http_get_module_ctx(r, ngx_http_js_module);
- flags = NGX_HTTP_SUBREQUEST_BACKGROUND;
-
- if (callback != NULL) {
- ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
- if (ps == NULL) {
- njs_vm_error(ctx->vm, "internal error");
- return NJS_ERROR;
- }
+ flags = NGX_HTTP_SUBREQUEST_BACKGROUND | NGX_HTTP_SUBREQUEST_IN_MEMORY;
- vm_event = njs_vm_add_event(ctx->vm, callback, 1, NULL, NULL);
- if (vm_event == NULL) {
- njs_vm_error(ctx->vm, "internal error");
- return NJS_ERROR;
- }
-
- ps->handler = ngx_http_js_subrequest_done;
- ps->data = vm_event;
-
- flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY;
+ ps = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
+ if (ps == NULL) {
+ njs_vm_error(ctx->vm, "internal error");
+ return NJS_ERROR;
+ }
- } else {
- ps = NULL;
- vm_event = NULL;
+ vm_event = njs_vm_add_event(ctx->vm, callback, 1, NULL, NULL);
+ if (vm_event == NULL) {
+ njs_vm_error(ctx->vm, "internal error");
+ return NJS_ERROR;
}
+ ps->handler = ngx_http_js_subrequest_done;
+ ps->data = vm_event;
+
uri.len = uri_arg->length;
uri.data = uri_arg->start;
};
+typedef njs_int_t (*njs_function_native_t) (njs_vm_t *vm, njs_value_t *args,
+ njs_uint_t nargs, njs_index_t retval);
+
/*
* NJS and event loops.
*
NJS_EXPORT njs_external_ptr_t njs_vm_external(njs_vm_t *vm,
const njs_value_t *value);
+NJS_EXPORT njs_function_t *njs_vm_function_alloc(njs_vm_t *vm,
+ njs_function_native_t native);
+
NJS_EXPORT void njs_disassembler(njs_vm_t *vm);
NJS_EXPORT void njs_disassemble(u_char *start, u_char *end);
NJS_EXPORT njs_int_t njs_vm_json_stringify(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs);
+NJS_EXPORT njs_int_t njs_vm_promise_create(njs_vm_t *vm, njs_value_t *retval,
+ njs_value_t *callbacks);
+
+
#endif /* _NJS_H_INCLUDED_ */