]> git.kaiwu.me - njs.git/commitdiff
Adding textual description for type converting exceptions.
authorDmitry Volyntsev <xeioex@nginx.com>
Mon, 12 Feb 2018 11:54:24 +0000 (14:54 +0300)
committerDmitry Volyntsev <xeioex@nginx.com>
Mon, 12 Feb 2018 11:54:24 +0000 (14:54 +0300)
14 files changed:
njs/njs_array.c
njs/njs_boolean.c
njs/njs_date.c
njs/njs_error.c
njs/njs_function.c
njs/njs_number.c
njs/njs_object.c
njs/njs_regexp.c
njs/njs_string.c
njs/njs_vm.c
njs/njs_vm.h
njs/test/njs_expect_test.exp
njs/test/njs_interactive_test.c
njs/test/njs_unit_test.c

index 8b1d559702346b348980c9919162cc3993d02c26..25270ff3ff99a9fd9cb6cfc17f19b81963a5b872 100644 (file)
@@ -1714,7 +1714,7 @@ njs_array_prototype_reduce(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
         n = njs_array_iterator_index(array, iter);
 
         if (n == NJS_ARRAY_INVALID_INDEX) {
-            njs_exception_type_error(vm, NULL, NULL);
+            njs_exception_type_error(vm, "invalid index", NULL);
             return NXT_ERROR;
         }
 
@@ -1775,7 +1775,7 @@ njs_array_iterator_args(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs)
         return NXT_OK;
     }
 
-    njs_exception_type_error(vm, NULL, NULL);
+    njs_exception_type_error(vm, "unexpected iterator arguments", NULL);
 
     return NXT_ERROR;
 }
@@ -1849,7 +1849,9 @@ njs_array_prototype_reduce_right(njs_vm_t *vm, njs_value_t *args,
         n = njs_array_reduce_right_index(array, iter);
 
         if (n == NJS_ARRAY_INVALID_INDEX) {
-            goto type_error;
+            njs_exception_type_error(vm, "invalid index", NULL);
+
+            return NXT_ERROR;
         }
 
         iter->retval = array->start[n];
@@ -1857,11 +1859,6 @@ njs_array_prototype_reduce_right(njs_vm_t *vm, njs_value_t *args,
 
     return njs_array_prototype_reduce_right_continuation(vm, args, nargs,
                                                          unused);
-type_error:
-
-    njs_exception_type_error(vm, NULL, NULL);
-
-    return NXT_ERROR;
 }
 
 
index ee1cb51edb0f799d8cb977d64dde392e82e93128..2b258f425c260ae64bd9584f8803ef404a774871 100644 (file)
@@ -99,7 +99,8 @@ njs_boolean_prototype_value_of(njs_vm_t *vm, njs_value_t *args,
             value = &value->data.u.object_value->value;
 
         } else {
-            njs_exception_type_error(vm, NULL, NULL);
+            njs_exception_type_error(vm, "unexpected value type:%s",
+                                     njs_type_string(value->type));
             return NXT_ERROR;
         }
     }
@@ -124,7 +125,8 @@ njs_boolean_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
             value = &value->data.u.object_value->value;
 
         } else {
-            njs_exception_type_error(vm, NULL, NULL);
+            njs_exception_type_error(vm, "unexpected value type:%s",
+                                     njs_type_string(value->type));
             return NXT_ERROR;
         }
     }
index b87b1f3a521e3f8a26dc0323231fabd9b516be17..64229af3f4c80f1374d4b5c71b2d6198956b01ed 100644 (file)
@@ -1911,7 +1911,7 @@ njs_date_prototype_to_json(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
         }
     }
 
-    njs_exception_type_error(vm, NULL, NULL);
+    njs_exception_type_error(vm, "'this' argument is not an object", NULL);
 
     return NXT_ERROR;
 }
index 5d9650e98b9b4f49125dc53dc9bf5e195edaa122..6d1e285f84ba02ac2ed4108c57e4bb72e75e1c1b 100644 (file)
@@ -612,7 +612,7 @@ njs_error_prototype_to_string(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     static const njs_value_t  default_name = njs_string("Error");
 
     if (nargs < 1 || !njs_is_object(&args[0])) {
-        njs_exception_type_error(vm, NULL, NULL);
+        njs_exception_type_error(vm, "'this' argument is not an object", NULL);
         return NXT_ERROR;
     }
 
index 63ec876b9ce96816ccf301bb55e1d0fd57e259ef..2f17e5d68e798b3794b07391d8efaebe598db005 100644 (file)
@@ -509,7 +509,7 @@ njs_function_prototype_call(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_function_t  *function;
 
     if (!njs_is_function(&args[0])) {
-        njs_exception_type_error(vm, NULL, NULL);
+        njs_exception_type_error(vm, "'this' argument is not a function", NULL);
         return NXT_ERROR;
     }
 
@@ -537,7 +537,8 @@ njs_function_prototype_apply(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_function_t  *function;
 
     if (!njs_is_function(&args[0])) {
-        goto type_error;
+        njs_exception_type_error(vm, "'this' argument is not a function", NULL);
+        return NXT_ERROR;
     }
 
     function = args[0].data.u.function;
@@ -545,7 +546,9 @@ njs_function_prototype_apply(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
 
     if (nargs > 2) {
         if (!njs_is_array(&args[2])) {
-            goto type_error;
+            njs_exception_type_error(vm, "second argument is not an array",
+                                     NULL);
+            return NXT_ERROR;
         }
 
         array = args[2].data.u.array;
@@ -561,12 +564,6 @@ njs_function_prototype_apply(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     }
 
     return njs_function_activate(vm, function, this, args, nargs, retval);
-
-type_error:
-
-    njs_exception_type_error(vm, NULL, NULL);
-
-    return NXT_ERROR;
 }
 
 
@@ -622,7 +619,7 @@ njs_function_prototype_bind(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_function_t  *function;
 
     if (!njs_is_function(&args[0])) {
-        njs_exception_type_error(vm, NULL, NULL);
+        njs_exception_type_error(vm, "'this' argument is not a function", NULL);
         return NXT_ERROR;
     }
 
index affc5461195aae55c96d2516a354127c7f05d345..3b648b7d0ceaa7e369ce94bfefb3cfc68b0fab4a 100644 (file)
@@ -586,7 +586,8 @@ njs_number_prototype_value_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
             value = &value->data.u.object_value->value;
 
         } else {
-            njs_exception_type_error(vm, NULL, NULL);
+            njs_exception_type_error(vm, "unexpected value type:%s",
+                                     njs_type_string(value->type));
             return NXT_ERROR;
         }
     }
@@ -612,7 +613,8 @@ njs_number_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
             value = &value->data.u.object_value->value;
 
         } else {
-            njs_exception_type_error(vm, NULL, NULL);
+            njs_exception_type_error(vm, "unexpected value type:%s",
+                                     njs_type_string(value->type));
             return NXT_ERROR;
         }
     }
index 29e392a9b570926016bd53b61853e1c958d3951c..68e262dad98d5c074bfb8b3bd33b1d36fb4ff52f 100644 (file)
@@ -224,8 +224,6 @@ njs_object_property(njs_vm_t *vm, njs_object_t *object, nxt_lvlhsh_query_t *lhq)
 
     } while (object != NULL);
 
-    njs_exception_type_error(vm, NULL, NULL);
-
     return NULL;
 }
 
@@ -264,7 +262,8 @@ njs_object_constructor(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
             type = njs_object_value_type(value->type);
 
         } else {
-            njs_exception_type_error(vm, NULL, NULL);
+            njs_exception_type_error(vm, "unexpected constructor argument:%s",
+                                     njs_type_string(value->type));
 
             return NXT_ERROR;
         }
@@ -312,7 +311,7 @@ njs_object_create(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
         }
     }
 
-    njs_exception_type_error(vm, NULL, NULL);
+    njs_exception_type_error(vm, "too few arguments", NULL);
 
     return NXT_ERROR;
 }
@@ -325,7 +324,10 @@ njs_object_keys(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_array_t  *keys;
 
     if (nargs < 2 || !njs_is_object(&args[1])) {
-        njs_exception_type_error(vm, NULL, NULL);
+        njs_exception_type_error(vm, "cannot convert %s argument to object",
+                                 (nargs >= 2) ? njs_type_string(args[1].type)
+                                              : "null");
+
         return NXT_ERROR;
     }
 
@@ -426,15 +428,24 @@ static njs_ret_t
 njs_object_define_property(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_index_t unused)
 {
-    nxt_int_t  ret;
+    nxt_int_t   ret;
+    const char  *type;
 
     if (nargs < 4 || !njs_is_object(&args[1]) || !njs_is_object(&args[3])) {
-        njs_exception_type_error(vm, NULL, NULL);
+        if (nargs < 2 || !njs_is_object(&args[1])) {
+            type = (nargs > 1) ? njs_type_string(args[1].type) : "null";
+            njs_exception_type_error(vm, "cannot convert %s argument to object",
+                                     type);
+
+        } else {
+            njs_exception_type_error(vm, "descriptor is not an object", NULL);
+        }
+
         return NXT_ERROR;
     }
 
     if (!args[1].data.u.object->extensible) {
-        njs_exception_type_error(vm, NULL, NULL);
+        njs_exception_type_error(vm, "object is not extensible", NULL);
         return NXT_ERROR;
     }
 
@@ -456,18 +467,27 @@ njs_object_define_properties(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_index_t unused)
 {
     nxt_int_t          ret;
+    const char         *type;
     nxt_lvlhsh_t       *hash;
     njs_object_t       *object;
     nxt_lvlhsh_each_t  lhe;
     njs_object_prop_t  *prop;
 
     if (nargs < 3 || !njs_is_object(&args[1]) || !njs_is_object(&args[2])) {
-        njs_exception_type_error(vm, NULL, NULL);
+        if (nargs < 2 || !njs_is_object(&args[1])) {
+            type = (nargs > 1) ? njs_type_string(args[1].type) : "null";
+            njs_exception_type_error(vm, "cannot convert %s argument to object",
+                                     type);
+
+        } else {
+            njs_exception_type_error(vm, "descriptor is not an object", NULL);
+        }
+
         return NXT_ERROR;
     }
 
     if (!args[1].data.u.object->extensible) {
-        njs_exception_type_error(vm, NULL, NULL);
+        njs_exception_type_error(vm, "object is not extensible", NULL);
         return NXT_ERROR;
     }
 
@@ -590,6 +610,7 @@ njs_object_get_own_property_descriptor(njs_vm_t *vm, njs_value_t *args,
 {
     uint32_t            index;
     nxt_int_t           ret;
+    const char          *type;
     njs_array_t         *array;
     njs_object_t        *descriptor;
     njs_object_prop_t   *pr, *prop, array_prop;
@@ -597,7 +618,9 @@ njs_object_get_own_property_descriptor(njs_vm_t *vm, njs_value_t *args,
     nxt_lvlhsh_query_t  lhq;
 
     if (nargs < 3 || !njs_is_object(&args[1])) {
-        njs_exception_type_error(vm, NULL, NULL);
+        type = (nargs > 1) ? njs_type_string(args[1].type) : "null";
+        njs_exception_type_error(vm, "cannot convert %s argument to object",
+                                 type);
         return NXT_ERROR;
     }
 
@@ -726,7 +749,9 @@ njs_object_get_prototype_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
         return NXT_OK;
     }
 
-    njs_exception_type_error(vm, NULL, NULL);
+    njs_exception_type_error(vm, "cannot convert %s argument to object",
+                             (nargs > 1) ? njs_type_string(args[1].type)
+                                         : "null");
     return NXT_ERROR;
 }
 
index 974a42252119e51b3c7667c170ec92e3d2e2c7ba..21d21196139a797f76e60553178085598e5d1a09 100644 (file)
@@ -573,7 +573,7 @@ njs_regexp_prototype_to_string(njs_vm_t *vm, njs_value_t *args,
         return njs_regexp_string_create(vm, &vm->retval, source, size, length);
     }
 
-    njs_exception_type_error(vm, NULL, NULL);
+    njs_exception_type_error(vm, "'this' argument is not a regexp", NULL);
 
     return NXT_ERROR;
 }
@@ -591,7 +591,7 @@ njs_regexp_prototype_test(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_regexp_pattern_t  *pattern;
 
     if (!njs_is_regexp(&args[0])) {
-        njs_exception_type_error(vm, NULL, NULL);
+        njs_exception_type_error(vm, "'this' argument is not a regexp", NULL);
         return NXT_ERROR;
     }
 
@@ -641,7 +641,7 @@ njs_regexp_prototype_exec(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     nxt_regex_match_data_t  *match_data;
 
     if (!njs_is_regexp(&args[0])) {
-        njs_exception_type_error(vm, NULL, NULL);
+        njs_exception_type_error(vm, "'this' argument is not a regexp", NULL);
         return NXT_ERROR;
     }
 
index cfd278d751b448ba8bf2b97b396bba72067dfa14..ced809c4caf6879f2db50dcfa2c38316f4d6c561 100644 (file)
@@ -553,7 +553,8 @@ njs_string_prototype_value_of(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
             value = &value->data.u.object_value->value;
 
         } else {
-            njs_exception_type_error(vm, NULL, NULL);
+            njs_exception_type_error(vm, "unexpected value type:%s",
+                                     njs_type_string(value->type));
             return NXT_ERROR;
         }
     }
@@ -578,7 +579,8 @@ njs_string_prototype_concat(njs_vm_t *vm, njs_value_t *args, nxt_uint_t nargs,
     njs_string_prop_t  string;
 
     if (njs_is_null_or_void(&args[0])) {
-        njs_exception_type_error(vm, NULL, NULL);
+        njs_exception_type_error(vm, "'this' argument is null or undefined",
+                                 NULL);
         return NXT_ERROR;
     }
 
@@ -2539,7 +2541,8 @@ njs_string_replace_regexp_continuation(njs_vm_t *vm, njs_value_t *args,
 
     nxt_regex_match_data_free(r->match_data, vm->regex_context);
 
-    njs_exception_type_error(vm, NULL, NULL);
+    njs_exception_internal_error(vm, "unexpected continuation retval type:%s",
+                                 njs_type_string(r->retval.type));
 
     return NXT_ERROR;
 }
@@ -2651,7 +2654,8 @@ njs_string_replace_search_continuation(njs_vm_t *vm, njs_value_t *args,
         return njs_string_replace_join(vm, r);
     }
 
-    njs_exception_type_error(vm, NULL, NULL);
+    njs_exception_internal_error(vm, "unexpected continuation retval type:%s",
+                                 njs_type_string(r->retval.type));
 
     return NXT_ERROR;
 }
index c4de887a1c2ef7abf3df474425cafbb7cfc275e2..194321cecb978d7344056cf33e89a5e953e76d68 100644 (file)
@@ -674,7 +674,8 @@ njs_vmcode_property_set(njs_vm_t *vm, njs_value_t *object,
     njs_vmcode_prop_set_t  *code;
 
     if (njs_is_primitive(object)) {
-        njs_exception_type_error(vm, NULL, NULL);
+        njs_exception_type_error(vm, "property set on primitive %s type",
+                                 njs_type_string(object->type));
         return NXT_ERROR;
     }
 
@@ -794,7 +795,7 @@ njs_vmcode_property_in(njs_vm_t *vm, njs_value_t *object, njs_value_t *property)
 
     case NJS_PRIMITIVE_VALUE:
     case NJS_STRING_VALUE:
-        njs_exception_type_error(vm, NULL, NULL);
+        njs_exception_type_error(vm, "property in on a primitive value", NULL);
 
         return NXT_ERROR;
 
@@ -1039,7 +1040,23 @@ njs_property_query(njs_vm_t *vm, njs_property_query_t *pq, njs_value_t *object,
         break;
 
     default:  /* NJS_VOID, NJS_NULL. */
-        njs_exception_type_error(vm, NULL, NULL);
+        if (nxt_fast_path(njs_is_primitive(property))) {
+
+            ret = njs_primitive_value_to_string(vm, &pq->value, property);
+
+            if (nxt_fast_path(ret == NXT_OK)) {
+                njs_string_get(&pq->value, &pq->lhq.key);
+                njs_exception_type_error(vm,
+                                      "cannot get property '%.*s' of undefined",
+                                      (int) pq->lhq.key.length,
+                                      pq->lhq.key.start);
+                return NXT_ERROR;
+            }
+        }
+
+        njs_exception_type_error(vm,
+                            "cannot get property 'unknown' of undefined", NULL);
+
         return NXT_ERROR;
     }
 
@@ -1322,7 +1339,7 @@ njs_vmcode_instance_of(njs_vm_t *vm, njs_value_t *object,
     nxt_lvlhsh_query_t  lhq;
 
     if (!njs_is_function(constructor)) {
-        njs_exception_type_error(vm, NULL, NULL);
+        njs_exception_type_error(vm, "right argument is not a function", NULL);
         return NXT_ERROR;
     }
 
@@ -2245,7 +2262,7 @@ njs_function_frame_create(njs_vm_t *vm, njs_value_t *value,
         }
     }
 
-    njs_exception_type_error(vm, NULL, NULL);
+    njs_exception_type_error(vm, "object is not callable", NULL);
 
     return NXT_ERROR;
 }
@@ -2304,7 +2321,9 @@ njs_vmcode_method_frame(njs_vm_t *vm, njs_value_t *object, njs_value_t *name)
 
     pq.query = NJS_PROPERTY_QUERY_GET;
 
-    switch (njs_property_query(vm, &pq, object, name)) {
+    ret = njs_property_query(vm, &pq, object, name);
+
+    switch (ret) {
 
     case NXT_OK:
         prop = pq.lhq.value;
@@ -2326,13 +2345,20 @@ njs_vmcode_method_frame(njs_vm_t *vm, njs_value_t *object, njs_value_t *name)
         ret = nxt_lvlhsh_find(&ext->hash, &pq.lhq);
 
         if (nxt_slow_path(ret != NXT_OK)) {
-            goto type_error;
+            njs_exception_type_error(vm,
+                            "cannot find property '%.*s' of an external object",
+                            (int) pq.lhq.key.length, pq.lhq.key.start);
+            return NXT_ERROR;
+
         }
 
         ext = pq.lhq.value;
 
         if (nxt_slow_path(ext->type != NJS_EXTERN_METHOD)) {
-            goto type_error;
+            njs_exception_type_error(vm,
+                          "method '%.*s' of an external object is not callable",
+                          (int) pq.lhq.key.length, pq.lhq.key.start);
+            return NXT_ERROR;
         }
 
         this.data.u.data = vm->external[ext->object];
@@ -2342,7 +2368,10 @@ njs_vmcode_method_frame(njs_vm_t *vm, njs_value_t *object, njs_value_t *name)
         break;
 
     default:
-        goto type_error;
+        njs_exception_internal_error(vm, "method '%.*s' query failed:%d",
+                                     (int) pq.lhq.key.length, pq.lhq.key.start,
+                                     ret);
+        return NXT_ERROR;
     }
 
     if (nxt_fast_path(ret == NXT_OK)) {
@@ -2350,12 +2379,6 @@ njs_vmcode_method_frame(njs_vm_t *vm, njs_value_t *object, njs_value_t *name)
     }
 
     return ret;
-
-type_error:
-
-    njs_exception_type_error(vm, NULL, NULL);
-
-    return NXT_ERROR;
 }
 
 
@@ -2574,12 +2597,130 @@ trap:
 
 type_error:
 
-    njs_exception_type_error(vm, NULL, NULL);
+    njs_exception_type_error(vm, "cannot convert %s to %s",
+                             njs_type_string(args->type),
+                             njs_arg_type_string(*args_types));
 
     return NXT_ERROR;
 }
 
 
+const char *
+njs_type_string(njs_value_type_t type)
+{
+    switch (type) {
+    case NJS_NULL:
+        return "null";
+
+    case NJS_VOID:
+        return "void";
+
+    case NJS_BOOLEAN:
+        return "boolean";
+
+    case NJS_NUMBER:
+        return "number";
+
+    case NJS_STRING:
+        return "string";
+
+    case NJS_EXTERNAL:
+        return "external";
+
+    case NJS_INVALID:
+        return "invalid";
+
+    case NJS_OBJECT:
+        return "object";
+
+    case NJS_ARRAY:
+        return "array";
+
+    case NJS_OBJECT_BOOLEAN:
+        return "object boolean";
+
+    case NJS_OBJECT_NUMBER:
+        return "object number";
+
+    case NJS_OBJECT_STRING:
+        return "object string";
+
+    case NJS_FUNCTION:
+        return "function";
+
+    case NJS_REGEXP:
+        return "regexp";
+
+    case NJS_DATE:
+        return "date";
+
+    case NJS_OBJECT_ERROR:
+        return "error";
+
+    case NJS_OBJECT_EVAL_ERROR:
+        return "eval error";
+
+    case NJS_OBJECT_INTERNAL_ERROR:
+        return "internal error";
+
+    case NJS_OBJECT_RANGE_ERROR:
+        return "range error";
+
+    case NJS_OBJECT_REF_ERROR:
+        return "reference error";
+
+    case NJS_OBJECT_SYNTAX_ERROR:
+        return "syntax error";
+
+    case NJS_OBJECT_TYPE_ERROR:
+        return "type error";
+
+    case NJS_OBJECT_URI_ERROR:
+        return "uri error";
+
+    default:
+        return NULL;
+    }
+}
+
+
+const char *
+njs_arg_type_string(uint8_t arg)
+{
+    switch (arg) {
+    case NJS_SKIP_ARG:
+        return "skip";
+
+    case NJS_NUMBER_ARG:
+        return "number";
+
+    case NJS_INTEGER_ARG:
+        return "integer";
+
+    case NJS_STRING_ARG:
+        return "string";
+
+    case NJS_OBJECT_ARG:
+        return "object";
+
+    case NJS_STRING_OBJECT_ARG:
+        return "string object";
+
+    case NJS_FUNCTION_ARG:
+        return "function";
+
+    case NJS_REGEXP_ARG:
+        return "regexp";
+
+    case NJS_DATE_ARG:
+        return "regexp";
+
+    default:
+        return "unknown";
+    }
+}
+
+
 njs_ret_t
 njs_vmcode_return(njs_vm_t *vm, njs_value_t *invld, njs_value_t *retval)
 {
@@ -3173,7 +3314,6 @@ njs_primitive_value(njs_vm_t *vm, njs_value_t *value, nxt_uint_t hint)
         if (!njs_is_primitive(retval)) {
 
             for ( ;; ) {
-                njs_exception_type_error(vm, NULL, NULL);
                 ret = NXT_ERROR;
 
                 if (njs_is_object(value) && vm->top_frame->trap_tries < 2) {
@@ -3221,6 +3361,11 @@ njs_primitive_value(njs_vm_t *vm, njs_value_t *value, nxt_uint_t hint)
                     }
                 }
 
+                if (ret == NXT_ERROR) {
+                    njs_exception_type_error(vm, "cannot evaluate an object's "
+                                             "value", NULL);
+                }
+
                 return ret;
             }
         }
index bbd9442fc54f6973cb1471be587ea8393b79a7ae..5ac2872826c571371516314cdd2c1c4855ea1f9f 100644 (file)
@@ -1152,6 +1152,8 @@ nxt_bool_t njs_values_strict_equal(const njs_value_t *val1,
 
 njs_ret_t njs_normalize_args(njs_vm_t *vm, njs_value_t *args,
     uint8_t *args_types, nxt_uint_t nargs);
+const char *njs_type_string(njs_value_type_t type);
+const char *njs_arg_type_string(uint8_t arg);
 
 njs_ret_t njs_native_function_arguments(njs_vm_t *vm, njs_value_t *args,
     uint8_t *args_types, nxt_uint_t nargs);
index d6adec6b81427f40ab2674a4b3d58937543085b1..2361f4f6f550fccc3a5d4e79abe836627af00d75 100644 (file)
@@ -166,12 +166,17 @@ njs_test {
      "console.help()\r\nVM built-in objects:"}
 }
 
+njs_test {
+    {"console.ll()\r\n"
+     "console.ll()\r\nTypeError: cannot find property 'll' of an external object"}
+}
+
 # Exception in njs_vm_retval()
 njs_test {
     {"var o = { toString: function() { return [1] } }\r\n"
      "undefined\r\n>> "}
     {"o\r\n"
-     "TypeError"}
+     "TypeError: cannot evaluate an object's value"}
 }
 
 # Backtraces are reset between invocations
index 19a78c4ae9a95e81c6c8816358acbd37e441ff06..d6e93f2ff1e17e2bcfb4a7503757be91a03e64d3 100644 (file)
@@ -120,7 +120,7 @@ static njs_interactive_test_t  njs_test[] =
     { nxt_string("function ff(o) {return o.a.a}" ENTER
                  "function f(o) {return ff(o)}" ENTER
                  "f({})" ENTER),
-      nxt_string("TypeError\n"
+      nxt_string("TypeError: cannot get property 'a' of undefined\n"
                  "    at ff (:1)\n"
                  "    at f (:1)\n"
                  "    at main (native)\n") },
@@ -129,27 +129,27 @@ static njs_interactive_test_t  njs_test[] =
                  "function f(o) {try {return ff(o)} "
                                  "finally {return o.a.a}}" ENTER
                  "f({})" ENTER),
-      nxt_string("TypeError\n"
+      nxt_string("TypeError: cannot get property 'a' of undefined\n"
                  "    at f (:1)\n"
                  "    at main (native)\n") },
 
     { nxt_string("function f(ff, o) {return ff(o)}" ENTER
                  "f(function (o) {return o.a.a}, {})" ENTER),
-      nxt_string("TypeError\n"
+      nxt_string("TypeError: cannot get property 'a' of undefined\n"
                  "    at anonymous (:1)\n"
                  "    at f (:1)\n"
                  "    at main (native)\n") },
 
     { nxt_string("'str'.replace(/t/g,"
                  "              function(m) {return m.a.a})" ENTER),
-      nxt_string("TypeError\n"
+      nxt_string("TypeError: cannot get property 'a' of undefined\n"
                  "    at anonymous (:1)\n"
                  "    at String.prototype.replace (native)\n"
                  "    at main (native)\n") },
 
     { nxt_string("function f(o) {return Object.keys(o)}" ENTER
                  "f()" ENTER),
-      nxt_string("TypeError\n"
+      nxt_string("TypeError: cannot convert void to object\n"
                  "    at Object.keys (native)\n"
                  "    at f (:1)\n"
                  "    at main (native)\n") },
@@ -160,20 +160,20 @@ static njs_interactive_test_t  njs_test[] =
                  "    at main (native)\n") },
 
     { nxt_string("Math.log({}.a.a)" ENTER),
-      nxt_string("TypeError\n"
+      nxt_string("TypeError: cannot get property 'a' of undefined\n"
                  "    at Math.log (native)\n"
                  "    at main (native)\n") },
 
     { nxt_string("function f(o) {function f_in(o) {return o.a.a};"
                  "               return f_in(o)}; f({})" ENTER),
-      nxt_string("TypeError\n"
+      nxt_string("TypeError: cannot get property 'a' of undefined\n"
                  "    at f_in (:1)\n"
                  "    at f (:1)\n"
                  "    at main (native)\n") },
 
     { nxt_string("function f(o) {var ff = function (o) {return o.a.a};"
                  "               return ff(o)}; f({})" ENTER),
-      nxt_string("TypeError\n"
+      nxt_string("TypeError: cannot get property 'a' of undefined\n"
                  "    at anonymous (:1)\n"
                  "    at f (:1)\n"
                  "    at main (native)\n") },
@@ -187,7 +187,7 @@ static njs_interactive_test_t  njs_test[] =
 
     { nxt_string("var o = { toString: function() { return [1] } }" ENTER
                  "o" ENTER),
-      nxt_string("TypeError\n"
+      nxt_string("TypeError: cannot evaluate an object's value\n"
                  "    at main (native)\n") },
 
 };
index 6b6084b1a939db3e80cf4eb6ad165a532731fbba..2bd3a0414820d288b0e943a4b66e0f8195620c90 100644 (file)
@@ -2309,10 +2309,10 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("undefined") },
 
     { nxt_string("var a = {}; a.b.c"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot get property 'c' of undefined") },
 
     { nxt_string("'a'.b = 1"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: property set on primitive string type") },
 
     { nxt_string("var a = {}; a.b = 1; a.b"),
       nxt_string("1") },
@@ -2342,16 +2342,16 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("3") },
 
     { nxt_string("var a = undefined; a.b++; a.b"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot get property 'b' of undefined") },
 
     { nxt_string("var a = null; a.b++; a.b"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot get property 'b' of undefined") },
 
     { nxt_string("var a = true; a.b++; a.b"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: property set on primitive boolean type") },
 
     { nxt_string("var a = 1; a.b++; a.b"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: property set on primitive number type") },
 
     { nxt_string("var n = 1, o = { p: n += 1 }; o.p"),
       nxt_string("2") },
@@ -2369,7 +2369,7 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("2 1") },
 
     { nxt_string("var a = 2; a.b = 1; var c = a.b++; a +' '+ a.b +' '+ c"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: property set on primitive number type") },
 
     { nxt_string("var x = { a: 1 }; x.a"),
       nxt_string("1") },
@@ -2408,7 +2408,7 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("SyntaxError: Unexpected token \";\" in 1") },
 
     { nxt_string("var x = { a: 1, b: x.a }"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot get property 'a' of undefined") },
 
     { nxt_string("var a = { b: 2 }; a.b += 1"),
       nxt_string("3") },
@@ -2481,10 +2481,10 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("false") },
 
     { nxt_string("var a = 1; 1 in a"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: property in on a primitive value") },
 
     { nxt_string("var a = true; 1 in a"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: property in on a primitive value") },
 
     { nxt_string("var n = { toString: function() { return 'a' } };"
                  "var o = { a: 5 }; o[n]"),
@@ -3224,7 +3224,7 @@ static njs_unit_test_t  njs_test[] =
 
     { nxt_string("var a = [];"
                  "a.reduce(function(p, v, i, a) { return p + v })"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: invalid index") },
 
     { nxt_string("var a = [];"
                  "a.reduce(function(p, v, i, a) { return p + v }, 10)"),
@@ -3232,7 +3232,7 @@ static njs_unit_test_t  njs_test[] =
 
     { nxt_string("var a = [,,];"
                  "a.reduce(function(p, v, i, a) { return p + v })"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: invalid index") },
 
     { nxt_string("var a = [,,];"
                  "a.reduce(function(p, v, i, a) { return p + v }, 10)"),
@@ -3260,7 +3260,7 @@ static njs_unit_test_t  njs_test[] =
 
     { nxt_string("var a = [];"
                  "a.reduceRight(function(p, v, i, a) { return p + v })"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: invalid index") },
 
     { nxt_string("var a = [];"
                  "a.reduceRight(function(p, v, i, a) { return p + v }, 10)"),
@@ -3268,7 +3268,7 @@ static njs_unit_test_t  njs_test[] =
 
     { nxt_string("var a = [,,];"
                  "a.reduceRight(function(p, v, i, a) { return p + v })"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: invalid index") },
 
     { nxt_string("var a = [,,];"
                  "a.reduceRight(function(p, v, i, a) { return p + v }, 10)"),
@@ -3725,7 +3725,7 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("abc") },
 
     { nxt_string("String.prototype.toString.call(1)"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: unexpected value type:number") },
 
     { nxt_string("'abc'.valueOf()"),
       nxt_string("abc") },
@@ -4131,7 +4131,7 @@ static njs_unit_test_t  njs_test[] =
 
     { nxt_string("var r = { toString: function() { return /45/ } };"
                  "'123456'.search(r)"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot evaluate an object's value") },
 
     { nxt_string("var r = { toString: function() { return /34/ },"
                  "          valueOf:  function() { return 45 } };"
@@ -4265,7 +4265,7 @@ static njs_unit_test_t  njs_test[] =
 
     { nxt_string("var r = { toString: function() { return /45/ } };"
                  "'123456'.match(r)"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot evaluate an object's value") },
 
     { nxt_string("var r = { toString: function() { return /34/ },"
                  "          valueOf:  function() { return 45 } };"
@@ -4509,10 +4509,10 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("OKundefined") },
 
     { nxt_string("var a = 1; a()"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: object is not callable") },
 
     { nxt_string("var o = {a:1}; o.a()"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: object is not callable") },
 
     { nxt_string("(function(){})()"),
       nxt_string("undefined") },
@@ -4800,7 +4800,7 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("5") },
 
     { nxt_string("var f = function(a) { return this + a }; f.apply(5, 1)"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: second argument is not an array") },
 
     { nxt_string("var f = function(a, b) { return this + a + b };"
                  "f.apply(5, [1, 2])"),
@@ -4814,7 +4814,7 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("[object Function]") },
 
     { nxt_string("''.concat.call()"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: 'this' argument is null or undefined") },
 
     { nxt_string("''.concat.call('a', 'b', 'c')"),
       nxt_string("abc") },
@@ -4829,13 +4829,13 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("ab,cd") },
 
     { nxt_string("''.concat.apply()"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: 'this' argument is null or undefined") },
 
     { nxt_string("''.concat.apply('a')"),
       nxt_string("a") },
 
     { nxt_string("''.concat.apply('a', 'b')"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: second argument is not an array") },
 
     { nxt_string("''.concat.apply('a', [ 'b', 'c' ])"),
       nxt_string("abc") },
@@ -4853,10 +4853,10 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("1552553") },
 
     { nxt_string("[].join.call()"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot convert void to object") },
 
     { nxt_string("[].slice.call()"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot convert void to object") },
 
     { nxt_string("function f(a) {} ; var a = f; var b = f; a === b"),
       nxt_string("true") },
@@ -4900,7 +4900,7 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("01") },
 
     { nxt_string("var concat = ''.concat; concat(1,2,3)"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: 'this' argument is null or undefined") },
 
     { nxt_string("var concat = ''.concat; concat.call(1,2,3)"),
       nxt_string("123") },
@@ -4997,10 +4997,10 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("object") },
 
     { nxt_string("new decodeURI('%00')"),
-      nxt_string("TypeError")},
+      nxt_string("TypeError: object is not callable")},
 
     { nxt_string("new ''.toString"),
-      nxt_string("TypeError")},
+      nxt_string("TypeError: object is not callable")},
 
     { nxt_string("function F() { return Number }"
                  "var o = new (F())(5);"
@@ -5214,7 +5214,7 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("true") },
 
     { nxt_string("[0].map(RegExp().toString)"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: 'this' argument is not a regexp") },
 
     /* Non-standard ECMA-262 features. */
 
@@ -5565,10 +5565,10 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("o:OK") },
 
     { nxt_string("var o = { toString: function() { return [1] } }; o"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot evaluate an object's value") },
 
     { nxt_string("var o = { toString: function() { return [1] } }; 'o:' + o"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot evaluate an object's value") },
 
     { nxt_string("var a = { valueOf: function() { return '3' } };"
                  "var b = { toString: function() { return 10 - a + 'OK' } };"
@@ -5620,7 +5620,7 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("true") },
 
     { nxt_string("[] instanceof []"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: right argument is not a function") },
 
     { nxt_string("[] instanceof Array"),
       nxt_string("true") },
@@ -6202,6 +6202,9 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("var o = Object.create(null); '__proto__' in o"),
       nxt_string("false") },
 
+    { nxt_string("Object.create()"),
+      nxt_string("TypeError: too few arguments") },
+
     { nxt_string("var o = {a:1, b:2, c:3};"
                  "Object.keys(o)"),
       nxt_string("a,b,c") },
@@ -6215,11 +6218,14 @@ static njs_unit_test_t  njs_test[] =
     { nxt_string("var a = [,6,,3]; a.one = 7; Object.keys(a)"),
       nxt_string("1,3,one") },
 
+    { nxt_string("Object.keys()"),
+      nxt_string("TypeError: cannot convert null argument to object") },
+
     { nxt_string("Object.keys('a')"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot convert string argument to object") },
 
     { nxt_string("Object.keys(1)"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot convert number argument to object") },
 
     { nxt_string("var o = {}; Object.defineProperty(o, 'a', {}); o.a"),
       nxt_string("undefined") },
@@ -6274,10 +6280,10 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("2") },
 
     { nxt_string("var o = {}; Object.defineProperty()"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot convert null argument to object") },
 
     { nxt_string("var o = {}; Object.defineProperty(o)"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: descriptor is not an object") },
 
     { nxt_string("var o = Object.defineProperties({}, {a:{value:1}}); o.a"),
       nxt_string("1") },
@@ -6295,10 +6301,10 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("1") },
 
     { nxt_string("Object.defineProperties(1, {})"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot convert number argument to object") },
 
     { nxt_string("Object.defineProperties({}, 1)"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: descriptor is not an object") },
 
     { nxt_string("var o = {a:1}; o.hasOwnProperty('a')"),
       nxt_string("true") },
@@ -6361,10 +6367,10 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("true") },
 
     { nxt_string("Object.getPrototypeOf(1)"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot convert number argument to object") },
 
     { nxt_string("Object.getPrototypeOf('a')"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot convert string argument to object") },
 
     { nxt_string("var p = {}; var o = Object.create(p);"
                  "p.isPrototypeOf(o)"),
@@ -6425,13 +6431,13 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("undefined") },
 
     { nxt_string("Object.getOwnPropertyDescriptor(1, '0')"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot convert number argument to object") },
 
     { nxt_string("Object.defineProperty(Object.freeze({}), 'b', {})"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: object is not extensible") },
 
     { nxt_string("Object.defineProperties(Object.freeze({}), {b:{}})"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: object is not extensible") },
 
     { nxt_string("Object.freeze()"),
       nxt_string("undefined") },
@@ -6456,7 +6462,7 @@ static njs_unit_test_t  njs_test[] =
 
     { nxt_string("var a = Object.freeze([1,2]);"
                  "Object.defineProperty(a, 'a', {value:1}).a"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: object is not extensible") },
 
     { nxt_string("var a = [1,2]; a.a = 1; Object.freeze(a);"
                  "delete a.a; a.a"),
@@ -6474,7 +6480,7 @@ static njs_unit_test_t  njs_test[] =
 
     { nxt_string("var f = Object.freeze(function() {});"
                  "Object.defineProperty(f, 'a', {value:1}).a"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: object is not extensible") },
 
     { nxt_string("var f = function() {}; f.a = 1; Object.freeze(f);"
                  "delete f.a; f.a"),
@@ -6492,7 +6498,7 @@ static njs_unit_test_t  njs_test[] =
 
     { nxt_string("var d = Object.freeze(new Date(''));"
                  "Object.defineProperty(d, 'a', {value:1}).a"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: object is not extensible") },
 
     { nxt_string("var d = new Date(''); d.a = 1; Object.freeze(d);"
                  "delete d.a; d.a"),
@@ -6510,7 +6516,7 @@ static njs_unit_test_t  njs_test[] =
 
     { nxt_string("var r = Object.freeze(new RegExp(''));"
                  "Object.defineProperty(r, 'a', {value:1}).a"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: object is not extensible") },
 
     { nxt_string("var r = new RegExp(''); r.a = 1; Object.freeze(r);"
                  "delete r.a; r.a"),
@@ -6657,11 +6663,11 @@ static njs_unit_test_t  njs_test[] =
 
     { nxt_string("var o = Object.preventExtensions({a:1});"
                  "Object.defineProperty(o, 'b', {value:1})"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: object is not extensible") },
 
     { nxt_string("var o = Object.preventExtensions({a:1});"
                  "Object.defineProperties(o, {b:{value:1}})"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: object is not extensible") },
 
     { nxt_string("var o = Object.preventExtensions({a:1}); o.a = 2; o.a"),
       nxt_string("2") },
@@ -7079,7 +7085,7 @@ static njs_unit_test_t  njs_test[] =
       nxt_string("true") },
 
     { nxt_string("[0].map(new Date().getDate)"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot convert void to regexp") },
 
     { nxt_string("new Date(eval)"),
       nxt_string("Invalid Date") },
@@ -8499,7 +8505,7 @@ static njs_unit_test_t  njs_test[] =
 
     { nxt_string("var o = JSON.parse('{\"a\":1}', "
                  "                   function(k, v) {return v.a.a;}); o"),
-      nxt_string("TypeError") },
+      nxt_string("TypeError: cannot get property 'a' of undefined") },
 
     /* JSON.stringify() */