details: https://hg.nginx.org/njs/rev/78f0887e5aa6 branches: changeset: 1478:78f0887e5aa6 user: Alexander Borisov <alexander.bori...@nginx.com> date: Thu Jul 23 13:24:10 2020 +0300 description: Fixed pre/post increment/decrement in assignment operations.
Previously, the compound assignment operations did not create temporary index for increments/decrements in the generator. The result was that the increment/decrement changed the value immediately in place, which led to incorrect calculations. The fix is to use a separate temporary index for increments/decrements in assignment operations. This closes #271 issue on GitHub. diffstat: src/njs_generator.c | 30 ++++++++++++++++++++++++- src/njs_lexer.h | 11 +++++---- src/test/njs_unit_test.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 6 deletions(-) diffs (165 lines): diff -r 7f5c5a425d03 -r 78f0887e5aa6 src/njs_generator.c --- a/src/njs_generator.c Wed Jul 22 15:21:15 2020 +0300 +++ b/src/njs_generator.c Thu Jul 23 13:24:10 2020 +0300 @@ -1799,7 +1799,7 @@ njs_generate_operation_assignment(njs_vm njs_parser_node_t *node) { njs_int_t ret; - njs_index_t index; + njs_index_t index, src; njs_parser_node_t *lvalue, *expr, *object, *property; njs_vmcode_move_t *move; njs_vmcode_3addr_t *code; @@ -1876,6 +1876,34 @@ njs_generate_operation_assignment(njs_vm return ret; } + if (njs_slow_path(njs_parser_has_side_effect(node->right))) { + /* + * Preserve object and property values stored in variables in a case + * if the variables can be changed by side effects in expression. + */ + if (object->token_type == NJS_TOKEN_NAME) { + src = object->index; + + index = njs_generate_node_temp_index_get(vm, generator, object); + if (njs_slow_path(index == NJS_INDEX_ERROR)) { + return NJS_ERROR; + } + + njs_generate_code_move(generator, move, index, src, object); + } + + if (property->token_type == NJS_TOKEN_NAME) { + src = property->index; + + index = njs_generate_node_temp_index_get(vm, generator, property); + if (njs_slow_path(index == NJS_INDEX_ERROR)) { + return NJS_ERROR; + } + + njs_generate_code_move(generator, move, index, src, property); + } + } + index = njs_generate_node_temp_index_get(vm, generator, node); if (njs_slow_path(index == NJS_INDEX_ERROR)) { return NJS_ERROR; diff -r 7f5c5a425d03 -r 78f0887e5aa6 src/njs_lexer.h --- a/src/njs_lexer.h Wed Jul 22 15:21:15 2020 +0300 +++ b/src/njs_lexer.h Thu Jul 23 13:24:10 2020 +0300 @@ -51,7 +51,12 @@ typedef enum { NJS_TOKEN_BITWISE_XOR_ASSIGNMENT, NJS_TOKEN_BITWISE_AND_ASSIGNMENT, -#define NJS_TOKEN_LAST_ASSIGNMENT NJS_TOKEN_BITWISE_AND_ASSIGNMENT + NJS_TOKEN_INCREMENT, + NJS_TOKEN_DECREMENT, + NJS_TOKEN_POST_INCREMENT, + NJS_TOKEN_POST_DECREMENT, + +#define NJS_TOKEN_LAST_ASSIGNMENT NJS_TOKEN_POST_DECREMENT NJS_TOKEN_EQUAL, NJS_TOKEN_STRICT_EQUAL, @@ -60,13 +65,9 @@ typedef enum { NJS_TOKEN_ADDITION, NJS_TOKEN_UNARY_PLUS, - NJS_TOKEN_INCREMENT, - NJS_TOKEN_POST_INCREMENT, NJS_TOKEN_SUBSTRACTION, NJS_TOKEN_UNARY_NEGATION, - NJS_TOKEN_DECREMENT, - NJS_TOKEN_POST_DECREMENT, NJS_TOKEN_MULTIPLICATION, diff -r 7f5c5a425d03 -r 78f0887e5aa6 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Wed Jul 22 15:21:15 2020 +0300 +++ b/src/test/njs_unit_test.c Thu Jul 23 13:24:10 2020 +0300 @@ -2183,6 +2183,20 @@ static njs_unit_test_t njs_test[] = "var b = ++a; a +' '+ b"), njs_str("NaN NaN") }, + { njs_str("var a = 0; a = a + ++a; a"), + njs_str("1") }, + + { njs_str("var a = 0; a += a + ++a; a"), + njs_str("1") }, + + { njs_str("var i = 0, arr = ['a', 'b'];" + "arr[i] = arr[i] + arr[++i]; arr"), + njs_str("ab,b") }, + + { njs_str("var i = 0, arr = ['a', 'b'];" + "arr[i] += arr[i] + arr[++i]; arr"), + njs_str("aab,b") }, + /* Post increment. */ { njs_str("var a = 1; a++"), @@ -2265,6 +2279,20 @@ static njs_unit_test_t njs_test[] = "var b = a++; a +' '+ b"), njs_str("NaN NaN") }, + { njs_str("var a = 0; a = a + a++; a"), + njs_str("0") }, + + { njs_str("var a = 0; a += a + a++; a"), + njs_str("0") }, + + { njs_str("var i = 1, arr = ['a', 'b'];" + "arr[i] = arr[i] + arr[i++]; arr"), + njs_str("a,bb") }, + + { njs_str("var i = 1, arr = ['a', 'b'];" + "arr[i] += arr[i] + arr[i++]; arr"), + njs_str("a,bbb") }, + /* Decrement. */ { njs_str("var a = 1; --a"), @@ -2347,6 +2375,20 @@ static njs_unit_test_t njs_test[] = "var b = --a; a +' '+ b"), njs_str("NaN NaN") }, + { njs_str("var a = 0; a = a + --a; a"), + njs_str("-1") }, + + { njs_str("var a = 0; a -= a + --a; a"), + njs_str("1") }, + + { njs_str("var i = 1, arr = ['a', 'b'];" + "arr[i] = arr[i] + arr[--i]; arr"), + njs_str("a,ba") }, + + { njs_str("var i = 1, arr = ['a', 'b'];" + "arr[i] += arr[i] + arr[--i]; arr"), + njs_str("a,bba") }, + /* Post decrement. */ { njs_str("var a = 1; a--"), @@ -2429,6 +2471,20 @@ static njs_unit_test_t njs_test[] = "var b = a--; a +' '+ b"), njs_str("NaN NaN") }, + { njs_str("var a = 0; a = a + a--; a"), + njs_str("0") }, + + { njs_str("var a = 0; a += a + a--; a"), + njs_str("0") }, + + { njs_str("var i = 1, arr = ['a', 'b'];" + "arr[i] = arr[i] + arr[i--]; arr"), + njs_str("a,bb") }, + + { njs_str("var i = 1, arr = ['a', 'b'];" + "arr[i] += arr[i] + arr[i--]; arr"), + njs_str("a,bbb") }, + /**/ { njs_str("var a, b; a = 2; b = ++a + ++a; a + ' ' + b"), _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel