details: https://hg.nginx.org/njs/rev/fc8d1b125cef branches: changeset: 2111:fc8d1b125cef user: Dmitry Volyntsev <xei...@nginx.com> date: Tue May 09 18:18:33 2023 -0700 description: Shell: CLIs is rewritten using public API.
diffstat: auto/make | 8 +- external/njs_shell.c | 1591 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/njs.h | 6 +- src/njs_builtin.c | 2 +- src/njs_shell.c | 1578 ------------------------------------------------- src/njs_vm.c | 10 + src/njs_vm.h | 2 - 7 files changed, 1609 insertions(+), 1588 deletions(-) diffs (truncated from 3268 to 1000 lines): diff -r d610d744bbd2 -r fc8d1b125cef auto/make --- a/auto/make Mon May 08 22:03:32 2023 -0700 +++ b/auto/make Tue May 09 18:18:33 2023 -0700 @@ -104,10 +104,10 @@ cat << END >> $NJS_MAKEFILE $NJS_BUILD_DIR/njs: \\ $NJS_BUILD_DIR/libnjs.a \\ - src/njs_shell.c + external/njs_shell.c \$(NJS_LINK) -o $NJS_BUILD_DIR/njs \$(NJS_CFLAGS) \\ $NJS_LIB_AUX_CFLAGS \$(NJS_LIB_INCS) -Injs \\ - src/njs_shell.c \\ + external/njs_shell.c \\ $NJS_BUILD_DIR/libnjs.a \\ $NJS_LD_OPT -lm $NJS_LIBS $NJS_LIB_AUX_LIBS $NJS_READLINE_LIB @@ -118,12 +118,12 @@ END cat << END >> $NJS_MAKEFILE $NJS_BUILD_DIR/njs_process_script_fuzzer.o: \\ - src/njs_shell.c + external/njs_shell.c \$(NJS_CC) -c \$(CFLAGS) $NJS_LIB_AUX_CFLAGS \\ \$(NJS_LIB_INCS) -Injs \\ -DNJS_FUZZER_TARGET \\ -o $NJS_BUILD_DIR/njs_process_script_fuzzer.o \\ - src/njs_shell.c + external/njs_shell.c $NJS_BUILD_DIR/njs_process_script_fuzzer: \\ $NJS_BUILD_DIR/libnjs.a \\ diff -r d610d744bbd2 -r fc8d1b125cef external/njs_shell.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/external/njs_shell.c Tue May 09 18:18:33 2023 -0700 @@ -0,0 +1,1591 @@ + +/* + * Copyright (C) Dmitry Volyntsev + * Copyright (C) NGINX, Inc. + */ + + +#include <njs.h> +#include <njs_unix.h> +#include <njs_time.h> +#include <njs_arr.h> +#include <njs_queue.h> +#include <njs_rbtree.h> +#include <njs_lvlhsh.h> +#include <njs_djb_hash.h> + +#if (!defined NJS_FUZZER_TARGET && defined NJS_HAVE_READLINE) + +#include <locale.h> +#include <signal.h> +#include <sys/select.h> +#if (NJS_HAVE_EDITLINE) +#include <editline/readline.h> +#elif (NJS_HAVE_EDIT_READLINE) +#include <edit/readline/readline.h> +#else +#include <readline/readline.h> +#if (NJS_HAVE_GNU_READLINE) +#include <readline/history.h> +#endif +#endif + +#endif + + +typedef void (*njs_console_output_pt)(njs_vm_t *vm, njs_value_t *value, + njs_int_t ret); + + +typedef struct { + uint8_t disassemble; + uint8_t denormals; + uint8_t interactive; + uint8_t module; + uint8_t quiet; + uint8_t sandbox; + uint8_t safe; + uint8_t version; + uint8_t ast; + uint8_t unhandled_rejection; + uint8_t opcode_debug; + uint8_t generator_debug; + int exit_code; + int stack_size; + + char *file; + char *command; + size_t n_paths; + char **paths; + char **argv; + njs_uint_t argc; +} njs_opts_t; + + +typedef struct { + size_t index; + size_t length; + njs_arr_t *completions; + njs_arr_t *suffix_completions; + njs_rbtree_node_t *node; + + enum { + NJS_COMPLETION_SUFFIX = 0, + NJS_COMPLETION_GLOBAL + } phase; +} njs_completion_t; + + +typedef struct { + njs_vm_event_t vm_event; + njs_queue_link_t link; +} njs_ev_t; + + +typedef struct { + njs_opaque_value_t name; + uint64_t time; +} njs_timelabel_t; + + +typedef struct { + njs_vm_t *vm; + + njs_lvlhsh_t events; /* njs_ev_t * */ + njs_queue_t posted_events; + + njs_lvlhsh_t labels; /* njs_timelabel_t */ + + njs_completion_t completion; +} njs_console_t; + + +static njs_int_t njs_console_init(njs_vm_t *vm, njs_console_t *console); +static void njs_console_output(njs_vm_t *vm, njs_value_t *value, + njs_int_t ret); +static njs_int_t njs_externals_init(njs_vm_t *vm); +static njs_vm_t *njs_create_vm(njs_opts_t *opts, njs_vm_opt_t *vm_options); +static void njs_process_output(njs_vm_t *vm, njs_value_t *value, njs_int_t ret); +static njs_int_t njs_process_script(njs_vm_t *vm, void *runtime, + const njs_str_t *script); + +#ifndef NJS_FUZZER_TARGET + +static njs_int_t njs_options_parse(njs_opts_t *opts, int argc, char **argv); +static void njs_options_free(njs_opts_t *opts); +static njs_int_t njs_process_file(njs_opts_t *opts, njs_vm_opt_t *vm_options); + +#ifdef NJS_HAVE_READLINE +static njs_int_t njs_interactive_shell(njs_opts_t *opts, + njs_vm_opt_t *vm_options); +static njs_int_t njs_editline_init(void); +static char *njs_completion_generator(const char *text, int state); +#endif + +#endif + +static njs_int_t njs_ext_console_log(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t indent, njs_value_t *retval); +static njs_int_t njs_ext_console_time(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); +static njs_int_t njs_ext_console_time_end(njs_vm_t *vm, njs_value_t *args, + njs_uint_t nargs, njs_index_t unused, njs_value_t *retval); + +static njs_host_event_t njs_console_set_timer(njs_external_ptr_t external, + uint64_t delay, njs_vm_event_t vm_event); + +static void njs_console_clear_timer(njs_external_ptr_t external, + njs_host_event_t event); +static void njs_console_log(njs_vm_t *vm, njs_external_ptr_t external, + njs_log_level_t level, const u_char *start, size_t length); + +static njs_int_t njs_timelabel_hash_test(njs_lvlhsh_query_t *lhq, void *data); + +static njs_int_t lvlhsh_key_test(njs_lvlhsh_query_t *lhq, void *data); +static void *lvlhsh_pool_alloc(void *pool, size_t size); +static void lvlhsh_pool_free(void *pool, void *p, size_t size); + + +static njs_external_t njs_ext_console[] = { + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("dump"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = njs_ext_console_log, + .magic8 = 1, + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("log"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = njs_ext_console_log, + } + }, + + { + .flags = NJS_EXTERN_PROPERTY | NJS_EXTERN_SYMBOL, + .name.symbol = NJS_SYMBOL_TO_STRING_TAG, + .u.property = { + .value = "Console", + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("time"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = njs_ext_console_time, + } + }, + + { + .flags = NJS_EXTERN_METHOD, + .name.string = njs_str("timeEnd"), + .writable = 1, + .configurable = 1, + .enumerable = 1, + .u.method = { + .native = njs_ext_console_time_end, + } + }, + +}; + + +static const njs_lvlhsh_proto_t lvlhsh_proto njs_aligned(64) = { + NJS_LVLHSH_LARGE_SLAB, + lvlhsh_key_test, + lvlhsh_pool_alloc, + lvlhsh_pool_free, +}; + + +static const njs_lvlhsh_proto_t njs_timelabel_hash_proto njs_aligned(64) = { + NJS_LVLHSH_DEFAULT, + njs_timelabel_hash_test, + lvlhsh_pool_alloc, + lvlhsh_pool_free, +}; + + +static njs_vm_ops_t njs_console_ops = { + njs_console_set_timer, + njs_console_clear_timer, + NULL, + njs_console_log, +}; + + +njs_module_t njs_console_module = { + .name = njs_str("console"), + .init = njs_externals_init, +}; + + +static njs_module_t *njs_console_addon_modules[] = { + &njs_console_module, + NULL, +}; + + +static njs_int_t njs_console_proto_id; + + +static njs_console_t njs_console; + + +#ifndef NJS_FUZZER_TARGET + +int +main(int argc, char **argv) +{ + njs_vm_t *vm; + njs_int_t ret; + njs_opts_t opts; + njs_str_t command; + njs_vm_opt_t vm_options; + + static uintptr_t uptr[] = { + (uintptr_t) njs_console_output, + }; + + static njs_vm_meta_t metas = { + .size = njs_nitems(uptr), + .values = uptr + }; + + njs_memzero(&opts, sizeof(njs_opts_t)); + opts.interactive = 1; + + ret = njs_options_parse(&opts, argc, argv); + if (ret != NJS_OK) { + ret = (ret == NJS_DONE) ? NJS_OK : NJS_ERROR; + goto done; + } + + if (opts.version != 0) { + njs_printf("%s\n", NJS_VERSION); + ret = NJS_OK; + goto done; + } + + njs_mm_denormals(opts.denormals); + + njs_vm_opt_init(&vm_options); + + if (opts.file == NULL) { + opts.file = (opts.command == NULL) ? (char *) "shell" + : (char *) "string"; + } + + vm_options.file.start = (u_char *) opts.file; + vm_options.file.length = njs_strlen(opts.file); + + vm_options.init = 1; + vm_options.interactive = opts.interactive; + vm_options.disassemble = opts.disassemble; + vm_options.backtrace = 1; + vm_options.quiet = opts.quiet; + vm_options.sandbox = opts.sandbox; + vm_options.unsafe = !opts.safe; + vm_options.module = opts.module; +#ifdef NJS_DEBUG_GENERATOR + vm_options.generator_debug = opts.generator_debug; +#endif +#ifdef NJS_DEBUG_OPCODE + vm_options.opcode_debug = opts.opcode_debug; +#endif + + vm_options.ops = &njs_console_ops; + vm_options.addons = njs_console_addon_modules; + vm_options.metas = &metas; + vm_options.external = &njs_console; + vm_options.argv = opts.argv; + vm_options.argc = opts.argc; + vm_options.ast = opts.ast; + vm_options.unhandled_rejection = opts.unhandled_rejection; + + if (opts.stack_size != 0) { + vm_options.max_stack_size = opts.stack_size; + } + +#ifdef NJS_HAVE_READLINE + + if (opts.interactive) { + ret = njs_interactive_shell(&opts, &vm_options); + + } else + +#endif + + if (opts.command) { + vm = njs_create_vm(&opts, &vm_options); + if (vm != NULL) { + command.start = (u_char *) opts.command; + command.length = njs_strlen(opts.command); + ret = njs_process_script(vm, njs_vm_external_ptr(vm), &command); + njs_vm_destroy(vm); + } + + } else { + ret = njs_process_file(&opts, &vm_options); + } + +done: + + njs_options_free(&opts); + + return (ret == NJS_OK) ? EXIT_SUCCESS : opts.exit_code; +} + + +static njs_int_t +njs_options_parse(njs_opts_t *opts, int argc, char **argv) +{ + char *p, **paths; + njs_int_t i, ret; + njs_uint_t n; + + static const char help[] = + "njs [options] [-c string | script.js | -] [script args]\n" + "\n" + "Interactive shell: " +#ifdef NJS_HAVE_READLINE + "enabled\n" +#else + "disabled\n" +#endif + "\n" + "Options:\n" + " -a print AST.\n" + " -c specify the command to execute.\n" + " -d print disassembled code.\n" + " -e <code> set failure exit code.\n" + " -f disabled denormals mode.\n" +#ifdef NJS_DEBUG_GENERATOR + " -g enable generator debug.\n" +#endif + " -j <size> set the maximum stack size in bytes.\n" +#ifdef NJS_DEBUG_OPCODE + " -o enable opcode debug.\n" +#endif + " -p <path> set path prefix for modules.\n" + " -q disable interactive introduction prompt.\n" + " -r ignore unhandled promise rejection.\n" + " -s sandbox mode.\n" + " -t script|module source code type (script is default).\n" + " -v print njs version and exit.\n" + " -u disable \"unsafe\" mode.\n" + " script.js | - run code from a file or stdin.\n"; + + ret = NJS_DONE; + + opts->denormals = 1; + opts->exit_code = EXIT_FAILURE; + opts->unhandled_rejection = NJS_VM_OPT_UNHANDLED_REJECTION_THROW; + + p = getenv("NJS_EXIT_CODE"); + if (p != NULL) { + opts->exit_code = atoi(p); + } + + for (i = 1; i < argc; i++) { + + p = argv[i]; + + if (p[0] != '-' || (p[0] == '-' && p[1] == '\0')) { + opts->interactive = 0; + opts->file = argv[i]; + goto done; + } + + p++; + + switch (*p) { + case '?': + case 'h': + njs_printf("%*s", njs_length(help), help); + return ret; + + case 'a': + opts->ast = 1; + break; + + case 'c': + opts->interactive = 0; + + if (++i < argc) { + opts->command = argv[i]; + goto done; + } + + njs_stderror("option \"-c\" requires argument\n"); + return NJS_ERROR; + + case 'd': + opts->disassemble = 1; + break; + + case 'e': + if (++i < argc) { + opts->exit_code = atoi(argv[i]); + break; + } + + njs_stderror("option \"-e\" requires argument\n"); + return NJS_ERROR; + + case 'f': + +#if !(NJS_HAVE_DENORMALS_CONTROL) + njs_stderror("option \"-f\" is not supported\n"); + return NJS_ERROR; +#endif + + opts->denormals = 0; + break; + +#ifdef NJS_DEBUG_GENERATOR + case 'g': + opts->generator_debug = 1; + break; +#endif + case 'j': + if (++i < argc) { + opts->stack_size = atoi(argv[i]); + break; + } + + njs_stderror("option \"-j\" requires argument\n"); + return NJS_ERROR; + +#ifdef NJS_DEBUG_OPCODE + case 'o': + opts->opcode_debug = 1; + break; +#endif + + case 'p': + if (++i < argc) { + opts->n_paths++; + paths = realloc(opts->paths, opts->n_paths * sizeof(char *)); + if (paths == NULL) { + njs_stderror("failed to add path\n"); + return NJS_ERROR; + } + + opts->paths = paths; + opts->paths[opts->n_paths - 1] = argv[i]; + break; + } + + njs_stderror("option \"-p\" requires directory name\n"); + return NJS_ERROR; + + case 'q': + opts->quiet = 1; + break; + + case 'r': + opts->unhandled_rejection = NJS_VM_OPT_UNHANDLED_REJECTION_IGNORE; + break; + + case 's': + opts->sandbox = 1; + break; + + case 't': + if (++i < argc) { + if (strcmp(argv[i], "module") == 0) { + opts->module = 1; + + } else if (strcmp(argv[i], "script") != 0) { + njs_stderror("option \"-t\" unexpected source type: %s\n", + argv[i]); + return NJS_ERROR; + } + + break; + } + + njs_stderror("option \"-t\" requires source type\n"); + return NJS_ERROR; + case 'v': + case 'V': + opts->version = 1; + break; + + case 'u': + opts->safe = 1; + break; + + default: + njs_stderror("Unknown argument: \"%s\" " + "try \"%s -h\" for available options\n", argv[i], + argv[0]); + return NJS_ERROR; + } + } + +done: + + opts->argc = njs_max(argc - i + 1, 2); + opts->argv = malloc(sizeof(char*) * opts->argc); + if (opts->argv == NULL) { + njs_stderror("failed to alloc argv\n"); + return NJS_ERROR; + } + + opts->argv[0] = argv[0]; + opts->argv[1] = (opts->file != NULL) ? opts->file : (char *) ""; + for (n = 2; n < opts->argc; n++) { + opts->argv[n] = argv[i + n - 1]; + } + + return NJS_OK; +} + + +static void +njs_options_free(njs_opts_t *opts) +{ + if (opts->paths != NULL) { + free(opts->paths); + } + + if (opts->argv != NULL) { + free(opts->argv); + } +} + + +static njs_int_t +njs_process_file(njs_opts_t *opts, njs_vm_opt_t *vm_options) +{ + int fd; + char *file; + u_char *p, *end, *start; + size_t size; + ssize_t n; + njs_vm_t *vm; + njs_int_t ret; + njs_str_t source, script; + struct stat sb; + u_char buf[4096]; + + file = opts->file; + + if (file[0] == '-' && file[1] == '\0') { + fd = STDIN_FILENO; + + } else { + fd = open(file, O_RDONLY); + if (fd == -1) { + njs_stderror("failed to open file: '%s' (%s)\n", + file, strerror(errno)); + return NJS_ERROR; + } + } + + if (fstat(fd, &sb) == -1) { + njs_stderror("fstat(%d) failed while reading '%s' (%s)\n", + fd, file, strerror(errno)); + ret = NJS_ERROR; + goto close_fd; + } + + size = sizeof(buf); + + if (S_ISREG(sb.st_mode) && sb.st_size) { + size = sb.st_size; + } + + vm = NULL; + + source.length = 0; + source.start = realloc(NULL, size); + if (source.start == NULL) { + njs_stderror("alloc failed while reading '%s'\n", file); + ret = NJS_ERROR; + goto done; + } + + p = source.start; + end = p + size; + + for ( ;; ) { + n = read(fd, buf, sizeof(buf)); + + if (n == 0) { + break; + } + + if (n < 0) { + njs_stderror("failed to read file: '%s' (%s)\n", + file, strerror(errno)); + ret = NJS_ERROR; + goto done; + } + + if (p + n > end) { + size *= 2; + + start = realloc(source.start, size); + if (start == NULL) { + njs_stderror("alloc failed while reading '%s'\n", file); + ret = NJS_ERROR; + goto done; + } + + source.start = start; + + p = source.start + source.length; + end = source.start + size; + } + + memcpy(p, buf, n); + + p += n; + source.length += n; + } + + vm = njs_create_vm(opts, vm_options); + if (vm == NULL) { + ret = NJS_ERROR; + goto done; + } + + script = source; + + /* shebang */ + + if (script.length > 2 && memcmp(script.start, "#!", 2) == 0) { + p = njs_strlchr(script.start, script.start + script.length, '\n'); + + if (p != NULL) { + script.length -= (p + 1 - script.start); + script.start = p + 1; + + } else { + script.length = 0; + } + } + + ret = njs_process_script(vm, vm_options->external, &script); + if (ret != NJS_OK) { + ret = NJS_ERROR; + goto done; + } + + ret = NJS_OK; + +done: + + if (vm != NULL) { + njs_vm_destroy(vm); + } + + if (source.start != NULL) { + free(source.start); + } + +close_fd: + + if (fd != STDIN_FILENO) { + (void) close(fd); + } + + return ret; +} + +#else + +int +LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) +{ + njs_vm_t *vm; + njs_opts_t opts; + njs_str_t script; + njs_vm_opt_t vm_options; + + static uintptr_t uptr[] = { + (uintptr_t) NULL, + }; + + static njs_vm_meta_t metas = { + .size = njs_nitems(uptr), + .values = uptr + }; + + if (size == 0) { + return 0; + } + + njs_memzero(&opts, sizeof(njs_opts_t)); + + njs_vm_opt_init(&vm_options); + + vm_options.init = 1; + vm_options.backtrace = 0; + vm_options.metas = &metas; + vm_options.ops = &njs_console_ops; + + vm = njs_create_vm(&opts, &vm_options); + + if (njs_fast_path(vm != NULL)) { + script.length = size; + script.start = (u_char *) data; + + (void) njs_process_script(vm, NULL, &script); + njs_vm_destroy(vm); + } + + return 0; +} + +#endif + +static njs_int_t +njs_console_init(njs_vm_t *vm, njs_console_t *console) +{ + console->vm = vm; + + njs_lvlhsh_init(&console->events); + njs_queue_init(&console->posted_events); + + njs_lvlhsh_init(&console->labels); + + console->completion.completions = njs_vm_completions(vm, NULL); + if (console->completion.completions == NULL) { + return NJS_ERROR; + } + + return NJS_OK; +} + + +static njs_int_t +njs_externals_init(njs_vm_t *vm) +{ + njs_int_t ret; + njs_value_t *value; + njs_console_t *console; + njs_opaque_value_t method; + + static const njs_str_t console_name = njs_str("console"); + static const njs_str_t print_name = njs_str("print"); + static const njs_str_t console_log = njs_str("console.log"); + + console = njs_vm_options(vm)->external; + + njs_console_proto_id = njs_vm_external_prototype(vm, njs_ext_console, + njs_nitems(njs_ext_console)); + if (njs_slow_path(njs_console_proto_id < 0)) { + njs_stderror("failed to add \"console\" proto\n"); + return NJS_ERROR; + } + + value = njs_mp_zalloc(njs_vm_memory_pool(vm), sizeof(njs_opaque_value_t)); + if (njs_slow_path(value == NULL)) { + return NJS_ERROR; + } + + ret = njs_vm_external_create(vm, value, njs_console_proto_id, console, 0); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + ret = njs_vm_bind(vm, &console_name, value, 0); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + ret = njs_vm_value(vm, &console_log, njs_value_arg(&method)); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + ret = njs_vm_bind(vm, &print_name, njs_value_arg(&method), 0); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + ret = njs_console_init(vm, console); + if (njs_slow_path(ret != NJS_OK)) { + return NJS_ERROR; + } + + return NJS_OK; +} + + +static njs_vm_t * +njs_create_vm(njs_opts_t *opts, njs_vm_opt_t *vm_options) +{ + u_char *p, *start; + njs_vm_t *vm; + njs_int_t ret; + njs_str_t path; + njs_uint_t i; + + vm = njs_vm_create(vm_options); + if (vm == NULL) { + njs_stderror("failed to create vm\n"); + return NULL; + } + + for (i = 0; i < opts->n_paths; i++) { + path.start = (u_char *) opts->paths[i]; + path.length = njs_strlen(opts->paths[i]); + + ret = njs_vm_add_path(vm, &path); + if (ret != NJS_OK) { + njs_stderror("failed to add path\n"); + return NULL; + } + } + + start = (u_char *) getenv("NJS_PATH"); + if (start == NULL) { + return vm; + } + + for ( ;; ) { + p = njs_strchr(start, ':'); + + path.start = start; + path.length = (p != NULL) ? (size_t) (p - start) : njs_strlen(start); + + ret = njs_vm_add_path(vm, &path); + if (ret != NJS_OK) { + njs_stderror("failed to add path\n"); + return NULL; + } + + if (p == NULL) { + break; + } + + start = p + 1; + } + + return vm; +} + + +static void +njs_console_output(njs_vm_t *vm, njs_value_t *value, njs_int_t ret) +{ + njs_str_t out; + + if (ret == NJS_OK) { + if (njs_vm_value_dump(vm, &out, value, 0, 1) != NJS_OK) { + njs_stderror("Shell:failed to get retval from VM\n"); + return; + } + + if (njs_vm_options(vm)->interactive) { + njs_print(out.start, out.length); + njs_print("\n", 1); + } + + } else { + njs_vm_exception_string(vm, &out); + njs_stderror("Thrown:\n%V\n", &out); + } +} + + +static njs_int_t +njs_process_events(void *runtime) +{ + njs_ev_t *ev; + njs_queue_t *events; + njs_console_t *console; + njs_queue_link_t *link; + + if (runtime == NULL) { + njs_stderror("njs_process_events(): no runtime\n"); + return NJS_ERROR; + } + + console = runtime; + + events = &console->posted_events; + + for ( ;; ) { + link = njs_queue_first(events); + + if (link == njs_queue_tail(events)) { + break; + } + + ev = njs_queue_link_data(link, njs_ev_t, link); + + njs_queue_remove(&ev->link); + ev->link.prev = NULL; + ev->link.next = NULL; + + njs_vm_post_event(console->vm, ev->vm_event, NULL, 0); + } + + return NJS_OK; +} + + +static njs_int_t +njs_process_script(njs_vm_t *vm, void *runtime, const njs_str_t *script) +{ + u_char *start, *end; + njs_int_t ret; + njs_opaque_value_t retval; + + start = script->start; + end = start + script->length; + + ret = njs_vm_compile(vm, &start, end); + + if (ret == NJS_OK) { + if (start == end) { + ret = njs_vm_start(vm, njs_value_arg(&retval)); + + } else { + njs_vm_error(vm, "Extra characters at the end of the script"); _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel