[PATCH] New directive to configure TLSv1.3 ciphers

Ramprasad Tamilselvan ramprasad.tamilselvan at quantil.com
Thu Nov 15 18:55:27 UTC 2018


Thanks for the clarification.
In this case, I think the patch is not required.

Regards,
Ramprasad

> On Nov 15, 2018, at 9:32 AM, nginx-devel-request at nginx.org wrote:
> 
> Send nginx-devel mailing list submissions to
> 	nginx-devel at nginx.org
> 
> To subscribe or unsubscribe via the World Wide Web, visit
> 	http://mailman.nginx.org/mailman/listinfo/nginx-devel
> or, via email, send a message with subject or body 'help' to
> 	nginx-devel-request at nginx.org
> 
> You can reach the person managing the list at
> 	nginx-devel-owner at nginx.org
> 
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of nginx-devel digest..."
> 
> 
> Today's Topics:
> 
>   1. [nginx] Core: free shared memory on cycle initialization
>      failure. (Ruslan Ermilov)
>   2. Re: [PATCH] New directive to configure TLSv1.3 ciphers
>      (Maxim Dounin)
>   3. [njs] console.time() and console.timeEnd() methods.
>      (Dmitry Volyntsev)
>   4. [njs] Fixed global objects. (Dmitry Volyntsev)
>   5. [njs] Improved handling of builtin objects. (Dmitry Volyntsev)
> 
> 
> ----------------------------------------------------------------------
> 
> Message: 1
> Date: Thu, 15 Nov 2018 14:19:57 +0000
> From: Ruslan Ermilov <ru at nginx.com>
> To: nginx-devel at nginx.org
> Subject: [nginx] Core: free shared memory on cycle initialization
> 	failure.
> Message-ID:
> 	<hg.650574a44505.1542291597.6026610855610030274 at dev.nginx.com>
> Content-Type: text/plain; charset="us-ascii"
> 
> details:   http://hg.nginx.org/nginx/rev/650574a44505
> branches:  
> changeset: 7394:650574a44505
> user:      Ruslan Ermilov <ru at nginx.com>
> date:      Thu Nov 15 15:28:54 2018 +0300
> description:
> Core: free shared memory on cycle initialization failure.
> 
> diffstat:
> 
> src/core/ngx_cycle.c |  64 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 64 insertions(+), 0 deletions(-)
> 
> diffs (81 lines):
> 
> diff -r 4698cede59ff -r 650574a44505 src/core/ngx_cycle.c
> --- a/src/core/ngx_cycle.c	Mon Nov 12 16:29:30 2018 +0300
> +++ b/src/core/ngx_cycle.c	Thu Nov 15 15:28:54 2018 +0300
> @@ -843,6 +843,69 @@ failed:
>         }
>     }
> 
> +    /* free the newly created shared memory */
> +
> +    part = &cycle->shared_memory.part;
> +    shm_zone = part->elts;
> +
> +    for (i = 0; /* void */ ; i++) {
> +
> +        if (i >= part->nelts) {
> +            if (part->next == NULL) {
> +                break;
> +            }
> +            part = part->next;
> +            shm_zone = part->elts;
> +            i = 0;
> +        }
> +
> +        if (shm_zone[i].shm.addr == NULL) {
> +            continue;
> +        }
> +
> +        opart = &old_cycle->shared_memory.part;
> +        oshm_zone = opart->elts;
> +
> +        for (n = 0; /* void */ ; n++) {
> +
> +            if (n >= opart->nelts) {
> +                if (opart->next == NULL) {
> +                    break;
> +                }
> +                opart = opart->next;
> +                oshm_zone = opart->elts;
> +                n = 0;
> +            }
> +
> +            if (shm_zone[i].shm.name.len != oshm_zone[n].shm.name.len) {
> +                continue;
> +            }
> +
> +            if (ngx_strncmp(shm_zone[i].shm.name.data,
> +                            oshm_zone[n].shm.name.data,
> +                            shm_zone[i].shm.name.len)
> +                != 0)
> +            {
> +                continue;
> +            }
> +
> +            if (shm_zone[i].tag == oshm_zone[n].tag
> +                && shm_zone[i].shm.size == oshm_zone[n].shm.size
> +                && !shm_zone[i].noreuse)
> +            {
> +                goto old_shm_zone_found;
> +            }
> +
> +            break;
> +        }
> +
> +        ngx_shm_free(&shm_zone[i].shm);
> +
> +    old_shm_zone_found:
> +
> +        continue;
> +    }
> +
>     if (ngx_test_config) {
>         ngx_destroy_cycle_pools(&conf);
>         return NULL;
> @@ -1274,6 +1337,7 @@ ngx_shared_memory_add(ngx_conf_t *cf, ng
> 
>     shm_zone->data = NULL;
>     shm_zone->shm.log = cf->cycle->log;
> +    shm_zone->shm.addr = NULL;
>     shm_zone->shm.size = size;
>     shm_zone->shm.name = *name;
>     shm_zone->shm.exists = 0;
> 
> 
> ------------------------------
> 
> Message: 2
> Date: Thu, 15 Nov 2018 17:53:53 +0300
> From: Maxim Dounin <mdounin at mdounin.ru>
> To: nginx-devel at nginx.org
> Subject: Re: [PATCH] New directive to configure TLSv1.3 ciphers
> Message-ID: <20181115145353.GA99070 at mdounin.ru>
> Content-Type: text/plain; charset=us-ascii
> 
> Hello!
> 
> On Wed, Nov 14, 2018 at 05:24:52PM -0800, Ramprasad Tamilselvan wrote:
> 
>> # HG changeset patch
>> # User Ramprasad Tamilselvan <ramprasad.tamilselvan at quantil.com>
>> # Date 1542241466 28800
>> #      Wed Nov 14 16:24:26 2018 -0800
>> # Node ID 83b05772dbd657b31df16d712a64c908c371f0d9
>> # Parent  4698cede59ffa438bcae1fd6c5d8fec4d69b2c92
>> New directive to configure TLSv1.3 ciphers.
>> 
>> In openssl 1.1.1, a new API is introduced to configure ciphers
>> for TLSv1.3. A new directive ssl_ciphersuites will call the new
>> API to configure the ciphers for TLSv1.3.
> 
> Thank you for your patch.
> 
> I do object introducing a new directive for this, see this ticket 
> for details:
> 
> https://trac.nginx.org/nginx/ticket/1529
> 
> -- 
> Maxim Dounin
> http://mdounin.ru/
> 
> 
> ------------------------------
> 
> Message: 3
> Date: Thu, 15 Nov 2018 17:32:02 +0000
> From: Dmitry Volyntsev <xeioex at nginx.com>
> To: nginx-devel at nginx.org
> Subject: [njs] console.time() and console.timeEnd() methods.
> Message-ID:
> 	<hg.46632012ac03.1542303122.5965299922797593991 at dev.nginx.com>
> Content-Type: text/plain; charset="utf-8"
> 
> details:   http://hg.nginx.org/njs/rev/46632012ac03
> branches:  
> changeset: 653:46632012ac03
> user:      Artem S. Povalyukhin <artem.povaluhin at gmail.com>
> date:      Wed Nov 14 18:14:49 2018 +0300
> description:
> console.time() and console.timeEnd() methods.
> 
> This fixes #62 issue on Github.
> 
> diffstat:
> 
> njs/njs_shell.c              |  86 ++++++++++++++++++++++++++++++++++++++++++++
> njs/test/njs_expect_test.exp |  18 ++++++++-
> 2 files changed, 103 insertions(+), 1 deletions(-)
> 
> diffs (156 lines):
> 
> diff -r 7f0f7d149709 -r 46632012ac03 njs/njs_shell.c
> --- a/njs/njs_shell.c	Thu Nov 15 12:45:02 2018 +0300
> +++ b/njs/njs_shell.c	Wed Nov 14 18:14:49 2018 +0300
> @@ -14,6 +14,7 @@
> #include <fcntl.h>
> #include <stdlib.h>
> #include <sys/stat.h>
> +#include <sys/time.h>
> #include <locale.h>
> 
> #include <readline.h>
> @@ -63,6 +64,10 @@ static njs_ret_t njs_ext_console_dump(nj
>     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_ret_t njs_ext_console_time(njs_vm_t *vm, njs_value_t *args,
> +    nxt_uint_t nargs, njs_index_t unused);
> +static njs_ret_t njs_ext_console_time_end(njs_vm_t *vm, njs_value_t *args,
> +    nxt_uint_t nargs, njs_index_t unused);
> 
> 
> static njs_external_t  njs_ext_console[] = {
> @@ -102,6 +107,30 @@ static njs_external_t  njs_ext_console[]
>       NULL,
>       njs_ext_console_help,
>       0 },
> +
> +    { nxt_string("time"),
> +      NJS_EXTERN_METHOD,
> +      NULL,
> +      0,
> +      NULL,
> +      NULL,
> +      NULL,
> +      NULL,
> +      NULL,
> +      njs_ext_console_time,
> +      0 },
> +
> +    { nxt_string("timeEnd"),
> +      NJS_EXTERN_METHOD,
> +      NULL,
> +      0,
> +      NULL,
> +      NULL,
> +      NULL,
> +      NULL,
> +      NULL,
> +      njs_ext_console_time_end,
> +      0 },
> };
> 
> static njs_external_t  njs_externals[] = {
> @@ -123,6 +152,9 @@ static njs_external_t  njs_externals[] =
> static njs_completion_t  njs_completion;
> 
> 
> +static struct timeval njs_console_time;
> +
> +
> int
> main(int argc, char **argv)
> {
> @@ -727,3 +759,57 @@ njs_ext_console_help(njs_vm_t *vm, njs_v
> 
>     return NJS_OK;
> }
> +
> +
> +static njs_ret_t
> +njs_ext_console_time(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
> +    njs_index_t unused)
> +{
> +    if (!njs_value_is_void(njs_arg(args, nargs, 1))) {
> +        njs_vm_error(vm, "labels not implemented");
> +        return NJS_ERROR;
> +    }
> +
> +    vm->retval = njs_value_void;
> +
> +    gettimeofday(&njs_console_time, NULL);
> +
> +    return NJS_OK;
> +}
> +
> +
> +static njs_ret_t
> +njs_ext_console_time_end(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
> +    njs_index_t unused)
> +{
> +    int64_t         us, ms;
> +    struct timeval  tv;
> +
> +    gettimeofday(&tv, NULL);
> +
> +    if (!njs_value_is_void(njs_arg(args, nargs, 1))) {
> +        njs_vm_error(vm, "labels not implemented");
> +        return NJS_ERROR;
> +    }
> +
> +    if (nxt_fast_path(njs_console_time.tv_sec || njs_console_time.tv_usec)) {
> +
> +        us = ((int64_t) tv.tv_sec - njs_console_time.tv_sec) * 1000000
> +             + ((int64_t) tv.tv_usec - njs_console_time.tv_usec);
> +
> +        ms = us / 1000;
> +        us = us % 1000;
> +
> +        printf("default: %" PRIu64 ".%03" PRIu64 "ms\n", ms, us);
> +
> +        njs_console_time.tv_sec = 0;
> +        njs_console_time.tv_usec = 0;
> +
> +    } else {
> +        printf("Timer \"default\" doesn?t exist.\n");
> +    }
> +
> +    vm->retval = njs_value_void;
> +
> +    return NJS_OK;
> +}
> diff -r 7f0f7d149709 -r 46632012ac03 njs/test/njs_expect_test.exp
> --- a/njs/test/njs_expect_test.exp	Thu Nov 15 12:45:02 2018 +0300
> +++ b/njs/test/njs_expect_test.exp	Wed Nov 14 18:14:49 2018 +0300
> @@ -80,7 +80,7 @@ njs_test {
> # Global completions, multiple partial match
> njs_test {
>     {"cons\t\t"
> -     "console*console.help*console.log*const"}
> +     "console*console.help*console.time*const"}
> }
> 
> njs_test {
> @@ -190,6 +190,22 @@ njs_test {
>      "console.help()\r\nVM built-in objects:"}
> }
> 
> +# console.time* functions
> +njs_test {
> +    {"console.time()\r\n"
> +     "console.time()\r\nundefined\r\n>> "}
> +    {"console.time(undefined)\r\n"
> +     "console.time(undefined)\r\nundefined\r\n>> "}
> +    {"console.timeEnd()\r\n"
> +     "console.timeEnd()\r\ndefault: *.*ms\r\nundefined\r\n>> "}
> +    {"console.time('a')\r\n"
> +     "console.time('a')\r\nError: labels not implemented"}
> +    {"console.timeEnd('a')\r\n"
> +     "console.timeEnd('a')\r\nError: labels not implemented"}
> +    {"console.timeEnd()\r\n"
> +     "console.timeEnd()\r\nTimer \"default\" doesn?t exist."}
> +}
> +
> njs_test {
>     {"console.ll()\r\n"
>      "console.ll()\r\nTypeError: 'll' is not a function"}
> 
> ------------------------------
> 
> Message: 4
> Date: Thu, 15 Nov 2018 17:32:02 +0000
> From: Dmitry Volyntsev <xeioex at nginx.com>
> To: nginx-devel at nginx.org
> Subject: [njs] Fixed global objects.
> Message-ID:
> 	<hg.e11011d45499.1542303122.5965299922797593991 at dev.nginx.com>
> Content-Type: text/plain; charset="us-ascii"
> 
> details:   http://hg.nginx.org/njs/rev/e11011d45499
> branches:  
> changeset: 655:e11011d45499
> user:      Dmitry Volyntsev <xeioex at nginx.com>
> date:      Thu Nov 15 20:31:35 2018 +0300
> description:
> Fixed global objects.
> 
>    1) Making it extensible.
>    2) Adding default properties according to ES5.1:15.1.1.
> 
> diffstat:
> 
> njs/njs_builtin.c        |  27 +++++++++++++++++++++++++--
> njs/test/njs_unit_test.c |  30 ++++++++++++++++++++++++++++++
> 2 files changed, 55 insertions(+), 2 deletions(-)
> 
> diffs (91 lines):
> 
> diff -r 2711e84ede6a -r e11011d45499 njs/njs_builtin.c
> --- a/njs/njs_builtin.c	Wed Apr 04 17:38:10 2018 +0300
> +++ b/njs/njs_builtin.c	Thu Nov 15 20:31:35 2018 +0300
> @@ -276,6 +276,7 @@ njs_builtin_objects_create(njs_vm_t *vm)
>         }
> 
>         object->shared = 1;
> +        object->extensible = 1;
> 
>         object++;
>     }
> @@ -1118,8 +1119,30 @@ const njs_object_init_t  njs_njs_object_
> };
> 
> 
> +static const njs_object_prop_t  njs_global_this_object_properties[] =
> +{
> +    {
> +        .type = NJS_PROPERTY,
> +        .name = njs_string("NaN"),
> +        .value = njs_value(NJS_NUMBER, 0, NAN),
> +    },
> +
> +    {
> +        .type = NJS_PROPERTY,
> +        .name = njs_string("Infinity"),
> +        .value = njs_value(NJS_NUMBER, 0, INFINITY),
> +    },
> +
> +    {
> +        .type = NJS_PROPERTY,
> +        .name = njs_string("undefined"),
> +        .value = njs_value(NJS_VOID, 0, NAN),
> +    },
> +};
> +
> +
> const njs_object_init_t  njs_global_this_init = {
>     nxt_string("this"),
> -    NULL,
> -    0
> +    njs_global_this_object_properties,
> +    nxt_nitems(njs_global_this_object_properties)
> };
> diff -r 2711e84ede6a -r e11011d45499 njs/test/njs_unit_test.c
> --- a/njs/test/njs_unit_test.c	Wed Apr 04 17:38:10 2018 +0300
> +++ b/njs/test/njs_unit_test.c	Thu Nov 15 20:31:35 2018 +0300
> @@ -6488,6 +6488,33 @@ static njs_unit_test_t  njs_test[] =
>     { nxt_string("this"),
>       nxt_string("[object Object]") },
> 
> +    { nxt_string("this.a = 1; this.a"),
> +      nxt_string("1") },
> +
> +    { nxt_string("this.undefined = 42"),
> +      nxt_string("TypeError: Cannot assign to read-only property 'undefined' of object") },
> +
> +    { nxt_string("this.Infinity = 42"),
> +      nxt_string("TypeError: Cannot assign to read-only property 'Infinity' of object") },
> +
> +    { nxt_string("this.NaN = 42"),
> +      nxt_string("TypeError: Cannot assign to read-only property 'NaN' of object") },
> +
> +    { nxt_string("typeof this.undefined"),
> +      nxt_string("undefined") },
> +
> +    { nxt_string("typeof this.Infinity"),
> +      nxt_string("number") },
> +
> +    { nxt_string("this.Infinity + 1"),
> +      nxt_string("Infinity") },
> +
> +    { nxt_string("typeof this.NaN"),
> +      nxt_string("number") },
> +
> +    { nxt_string("this.NaN + 1"),
> +      nxt_string("NaN") },
> +
>     { nxt_string("njs"),
>       nxt_string("[object Object]") },
> 
> @@ -9177,6 +9204,9 @@ static njs_unit_test_t  njs_test[] =
>     { nxt_string("Math"),
>       nxt_string("[object Object]") },
> 
> +    { nxt_string("Math.x = function (x) {return 2*x;}; Math.x(3)"),
> +      nxt_string("6") },
> +
>     { nxt_string("isNaN"),
>       nxt_string("[object Function]") },
> 
> 
> 
> ------------------------------
> 
> Message: 5
> Date: Thu, 15 Nov 2018 17:32:02 +0000
> From: Dmitry Volyntsev <xeioex at nginx.com>
> To: nginx-devel at nginx.org
> Subject: [njs] Improved handling of builtin objects.
> Message-ID:
> 	<hg.2711e84ede6a.1542303122.5965299922797593991 at dev.nginx.com>
> Content-Type: text/plain; charset="us-ascii"
> 
> details:   http://hg.nginx.org/njs/rev/2711e84ede6a
> branches:  
> changeset: 654:2711e84ede6a
> user:      Dmitry Volyntsev <xeioex at nginx.com>
> date:      Wed Apr 04 17:38:10 2018 +0300
> description:
> Improved handling of builtin objects.
> 
> The handling of njs_object_init_t arrays is unified across
> njs_builtin.c functions.
> 
> diffstat:
> 
> njs/njs_builtin.c               |  939 +++++++++++++++++++--------------------
> njs/njs_crypto.c                |   12 +
> njs/njs_fs.c                    |    6 +
> njs/njs_module.c                |   16 -
> njs/njs_module.h                |    1 -
> njs/njs_shell.c                 |   19 +-
> njs/njs_vm.h                    |    7 -
> njs/test/njs_expect_test.exp    |    5 +
> njs/test/njs_interactive_test.c |    5 +
> 9 files changed, 499 insertions(+), 511 deletions(-)
> 
> diffs (truncated from 1323 to 1000 lines):
> 
> diff -r 46632012ac03 -r 2711e84ede6a njs/njs_builtin.c
> --- a/njs/njs_builtin.c	Wed Nov 14 18:14:49 2018 +0300
> +++ b/njs/njs_builtin.c	Wed Apr 04 17:38:10 2018 +0300
> @@ -1,6 +1,7 @@
> 
> /*
>  * Copyright (C) Igor Sysoev
> + * Copyright (C) Dmitry Volyntsev
>  * Copyright (C) NGINX, Inc.
>  */
> 
> @@ -23,25 +24,30 @@ typedef struct {
> } njs_function_init_t;
> 
> 
> -static nxt_int_t njs_builtin_completions(njs_vm_t *vm, size_t *size,
> -    nxt_str_t *completions);
> +static njs_ret_t njs_prototype_function(njs_vm_t *vm, njs_value_t *args,
> +    nxt_uint_t nargs, njs_index_t unused);
> static nxt_array_t *njs_vm_expression_completions(njs_vm_t *vm,
>     nxt_str_t *expression);
> static nxt_array_t *njs_object_completions(njs_vm_t *vm, njs_object_t *object);
> 
> +
> const njs_object_init_t     njs_njs_object_init;
> +const njs_object_init_t     njs_global_this_init;
> +
> 
> const njs_object_init_t    *njs_object_init[] = {
> -    NULL,                         /* global this        */
> +    &njs_global_this_init,        /* global this        */
>     &njs_njs_object_init,         /* global njs object  */
>     &njs_math_object_init,        /* Math               */
>     &njs_json_object_init,        /* JSON               */
> +    NULL
> };
> 
> 
> const njs_object_init_t    *njs_module_init[] = {
>     &njs_fs_object_init,         /* fs                 */
> -    &njs_crypto_object_init      /* crypto             */
> +    &njs_crypto_object_init,     /* crypto             */
> +    NULL
> };
> 
> 
> @@ -64,6 +70,7 @@ const njs_object_init_t  *njs_prototype_
>     &njs_syntax_error_prototype_init,
>     &njs_type_error_prototype_init,
>     &njs_uri_error_prototype_init,
> +    NULL
> };
> 
> 
> @@ -87,6 +94,7 @@ const njs_object_init_t    *njs_construc
>     &njs_type_error_constructor_init,
>     &njs_uri_error_constructor_init,
>     &njs_memory_error_constructor_init,
> +    NULL
> };
> 
> 
> @@ -103,7 +111,8 @@ const njs_object_init_t    *njs_function
>     &njs_decode_uri_component_function_init,
>     &njs_require_function_init,
>     &njs_set_timeout_function_init,
> -    &njs_clear_timeout_function_init
> +    &njs_clear_timeout_function_init,
> +    NULL
> };
> 
> 
> @@ -143,102 +152,95 @@ const njs_object_prop_t  njs_arguments_o
> };
> 
> 
> -static njs_ret_t
> -njs_prototype_function(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
> -    njs_index_t unused)
> -{
> -    vm->retval = njs_value_void;
> +const njs_function_init_t  njs_native_constructors[] = {
> +    /* SunC does not allow empty array initialization. */
> +    { njs_object_constructor,     { 0 } },
> +    { njs_array_constructor,      { 0 } },
> +    { njs_boolean_constructor,    { 0 } },
> +    { njs_number_constructor,     { NJS_SKIP_ARG, NJS_NUMBER_ARG } },
> +    { njs_string_constructor,     { NJS_SKIP_ARG, NJS_STRING_ARG } },
> +    { njs_function_constructor,   { 0 } },
> +    { njs_regexp_constructor,
> +      { NJS_SKIP_ARG, NJS_STRING_ARG, NJS_STRING_ARG } },
> +    { njs_date_constructor,       { 0 } },
> +    { njs_hash_constructor,       { NJS_SKIP_ARG, NJS_STRING_ARG } },
> +    { njs_hmac_constructor,       { NJS_SKIP_ARG, NJS_STRING_ARG,
> +                                    NJS_STRING_ARG } },
> +    { njs_error_constructor,      { NJS_SKIP_ARG, NJS_STRING_ARG } },
> +    { njs_eval_error_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } },
> +    { njs_internal_error_constructor,
> +      { NJS_SKIP_ARG, NJS_STRING_ARG } },
> +    { njs_range_error_constructor,
> +      { NJS_SKIP_ARG, NJS_STRING_ARG } },
> +    { njs_reference_error_constructor,  { NJS_SKIP_ARG, NJS_STRING_ARG } },
> +    { njs_syntax_error_constructor,
> +      { NJS_SKIP_ARG, NJS_STRING_ARG } },
> +    { njs_type_error_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } },
> +    { njs_uri_error_constructor,  { NJS_SKIP_ARG, NJS_STRING_ARG } },
> +    { njs_memory_error_constructor,  { NJS_SKIP_ARG, NJS_STRING_ARG } },
> +};
> +
> +const njs_object_prototype_t  njs_prototype_values[] = {
> +    /*
> +     * GCC 4 complains about uninitialized .shared field,
> +     * if the .type field is initialized as .object.type.
> +     */
> +    { .object =       { .type = NJS_OBJECT } },
> +    { .object =       { .type = NJS_ARRAY } },
> 
> -    return NXT_OK;
> -}
> +    /*
> +     * The .object.type field must be initialzed after the .value field,
> +     * otherwise SunC 5.9 treats the .value as .object.value or so.
> +     */
> +    { .object_value = { .value = njs_value(NJS_BOOLEAN, 0, 0.0),
> +                        .object = { .type = NJS_OBJECT_BOOLEAN } } },
> +
> +    { .object_value = { .value = njs_value(NJS_NUMBER, 0, 0.0),
> +                        .object = { .type = NJS_OBJECT_NUMBER } } },
> +
> +    { .object_value = { .value = njs_string(""),
> +                        .object = { .type = NJS_OBJECT_STRING } } },
> +
> +    { .function =     { .native = 1,
> +                        .args_offset = 1,
> +                        .u.native = njs_prototype_function,
> +                        .object = { .type = NJS_FUNCTION } } },
> +
> +    { .object =       { .type = NJS_REGEXP } },
> +
> +    { .date =         { .time = NAN,
> +                        .object = { .type = NJS_DATE } } },
> +
> +    { .object_value = { .value = njs_value(NJS_DATA, 0, 0.0),
> +                        .object = { .type = NJS_OBJECT } } },
> +
> +    { .object_value = { .value = njs_value(NJS_DATA, 0, 0.0),
> +                        .object = { .type = NJS_OBJECT } } },
> +
> +    { .object =       { .type = NJS_OBJECT_ERROR } },
> +    { .object =       { .type = NJS_OBJECT_EVAL_ERROR } },
> +    { .object =       { .type = NJS_OBJECT_INTERNAL_ERROR } },
> +    { .object =       { .type = NJS_OBJECT_RANGE_ERROR } },
> +    { .object =       { .type = NJS_OBJECT_REF_ERROR } },
> +    { .object =       { .type = NJS_OBJECT_SYNTAX_ERROR } },
> +    { .object =       { .type = NJS_OBJECT_TYPE_ERROR } },
> +    { .object =       { .type = NJS_OBJECT_URI_ERROR } },
> +    { .object =       { .type = NJS_OBJECT_INTERNAL_ERROR } },
> +};
> +
> 
> 
> nxt_int_t
> njs_builtin_objects_create(njs_vm_t *vm)
> {
> -    nxt_int_t               ret;
> -    nxt_uint_t              i;
> -    njs_module_t            *module;
> -    njs_object_t            *objects;
> -    njs_function_t          *functions, *constructors;
> -    nxt_lvlhsh_query_t      lhq;
> -    njs_object_prototype_t  *prototypes;
> -
> -    static const njs_object_prototype_t  prototype_values[] = {
> -        /*
> -         * GCC 4 complains about uninitialized .shared field,
> -         * if the .type field is initialized as .object.type.
> -         */
> -        { .object =       { .type = NJS_OBJECT } },
> -        { .object =       { .type = NJS_ARRAY } },
> -
> -        /*
> -         * The .object.type field must be initialzed after the .value field,
> -         * otherwise SunC 5.9 treats the .value as .object.value or so.
> -         */
> -        { .object_value = { .value = njs_value(NJS_BOOLEAN, 0, 0.0),
> -                            .object = { .type = NJS_OBJECT_BOOLEAN } } },
> -
> -        { .object_value = { .value = njs_value(NJS_NUMBER, 0, 0.0),
> -                            .object = { .type = NJS_OBJECT_NUMBER } } },
> -
> -        { .object_value = { .value = njs_string(""),
> -                            .object = { .type = NJS_OBJECT_STRING } } },
> -
> -        { .function =     { .native = 1,
> -                            .args_offset = 1,
> -                            .u.native = njs_prototype_function,
> -                            .object = { .type = NJS_FUNCTION } } },
> -
> -        { .object =       { .type = NJS_REGEXP } },
> -
> -        { .date =         { .time = NAN,
> -                            .object = { .type = NJS_DATE } } },
> -
> -        { .object_value = { .value = njs_value(NJS_DATA, 0, 0.0),
> -                            .object = { .type = NJS_OBJECT } } },
> -
> -        { .object_value = { .value = njs_value(NJS_DATA, 0, 0.0),
> -                            .object = { .type = NJS_OBJECT } } },
> -
> -        { .object =       { .type = NJS_OBJECT_ERROR } },
> -        { .object =       { .type = NJS_OBJECT_EVAL_ERROR } },
> -        { .object =       { .type = NJS_OBJECT_INTERNAL_ERROR } },
> -        { .object =       { .type = NJS_OBJECT_RANGE_ERROR } },
> -        { .object =       { .type = NJS_OBJECT_REF_ERROR } },
> -        { .object =       { .type = NJS_OBJECT_SYNTAX_ERROR } },
> -        { .object =       { .type = NJS_OBJECT_TYPE_ERROR } },
> -        { .object =       { .type = NJS_OBJECT_URI_ERROR } },
> -        { .object =       { .type = NJS_OBJECT_INTERNAL_ERROR } },
> -    };
> -
> -    static const njs_function_init_t  native_constructors[] = {
> -        /* SunC does not allow empty array initialization. */
> -        { njs_object_constructor,     { 0 } },
> -        { njs_array_constructor,      { 0 } },
> -        { njs_boolean_constructor,    { 0 } },
> -        { njs_number_constructor,     { NJS_SKIP_ARG, NJS_NUMBER_ARG } },
> -        { njs_string_constructor,     { NJS_SKIP_ARG, NJS_STRING_ARG } },
> -        { njs_function_constructor,   { 0 } },
> -        { njs_regexp_constructor,
> -          { NJS_SKIP_ARG, NJS_STRING_ARG, NJS_STRING_ARG } },
> -        { njs_date_constructor,       { 0 } },
> -        { njs_hash_constructor,       { NJS_SKIP_ARG, NJS_STRING_ARG } },
> -        { njs_hmac_constructor,       { NJS_SKIP_ARG, NJS_STRING_ARG,
> -                                        NJS_STRING_ARG } },
> -        { njs_error_constructor,      { NJS_SKIP_ARG, NJS_STRING_ARG } },
> -        { njs_eval_error_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } },
> -        { njs_internal_error_constructor,
> -          { NJS_SKIP_ARG, NJS_STRING_ARG } },
> -        { njs_range_error_constructor,
> -          { NJS_SKIP_ARG, NJS_STRING_ARG } },
> -        { njs_reference_error_constructor,  { NJS_SKIP_ARG, NJS_STRING_ARG } },
> -        { njs_syntax_error_constructor,
> -          { NJS_SKIP_ARG, NJS_STRING_ARG } },
> -        { njs_type_error_constructor, { NJS_SKIP_ARG, NJS_STRING_ARG } },
> -        { njs_uri_error_constructor,  { NJS_SKIP_ARG, NJS_STRING_ARG } },
> -        { njs_memory_error_constructor,  { NJS_SKIP_ARG, NJS_STRING_ARG } },
> -    };
> +    nxt_int_t                  ret;
> +    njs_module_t               *module;
> +    njs_object_t               *object;
> +    njs_function_t             *func;
> +    nxt_lvlhsh_query_t         lhq;
> +    njs_object_prototype_t     *prototype;
> +    const njs_object_init_t    *obj, **p;
> +    const njs_function_init_t  *f;
> 
>     static const njs_object_prop_t    function_prototype_property = {
>         .type = NJS_PROPERTY_HANDLER,
> @@ -246,6 +248,8 @@ njs_builtin_objects_create(njs_vm_t *vm)
>         .value = njs_prop_handler(njs_function_prototype_create),
>     };
> 
> +    static const nxt_str_t  sandbox_key = nxt_string("sandbox");
> +
>     ret = njs_object_hash_create(vm, &vm->shared->function_prototype_hash,
>                                  &function_prototype_property, 1);
>     if (nxt_slow_path(ret != NXT_OK)) {
> @@ -259,48 +263,57 @@ njs_builtin_objects_create(njs_vm_t *vm)
>         return NXT_ERROR;
>     }
> 
> -    objects = vm->shared->objects;
> +    object = vm->shared->objects;
> +
> +    for (p = njs_object_init; *p != NULL; p++) {
> +        obj = *p;
> 
> -    for (i = NJS_OBJECT_THIS; i < NJS_OBJECT_MAX; i++) {
> -        if (njs_object_init[i] != NULL) {
> -            ret = njs_object_hash_create(vm, &objects[i].shared_hash,
> -                                         njs_object_init[i]->properties,
> -                                         njs_object_init[i]->items);
> -            if (nxt_slow_path(ret != NXT_OK)) {
> -                return NXT_ERROR;
> -            }
> +        ret = njs_object_hash_create(vm, &object->shared_hash,
> +                                     obj->properties, obj->items);
> +
> +        if (nxt_slow_path(ret != NXT_OK)) {
> +            return NXT_ERROR;
>         }
> 
> -        objects[i].shared = 1;
> +        object->shared = 1;
> +
> +        object++;
>     }
> 
>     lhq.replace = 0;
> -    lhq.proto = &njs_modules_hash_proto;
>     lhq.pool = vm->mem_cache_pool;
> 
> -    for (i = NJS_MODULE_FS; i < NJS_MODULE_MAX; i++) {
> -        if (vm->options.sandbox && !njs_sandbox_module(i)) {
> -            continue;
> -        }
> +    for (p = njs_module_init; *p != NULL; p++) {
> +        obj = *p;
> 
>         module = nxt_mem_cache_zalloc(vm->mem_cache_pool, sizeof(njs_module_t));
>         if (nxt_slow_path(module == NULL)) {
>             return NJS_ERROR;
>         }
> 
> -        module->name = njs_module_init[i]->name;
> -
>         ret = njs_object_hash_create(vm, &module->object.shared_hash,
> -                                     njs_module_init[i]->properties,
> -                                     njs_module_init[i]->items);
> +                                     obj->properties, obj->items);
>         if (nxt_slow_path(ret != NXT_OK)) {
>             return NXT_ERROR;
>         }
> 
> +        if (vm->options.sandbox) {
> +            lhq.key = sandbox_key;
> +            lhq.key_hash = nxt_djb_hash(sandbox_key.start, sandbox_key.length);
> +            lhq.proto = &njs_object_hash_proto;
> +
> +            ret = nxt_lvlhsh_find(&module->object.shared_hash, &lhq);
> +            if (nxt_fast_path(ret != NXT_OK)) {
> +                continue;
> +            }
> +        }
> +
> +        module->name = obj->name;
>         module->object.shared = 1;
> 
>         lhq.key = module->name;
>         lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length);
> +        lhq.proto = &njs_modules_hash_proto;
>         lhq.value = module;
> 
>         ret = nxt_lvlhsh_insert(&vm->modules_hash, &lhq);
> @@ -309,73 +322,88 @@ njs_builtin_objects_create(njs_vm_t *vm)
>         }
>     }
> 
> -    functions = vm->shared->functions;
> +    f = njs_native_functions;
> +    func = vm->shared->functions;
> 
> -    for (i = NJS_FUNCTION_EVAL; i < NJS_FUNCTION_MAX; i++) {
> -        if (njs_function_init[i]->items != 0) {
> -            ret = njs_object_hash_create(vm, &functions[i].object.shared_hash,
> -                                         njs_function_init[i]->properties,
> -                                         njs_function_init[i]->items);
> -            if (nxt_slow_path(ret != NXT_OK)) {
> -                return NXT_ERROR;
> -            }
> +    for (p = njs_function_init; *p != NULL; p++) {
> +        obj = *p;
> +
> +        ret = njs_object_hash_create(vm, &func->object.shared_hash,
> +                                     obj->properties, obj->items);
> +        if (nxt_slow_path(ret != NXT_OK)) {
> +            return NXT_ERROR;
>         }
> 
> -        functions[i].object.shared = 1;
> -        functions[i].object.extensible = 1;
> -        functions[i].native = 1;
> -        functions[i].args_offset = 1;
> -        functions[i].u.native = njs_native_functions[i].native;
> -        functions[i].args_types[0] = njs_native_functions[i].args_types[0];
> -        functions[i].args_types[1] = njs_native_functions[i].args_types[1];
> -        functions[i].args_types[2] = njs_native_functions[i].args_types[2];
> -        functions[i].args_types[3] = njs_native_functions[i].args_types[3];
> -        functions[i].args_types[4] = njs_native_functions[i].args_types[4];
> +        func->object.shared = 1;
> +        func->object.extensible = 1;
> +        func->native = 1;
> +        func->args_offset = 1;
> +
> +        func->u.native = f->native;
> +        memcpy(func->args_types, f->args_types, NJS_ARGS_TYPES_MAX);
> +
> +        f++;
> +        func++;
>     }
> 
> -    prototypes = vm->shared->prototypes;
> +    prototype = vm->shared->prototypes;
> +    memcpy(prototype, njs_prototype_values, sizeof(njs_prototype_values));
> 
> -    for (i = NJS_PROTOTYPE_OBJECT; i < NJS_PROTOTYPE_MAX; i++) {
> -        prototypes[i] = prototype_values[i];
> +    for (p = njs_prototype_init; *p != NULL; p++) {
> +        obj = *p;
> 
> -        ret = njs_object_hash_create(vm, &prototypes[i].object.shared_hash,
> -                                     njs_prototype_init[i]->properties,
> -                                     njs_prototype_init[i]->items);
> +        ret = njs_object_hash_create(vm, &prototype->object.shared_hash,
> +                                     obj->properties, obj->items);
>         if (nxt_slow_path(ret != NXT_OK)) {
>             return NXT_ERROR;
>         }
> +
> +        prototype++;
>     }
> 
> -    prototypes[NJS_PROTOTYPE_REGEXP].regexp.pattern =
> +    vm->shared->prototypes[NJS_PROTOTYPE_REGEXP].regexp.pattern =
>                                               vm->shared->empty_regexp_pattern;
> 
> -    constructors = vm->shared->constructors;
> +    f = njs_native_constructors;
> +    func = vm->shared->constructors;
> +
> +    for (p = njs_constructor_init; *p != NULL; p++) {
> +        obj = *p;
> 
> -    for (i = NJS_CONSTRUCTOR_OBJECT; i < NJS_CONSTRUCTOR_MAX; i++) {
> -        constructors[i].object.shared = 0;
> -        constructors[i].object.extensible = 1;
> -        constructors[i].native = 1;
> -        constructors[i].ctor = 1;
> -        constructors[i].args_offset = 1;
> -        constructors[i].u.native = native_constructors[i].native;
> -        constructors[i].args_types[0] = native_constructors[i].args_types[0];
> -        constructors[i].args_types[1] = native_constructors[i].args_types[1];
> -        constructors[i].args_types[2] = native_constructors[i].args_types[2];
> -        constructors[i].args_types[3] = native_constructors[i].args_types[3];
> -        constructors[i].args_types[4] = native_constructors[i].args_types[4];
> +        func->object.shared = 0;
> +        func->object.extensible = 1;
> +        func->native = 1;
> +        func->ctor = 1;
> +        func->args_offset = 1;
> 
> -        ret = njs_object_hash_create(vm, &constructors[i].object.shared_hash,
> -                                     njs_constructor_init[i]->properties,
> -                                     njs_constructor_init[i]->items);
> +        func->u.native = f->native;
> +
> +        memcpy(func->args_types, f->args_types, NJS_ARGS_TYPES_MAX);
> +
> +        ret = njs_object_hash_create(vm, &func->object.shared_hash,
> +                                     obj->properties, obj->items);
>         if (nxt_slow_path(ret != NXT_OK)) {
>             return NXT_ERROR;
>         }
> +
> +        f++;
> +        func++;
>     }
> 
>     return NXT_OK;
> }
> 
> 
> +static njs_ret_t
> +njs_prototype_function(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
> +    njs_index_t unused)
> +{
> +    vm->retval = njs_value_void;
> +
> +    return NXT_OK;
> +}
> +
> +
> /*
>  * Object(),
>  * Object.__proto__             -> Function_Prototype,
> @@ -493,53 +521,15 @@ njs_builtin_objects_clone(njs_vm_t *vm)
> }
> 
> 
> -nxt_array_t *
> -njs_vm_completions(njs_vm_t *vm, nxt_str_t *expression)
> +static size_t
> +njs_builtin_completions_size(njs_vm_t *vm)
> {
> -    size_t       size;
> -    nxt_array_t  *completions;
> -
> -    if (expression == NULL) {
> -        if (njs_builtin_completions(vm, &size, NULL) != NXT_OK) {
> -            return NULL;
> -        }
> -
> -        completions = nxt_array_create(size, sizeof(nxt_str_t),
> -                                       &njs_array_mem_proto,
> -                                       vm->mem_cache_pool);
> -
> -        if (nxt_slow_path(completions == NULL)) {
> -            return NULL;
> -        }
> -
> -        if (njs_builtin_completions(vm, &size, completions->start) != NXT_OK) {
> -            return NULL;
> -        }
> -
> -        completions->items = size;
> -
> -        return completions;
> -    }
> -
> -    return njs_vm_expression_completions(vm, expression);
> -}
> -
> -
> -static nxt_int_t
> -njs_builtin_completions(njs_vm_t *vm, size_t *size, nxt_str_t *completions)
> -{
> -    char                    *compl;
> -    size_t                  n, len;
> -    nxt_str_t               string;
> -    nxt_uint_t              i, k;
> -    njs_object_t            *objects;
> -    njs_keyword_t           *keyword;
> -    njs_function_t          *constructors;
> -    njs_object_prop_t       *prop;
> -    nxt_lvlhsh_each_t       lhe, lhe_prop;
> -    njs_extern_value_t      *ev;
> -    const njs_extern_t      *ext_proto, *ext_prop;
> -    njs_object_prototype_t  *prototypes;
> +    nxt_uint_t               n;
> +    njs_keyword_t            *keyword;
> +    nxt_lvlhsh_each_t        lhe, lhe_prop;
> +    njs_extern_value_t       *ev;
> +    const njs_extern_t       *ext_proto, *ext_prop;
> +    const njs_object_init_t  **p;
> 
>     n = 0;
> 
> @@ -552,123 +542,147 @@ njs_builtin_completions(njs_vm_t *vm, si
>             break;
>         }
> 
> -        if (completions != NULL) {
> -            completions[n++] = keyword->name;
> +        n++;
> +    }
> +
> +    for (p = njs_object_init; *p != NULL; p++) {
> +        n += (*p)->items;
> +    }
> +
> +    for (p = njs_prototype_init; *p != NULL; p++) {
> +        n += (*p)->items;
> +    }
> +
> +    for (p = njs_constructor_init; *p != NULL; p++) {
> +        n += (*p)->items;
> +    }
> +
> +    nxt_lvlhsh_each_init(&lhe, &njs_extern_value_hash_proto);
> 
> -        } else {
> +    for ( ;; ) {
> +        ev = nxt_lvlhsh_each(&vm->externals_hash, &lhe);
> +
> +        if (ev == NULL) {
> +            break;
> +        }
> +
> +        ext_proto = ev->value.external.proto;
> +
> +        nxt_lvlhsh_each_init(&lhe_prop, &njs_extern_hash_proto);
> +
> +        n++;
> +
> +        for ( ;; ) {
> +            ext_prop = nxt_lvlhsh_each(&ext_proto->hash, &lhe_prop);
> +
> +            if (ext_prop == NULL) {
> +                break;
> +            }
> +
>             n++;
>         }
>     }
> 
> -    objects = vm->shared->objects;
> +    return n;
> +}
> +
> 
> -    for (i = NJS_OBJECT_THIS; i < NJS_OBJECT_MAX; i++) {
> -        if (njs_object_init[i] == NULL) {
> -            continue;
> +static nxt_array_t *
> +njs_builtin_completions(njs_vm_t *vm, nxt_array_t *array)
> +{
> +    char                     *compl;
> +    size_t                   n, len;
> +    nxt_str_t                string, *completions;
> +    nxt_uint_t               i, k;
> +    njs_keyword_t            *keyword;
> +    nxt_lvlhsh_each_t        lhe, lhe_prop;
> +    njs_extern_value_t       *ev;
> +    const njs_extern_t       *ext_proto, *ext_prop;
> +    const njs_object_prop_t  *prop;
> +    const njs_object_init_t  *obj, **p;
> +
> +    n = 0;
> +    completions = array->start;
> +
> +    nxt_lvlhsh_each_init(&lhe, &njs_keyword_hash_proto);
> +
> +    for ( ;; ) {
> +        keyword = nxt_lvlhsh_each(&vm->shared->keywords_hash, &lhe);
> +
> +        if (keyword == NULL) {
> +            break;
>         }
> 
> -        nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
> +        completions[n++] = keyword->name;
> +    }
> +
> +    for (p = njs_object_init; *p != NULL; p++) {
> +        obj = *p;
> 
> -        for ( ;; ) {
> -            prop = nxt_lvlhsh_each(&objects[i].shared_hash, &lhe);
> +        for (i = 0; i < obj->items; i++) {
> +            prop = &obj->properties[i];
> +            njs_string_get(&prop->name, &string);
> +            len = obj->name.length + string.length + 2;
> 
> -            if (prop == NULL) {
> -                break;
> +            compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
> +            if (compl == NULL) {
> +                return NULL;
>             }
> 
> -            if (completions != NULL) {
> -                njs_string_get(&prop->name, &string);
> -                len = njs_object_init[i]->name.length + string.length + 2;
> +            snprintf(compl, len, "%s.%s", obj->name.start, string.start);
> +
> +            completions[n].length = len;
> +            completions[n++].start = (u_char *) compl;
> +        }
> +    }
> +
> +    for (p = njs_prototype_init; *p != NULL; p++) {
> +        obj = *p;
> +
> +        for (i = 0; i < obj->items; i++) {
> +            prop = &obj->properties[i];
> +            njs_string_get(&prop->name, &string);
> +            len = string.length + 2;
> 
> -                compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
> -                if (compl == NULL) {
> -                    return NXT_ERROR;
> +            compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
> +            if (compl == NULL) {
> +                return NULL;
> +            }
> +
> +            snprintf(compl, len, ".%s", string.start);
> +
> +            for (k = 0; k < n; k++) {
> +                if (strncmp((char *) completions[k].start, compl, len)
> +                    == 0)
> +                {
> +                    break;
>                 }
> +            }
> 
> -                snprintf(compl, len, "%s.%s", njs_object_init[i]->name.start,
> -                         string.start);
> -
> +            if (k == n) {
>                 completions[n].length = len;
>                 completions[n++].start = (u_char *) compl;
> -
> -            } else {
> -                n++;
>             }
>         }
>     }
> 
> -    prototypes = vm->shared->prototypes;
> -
> -    for (i = NJS_PROTOTYPE_OBJECT; i < NJS_PROTOTYPE_MAX; i++) {
> -        nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
> +    for (p = njs_constructor_init; *p != NULL; p++) {
> +        obj = *p;
> 
> -        for ( ;; ) {
> -            prop = nxt_lvlhsh_each(&prototypes[i].object.shared_hash, &lhe);
> +        for (i = 0; i < obj->items; i++) {
> +            prop = &obj->properties[i];
> +            njs_string_get(&prop->name, &string);
> +            len = obj->name.length + string.length + 2;
> 
> -            if (prop == NULL) {
> -                break;
> +            compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
> +            if (compl == NULL) {
> +                return NULL;
>             }
> 
> -            if (completions != NULL) {
> -                njs_string_get(&prop->name, &string);
> -                len = string.length + 2;
> -
> -                compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
> -                if (compl == NULL) {
> -                    return NXT_ERROR;
> -                }
> -
> -                snprintf(compl, len, ".%s", string.start);
> -
> -                for (k = 0; k < n; k++) {
> -                    if (strncmp((char *) completions[k].start, compl, len)
> -                        == 0)
> -                    {
> -                        break;
> -                    }
> -                }
> -
> -                if (k == n) {
> -                    completions[n].length = len;
> -                    completions[n++].start = (u_char *) compl;
> -                }
> -
> -            } else {
> -                n++;
> -            }
> -        }
> -    }
> +            snprintf(compl, len, "%s.%s", obj->name.start, string.start);
> 
> -    constructors = vm->shared->constructors;
> -
> -    for (i = NJS_CONSTRUCTOR_OBJECT; i < NJS_CONSTRUCTOR_MAX; i++) {
> -        nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
> -
> -        for ( ;; ) {
> -            prop = nxt_lvlhsh_each(&constructors[i].object.shared_hash, &lhe);
> -
> -            if (prop == NULL) {
> -                break;
> -            }
> -
> -            if (completions != NULL) {
> -                njs_string_get(&prop->name, &string);
> -                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",
> -                         njs_constructor_init[i]->name.start, string.start);
> -
> -                completions[n].length = len;
> -                completions[n++].start = (u_char *) compl;
> -
> -            } else {
> -                n++;
> -            }
> +            completions[n].length = len;
> +            completions[n++].start = (u_char *) compl;
>         }
>     }
> 
> @@ -685,21 +699,16 @@ njs_builtin_completions(njs_vm_t *vm, si
> 
>         nxt_lvlhsh_each_init(&lhe_prop, &njs_extern_hash_proto);
> 
> -        if (completions != NULL) {
> -            len = ev->name.length + 1;
> -            compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
> -            if (compl == NULL) {
> -                return NXT_ERROR;
> -            }
> +        len = ev->name.length + 1;
> +        compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
> +        if (compl == NULL) {
> +            return NULL;
> +        }
> 
> -            snprintf(compl, len, "%.*s", (int) ev->name.length, ev->name.start);
> +        snprintf(compl, len, "%.*s", (int) ev->name.length, ev->name.start);
> 
> -            completions[n].length = len;
> -            completions[n++].start = (u_char *) compl;
> -
> -        } else {
> -            n++;
> -        }
> +        completions[n].length = len;
> +        completions[n++].start = (u_char *) compl;
> 
>         for ( ;; ) {
>             ext_prop = nxt_lvlhsh_each(&ext_proto->hash, &lhe_prop);
> @@ -708,31 +717,48 @@ njs_builtin_completions(njs_vm_t *vm, si
>                 break;
>             }
> 
> -            if (completions != NULL) {
> -                len = ev->name.length + ev->name.length + 2;
> -                compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
> -                if (compl == NULL) {
> -                    return NXT_ERROR;
> -                }
> +            len = ev->name.length + ev->name.length + 2;
> +            compl = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
> +            if (compl == NULL) {
> +                return NULL;
> +            }
> 
> -                snprintf(compl, len, "%.*s.%.*s", (int) ev->name.length,
> -                         ev->name.start, (int) ext_prop->name.length,
> -                         ext_prop->name.start);
> +            snprintf(compl, len, "%.*s.%.*s", (int) ev->name.length,
> +                     ev->name.start, (int) ext_prop->name.length,
> +                     ext_prop->name.start);
> 
> -                completions[n].length = len;
> -                completions[n++].start = (u_char *) compl;
> -
> -            } else {
> -                n++;
> -            }
> +            completions[n].length = len;
> +            completions[n++].start = (u_char *) compl;
>         }
>     }
> 
> -    if (size) {
> -        *size = n;
> +    array->items = n;
> +
> +    return array;
> +}
> +
> +
> +nxt_array_t *
> +njs_vm_completions(njs_vm_t *vm, nxt_str_t *expression)
> +{
> +    size_t       size;
> +    nxt_array_t  *completions;
> +
> +    if (expression == NULL) {
> +        size = njs_builtin_completions_size(vm);
> +
> +        completions = nxt_array_create(size, sizeof(nxt_str_t),
> +                                       &njs_array_mem_proto,
> +                                       vm->mem_cache_pool);
> +
> +        if (nxt_slow_path(completions == NULL)) {
> +            return NULL;
> +        }
> +
> +        return njs_builtin_completions(vm, completions);
>     }
> 
> -    return NXT_OK;
> +    return njs_vm_expression_completions(vm, expression);
> }
> 
> 
> @@ -911,185 +937,135 @@ njs_object_completions(njs_vm_t *vm, njs
> }
> 
> 
> -nxt_int_t
> -njs_builtin_match_native_function(njs_vm_t *vm, njs_function_t *function,
> -    nxt_str_t *name)
> +static nxt_int_t
> +njs_builtin_match(const njs_object_init_t **objects, njs_function_t *function,
> +    const njs_object_prop_t **prop, const njs_object_init_t **object)
> {
> -    char                    *buf;
> -    size_t                  len;
> -    nxt_str_t               string;
> -    nxt_uint_t              i;
> -    njs_module_t            *module;
> -    njs_object_t            *objects;
> -    njs_function_t          *constructors;
> -    njs_object_prop_t       *prop;
> -    nxt_lvlhsh_each_t       lhe, lhe_prop;
> -    njs_object_prototype_t  *prototypes;
> +    nxt_uint_t               i;
> +    const njs_object_init_t  *o, **p;
> +    const njs_object_prop_t  *pr;
> 
> -    objects = vm->shared->objects;
> -
> -    for (i = NJS_OBJECT_THIS; i < NJS_OBJECT_MAX; i++) {
> -        if (njs_object_init[i] == NULL) {
> -            continue;
> -        }
> -
> -        nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
> +    for (p = objects; *p != NULL; p++) {
> +        o = *p;
> 
> -        for ( ;; ) {
> -            prop = nxt_lvlhsh_each(&objects[i].shared_hash, &lhe);
> +        for (i = 0; i < o->items; i++) {
> +            pr = &o->properties[i];
> 
> -            if (prop == NULL) {
> -                break;
> -            }
> -
> -            if (!njs_is_function(&prop->value)) {
> +            if (pr->type != NJS_METHOD) {
>                 continue;
>             }
> 
> -            if (function == prop->value.data.u.function) {
> -                njs_string_get(&prop->name, &string);
> -                len = njs_object_init[i]->name.length + string.length
> -                      + sizeof(".");
> -
> -                buf = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
> -                if (buf == NULL) {
> -                    return NXT_ERROR;
> -                }
> -
> -                snprintf(buf, len, "%s.%s", njs_object_init[i]->name.start,
> -                         string.start);
> -
> -                name->length = len;
> -                name->start = (u_char *) buf;
> -
> -                return NXT_OK;
> -            }
> -        }
> -    }
> -
> -    prototypes = vm->shared->prototypes;
> -
> -    for (i = NJS_PROTOTYPE_OBJECT; i < NJS_PROTOTYPE_MAX; i++) {
> -        nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
> -
> -        for ( ;; ) {
> -            prop = nxt_lvlhsh_each(&prototypes[i].object.shared_hash, &lhe);
> -
> -            if (prop == NULL) {
> -                break;
> -            }
> -
> -            if (!njs_is_function(&prop->value)) {
> +            if (function != pr->value.data.u.function) {
>                 continue;
>             }
> 
> -            if (function == prop->value.data.u.function) {
> -                njs_string_get(&prop->name, &string);
> -                len = njs_prototype_init[i]->name.length + string.length
> -                      + sizeof(".prototype.");
> -
> -                buf = nxt_mem_cache_zalloc(vm->mem_cache_pool, len);
> -                if (buf == NULL) {
> -                    return NXT_ERROR;
> -                }
> -
> -                snprintf(buf, len, "%s.prototype.%s",
> -                         njs_prototype_init[i]->name.start, string.start);
> -
> -                name->length = len;
> -                name->start = (u_char *) buf;
> -
> -                return NXT_OK;
> -            }
> -        }
> -    }
> -
> -    constructors = vm->shared->constructors;
> -
> -    for (i = NJS_CONSTRUCTOR_OBJECT; i < NJS_CONSTRUCTOR_MAX; i++) {
> -        nxt_lvlhsh_each_init(&lhe, &njs_object_hash_proto);
> -
> -        for ( ;; ) {
> -            prop = nxt_lvlhsh_each(&constructors[i].object.shared_hash, &lhe);
> -
> -            if (prop == NULL) {
> -                break;
> -            }
> -
> -            if (!njs_is_function(&prop->value)) {
> -                continue;
> -            }
> -
> -            if (function == prop->value.data.u.function) {
> -                njs_string_get(&prop->name, &string);
> 
> 
> ------------------------------
> 
> Subject: Digest Footer
> 
> _______________________________________________
> nginx-devel mailing list
> nginx-devel at nginx.org
> http://mailman.nginx.org/mailman/listinfo/nginx-devel
> 
> ------------------------------
> 
> End of nginx-devel Digest, Vol 109, Issue 15
> ********************************************



More information about the nginx-devel mailing list