[njs] Fixed SetFunctionName() with Symbol keys.

Dmitry Volyntsev xeioex at nginx.com
Thu Jul 9 14:00:27 UTC 2020


details:   https://hg.nginx.org/njs/rev/5f2034557bc3
branches:  
changeset: 1463:5f2034557bc3
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Thu Jul 09 13:57:10 2020 +0000
description:
Fixed SetFunctionName() with Symbol keys.

This improves 85c1b6ba326b.

diffstat:

 src/njs_builtin.c        |  27 +++++++++----
 src/njs_function.c       |  45 ++++++++++++++++++------
 src/njs_function.h       |   2 +-
 src/njs_json.c           |   4 +-
 src/njs_object.h         |   2 +-
 src/njs_object_prop.c    |   2 +-
 src/njs_string.c         |   2 +-
 src/njs_symbol.c         |  88 +++++++++++++++++++----------------------------
 src/njs_symbol.h         |   5 +-
 src/test/njs_unit_test.c |  10 +++++
 10 files changed, 106 insertions(+), 81 deletions(-)

diffs (377 lines):

diff -r 0c941c887ab7 -r 5f2034557bc3 src/njs_builtin.c
--- a/src/njs_builtin.c	Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_builtin.c	Thu Jul 09 13:57:10 2020 +0000
@@ -396,6 +396,7 @@ njs_builtin_traverse(njs_vm_t *vm, njs_t
     u_char                  *p, *start, *end;
     njs_int_t               ret, n;
     njs_str_t               name;
+    njs_bool_t              symbol;
     njs_value_t             key;
     njs_function_t          *func;
     njs_object_prop_t       *prop;
@@ -431,29 +432,37 @@ njs_builtin_traverse(njs_vm_t *vm, njs_t
     end = buf + sizeof(buf);
 
     do {
+        symbol = 0;
         key = path[n]->prop->name;
 
         if (njs_slow_path(njs_is_symbol(&key))) {
-            ret = njs_symbol_to_string(vm, &key, &key, 1);
-            if (njs_slow_path(ret != NJS_OK)) {
-                name = njs_str_value("#BROKEN_KEY");
-            }
-
-        } else {
-            if (p != buf) {
-                *p++ = '.';
+            symbol = 1;
+            key = *njs_symbol_description(&key);
+            if (njs_is_undefined(&key)) {
+                key = njs_string_empty;
             }
         }
 
         njs_string_get(&key, &name);
 
-        if (njs_slow_path((p + name.length + 1) > end)) {
+        if (njs_slow_path((p + name.length + 3) > end)) {
             njs_type_error(vm, "njs_builtin_traverse() key is too long");
             return NJS_ERROR;
         }
 
+        if (symbol) {
+            *p++ = '[';
+
+        } else if (p != buf) {
+            *p++ = '.';
+        }
+
         p = njs_cpymem(p, name.start, name.length);
 
+        if (symbol) {
+            *p++ = ']';
+        }
+
     } while (n-- > 0);
 
     if (ctx->type == NJS_BUILTIN_TRAVERSE_MATCH) {
diff -r 0c941c887ab7 -r 5f2034557bc3 src/njs_function.c
--- a/src/njs_function.c	Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_function.c	Thu Jul 09 13:57:10 2020 +0000
@@ -131,30 +131,53 @@ njs_function_active_closures(njs_vm_t *v
 
 njs_int_t
 njs_function_name_set(njs_vm_t *vm, njs_function_t *function,
-    njs_value_t *name, njs_bool_t bound)
+    njs_value_t *name, const char *prefix)
 {
-    u_char              *start;
+    u_char              *p;
+    size_t              len, symbol;
     njs_int_t           ret;
+    njs_value_t         value;
     njs_string_prop_t   string;
     njs_object_prop_t   *prop;
     njs_lvlhsh_query_t  lhq;
 
     prop = njs_object_prop_alloc(vm, &njs_string_name, name, 0);
-    if (njs_slow_path(name == NULL)) {
+    if (njs_slow_path(prop == NULL)) {
         return NJS_ERROR;
     }
 
-    if (bound) {
-        (void) njs_string_prop(&string, name);
+    symbol = 0;
+
+    if (njs_is_symbol(&prop->value)) {
+        symbol = 2;
+        prop->value = *njs_symbol_description(&prop->value);
+    }
 
-        start = njs_string_alloc(vm, &prop->value, string.size + 6,
-                                 string.length + 6);
-        if (njs_slow_path(start == NULL)) {
+    if (prefix != NULL || symbol != 0) {
+        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;
         }
 
-        start = njs_cpymem(start, "bound ", 6);
-        memcpy(start, string.start, string.size);
+        if (len != 0) {
+            p = njs_cpymem(p, prefix, len - 1);
+            *p++ = ' ';
+        }
+
+        if (symbol != 0) {
+            *p++ = '[';
+        }
+
+        p = njs_cpymem(p, string.start, string.size);
+
+        if (symbol != 0) {
+            *p++ = ']';
+        }
     }
 
     prop->configurable = 1;
@@ -1204,7 +1227,7 @@ njs_function_prototype_bind(njs_vm_t *vm
         name = njs_string_empty;
     }
 
-    ret = njs_function_name_set(vm, function, &name, 1);
+    ret = njs_function_name_set(vm, function, &name, "bound");
     if (njs_slow_path(ret == NJS_ERROR)) {
         return ret;
     }
diff -r 0c941c887ab7 -r 5f2034557bc3 src/njs_function.h
--- a/src/njs_function.h	Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_function.h	Thu Jul 09 13:57:10 2020 +0000
@@ -93,7 +93,7 @@ njs_function_t *njs_function_alloc(njs_v
     njs_closure_t *closures[], njs_bool_t shared);
 njs_function_t *njs_function_value_copy(njs_vm_t *vm, njs_value_t *value);
 njs_int_t njs_function_name_set(njs_vm_t *vm, njs_function_t *function,
-    njs_value_t *name, njs_bool_t bound);
+    njs_value_t *name, const char *prefix);
 njs_int_t njs_function_arguments_object_init(njs_vm_t *vm,
     njs_native_frame_t *frame);
 njs_int_t njs_function_rest_parameters_init(njs_vm_t *vm,
diff -r 0c941c887ab7 -r 5f2034557bc3 src/njs_json.c
--- a/src/njs_json.c	Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_json.c	Thu Jul 09 13:57:10 2020 +0000
@@ -1856,7 +1856,7 @@ njs_dump_terminal(njs_json_stringify_t *
     case NJS_OBJECT_SYMBOL:
         value = njs_object_value(value);
 
-        ret = njs_symbol_to_string(stringify->vm, &str_val, value, 0);
+        ret = njs_symbol_descriptive_string(stringify->vm, &str_val, value);
         if (njs_slow_path(ret != NJS_OK)) {
             return NJS_ERROR;
         }
@@ -1867,7 +1867,7 @@ njs_dump_terminal(njs_json_stringify_t *
         break;
 
     case NJS_SYMBOL:
-        ret = njs_symbol_to_string(stringify->vm, &str_val, value, 0);
+        ret = njs_symbol_descriptive_string(stringify->vm, &str_val, value);
         if (njs_slow_path(ret != NJS_OK)) {
             return NJS_ERROR;
         }
diff -r 0c941c887ab7 -r 5f2034557bc3 src/njs_object.h
--- a/src/njs_object.h	Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_object.h	Thu Jul 09 13:57:10 2020 +0000
@@ -213,7 +213,7 @@ njs_key_string_get(njs_vm_t *vm, njs_val
     njs_int_t  ret;
 
     if (njs_slow_path(njs_is_symbol(key))) {
-        ret = njs_symbol_to_string(vm, key, key, 0);
+        ret = njs_symbol_descriptive_string(vm, key, key);
         if (njs_slow_path(ret != NJS_OK)) {
             return ret;
         }
diff -r 0c941c887ab7 -r 5f2034557bc3 src/njs_object_prop.c
--- a/src/njs_object_prop.c	Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_object_prop.c	Thu Jul 09 13:57:10 2020 +0000
@@ -554,7 +554,7 @@ njs_prop_private_copy(njs_vm_t *vm, njs_
             return NJS_ERROR;
         }
 
-        return njs_function_name_set(vm, function, &prop->name, 0);
+        return njs_function_name_set(vm, function, &prop->name, NULL);
 
     default:
         break;
diff -r 0c941c887ab7 -r 5f2034557bc3 src/njs_string.c
--- a/src/njs_string.c	Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_string.c	Thu Jul 09 13:57:10 2020 +0000
@@ -486,7 +486,7 @@ njs_string_constructor(njs_vm_t *vm, njs
 
         if (njs_slow_path(!njs_is_string(value))) {
             if (!vm->top_frame->ctor && njs_is_symbol(value)) {
-                return njs_symbol_to_string(vm, &vm->retval, value, 0);
+                return njs_symbol_descriptive_string(vm, &vm->retval, value);
             }
 
             ret = njs_value_to_string(vm, value, value);
diff -r 0c941c887ab7 -r 5f2034557bc3 src/njs_symbol.c
--- a/src/njs_symbol.c	Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_symbol.c	Thu Jul 09 13:57:10 2020 +0000
@@ -54,56 +54,52 @@ static const njs_value_t  *njs_symbol_na
 };
 
 
-njs_int_t
-njs_symbol_to_string(njs_vm_t *vm, njs_value_t *dst, const njs_value_t *value,
-    njs_bool_t as_name)
+const njs_value_t *
+njs_symbol_description(const njs_value_t *value)
 {
-    u_char             *start;
     const njs_value_t  *name;
-    njs_string_prop_t  string;
-
-    static const njs_value_t  string_symbol = njs_string("Symbol()");
 
-    name = value->data.u.value;
-
-    if (name == NULL) {
-        if (njs_fast_path(njs_symbol_key(value) < NJS_SYMBOL_KNOWN_MAX)) {
+    if (njs_symbol_key(value) < NJS_SYMBOL_KNOWN_MAX) {
+        name = njs_symbol_names[njs_symbol_key(value)];
 
-            name = njs_symbol_names[njs_symbol_key(value)];
+    } else {
+        name = value->data.u.value;
 
-        } else {
-            *dst = string_symbol;
-
-            return NJS_OK;
+        if (name == NULL) {
+            return  &njs_value_undefined;
         }
     }
 
-    (void) njs_string_prop(&string, name);
+    return name;
+}
 
-    if (as_name) {
-        string.length += njs_length("[]");
 
-        start = njs_string_alloc(vm, dst, string.size + 2, string.length);
-        if (njs_slow_path(start == NULL)) {
-            return NJS_ERROR;
-        }
+njs_int_t
+njs_symbol_descriptive_string(njs_vm_t *vm, njs_value_t *dst,
+    const njs_value_t *value)
+{
+    u_char             *start;
+    const njs_value_t  *description;
+    njs_string_prop_t  string;
+
+    description = njs_symbol_description(value);
 
-        start = njs_cpymem(start, "[", 1);
-        start = njs_cpymem(start, string.start, string.size);
-        *start = ']';
+    if (njs_is_undefined(description)) {
+        description = &njs_string_empty;
+    }
 
-    } else {
-        string.length += njs_length("Symbol()");
+    (void) njs_string_prop(&string, description);
+
+    string.length += njs_length("Symbol()");
 
-        start = njs_string_alloc(vm, dst, string.size + 8, string.length);
-        if (njs_slow_path(start == NULL)) {
-            return NJS_ERROR;
-        }
+    start = njs_string_alloc(vm, dst, string.size + 8, string.length);
+    if (njs_slow_path(start == NULL)) {
+        return NJS_ERROR;
+    }
 
-        start = njs_cpymem(start, "Symbol(", 7);
-        start = njs_cpymem(start, string.start, string.size);
-        *start = ')';
-    }
+    start = njs_cpymem(start, "Symbol(", 7);
+    start = njs_cpymem(start, string.start, string.size);
+    *start = ')';
 
     return NJS_OK;
 }
@@ -344,7 +340,7 @@ njs_symbol_prototype_to_string(njs_vm_t 
         return ret;
     }
 
-    return njs_symbol_to_string(vm, &vm->retval, &vm->retval, 0);
+    return njs_symbol_descriptive_string(vm, &vm->retval, &vm->retval);
 }
 
 
@@ -352,28 +348,14 @@ static njs_int_t
 njs_symbol_prototype_description(njs_vm_t *vm, njs_value_t *args,
     njs_uint_t nargs, njs_index_t unused)
 {
-    njs_int_t          ret;
-    const njs_value_t  *value, *name;
+    njs_int_t  ret;
 
     ret = njs_symbol_prototype_value_of(vm, args, nargs, unused);
     if (njs_slow_path(ret != NJS_OK)) {
         return ret;
     }
 
-    value = &vm->retval;
-
-    name = value->data.u.value;
-
-    if (name == NULL) {
-        if (njs_fast_path(njs_symbol_key(value) < NJS_SYMBOL_KNOWN_MAX)) {
-            name = njs_symbol_names[njs_symbol_key(value)];
-
-        } else {
-            name = &njs_value_undefined;
-        }
-    }
-
-    vm->retval = *name;
+    vm->retval = *njs_symbol_description(&vm->retval);
 
     return NJS_OK;
 }
diff -r 0c941c887ab7 -r 5f2034557bc3 src/njs_symbol.h
--- a/src/njs_symbol.h	Wed Jul 08 13:07:06 2020 +0000
+++ b/src/njs_symbol.h	Thu Jul 09 13:57:10 2020 +0000
@@ -7,8 +7,9 @@
 #ifndef _NJS_SYMBOL_H_INCLUDED_
 #define _NJS_SYMBOL_H_INCLUDED_
 
-njs_int_t njs_symbol_to_string(njs_vm_t *vm, njs_value_t *dst,
-    const njs_value_t *value, njs_bool_t as_name);
+const njs_value_t *njs_symbol_description(const njs_value_t *value);
+njs_int_t njs_symbol_descriptive_string(njs_vm_t *vm, njs_value_t *dst,
+    const njs_value_t *value);
 
 
 extern const njs_object_type_init_t  njs_symbol_type_init;
diff -r 0c941c887ab7 -r 5f2034557bc3 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Wed Jul 08 13:07:06 2020 +0000
+++ b/src/test/njs_unit_test.c	Thu Jul 09 13:57:10 2020 +0000
@@ -6698,6 +6698,13 @@ static njs_unit_test_t  njs_test[] =
               "[f.name, f.bind().name]"),
       njs_str("F,bound F") },
 
+    { njs_str("var s = Symbol('F'); var f = Object.defineProperty(function() {}, 'name', {get:()=>s});"
+              "[f.name.description, f.bind().name]"),
+      njs_str("F,bound ") },
+
+    { njs_str("/a/[Symbol.replace].bind().name"),
+      njs_str("bound [Symbol.replace]") },
+
     { njs_str("var f = Object.defineProperty(function() {}, 'name', {get:()=>{throw Error('Oops')}});"
               "f.bind().name"),
       njs_str("Error: Oops") },
@@ -7736,6 +7743,9 @@ static njs_unit_test_t  njs_test[] =
               "'ABC'.replace(/(B)/, '$<g>')"),
       njs_str("OOps") },
 
+    { njs_str("var name = /a/g[Symbol.replace].name; [name, typeof name]"),
+      njs_str("[Symbol.replace],string") },
+
     { njs_str("RegExp.prototype[Symbol.replace].call()"),
       njs_str("TypeError: \"this\" is not object") },
 


More information about the nginx-devel mailing list