[PATCH] New directive to configure TLSv1.3 ciphers

Ramprasad Tamilselvan ramprasad.tamilselvan at quantil.com
Thu Nov 15 20:17:15 UTC 2018


I have a question regarding the ticket.
What if different TLSv1.3 ciphers need to be configured in different server blocks?
In this case, changing openssl.conf will not help right.

Thanks,
Ramprasad

> On Nov 15, 2018, at 10:55 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. Re: [PATCH] New directive to configure TLSv1.3 ciphers
>      (Ramprasad Tamilselvan)
> 
> 
> ----------------------------------------------------------------------
> 
> Message: 1
> Date: Thu, 15 Nov 2018 10:55:27 -0800
> From: Ramprasad Tamilselvan <ramprasad.tamilselvan at quantil.com>
> To: nginx-devel at nginx.org
> Subject: Re: [PATCH] New directive to configure TLSv1.3 ciphers
> Message-ID: <F539B796-322E-4F98-816D-51195015E56B at quantil.com>
> Content-Type: text/plain;	charset=us-ascii
> 
> 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
>> ********************************************
> 
> 
> 
> ------------------------------
> 
> 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 17
> ********************************************



More information about the nginx-devel mailing list