#include <nxt_array.h>
#include <nxt_lvlhsh.h>
#include <nxt_random.h>
+#include <nxt_djb_hash.h>
#include <nxt_mem_cache_pool.h>
#include <njscript.h>
#include <njs_vm.h>
+#include <njs_object.h>
+#include <njs_builtin.h>
#include <njs_variable.h>
#include <njs_parser.h>
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);
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;
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)
+{
+ 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)
{
return NXT_ERROR;
}
- printf("interactive njscript\n");
+ printf("interactive njscript\n\n");
+
+ printf("v<Tab> -> the properties of v object.\n");
+ printf("v.<Tab> -> all the available prototype methods.\n");
+ printf("type console.help() for more information\n\n");
for ( ;; ) {
line.start = (u_char *) readline(">> ");
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);
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;
}
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;
+}
#include <njs_array.h>
#include <njs_function.h>
#include <njs_variable.h>
+#include <njs_extern.h>
#include <njs_parser.h>
#include <njs_regexp.h>
#include <njs_date.h>
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,
};
-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,
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;
}
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;
}
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;
}
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;
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;
}
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;
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;
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;
}
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);
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;
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);
}
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;
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);
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;