diff --git a/src/njs_string.c b/src/njs_string.c index 6d7c464dc..cf3e13937 100644 --- a/src/njs_string.c +++ b/src/njs_string.c @@ -601,10 +601,11 @@ njs_int_t njs_string_prototype_concat(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, njs_index_t unused, njs_value_t *retval) { + double num; u_char *p, *start; uint64_t size, length, mask; njs_int_t ret; - njs_uint_t i; + njs_uint_t i, i_buf, n_bufs; njs_string_prop_t string; if (njs_is_null_or_undefined(&args[0])) { @@ -612,8 +613,44 @@ njs_string_prototype_concat(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, return NJS_ERROR; } + n_bufs = njs_min(nargs,16); + + u_char buf[n_bufs][32]; + njs_string_t sp[n_bufs]; + + i_buf = 0; + for (i = 0; i < nargs; i++) { - if (!njs_is_string(&args[i])) { + if (i_buf < n_bufs && njs_is_number(&args[i])) { + num = njs_number(&args[i]); + + if (isnan(num)) { + njs_atom_to_value(vm, &args[i], NJS_ATOM_STRING_NaN); + + } else if (isinf(num)) { + + if (num < 0) { + njs_atom_to_value(vm, &args[i], NJS_ATOM_STRING__Infinity); + + } else { + njs_atom_to_value(vm, &args[i], NJS_ATOM_STRING_Infinity); + } + + } else { + size = njs_dtoa(num, (char *) buf[i]); + + sp[i_buf].start = (u_char *)buf[i]; + sp[i_buf].length = sp[i_buf].size = size; + + args[i].type = NJS_STRING; + args[i].truth = size != 0; + args[i].atom_id = NJS_ATOM_STRING_unknown; + args[i].string.data = &sp[i_buf]; + + i_buf++; + } + + } if (!njs_is_string(&args[i])) { ret = njs_value_to_string(vm, &args[i], &args[i]); if (ret != NJS_OK) { return ret; diff --git a/src/njs_vmcode.c b/src/njs_vmcode.c index c7adf63f7..3b7993ce7 100644 --- a/src/njs_vmcode.c +++ b/src/njs_vmcode.c @@ -667,14 +667,52 @@ NEXT_LBL; src = value1; } - ret = njs_primitive_value_to_string(vm, &dst, src); - if (njs_slow_path(ret != NJS_OK)) { - goto error; - } + if (src->type == NJS_NUMBER) { - ret = njs_string_concat(vm, s1, s2, &name); - if (njs_slow_path(ret == NJS_ERROR)) { - goto error; + double num; + size_t size; + u_char buf[32]; + + njs_string_t sp; + + num = njs_number(src); + + if (isnan(num)) { + njs_atom_to_value(vm, &dst, NJS_ATOM_STRING_NaN); + + } else if (isinf(num)) { + + if (num < 0) { + njs_atom_to_value(vm, &dst, NJS_ATOM_STRING__Infinity); + + } else { + njs_atom_to_value(vm, &dst, NJS_ATOM_STRING_Infinity); + } + + } else { + size = njs_dtoa(num, (char *) buf); + + sp.start = (u_char *)buf; + sp.length = sp.size = size; + + dst.string.data = &sp; + } + + ret = njs_string_concat(vm, s1, s2, &name); + if (njs_slow_path(ret == NJS_ERROR)) { + goto error; + } + + } else { + ret = njs_primitive_value_to_string(vm, &dst, src); + if (njs_slow_path(ret != NJS_OK)) { + goto error; + } + + ret = njs_string_concat(vm, s1, s2, &name); + if (njs_slow_path(ret == NJS_ERROR)) { + goto error; + } } njs_value_assign(retval, &name); @@ -2010,6 +2048,8 @@ njs_vmcode_template_literal(njs_vm_t *vm, njs_value_t *retval) return ret; } + njs_array_destroy(vm, array); + return sizeof(njs_vmcode_template_literal_t); }