summaryrefslogtreecommitdiffhomepage
path: root/src/nodejs/unit-http/nxt_napi.h
diff options
context:
space:
mode:
authorMax Romanov <max.romanov@nginx.com>2019-04-01 16:40:33 +0300
committerMax Romanov <max.romanov@nginx.com>2019-04-01 16:40:33 +0300
commitaca42de18ad9877db7e4a7f598a4c5cb55644fe8 (patch)
tree298e98c7e5163f2d87afeaebe056638247de1a90 /src/nodejs/unit-http/nxt_napi.h
parent19eba1730a1ca839ed62a37f34c204f580d1b653 (diff)
downloadunit-aca42de18ad9877db7e4a7f598a4c5cb55644fe8.tar.gz
unit-aca42de18ad9877db7e4a7f598a4c5cb55644fe8.tar.bz2
Adding syntax sugar.
With exceptions and overloads.
Diffstat (limited to 'src/nodejs/unit-http/nxt_napi.h')
-rw-r--r--src/nodejs/unit-http/nxt_napi.h656
1 files changed, 656 insertions, 0 deletions
diff --git a/src/nodejs/unit-http/nxt_napi.h b/src/nodejs/unit-http/nxt_napi.h
new file mode 100644
index 00000000..9bcf3a21
--- /dev/null
+++ b/src/nodejs/unit-http/nxt_napi.h
@@ -0,0 +1,656 @@
+
+/*
+ * Copyright (C) NGINX, Inc.
+ */
+
+#ifndef _NXT_NODEJS_NAPI_H_INCLUDED_
+#define _NXT_NODEJS_NAPI_H_INCLUDED_
+
+#include <node_api.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "version.h"
+#include <nxt_unit.h>
+
+#if NXT_VERNUM != NXT_NODE_VERNUM
+#error "libunit version mismatch."
+#endif
+
+#include <nxt_unit_response.h>
+#include <nxt_unit_request.h>
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+struct nxt_napi {
+
+ struct exception {
+ exception(const char *s) : str(s) { }
+
+ const char *str;
+ };
+
+
+ nxt_napi(napi_env env) : env_(env) { }
+
+
+ inline napi_value
+ coerce_to_string(napi_value val)
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_coerce_to_string(env_, val, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to coerce to string");
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ create_buffer(size_t size, void **data)
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_create_buffer(env_, size, data, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to create buffer");
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ create_function(const char *name, size_t len, napi_callback cb, void *data)
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_create_function(env_, name, len, cb, data, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to create function");
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ create_function(napi_callback cb)
+ {
+ return create_function(NULL, 0, cb, NULL);
+ }
+
+
+ inline napi_value
+ create_object()
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_create_object(env_, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to create object");
+ }
+
+ return res;
+ }
+
+
+ inline napi_ref
+ create_reference(napi_value val, int ref_count = 1)
+ {
+ napi_ref res;
+ napi_status status;
+
+ status = napi_create_reference(env_, val, ref_count, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to create reference");
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ create_string_latin1(const char *str, size_t len)
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_create_string_latin1(env_, str, len, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to create latin1 string");
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ create_string_latin1(nxt_unit_sptr_t &str, size_t len)
+ {
+ const char *p;
+
+ p = (const char *) nxt_unit_sptr_get(&str);
+
+ return create_string_latin1(p, len);
+ }
+
+
+ inline napi_value
+ define_class(const char *name, napi_callback ctor, size_t prop_count,
+ const napi_property_descriptor* props)
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_define_class(env_, name, NAPI_AUTO_LENGTH, ctor, nullptr,
+ prop_count, props, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to define class");
+ }
+
+ return res;
+ }
+
+
+ inline void
+ delete_reference(napi_ref ref)
+ {
+ napi_delete_reference(env_, ref);
+ }
+
+
+ inline uint32_t
+ get_array_length(napi_value val)
+ {
+ uint32_t res;
+ napi_status status;
+
+ status = napi_get_array_length(env_, val, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to get array length");
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ get_cb_info(napi_callback_info info, size_t &argc, napi_value *argv)
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_get_cb_info(env_, info, &argc, argv, &res, nullptr);
+ if (status != napi_ok) {
+ throw exception("Failed to get arguments from js");
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ get_cb_info(napi_callback_info info)
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_get_cb_info(env_, info, nullptr, nullptr, &res, nullptr);
+ if (status != napi_ok) {
+ throw exception("Failed to get arguments from js");
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ get_element(napi_value obj, uint32_t i)
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_get_element(env_, obj, i, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to get element");
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ get_named_property(napi_value obj, const char *name)
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_get_named_property(env_, obj, name, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to get named property");
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ get_new_target(napi_callback_info info)
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_get_new_target(env_, info, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to get new target");
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ get_property(napi_value val, napi_value key)
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_get_property(env_, val, key, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to get property");
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ get_property_names(napi_value val)
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_get_property_names(env_, val, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to get property names");
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ get_reference_value(napi_ref ref)
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_get_reference_value(env_, ref, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to get reference value");
+ }
+
+ return res;
+ }
+
+
+ inline nxt_unit_request_info_t *
+ get_request_info(napi_value obj)
+ {
+ int64_t n;
+ napi_status status;
+
+ status = napi_get_value_int64(env_, obj, &n);
+ if (status != napi_ok) {
+ throw exception("Failed to get request pointer");
+ }
+
+ return (nxt_unit_request_info_t *) (intptr_t) n;
+ }
+
+
+ inline size_t
+ get_value_string_latin1(napi_value val, char *buf, size_t bufsize)
+ {
+ size_t res;
+ napi_status status;
+
+ status = napi_get_value_string_latin1(env_, val, buf, bufsize, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to get string latin1");
+ }
+
+ return res;
+ }
+
+
+ inline uint32_t
+ get_value_uint32(napi_value obj)
+ {
+ uint32_t res;
+ napi_status status;
+
+ status = napi_get_value_uint32(env_, obj, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to get uint32_t");
+ }
+
+ return res;
+ }
+
+
+ inline bool
+ is_array(napi_value val)
+ {
+ bool res;
+ napi_status status;
+
+ status = napi_is_array(env_, val, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to confirm value is array");
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ make_callback(napi_async_context ctx, napi_value val, napi_value func,
+ int argc, const napi_value *argv)
+ {
+ napi_value res, ex;
+ napi_status status;
+
+ status = napi_make_callback(env_, ctx, val, func, argc, argv, &res);
+ if (status != napi_ok) {
+ if (status != napi_pending_exception) {
+ throw exception("Failed to make callback");
+ }
+
+ status = napi_get_and_clear_last_exception(env_, &ex);
+ if (status != napi_ok) {
+ throw exception("Failed to get and clear last exception");
+ }
+
+ /* Logging a description of the error and call stack. */
+ status = napi_fatal_exception(env_, ex);
+ if (status != napi_ok) {
+ throw exception("Failed napi_fatal_exception()");
+ }
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ new_instance(napi_value ctor)
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_new_instance(env_, ctor, 0, NULL, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to create instance");
+ }
+
+ return res;
+ }
+
+
+ inline napi_value
+ new_instance(napi_value ctor, napi_value param)
+ {
+ napi_value res;
+ napi_status status;
+
+ status = napi_new_instance(env_, ctor, 1, &param, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to create instance");
+ }
+
+ return res;
+ }
+
+
+ inline void
+ set_element(napi_value obj, uint32_t i, napi_value val)
+ {
+ napi_status status;
+
+ status = napi_set_element(env_, obj, i, val);
+ if (status != napi_ok) {
+ throw exception("Failed to set element");
+ }
+ }
+
+
+ inline void
+ set_named_property(napi_value obj, const char *name, napi_value val)
+ {
+ napi_status status;
+
+ status = napi_set_named_property(env_, obj, name, val);
+ if (status != napi_ok) {
+ throw exception("Failed to set named property");
+ }
+ }
+
+
+ inline void
+ set_named_property(napi_value obj, const char *name, napi_callback cb)
+ {
+ set_named_property(obj, name, create_function(cb));
+ }
+
+
+ inline napi_value
+ set_named_property(napi_value obj, const char *name, nxt_unit_sptr_t &val,
+ size_t len)
+ {
+ napi_value str;
+
+ str = create_string_latin1(val, len);
+
+ set_named_property(obj, name, str);
+
+ return str;
+ }
+
+
+ inline void
+ set_named_property(napi_value obj, const char *name, intptr_t val)
+ {
+ napi_value ptr;
+ napi_status status;
+
+ status = napi_create_int64(env_, val, &ptr);
+ if (status != napi_ok) {
+ throw exception("Failed to create int64");
+ }
+
+ set_named_property(obj, name, ptr);
+ }
+
+
+ inline void
+ throw_error(const char *str)
+ {
+ napi_throw_error(env_, NULL, str);
+ }
+
+
+ inline void
+ throw_error(const exception &e)
+ {
+ napi_throw_error(env_, NULL, e.str);
+ }
+
+
+ inline napi_valuetype
+ type_of(napi_value val)
+ {
+ napi_status status;
+ napi_valuetype res;
+
+ status = napi_typeof(env_, val, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to get typeof");
+ }
+
+ return res;
+ }
+
+
+ inline void *
+ unwrap(napi_value val)
+ {
+ void *res;
+ napi_status status;
+
+ status = napi_unwrap(env_, val, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to unwrap");
+ }
+
+ return res;
+ }
+
+
+ inline napi_ref
+ wrap(napi_value val, void *obj, napi_finalize fin_cb, void *hint = nullptr)
+ {
+ napi_ref res;
+ napi_status status;
+
+ status = napi_wrap(env_, val, obj, fin_cb, hint, &res);
+ if (status != napi_ok) {
+ throw exception("Failed to wrap");
+ }
+
+ return res;
+ }
+
+
+ inline
+ operator napi_env()
+ {
+ return env_;
+ }
+
+
+ napi_env env()
+ {
+ return env_;
+ }
+
+private:
+ napi_env env_;
+};
+
+
+struct nxt_handle_scope : public nxt_napi {
+ nxt_handle_scope(napi_env env) : nxt_napi(env)
+ {
+ napi_status status;
+
+ status = napi_open_handle_scope(env, &scope_);
+ if (status != napi_ok) {
+ throw exception("Failed to open handle scope");
+ }
+ }
+
+ ~nxt_handle_scope()
+ {
+ napi_status status;
+
+ status = napi_close_handle_scope(env(), scope_);
+ if (status != napi_ok) {
+ throw_error("Failed to close handle scope");
+ }
+ }
+
+private:
+ napi_handle_scope scope_;
+};
+
+
+struct nxt_async_context : public nxt_napi {
+ nxt_async_context(napi_env env, const char *name) :
+ nxt_napi(env)
+ {
+ napi_value name_val;
+ napi_status status;
+
+ name_val = create_string_latin1(name, NAPI_AUTO_LENGTH);
+
+ status = napi_async_init(env, NULL, name_val, &context_);
+ if (status != napi_ok) {
+ throw exception("Failed to init async object");
+ }
+ }
+
+ operator napi_async_context() {
+ return context_;
+ }
+
+ ~nxt_async_context()
+ {
+ napi_status status;
+
+ status = napi_async_destroy(env(), context_);
+ if (status != napi_ok) {
+ throw_error("Failed to destroy async object");
+ }
+ }
+
+private:
+ napi_async_context context_;
+};
+
+
+struct nxt_callback_scope : public nxt_napi {
+ nxt_callback_scope(nxt_async_context& ctx) :
+ nxt_napi(ctx.env())
+ {
+ napi_value resource;
+ napi_status status;
+
+ resource = create_object();
+
+ status = napi_open_callback_scope(env(), resource, ctx, &scope_);
+ if (status != napi_ok) {
+ throw exception("Failed to open callback scope");
+ }
+ }
+
+ ~nxt_callback_scope()
+ {
+ napi_status status;
+
+ status = napi_close_callback_scope(env(), scope_);
+ if (status != napi_ok) {
+ throw_error("Failed to close callback scope");
+ }
+ }
+
+private:
+ napi_callback_scope scope_;
+};
+
+
+#endif /* _NXT_NODEJS_NAPI_H_INCLUDED_ */