From ce5126380eb6aa3a495fc5ec5f5e4cd22db25593 Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Fri, 11 Dec 2015 18:41:20 +0300 Subject: [PATCH] Array.toString() fixed. --- njs/njs_array.c | 37 ++++++++++++++++--------------------- njs/njs_object.c | 2 +- njs/njs_object.h | 1 + njs/test/njs_unit_test.c | 16 +++++++++++++++- 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/njs/njs_array.c b/njs/njs_array.c index 788907c1..28d3bab7 100644 --- a/njs/njs_array.c +++ b/njs/njs_array.c @@ -455,38 +455,33 @@ njs_array_prototype_shift(njs_vm_t *vm, njs_param_t *param) } +/* + * ECMAScript 5.1: try first to use object method "join", then + * use the standard built-in method Object.prototype.toString(). + */ + static njs_ret_t njs_array_prototype_to_string(njs_vm_t *vm, njs_param_t *param) { - njs_object_t *object; + njs_value_t *this; njs_object_prop_t *prop; nxt_lvlhsh_query_t lhq; - lhq.key_hash = NJS_JOIN_HASH; - lhq.key.len = sizeof("join") - 1; - lhq.key.data = (u_char *) "join"; - - object = param->object->data.u.object; - - prop = njs_object_property(vm, object, &lhq); + this = param->object; - if (nxt_fast_path(prop != NULL && njs_is_function(&prop->value))) { - return njs_function_apply(vm, &prop->value, param); - } - - lhq.key_hash = NJS_TO_STRING_HASH; - lhq.key.len = sizeof("toString") - 1; - lhq.key.data = (u_char *) "toString"; - - object = &vm->prototypes[NJS_PROTOTYPE_OBJECT]; + if (njs_is_object(this)) { + lhq.key_hash = NJS_JOIN_HASH; + lhq.key.len = sizeof("join") - 1; + lhq.key.data = (u_char *) "join"; - prop = njs_object_property(vm, object, &lhq); + prop = njs_object_property(vm, this->data.u.object, &lhq); - if (nxt_fast_path(prop != NULL)) { - return njs_function_apply(vm, &prop->value, param); + if (nxt_fast_path(prop != NULL && njs_is_function(&prop->value))) { + return njs_function_apply(vm, &prop->value, param); + } } - return NXT_ERROR; + return njs_object_prototype_to_string(vm, param); } diff --git a/njs/njs_object.c b/njs/njs_object.c index a0e37795..df516615 100644 --- a/njs/njs_object.c +++ b/njs/njs_object.c @@ -537,7 +537,7 @@ static const njs_value_t njs_object_regexp_string = njs_long_string("[object RegExp]"); -static njs_ret_t +njs_ret_t njs_object_prototype_to_string(njs_vm_t *vm, njs_param_t *param) { int32_t index; diff --git a/njs/njs_object.h b/njs/njs_object.h index a645494a..ce18d014 100644 --- a/njs/njs_object.h +++ b/njs/njs_object.h @@ -56,6 +56,7 @@ njs_ret_t njs_object_constructor(njs_vm_t *vm, njs_param_t *param); njs_object_prop_t *njs_object_prop_alloc(njs_vm_t *vm, const njs_value_t *name); njs_ret_t njs_primitive_prototype_get_proto(njs_vm_t *vm, njs_value_t *value); njs_ret_t njs_object_prototype_create(njs_vm_t *vm, njs_value_t *value); +njs_ret_t njs_object_prototype_to_string(njs_vm_t *vm, njs_param_t *param); extern const njs_object_init_t njs_object_constructor_init; extern const njs_object_init_t njs_object_prototype_init; diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index a9f50eb9..6af272c1 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -1708,7 +1708,19 @@ static njs_unit_test_t njs_test[] = { nxt_string("a = []; a.concat([]) +''"), nxt_string("") }, - /**/ + /* Array.toString(). */ + + { nxt_string("a = [1,2,3]; a.join = 'NO';" + "Object.prototype.toString = function () { return 'A' }; a"), + nxt_string("[object Array]") }, + + { nxt_string("Array.prototype.toString.call(1)"), + nxt_string("[object Number]") }, + + { nxt_string("Array.prototype.toString.call('abc')"), + nxt_string("[object String]") }, + + /* Empty array elements. */ { nxt_string("[,,]"), nxt_string(",") }, @@ -3464,6 +3476,7 @@ njs_unit_test(nxt_bool_t disassemble) r.uri.data = (u_char *) "АБВ"; if (njs_vm_run(nvm) == NXT_OK) { + if (njs_vm_retval(nvm, &s) != NXT_OK) { return NXT_ERROR; } @@ -3559,6 +3572,7 @@ njs_unit_test_benchmark(nxt_str_t *script, nxt_str_t *result, const char *msg, } if (njs_vm_run(nvm) == NXT_OK) { + if (njs_vm_retval(nvm, &s) != NXT_OK) { return NXT_ERROR; } -- 2.47.3