From: Dmitry Volyntsev Date: Thu, 31 Aug 2017 17:27:31 +0000 (+0300) Subject: Interactive shell: console object. X-Git-Tag: 0.1.13~1 X-Git-Url: http://www.kaiwu.me/postgresql/commit/?a=commitdiff_plain;h=92d8cbb1d350efcfd1051c3829f937c4d0138b3c;p=njs.git Interactive shell: console object. --- diff --git a/nginx/ngx_http_js_module.c b/nginx/ngx_http_js_module.c index e81c3116..e589f11a 100644 --- a/nginx/ngx_http_js_module.c +++ b/nginx/ngx_http_js_module.c @@ -1322,7 +1322,7 @@ ngx_http_js_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_memzero(&options, sizeof(njs_vm_opt_t)); options.mcp = mcp; - options.externals = &externals; + options.externals_hash = &externals; jlcf->vm = njs_vm_create(&options); if (jlcf->vm == NULL) { diff --git a/nginx/ngx_stream_js_module.c b/nginx/ngx_stream_js_module.c index b8f845ff..f734e5a3 100644 --- a/nginx/ngx_stream_js_module.c +++ b/nginx/ngx_stream_js_module.c @@ -1032,7 +1032,7 @@ ngx_stream_js_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_memzero(&options, sizeof(njs_vm_opt_t)); options.mcp = mcp; - options.externals = &externals; + options.externals_hash = &externals; jscf->vm = njs_vm_create(&options); if (jscf->vm == NULL) { diff --git a/njs/njs.c b/njs/njs.c index 6da5884f..f1a404a5 100644 --- a/njs/njs.c +++ b/njs/njs.c @@ -21,9 +21,12 @@ #include #include #include +#include #include #include #include +#include +#include #include #include @@ -54,6 +57,7 @@ typedef struct { 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_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); @@ -64,7 +68,56 @@ static nxt_int_t njs_editline_init(njs_vm_t *vm); static char **njs_completion_handler(const char *text, int start, int end); static char *njs_completion_generator(const char *text, int state); - +static njs_ret_t njs_ext_console_log(njs_vm_t *vm, njs_value_t *args, + nxt_uint_t nargs, njs_index_t unused); +static njs_ret_t njs_ext_console_help(njs_vm_t *vm, njs_value_t *args, + nxt_uint_t nargs, njs_index_t unused); + + +static njs_external_t njs_ext_console[] = { + + { nxt_string("log"), + NJS_EXTERN_METHOD, + NULL, + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + njs_ext_console_log, + 0 }, + + { nxt_string("help"), + NJS_EXTERN_METHOD, + NULL, + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + njs_ext_console_help, + 0 }, +}; + +static njs_external_t njs_externals[] = { + + { nxt_string("console"), + NJS_EXTERN_OBJECT, + njs_ext_console, + nxt_nitems(njs_ext_console), + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + 0 }, +}; + + +static nxt_lvlhsh_t njs_externals_hash; static njs_completion_t njs_completion; @@ -96,6 +149,10 @@ main(int argc, char **argv) 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); @@ -149,6 +206,36 @@ 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) +{ + void **ext; + nxt_uint_t i; + + nxt_lvlhsh_init(&njs_externals_hash); + + 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; + } + } + + ext = nxt_mem_cache_zalloc(vm_options->mcp, sizeof(void *) * i); + if (ext == NULL) { + return NXT_ERROR; + } + + vm_options->external = ext; + vm_options->externals_hash = &njs_externals_hash; + + return NXT_OK; +} + + static nxt_int_t njs_interactive_shell(njs_opts_t *opts, njs_vm_opt_t *vm_options) { @@ -168,7 +255,11 @@ njs_interactive_shell(njs_opts_t *opts, njs_vm_opt_t *vm_options) return NXT_ERROR; } - printf("interactive njscript\n"); + printf("interactive njscript\n\n"); + + printf("v -> the properties of v object.\n"); + printf("v. -> all the available prototype methods.\n"); + printf("type console.help() for more information\n\n"); for ( ;; ) { line.start = (u_char *) readline(">> "); @@ -185,8 +276,8 @@ njs_interactive_shell(njs_opts_t *opts, njs_vm_opt_t *vm_options) ret = njs_process_script(vm, opts, &line, &out); if (ret != NXT_OK) { - printf("njs_process_script() failed\n"); - return NXT_ERROR; + printf("shell: failed to get retval from VM\n"); + continue; } printf("%.*s\n", (int) out.length, out.start); @@ -290,7 +381,7 @@ njs_process_file(njs_opts_t *opts, njs_vm_opt_t *vm_options) ret = njs_process_script(vm, opts, &script, &out); if (ret != NXT_OK) { - fprintf(stderr, "njs_process_script() failed\n"); + fprintf(stderr, "failed to get retval from VM\n"); return NXT_ERROR; } @@ -498,3 +589,58 @@ njs_completion_generator(const char *text, int state) return NULL; } + + +static njs_ret_t +njs_ext_console_log(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, + njs_index_t unused) +{ + nxt_str_t msg; + + msg.length = 0; + + if (nargs >= 2 + && njs_value_to_ext_string(vm, &msg, njs_argument(args, 1)) + == NJS_ERROR) + { + + return NJS_ERROR; + } + + printf("%.*s\n", (int) msg.length, msg.start); + + vm->retval = njs_value_void; + + return NJS_OK; +} + + +static njs_ret_t +njs_ext_console_help(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs, + njs_index_t unused) +{ + nxt_uint_t i; + + printf("VM built-in objects:\n"); + for (i = NJS_CONSTRUCTOR_OBJECT; i < NJS_CONSTRUCTOR_MAX; i++) { + printf(" %.*s\n", (int) njs_constructor_init[i]->name.length, + njs_constructor_init[i]->name.start); + } + + for (i = NJS_OBJECT_THIS; i < NJS_OBJECT_MAX; i++) { + if (njs_object_init[i] != NULL) { + printf(" %.*s\n", (int) njs_object_init[i]->name.length, + njs_object_init[i]->name.start); + } + } + + 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("\n"); + + return NJS_OK; +} diff --git a/njs/njs_builtin.c b/njs/njs_builtin.c index b931856c..53d699a7 100644 --- a/njs/njs_builtin.c +++ b/njs/njs_builtin.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -40,13 +41,13 @@ static nxt_int_t njs_builtin_completions(njs_vm_t *vm, size_t *size, const char **completions); -static const njs_object_init_t *object_init[] = { +const njs_object_init_t *njs_object_init[] = { NULL, /* global this */ &njs_math_object_init, /* Math */ }; -static const njs_object_init_t *prototype_init[] = { +const njs_object_init_t *njs_prototype_init[] = { &njs_object_prototype_init, &njs_array_prototype_init, &njs_boolean_prototype_init, @@ -58,7 +59,7 @@ static const njs_object_init_t *prototype_init[] = { }; -static const njs_object_init_t *constructor_init[] = { +const njs_object_init_t *njs_constructor_init[] = { &njs_object_constructor_init, &njs_array_constructor_init, &njs_boolean_constructor_init, @@ -189,10 +190,10 @@ njs_builtin_objects_create(njs_vm_t *vm) objects = vm->shared->objects; for (i = NJS_OBJECT_THIS; i < NJS_OBJECT_MAX; i++) { - if (object_init[i] != NULL) { + if (njs_object_init[i] != NULL) { ret = njs_object_hash_create(vm, &objects[i].shared_hash, - object_init[i]->properties, - object_init[i]->items); + njs_object_init[i]->properties, + njs_object_init[i]->items); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } @@ -231,8 +232,8 @@ njs_builtin_objects_create(njs_vm_t *vm) prototypes[i] = prototype_values[i]; ret = njs_object_hash_create(vm, &prototypes[i].object.shared_hash, - prototype_init[i]->properties, - prototype_init[i]->items); + njs_prototype_init[i]->properties, + njs_prototype_init[i]->items); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } @@ -257,8 +258,8 @@ njs_builtin_objects_create(njs_vm_t *vm) constructors[i].args_types[4] = native_constructors[i].args_types[4]; ret = njs_object_hash_create(vm, &constructors[i].object.shared_hash, - constructor_init[i]->properties, - constructor_init[i]->items); + njs_constructor_init[i]->properties, + njs_constructor_init[i]->items); if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } @@ -375,11 +376,12 @@ njs_builtin_completions(njs_vm_t *vm, size_t *size, const char **completions) 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; + nxt_lvlhsh_each_t lhe, lhe_prop; njs_object_prototype_t *prototypes; n = 0; @@ -404,7 +406,7 @@ njs_builtin_completions(njs_vm_t *vm, size_t *size, const char **completions) objects = vm->shared->objects; for (i = NJS_OBJECT_THIS; i < NJS_OBJECT_MAX; i++) { - if (object_init[i] == NULL) { + if (njs_object_init[i] == NULL) { continue; } @@ -419,14 +421,14 @@ njs_builtin_completions(njs_vm_t *vm, size_t *size, const char **completions) if (completions != NULL) { njs_string_get(&prop->name, &string); - len = object_init[i]->name.length + string.length + 2; + len = njs_object_init[i]->name.length + string.length + 2; compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len); if (compl == NULL) { return NXT_ERROR; } - snprintf(compl, len, "%s.%s", object_init[i]->name.start, + snprintf(compl, len, "%s.%s", njs_object_init[i]->name.start, string.start); completions[n++] = (char *) compl; @@ -490,15 +492,68 @@ njs_builtin_completions(njs_vm_t *vm, size_t *size, const char **completions) if (completions != NULL) { njs_string_get(&prop->name, &string); - len = constructor_init[i]->name.length + string.length + 2; + len = njs_constructor_init[i]->name.length + string.length + 2; compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len); if (compl == NULL) { return NXT_ERROR; } - snprintf(compl, len, "%s.%s", constructor_init[i]->name.start, - string.start); + snprintf(compl, len, "%s.%s", + njs_constructor_init[i]->name.start, string.start); + + completions[n++] = (char *) compl; + + } else { + n++; + } + } + } + + nxt_lvlhsh_each_init(&lhe, &njs_extern_hash_proto); + + for ( ;; ) { + ext_object = nxt_lvlhsh_each(&vm->externals_hash, &lhe); + + if (ext_object == NULL) { + break; + } + + nxt_lvlhsh_each_init(&lhe_prop, &njs_extern_hash_proto); + + if (completions != NULL) { + len = ext_object->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); + + completions[n++] = (char *) compl; + + } else { + n++; + } + + for ( ;; ) { + ext_prop = nxt_lvlhsh_each(&ext_object->hash, &lhe_prop); + + if (ext_prop == NULL) { + break; + } + + if (completions != NULL) { + len = ext_object->name.length + ext_prop->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); completions[n++] = (char *) compl; @@ -533,7 +588,7 @@ njs_builtin_match_native_function(njs_vm_t *vm, njs_function_t *function, objects = vm->shared->objects; for (i = NJS_OBJECT_THIS; i < NJS_OBJECT_MAX; i++) { - if (object_init[i] == NULL) { + if (njs_object_init[i] == NULL) { continue; } @@ -552,7 +607,7 @@ njs_builtin_match_native_function(njs_vm_t *vm, njs_function_t *function, if (function == prop->value.data.u.function) { njs_string_get(&prop->name, &string); - len = object_init[i]->name.length + string.length + len = njs_object_init[i]->name.length + string.length + sizeof("."); buf = nxt_mem_cache_zalloc(vm->mem_cache_pool, len); @@ -560,7 +615,7 @@ njs_builtin_match_native_function(njs_vm_t *vm, njs_function_t *function, return NXT_ERROR; } - snprintf(buf, len, "%s.%s", object_init[i]->name.start, + snprintf(buf, len, "%s.%s", njs_object_init[i]->name.start, string.start); name->length = len; @@ -589,7 +644,7 @@ njs_builtin_match_native_function(njs_vm_t *vm, njs_function_t *function, if (function == prop->value.data.u.function) { njs_string_get(&prop->name, &string); - len = prototype_init[i]->name.length + string.length + len = njs_prototype_init[i]->name.length + string.length + sizeof(".prototype."); buf = nxt_mem_cache_zalloc(vm->mem_cache_pool, len); @@ -598,7 +653,7 @@ njs_builtin_match_native_function(njs_vm_t *vm, njs_function_t *function, } snprintf(buf, len, "%s.prototype.%s", - prototype_init[i]->name.start, string.start); + njs_prototype_init[i]->name.start, string.start); name->length = len; name->start = (u_char *) buf; @@ -626,7 +681,7 @@ njs_builtin_match_native_function(njs_vm_t *vm, njs_function_t *function, if (function == prop->value.data.u.function) { njs_string_get(&prop->name, &string); - len = constructor_init[i]->name.length + string.length + len = njs_constructor_init[i]->name.length + string.length + sizeof("."); buf = nxt_mem_cache_zalloc(vm->mem_cache_pool, len); @@ -634,7 +689,7 @@ njs_builtin_match_native_function(njs_vm_t *vm, njs_function_t *function, return NXT_ERROR; } - snprintf(buf, len, "%s.%s", constructor_init[i]->name.start, + snprintf(buf, len, "%s.%s", njs_constructor_init[i]->name.start, string.start); name->length = len; diff --git a/njs/njs_builtin.h b/njs/njs_builtin.h new file mode 100644 index 00000000..bac1a8a5 --- /dev/null +++ b/njs/njs_builtin.h @@ -0,0 +1,15 @@ + +/* + * Copyright (C) Dmitry Volyntsev + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NJS_BUILTIN_H_INCLUDED_ +#define _NJS_BUILTIN_H_INCLUDED_ + + +extern const njs_object_init_t *njs_object_init[]; +extern const njs_object_init_t *njs_prototype_init[]; +extern const njs_object_init_t *njs_constructor_init[]; + +#endif /* _NJS_BUILTIN_H_INCLUDED_ */ diff --git a/njs/njscript.c b/njs/njscript.c index c62864bc..4f54dfc7 100644 --- a/njs/njscript.c +++ b/njs/njscript.c @@ -162,12 +162,16 @@ njs_vm_create(njs_vm_opt_t *options) 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 != NULL) { - vm->externals_hash = *options->externals; + if (options->externals_hash != NULL) { + vm->externals_hash = *options->externals_hash; } vm->trace.level = NXT_LEVEL_TRACE; diff --git a/njs/njscript.h b/njs/njscript.h index 45b48527..041f3344 100644 --- a/njs/njscript.h +++ b/njs/njscript.h @@ -66,7 +66,8 @@ struct njs_external_s { }; typedef struct { - nxt_lvlhsh_t *externals; + void **external; + nxt_lvlhsh_t *externals_hash; njs_vm_shared_t *shared; nxt_mem_cache_pool_t *mcp; diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index e3c83a3e..ec07deaa 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -8170,7 +8170,7 @@ njs_unit_test(nxt_bool_t disassemble) memset(&options, 0, sizeof(njs_vm_opt_t)); options.mcp = mcp; - options.externals = &externals; + options.externals_hash = &externals; vm = njs_vm_create(&options); if (vm == NULL) {