#include <nxt_string.h>
#include <nxt_stub.h>
#include <nxt_array.h>
-#include <nxt_random.h>
-#include <nxt_lvlhsh.h>
-#include <nxt_mem_cache_pool.h>
#include <njscript.h>
-#define NGX_HTTP_JS_MCP_CLUSTER_SIZE (2 * ngx_pagesize)
-#define NGX_HTTP_JS_MCP_PAGE_ALIGNMENT 128
-#define NGX_HTTP_JS_MCP_PAGE_SIZE 512
-#define NGX_HTTP_JS_MCP_MIN_CHUNK_SIZE 16
-
-
-#define ngx_http_js_create_mem_cache_pool() \
- nxt_mem_cache_pool_create(&ngx_http_js_mem_cache_pool_proto, NULL, NULL, \
- NGX_HTTP_JS_MCP_CLUSTER_SIZE, \
- NGX_HTTP_JS_MCP_PAGE_ALIGNMENT, \
- NGX_HTTP_JS_MCP_PAGE_SIZE, \
- NGX_HTTP_JS_MCP_MIN_CHUNK_SIZE)
-
-
typedef struct {
njs_vm_t *vm;
- njs_opaque_value_t args[2];
ngx_str_t content;
+ const njs_extern_t *req_proto;
+ const njs_extern_t *res_proto;
} ngx_http_js_loc_conf_t;
typedef struct {
njs_vm_t *vm;
- njs_opaque_value_t *args;
+ njs_opaque_value_t args[2];
} ngx_http_js_ctx_t;
static ngx_int_t ngx_http_js_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_js_init_vm(ngx_http_request_t *r);
-static void ngx_http_js_cleanup_mem_cache_pool(void *data);
-
-static void *ngx_http_js_alloc(void *mem, size_t size);
-static void *ngx_http_js_calloc(void *mem, size_t size);
-static void *ngx_http_js_memalign(void *mem, size_t alignment, size_t size);
-static void ngx_http_js_free(void *mem, void *p);
+static void ngx_http_js_cleanup_vm(void *data);
static njs_ret_t ngx_http_js_ext_get_string(njs_vm_t *vm, njs_value_t *value,
void *obj, uintptr_t data);
};
-static const nxt_mem_proto_t ngx_http_js_mem_cache_pool_proto = {
- ngx_http_js_alloc,
- ngx_http_js_calloc,
- ngx_http_js_memalign,
- NULL,
- ngx_http_js_free,
- NULL,
- NULL,
-};
-
-
static njs_external_t ngx_http_js_ext_response[] = {
{ nxt_string("headers"),
static njs_external_t ngx_http_js_ext_request[] = {
- { nxt_string("response"),
- NJS_EXTERN_OBJECT,
- ngx_http_js_ext_response,
- nxt_nitems(ngx_http_js_ext_response),
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 0 },
-
{ nxt_string("log"),
NJS_EXTERN_METHOD,
NULL,
static njs_external_t ngx_http_js_externals[] = {
- { nxt_string("$r"),
+ { nxt_string("request"),
NJS_EXTERN_OBJECT,
ngx_http_js_ext_request,
nxt_nitems(ngx_http_js_ext_request),
NULL,
NULL,
0 },
+
+ { nxt_string("response"),
+ NJS_EXTERN_OBJECT,
+ ngx_http_js_ext_response,
+ nxt_nitems(ngx_http_js_ext_response),
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0 },
};
static ngx_int_t
ngx_http_js_init_vm(ngx_http_request_t *r)
{
- void **ext;
- ngx_http_js_ctx_t *ctx;
- ngx_pool_cleanup_t *cln;
- nxt_mem_cache_pool_t *mcp;
- ngx_http_js_loc_conf_t *jlcf;
+ nxt_int_t rc;
+ ngx_http_js_ctx_t *ctx;
+ ngx_pool_cleanup_t *cln;
+ ngx_http_js_loc_conf_t *jlcf;
jlcf = ngx_http_get_module_loc_conf(r, ngx_http_js_module);
if (jlcf->vm == NULL) {
return NGX_OK;
}
- mcp = ngx_http_js_create_mem_cache_pool();
- if (mcp == NULL) {
+ ctx->vm = njs_vm_clone(jlcf->vm, r);
+ if (ctx->vm == NULL) {
return NGX_ERROR;
}
return NGX_ERROR;
}
- cln->handler = ngx_http_js_cleanup_mem_cache_pool;
- cln->data = mcp;
+ cln->handler = ngx_http_js_cleanup_vm;
+ cln->data = ctx->vm;
- ext = ngx_palloc(r->pool, sizeof(void *));
- if (ext == NULL) {
+ if (njs_vm_run(ctx->vm) != NJS_OK) {
return NGX_ERROR;
}
- *ext = r;
-
- ctx->vm = njs_vm_clone(jlcf->vm, mcp, ext);
- if (ctx->vm == NULL) {
+ rc = njs_vm_external_create(ctx->vm, &ctx->args[0], jlcf->req_proto, r);
+ if (rc != NXT_OK) {
return NGX_ERROR;
}
- if (njs_vm_run(ctx->vm) != NJS_OK) {
+ rc = njs_vm_external_create(ctx->vm, &ctx->args[1], jlcf->res_proto, r);
+ if (rc != NXT_OK) {
return NGX_ERROR;
}
- ctx->args = &jlcf->args[0];
-
return NGX_OK;
}
static void
-ngx_http_js_cleanup_mem_cache_pool(void *data)
-{
- nxt_mem_cache_pool_t *mcp = data;
-
- nxt_mem_cache_pool_destroy(mcp);
-}
-
-
-static void *
-ngx_http_js_alloc(void *mem, size_t size)
+ngx_http_js_cleanup_vm(void *data)
{
- return ngx_alloc(size, ngx_cycle->log);
-}
-
+ njs_vm_t *vm = data;
-static void *
-ngx_http_js_calloc(void *mem, size_t size)
-{
- return ngx_calloc(size, ngx_cycle->log);
-}
-
-
-static void *
-ngx_http_js_memalign(void *mem, size_t alignment, size_t size)
-{
- return ngx_memalign(alignment, size, ngx_cycle->log);
-}
-
-
-static void
-ngx_http_js_free(void *mem, void *p)
-{
- ngx_free(p);
+ njs_vm_destroy(vm);
}
ngx_fd_t fd;
ngx_str_t *value, file;
nxt_int_t rc;
- nxt_str_t text, ext;
+ nxt_str_t text;
njs_vm_opt_t options;
- nxt_lvlhsh_t externals;
ngx_file_info_t fi;
ngx_pool_cleanup_t *cln;
- nxt_mem_cache_pool_t *mcp;
if (jlcf->vm) {
return "is duplicate";
end = start + size;
- mcp = ngx_http_js_create_mem_cache_pool();
- if (mcp == NULL) {
+ ngx_memzero(&options, sizeof(njs_vm_opt_t));
+
+ options.backtrace = 1;
+
+ jlcf->vm = njs_vm_create(&options);
+ if (jlcf->vm == NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to create JS VM");
return NGX_CONF_ERROR;
}
return NGX_CONF_ERROR;
}
- cln->handler = ngx_http_js_cleanup_mem_cache_pool;
- cln->data = mcp;
-
- nxt_lvlhsh_init(&externals);
+ cln->handler = ngx_http_js_cleanup_vm;
+ cln->data = jlcf->vm;
- if (njs_vm_external_add(&externals, mcp, 0, ngx_http_js_externals,
- nxt_nitems(ngx_http_js_externals))
- != NJS_OK)
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "could not add js externals");
+ jlcf->req_proto = njs_vm_external_prototype(jlcf->vm,
+ &ngx_http_js_externals[0]);
+ if (jlcf->req_proto == NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to add request proto");
return NGX_CONF_ERROR;
}
- ngx_memzero(&options, sizeof(njs_vm_opt_t));
-
- options.mcp = mcp;
- options.backtrace = 1;
- options.externals_hash = &externals;
-
- jlcf->vm = njs_vm_create(&options);
- if (jlcf->vm == NULL) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to create JS VM");
+ jlcf->res_proto = njs_vm_external_prototype(jlcf->vm,
+ &ngx_http_js_externals[1]);
+ if (jlcf->res_proto == NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "failed to add response proto");
return NGX_CONF_ERROR;
}
return NGX_CONF_ERROR;
}
- ext = nxt_string_value("$r");
-
- if (njs_vm_external(jlcf->vm, NULL, &ext, &jlcf->args[0]) != NJS_OK) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "js external \"%*s\" not found",
- ext.length, ext.start);
- return NGX_CONF_ERROR;
- }
-
- ext = nxt_string_value("response");
-
- rc = njs_vm_external(jlcf->vm, &jlcf->args[0], &ext, &jlcf->args[1]);
- if (rc != NXT_OK) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "js external \"$r.%*s\" not found",
- ext.length, ext.start);
- return NGX_CONF_ERROR;
- }
-
return NGX_CONF_OK;
}
* set by ngx_pcalloc():
*
* conf->vm = NULL;
+ * conf->req_proto = NULL;
+ * conf->res_proto = NULL;
*/
return conf;
if (conf->vm == NULL) {
conf->vm = prev->vm;
- conf->args[0] = prev->args[0];
- conf->args[1] = prev->args[1];
+ conf->req_proto = prev->req_proto;
+ conf->res_proto = prev->res_proto;
}
return NGX_CONF_OK;
#include <nxt_string.h>
#include <nxt_stub.h>
#include <nxt_array.h>
-#include <nxt_random.h>
-#include <nxt_lvlhsh.h>
-#include <nxt_mem_cache_pool.h>
#include <njscript.h>
-#define NGX_STREAM_JS_MCP_CLUSTER_SIZE (2 * ngx_pagesize)
-#define NGX_STREAM_JS_MCP_PAGE_ALIGNMENT 128
-#define NGX_STREAM_JS_MCP_PAGE_SIZE 512
-#define NGX_STREAM_JS_MCP_MIN_CHUNK_SIZE 16
-
-
-#define ngx_stream_js_create_mem_cache_pool() \
- nxt_mem_cache_pool_create(&ngx_stream_js_mem_cache_pool_proto, NULL, NULL,\
- NGX_STREAM_JS_MCP_CLUSTER_SIZE, \
- NGX_STREAM_JS_MCP_PAGE_ALIGNMENT, \
- NGX_STREAM_JS_MCP_PAGE_SIZE, \
- NGX_STREAM_JS_MCP_MIN_CHUNK_SIZE)
-
-
typedef struct {
njs_vm_t *vm;
- njs_opaque_value_t arg;
ngx_str_t access;
ngx_str_t preread;
ngx_str_t filter;
+ const njs_extern_t *proto;
} ngx_stream_js_srv_conf_t;
typedef struct {
njs_vm_t *vm;
- njs_opaque_value_t *arg;
+ njs_opaque_value_t arg;
ngx_buf_t *buf;
ngx_chain_t *free;
ngx_chain_t *busy;
ngx_chain_t *in, ngx_uint_t from_upstream);
static ngx_int_t ngx_stream_js_variable(ngx_stream_session_t *s,
ngx_stream_variable_value_t *v, uintptr_t data);
-static void ngx_stream_js_cleanup_mem_cache_pool(void *data);
static ngx_int_t ngx_stream_js_init_vm(ngx_stream_session_t *s);
-
-static void *ngx_stream_js_alloc(void *mem, size_t size);
-static void *ngx_stream_js_calloc(void *mem, size_t size);
-static void *ngx_stream_js_memalign(void *mem, size_t alignment, size_t size);
-static void ngx_stream_js_free(void *mem, void *p);
+static void ngx_stream_js_cleanup_vm(void *data);
static njs_ret_t ngx_stream_js_ext_get_remote_address(njs_vm_t *vm,
njs_value_t *value, void *obj, uintptr_t data);
};
-static const nxt_mem_proto_t ngx_stream_js_mem_cache_pool_proto = {
- ngx_stream_js_alloc,
- ngx_stream_js_calloc,
- ngx_stream_js_memalign,
- NULL,
- ngx_stream_js_free,
- NULL,
- NULL,
-};
-
-
static njs_external_t ngx_stream_js_ext_session[] = {
{ nxt_string("remoteAddress"),
static njs_external_t ngx_stream_js_externals[] = {
- { nxt_string("$s"),
+ { nxt_string("stream"),
NJS_EXTERN_OBJECT,
ngx_stream_js_ext_session,
nxt_nitems(ngx_stream_js_ext_session),
return NGX_ERROR;
}
- if (njs_vm_call(ctx->vm, func, ctx->arg, 1) != NJS_OK) {
+ if (njs_vm_call(ctx->vm, func, &ctx->arg, 1) != NJS_OK) {
njs_vm_retval_to_ext_string(ctx->vm, &exception);
ngx_log_error(NGX_LOG_ERR, c->log, 0, "js exception: %*s",
while (in) {
ctx->buf = in->buf;
- if (njs_vm_call(ctx->vm, func, ctx->arg, 1) != NJS_OK) {
+ if (njs_vm_call(ctx->vm, func, &ctx->arg, 1) != NJS_OK) {
njs_vm_retval_to_ext_string(ctx->vm, &exception);
ngx_log_error(NGX_LOG_ERR, c->log, 0, "js exception: %*s",
return NGX_OK;
}
- if (njs_vm_call(ctx->vm, func, ctx->arg, 1) != NJS_OK) {
+ if (njs_vm_call(ctx->vm, func, &ctx->arg, 1) != NJS_OK) {
njs_vm_retval_to_ext_string(ctx->vm, &exception);
ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
static ngx_int_t
ngx_stream_js_init_vm(ngx_stream_session_t *s)
{
- void **ext;
- ngx_pool_cleanup_t *cln;
- nxt_mem_cache_pool_t *mcp;
- ngx_stream_js_ctx_t *ctx;
- ngx_stream_js_srv_conf_t *jscf;
+ nxt_int_t rc;
+ ngx_pool_cleanup_t *cln;
+ ngx_stream_js_ctx_t *ctx;
+ ngx_stream_js_srv_conf_t *jscf;
jscf = ngx_stream_get_module_srv_conf(s, ngx_stream_js_module);
if (jscf->vm == NULL) {
return NGX_OK;
}
- mcp = ngx_stream_js_create_mem_cache_pool();
- if (mcp == NULL) {
+ ctx->vm = njs_vm_clone(jscf->vm, s);
+ if (ctx->vm == NULL) {
return NGX_ERROR;
}
return NGX_ERROR;
}
- cln->handler = ngx_stream_js_cleanup_mem_cache_pool;
- cln->data = mcp;
-
- ext = ngx_palloc(s->connection->pool, sizeof(void *));
- if (ext == NULL) {
- return NGX_ERROR;
- }
-
- *ext = s;
+ cln->handler = ngx_stream_js_cleanup_vm;
+ cln->data = ctx->vm;
- ctx->vm = njs_vm_clone(jscf->vm, mcp, ext);
- if (ctx->vm == NULL) {
+ if (njs_vm_run(ctx->vm) != NJS_OK) {
return NGX_ERROR;
}
- if (njs_vm_run(ctx->vm) != NJS_OK) {
+ rc = njs_vm_external_create(ctx->vm, &ctx->arg, jscf->proto, s);
+ if (rc != NXT_OK) {
return NGX_ERROR;
}
- ctx->arg = &jscf->arg;
-
return NGX_OK;
}
static void
-ngx_stream_js_cleanup_mem_cache_pool(void *data)
-{
- nxt_mem_cache_pool_t *mcp = data;
-
- nxt_mem_cache_pool_destroy(mcp);
-}
-
-
-static void *
-ngx_stream_js_alloc(void *mem, size_t size)
-{
- return ngx_alloc(size, ngx_cycle->log);
-}
-
-
-static void *
-ngx_stream_js_calloc(void *mem, size_t size)
+ngx_stream_js_cleanup_vm(void *data)
{
- return ngx_calloc(size, ngx_cycle->log);
-}
-
-
-static void *
-ngx_stream_js_memalign(void *mem, size_t alignment, size_t size)
-{
- return ngx_memalign(alignment, size, ngx_cycle->log);
-}
+ njs_vm_t *vm = data;
-
-static void
-ngx_stream_js_free(void *mem, void *p)
-{
- ngx_free(p);
+ njs_vm_destroy(vm);
}
ngx_fd_t fd;
ngx_str_t *value, file;
nxt_int_t rc;
- nxt_str_t text, ext;
+ nxt_str_t text;
njs_vm_opt_t options;
- nxt_lvlhsh_t externals;
ngx_file_info_t fi;
ngx_pool_cleanup_t *cln;
- nxt_mem_cache_pool_t *mcp;
if (jscf->vm) {
return "is duplicate";
end = start + size;
- mcp = ngx_stream_js_create_mem_cache_pool();
- if (mcp == NULL) {
+ ngx_memzero(&options, sizeof(njs_vm_opt_t));
+
+ options.backtrace = 1;
+
+ jscf->vm = njs_vm_create(&options);
+ if (jscf->vm == NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to create JS VM");
return NGX_CONF_ERROR;
}
return NGX_CONF_ERROR;
}
- cln->handler = ngx_stream_js_cleanup_mem_cache_pool;
- cln->data = mcp;
+ cln->handler = ngx_stream_js_cleanup_vm;
+ cln->data = jscf->vm;
- nxt_lvlhsh_init(&externals);
+ jscf->proto = njs_vm_external_prototype(jscf->vm,
+ &ngx_stream_js_externals[0]);
- if (njs_vm_external_add(&externals, mcp, 0, ngx_stream_js_externals,
- nxt_nitems(ngx_stream_js_externals))
- != NJS_OK)
- {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "could not add js externals");
- return NGX_CONF_ERROR;
- }
-
- ngx_memzero(&options, sizeof(njs_vm_opt_t));
-
- options.mcp = mcp;
- options.backtrace = 1;
- options.externals_hash = &externals;
-
- jscf->vm = njs_vm_create(&options);
- if (jscf->vm == NULL) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to create JS VM");
+ if (jscf->proto == NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to add stream proto");
return NGX_CONF_ERROR;
}
return NGX_CONF_ERROR;
}
- ext = nxt_string_value("$s");
-
- if (njs_vm_external(jscf->vm, NULL, &ext, &jscf->arg) != NJS_OK) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "js external \"%*s\" not found", ext.length, ext.start);
- return NGX_CONF_ERROR;
- }
-
return NGX_CONF_OK;
}
* set by ngx_pcalloc():
*
* conf->vm = NULL;
- * conf->arg = NULL;
+ * conf->proto = NULL;
* conf->access = { 0, NULL };
* conf->preread = { 0, NULL };
* conf->filter = { 0, NULL };
if (conf->vm == NULL) {
conf->vm = prev->vm;
- conf->arg = prev->arg;
+ conf->proto = prev->proto;
}
ngx_conf_merge_str_value(conf->access, prev->access, "");
static nxt_int_t njs_get_options(njs_opts_t *opts, int argc, char **argv);
-static nxt_int_t njs_externals_init(njs_opts_t *opts, njs_vm_opt_t *vm_options);
+static nxt_int_t njs_externals_init(njs_vm_t *vm);
static nxt_int_t njs_interactive_shell(njs_opts_t *opts,
njs_vm_opt_t *vm_options);
static nxt_int_t njs_process_file(njs_opts_t *opts, njs_vm_opt_t *vm_options);
};
-static nxt_lvlhsh_t njs_externals_hash;
static njs_completion_t njs_completion;
int
main(int argc, char **argv)
{
- nxt_int_t ret;
- njs_opts_t opts;
- njs_vm_opt_t vm_options;
- nxt_mem_cache_pool_t *mcp;
+ nxt_int_t ret;
+ njs_opts_t opts;
+ njs_vm_opt_t vm_options;
memset(&opts, 0, sizeof(njs_opts_t));
opts.interactive = 1;
return EXIT_SUCCESS;
}
- mcp = nxt_mem_cache_pool_create(&njs_vm_mem_cache_pool_proto, NULL,
- NULL, 2 * nxt_pagesize(), 128, 512, 16);
- if (nxt_slow_path(mcp == NULL)) {
- return EXIT_FAILURE;
- }
-
memset(&vm_options, 0, sizeof(njs_vm_opt_t));
- vm_options.mcp = mcp;
vm_options.accumulative = 1;
vm_options.backtrace = 1;
- if (njs_externals_init(&opts, &vm_options) != NXT_OK) {
- return EXIT_FAILURE;
- }
-
if (opts.interactive) {
ret = njs_interactive_shell(&opts, &vm_options);
static nxt_int_t
-njs_externals_init(njs_opts_t *opts, njs_vm_opt_t *vm_options)
+njs_externals_init(njs_vm_t *vm)
{
- void **ext;
- nxt_uint_t i;
+ nxt_uint_t ret;
+ const njs_extern_t *proto;
+ njs_opaque_value_t *value;
- nxt_lvlhsh_init(&njs_externals_hash);
+ static const nxt_str_t name = nxt_string_value("console");
- for (i = 0; i < nxt_nitems(njs_externals); i++) {
- if (njs_vm_external_add(&njs_externals_hash, vm_options->mcp,
- (uintptr_t) i, &njs_externals[i], 1)
- != NXT_OK)
- {
- fprintf(stderr, "could not add external objects\n");
- return NXT_ERROR;
- }
+ proto = njs_vm_external_prototype(vm, &njs_externals[0]);
+ if (proto == NULL) {
+ fprintf(stderr, "failed to add console proto\n");
+ return NXT_ERROR;
}
- ext = nxt_mem_cache_zalloc(vm_options->mcp, sizeof(void *) * i);
- if (ext == NULL) {
+ value = nxt_mem_cache_zalloc(vm->mem_cache_pool,
+ sizeof(njs_opaque_value_t));
+ if (value == NULL) {
return NXT_ERROR;
}
- vm_options->external = ext;
- vm_options->externals_hash = &njs_externals_hash;
+ ret = njs_vm_external_create(vm, value, proto, NULL);
+ if (ret != NXT_OK) {
+ return NXT_ERROR;
+ }
+
+ ret = njs_vm_external_bind(vm, &name, value);
+ if (ret != NXT_OK) {
+ return NXT_ERROR;
+ }
return NXT_OK;
}
return NXT_ERROR;
}
+ if (njs_externals_init(vm) != NXT_OK) {
+ return NXT_ERROR;
+ }
+
if (njs_editline_init(vm) != NXT_OK) {
fprintf(stderr, "failed to init completions\n");
return NXT_ERROR;
goto done;
}
+ if (njs_externals_init(vm) != NXT_OK) {
+ return NXT_ERROR;
+ }
+
ret = njs_process_script(vm, opts, &script, &out);
if (ret != NXT_OK) {
fprintf(stderr, "failed to get retval from VM\n");
}
printf("\nEmbedded objects:\n");
- for (i = 0; i < nxt_nitems(njs_externals); i++) {
- printf(" %.*s\n", (int) njs_externals[i].name.length,
- njs_externals[i].name.start);
- }
+ printf(" console\n");
printf("\n");
size_t n, len;
nxt_str_t string;
nxt_uint_t i, k;
- njs_extern_t *ext_object, *ext_prop;
njs_object_t *objects;
njs_keyword_t *keyword;
njs_function_t *constructors;
njs_object_prop_t *prop;
nxt_lvlhsh_each_t lhe, lhe_prop;
+ njs_extern_value_t *ev;
+ const njs_extern_t *ext_proto, *ext_prop;
njs_object_prototype_t *prototypes;
n = 0;
}
}
- nxt_lvlhsh_each_init(&lhe, &njs_extern_hash_proto);
+ nxt_lvlhsh_each_init(&lhe, &njs_extern_value_hash_proto);
for ( ;; ) {
- ext_object = nxt_lvlhsh_each(&vm->externals_hash, &lhe);
+ ev = nxt_lvlhsh_each(&vm->externals_hash, &lhe);
- if (ext_object == NULL) {
+ if (ev == NULL) {
break;
}
+ ext_proto = ev->value->external.proto;
+
nxt_lvlhsh_each_init(&lhe_prop, &njs_extern_hash_proto);
if (completions != NULL) {
- len = ext_object->name.length + 1;
+ len = ev->name.length + 1;
compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
if (compl == NULL) {
return NXT_ERROR;
}
- snprintf(compl, len, "%.*s",
- (int) ext_object->name.length, ext_object->name.start);
+ snprintf(compl, len, "%.*s", (int) ev->name.length, ev->name.start);
completions[n].length = len;
completions[n++].start = (u_char *) compl;
}
for ( ;; ) {
- ext_prop = nxt_lvlhsh_each(&ext_object->hash, &lhe_prop);
+ ext_prop = nxt_lvlhsh_each(&ext_proto->hash, &lhe_prop);
if (ext_prop == NULL) {
break;
}
if (completions != NULL) {
- len = ext_object->name.length + ext_prop->name.length + 2;
+ len = ev->name.length + ev->name.length + 2;
compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
if (compl == NULL) {
return NXT_ERROR;
}
- snprintf(compl, len, "%.*s.%.*s",
- (int) ext_object->name.length, ext_object->name.start,
- (int) ext_prop->name.length, ext_prop->name.start);
+ snprintf(compl, len, "%.*s.%.*s", (int) ev->name.length,
+ ev->name.start, (int) ext_prop->name.length,
+ ext_prop->name.start);
completions[n].length = len;
completions[n++].start = (u_char *) compl;
{
njs_extern_t *ext;
- ext = data;
+ ext = (njs_extern_t *) data;
-// STUB
-// if (nxt_strcasestr_eq(&lhq->key, &ext->name)) {
if (nxt_strstr_eq(&lhq->key, &ext->name)) {
return NXT_OK;
}
}
+static nxt_int_t
+njs_extern_value_hash_test(nxt_lvlhsh_query_t *lhq, void *data)
+{
+ njs_extern_value_t *ev;
+
+ ev = (njs_extern_value_t *) data;
+
+ if (nxt_strstr_eq(&lhq->key, &ev->name)) {
+ return NXT_OK;
+ }
+
+ return NXT_DECLINED;
+}
+
+
const nxt_lvlhsh_proto_t njs_extern_hash_proto
nxt_aligned(64) =
{
};
-nxt_int_t
-njs_vm_external_add(nxt_lvlhsh_t *hash, nxt_mem_cache_pool_t *mcp,
- uintptr_t object, njs_external_t *external, nxt_uint_t n)
+const nxt_lvlhsh_proto_t njs_extern_value_hash_proto
+ nxt_aligned(64) =
+{
+ NXT_LVLHSH_DEFAULT,
+ NXT_LVLHSH_BATCH_ALLOC,
+ njs_extern_value_hash_test,
+ njs_lvlhsh_alloc,
+ njs_lvlhsh_free,
+};
+
+
+static njs_extern_t *
+njs_vm_external_add(njs_vm_t *vm, nxt_lvlhsh_t *hash, njs_external_t *external,
+ nxt_uint_t n)
{
nxt_int_t ret;
- njs_extern_t *ext;
+ njs_extern_t *ext, *child;
nxt_lvlhsh_query_t lhq;
do {
- ext = nxt_mem_cache_align(mcp, sizeof(njs_value_t),
- sizeof(njs_extern_t));
+ ext = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_extern_t));
if (nxt_slow_path(ext == NULL)) {
- return NXT_ERROR;
- }
-
- ext->name.length = external->name.length;
- ext->name.start = nxt_mem_cache_alloc(mcp, external->name.length);
- if (nxt_slow_path(ext->name.start == NULL)) {
- return NXT_ERROR;
+ return NULL;
}
- memcpy(ext->name.start, external->name.start, external->name.length);
-
- ext->value.type = NJS_EXTERNAL;
- ext->value.data.truth = 1;
- ext->value.data.u.external = ext;
-
- if (external->method != NULL) {
- ext->function = nxt_mem_cache_zalloc(mcp, sizeof(njs_function_t));
- if (nxt_slow_path(ext->function == NULL)) {
- return NXT_ERROR;
- }
-
- ext->function->native = 1;
- ext->function->args_offset = 1;
- ext->function->u.native = external->method;
- }
+ ext->name = external->name;
nxt_lvlhsh_init(&ext->hash);
+
ext->type = external->type;
ext->get = external->get;
ext->set = external->set;
ext->find = external->find;
ext->foreach = external->foreach;
ext->next = external->next;
- ext->object = object;
ext->data = external->data;
- lhq.key_hash = nxt_djb_hash(external->name.start, external->name.length);
- lhq.key = ext->name;
- lhq.replace = 0;
- lhq.value = ext;
- lhq.pool = mcp;
- lhq.proto = &njs_extern_hash_proto;
+ if (external->method != NULL) {
+ ext->function = nxt_mem_cache_zalloc(vm->mem_cache_pool,
+ sizeof(njs_function_t));
+ if (nxt_slow_path(ext->function == NULL)) {
+ return NULL;
+ }
+
+ ext->function->native = 1;
+ ext->function->args_offset = 1;
+ ext->function->u.native = external->method;
- ret = nxt_lvlhsh_insert(hash, &lhq);
- if (nxt_slow_path(ret != NXT_OK)) {
- return ret;
+ } else {
+ ext->function = NULL;
}
if (external->properties != NULL) {
- ret = njs_vm_external_add(&ext->hash, mcp, object,
- external->properties, external->nproperties);
+ child = njs_vm_external_add(vm, &ext->hash, external->properties,
+ external->nproperties);
+ if (nxt_slow_path(child == NULL)) {
+ return NULL;
+ }
+ }
+
+ if (hash != NULL) {
+ lhq.key_hash = nxt_djb_hash(external->name.start,
+ external->name.length);
+ lhq.key = ext->name;
+ lhq.replace = 0;
+ lhq.value = ext;
+ lhq.pool = vm->mem_cache_pool;
+ lhq.proto = &njs_extern_hash_proto;
+
+ ret = nxt_lvlhsh_insert(hash, &lhq);
if (nxt_slow_path(ret != NXT_OK)) {
- return ret;
+ return NULL;
}
}
} while (n != 0);
- return NXT_OK;
+ return ext;
+}
+
+
+const njs_extern_t *
+njs_vm_external_prototype(njs_vm_t *vm, njs_external_t *external)
+{
+ return njs_vm_external_add(vm, &vm->external_prototypes_hash, external, 1);
}
nxt_int_t
-njs_vm_external(njs_vm_t *vm, njs_opaque_value_t *obj, nxt_str_t *property,
- njs_opaque_value_t *value)
+njs_vm_external_create(njs_vm_t *vm, njs_opaque_value_t *value,
+ const njs_extern_t *proto, void *object)
{
- uint32_t (*key_hash)(const void *, size_t);
- njs_value_t *object;
- njs_extern_t *ext;
- nxt_lvlhsh_t hash;
- nxt_lvlhsh_query_t lhq;
+ void *obj;
+ njs_value_t *ext_val;
- object = (njs_value_t *) obj;
+ if (nxt_slow_path(proto == NULL)) {
+ return NXT_ERROR;
+ }
- key_hash = nxt_djb_hash;
- hash = vm->externals_hash;
+ obj = nxt_array_add(vm->external_objects, &njs_array_mem_proto,
+ vm->mem_cache_pool);
+ if (nxt_slow_path(obj == NULL)) {
+ return NXT_ERROR;
+ }
- if (object != NULL) {
- if (!njs_is_external(object)) {
- return NXT_ERROR;
- }
+ memcpy(obj, &object, sizeof(void *));
- ext = object->data.u.external;
- hash = ext->hash;
+ ext_val = (njs_value_t *) value;
- if (ext->type == NJS_EXTERN_CASELESS_OBJECT) {
- key_hash = nxt_djb_hash_lowcase;
- }
+ ext_val->type = NJS_EXTERNAL;
+ ext_val->data.truth = 1;
+ ext_val->external.proto = proto;
+ ext_val->external.index = vm->external_objects->items - 1;
+
+ return NXT_OK;
+}
+
+
+nxt_int_t
+njs_vm_external_bind(njs_vm_t *vm, const nxt_str_t *var_name,
+ njs_opaque_value_t *val)
+{
+ nxt_int_t ret;
+ njs_value_t *value;
+ njs_extern_value_t *ev;
+ nxt_lvlhsh_query_t lhq;
+
+ value = (njs_value_t *) val;
+
+ if (nxt_slow_path(!njs_is_external(value))) {
+ return NXT_ERROR;
+ }
+
+ ev = nxt_mem_cache_alloc(vm->mem_cache_pool, sizeof(njs_extern_value_t));
+ if (nxt_slow_path(ev == NULL)) {
+ return NXT_ERROR;
}
- lhq.key_hash = key_hash(property->start, property->length);
- lhq.key = *property;
- lhq.proto = &njs_extern_hash_proto;
+ ev->name = *var_name;
+ ev->value = value;
- if (nxt_lvlhsh_find(&hash, &lhq) == NXT_OK) {
- *value = *(njs_opaque_value_t *) lhq.value;
- return NXT_OK;
+ lhq.key = *var_name;
+ lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length);
+ lhq.proto = &njs_extern_value_hash_proto;
+ lhq.value = ev;
+ lhq.replace = 0;
+ lhq.pool = vm->mem_cache_pool;
+
+ ret = nxt_lvlhsh_insert(&vm->externals_hash, &lhq);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return ret;
}
- return NXT_ERROR;
+ return NXT_OK;
}
-njs_extern_t *
+njs_value_t *
njs_parser_external(njs_vm_t *vm, njs_parser_t *parser)
{
nxt_lvlhsh_query_t lhq;
+ njs_extern_value_t *ev;
lhq.key_hash = parser->lexer->key_hash;
lhq.key = parser->lexer->text;
- lhq.proto = &njs_extern_hash_proto;
+ lhq.proto = &njs_extern_value_hash_proto;
if (nxt_lvlhsh_find(&vm->externals_hash, &lhq) == NXT_OK) {
- return lhq.value;
+ ev = (njs_extern_value_t *) lhq.value;
+ return ev->value;
}
return NULL;
#define _NJS_EXTERN_H_INCLUDED_
-struct njs_extern_s {
- njs_value_t value;
+#define njs_extern_object(vm, ext) \
+ (*(void **) nxt_array_item((vm)->external_objects, (ext)->external.index))
+
+struct njs_extern_s {
/* A hash of inclusive njs_extern_t. */
nxt_lvlhsh_t hash;
njs_function_t *function;
- uintptr_t object;
uintptr_t data;
};
+typedef struct {
+ nxt_str_t name;
+ njs_value_t *value;
+} njs_extern_value_t;
+
+
extern const nxt_lvlhsh_proto_t njs_extern_hash_proto;
+extern const nxt_lvlhsh_proto_t njs_extern_value_hash_proto;
#endif /* _NJS_EXTERN_H_INCLUDED_ */
#include <nxt_djb_hash.h>
#include <njscript.h>
#include <njs_vm.h>
+#include <njs_extern.h>
#include <njs_number.h>
#include <njs_string.h>
#include <njs_object.h>
{
double num;
njs_ret_t ret;
- njs_extern_t *ext;
+ njs_value_t *ext;
njs_parser_node_t *node;
if (token == NJS_TOKEN_OPEN_PARENTHESIS) {
if (ext != NULL) {
node->token = NJS_TOKEN_EXTERNAL;
- node->u.value.type = NJS_EXTERNAL;
- node->u.value.data.truth = 1;
+ node->u.value = *ext;
node->index = (njs_index_t) ext;
break;
}
njs_value_t value;
njs_vmcode_operation_t operation;
njs_parser_node_t *object;
- njs_extern_t *external;
} u;
njs_index_t index;
nxt_lvlhsh_t *hash);
njs_token_t njs_lexer_keyword(njs_lexer_t *lexer);
-njs_extern_t *njs_parser_external(njs_vm_t *vm, njs_parser_t *parser);
+njs_value_t *njs_parser_external(njs_vm_t *vm, njs_parser_t *parser);
njs_parser_node_t *njs_parser(njs_vm_t *vm, njs_parser_t *parser,
njs_parser_t *prev);
njs_vmcode_property_get(njs_vm_t *vm, njs_value_t *object,
njs_value_t *property)
{
+ void *obj;
int32_t index;
uintptr_t data;
njs_ret_t ret;
- njs_value_t *val;
- njs_extern_t *ext;
+ njs_value_t *val, ext_val;
njs_slice_prop_t slice;
njs_string_prop_t string;
njs_object_prop_t *prop;
const njs_value_t *retval;
+ const njs_extern_t *ext_proto;
njs_property_query_t pq;
pq.query = NJS_PROPERTY_QUERY_GET;
break;
case NJS_EXTERNAL_VALUE:
- ext = object->data.u.external;
+ ext_proto = object->external.proto;
- ret = nxt_lvlhsh_find(&ext->hash, &pq.lhq);
+ ret = nxt_lvlhsh_find(&ext_proto->hash, &pq.lhq);
if (ret == NXT_OK) {
- ext = pq.lhq.value;
+ ext_proto = pq.lhq.value;
- if ((ext->type & NJS_EXTERN_OBJECT) != 0) {
- retval = &ext->value;
+ ext_val.type = NJS_EXTERNAL;
+ ext_val.data.truth = 1;
+ ext_val.external.proto = ext_proto;
+ ext_val.external.index = object->external.index;
+
+ if ((ext_proto->type & NJS_EXTERN_OBJECT) != 0) {
+ retval = &ext_val;
break;
}
- data = ext->data;
+ data = ext_proto->data;
} else {
data = (uintptr_t) &pq.lhq.key;
vm->retval = njs_value_void;
- if (ext->get != NULL) {
- ret = ext->get(vm, &vm->retval, vm->external[ext->object], data);
+ if (ext_proto->get != NULL) {
+ obj = njs_extern_object(vm, object);
+
+ ret = ext_proto->get(vm, &vm->retval, obj, data);
if (nxt_slow_path(ret != NXT_OK)) {
return ret;
}
- /* The vm->retval is already retained by ext->get(). */
+ /* The vm->retval is already retained by ext_proto->get(). */
}
return sizeof(njs_vmcode_prop_get_t);
njs_vmcode_property_set(njs_vm_t *vm, njs_value_t *object,
njs_value_t *property)
{
+ void *obj;
uintptr_t data;
nxt_str_t s;
njs_ret_t ret;
njs_value_t *p, *value;
- njs_extern_t *ext;
njs_object_prop_t *prop;
+ const njs_extern_t *ext_proto;
njs_property_query_t pq;
njs_vmcode_prop_set_t *code;
return sizeof(njs_vmcode_prop_set_t);
case NJS_EXTERNAL_VALUE:
- ext = object->data.u.external;
+ ext_proto = object->external.proto;
- ret = nxt_lvlhsh_find(&ext->hash, &pq.lhq);
+ ret = nxt_lvlhsh_find(&ext_proto->hash, &pq.lhq);
if (ret == NXT_OK) {
- ext = pq.lhq.value;
- data = ext->data;
+ ext_proto = pq.lhq.value;
+ data = ext_proto->data;
} else {
data = (uintptr_t) &pq.lhq.key;
}
- if (ext->set != NULL) {
+ if (ext_proto->set != NULL) {
ret = njs_vm_value_to_ext_string(vm, &s, value, 0);
if (nxt_slow_path(ret != NXT_OK)) {
return ret;
/* TODO retain value if it is string. */
- ret = ext->set(vm, vm->external[ext->object], data, &s);
+ obj = njs_extern_object(vm, object);
+
+ ret = ext_proto->set(vm, obj, data, &s);
if (nxt_slow_path(ret != NXT_OK)) {
return ret;
}
njs_ret_t
njs_vmcode_property_in(njs_vm_t *vm, njs_value_t *object, njs_value_t *property)
{
+ void *obj;
uintptr_t data;
njs_ret_t ret;
njs_value_t *value;
- njs_extern_t *ext;
const njs_value_t *retval;
+ const njs_extern_t *ext_proto;
njs_property_query_t pq;
retval = &njs_value_false;
break;
case NJS_EXTERNAL_VALUE:
- ext = object->data.u.external;
+ ext_proto = object->external.proto;
- ret = nxt_lvlhsh_find(&ext->hash, &pq.lhq);
+ ret = nxt_lvlhsh_find(&ext_proto->hash, &pq.lhq);
if (ret == NXT_OK) {
retval = &njs_value_true;
} else {
data = (uintptr_t) &pq.lhq.key;
- if (ext->find != NULL) {
- ret = ext->find(vm, vm->external[ext->object], data, 0);
+ if (ext_proto->find != NULL) {
+ obj = njs_extern_object(vm, object);
+
+ ret = ext_proto->find(vm, obj, data, 0);
if (nxt_slow_path(ret == NXT_ERROR)) {
return ret;
njs_vmcode_property_delete(njs_vm_t *vm, njs_value_t *object,
njs_value_t *property)
{
+ void *obj;
uintptr_t data;
njs_ret_t ret;
- njs_value_t *value;
- njs_extern_t *ext;
+ njs_value_t *value, ext_val;
const njs_value_t *retval;
njs_object_prop_t *prop;
+ const njs_extern_t *ext_proto;
njs_property_query_t pq;
retval = &njs_value_false;
case NJS_EXTERNAL_VALUE:
- ext = object->data.u.external;
+ ext_proto = object->external.proto;
- ret = nxt_lvlhsh_find(&ext->hash, &pq.lhq);
+ ret = nxt_lvlhsh_find(&ext_proto->hash, &pq.lhq);
if (ret == NXT_OK) {
- ext = pq.lhq.value;
+ ext_proto = pq.lhq.value;
+
+ if ((ext_proto->type & NJS_EXTERN_OBJECT) != 0) {
+
+ ext_val.type = NJS_EXTERNAL;
+ ext_val.data.truth = 1;
+ ext_val.external.proto = ext_proto;
+ ext_val.external.index = object->external.index;
- if ((ext->type & NJS_EXTERN_OBJECT) != 0) {
- data = (uintptr_t) &ext->value;
+ data = (uintptr_t) &ext_val;
} else {
- data = ext->data;
+ data = ext_proto->data;
}
} else {
data = (uintptr_t) &pq.lhq.key;
}
- if (ext->find != NULL) {
- ret = ext->find(vm, vm->external[ext->object], data, 1);
+ if (ext_proto->find != NULL) {
+ obj = njs_extern_object(vm, object);
+
+ ret = ext_proto->find(vm, obj, data, 1);
if (nxt_slow_path(ret == NXT_ERROR)) {
return ret;
njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *object,
njs_value_t *property)
{
- uint32_t index;
- uint32_t (*hash)(const void *, size_t);
- njs_ret_t ret;
- njs_extern_t *ext;
- njs_object_t *obj;
- njs_function_t *function;
+ uint32_t index;
+ uint32_t (*hash)(const void *, size_t);
+ njs_ret_t ret;
+ njs_object_t *obj;
+ njs_function_t *function;
+ const njs_extern_t *ext_proto;
hash = nxt_djb_hash;
break;
case NJS_EXTERNAL:
- ext = object->data.u.external;
+ ext_proto = object->external.proto;
- if (ext->type == NJS_EXTERN_CASELESS_OBJECT) {
+ if (ext_proto->type == NJS_EXTERN_CASELESS_OBJECT) {
hash = nxt_djb_hash_lowcase;
}
njs_vmcode_property_foreach(njs_vm_t *vm, njs_value_t *object,
njs_value_t *invld)
{
+ void *obj;
njs_ret_t ret;
- njs_extern_t *ext;
njs_property_next_t *next;
+ const njs_extern_t *ext_proto;
njs_vmcode_prop_foreach_t *code;
if (njs_is_object(object)) {
}
} else if (njs_is_external(object)) {
- ext = object->data.u.external;
+ ext_proto = object->external.proto;
- if (ext->foreach != NULL) {
- ret = ext->foreach(vm, vm->external[ext->object], &vm->retval);
+ if (ext_proto->foreach != NULL) {
+ obj = njs_extern_object(vm, object);
+
+ ret = ext_proto->foreach(vm, obj, &vm->retval);
if (nxt_slow_path(ret != NXT_OK)) {
return ret;
}
njs_ret_t
njs_vmcode_property_next(njs_vm_t *vm, njs_value_t *object, njs_value_t *value)
{
+ void *obj;
njs_ret_t ret;
nxt_uint_t n;
njs_value_t *retval;
njs_array_t *array;
- njs_extern_t *ext;
njs_object_prop_t *prop;
njs_property_next_t *next;
+ const njs_extern_t *ext_proto;
njs_vmcode_prop_next_t *code;
code = (njs_vmcode_prop_next_t *) vm->current;
nxt_mem_cache_free(vm->mem_cache_pool, next);
} else if (njs_is_external(object)) {
- ext = object->data.u.external;
+ ext_proto = object->external.proto;
+
+ if (ext_proto->next != NULL) {
+ obj = njs_extern_object(vm, object);
- if (ext->next != NULL) {
- ret = ext->next(vm, retval, vm->external[ext->object], value);
+ ret = ext_proto->next(vm, retval, obj, value);
if (ret == NXT_OK) {
return code->offset;
njs_ret_t
njs_vmcode_method_frame(njs_vm_t *vm, njs_value_t *object, njs_value_t *name)
{
+ void *obj;
njs_ret_t ret;
njs_value_t this, *value;
- njs_extern_t *ext;
njs_object_prop_t *prop;
njs_property_query_t pq;
+ const njs_extern_t *ext_proto;
njs_vmcode_method_frame_t *method;
method = (njs_vmcode_method_frame_t *) vm->current;
break;
case NJS_EXTERNAL_VALUE:
- ext = object->data.u.external;
+ ext_proto = object->external.proto;
- ret = nxt_lvlhsh_find(&ext->hash, &pq.lhq);
+ ret = nxt_lvlhsh_find(&ext_proto->hash, &pq.lhq);
if (nxt_slow_path(ret != NXT_OK)) {
njs_exception_type_error(vm,
}
- ext = pq.lhq.value;
+ ext_proto = pq.lhq.value;
- if (nxt_slow_path(ext->type != NJS_EXTERN_METHOD)) {
+ if (nxt_slow_path(ext_proto->type != NJS_EXTERN_METHOD)) {
njs_exception_type_error(vm,
"method '%.*s' of an external object is not callable",
(int) pq.lhq.key.length, pq.lhq.key.start);
return NXT_ERROR;
}
- this.data.u.data = vm->external[ext->object];
+ obj = njs_extern_object(vm, object);
+
+ this.data.u.data = obj;
- ret = njs_function_native_frame(vm, ext->function, &this, NULL,
+ ret = njs_function_native_frame(vm, ext_proto->function, &this, NULL,
method->nargs, 0, method->code.ctor);
break;
#include <nxt_trace.h>
#include <nxt_queue.h>
#include <nxt_regex.h>
+#include <nxt_random.h>
#define NJS_MAX_STACK_SIZE (16 * 1024 * 1024)
typedef struct njs_regexp_s njs_regexp_t;
typedef struct njs_regexp_pattern_s njs_regexp_pattern_t;
typedef struct njs_date_s njs_date_t;
-typedef struct njs_extern_s njs_extern_t;
typedef struct njs_frame_s njs_frame_t;
typedef struct njs_native_frame_s njs_native_frame_t;
typedef struct njs_property_next_s njs_property_next_t;
njs_regexp_t *regexp;
njs_date_t *date;
njs_getter_t getter;
- njs_extern_t *external;
njs_value_t *value;
njs_property_next_t *next;
void *data;
njs_string_t *data;
} long_string;
+ struct {
+ njs_value_type_t type:8; /* 5 bits */
+ uint8_t truth;
+
+ uint16_t _spare;
+
+ uint32_t index;
+ const njs_extern_t *proto;
+ } external;
+
njs_value_type_t type:8; /* 5 bits */
};
njs_value_t *scopes[NJS_SCOPES];
- void **external;
+ void *external;
njs_native_frame_t *top_frame;
njs_frame_t *active_frame;
+ nxt_array_t *external_objects; /* of void * */
+
nxt_lvlhsh_t externals_hash;
+ nxt_lvlhsh_t external_prototypes_hash;
+
nxt_lvlhsh_t variables_hash;
nxt_lvlhsh_t values_hash;
nxt_lvlhsh_t modules_hash;
nxt_mem_cache_pool_t *mcp;
njs_regexp_pattern_t *pattern;
- mcp = options->mcp;
-
- if (mcp == NULL) {
- mcp = nxt_mem_cache_pool_create(&njs_vm_mem_cache_pool_proto, NULL,
- NULL, 2 * nxt_pagesize(), 128, 512, 16);
- if (nxt_slow_path(mcp == NULL)) {
- return NULL;
- }
+ mcp = nxt_mem_cache_pool_create(&njs_vm_mem_cache_pool_proto, NULL,
+ NULL, 2 * nxt_pagesize(), 128, 512, 16);
+ if (nxt_slow_path(mcp == NULL)) {
+ return NULL;
}
vm = nxt_mem_cache_zalign(mcp, sizeof(njs_value_t), sizeof(njs_vm_t));
if (nxt_slow_path(ret != NXT_OK)) {
return NULL;
}
-
- if (options->externals_hash != NULL) {
- vm->external = options->external;
- }
}
nxt_lvlhsh_init(&vm->values_hash);
- if (options->externals_hash != NULL) {
- vm->externals_hash = *options->externals_hash;
+ vm->external = options->external;
+
+ vm->external_objects = nxt_array_create(4, sizeof(void *),
+ &njs_array_mem_proto,
+ vm->mem_cache_pool);
+ if (nxt_slow_path(vm->external_objects == NULL)) {
+ return NULL;
}
+ nxt_lvlhsh_init(&vm->externals_hash);
+ nxt_lvlhsh_init(&vm->external_prototypes_hash);
+
vm->trace.level = NXT_LEVEL_TRACE;
vm->trace.size = 2048;
vm->trace.handler = njs_parser_trace_handler;
njs_vm_t *
-njs_vm_clone(njs_vm_t *vm, nxt_mem_cache_pool_t *mcp, void **external)
+njs_vm_clone(njs_vm_t *vm, void *external)
{
njs_vm_t *nvm;
+ uint32_t items;
nxt_int_t ret;
nxt_mem_cache_pool_t *nmcp;
return NULL;
}
- nmcp = mcp;
-
- if (nmcp == NULL) {
- nmcp = nxt_mem_cache_pool_create(&njs_vm_mem_cache_pool_proto, NULL,
- NULL, 2 * nxt_pagesize(), 128, 512, 16);
- if (nxt_slow_path(nmcp == NULL)) {
- return NULL;
- }
+ nmcp = nxt_mem_cache_pool_create(&njs_vm_mem_cache_pool_proto, NULL,
+ NULL, 2 * nxt_pagesize(), 128, 512, 16);
+ if (nxt_slow_path(nmcp == NULL)) {
+ return NULL;
}
nvm = nxt_mem_cache_zalloc(nmcp, sizeof(njs_vm_t));
nvm->variables_hash = vm->variables_hash;
nvm->values_hash = vm->values_hash;
nvm->modules_hash = vm->modules_hash;
+
nvm->externals_hash = vm->externals_hash;
+ nvm->external_prototypes_hash = vm->external_prototypes_hash;
+
+ items = vm->external_objects->items;
+ nvm->external_objects = nxt_array_create(items + 4, sizeof(void *),
+ &njs_array_mem_proto,
+ vm->mem_cache_pool);
+ if (nxt_slow_path(vm->external_objects == NULL)) {
+ return NULL;
+ }
+
+ if (items > 0) {
+ memcpy(nvm->external_objects->start, vm->external_objects->start,
+ items * sizeof(void *));
+ vm->external_objects->items = items;
+ }
nvm->current = vm->current;
+
nvm->external = external;
nvm->global_scope = vm->global_scope;
fail:
- if (mcp == NULL) {
- nxt_mem_cache_pool_destroy(nmcp);
- }
+ nxt_mem_cache_pool_destroy(nmcp);
return NULL;
}
}
+nxt_noinline void
+njs_vm_retval_set(njs_vm_t *vm, njs_opaque_value_t *value)
+{
+ vm->retval = *(njs_value_t *) value;
+}
+
+
njs_ret_t njs_vm_retval_to_ext_string(njs_vm_t *vm, nxt_str_t *retval)
{
if (vm->top_frame == NULL) {
typedef uintptr_t njs_index_t;
typedef struct njs_vm_s njs_vm_t;
typedef union njs_value_s njs_value_t;
+typedef struct njs_extern_s njs_extern_t;
typedef struct njs_function_s njs_function_t;
typedef struct njs_vm_shared_s njs_vm_shared_t;
};
typedef struct {
- void **external;
- nxt_lvlhsh_t *externals_hash;
+ void *external;
njs_vm_shared_t *shared;
- nxt_mem_cache_pool_t *mcp;
uint8_t trailer; /* 1 bit */
uint8_t accumulative; /* 1 bit */
#define NJS_DONE NXT_DONE
-NXT_EXPORT nxt_int_t njs_vm_external_add(nxt_lvlhsh_t *hash,
- nxt_mem_cache_pool_t *mcp, uintptr_t object, njs_external_t *external,
- nxt_uint_t n);
-NXT_EXPORT nxt_int_t njs_vm_external(njs_vm_t *vm, njs_opaque_value_t *object,
- nxt_str_t *property, njs_opaque_value_t *value);
-
NXT_EXPORT njs_vm_t *njs_vm_create(njs_vm_opt_t *options);
NXT_EXPORT void njs_vm_destroy(njs_vm_t *vm);
NXT_EXPORT nxt_int_t njs_vm_compile(njs_vm_t *vm, u_char **start, u_char *end);
-NXT_EXPORT njs_vm_t *njs_vm_clone(njs_vm_t *vm, nxt_mem_cache_pool_t *mcp,
- void **external);
+NXT_EXPORT njs_vm_t *njs_vm_clone(njs_vm_t *vm, void *external);
NXT_EXPORT nxt_int_t njs_vm_call(njs_vm_t *vm, njs_function_t *function,
njs_opaque_value_t *args, nxt_uint_t nargs);
NXT_EXPORT nxt_int_t njs_vm_run(njs_vm_t *vm);
+NXT_EXPORT const njs_extern_t *njs_vm_external_prototype(njs_vm_t *vm,
+ njs_external_t *external);
+NXT_EXPORT nxt_int_t njs_vm_external_create(njs_vm_t *vm,
+ njs_opaque_value_t *value, const njs_extern_t *proto, void *object);
+NXT_EXPORT nxt_int_t njs_vm_external_bind(njs_vm_t *vm,
+ const nxt_str_t *var_name, njs_opaque_value_t *value);
+
NXT_EXPORT void njs_disassembler(njs_vm_t *vm);
NXT_EXPORT nxt_array_t *njs_vm_completions(njs_vm_t *vm, nxt_str_t *expression);
NXT_EXPORT njs_function_t *njs_vm_function(njs_vm_t *vm, nxt_str_t *name);
NXT_EXPORT njs_value_t *njs_vm_retval(njs_vm_t *vm);
+NXT_EXPORT void njs_vm_retval_set(njs_vm_t *vm, njs_opaque_value_t *value);
NXT_EXPORT u_char * njs_string_alloc(njs_vm_t *vm, njs_value_t *value,
uint32_t size, uint32_t length);
#include <nxt_stub.h>
#include <nxt_malloc.h>
#include <nxt_array.h>
-#include <nxt_lvlhsh.h>
-#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
-static void *
-njs_alloc(void *mem, size_t size)
-{
- return nxt_malloc(size);
-}
-
-
-static void *
-njs_zalloc(void *mem, size_t size)
-{
- void *p;
-
- p = nxt_malloc(size);
-
- if (p != NULL) {
- memset(p, 0, size);
- }
-
- return p;
-}
-
-
-static void *
-njs_align(void *mem, size_t alignment, size_t size)
-{
- return nxt_memalign(alignment, size);
-}
-
-
-static void
-njs_free(void *mem, void *p)
-{
- nxt_free(p);
-}
-
-
-static const nxt_mem_proto_t njs_mem_cache_pool_proto = {
- njs_alloc,
- njs_zalloc,
- njs_align,
- NULL,
- njs_free,
- NULL,
- NULL,
-};
-
-
static nxt_int_t
njs_unit_test_benchmark(nxt_str_t *script, nxt_str_t *result, const char *msg,
nxt_uint_t n)
{
- u_char *start;
- njs_vm_t *vm, *nvm;
- uint64_t us;
- nxt_int_t ret;
- nxt_str_t s;
- nxt_uint_t i;
- nxt_bool_t success;
- njs_vm_opt_t options;
- struct rusage usage;
- nxt_mem_cache_pool_t *mcp;
-
- mcp = nxt_mem_cache_pool_create(&njs_mem_cache_pool_proto, NULL, NULL,
- 2 * nxt_pagesize(), 128, 512, 16);
- if (nxt_slow_path(mcp == NULL)) {
- return NXT_ERROR;
- }
+ u_char *start;
+ njs_vm_t *vm, *nvm;
+ uint64_t us;
+ nxt_int_t ret, rc;
+ nxt_str_t s;
+ nxt_uint_t i;
+ nxt_bool_t success;
+ njs_vm_opt_t options;
+ struct rusage usage;
memset(&options, 0, sizeof(njs_vm_opt_t));
- options.mcp = mcp;
+ vm = NULL;
+ nvm = NULL;
+ rc = NXT_ERROR;
vm = njs_vm_create(&options);
if (vm == NULL) {
- return NXT_ERROR;
+ printf("njs_vm_create() failed\n");
+ goto done;
}
start = script->start;
ret = njs_vm_compile(vm, &start, start + script->length);
if (ret != NXT_OK) {
- return NXT_ERROR;
+ printf("njs_vm_compile() failed\n");
+ goto done;
}
for (i = 0; i < n; i++) {
- nvm = njs_vm_clone(vm, NULL, NULL);
+ nvm = njs_vm_clone(vm, NULL);
if (nvm == NULL) {
- return NXT_ERROR;
+ printf("njs_vm_clone() failed\n");
+ goto done;
}
(void) njs_vm_run(nvm);
if (njs_vm_retval_to_ext_string(nvm, &s) != NXT_OK) {
- return NXT_ERROR;
+ printf("njs_vm_retval_to_ext_string() failed\n");
+ goto done;
}
success = nxt_strstr_eq(result, &s);
if (!success) {
- return NXT_ERROR;
+ printf("failed: \"%.*s\" vs \"%.*s\"\n",
+ (int) result->length, result->start, (int) s.length,
+ s.start);
+ goto done;
}
njs_vm_destroy(nvm);
+ nvm = NULL;
}
- nxt_mem_cache_pool_destroy(mcp);
-
getrusage(RUSAGE_SELF, &usage);
us = usage.ru_utime.tv_sec * 1000000 + usage.ru_utime.tv_usec
msg, (double) us / n, (int) ((uint64_t) n * 1000000 / us));
}
- return NXT_OK;
+ rc = NXT_OK;
+
+done:
+
+ if (nvm != NULL) {
+ njs_vm_destroy(nvm);
+ }
+
+ if (vm != NULL) {
+ njs_vm_destroy(vm);
+ }
+
+ return rc;
}
#include <nxt_stub.h>
#include <nxt_malloc.h>
#include <nxt_array.h>
-#include <nxt_lvlhsh.h>
-#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <string.h>
#include <stdio.h>
nxt_uint_t i;
nxt_bool_t success;
njs_vm_opt_t options;
- nxt_mem_cache_pool_t *mcp;
njs_interactive_test_t *test;
- mcp = nxt_mem_cache_pool_create(&njs_vm_mem_cache_pool_proto, NULL, NULL,
- 2 * nxt_pagesize(), 128, 512, 16);
- if (nxt_slow_path(mcp == NULL)) {
- return NXT_ERROR;
- }
-
+ vm = NULL;
ret = NXT_ERROR;
for (i = 0; i < nxt_nitems(njs_test); i++) {
memset(&options, 0, sizeof(njs_vm_opt_t));
- options.mcp = mcp;
options.accumulative = 1;
options.backtrace = 1;
vm = njs_vm_create(&options);
if (vm == NULL) {
- goto fail;
+ printf("njs_vm_create() failed\n");
+ goto done;
}
start = test->script.start;
}
if (njs_vm_retval_to_ext_string(vm, &s) != NXT_OK) {
- return NXT_ERROR;
+ printf("njs_vm_retval_to_ext_string() failed\n");
+ goto done;
}
success = nxt_strstr_eq(&test->ret, &s);
if (success) {
+ njs_vm_destroy(vm);
+ vm = NULL;
continue;
}
(int) test->ret.length, test->ret.start,
(int) s.length, s.start);
- goto fail;
+ goto done;
}
ret = NXT_OK;
printf("njs interactive tests passed\n");
-fail:
+done:
- nxt_mem_cache_pool_destroy(mcp);
+ if (vm != NULL) {
+ njs_vm_destroy(vm);
+ }
return ret;
}
#include <nxt_lvlhsh.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
+#include <njs_vm.h>
#include <string.h>
#include <stdio.h>
#include <sys/resource.h>
{ nxt_string("var a = $r.uri, s = a.fromUTF8(); s.length +' '+ s"),
nxt_string("3 АБВ") },
+ { nxt_string("var a = $r.uri, b = $r2.uri, c = $r3.uri; a+b+c"),
+ nxt_string("АБВαβγabc") },
+
+ { nxt_string("var a = $r.uri; $r.uri = $r2.uri; $r2.uri = a; $r2.uri+$r.uri"),
+ nxt_string("АБВαβγ") },
+
{ nxt_string("var a = $r.uri, s = a.fromUTF8(2); s.length +' '+ s"),
nxt_string("2 БВ") },
{ nxt_string("$r.uri = $r.uri.substr(2); $r.uri.length +' '+ $r.uri"),
nxt_string("4 БВ") },
+ { nxt_string("'' + $r.props.a + $r2.props.a + $r.props.a"),
+ nxt_string("121") },
+
+ { nxt_string("var p1 = $r.props, p2 = $r2.props; '' + p2.a + p1.a"),
+ nxt_string("21") },
+
+ { nxt_string("var p1 = $r.props, p2 = $r2.props; '' + p1.a + p2.a"),
+ nxt_string("12") },
+
{ nxt_string("var a = $r.host; a +' '+ a.length +' '+ a"),
nxt_string("АБВГДЕЁЖЗИЙ 22 АБВГДЕЁЖЗИЙ") },
{ nxt_string("$r.some_method('YES')"),
nxt_string("АБВ") },
+ { nxt_string("$r.create('XXX').uri"),
+ nxt_string("XXX") },
+
+ { nxt_string("var sr = $r.create('XXX'); sr.uri = 'YYY'; sr.uri"),
+ nxt_string("YYY") },
+
+ { nxt_string("var sr = $r.create('XXX'), sr2 = $r.create('YYY');"
+ "sr.uri = 'ZZZ'; "
+ "sr.uri + sr2.uri"),
+ nxt_string("ZZZYYY") },
+
{ nxt_string("var p; for (p in $r.some_method);"),
nxt_string("undefined") },
{ nxt_string("'one' in $r"),
nxt_string("false") },
+ { nxt_string("'a' in $r.props"),
+ nxt_string("true") },
+
{ nxt_string("delete $r.uri"),
nxt_string("false") },
typedef struct {
- nxt_mem_cache_pool_t *mem_cache_pool;
nxt_str_t uri;
-} njs_unit_test_req;
+ uint32_t a;
+ nxt_mem_cache_pool_t *mem_cache_pool;
+ const njs_extern_t *proto;
+} njs_unit_test_req_t;
static njs_ret_t
njs_unit_test_r_get_uri_external(njs_vm_t *vm, njs_value_t *value, void *obj,
uintptr_t data)
{
- njs_unit_test_req *r;
+ njs_unit_test_req_t *r;
- r = (njs_unit_test_req *) obj;
+ r = (njs_unit_test_req_t *) obj;
return njs_string_create(vm, value, r->uri.start, r->uri.length, 0);
}
njs_unit_test_r_set_uri_external(njs_vm_t *vm, void *obj, uintptr_t data,
nxt_str_t *value)
{
- njs_unit_test_req *r;
+ njs_unit_test_req_t *r;
+
+ r = (njs_unit_test_req_t *) obj;
- r = (njs_unit_test_req *) obj;
r->uri = *value;
return NXT_OK;
}
+static njs_ret_t
+njs_unit_test_r_get_a_external(njs_vm_t *vm, njs_value_t *value, void *obj,
+ uintptr_t data)
+{
+ char buf[16];
+ size_t len;
+ njs_unit_test_req_t *r;
+
+ r = (njs_unit_test_req_t *) obj;
+
+ len = sprintf(buf, "%u", r->a);
+
+ return njs_string_create(vm, value, (u_char *) buf, len, 0);
+}
+
+
static njs_ret_t
njs_unit_test_host_external(njs_vm_t *vm, njs_value_t *value, void *obj,
uintptr_t data)
njs_unit_test_header_external(njs_vm_t *vm, njs_value_t *value, void *obj,
uintptr_t data)
{
- u_char *s, *p;
- uint32_t size;
- nxt_str_t *h;
- njs_unit_test_req *r;
+ u_char *p;
+ uint32_t size;
+ nxt_str_t *h;
- r = (njs_unit_test_req *) obj;
h = (nxt_str_t *) data;
size = 7 + h->length;
- s = nxt_mem_cache_alloc(r->mem_cache_pool, size);
- if (nxt_slow_path(s == NULL)) {
- return NXT_ERROR;
+ p = njs_string_alloc(vm, value, size, 0);
+ if (p == NULL) {
+ return NJS_ERROR;
}
- p = memcpy(s, h->start, h->length);
- p += h->length;
+ p = nxt_cpymem(p, h->start, h->length);
*p++ = '|';
memcpy(p, "АБВ", 6);
- return njs_string_create(vm, value, s, size, 0);
+ return NJS_OK;
}
njs_unit_test_method_external(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
njs_index_t unused)
{
- nxt_int_t ret;
- nxt_str_t s;
- uintptr_t next;
- njs_unit_test_req *r;
+ nxt_int_t ret;
+ nxt_str_t s;
+ uintptr_t next;
+ njs_unit_test_req_t *r;
next = 0;
}
+static njs_ret_t
+njs_unit_test_create_external(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
+ njs_index_t unused)
+{
+ nxt_int_t ret;
+ nxt_str_t uri;
+ njs_opaque_value_t *value;
+ njs_unit_test_req_t *r, *sr;
+
+ if (nargs > 1) {
+ r = njs_value_data(njs_argument(args, 0));
+
+ if (njs_vm_value_to_ext_string(vm, &uri, njs_argument(args, 1), 0)
+ == NJS_ERROR)
+ {
+ return NJS_ERROR;
+ }
+
+ value = nxt_mem_cache_zalloc(r->mem_cache_pool,
+ sizeof(njs_opaque_value_t));
+ if (value == NULL) {
+ return NXT_ERROR;
+ }
+
+ sr = nxt_mem_cache_zalloc(r->mem_cache_pool,
+ sizeof(njs_unit_test_req_t));
+ if (sr == NULL) {
+ return NXT_ERROR;
+ }
+
+ sr->uri = uri;
+ sr->mem_cache_pool = r->mem_cache_pool;
+ sr->proto = r->proto;
+
+ ret = njs_vm_external_create(vm, value, sr->proto, sr);
+ if (ret != NXT_OK) {
+ return NXT_ERROR;
+ }
+
+ njs_vm_retval_set(vm, value);
+
+ return NXT_OK;
+ }
+
+ return NXT_ERROR;
+}
+
+
+static njs_external_t njs_unit_test_r_props[] = {
+
+ { nxt_string("a"),
+ NJS_EXTERN_PROPERTY,
+ NULL,
+ 0,
+ njs_unit_test_r_get_a_external,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0 },
+};
+
+
static njs_external_t njs_unit_test_r_external[] = {
{ nxt_string("uri"),
NULL,
0 },
+ { nxt_string("props"),
+ NJS_EXTERN_OBJECT,
+ njs_unit_test_r_props,
+ nxt_nitems(njs_unit_test_r_props),
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ 0 },
+
{ nxt_string("header"),
NJS_EXTERN_OBJECT,
NULL,
njs_unit_test_method_external,
0 },
+ { nxt_string("create"),
+ NJS_EXTERN_METHOD,
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ njs_unit_test_create_external,
+ 0 },
+
};
static njs_external_t nxt_test_external[] = {
- { nxt_string("$r"),
+ { nxt_string("request.proto"),
NJS_EXTERN_OBJECT,
njs_unit_test_r_external,
nxt_nitems(njs_unit_test_r_external),
};
-static nxt_int_t
-njs_unit_test_externals(nxt_lvlhsh_t *externals, nxt_mem_cache_pool_t *mcp)
-{
- nxt_lvlhsh_init(externals);
-
- return njs_vm_external_add(externals, mcp, 0, nxt_test_external,
- nxt_nitems(nxt_test_external));
-}
+typedef struct {
+ nxt_str_t name;
+ njs_unit_test_req_t request;
+} njs_unit_test_req_t_init_t;
-static void *
-njs_alloc(void *mem, size_t size)
-{
- return nxt_malloc(size);
-}
+static const njs_unit_test_req_t_init_t nxt_test_requests[] = {
+ { nxt_string("$r"), {.uri = nxt_string("АБВ"), .a = 1}},
+ { nxt_string("$r2"), {.uri = nxt_string("αβγ"), .a = 2}},
+ { nxt_string("$r3"), {.uri = nxt_string("abc"), .a = 3}},
+};
-static void *
-njs_zalloc(void *mem, size_t size)
+static nxt_int_t
+njs_externals_init(njs_vm_t *vm)
{
- void *p;
+ nxt_int_t ret;
+ nxt_uint_t i;
+ const njs_extern_t *proto;
+ njs_opaque_value_t *values;
+ njs_unit_test_req_t *requests;
+
+ proto = njs_vm_external_prototype(vm, &nxt_test_external[0]);
+ if (proto == NULL) {
+ printf("njs_vm_external_prototype() failed\n");
+ return NXT_ERROR;
+ }
- p = nxt_malloc(size);
+ values = nxt_mem_cache_zalloc(vm->mem_cache_pool,
+ nxt_nitems(nxt_test_requests)
+ * sizeof(njs_opaque_value_t));
+ if (values == NULL) {
+ return NXT_ERROR;
+ }
- if (p != NULL) {
- memset(p, 0, size);
+ requests = nxt_mem_cache_zalloc(vm->mem_cache_pool,
+ nxt_nitems(nxt_test_requests)
+ * sizeof(njs_unit_test_req_t));
+ if (requests == NULL) {
+ return NXT_ERROR;
}
- return p;
-}
+ for (i = 0; i < nxt_nitems(nxt_test_requests); i++) {
+ requests[i] = nxt_test_requests[i].request;
+ requests[i].mem_cache_pool = vm->mem_cache_pool;
+ requests[i].proto = proto;
-static void *
-njs_align(void *mem, size_t alignment, size_t size)
-{
- return nxt_memalign(alignment, size);
-}
+ ret = njs_vm_external_create(vm, &values[i], proto, &requests[i]);
+ if (ret != NXT_OK) {
+ printf("njs_vm_external_create() failed\n");
+ return NXT_ERROR;
+ }
+ ret = njs_vm_external_bind(vm, &nxt_test_requests[i].name, &values[i]);
+ if (ret != NXT_OK) {
+ printf("njs_vm_external_bind() failed\n");
+ return NXT_ERROR;
+ }
+ }
-static void
-njs_free(void *mem, void *p)
-{
- nxt_free(p);
+ return NXT_OK;
}
-static const nxt_mem_proto_t njs_mem_cache_pool_proto = {
- njs_alloc,
- njs_zalloc,
- njs_align,
- NULL,
- njs_free,
- NULL,
- NULL,
-};
-
-
static nxt_int_t
njs_unit_test(nxt_bool_t disassemble)
{
- void *ext_object;
- u_char *start;
- njs_vm_t *vm, *nvm;
- nxt_int_t ret;
- nxt_str_t s;
- nxt_uint_t i;
- nxt_bool_t success;
- njs_vm_opt_t options;
- nxt_lvlhsh_t externals;
- njs_unit_test_req r;
- nxt_mem_cache_pool_t *mcp;
+ u_char *start;
+ njs_vm_t *vm, *nvm;
+ nxt_int_t ret, rc;
+ nxt_str_t s;
+ nxt_uint_t i;
+ nxt_bool_t success;
+ njs_vm_opt_t options;
/*
* Chatham Islands NZ-CHAT time zone.
(void) putenv((char *) "TZ=Pacific/Chatham");
tzset();
- mcp = nxt_mem_cache_pool_create(&njs_mem_cache_pool_proto, NULL, NULL,
- 2 * nxt_pagesize(), 128, 512, 16);
- if (nxt_slow_path(mcp == NULL)) {
- return NXT_ERROR;
- }
-
- r.mem_cache_pool = mcp;
- r.uri.length = 6;
- r.uri.start = (u_char *) "АБВ";
- ext_object = &r;
+ vm = NULL;
+ nvm = NULL;
- if (njs_unit_test_externals(&externals, mcp) != NXT_OK) {
- return NXT_ERROR;
- }
+ rc = NXT_ERROR;
for (i = 0; i < nxt_nitems(njs_test); i++) {
memset(&options, 0, sizeof(njs_vm_opt_t));
- options.mcp = mcp;
- options.externals_hash = &externals;
-
vm = njs_vm_create(&options);
if (vm == NULL) {
- return NXT_ERROR;
+ printf("njs_vm_create() failed\n");
+ goto done;
+ }
+
+ ret = njs_externals_init(vm);
+ if (ret != NXT_OK) {
+ goto done;
}
start = njs_test[i].script.start;
fflush(stdout);
}
- nvm = njs_vm_clone(vm, NULL, &ext_object);
+ nvm = njs_vm_clone(vm, NULL);
if (nvm == NULL) {
- return NXT_ERROR;
+ printf("njs_vm_clone() failed\n");
+ goto done;
}
- r.uri.length = 6;
- r.uri.start = (u_char *) "АБВ";
-
ret = njs_vm_run(nvm);
if (njs_vm_retval_to_ext_string(nvm, &s) != NXT_OK) {
- return NXT_ERROR;
+ printf("njs_vm_retval_to_ext_string() failed\n");
+ goto done;
}
} else {
if (njs_vm_retval_to_ext_string(vm, &s) != NXT_OK) {
- return NXT_ERROR;
+ printf("njs_vm_retval_to_ext_string() failed\n");
+ goto done;
}
-
- nvm = NULL;
}
success = nxt_strstr_eq(&njs_test[i].ret, &s);
if (success) {
if (nvm != NULL) {
njs_vm_destroy(nvm);
+ nvm = NULL;
}
+ njs_vm_destroy(vm);
+ vm = NULL;
+
continue;
}
(int) njs_test[i].ret.length, njs_test[i].ret.start,
(int) s.length, s.start);
- return NXT_ERROR;
+ goto done;
+ }
+
+ rc = NXT_OK;
+
+done:
+
+ if (nvm != NULL) {
+ njs_vm_destroy(nvm);
}
- nxt_mem_cache_pool_destroy(mcp);
+ if (vm != NULL) {
+ njs_vm_destroy(vm);
+ }
- printf("njs unit tests passed\n");
+ if (rc == NXT_OK) {
+ printf("njs unit tests passed\n");
+ }
return NXT_OK;
}
NXT_EXPORT void nxt_array_remove(nxt_array_t *array, void *item);
+#define nxt_array_item(array, i) \
+ ((void *) ((char *) (array)->start + (array)->item_size * (i)))
+
+
#define nxt_array_last(array) \
((void *) \
((char *) (array)->start \
nxt_int_t
-nxt_lvlhsh_find(nxt_lvlhsh_t *lh, nxt_lvlhsh_query_t *lhq)
+nxt_lvlhsh_find(const nxt_lvlhsh_t *lh, nxt_lvlhsh_query_t *lhq)
{
void *slot;
void *
-nxt_lvlhsh_each(nxt_lvlhsh_t *lh, nxt_lvlhsh_each_t *lhe)
+nxt_lvlhsh_each(const nxt_lvlhsh_t *lh, nxt_lvlhsh_each_t *lhe)
{
void **slot;
*
* The required nxt_lvlhsh_query_t fields: key_hash, key, proto.
*/
-NXT_EXPORT nxt_int_t nxt_lvlhsh_find(nxt_lvlhsh_t *lh, nxt_lvlhsh_query_t *lhq);
+NXT_EXPORT nxt_int_t nxt_lvlhsh_find(const nxt_lvlhsh_t *lh,
+ nxt_lvlhsh_query_t *lhq);
/*
* nxt_lvlhsh_insert() adds a hash element. If the element already
(lhe)->proto = _proto; \
} while (0)
-NXT_EXPORT void *nxt_lvlhsh_each(nxt_lvlhsh_t *lh, nxt_lvlhsh_each_t *lhe);
+NXT_EXPORT void *nxt_lvlhsh_each(const nxt_lvlhsh_t *lh,
+ nxt_lvlhsh_each_t *lhe);
#endif /* _NXT_LVLHSH_H_INCLUDED_ */