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;
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;
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;
{ 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") },