[njs] Fixed Error.prototype.toString().

Dmitry Volyntsev xeioex at nginx.com
Wed Aug 7 18:28:58 UTC 2019


details:   https://hg.nginx.org/njs/rev/e47f82b5f2ca
branches:  
changeset: 1115:e47f82b5f2ca
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Mon Aug 05 17:10:59 2019 +0300
description:
Fixed Error.prototype.toString().

1) with UTF8 string properties.
1) with non-string values for "name" and "message" properties.

This closes #199 issue on Github.

diffstat:

 src/njs_error.c          |  50 +++++++++++++++++++++++++++++++++++------------
 src/test/njs_unit_test.c |  27 ++++++++++++++++++++++++-
 2 files changed, 63 insertions(+), 14 deletions(-)

diffs (137 lines):

diff -r b9d9f2813d9a -r e47f82b5f2ca src/njs_error.c
--- a/src/njs_error.c	Tue Aug 06 22:54:13 2019 -0400
+++ b/src/njs_error.c	Mon Aug 05 17:10:59 2019 +0300
@@ -617,12 +617,12 @@ njs_error_prototype_to_string(njs_vm_t *
 njs_int_t
 njs_error_to_string(njs_vm_t *vm, njs_value_t *retval, const njs_value_t *error)
 {
-    size_t              size;
+    size_t              length;
     u_char              *p;
     njs_int_t           ret;
-    njs_str_t           name, message;
     njs_value_t         value1, value2;
-    const njs_value_t   *name_value, *message_value;
+    njs_value_t         *name_value, *message_value;
+    njs_string_prop_t   name, message;
     njs_lvlhsh_query_t  lhq;
 
     static const njs_value_t  default_name = njs_string("Error");
@@ -635,9 +635,18 @@ njs_error_to_string(njs_vm_t *vm, njs_va
         return ret;
     }
 
-    name_value = (ret == NJS_OK) ? &value1 : &default_name;
+    name_value = (ret == NJS_OK) ? &value1 : njs_value_arg(&default_name);
 
-    njs_string_get(name_value, &name);
+    if (njs_slow_path(!njs_is_string(name_value))) {
+        ret = njs_value_to_string(vm, &value1, name_value);
+        if (njs_slow_path(ret != NJS_OK)) {
+            return ret;
+        }
+
+        name_value = &value1;
+    }
+
+    (void) njs_string_prop(&name, name_value);
 
     lhq.key_hash = NJS_MESSAGE_HASH;
     lhq.key = njs_str_value("message");
@@ -648,29 +657,44 @@ njs_error_to_string(njs_vm_t *vm, njs_va
         return ret;
     }
 
-    message_value = (ret == NJS_OK) ? &value2 : &njs_string_empty;
+    message_value = (ret == NJS_OK) ? &value2
+                                    : njs_value_arg(&njs_string_empty);
 
-    njs_string_get(message_value, &message);
+    if (njs_slow_path(!njs_is_string(message_value))) {
+        ret = njs_value_to_string(vm, &value2, message_value);
+        if (njs_slow_path(ret != NJS_OK)) {
+            return ret;
+        }
 
-    if (name.length == 0) {
+        message_value = &value2;
+    }
+
+    (void) njs_string_prop(&message, message_value);
+
+    if (name.size == 0) {
         *retval = *message_value;
         return NJS_OK;
     }
 
-    if (message.length == 0) {
+    if (message.size == 0) {
         *retval = *name_value;
         return NJS_OK;
     }
 
-    size = name.length + message.length + 2;
+    if (name.length != 0 && message.length != 0) {
+        length = name.length + message.length + 2;
 
-    p = njs_string_alloc(vm, retval, size, size);
+    } else {
+        length = 0;
+    }
+
+    p = njs_string_alloc(vm, retval, name.size + message.size + 2, length);
 
     if (njs_fast_path(p != NULL)) {
-        p = njs_cpymem(p, name.start, name.length);
+        p = njs_cpymem(p, name.start, name.size);
         *p++ = ':';
         *p++ = ' ';
-        memcpy(p, message.start, message.length);
+        memcpy(p, message.start, message.size);
 
         return NJS_OK;
     }
diff -r b9d9f2813d9a -r e47f82b5f2ca src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Tue Aug 06 22:54:13 2019 -0400
+++ b/src/test/njs_unit_test.c	Mon Aug 05 17:10:59 2019 +0300
@@ -7835,7 +7835,25 @@ static njs_unit_test_t  njs_test[] =
     { njs_str("Error('e')"),
       njs_str("Error: e") },
 
-    { njs_str("var e = Error('e'); e.name = 'E'; e"),
+    { njs_str("Error(123)"),
+      njs_str("Error: 123") },
+
+    { njs_str("Error({toString(){return 'e'}})"),
+      njs_str("Error: e") },
+
+    { njs_str("Error([1,'α'])"),
+      njs_str("Error: 1,α") },
+
+    { njs_str("var e = TypeError(Error('e')); e"),
+      njs_str("TypeError: Error: e") },
+
+    { njs_str("Error('α'.repeat(33)).toString().length"),
+      njs_str("40") },
+
+    { njs_str("var e = Error('e'); e.name = {toString(){return 'E'}}; e"),
+      njs_str("E: e") },
+
+    { njs_str("var e = Error('e'); Object.defineProperty(e, 'name', {get(){return 'E'}}); e"),
       njs_str("E: e") },
 
     { njs_str("var e = Error('e'); e.name = ''; e"),
@@ -7850,6 +7868,13 @@ static njs_unit_test_t  njs_test[] =
     { njs_str("Error('e').name + ': ' + Error('e').message"),
       njs_str("Error: e") },
 
+    { njs_str("Error(String.bytesFrom(Array(1).fill(0x9d))).toString().length"),
+      njs_str("8") },
+
+    { njs_str("var e = Error('α'); e.name = String.bytesFrom(Array(1).fill(0x9d)); "
+              "e.toString().length"),
+      njs_str("5") },
+
     { njs_str("Error(1)"),
       njs_str("Error: 1") },
 


More information about the nginx-devel mailing list