]> git.kaiwu.me - njs.git/commitdiff
Fixed Error.prototype.toString().
authorDmitry Volyntsev <xeioex@nginx.com>
Mon, 5 Aug 2019 14:10:59 +0000 (17:10 +0300)
committerDmitry Volyntsev <xeioex@nginx.com>
Mon, 5 Aug 2019 14:10:59 +0000 (17:10 +0300)
1) with UTF8 string properties.
1) with non-string values for "name" and "message" properties.

This closes #199 issue on Github.

src/njs_error.c
src/test/njs_unit_test.c

index 4d807e46f57fc912be4bdd2646c6c00744ab7661..e60178d746e108a48b00b938e0a747e959b68520 100644 (file)
@@ -617,12 +617,12 @@ njs_error_prototype_to_string(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
 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_value_t *retval, const njs_value_t *error)
         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_value_t *retval, const njs_value_t *error)
         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;
+
+    } else {
+        length = 0;
+    }
 
-    p = njs_string_alloc(vm, retval, size, size);
+    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;
     }
index 5207cedb2e7f3244b7bed0bb403edef2518168a7..8b791e5e96b5843510eb80ec7ba5c2e929feaeee 100644 (file)
@@ -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") },