]> git.kaiwu.me - njs.git/commitdiff
Refactored working with external prototypes.
authorDmitry Volyntsev <xeioex@nginx.com>
Thu, 24 Dec 2020 18:35:18 +0000 (18:35 +0000)
committerDmitry Volyntsev <xeioex@nginx.com>
Thu, 24 Dec 2020 18:35:18 +0000 (18:35 +0000)
Previously, njs_vm_external_prototype() returned the pointer to a
created prototype structure. Which were expected to be passed to
njs_vm_external_create() as is.  The returned pointer is needed to be
stored somewhere by user code which complicates user code in cases when
many prototypes are created.

Instead, an index in the VM internal table is returned.
njs_vm_external_create() is changed accordingly.  This simplifies
user code because the index is known at static time for most cases.

12 files changed:
nginx/ngx_http_js_module.c
nginx/ngx_js.c
nginx/ngx_js.h
nginx/ngx_stream_js_module.c
src/njs.h
src/njs_extern.c
src/njs_shell.c
src/njs_vm.h
src/test/njs_benchmark.c
src/test/njs_externals_test.c
src/test/njs_externals_test.h
src/test/njs_unit_test.c

index 9a6c5cd9c582e092d9342c14fd6ec408b1f151d4..5bf28d3cba0db0e89b79479f50422b365efcd161 100644 (file)
@@ -19,7 +19,6 @@ typedef struct {
     ngx_uint_t             line;
     ngx_array_t           *imports;
     ngx_array_t           *paths;
-    njs_external_proto_t   req_proto;
 } ngx_http_js_main_conf_t;
 
 
@@ -836,7 +835,7 @@ ngx_http_js_init_vm(ngx_http_request_t *r)
     }
 
     rc = njs_vm_external_create(ctx->vm, njs_value_arg(&ctx->request),
-                                jmcf->req_proto, r, 0);
+                                NGX_JS_PROTO_MAIN, r, 0);
     if (rc != NJS_OK) {
         return NGX_ERROR;
     }
@@ -2708,10 +2707,9 @@ ngx_http_js_subrequest_done(ngx_http_request_t *r, void *data, ngx_int_t rc)
 {
     njs_vm_event_t  vm_event = data;
 
-    njs_int_t                 ret;
-    ngx_http_js_ctx_t        *ctx;
-    njs_opaque_value_t        reply;
-    ngx_http_js_main_conf_t  *jmcf;
+    njs_int_t            ret;
+    ngx_http_js_ctx_t   *ctx;
+    njs_opaque_value_t   reply;
 
     if (rc != NGX_OK || r->connection->error || r->buffered) {
         return rc;
@@ -2734,8 +2732,6 @@ ngx_http_js_subrequest_done(ngx_http_request_t *r, void *data, ngx_int_t rc)
 
     ctx->done = 1;
 
-    jmcf = ngx_http_get_module_main_conf(r, ngx_http_js_module);
-
     ctx = ngx_http_get_module_ctx(r->parent, ngx_http_js_module);
 
     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -2750,7 +2746,7 @@ ngx_http_js_subrequest_done(ngx_http_request_t *r, void *data, ngx_int_t rc)
     }
 
     ret = njs_vm_external_create(ctx->vm, njs_value_arg(&reply),
-                                 jmcf->req_proto, r, 0);
+                                 NGX_JS_PROTO_MAIN, r, 0);
     if (ret != NJS_OK) {
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                       "js subrequest reply creation failed");
@@ -2954,7 +2950,7 @@ ngx_http_js_init_main_conf(ngx_conf_t *cf, void *conf)
     ssize_t                n;
     ngx_fd_t               fd;
     ngx_str_t             *m, file;
-    njs_int_t              rc;
+    njs_int_t              rc, proto_id;
     njs_str_t              text, path;
     ngx_uint_t             i;
     njs_value_t           *value;
@@ -2962,7 +2958,6 @@ ngx_http_js_init_main_conf(ngx_conf_t *cf, void *conf)
     ngx_file_info_t        fi;
     ngx_pool_cleanup_t    *cln;
     njs_opaque_value_t     lvalue, exception;
-    njs_external_proto_t   proto;
     ngx_http_js_import_t  *import;
 
     static const njs_str_t line_number_key = njs_str("lineNumber");
@@ -3114,16 +3109,14 @@ ngx_http_js_init_main_conf(ngx_conf_t *cf, void *conf)
         }
     }
 
-    proto = njs_vm_external_prototype(jmcf->vm, ngx_http_js_ext_request,
-                                      njs_nitems(ngx_http_js_ext_request));
-    if (proto == NULL) {
+    proto_id = njs_vm_external_prototype(jmcf->vm, ngx_http_js_ext_request,
+                                         njs_nitems(ngx_http_js_ext_request));
+    if (proto_id < 0) {
         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                       "failed to add js request proto");
         return NGX_CONF_ERROR;
     }
 
-    jmcf->req_proto = proto;
-
     rc = ngx_js_core_init(jmcf->vm, cf->log);
     if (njs_slow_path(rc != NJS_OK)) {
         return NGX_CONF_ERROR;
@@ -3379,7 +3372,6 @@ ngx_http_js_create_main_conf(ngx_conf_t *cf)
      *     conf->include = { 0, NULL };
      *     conf->file = NULL;
      *     conf->line = 0;
-     *     conf->req_proto = NULL;
      */
 
     conf->paths = NGX_CONF_UNSET_PTR;
index 56b2bdd48053a32b97762e819765319f0860bca3..f47b916fdebe0934115b9e8206d82f2e5c235d89 100644 (file)
@@ -117,19 +117,18 @@ ngx_js_string(njs_vm_t *vm, njs_value_t *value, njs_str_t *str)
 ngx_int_t
 ngx_js_core_init(njs_vm_t *vm, ngx_log_t *log)
 {
-    njs_int_t             ret;
-    njs_str_t             name;
-    njs_opaque_value_t    value;
-    njs_external_proto_t  proto;
-
-    proto = njs_vm_external_prototype(vm, ngx_js_ext_core,
-                                      njs_nitems(ngx_js_ext_core));
-    if (proto == NULL) {
+    njs_int_t           ret, proto_id;
+    njs_str_t           name;
+    njs_opaque_value_t  value;
+
+    proto_id = njs_vm_external_prototype(vm, ngx_js_ext_core,
+                                         njs_nitems(ngx_js_ext_core));
+    if (proto_id < 0) {
         ngx_log_error(NGX_LOG_EMERG, log, 0, "failed to add js core proto");
         return NGX_ERROR;
     }
 
-    ret = njs_vm_external_create(vm, njs_value_arg(&value), proto, NULL, 1);
+    ret = njs_vm_external_create(vm, njs_value_arg(&value), proto_id, NULL, 1);
     if (njs_slow_path(ret != NJS_OK)) {
         ngx_log_error(NGX_LOG_EMERG, log, 0,
                       "njs_vm_external_create() failed\n");
index 0e290d5269b2f474b905595a1f602c291902f21a..fe31124491a8193ce9470c7cc46a3573d9ec214c 100644 (file)
@@ -19,6 +19,8 @@
 #define NGX_JS_STRING  1
 #define NGX_JS_BUFFER  2
 
+#define NGX_JS_PROTO_MAIN      0
+
 
 #define ngx_external_connection(vm, ext)                                    \
     (*((ngx_connection_t **) ((u_char *) ext + njs_vm_meta(vm, 0))))
index 0830b10202549e9ca16c207df154d9744975cc5f..91852ba4dd3cf036e530241c26db1fc26789420c 100644 (file)
@@ -19,7 +19,6 @@ typedef struct {
     ngx_uint_t             line;
     ngx_array_t           *imports;
     ngx_array_t           *paths;
-    njs_external_proto_t   proto;
 } ngx_stream_js_main_conf_t;
 
 
@@ -696,7 +695,7 @@ ngx_stream_js_init_vm(ngx_stream_session_t *s)
     }
 
     rc = njs_vm_external_create(ctx->vm, njs_value_arg(&ctx->args[0]),
-                                jmcf->proto, s, 0);
+                                NGX_JS_PROTO_MAIN, s, 0);
     if (rc != NJS_OK) {
         return NGX_ERROR;
     }
@@ -1306,7 +1305,7 @@ ngx_stream_js_init_main_conf(ngx_conf_t *cf, void *conf)
     ssize_t                  n;
     ngx_fd_t                 fd;
     ngx_str_t               *m, file;
-    njs_int_t                rc;
+    njs_int_t                rc, proto_id;
     njs_str_t                text, path;
     ngx_uint_t               i;
     njs_value_t             *value;
@@ -1314,7 +1313,6 @@ ngx_stream_js_init_main_conf(ngx_conf_t *cf, void *conf)
     ngx_file_info_t          fi;
     ngx_pool_cleanup_t      *cln;
     njs_opaque_value_t       lvalue, exception;
-    njs_external_proto_t     proto;
     ngx_stream_js_import_t  *import;
 
     static const njs_str_t line_number_key = njs_str("lineNumber");
@@ -1466,16 +1464,14 @@ ngx_stream_js_init_main_conf(ngx_conf_t *cf, void *conf)
         }
     }
 
-    proto = njs_vm_external_prototype(jmcf->vm, ngx_stream_js_ext_session,
-                                      njs_nitems(ngx_stream_js_ext_session));
-    if (proto == NULL) {
+    proto_id = njs_vm_external_prototype(jmcf->vm, ngx_stream_js_ext_session,
+                                         njs_nitems(ngx_stream_js_ext_session));
+    if (proto_id < 0) {
         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                       "failed to add js request proto");
         return NGX_CONF_ERROR;
     }
 
-    jmcf->proto = proto;
-
     rc = ngx_js_core_init(jmcf->vm, cf->log);
     if (njs_slow_path(rc != NJS_OK)) {
         return NGX_CONF_ERROR;
@@ -1708,7 +1704,6 @@ ngx_stream_js_create_main_conf(ngx_conf_t *cf)
      *     conf->include = { 0, NULL };
      *     conf->file = NULL;
      *     conf->line = 0;
-     *     conf->proto = NULL;
      */
 
     conf->paths = NGX_CONF_UNSET_PTR;
index 42261a6f8fff7ce23e7a7f0bc789008ae8928664..7af86fa543f4a1e7f4dae29df1e4251133a82eab 100644 (file)
--- a/src/njs.h
+++ b/src/njs.h
@@ -29,7 +29,6 @@ typedef struct njs_function_s       njs_function_t;
 typedef struct njs_vm_shared_s      njs_vm_shared_t;
 typedef struct njs_object_prop_s    njs_object_prop_t;
 typedef struct njs_external_s       njs_external_t;
-typedef void *                      njs_external_proto_t;
 
 /*
  * njs_opaque_value_t is the external storage type for native njs_value_t type.
@@ -297,10 +296,10 @@ NJS_EXPORT njs_int_t njs_vm_start(njs_vm_t *vm);
 
 NJS_EXPORT njs_int_t njs_vm_add_path(njs_vm_t *vm, const njs_str_t *path);
 
-NJS_EXPORT njs_external_proto_t njs_vm_external_prototype(njs_vm_t *vm,
+NJS_EXPORT njs_int_t njs_vm_external_prototype(njs_vm_t *vm,
     const njs_external_t *definition, njs_uint_t n);
 NJS_EXPORT njs_int_t njs_vm_external_create(njs_vm_t *vm, njs_value_t *value,
-    njs_external_proto_t proto, njs_external_ptr_t external, njs_bool_t shared);
+    njs_int_t proto_id, njs_external_ptr_t external, njs_bool_t shared);
 NJS_EXPORT njs_external_ptr_t njs_vm_external(njs_vm_t *vm,
     const njs_value_t *value);
 NJS_EXPORT uintptr_t njs_vm_meta(njs_vm_t *vm, njs_uint_t index);
index a2dfd01f86694ef2b48f4171c2699f428f909d8f..a5de5b47e2a93d8bb9d938369ea882b48649e239 100644 (file)
@@ -256,12 +256,13 @@ njs_external_protos(const njs_external_t *external, njs_uint_t size)
 }
 
 
-njs_external_proto_t
+njs_int_t
 njs_vm_external_prototype(njs_vm_t *vm, const njs_external_t *definition,
     njs_uint_t n)
 {
     njs_arr_t   *protos;
     njs_int_t   ret;
+    uintptr_t   *pr;
     njs_uint_t  size;
 
     size = njs_external_protos(definition, n) + 1;
@@ -269,38 +270,55 @@ njs_vm_external_prototype(njs_vm_t *vm, const njs_external_t *definition,
     protos = njs_arr_create(vm->mem_pool, size, sizeof(njs_exotic_slots_t));
     if (njs_slow_path(protos == NULL)) {
         njs_memory_error(vm);
-        return NULL;
+        return -1;
     }
 
     ret = njs_external_add(vm, protos, definition, n);
     if (njs_slow_path(ret != NJS_OK)) {
         njs_internal_error(vm, "njs_vm_external_add() failed");
-        return NULL;
+        return -1;
+    }
+
+    if (vm->protos == NULL) {
+        vm->protos = njs_arr_create(vm->mem_pool, 4, sizeof(uintptr_t));
+        if (njs_slow_path(vm->protos == NULL)) {
+            return -1;
+        }
     }
 
-    return protos;
+    pr = njs_arr_add(vm->protos);
+    if (njs_slow_path(pr == NULL)) {
+        return -1;
+    }
+
+    *pr = (uintptr_t) protos;
+
+    return vm->protos->items - 1;
 }
 
 
 njs_int_t
-njs_vm_external_create(njs_vm_t *vm, njs_value_t *value,
-    njs_external_proto_t proto, njs_external_ptr_t external, njs_bool_t shared)
+njs_vm_external_create(njs_vm_t *vm, njs_value_t *value, njs_int_t proto_id,
+    njs_external_ptr_t external, njs_bool_t shared)
 {
     njs_arr_t           *protos;
+    uintptr_t           proto;
     njs_object_value_t  *ov;
     njs_exotic_slots_t  *slots;
 
-    if (njs_slow_path(proto == NULL)) {
+    if (vm->protos == NULL || (njs_int_t) vm->protos->items <= proto_id) {
         return NJS_ERROR;
     }
 
+    proto = ((uintptr_t *) vm->protos->start)[proto_id];
+
     ov = njs_mp_alloc(vm->mem_pool, sizeof(njs_object_value_t));
     if (njs_slow_path(ov == NULL)) {
         njs_memory_error(vm);
         return NJS_ERROR;
     }
 
-    protos = proto;
+    protos = (njs_arr_t *) proto;
     slots = protos->start;
 
     njs_lvlhsh_init(&ov->object.hash);
index 8a878428ab2d21aa8f13e25d61ae3b20a5ace6ad..be7a90dffbbf041319669104b367ca368528edf7 100644 (file)
@@ -653,12 +653,11 @@ static njs_value_t *
 njs_external_add(njs_vm_t *vm, njs_external_t *definition,
     njs_uint_t n, const njs_str_t *name, njs_external_ptr_t external)
 {
-    njs_int_t             ret;
-    njs_value_t           *value;
-    njs_external_proto_t  proto;
+    njs_int_t    ret, proto_id;
+    njs_value_t  *value;
 
-    proto = njs_vm_external_prototype(vm, definition, n);
-    if (njs_slow_path(proto == NULL)) {
+    proto_id = njs_vm_external_prototype(vm, definition, n);
+    if (njs_slow_path(proto_id < 0)) {
         njs_stderror("failed to add \"%V\" proto\n", name);
         return NULL;
     }
@@ -668,7 +667,7 @@ njs_external_add(njs_vm_t *vm, njs_external_t *definition,
         return NULL;
     }
 
-    ret = njs_vm_external_create(vm, value, proto, external, 0);
+    ret = njs_vm_external_create(vm, value, proto_id, external, 0);
     if (njs_slow_path(ret != NJS_OK)) {
         return NULL;
     }
index 872762138c6dbe53d6d1e0d6a1862622105c7f99..3f63b7abe31e687a3b0a79ce70b1f709887f9235 100644 (file)
@@ -180,6 +180,7 @@ struct njs_vm_s {
     njs_value_t              retval;
 
     njs_arr_t                *paths;
+    njs_arr_t                *protos;
 
     njs_value_t              *scopes[NJS_SCOPES];
 
index 0025f3559ba53ed9a1f1e3fe034b14cf94eef96f..688503de19574371275be8e6e1177306b8dd469c 100644 (file)
@@ -36,13 +36,12 @@ njs_benchmark_test(njs_vm_t *parent, njs_opts_t *opts, njs_value_t *report,
     u_char                *start;
     njs_vm_t              *vm, *nvm;
     uint64_t              us;
-    njs_int_t             ret;
+    njs_int_t             ret, proto_id;
     njs_str_t             s, *expected;
     njs_uint_t            i, n;
     njs_bool_t            success;
     njs_value_t           *result, name, usec, times;
     njs_vm_opt_t          options;
-    njs_external_proto_t  proto;
 
     static const njs_value_t  name_key = njs_string("name");
     static const njs_value_t  usec_key = njs_string("usec");
@@ -68,8 +67,8 @@ njs_benchmark_test(njs_vm_t *parent, njs_opts_t *opts, njs_value_t *report,
         goto done;
     }
 
-    proto = njs_externals_shared_init(vm);
-    if (proto == NULL) {
+    proto_id = njs_externals_shared_init(vm);
+    if (proto_id < 0) {
         goto done;
     }
 
index cdb89dab948c70a7e0d24988596633a3e8595ef5..f87e38119ebea651c9cb20a4366fe617e569e6e0 100644 (file)
@@ -11,7 +11,7 @@
 
 typedef struct {
     njs_lvlhsh_t          hash;
-    njs_external_proto_t  proto;
+    njs_int_t             proto_id;
 
     uint32_t              a;
     uint32_t              d;
@@ -394,9 +394,9 @@ njs_unit_test_r_create(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
         return NJS_ERROR;
     }
 
-    sr->proto = r->proto;
+    sr->proto_id = r->proto_id;
 
-    ret = njs_vm_external_create(vm, &vm->retval, sr->proto, sr, 0);
+    ret = njs_vm_external_create(vm, &vm->retval, sr->proto_id, sr, 0);
     if (ret != NJS_OK) {
         return NJS_ERROR;
     }
@@ -678,8 +678,8 @@ static njs_unit_test_req_init_t njs_test_requests[] = {
 };
 
 
-static njs_external_proto_t
-njs_externals_init_internal(njs_vm_t *vm, njs_external_proto_t proto,
+static njs_int_t
+njs_externals_init_internal(njs_vm_t *vm, njs_int_t proto_id,
     njs_unit_test_req_init_t *init, njs_uint_t n, njs_bool_t shared)
 {
     njs_int_t             ret;
@@ -687,37 +687,37 @@ njs_externals_init_internal(njs_vm_t *vm, njs_external_proto_t proto,
     njs_unit_test_req_t   *requests;
     njs_unit_test_prop_t  *prop;
 
-    if (proto == NULL) {
-        proto = njs_vm_external_prototype(vm, njs_unit_test_r_external,
-                                          njs_nitems(njs_unit_test_r_external));
-        if (njs_slow_path(proto == NULL)) {
+    if (proto_id == -1) {
+        proto_id = njs_vm_external_prototype(vm, njs_unit_test_r_external,
+                                         njs_nitems(njs_unit_test_r_external));
+        if (njs_slow_path(proto_id < 0)) {
             njs_printf("njs_vm_external_prototype() failed\n");
-            return NULL;
+            return -1;
         }
     }
 
     requests = njs_mp_zalloc(vm->mem_pool, n * sizeof(njs_unit_test_req_t));
     if (njs_slow_path(requests == NULL)) {
-        return NULL;
+        return -1;
     }
 
     for (i = 0; i < n; i++) {
 
         requests[i] = init[i].request;
-        requests[i].proto = proto;
+        requests[i].proto_id = proto_id;
 
         ret = njs_vm_external_create(vm, njs_value_arg(&requests[i].value),
-                                     proto, &requests[i], shared);
+                                     proto_id, &requests[i], shared);
         if (njs_slow_path(ret != NJS_OK)) {
             njs_printf("njs_vm_external_create() failed\n");
-            return NULL;
+            return -1;
         }
 
         ret = njs_vm_bind(vm, &init[i].name, njs_value_arg(&requests[i].value),
                           shared);
         if (njs_slow_path(ret != NJS_OK)) {
             njs_printf("njs_vm_bind() failed\n");
-            return NULL;
+            return -1;
         }
 
         for (j = 0; j < njs_nitems(init[i].props); j++) {
@@ -726,33 +726,34 @@ njs_externals_init_internal(njs_vm_t *vm, njs_external_proto_t proto,
 
             if (njs_slow_path(prop == NULL)) {
                 njs_printf("lvlhsh_unit_test_alloc() failed\n");
-                return NULL;
+                return -1;
             }
 
             ret = lvlhsh_unit_test_add(vm->mem_pool, &requests[i], prop);
             if (njs_slow_path(ret != NJS_OK)) {
                 njs_printf("lvlhsh_unit_test_add() failed\n");
-                return NULL;
+                return -1;
             }
         }
     }
 
-    return proto;
+    return proto_id;
 }
 
 
-njs_external_proto_t
+njs_int_t
 njs_externals_shared_init(njs_vm_t *vm)
 {
-    return njs_externals_init_internal(vm, NULL, njs_test_requests, 1, 1);
+    return njs_externals_init_internal(vm, -1, njs_test_requests, 1, 1);
 }
 
 
 njs_int_t
-njs_externals_init(njs_vm_t *vm, njs_external_proto_t proto)
+njs_externals_init(njs_vm_t *vm, njs_int_t proto_id)
 {
-    proto = njs_externals_init_internal(vm, proto, &njs_test_requests[1], 3, 0);
-    if (proto == NULL) {
+    proto_id = njs_externals_init_internal(vm, proto_id, &njs_test_requests[1],
+                                        3, 0);
+    if (proto_id < 0) {
         return NJS_ERROR;
     }
 
index 97553b5facbcac295d594fe5b9d7de6829b2eb0f..2253b4db164d32f1fe486da8bc2fe36d35a73f13 100644 (file)
@@ -8,8 +8,8 @@
 #define _NJS_EXTERNALS_TEST_H_INCLUDED_
 
 
-njs_external_proto_t njs_externals_shared_init(njs_vm_t *vm);
-njs_int_t njs_externals_init(njs_vm_t *vm, njs_external_proto_t proto);
+njs_int_t njs_externals_shared_init(njs_vm_t *vm);
+njs_int_t njs_externals_init(njs_vm_t *vm, njs_int_t proto_id);
 
 
 #endif /* _NJS_EXTERNALS_TEST_H_INCLUDED_ */
index 5109d3a10dea3a7ce3c94c9c1415ba9a6c867ebb..4cd63257b6815278b993c065e751a02e9654c794 100644 (file)
@@ -20483,19 +20483,18 @@ static njs_int_t
 njs_unit_test(njs_unit_test_t tests[], size_t num, njs_str_t *name,
     njs_opts_t *opts, njs_stat_t *stat)
 {
-    u_char                *start, *end;
-    njs_vm_t              *vm, *nvm;
-    njs_int_t             ret;
-    njs_str_t             s;
-    njs_uint_t            i, repeat;
-    njs_stat_t            prev;
-    njs_bool_t            success;
-    njs_vm_opt_t          options;
-    njs_external_proto_t  proto;
+    u_char        *start, *end;
+    njs_vm_t      *vm, *nvm;
+    njs_int_t     ret, proto_id;
+    njs_str_t     s;
+    njs_uint_t    i, repeat;
+    njs_stat_t    prev;
+    njs_bool_t    success;
+    njs_vm_opt_t  options;
 
     vm = NULL;
     nvm = NULL;
-    proto = NULL;
+    proto_id = -1;
 
     prev = *stat;
 
@@ -20519,8 +20518,8 @@ njs_unit_test(njs_unit_test_t tests[], size_t num, njs_str_t *name,
         }
 
         if (opts->externals) {
-            proto = njs_externals_shared_init(vm);
-            if (proto == NULL) {
+            proto_id = njs_externals_shared_init(vm);
+            if (proto_id < 0) {
                 goto done;
             }
         }
@@ -20549,7 +20548,7 @@ njs_unit_test(njs_unit_test_t tests[], size_t num, njs_str_t *name,
                 }
 
                 if (opts->externals) {
-                    ret = njs_externals_init(nvm, proto);
+                    ret = njs_externals_init(nvm, proto_id);
                     if (ret != NJS_OK) {
                         goto done;
                     }
@@ -20653,7 +20652,7 @@ njs_interactive_test(njs_unit_test_t tests[], size_t num, njs_str_t *name,
         }
 
         if (opts->externals) {
-            ret = njs_externals_init(vm, NULL);
+            ret = njs_externals_init(vm, -1);
             if (ret != NJS_OK) {
                 goto done;
             }