[njs] Fixed assignment to global property by name only.

Vadim Zhestikov v.zhestikov at f5.com
Fri Jul 22 01:40:12 UTC 2022


details:   https://hg.nginx.org/njs/rev/4b8d8237f598
branches:  
changeset: 1916:4b8d8237f598
user:      Vadim Zhestikov <v.zhestikov at f5.com>
date:      Thu Jul 21 18:33:20 2022 -0700
description:
Fixed assignment to global property by name only.

This closes #145 issue on Github.

diffstat:

 src/njs_generator.c      |  72 ++++++++++++++++++++++++++++++++++++++++++++++--
 src/test/njs_unit_test.c |  22 ++++++++++++++
 2 files changed, 91 insertions(+), 3 deletions(-)

diffs (170 lines):

diff -r c597ee3450ab -r 4b8d8237f598 src/njs_generator.c
--- a/src/njs_generator.c	Wed Jul 20 17:49:00 2022 -0700
+++ b/src/njs_generator.c	Thu Jul 21 18:33:20 2022 -0700
@@ -222,6 +222,9 @@ static njs_int_t njs_generate_comma_expr
     njs_generator_t *generator, njs_parser_node_t *node);
 static njs_int_t njs_generate_comma_expression_end(njs_vm_t *vm,
     njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_global_property_set(njs_vm_t *vm,
+    njs_generator_t *generator, njs_parser_node_t *node_dst,
+    njs_parser_node_t *node_src);
 static njs_int_t njs_generate_assignment(njs_vm_t *vm,
     njs_generator_t *generator, njs_parser_node_t *node);
 static njs_int_t njs_generate_assignment_name(njs_vm_t *vm,
@@ -2659,6 +2662,53 @@ njs_generate_comma_expression_end(njs_vm
 
 
 static njs_int_t
+njs_generate_global_property_set(njs_vm_t *vm, njs_generator_t *generator,
+    njs_parser_node_t *node_dst, njs_parser_node_t *node_src)
+{
+    ssize_t                  length;
+    njs_int_t                ret;
+    njs_value_t              property;
+    njs_variable_t           *var;
+    njs_vmcode_prop_set_t    *prop_set;
+    const njs_lexer_entry_t  *lex_entry;
+
+    var = njs_variable_reference(vm, node_dst);
+    if (var == NULL) {
+        njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set,
+                          NJS_VMCODE_PROPERTY_SET, 3, node_src);
+
+        prop_set->value = node_dst->index;
+        prop_set->object = njs_scope_global_this_index();
+
+        lex_entry = njs_lexer_entry(node_dst->u.reference.unique_id);
+        if (njs_slow_path(lex_entry == NULL)) {
+            return NJS_ERROR;
+        }
+
+        length = njs_utf8_length(lex_entry->name.start, lex_entry->name.length);
+        if (njs_slow_path(length < 0)) {
+            return NJS_ERROR;
+        }
+
+        ret = njs_string_new(vm, &property, lex_entry->name.start,
+                         lex_entry->name.length, length);
+        if (njs_slow_path(ret != NJS_OK)) {
+            return NJS_ERROR;
+        }
+
+        prop_set->property = njs_scope_global_index(vm, &property,
+                                                generator->runtime);
+        if (njs_slow_path(prop_set->property == NJS_INDEX_ERROR)) {
+            return NJS_ERROR;
+        }
+
+    }
+
+    return NJS_OK;
+}
+
+
+static njs_int_t
 njs_generate_assignment(njs_vm_t *vm, njs_generator_t *generator,
     njs_parser_node_t *node)
 {
@@ -2673,7 +2723,7 @@ njs_generate_assignment(njs_vm_t *vm, nj
 
     if (lvalue->token_type == NJS_TOKEN_NAME) {
 
-        ret = njs_generate_variable(vm, generator, lvalue, NJS_DECLARATION,
+        ret = njs_generate_variable(vm, generator, lvalue, NJS_REFERENCE,
                                     &var);
         if (njs_slow_path(ret != NJS_OK)) {
             return ret;
@@ -2721,6 +2771,7 @@ static njs_int_t
 njs_generate_assignment_name(njs_vm_t *vm, njs_generator_t *generator,
     njs_parser_node_t *node)
 {
+    njs_int_t          ret;
     njs_parser_node_t  *lvalue, *expr;
     njs_vmcode_move_t  *move;
 
@@ -2739,6 +2790,11 @@ njs_generate_assignment_name(njs_vm_t *v
     node->index = expr->index;
     node->temporary = expr->temporary;
 
+    ret = njs_generate_global_property_set(vm, generator, node->left, expr);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return ret;
+    }
+
     return njs_generator_stack_pop(vm, generator, NULL);
 }
 
@@ -2855,7 +2911,7 @@ njs_generate_operation_assignment(njs_vm
 
     if (lvalue->token_type == NJS_TOKEN_NAME) {
 
-        ret = njs_generate_variable(vm, generator, lvalue, NJS_DECLARATION,
+        ret = njs_generate_variable(vm, generator, lvalue, NJS_REFERENCE,
                                     &var);
         if (njs_slow_path(ret != NJS_OK)) {
             return ret;
@@ -2938,6 +2994,11 @@ njs_generate_operation_assignment_name(n
 
     node->index = lvalue->index;
 
+    ret = njs_generate_global_property_set(vm, generator, node->left, expr);
+    if (njs_slow_path(ret != NJS_OK)) {
+        return ret;
+    }
+
     if (lvalue->index != index) {
         ret = njs_generate_index_release(vm, generator, index);
         if (njs_slow_path(ret != NJS_OK)) {
@@ -3553,7 +3614,7 @@ njs_generate_inc_dec_operation(njs_vm_t 
 
     if (lvalue->token_type == NJS_TOKEN_NAME) {
 
-        ret = njs_generate_variable(vm, generator, lvalue, NJS_DECLARATION,
+        ret = njs_generate_variable(vm, generator, lvalue, NJS_REFERENCE,
                                     &var);
         if (njs_slow_path(ret != NJS_OK)) {
             return ret;
@@ -3580,6 +3641,11 @@ njs_generate_inc_dec_operation(njs_vm_t 
         code->src1 = lvalue->index;
         code->src2 = lvalue->index;
 
+        ret = njs_generate_global_property_set(vm, generator, lvalue, lvalue);
+        if (njs_slow_path(ret) != NJS_OK) {
+            return ret;
+        }
+
         return njs_generator_stack_pop(vm, generator, NULL);
     }
 
diff -r c597ee3450ab -r 4b8d8237f598 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Wed Jul 20 17:49:00 2022 -0700
+++ b/src/test/njs_unit_test.c	Thu Jul 21 18:33:20 2022 -0700
@@ -12077,6 +12077,28 @@ static njs_unit_test_t  njs_test[] =
     { njs_str("this.a = 1; a"),
       njs_str("1") },
 
+    { njs_str("this.a = 1; a = 3; this.a"),
+      njs_str("3") },
+
+    { njs_str("this.a = 1; ++a; this.a"),
+      njs_str("2") },
+
+    { njs_str("this.a = 1; a += 3; this.a"),
+      njs_str("4") },
+
+    { njs_str("var b=11;"
+              "var t = function () {b += 5; return b};"
+              "t() === 16 && b === 16 && this.b === 16" ),
+      njs_str("true") },
+
+    { njs_str("this.c=15;"
+              "var t = function () {c += 5; return c};"
+              "t() === 20 && c === 20 && this.c === 20" ),
+      njs_str("true") },
+
+    { njs_str("--undefined"),
+      njs_str("TypeError: Cannot assign to read-only property \"undefined\" of object") },
+
     { njs_str("this.a = 2; this.b = 3; a * b - a"),
       njs_str("4") },
 



More information about the nginx-devel mailing list