[njs] Refactored Array.prototype.join() using njs_chb_t API.
Dmitry Volyntsev
xeioex at nginx.com
Wed Dec 11 12:58:28 UTC 2019
details: https://hg.nginx.org/njs/rev/5bf71dfc052f
branches:
changeset: 1283:5bf71dfc052f
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Wed Dec 11 15:58:05 2019 +0300
description:
Refactored Array.prototype.join() using njs_chb_t API.
diffstat:
src/njs_array.c | 130 ++++++++++----------------------------------
src/njs_number.c | 34 +++++++++++
src/njs_number.h | 2 +
src/njs_string.c | 42 --------------
src/njs_value.c | 89 ++++++++++++++++++++++++++++++
src/njs_value.h | 2 +
src/njs_value_conversion.h | 25 ++++++++
src/test/njs_unit_test.c | 6 ++
8 files changed, 188 insertions(+), 142 deletions(-)
diffs (432 lines):
diff -r 5ba9145d9b0c -r 5bf71dfc052f src/njs_array.c
--- a/src/njs_array.c Wed Dec 11 15:30:26 2019 +0300
+++ b/src/njs_array.c Wed Dec 11 15:58:05 2019 +0300
@@ -1123,12 +1123,13 @@ njs_array_prototype_join(njs_vm_t *vm, n
njs_index_t unused)
{
u_char *p;
- uint32_t max;
- size_t size, length, mask;
+ size_t size;
+ ssize_t length;
njs_int_t ret;
- njs_uint_t i, n;
+ njs_chb_t chain;
+ njs_uint_t i;
njs_array_t *array;
- njs_value_t *value, *values;
+ njs_value_t *value;
njs_string_prop_t separator, string;
ret = njs_value_to_object(vm, &args[0]);
@@ -1159,117 +1160,46 @@ njs_array_prototype_join(njs_vm_t *vm, n
array = njs_array(&args[0]);
- max = 0;
- values = NULL;
+ njs_chb_init(&chain, vm->mem_pool);
+
+ length = 0;
for (i = 0; i < array->length; i++) {
value = &array->start[i];
-
- if (!njs_is_string(value)
- && njs_is_valid(value)
- && !njs_is_null_or_undefined(value))
- {
- max++;
- }
- }
-
- if (max != 0) {
- values = njs_mp_align(vm->mem_pool, sizeof(njs_value_t),
- sizeof(njs_value_t) * max);
- if (njs_slow_path(values == NULL)) {
- njs_memory_error(vm);
- return NJS_ERROR;
- }
-
- n = 0;
-
- for (i = 0; i < array->length; i++) {
- value = &array->start[i];
-
- if (!njs_is_string(value)
- && njs_is_valid(value)
- && !njs_is_null_or_undefined(value))
- {
- values[n++] = *value;
-
- if (n >= max) {
- break;
+ if (njs_is_valid(value) && !njs_is_null_or_undefined(value)) {
+ if (!njs_is_string(value)) {
+ ret = njs_value_to_chain(vm, &chain, value);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
}
+
+ } else {
+ (void) njs_string_prop(&string, value);
+ length += string.length;
+
+ njs_chb_append(&chain, string.start, string.size);
}
}
+
+ length += separator.length;
+ njs_chb_append(&chain, separator.start, separator.size);
}
- size = 0;
- length = 0;
- n = 0;
- mask = -1;
-
- array = njs_array(&args[0]);
-
- for (i = 0; i < array->length; i++) {
- value = &array->start[i];
-
- if (njs_is_valid(value) && !njs_is_null_or_undefined(value)) {
-
- if (!njs_is_string(value)) {
- value = &values[n++];
-
- if (!njs_is_string(value)) {
- ret = njs_value_to_string(vm, value, value);
- if (ret != NJS_OK) {
- return ret;
- }
- }
- }
-
- (void) njs_string_prop(&string, value);
-
- size += string.size;
- length += string.length;
-
- if (string.length == 0 && string.size != 0) {
- mask = 0;
- }
- }
+ njs_chb_drop(&chain, separator.size);
+
+ size = njs_chb_size(&chain);
+
+ if (length != 0) {
+ length -= separator.length;
}
- size += separator.size * (array->length - 1);
- length += separator.length * (array->length - 1);
-
- length &= mask;
-
p = njs_string_alloc(vm, &vm->retval, size, length);
if (njs_slow_path(p == NULL)) {
return NJS_ERROR;
}
- n = 0;
-
- for (i = 0; i < array->length; i++) {
- value = &array->start[i];
-
- if (njs_is_valid(value) && !njs_is_null_or_undefined(value)) {
- if (!njs_is_string(value)) {
- value = &values[n++];
- }
-
- (void) njs_string_prop(&string, value);
-
- p = memcpy(p, string.start, string.size);
- p += string.size;
- }
-
- if (i < array->length - 1) {
- p = memcpy(p, separator.start, separator.size);
- p += separator.size;
- }
- }
-
- for (i = 0; i < max; i++) {
- njs_release(vm, &values[i]);
- }
-
- njs_mp_free(vm->mem_pool, values);
+ njs_chb_join_to(&chain, p);
+ njs_chb_destroy(&chain);
return NJS_OK;
}
diff -r 5ba9145d9b0c -r 5bf71dfc052f src/njs_number.c
--- a/src/njs_number.c Wed Dec 11 15:30:26 2019 +0300
+++ b/src/njs_number.c Wed Dec 11 15:58:05 2019 +0300
@@ -236,6 +236,40 @@ njs_number_to_string(njs_vm_t *vm, njs_v
}
+void
+njs_number_to_chain(njs_vm_t *vm, njs_chb_t *chain, const njs_value_t *number)
+{
+ double num;
+ size_t size;
+ u_char *p;
+
+ num = njs_number(number);
+
+ if (isnan(num)) {
+ njs_chb_append_literal(chain, "NaN");
+
+ } else if (isinf(num)) {
+
+ if (num < 0) {
+ njs_chb_append_literal(chain, "-Infinity");
+
+ } else {
+ njs_chb_append_literal(chain, "Infinity");
+ }
+
+ } else {
+ p = njs_chb_reserve(chain, 64);
+ if (njs_slow_path(p == NULL)) {
+ return;
+ }
+
+ size = njs_dtoa(num, (char *) p);
+
+ njs_chb_written(chain, size);
+ }
+}
+
+
static njs_int_t
njs_number_constructor(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
njs_index_t unused)
diff -r 5ba9145d9b0c -r 5bf71dfc052f src/njs_number.h
--- a/src/njs_number.h Wed Dec 11 15:30:26 2019 +0300
+++ b/src/njs_number.h Wed Dec 11 15:58:05 2019 +0300
@@ -17,6 +17,8 @@ int64_t njs_number_radix_parse(const u_c
uint8_t radix);
njs_int_t njs_number_to_string(njs_vm_t *vm, njs_value_t *string,
const njs_value_t *number);
+void njs_number_to_chain(njs_vm_t *vm, njs_chb_t *chain,
+ const njs_value_t *number);
njs_int_t njs_number_global_is_nan(njs_vm_t *vm, njs_value_t *args,
njs_uint_t nargs, njs_index_t unused);
njs_int_t njs_number_global_is_finite(njs_vm_t *vm, njs_value_t *args,
diff -r 5ba9145d9b0c -r 5bf71dfc052f src/njs_string.c
--- a/src/njs_string.c Wed Dec 11 15:30:26 2019 +0300
+++ b/src/njs_string.c Wed Dec 11 15:58:05 2019 +0300
@@ -4254,48 +4254,6 @@ njs_string_replacement_copy(njs_string_r
}
-njs_int_t
-njs_primitive_value_to_string(njs_vm_t *vm, njs_value_t *dst,
- const njs_value_t *src)
-{
- const njs_value_t *value;
-
- switch (src->type) {
-
- case NJS_NULL:
- value = &njs_string_null;
- break;
-
- case NJS_UNDEFINED:
- value = &njs_string_undefined;
- break;
-
- case NJS_BOOLEAN:
- value = njs_is_true(src) ? &njs_string_true : &njs_string_false;
- break;
-
- case NJS_NUMBER:
- return njs_number_to_string(vm, dst, src);
-
- case NJS_SYMBOL:
- njs_symbol_conversion_failed(vm, 1);
- return NJS_ERROR;
-
- case NJS_STRING:
- /* GC: njs_retain(src); */
- value = src;
- break;
-
- default:
- return NJS_ERROR;
- }
-
- *dst = *value;
-
- return NJS_OK;
-}
-
-
double
njs_string_to_number(const njs_value_t *value, njs_bool_t parse_float)
{
diff -r 5ba9145d9b0c -r 5bf71dfc052f src/njs_value.c
--- a/src/njs_value.c Wed Dec 11 15:30:26 2019 +0300
+++ b/src/njs_value.c Wed Dec 11 15:58:05 2019 +0300
@@ -1225,6 +1225,95 @@ njs_value_property_delete(njs_vm_t *vm,
njs_int_t
+njs_primitive_value_to_string(njs_vm_t *vm, njs_value_t *dst,
+ const njs_value_t *src)
+{
+ const njs_value_t *value;
+
+ switch (src->type) {
+
+ case NJS_NULL:
+ value = &njs_string_null;
+ break;
+
+ case NJS_UNDEFINED:
+ value = &njs_string_undefined;
+ break;
+
+ case NJS_BOOLEAN:
+ value = njs_is_true(src) ? &njs_string_true : &njs_string_false;
+ break;
+
+ case NJS_NUMBER:
+ return njs_number_to_string(vm, dst, src);
+
+ case NJS_SYMBOL:
+ njs_symbol_conversion_failed(vm, 1);
+ return NJS_ERROR;
+
+ case NJS_STRING:
+ /* GC: njs_retain(src); */
+ value = src;
+ break;
+
+ default:
+ return NJS_ERROR;
+ }
+
+ *dst = *value;
+
+ return NJS_OK;
+}
+
+
+njs_int_t
+njs_primitive_value_to_chain(njs_vm_t *vm, njs_chb_t *chain,
+ const njs_value_t *src)
+{
+ njs_str_t string;
+
+ switch (src->type) {
+
+ case NJS_NULL:
+ njs_chb_append_literal(chain, "null");
+ break;
+
+ case NJS_UNDEFINED:
+ njs_chb_append_literal(chain, "undefined");
+ break;
+
+ case NJS_BOOLEAN:
+ if (njs_is_true(src)) {
+ njs_chb_append_literal(chain, "true");
+
+ } else {
+ njs_chb_append_literal(chain, "false");
+ }
+
+ break;
+
+ case NJS_NUMBER:
+ njs_number_to_chain(vm, chain, src);
+ break;
+
+ case NJS_SYMBOL:
+ njs_symbol_conversion_failed(vm, 1);
+ return NJS_ERROR;
+
+ case NJS_STRING:
+ njs_string_get(src, &string);
+ njs_chb_append_str(chain, &string);
+ break;
+
+ default:
+ return NJS_ERROR;
+ }
+
+ return NJS_OK;
+}
+
+
+njs_int_t
njs_value_to_object(njs_vm_t *vm, njs_value_t *value)
{
njs_object_t *object;
diff -r 5ba9145d9b0c -r 5bf71dfc052f src/njs_value.h
--- a/src/njs_value.h Wed Dec 11 15:30:26 2019 +0300
+++ b/src/njs_value.h Wed Dec 11 15:58:05 2019 +0300
@@ -946,6 +946,8 @@ const char *njs_type_string(njs_value_ty
njs_int_t njs_primitive_value_to_string(njs_vm_t *vm, njs_value_t *dst,
const njs_value_t *src);
+njs_int_t njs_primitive_value_to_chain(njs_vm_t *vm, njs_chb_t *chain,
+ const njs_value_t *src);
double njs_string_to_number(const njs_value_t *value, njs_bool_t parse_float);
njs_bool_t njs_string_eq(const njs_value_t *v1, const njs_value_t *v2);
diff -r 5ba9145d9b0c -r 5bf71dfc052f src/njs_value_conversion.h
--- a/src/njs_value_conversion.h Wed Dec 11 15:30:26 2019 +0300
+++ b/src/njs_value_conversion.h Wed Dec 11 15:58:05 2019 +0300
@@ -199,4 +199,29 @@ njs_value_to_string(njs_vm_t *vm, njs_va
}
+njs_inline njs_int_t
+njs_value_to_chain(njs_vm_t *vm, njs_chb_t *chain, njs_value_t *value)
+{
+ njs_int_t ret;
+ njs_value_t primitive;
+
+ if (njs_slow_path(!njs_is_primitive(value))) {
+ if (njs_slow_path(value->type == NJS_OBJECT_SYMBOL)) {
+ /* should fail */
+ value = njs_object_value(value);
+
+ } else {
+ ret = njs_value_to_primitive(vm, &primitive, value, 1);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return ret;
+ }
+
+ value = &primitive;
+ }
+ }
+
+ return njs_primitive_value_to_chain(vm, chain, value);
+}
+
+
#endif /* _NJS_VALUE_CONVERSION_H_INCLUDED_ */
diff -r 5ba9145d9b0c -r 5bf71dfc052f src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Wed Dec 11 15:30:26 2019 +0300
+++ b/src/test/njs_unit_test.c Wed Dec 11 15:58:05 2019 +0300
@@ -3876,6 +3876,12 @@ static njs_unit_test_t njs_test[] =
{ njs_str("var a = [1,2,3]; a.join(':')"),
njs_str("1:2:3") },
+ { njs_str("var a = ['#', '@']; var out= a.join('α'.repeat(33)); [out, out.length]"),
+ njs_str("#ααααααααααααααααααααααααααααααααα@,35") },
+
+ { njs_str("var a = ['β', 'γ']; var out= a.join('α'); [out, out.length]"),
+ njs_str("βαγ,3") },
+
{ njs_str("var a = []; a[5] = 5; a.join()"),
njs_str(",,,,,5") },
More information about the nginx-devel
mailing list