summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_js.c
diff options
context:
space:
mode:
authorZhidao HONG <z.hong@f5.com>2023-05-08 16:00:25 +0800
committerZhidao HONG <z.hong@f5.com>2023-05-08 16:00:25 +0800
commita3c3a29493798873ad04922bb2a7180b2ce267d5 (patch)
tree4332cbb50520c389d859db27e7266ffa53954b92 /src/nxt_js.c
parent56af7bb825c286e1a397f780bff9da275e5602ad (diff)
downloadunit-a3c3a29493798873ad04922bb2a7180b2ce267d5.tar.gz
unit-a3c3a29493798873ad04922bb2a7180b2ce267d5.tar.bz2
NJS: supported loadable modules.
Diffstat (limited to 'src/nxt_js.c')
-rw-r--r--src/nxt_js.c248
1 files changed, 222 insertions, 26 deletions
diff --git a/src/nxt_js.c b/src/nxt_js.c
index 4327e848..df945db6 100644
--- a/src/nxt_js.c
+++ b/src/nxt_js.c
@@ -8,16 +8,72 @@
struct nxt_js_s {
uint32_t index;
- njs_vm_t *vm;
};
+typedef struct {
+ nxt_str_t name;
+ nxt_str_t text;
+} nxt_js_module_t;
+
+
struct nxt_js_conf_s {
nxt_mp_t *pool;
njs_vm_t *vm;
njs_uint_t protos;
njs_external_t *proto;
+ nxt_str_t init;
+ nxt_array_t *modules; /* of nxt_js_module_t */
nxt_array_t *funcs;
+ uint8_t test; /* 1 bit */
+};
+
+
+njs_mod_t *
+nxt_js_module_loader(njs_vm_t *vm, njs_external_ptr_t external, njs_str_t *name)
+{
+ nxt_str_t text;
+ nxt_uint_t i, n;
+ nxt_js_conf_t *jcf;
+ nxt_js_module_t *modules, *module;
+
+ jcf = external;
+
+ module = NULL;
+
+ n = jcf->modules->nelts;
+ modules = jcf->modules->elts;
+
+ for (i = 0; i < n; i++) {
+ if (nxt_strstr_eq(name, &modules[i].name)) {
+ module = &modules[i];
+ break;
+ }
+ }
+
+ if (module == NULL) {
+ return NULL;
+ }
+
+ text.length = module->text.length;
+
+ text.start = njs_mp_alloc(vm->mem_pool, text.length);
+ if (nxt_slow_path(text.start == NULL)) {
+ return NULL;
+ }
+
+ nxt_memcpy(text.start, module->text.start, text.length);
+
+ return njs_vm_compile_module(vm, name, &text.start,
+ &text.start[text.length]);
+}
+
+
+static njs_vm_ops_t nxt_js_ops = {
+ NULL,
+ NULL,
+ nxt_js_module_loader,
+ NULL,
};
@@ -25,9 +81,8 @@ njs_int_t nxt_js_proto_id;
nxt_js_conf_t *
-nxt_js_conf_new(nxt_mp_t *mp)
+nxt_js_conf_new(nxt_mp_t *mp, nxt_bool_t test)
{
- njs_vm_opt_t opts;
nxt_js_conf_t *jcf;
jcf = nxt_mp_zget(mp, sizeof(nxt_js_conf_t));
@@ -36,17 +91,15 @@ nxt_js_conf_new(nxt_mp_t *mp)
}
jcf->pool = mp;
+ jcf->test = test;
- njs_vm_opt_init(&opts);
-
- jcf->vm = njs_vm_create(&opts);
- if (nxt_slow_path(jcf->vm == NULL)) {
+ jcf->modules = nxt_array_create(mp, 4, sizeof(nxt_js_module_t));
+ if (nxt_slow_path(jcf->modules == NULL)) {
return NULL;
}
jcf->funcs = nxt_array_create(mp, 4, sizeof(nxt_str_t));
if (nxt_slow_path(jcf->funcs == NULL)) {
- njs_vm_destroy(jcf->vm);
return NULL;
}
@@ -69,6 +122,115 @@ nxt_js_set_proto(nxt_js_conf_t *jcf, njs_external_t *proto, njs_uint_t n)
}
+static njs_vm_t *
+nxt_js_vm_create(nxt_js_conf_t *jcf)
+{
+ u_char *p;
+ size_t size;
+ nxt_uint_t i;
+ njs_vm_opt_t opts;
+ nxt_js_module_t *module, *mod;
+
+ static nxt_str_t import_str = nxt_string("import");
+ static nxt_str_t from_str = nxt_string("from");
+ static nxt_str_t global_str = nxt_string("globalThis");
+
+ njs_vm_opt_init(&opts);
+
+ opts.backtrace = 1;
+
+ opts.file.start = (u_char *) "default";
+ opts.file.length = 7;
+
+ if (jcf->test || jcf->modules->nelts == 0) {
+ goto done;
+ }
+
+ opts.ops = &nxt_js_ops;
+ opts.external = jcf;
+
+ size = 0;
+ module = jcf->modules->elts;
+
+ for (i = 0; i < jcf->modules->nelts; i++) {
+ mod = &module[i];
+
+ size += import_str.length + 1 + mod->name.length + 1
+ + from_str.length + 2 + mod->name.length + 3;
+
+ size += global_str.length + 1 + mod->name.length + 3
+ + mod->name.length + 2;
+ }
+
+ p = nxt_mp_nget(jcf->pool, size);
+ if (nxt_slow_path(p == NULL)) {
+ return NULL;
+ }
+
+ jcf->init.length = size;
+ jcf->init.start = p;
+
+ for (i = 0; i < jcf->modules->nelts; i++) {
+ mod = &module[i];
+
+ p = nxt_cpymem(p, import_str.start, import_str.length);
+ *p++ = ' ';
+
+ p = nxt_cpymem(p, mod->name.start, mod->name.length);
+ *p++ = ' ';
+
+ p = nxt_cpymem(p, from_str.start, from_str.length);
+ *p++ = ' ';
+
+ *p++ = '\"';
+ p = nxt_cpymem(p, mod->name.start, mod->name.length);
+ *p++ = '\"';
+ *p++ = ';';
+ *p++ = '\n';
+
+ p = nxt_cpymem(p, global_str.start, global_str.length);
+ *p++ = '.';
+
+ p = nxt_cpymem(p, mod->name.start, mod->name.length);
+ *p++ = ' ';
+ *p++ = '=';
+ *p++ = ' ';
+
+ p = nxt_cpymem(p, mod->name.start, mod->name.length);
+ *p++ = ';';
+ *p++ = '\n';
+ }
+
+done:
+
+ return njs_vm_create(&opts);
+}
+
+
+nxt_int_t
+nxt_js_add_module(nxt_js_conf_t *jcf, nxt_str_t *name, nxt_str_t *text)
+{
+ nxt_js_module_t *module;
+
+ module = nxt_array_add(jcf->modules);
+ if (nxt_slow_path(module == NULL)) {
+ return NXT_ERROR;
+ }
+
+ module->name = *name;
+
+ module->text.length = text->length;
+ module->text.start = nxt_mp_nget(jcf->pool, text->length);
+ if (nxt_slow_path(module->text.start == NULL)) {
+ return NXT_ERROR;
+ }
+
+ nxt_memcpy(module->text.start, text->start, text->length);
+
+ return NXT_OK;
+}
+
+
nxt_js_t *
nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz)
{
@@ -113,8 +275,6 @@ nxt_js_add_tpl(nxt_js_conf_t *jcf, nxt_str_t *str, nxt_bool_t strz)
return NULL;
}
- js->vm = jcf->vm;
-
func = nxt_array_add(jcf->funcs);
if (nxt_slow_path(func == NULL)) {
return NULL;
@@ -138,7 +298,16 @@ nxt_js_compile(nxt_js_conf_t *jcf)
nxt_str_t *func;
nxt_uint_t i;
- size = 2;
+ if (jcf->test) {
+ return NXT_OK;
+ }
+
+ jcf->vm = nxt_js_vm_create(jcf);
+ if (nxt_slow_path(jcf->vm == NULL)) {
+ return NXT_ERROR;
+ }
+
+ size = jcf->init.length + 2;
func = jcf->funcs->elts;
for (i = 0; i < jcf->funcs->nelts; i++) {
@@ -150,7 +319,7 @@ nxt_js_compile(nxt_js_conf_t *jcf)
return NXT_ERROR;
}
- p = start;
+ p = nxt_cpymem(start, jcf->init.start, jcf->init.length);
*p++ = '[';
func = jcf->funcs->elts;
@@ -178,37 +347,43 @@ nxt_int_t
nxt_js_test(nxt_js_conf_t *jcf, nxt_str_t *str, u_char *error)
{
u_char *start;
- nxt_str_t err;
+ njs_vm_t *vm;
njs_int_t ret;
- njs_str_t res;
+
+ vm = nxt_js_vm_create(jcf);
+ if (nxt_slow_path(vm == NULL)) {
+ return NXT_ERROR;
+ }
start = nxt_mp_nget(jcf->pool, str->length);
if (nxt_slow_path(start == NULL)) {
- return NXT_ERROR;
+ goto fail;
}
nxt_memcpy(start, str->start, str->length);
- ret = njs_vm_compile(jcf->vm, &start, start + str->length);
+ ret = njs_vm_compile(vm, &start, start + str->length);
if (nxt_slow_path(ret != NJS_OK)) {
- (void) njs_vm_retval_string(jcf->vm, &res);
+ (void) nxt_js_error(vm, error);
+ goto fail;
+ }
+
+ njs_vm_destroy(vm);
- err.start = res.start;
- err.length = res.length;
+ return NXT_OK;
- nxt_sprintf(error, error + NXT_MAX_ERROR_STR, "\"%V\"%Z", &err);
+fail:
- return NXT_ERROR;
- }
+ njs_vm_destroy(vm);
- return NXT_OK;
+ return NXT_ERROR;
}
nxt_int_t
-nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js,
- nxt_str_t *str, void *ctx)
+nxt_js_call(nxt_task_t *task, nxt_js_conf_t *jcf, nxt_js_cache_t *cache,
+ nxt_js_t *js, nxt_str_t *str, void *ctx)
{
njs_vm_t *vm;
njs_int_t rc, ret;
@@ -227,7 +402,7 @@ nxt_js_call(nxt_task_t *task, nxt_js_cache_t *cache, nxt_js_t *js,
vm = cache->vm;
if (vm == NULL) {
- vm = njs_vm_clone(js->vm, ctx);
+ vm = njs_vm_clone(jcf->vm, ctx);
if (nxt_slow_path(vm == NULL)) {
return NXT_ERROR;
}
@@ -314,3 +489,24 @@ nxt_js_release(nxt_js_cache_t *cache)
njs_vm_destroy(cache->vm);
}
}
+
+
+nxt_int_t
+nxt_js_error(njs_vm_t *vm, u_char *error)
+{
+ njs_int_t ret;
+ njs_str_t res;
+ nxt_str_t err;
+
+ ret = njs_vm_retval_string(vm, &res);
+ if (nxt_slow_path(ret != NJS_OK)) {
+ return NXT_ERROR;
+ }
+
+ err.start = res.start;
+ err.length = res.length;
+
+ nxt_sprintf(error, error + NXT_MAX_ERROR_STR, "\"%V\"%Z", &err);
+
+ return NXT_OK;
+}