[njs] Introduced "name" instance property for a function object.

Dmitry Volyntsev xeioex at nginx.com
Wed Sep 21 00:46:00 UTC 2022


details:   https://hg.nginx.org/njs/rev/74d30c2d70f3
branches:  
changeset: 1960:74d30c2d70f3
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Tue Sep 20 17:44:25 2022 -0700
description:
Introduced "name" instance property for a function object.

This closes #360 issue on Github.

diffstat:

 src/njs_async.c          |   7 +++
 src/njs_disassembler.c   |   8 ++-
 src/njs_error.c          |   5 ++
 src/njs_function.c       |  99 +++++++++++++++++++++++++++++++++++------------
 src/njs_function.h       |   4 +
 src/njs_generator.c      |  92 ++++++++++++++++++++++++++++++++++++++++---
 src/njs_object_prop.c    |   5 ++
 src/njs_parser.c         |  10 ++--
 src/njs_value.c          |   1 +
 src/njs_value.h          |   1 +
 src/njs_vm.c             |   1 +
 src/njs_vm.h             |   1 +
 src/njs_vmcode.c         |  36 +++++++++++++---
 src/njs_vmcode.h         |   2 +
 src/test/njs_unit_test.c |  71 +++++++++++++++++++++++++++++++++-
 15 files changed, 293 insertions(+), 50 deletions(-)

diffs (670 lines):

diff -r 33fcc9fc6704 -r 74d30c2d70f3 src/njs_async.c
--- a/src/njs_async.c	Mon Sep 19 17:36:02 2022 -0700
+++ b/src/njs_async.c	Tue Sep 20 17:44:25 2022 -0700
@@ -228,6 +228,13 @@ const njs_object_prop_t  njs_async_funct
         .value = njs_prop_handler(njs_function_instance_length),
         .configurable = 1,
     },
+
+    {
+        .type = NJS_PROPERTY_HANDLER,
+        .name = njs_string("name"),
+        .value = njs_prop_handler(njs_function_instance_name),
+        .configurable = 1,
+    },
 };
 
 
diff -r 33fcc9fc6704 -r 74d30c2d70f3 src/njs_disassembler.c
--- a/src/njs_disassembler.c	Mon Sep 19 17:36:02 2022 -0700
+++ b/src/njs_disassembler.c	Tue Sep 20 17:44:25 2022 -0700
@@ -74,8 +74,12 @@ static njs_code_name_t  code_names[] = {
           njs_str("VOID            ") },
     { NJS_VMCODE_TYPEOF, sizeof(njs_vmcode_2addr_t),
           njs_str("TYPEOF          ") },
-    { NJS_VMCODE_TO_PROPERTY_KEY, sizeof(njs_vmcode_3addr_t),
-          njs_str("TO PROPERTY KEY ") },
+    { NJS_VMCODE_TO_PROPERTY_KEY, sizeof(njs_vmcode_2addr_t),
+          njs_str("TO PROP KEY     ") },
+    { NJS_VMCODE_TO_PROPERTY_KEY_CHK, sizeof(njs_vmcode_3addr_t),
+          njs_str("TO PROP KEY CHK ") },
+    { NJS_VMCODE_SET_FUNCTION_NAME, sizeof(njs_vmcode_2addr_t),
+          njs_str("SET FUNC NAME   ") },
 
     { NJS_VMCODE_UNARY_PLUS, sizeof(njs_vmcode_2addr_t),
           njs_str("PLUS            ") },
diff -r 33fcc9fc6704 -r 74d30c2d70f3 src/njs_error.c
--- a/src/njs_error.c	Mon Sep 19 17:36:02 2022 -0700
+++ b/src/njs_error.c	Tue Sep 20 17:44:25 2022 -0700
@@ -1319,6 +1319,11 @@ njs_add_backtrace_entry(njs_vm_t *vm, nj
 
     if (code != NULL) {
         be->name = code->name;
+
+        if (be->name.length == 0) {
+            be->name = njs_entry_anonymous;
+        }
+
         be->line = njs_lookup_line(code->lines, native_frame->pc - code->start);
         if (!vm->options.quiet) {
             be->file = code->file;
diff -r 33fcc9fc6704 -r 74d30c2d70f3 src/njs_function.c
--- a/src/njs_function.c	Mon Sep 19 17:36:02 2022 -0700
+++ b/src/njs_function.c	Tue Sep 20 17:44:25 2022 -0700
@@ -145,29 +145,34 @@ njs_function_name_set(njs_vm_t *vm, njs_
     }
 
     if (prefix != NULL || symbol != 0) {
-        value = prop->value;
-        (void) njs_string_prop(&string, &value);
+        if (njs_is_defined(&prop->value)) {
+            value = prop->value;
+            (void) njs_string_prop(&string, &value);
 
-        len = (prefix != NULL) ? njs_strlen(prefix) + 1: 0;
-        p = njs_string_alloc(vm, &prop->value, string.size + len + symbol,
-                             string.length + len + symbol);
-        if (njs_slow_path(p == NULL)) {
-            return NJS_ERROR;
-        }
+            len = (prefix != NULL) ? njs_strlen(prefix) + 1: 0;
+            p = njs_string_alloc(vm, &prop->value, string.size + len + symbol,
+                                 string.length + len + symbol);
+            if (njs_slow_path(p == NULL)) {
+                return NJS_ERROR;
+            }
 
-        if (len != 0) {
-            p = njs_cpymem(p, prefix, len - 1);
-            *p++ = ' ';
-        }
+            if (len != 0) {
+                p = njs_cpymem(p, prefix, len - 1);
+                *p++ = ' ';
+            }
+
+            if (symbol != 0) {
+                *p++ = '[';
+            }
 
-        if (symbol != 0) {
-            *p++ = '[';
-        }
+            p = njs_cpymem(p, string.start, string.size);
 
-        p = njs_cpymem(p, string.start, string.size);
+            if (symbol != 0) {
+                *p++ = ']';
+            }
 
-        if (symbol != 0) {
-            *p++ = ']';
+        } else {
+            njs_value_assign(&prop->value, &njs_string_empty);
         }
     }
 
@@ -1253,6 +1258,12 @@ njs_function_constructor(njs_vm_t *vm, n
     function->global_this = 1;
     function->args_count = lambda->nargs - lambda->rest_parameters;
 
+    ret = njs_function_name_set(vm, function,
+                                njs_value_arg(&njs_string_anonymous), NULL);
+    if (njs_slow_path(ret == NJS_ERROR)) {
+        return ret;
+    }
+
     njs_set_function(&vm->retval, function);
 
     return NJS_OK;
@@ -1324,6 +1335,30 @@ njs_function_instance_length(njs_vm_t *v
 }
 
 
+njs_int_t
+njs_function_instance_name(njs_vm_t *vm, njs_object_prop_t *prop,
+    njs_value_t *value, njs_value_t *setval, njs_value_t *retval)
+{
+    njs_function_t  *function;
+
+    function = njs_object_proto_lookup(njs_object(value), NJS_FUNCTION,
+                                     njs_function_t);
+    if (njs_slow_path(function == NULL)) {
+        njs_set_undefined(retval);
+        return NJS_DECLINED;
+    }
+
+    if (!function->native) {
+        njs_value_assign(retval, &function->u.lambda->name);
+        return NJS_OK;
+    }
+
+    njs_value_assign(retval, &njs_string_empty);
+
+    return NJS_OK;
+}
+
+
 static njs_int_t
 njs_function_prototype_call(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     njs_index_t unused)
@@ -1447,11 +1482,10 @@ static njs_int_t
 njs_function_prototype_bind(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     njs_index_t unused)
 {
-    size_t              size;
-    njs_int_t           ret;
-    njs_value_t         *values, name;
-    njs_function_t      *function;
-    njs_lvlhsh_query_t  lhq;
+    size_t          size;
+    njs_int_t       ret;
+    njs_value_t     *values, name;
+    njs_function_t  *function;
 
     if (!njs_is_function(&args[0])) {
         njs_type_error(vm, "\"this\" argument is not a function");
@@ -1476,9 +1510,8 @@ njs_function_prototype_bind(njs_vm_t *vm
 
     function->u.bound_target = njs_function(&args[0]);
 
-    njs_object_property_init(&lhq, &njs_string_name, NJS_NAME_HASH);
-
-    ret = njs_object_property(vm, &args[0], &lhq, &name);
+    ret = njs_value_property(vm, &args[0], njs_value_arg(&njs_string_name),
+                             &name);
     if (njs_slow_path(ret == NJS_ERROR)) {
         return ret;
     }
@@ -1616,6 +1649,13 @@ const njs_object_prop_t  njs_function_in
 
     {
         .type = NJS_PROPERTY_HANDLER,
+        .name = njs_string("name"),
+        .value = njs_prop_handler(njs_function_instance_name),
+        .configurable = 1,
+    },
+
+    {
+        .type = NJS_PROPERTY_HANDLER,
         .name = njs_string("prototype"),
         .value = njs_prop_handler(njs_function_prototype_create),
         .writable = 1
@@ -1637,6 +1677,13 @@ const njs_object_prop_t  njs_arrow_insta
         .value = njs_prop_handler(njs_function_instance_length),
         .configurable = 1,
     },
+
+    {
+        .type = NJS_PROPERTY_HANDLER,
+        .name = njs_string("name"),
+        .value = njs_prop_handler(njs_function_instance_name),
+        .configurable = 1,
+    },
 };
 
 
diff -r 33fcc9fc6704 -r 74d30c2d70f3 src/njs_function.h
--- a/src/njs_function.h	Mon Sep 19 17:36:02 2022 -0700
+++ b/src/njs_function.h	Tue Sep 20 17:44:25 2022 -0700
@@ -23,6 +23,8 @@ struct njs_function_lambda_s {
     uint8_t                        ctor;              /* 1 bit */
     uint8_t                        rest_parameters;   /* 1 bit */
 
+    njs_value_t                    name;
+
     u_char                         *start;
 };
 
@@ -99,6 +101,8 @@ njs_int_t njs_function_constructor(njs_v
     njs_uint_t nargs, njs_index_t unused);
 njs_int_t njs_function_instance_length(njs_vm_t *vm, njs_object_prop_t *prop,
     njs_value_t *value, njs_value_t *setval, njs_value_t *retval);
+njs_int_t njs_function_instance_name(njs_vm_t *vm, njs_object_prop_t *prop,
+    njs_value_t *value, njs_value_t *setval, njs_value_t *retval);
 njs_int_t njs_eval_function(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
     njs_index_t unused);
 njs_int_t njs_function_native_frame(njs_vm_t *vm, njs_function_t *function,
diff -r 33fcc9fc6704 -r 74d30c2d70f3 src/njs_generator.c
--- a/src/njs_generator.c	Mon Sep 19 17:36:02 2022 -0700
+++ b/src/njs_generator.c	Tue Sep 20 17:44:25 2022 -0700
@@ -1050,10 +1050,12 @@ static njs_int_t
 njs_generate_var_statement_after(njs_vm_t *vm, njs_generator_t *generator,
     njs_parser_node_t *node)
 {
-    njs_int_t          ret;
-    njs_variable_t     *var;
-    njs_parser_node_t  *lvalue, *expr;
-    njs_vmcode_move_t  *move;
+    ssize_t                  length;
+    njs_int_t                ret;
+    njs_variable_t           *var;
+    njs_parser_node_t        *lvalue, *expr;
+    njs_vmcode_move_t        *move;
+    const njs_lexer_entry_t  *lex_entry;
 
     lvalue = node->left;
     expr = node->right;
@@ -1080,6 +1082,29 @@ njs_generate_var_statement_after(njs_vm_
     node->index = expr->index;
     node->temporary = expr->temporary;
 
+    if ((expr->token_type == NJS_TOKEN_FUNCTION_EXPRESSION
+         || expr->token_type == NJS_TOKEN_ASYNC_FUNCTION_EXPRESSION)
+        && njs_values_same(&expr->u.value.data.u.lambda->name,
+                           &njs_string_empty))
+    {
+        lex_entry = njs_lexer_entry(node->left->u.reference.unique_id);
+        if (njs_slow_path(lex_entry == NULL)) {
+            return NJS_ERROR;
+        }
+
+        length = njs_utf8_length(lex_entry->name.start, lex_entry->name.length);
+        if (njs_slow_path(length < 0)) {
+            return NJS_ERROR;
+        }
+
+        ret = njs_string_new(vm, &expr->u.value.data.u.lambda->name,
+                             lex_entry->name.start, lex_entry->name.length,
+                             length);
+        if (njs_slow_path(ret != NJS_OK)) {
+            return NJS_ERROR;
+        }
+    }
+
     return njs_generator_stack_pop(vm, generator, NULL);
 }
 
@@ -2854,7 +2879,9 @@ njs_generate_assignment_end(njs_vm_t *vm
     njs_parser_node_t *node)
 {
     njs_int_t              ret;
+    njs_index_t            prop_index;
     njs_parser_node_t      *lvalue, *expr, *object, *property;
+    njs_vmcode_2addr_t     *set_function, *to_prop_key;
     njs_vmcode_prop_set_t  *prop_set;
 
     lvalue = node->left;
@@ -2862,9 +2889,34 @@ njs_generate_assignment_end(njs_vm_t *vm
 
     object = lvalue->left;
     property = lvalue->right;
+    prop_index = property->index;
 
     switch (lvalue->token_type) {
     case NJS_TOKEN_PROPERTY_INIT:
+
+        if ((expr->token_type == NJS_TOKEN_FUNCTION
+             || expr->token_type == NJS_TOKEN_FUNCTION_EXPRESSION
+             || expr->token_type == NJS_TOKEN_ASYNC_FUNCTION_EXPRESSION))
+        {
+            if (property->token_type == NJS_TOKEN_STRING) {
+                njs_value_assign(&expr->u.value.data.u.lambda->name,
+                                 &property->u.value);
+
+            } else {
+                njs_generate_code(generator, njs_vmcode_2addr_t, to_prop_key,
+                                  NJS_VMCODE_TO_PROPERTY_KEY, 2, property);
+
+                to_prop_key->src = property->index;
+                to_prop_key->dst = prop_index;
+
+                njs_generate_code(generator, njs_vmcode_2addr_t, set_function,
+                                  NJS_VMCODE_SET_FUNCTION_NAME, 2, expr);
+
+                set_function->dst = expr->index;
+                set_function->src = prop_index;
+            }
+        }
+
         njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set,
                           NJS_VMCODE_PROPERTY_INIT, 3, expr);
         break;
@@ -2882,7 +2934,7 @@ njs_generate_assignment_end(njs_vm_t *vm
 
     prop_set->value = expr->index;
     prop_set->object = object->index;
-    prop_set->property = property->index;
+    prop_set->property = prop_index;
 
     node->index = expr->index;
     node->temporary = expr->temporary;
@@ -3063,7 +3115,7 @@ njs_generate_operation_assignment_prop(n
         }
 
         njs_generate_code(generator, njs_vmcode_3addr_t, to_property_key,
-                          NJS_VMCODE_TO_PROPERTY_KEY, 2, property);
+                          NJS_VMCODE_TO_PROPERTY_KEY_CHK, 2, property);
 
         to_property_key->src2 = object->index;
         to_property_key->src1 = property->index;
@@ -3233,6 +3285,7 @@ static njs_int_t
 njs_generate_function_expression(njs_vm_t *vm, njs_generator_t *generator,
     njs_parser_node_t *node)
 {
+    ssize_t                  length;
     njs_int_t                ret;
     njs_variable_t           *var;
     njs_function_lambda_t    *lambda;
@@ -3262,6 +3315,17 @@ njs_generate_function_expression(njs_vm_
         return ret;
     }
 
+    length = njs_utf8_length(lex_entry->name.start, lex_entry->name.length);
+    if (njs_slow_path(length < 0)) {
+        return NJS_ERROR;
+    }
+
+    ret = njs_string_new(vm, &lambda->name, lex_entry->name.start,
+                         lex_entry->name.length, length);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return NJS_ERROR;
+    }
+
     njs_generate_code(generator, njs_vmcode_function_t, function,
                       NJS_VMCODE_FUNCTION, 1, node);
     function->lambda = lambda;
@@ -3289,7 +3353,7 @@ njs_generate_function(njs_vm_t *vm, njs_
     lambda = node->u.value.data.u.lambda;
 
     ret = njs_generate_function_scope(vm, generator, lambda, node,
-                                      &njs_entry_anonymous);
+                                      &njs_entry_empty);
     if (njs_slow_path(ret != NJS_OK)) {
         return ret;
     }
@@ -3731,7 +3795,7 @@ found:
         }
 
         njs_generate_code(generator, njs_vmcode_3addr_t, to_property_key,
-                          NJS_VMCODE_TO_PROPERTY_KEY, 2, node);
+                          NJS_VMCODE_TO_PROPERTY_KEY_CHK, 2, node);
 
         to_property_key->src2 = lvalue->left->index;
         to_property_key->src1 = lvalue->right->index;
@@ -3787,6 +3851,7 @@ static njs_int_t
 njs_generate_function_declaration(njs_vm_t *vm, njs_generator_t *generator,
     njs_parser_node_t *node)
 {
+    ssize_t                  length;
     njs_int_t                ret;
     njs_bool_t               async;
     njs_variable_t           *var;
@@ -3811,6 +3876,17 @@ njs_generate_function_declaration(njs_vm
         return NJS_ERROR;
     }
 
+    length = njs_utf8_length(lex_entry->name.start, lex_entry->name.length);
+    if (njs_slow_path(length < 0)) {
+        return NJS_ERROR;
+    }
+
+    ret = njs_string_new(vm, &lambda->name, lex_entry->name.start,
+                         lex_entry->name.length, length);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return NJS_ERROR;
+    }
+
     ret = njs_generate_function_scope(vm, generator, lambda, node,
                                       &lex_entry->name);
     if (njs_slow_path(ret != NJS_OK)) {
diff -r 33fcc9fc6704 -r 74d30c2d70f3 src/njs_object_prop.c
--- a/src/njs_object_prop.c	Mon Sep 19 17:36:02 2022 -0700
+++ b/src/njs_object_prop.c	Tue Sep 20 17:44:25 2022 -0700
@@ -452,6 +452,11 @@ done:
                     pq.lhq.value = NULL;
                     goto set_prop;
                 }
+
+            } else {
+
+                prev->type = prop->type;
+                njs_value_assign(&prev->value, &prop->value);
             }
 
         } else {
diff -r 33fcc9fc6704 -r 74d30c2d70f3 src/njs_parser.c
--- a/src/njs_parser.c	Mon Sep 19 17:36:02 2022 -0700
+++ b/src/njs_parser.c	Tue Sep 20 17:44:25 2022 -0700
@@ -6872,9 +6872,9 @@ njs_parser_function_parse(njs_parser_t *
 }
 
 
-static const njs_lexer_entry_t njs_parser_anonymous_entry =
-{
-    .name = njs_str("anonymous")
+static const njs_lexer_entry_t njs_parser_empty_entry =
+{
+    .name = njs_str("")
 };
 
 
@@ -6909,7 +6909,7 @@ njs_parser_function_expression(njs_parse
         }
 
     } else {
-        unique_id = (uintptr_t) &njs_parser_anonymous_entry;
+        unique_id = (uintptr_t) &njs_parser_empty_entry;
     }
 
     if (token->type != NJS_TOKEN_OPEN_PARENTHESIS) {
@@ -7155,7 +7155,7 @@ njs_parser_arrow_function(njs_parser_t *
 
     node->left = name;
 
-    unique_id = (uintptr_t) &njs_parser_anonymous_entry;
+    unique_id = (uintptr_t) &njs_parser_empty_entry;
 
     var = njs_variable_scope_add(parser, parser->scope, parser->scope,
                                  unique_id, NJS_VARIABLE_FUNCTION, 1);
diff -r 33fcc9fc6704 -r 74d30c2d70f3 src/njs_value.c
--- a/src/njs_value.c	Mon Sep 19 17:36:02 2022 -0700
+++ b/src/njs_value.c	Tue Sep 20 17:44:25 2022 -0700
@@ -54,6 +54,7 @@ const njs_value_t  njs_string_external =
 const njs_value_t  njs_string_invalid =     njs_string("invalid");
 const njs_value_t  njs_string_object =      njs_string("object");
 const njs_value_t  njs_string_function =    njs_string("function");
+const njs_value_t  njs_string_anonymous =   njs_string("anonymous");
 const njs_value_t  njs_string_memory_error = njs_string("MemoryError");
 
 
diff -r 33fcc9fc6704 -r 74d30c2d70f3 src/njs_value.h
--- a/src/njs_value.h	Mon Sep 19 17:36:02 2022 -0700
+++ b/src/njs_value.h	Tue Sep 20 17:44:25 2022 -0700
@@ -836,6 +836,7 @@ extern const njs_value_t  njs_string_ext
 extern const njs_value_t  njs_string_invalid;
 extern const njs_value_t  njs_string_object;
 extern const njs_value_t  njs_string_function;
+extern const njs_value_t  njs_string_anonymous;
 extern const njs_value_t  njs_string_memory_error;
 
 
diff -r 33fcc9fc6704 -r 74d30c2d70f3 src/njs_vm.c
--- a/src/njs_vm.c	Mon Sep 19 17:36:02 2022 -0700
+++ b/src/njs_vm.c	Tue Sep 20 17:44:25 2022 -0700
@@ -12,6 +12,7 @@ static njs_int_t njs_vm_init(njs_vm_t *v
 static njs_int_t njs_vm_handle_events(njs_vm_t *vm);
 
 
+const njs_str_t  njs_entry_empty =          njs_str("");
 const njs_str_t  njs_entry_main =           njs_str("main");
 const njs_str_t  njs_entry_module =         njs_str("module");
 const njs_str_t  njs_entry_native =         njs_str("native");
diff -r 33fcc9fc6704 -r 74d30c2d70f3 src/njs_vm.h
--- a/src/njs_vm.h	Mon Sep 19 17:36:02 2022 -0700
+++ b/src/njs_vm.h	Tue Sep 20 17:44:25 2022 -0700
@@ -267,6 +267,7 @@ void *njs_lvlhsh_alloc(void *data, size_
 void njs_lvlhsh_free(void *data, void *p, size_t size);
 
 
+extern const njs_str_t    njs_entry_empty;
 extern const njs_str_t    njs_entry_main;
 extern const njs_str_t    njs_entry_module;
 extern const njs_str_t    njs_entry_native;
diff -r 33fcc9fc6704 -r 74d30c2d70f3 src/njs_vmcode.c
--- a/src/njs_vmcode.c	Mon Sep 19 17:36:02 2022 -0700
+++ b/src/njs_vmcode.c	Tue Sep 20 17:44:25 2022 -0700
@@ -889,21 +889,41 @@ next:
                 break;
 
             case NJS_VMCODE_TO_PROPERTY_KEY:
+            case NJS_VMCODE_TO_PROPERTY_KEY_CHK:
                 njs_vmcode_operand(vm, (njs_index_t) value2, retval);
-                njs_vmcode_operand(vm, vmcode->operand3, value2);
-
-                if (njs_slow_path(njs_is_null_or_undefined(value2))) {
-                    (void) njs_throw_cannot_property(vm, value2, value1,
-                                                     "get");
-                    goto error;
+
+                if (op == NJS_VMCODE_TO_PROPERTY_KEY_CHK) {
+                    njs_vmcode_operand(vm, vmcode->operand3, value2);
+
+                    if (njs_slow_path(njs_is_null_or_undefined(value2))) {
+                        (void) njs_throw_cannot_property(vm, value2, value1,
+                                                         "get");
+                        goto error;
+                    }
                 }
 
-                ret = njs_value_to_string(vm, retval, value1);
+                ret = njs_value_to_key(vm, retval, value1);
                 if (njs_fast_path(ret == NJS_ERROR)) {
                     goto error;
                 }
 
-                ret = sizeof(njs_vmcode_3addr_t);
+                ret = (op == NJS_VMCODE_TO_PROPERTY_KEY)
+                       ? sizeof(njs_vmcode_2addr_t)
+                       : sizeof(njs_vmcode_3addr_t);
+                break;
+
+            case NJS_VMCODE_SET_FUNCTION_NAME:
+                njs_vmcode_operand(vm, (njs_index_t) value2, value2);
+
+                njs_assert(njs_is_function(value2));
+
+                ret = njs_function_name_set(vm, njs_function(value2), value1,
+                                            NULL);
+                if (njs_slow_path(ret == NJS_ERROR)) {
+                    return ret;
+                }
+
+                ret = sizeof(njs_vmcode_2addr_t);
                 break;
 
             case NJS_VMCODE_PROTO_INIT:
diff -r 33fcc9fc6704 -r 74d30c2d70f3 src/njs_vmcode.h
--- a/src/njs_vmcode.h	Mon Sep 19 17:36:02 2022 -0700
+++ b/src/njs_vmcode.h	Tue Sep 20 17:44:25 2022 -0700
@@ -50,6 +50,8 @@ enum {
     NJS_VMCODE_ARGUMENTS,
     NJS_VMCODE_PROTO_INIT,
     NJS_VMCODE_TO_PROPERTY_KEY,
+    NJS_VMCODE_TO_PROPERTY_KEY_CHK,
+    NJS_VMCODE_SET_FUNCTION_NAME,
     NJS_VMCODE_IMPORT,
 
     NJS_VMCODE_AWAIT,
diff -r 33fcc9fc6704 -r 74d30c2d70f3 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Mon Sep 19 17:36:02 2022 -0700
+++ b/src/test/njs_unit_test.c	Tue Sep 20 17:44:25 2022 -0700
@@ -3846,6 +3846,24 @@ static njs_unit_test_t  njs_test[] =
     { njs_str("({[{toString(){return {}}}]:1})"),
       njs_str("TypeError: Cannot convert object to primitive value") },
 
+    { njs_str("({['a' + 'v'](){}}).av.name"),
+      njs_str("av") },
+
+    { njs_str("({[Symbol.toStringTag](){}})[Symbol.toStringTag].name"),
+      njs_str("[Symbol.toStringTag]") },
+
+    { njs_str("var anonSym = Symbol(); ({[anonSym]: () => {}})[anonSym].name"),
+      njs_str("") },
+
+    { njs_str("var named = Symbol('xxx'); ({[named]: () => {}})[named].name"),
+      njs_str("[xxx]") },
+
+    { njs_str("var called = false;"
+             "({"
+             "   [{toString(){ if (called) throw 'OOps'; called = true; return 'a'}}](){}"
+             "}).a.name"),
+      njs_str("a") },
+
     { njs_str("var o = { [new Number(12345)]: 1000 }; o[12345]"),
       njs_str("1000") },
 
@@ -7740,6 +7758,10 @@ static njs_unit_test_t  njs_test[] =
                  "var o = { toString: f }; o"),
       njs_str("0,1,2") },
 
+    { njs_str("var f = function F() {};"
+              "[f.name, f.bind().name, f.bind().bind().name]"),
+      njs_str("F,bound F,bound bound F") },
+
     { njs_str("var f = Object.defineProperty(function() {}, 'name', {value: 'F'});"
               "[f.name, f.bind().name, f.bind().bind().name]"),
       njs_str("F,bound F,bound bound F") },
@@ -9948,6 +9970,53 @@ static njs_unit_test_t  njs_test[] =
               "f.length"),
       njs_str("42") },
 
+    { njs_str("function f(){}; f.name"),
+      njs_str("f") },
+
+    { njs_str("function f(){}; njs.dump(Object.getOwnPropertyDescriptor(f, 'name'))"),
+      njs_str("{value:'f',writable:false,enumerable:false,configurable:true}") },
+
+    { njs_str("function f(){}; Object.defineProperty(f, 'name', {value: 'F'}); f.name"),
+      njs_str("F") },
+
+    { njs_str("function f(){}; Object.defineProperty(f, 'name', {value: 'F'});"
+              "njs.dump(Object.getOwnPropertyDescriptor(f, 'name'))"),
+      njs_str("{value:'F',writable:false,enumerable:false,configurable:true}") },
+
+    { njs_str("function f() {}; f.name = 'a'"),
+      njs_str("TypeError: Cannot assign to read-only property \"name\" of function") },
+
+    { njs_str("(function f () { return f.name})()"),
+      njs_str("f") },
+
+    { njs_str("var a = function () {}; a.name"),
+      njs_str("a") },
+
+    { njs_str("(function () {}).name"),
+      njs_str("") },
+
+    { njs_str("var a = (null, function () {}); a.name"),
+      njs_str("") },
+
+    { njs_str("var a = async function () {}; a.name"),
+      njs_str("a") },
+
+    { njs_str("let a = () => {}; a.name"),
+      njs_str("a") },
+
+    { njs_str("let a = async () => {}; a.name"),
+      njs_str("a") },
+
+    { njs_str("Function().name"),
+      njs_str("anonymous") },
+
+    { njs_str("var o = {f: function (){}, g: () => {}, h: async function(){}};"
+              "[o.f.name, o.g.name, o.h.name]"),
+      njs_str("f,g,h") },
+
+    { njs_str("({t(){}}).t.name"),
+      njs_str("t") },
+
     /* Function nesting depth. */
 
     { njs_str("() => () => () => () => () => () => () => () => () => () => () =>"
@@ -14789,7 +14858,7 @@ static njs_unit_test_t  njs_test[] =
       njs_str("0,1,2,length") },
 
     { njs_str("Object.getOwnPropertyNames(function() {})"),
-      njs_str("length,prototype") },
+      njs_str("length,name,prototype") },
 
     { njs_str("Object.getOwnPropertyNames(Array)"),
       njs_str("name,length,prototype,isArray,of") },



More information about the nginx-devel mailing list