Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/njs_dtoa.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#ifndef _NJS_DTOA_H_INCLUDED_
#define _NJS_DTOA_H_INCLUDED_

#define NJS_DTOA_MAX_LEN njs_length("-1.7976931348623157e+308")

NJS_EXPORT size_t njs_dtoa(double value, char *start);
NJS_EXPORT size_t njs_dtoa_precision(double value, char *start, size_t prec);
NJS_EXPORT size_t njs_dtoa_exponential(double value, char *start,
Expand Down
7 changes: 1 addition & 6 deletions src/njs_flathsh.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,6 @@ njs_flathsh_unique_find(const njs_flathsh_t *fh, njs_flathsh_query_t *fhq)
njs_int_t
njs_flathsh_insert(njs_flathsh_t *fh, njs_flathsh_query_t *fhq)
{
void *tmp;
Comment thread
xeioex marked this conversation as resolved.
njs_int_t cell_num, elt_num;
njs_flathsh_elt_t *elt, *elts;
njs_flathsh_descr_t *h;
Expand All @@ -403,15 +402,11 @@ njs_flathsh_insert(njs_flathsh_t *fh, njs_flathsh_query_t *fhq)
fhq->proto->test(fhq, elt->value) == NJS_OK)
{
if (fhq->replace) {
tmp = fhq->value;
fhq->value = elt->value;
elt->value = tmp;
elt->value = fhq->value;

return NJS_OK;

} else {
fhq->value = elt->value;

return NJS_DECLINED;
}
}
Expand Down
13 changes: 6 additions & 7 deletions src/njs_flathsh.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,14 +91,13 @@ NJS_EXPORT njs_int_t njs_flathsh_unique_find(const njs_flathsh_t *fh,
njs_flathsh_query_t *fhq);

/*
* njs_flathsh_insert() adds a hash element. If the element is already
* present in flathsh and the fhq->replace flag is zero, then fhq->value
* is updated with the old element and NJS_DECLINED is returned.
* If the element is already present in flathsh and the fhq->replace flag
* is non-zero, then the old element is replaced with the new element.
* fhq->value is updated with the old element, and NJS_OK is returned.
* njs_flathsh_insert() adds a hash element. If the element is already present
* in flathsh and the fhq->replace flag is zero, then NJS_DECLINED is returned.
* If the element is already present in flathsh and the fhq->replace flag is
* non-zero, then the old element is replaced with the new element and NJS_OK is
* returned.
* If the element is not present in flathsh, then it is inserted and
* NJS_OK is returned. The fhq->value is not changed.
* NJS_OK is returned.
* On memory allocation failure NJS_ERROR is returned.
*
* The required njs_flathsh_query_t fields: key_hash, key, proto, replace,
Expand Down
12 changes: 2 additions & 10 deletions src/njs_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -993,13 +993,7 @@ njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object,

njs_object_prop_t *hash_prop = lhq.value;

/* select names of prop which are not deleted and
* not deleted and created again i.e.,
* they are replaced shared hash props
*/
if (hash_prop->type != NJS_WHITEOUT &&
!(hash_prop->enum_in_object_hash))
{
if (hash_prop->type != NJS_WHITEOUT) {
njs_process_prop(vm, &prop_name, flags, items_string,
items_symbol);
}
Expand Down Expand Up @@ -1060,8 +1054,7 @@ njs_get_own_ordered_keys(njs_vm_t *vm, const njs_object_t *object,
} else {
/* prop is: in_hash && in_shared_hash */

/* select names of not deleted and created again */
if (prop->enum_in_object_hash) {
if (prop->type == NJS_WHITEOUT) {
njs_process_prop(vm, &prop_name, flags, items_string,
items_symbol);
}
Expand Down Expand Up @@ -2438,7 +2431,6 @@ njs_property_constructor_set(njs_vm_t *vm, njs_flathsh_t *hash,
return NULL;
}

njs_value_assign(njs_prop_value(prop), constructor);
prop->enumerable = 0;

lhq.value = prop;
Expand Down
1 change: 0 additions & 1 deletion src/njs_object_prop.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ njs_object_prop_alloc2(njs_vm_t *vm,
}

prop->type = type;
prop->enum_in_object_hash = 0;

if (flags != NJS_OBJECT_PROP_UNSET) {
prop->enumerable = !!(flags & NJS_OBJECT_PROP_ENUMERABLE);
Expand Down
16 changes: 0 additions & 16 deletions src/njs_scope.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,6 @@ njs_scope_temp_index(njs_parser_scope_t *scope)
}


njs_value_t *
njs_scope_create_index_value(njs_vm_t *vm, njs_index_t index)
{
njs_value_t *value;

value = njs_mp_alloc(vm->mem_pool, sizeof(njs_value_t));
if (njs_slow_path(value == NULL)) {
return NULL;
}

njs_scope_value_set(vm, index, value);

return value;
}


njs_value_t **
njs_scope_make(njs_vm_t *vm, uint32_t count)
{
Expand Down
1 change: 0 additions & 1 deletion src/njs_scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@


njs_index_t njs_scope_temp_index(njs_parser_scope_t *scope);
njs_value_t *njs_scope_create_index_value(njs_vm_t *vm, njs_index_t index);
njs_value_t **njs_scope_make(njs_vm_t *vm, uint32_t count);
njs_index_t njs_scope_global_index(njs_vm_t *vm, const njs_value_t *src,
njs_uint_t runtime);
Expand Down
110 changes: 84 additions & 26 deletions src/njs_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -601,56 +601,114 @@ 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)
{
u_char *p, *start;
uint64_t size, length, mask;
char *np, *np_end;
double num;
u_char *p;
uint64_t sz, size, length;
njs_int_t ret;
njs_uint_t i;
njs_string_prop_t string;
char buf[512], tmp[NJS_DTOA_MAX_LEN];

if (njs_is_null_or_undefined(&args[0])) {
njs_type_error(vm, "\"this\" argument is null or undefined");
return NJS_ERROR;
}

size = 0;
length = 0;

np = buf;
np_end = buf + sizeof(buf);

for (i = 0; i < nargs; i++) {
if (!njs_is_string(&args[i])) {
ret = njs_value_to_string(vm, &args[i], &args[i]);
if (ret != NJS_OK) {
return ret;
if (njs_is_number(&args[i])) {
num = njs_number(&args[i]);

if (isnan(num)) {
size += njs_length("NaN");
length += njs_length("NaN");

} else if (isinf(num)) {
if (num < 0) {
size += njs_length("-Infinity");
length += njs_length("-Infinity");

} else {
size += njs_length("Infinity");
length += njs_length("Infinity");
}

} else {
if (njs_fast_path(np < np_end - NJS_DTOA_MAX_LEN)) {
sz = njs_dtoa(num, np + sizeof(uint8_t));

*np = (uint8_t) sz;
np += sizeof(uint8_t) + sz;

} else {
sz = njs_dtoa(num, tmp);
}

size += sz;
length += sz;
}

} else {
if (!njs_is_string(&args[i])) {
ret = njs_value_to_string(vm, &args[i], &args[i]);
if (ret != NJS_OK) {
return ret;
}

}

njs_string_prop(vm, &string, &args[i]);

size += string.size;
length += string.length;
}
}

if (nargs == 1) {
njs_string_copy(retval, &args[0]);
return NJS_OK;
p = njs_string_alloc(vm, retval, size, length);
if (njs_slow_path(p == NULL)) {
return NJS_ERROR;
}

size = 0;
length = 0;
mask = -1;
np = buf;

for (i = 0; i < nargs; i++) {
(void) njs_string_prop(vm, &string, &args[i]);
if (njs_is_number(&args[i])) {
num = njs_number(&args[i]);

size += string.size;
length += string.length;
}
if (isnan(num)) {
p = njs_cpymem(p, "NaN", njs_length("NaN"));

length &= mask;
} else if (isinf(num)) {
if (num < 0) {
p = njs_cpymem(p, "-Infinity", njs_length("-Infinity"));

start = njs_string_alloc(vm, retval, size, length);
if (njs_slow_path(start == NULL)) {
return NJS_ERROR;
}
} else {
p = njs_cpymem(p, "Infinity", njs_length("Infinity"));
}

p = start;
} else {
if (njs_fast_path(np < np_end - NJS_DTOA_MAX_LEN)) {
length = *np++;
p = njs_cpymem(p, np, length);
np += length;

for (i = 0; i < nargs; i++) {
(void) njs_string_prop(vm, &string, &args[i]);
} else {
sz = njs_dtoa(num, (char *) p);
p += sz;
}
}

p = memcpy(p, string.start, string.size);
p += string.size;
} else {
njs_string_prop(vm, &string, &args[i]);

p = njs_cpymem(p, string.start, string.size);
}
}

return NJS_OK;
Expand Down
1 change: 0 additions & 1 deletion src/njs_value.c
Original file line number Diff line number Diff line change
Expand Up @@ -1452,7 +1452,6 @@ njs_value_property_delete(njs_vm_t *vm, njs_value_t *value, uint32_t atom_id,
}

prop->type = NJS_WHITEOUT;
prop->enum_in_object_hash = 1;

return NJS_OK;
}
Expand Down
1 change: 0 additions & 1 deletion src/njs_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,6 @@ struct njs_object_prop_s {
#define njs_prop_setter(_p) (_p)->u.accessor.setter

njs_object_prop_type_t type:8; /* 3 bits */
njs_object_prop_type_t enum_in_object_hash:8; /* 3 bits */

njs_object_attribute_t writable:8; /* 2 bits */
njs_object_attribute_t enumerable:8; /* 2 bits */
Expand Down
54 changes: 47 additions & 7 deletions src/njs_vmcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 (njs_is_number(src)) {
size_t size;
njs_string_t sp;
char buf[64];

ret = njs_string_concat(vm, s1, s2, &name);
if (njs_slow_path(ret == NJS_ERROR)) {
goto error;
/* Alloc free path for "str" + int or int + "str" concatenation. */

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, buf);

sp.start = (u_char *) buf;
sp.size = size;
sp.length = 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);
Expand Down Expand Up @@ -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);
}

Expand Down
9 changes: 9 additions & 0 deletions src/test/njs_unit_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -11036,6 +11036,15 @@ static njs_unit_test_t njs_test[] =
{ njs_str("''.concat.apply('a', [ 'b', 'c' ], 'd')"),
njs_str("abc") },

{ njs_str("''.concat.apply('', Array(128).fill(1.23456789123e14)) == '123456789123000'.repeat(128)"),
njs_str("true") },

{ njs_str("''.concat.apply('', Array(128).fill(0).map((v,i)=>Math.log2(i))).startsWith('-Infinity')"),
njs_str("true") },

{ njs_str("''.concat.apply('', Array(256).fill(0).map((v,i)=> !(i % 2) ? Math.exp(i) : 'α'.repeat(Math.log2(i)))).endsWith('110ααααααα')"),
njs_str("true") },

{ njs_str("[].join.call([1,2,3])"),
njs_str("1,2,3") },

Expand Down