From: Igor Sysoev Date: Sun, 27 Dec 2015 12:26:08 +0000 (+0300) Subject: Object to primitive value convertion traps have been fixed. X-Git-Tag: 0.1.0~89 X-Git-Url: http://git.kaiwu.me/%7B@url%7D?a=commitdiff_plain;h=2773c56e5f411846e371022b291b4b6368baaa79;p=njs.git Object to primitive value convertion traps have been fixed. --- diff --git a/njs/njs_vm.c b/njs/njs_vm.c index c1f98b79..a72102f1 100644 --- a/njs/njs_vm.c +++ b/njs/njs_vm.c @@ -2563,6 +2563,15 @@ njs_vm_trap(njs_vm_t *vm, nxt_uint_t trap, njs_value_t *value1, frame->ctor = 0; + /* + * The values[0] is scratch value for results of "valueOf" and + * "toString" methods. The values[1] and values[2] are original + * operand values which will be replaced with primitive values + * returned by "valueOf" or "toString" methods. The scratch value + * is stored separately to preserve the original operand values for + * the second method call if the first method call will return + * non-primitive value. + */ values = njs_native_data(frame); njs_set_invalid(&values[0]); values[2] = *value2; @@ -2695,7 +2704,7 @@ njs_primitive_value(njs_vm_t *vm, njs_value_t *value, nxt_uint_t hint) if (!njs_is_primitive(value)) { retval = njs_native_data(vm->frame); - if (!njs_is_valid(retval)) { + if (!njs_is_primitive(retval)) { for ( ;; ) { vm->exception = &njs_exception_type_error; @@ -2710,6 +2719,12 @@ njs_primitive_value(njs_vm_t *vm, njs_value_t *value, nxt_uint_t hint) prop = njs_object_property(vm, value->data.u.object, &lhq); if (nxt_fast_path(prop != NULL)) { + + if (!njs_is_function(&prop->value)) { + /* Try the second method. */ + continue; + } + param.this = value; param.retval = (njs_index_t) retval; param.args = NULL; diff --git a/njs/test/njs_unit_test.c b/njs/test/njs_unit_test.c index 3cfb91e0..31f6a105 100644 --- a/njs/test/njs_unit_test.c +++ b/njs/test/njs_unit_test.c @@ -91,6 +91,28 @@ static njs_unit_test_t njs_test[] = { nxt_string("\n +1"), nxt_string("1") }, + /* An object "valueOf/toString" methods. */ + + { nxt_string("var a = { valueOf: function() { return 1 } }; +a"), + nxt_string("1") }, + + { nxt_string("var a = { valueOf: function() { return '1' } }; +a"), + nxt_string("1") }, + + { nxt_string("var a = { valueOf: 2," + " toString: function() { return '1' } }; +a"), + nxt_string("1") }, + + { nxt_string("var a = { valueOf: function() { return [] }," + " toString: function() { return '1' } }; +a"), + nxt_string("1") }, + + { nxt_string("var a = { toString: function() { return 'a' } };" + "var b = { toString: function() { return a+'b' } }; '0'+b"), + nxt_string("0ab") }, + + /**/ + { nxt_string("1 + undefined"), nxt_string("NaN") },