details: https://hg.nginx.org/njs/rev/82f41f43abd4 branches: changeset: 1956:82f41f43abd4 user: Dmitry Volyntsev <xei...@nginx.com> date: Thu Sep 15 20:20:11 2022 -0700 description: Fixed complex assignments.
A new instruction is introduced NJS_VMCODE_TO_PROPERTY_KEY to ensure that property key is evaluated only once. diffstat: src/njs_disassembler.c | 2 ++ src/njs_generator.c | 45 +++++++++++++++++++++++++++++++++++++-------- src/njs_value.c | 8 +++++--- src/njs_vmcode.c | 17 +++++++++++++++++ src/njs_vmcode.h | 1 + src/test/njs_unit_test.c | 7 +++++-- 6 files changed, 67 insertions(+), 13 deletions(-) diffs (231 lines): diff -r 23caaca15f08 -r 82f41f43abd4 src/njs_disassembler.c --- a/src/njs_disassembler.c Thu Sep 15 20:20:10 2022 -0700 +++ b/src/njs_disassembler.c Thu Sep 15 20:20:11 2022 -0700 @@ -74,6 +74,8 @@ static njs_code_name_t code_names[] = { njs_str("VOID ") }, { NJS_VMCODE_TYPEOF, sizeof(njs_vmcode_2addr_t), njs_str("TYPEOF ") }, + { NJS_VMCODE_TO_PROPERTY_KEY, sizeof(njs_vmcode_3addr_t), + njs_str("TO PROPERTY KEY ") }, { NJS_VMCODE_UNARY_PLUS, sizeof(njs_vmcode_2addr_t), njs_str("PLUS ") }, diff -r 23caaca15f08 -r 82f41f43abd4 src/njs_generator.c --- a/src/njs_generator.c Thu Sep 15 20:20:10 2022 -0700 +++ b/src/njs_generator.c Thu Sep 15 20:20:11 2022 -0700 @@ -3016,9 +3016,10 @@ static njs_int_t njs_generate_operation_assignment_prop(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) { - njs_index_t index, src; + njs_index_t index, src, prop_index; njs_parser_node_t *lvalue, *object, *property; njs_vmcode_move_t *move; + njs_vmcode_3addr_t *to_property_key; njs_vmcode_prop_get_t *prop_get; lvalue = node->left; @@ -3053,6 +3054,18 @@ njs_generate_operation_assignment_prop(n } } + prop_index = njs_generate_node_temp_index_get(vm, generator, node); + if (njs_slow_path(prop_index == NJS_INDEX_ERROR)) { + return NJS_ERROR; + } + + njs_generate_code(generator, njs_vmcode_3addr_t, to_property_key, + NJS_VMCODE_TO_PROPERTY_KEY, 2, property); + + to_property_key->src2 = object->index; + to_property_key->src1 = property->index; + to_property_key->dst = prop_index; + index = njs_generate_node_temp_index_get(vm, generator, node); if (njs_slow_path(index == NJS_INDEX_ERROR)) { return NJS_ERROR; @@ -3062,13 +3075,14 @@ njs_generate_operation_assignment_prop(n NJS_VMCODE_PROPERTY_GET, 3, property); prop_get->value = index; prop_get->object = object->index; - prop_get->property = property->index; + prop_get->property = prop_index; njs_generator_next(generator, njs_generate, node->right); return njs_generator_after(vm, generator, njs_queue_first(&generator->stack), node, - njs_generate_operation_assignment_end, NULL, 0); + njs_generate_operation_assignment_end, + &prop_index, sizeof(njs_index_t)); } @@ -3077,6 +3091,7 @@ njs_generate_operation_assignment_end(nj njs_parser_node_t *node) { njs_int_t ret; + njs_index_t prop_index; njs_parser_node_t *lvalue, *expr; njs_vmcode_3addr_t *code; njs_vmcode_prop_set_t *prop_set; @@ -3084,6 +3099,8 @@ njs_generate_operation_assignment_end(nj lvalue = node->left; expr = node->right; + prop_index = *((njs_index_t *) generator->context); + njs_generate_code(generator, njs_vmcode_3addr_t, code, node->u.operation, 3, expr); code->dst = node->index; @@ -3094,7 +3111,7 @@ njs_generate_operation_assignment_end(nj NJS_VMCODE_PROPERTY_SET, 3, expr); prop_set->value = node->index; prop_set->object = lvalue->left->index; - prop_set->property = lvalue->right->index; + prop_set->property = prop_index; ret = njs_generate_children_indexes_release(vm, generator, lvalue); if (njs_slow_path(ret != NJS_OK)) { @@ -3677,9 +3694,9 @@ njs_generate_inc_dec_operation_prop(njs_ { njs_int_t ret; njs_bool_t post; - njs_index_t index, dest_index; + njs_index_t index, dest_index, prop_index; njs_parser_node_t *lvalue; - njs_vmcode_3addr_t *code; + njs_vmcode_3addr_t *code, *to_property_key; njs_vmcode_prop_get_t *prop_get; njs_vmcode_prop_set_t *prop_set; @@ -3701,6 +3718,18 @@ njs_generate_inc_dec_operation_prop(njs_ found: + prop_index = njs_generate_temp_index_get(vm, generator, node); + if (njs_slow_path(prop_index == NJS_INDEX_ERROR)) { + return NJS_ERROR; + } + + njs_generate_code(generator, njs_vmcode_3addr_t, to_property_key, + NJS_VMCODE_TO_PROPERTY_KEY, 2, node); + + to_property_key->src2 = lvalue->left->index; + to_property_key->src1 = lvalue->right->index; + to_property_key->dst = prop_index; + post = *((njs_bool_t *) generator->context); index = post ? njs_generate_temp_index_get(vm, generator, node) @@ -3714,7 +3743,7 @@ found: NJS_VMCODE_PROPERTY_GET, 3, node); prop_get->value = index; prop_get->object = lvalue->left->index; - prop_get->property = lvalue->right->index; + prop_get->property = prop_index; njs_generate_code(generator, njs_vmcode_3addr_t, code, node->u.operation, 3, node); @@ -3726,7 +3755,7 @@ found: NJS_VMCODE_PROPERTY_SET, 3, node); prop_set->value = index; prop_set->object = lvalue->left->index; - prop_set->property = lvalue->right->index; + prop_set->property = prop_index; if (post) { ret = njs_generate_index_release(vm, generator, index); diff -r 23caaca15f08 -r 82f41f43abd4 src/njs_value.c --- a/src/njs_value.c Thu Sep 15 20:20:10 2022 -0700 +++ b/src/njs_value.c Thu Sep 15 20:20:11 2022 -0700 @@ -586,12 +586,14 @@ njs_property_query(njs_vm_t *vm, njs_pro if (njs_fast_path(ret == NJS_OK)) { njs_string_get(&pq->key, &pq->lhq.key); - njs_type_error(vm, "cannot get property \"%V\" of undefined", - &pq->lhq.key); + njs_type_error(vm, "cannot get property \"%V\" of %s", + &pq->lhq.key, njs_is_null(value) ? "null" + : "undefined"); return NJS_ERROR; } - njs_type_error(vm, "cannot get property \"unknown\" of undefined"); + njs_type_error(vm, "cannot get property \"unknown\" of %s", + njs_is_null(value) ? "null" : "undefined"); return NJS_ERROR; } diff -r 23caaca15f08 -r 82f41f43abd4 src/njs_vmcode.c --- a/src/njs_vmcode.c Thu Sep 15 20:20:10 2022 -0700 +++ b/src/njs_vmcode.c Thu Sep 15 20:20:11 2022 -0700 @@ -883,9 +883,26 @@ next: case NJS_VMCODE_ARGUMENTS: ret = njs_vmcode_arguments(vm, pc); if (njs_slow_path(ret == NJS_ERROR)) { + } + + break; + + case NJS_VMCODE_TO_PROPERTY_KEY: + njs_vmcode_operand(vm, (njs_index_t) value2, retval); + njs_vmcode_operand(vm, vmcode->operand3, value2); + + if (njs_slow_path(njs_is_null_or_undefined(value2))) { + (void) njs_throw_cannot_property(vm, value2, value1, + "get"); goto error; } + ret = njs_value_to_string(vm, retval, value1); + if (njs_fast_path(ret == NJS_ERROR)) { + goto error; + } + + ret = sizeof(njs_vmcode_3addr_t); break; case NJS_VMCODE_PROTO_INIT: diff -r 23caaca15f08 -r 82f41f43abd4 src/njs_vmcode.h --- a/src/njs_vmcode.h Thu Sep 15 20:20:10 2022 -0700 +++ b/src/njs_vmcode.h Thu Sep 15 20:20:11 2022 -0700 @@ -49,6 +49,7 @@ enum { NJS_VMCODE_THIS, NJS_VMCODE_ARGUMENTS, NJS_VMCODE_PROTO_INIT, + NJS_VMCODE_TO_PROPERTY_KEY, NJS_VMCODE_IMPORT, NJS_VMCODE_AWAIT, diff -r 23caaca15f08 -r 82f41f43abd4 src/test/njs_unit_test.c --- a/src/test/njs_unit_test.c Thu Sep 15 20:20:10 2022 -0700 +++ b/src/test/njs_unit_test.c Thu Sep 15 20:20:11 2022 -0700 @@ -3651,7 +3651,7 @@ static njs_unit_test_t njs_test[] = njs_str("TypeError: cannot get property \"b\" of undefined") }, { njs_str("var a = null; a.b++; a.b"), - njs_str("TypeError: cannot get property \"b\" of undefined") }, + njs_str("TypeError: cannot get property \"b\" of null") }, { njs_str("var a = true; a.b++; a.b"), njs_str("TypeError: property set on primitive boolean type") }, @@ -4423,6 +4423,9 @@ static njs_unit_test_t njs_test[] = { njs_str("var o = null; o[{toString:()=>{throw 'OOps'}}] = 1"), njs_str("TypeError: cannot set property \"[object Object]\" of null") }, + { njs_str("var o = null; o[{toString:()=>{throw 'OOps'}}] += 1"), + njs_str("TypeError: cannot get property \"[object Object]\" of null") }, + /**/ { njs_str("Array.isArray()"), @@ -12281,7 +12284,7 @@ static njs_unit_test_t njs_test[] = njs_str("TypeError: Cyclic __proto__ value") }, { njs_str("Object.prototype.__proto__.f()"), - njs_str("TypeError: cannot get property \"f\" of undefined") }, + njs_str("TypeError: cannot get property \"f\" of null") }, { njs_str("var obj = Object.create(null); obj.one = 1;" "var res = [];" _______________________________________________ nginx-devel mailing list -- nginx-devel@nginx.org To unsubscribe send an email to nginx-devel-le...@nginx.org