[njs] Fixed complex assignments.
Dmitry Volyntsev
xeioex at nginx.com
Fri Sep 16 06:46:17 UTC 2022
details: https://hg.nginx.org/njs/rev/82f41f43abd4
branches:
changeset: 1956:82f41f43abd4
user: Dmitry Volyntsev <xeioex at 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 = [];"
More information about the nginx-devel
mailing list