[njs] This object as a variable.

Dmitry Volyntsev xeioex at nginx.com
Fri Apr 12 16:58:15 UTC 2019


details:   https://hg.nginx.org/njs/rev/070b635928a9
branches:  
changeset: 887:070b635928a9
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Wed Apr 10 17:46:29 2019 +0300
description:
This object as a variable.

Non-local this is introduced to support arrow functions.
this is non-local when reference scope != first non-arrow
function scope.

diffstat:

 njs/njs_disassembler.c    |   2 ++
 njs/njs_generator.c       |   8 ++++++++
 njs/njs_lexer.h           |   1 +
 njs/njs_parser.h          |  15 +++++++++++++++
 njs/njs_parser_terminal.c |  28 ++++++++++++++++++++++++++--
 njs/njs_variable.h        |   1 +
 njs/njs_vm.c              |  17 +++++++++++++++++
 njs/njs_vm.h              |   8 ++++++++
 8 files changed, 78 insertions(+), 2 deletions(-)

diffs (187 lines):

diff -r f582672967ad -r 070b635928a9 njs/njs_disassembler.c
--- a/njs/njs_disassembler.c	Wed Apr 10 17:46:29 2019 +0300
+++ b/njs/njs_disassembler.c	Wed Apr 10 17:46:29 2019 +0300
@@ -23,6 +23,8 @@ static njs_code_name_t  code_names[] = {
           nxt_string("OBJECT          ") },
     { njs_vmcode_function, sizeof(njs_vmcode_function_t),
           nxt_string("FUNCTION        ") },
+    { njs_vmcode_this, sizeof(njs_vmcode_this_t),
+          nxt_string("THIS            ") },
     { njs_vmcode_arguments, sizeof(njs_vmcode_arguments_t),
           nxt_string("ARGUMENTS       ") },
     { njs_vmcode_regexp, sizeof(njs_vmcode_regexp_t),
diff -r f582672967ad -r 070b635928a9 njs/njs_generator.c
--- a/njs/njs_generator.c	Wed Apr 10 17:46:29 2019 +0300
+++ b/njs/njs_generator.c	Wed Apr 10 17:46:29 2019 +0300
@@ -427,6 +427,7 @@ njs_generator(njs_vm_t *vm, njs_generato
 
     case NJS_TOKEN_NAME:
     case NJS_TOKEN_ARGUMENTS:
+    case NJS_TOKEN_NON_LOCAL_THIS:
         return njs_generate_name(vm, generator, node);
 
     case NJS_TOKEN_GLOBAL_THIS:
@@ -2414,6 +2415,7 @@ njs_generate_lambda_variables(njs_vm_t *
     njs_variable_t          *var;
     njs_vmcode_move_t       *move;
     nxt_lvlhsh_each_t       lhe;
+    njs_vmcode_this_t       *this;
     njs_vmcode_arguments_t  *arguments;
 
     nxt_lvlhsh_each_init(&lhe, &njs_variables_hash_proto);
@@ -2431,6 +2433,12 @@ njs_generate_lambda_variables(njs_vm_t *
             njs_generate_code_move(generator, move, var->index, index);
         }
 
+        if (var->this_object) {
+            njs_generate_code(generator, njs_vmcode_this_t, this,
+                              njs_vmcode_this, 1, 0);
+            this->dst = var->index;
+        }
+
         if (var->arguments_object) {
             njs_generate_code(generator, njs_vmcode_arguments_t, arguments,
                               njs_vmcode_arguments, 1, 0);
diff -r f582672967ad -r 070b635928a9 njs/njs_lexer.h
--- a/njs/njs_lexer.h	Wed Apr 10 17:46:29 2019 +0300
+++ b/njs/njs_lexer.h	Wed Apr 10 17:46:29 2019 +0300
@@ -159,6 +159,7 @@ typedef enum {
     NJS_TOKEN_THROW,
 
     NJS_TOKEN_THIS,
+    NJS_TOKEN_NON_LOCAL_THIS,
     NJS_TOKEN_ARGUMENTS,
 
 #define NJS_TOKEN_FIRST_OBJECT     NJS_TOKEN_GLOBAL_THIS
diff -r f582672967ad -r 070b635928a9 njs/njs_parser.h
--- a/njs/njs_parser.h	Wed Apr 10 17:46:29 2019 +0300
+++ b/njs/njs_parser.h	Wed Apr 10 17:46:29 2019 +0300
@@ -225,6 +225,21 @@ njs_parser_global_scope(njs_vm_t *vm)
 }
 
 
+nxt_inline njs_parser_scope_t *
+njs_function_scope(njs_parser_scope_t *scope)
+{
+    while (scope->type != NJS_SCOPE_GLOBAL) {
+        if (scope->type == NJS_SCOPE_FUNCTION) {
+            return scope;
+        }
+
+        scope = scope->parent;
+    }
+
+    return NULL;
+}
+
+
 extern const nxt_lvlhsh_proto_t  njs_keyword_hash_proto;
 
 
diff -r f582672967ad -r 070b635928a9 njs/njs_parser_terminal.c
--- a/njs/njs_parser_terminal.c	Wed Apr 10 17:46:29 2019 +0300
+++ b/njs/njs_parser_terminal.c	Wed Apr 10 17:46:29 2019 +0300
@@ -215,14 +215,38 @@ njs_parser_reference(njs_vm_t *vm, njs_p
 
         while (scope->type != NJS_SCOPE_GLOBAL) {
             if (scope->type == NJS_SCOPE_FUNCTION) {
-                node->index = NJS_INDEX_THIS;
                 break;
             }
 
             scope = scope->parent;
         }
 
-        if (node->index == NJS_INDEX_THIS) {
+        if (scope->type != NJS_SCOPE_GLOBAL) {
+            if (njs_function_scope(scope)
+                == njs_function_scope(parser->scope))
+            {
+                node->index = NJS_INDEX_THIS;
+
+            } else {
+                node->token = NJS_TOKEN_NON_LOCAL_THIS;
+
+                node->token_line = token_line;
+
+                ret = njs_variable_reference(vm, parser->scope, node, name,
+                                             hash, NJS_REFERENCE);
+                if (nxt_slow_path(ret != NXT_OK)) {
+                    return NULL;
+                }
+
+                var = njs_variable_add(vm, parser->scope, name, hash,
+                                       NJS_VARIABLE_VAR);
+                if (nxt_slow_path(var == NULL)) {
+                    return NULL;
+                }
+
+                var->this_object = 1;
+            }
+
             break;
         }
 
diff -r f582672967ad -r 070b635928a9 njs/njs_variable.h
--- a/njs/njs_variable.h	Wed Apr 10 17:46:29 2019 +0300
+++ b/njs/njs_variable.h	Wed Apr 10 17:46:29 2019 +0300
@@ -23,6 +23,7 @@ typedef struct {
 
     njs_variable_type_t   type:8;    /* 3 bits */
     uint8_t               argument;
+    uint8_t               this_object;
     uint8_t               arguments_object;
 
     njs_index_t           index;
diff -r f582672967ad -r 070b635928a9 njs/njs_vm.c
--- a/njs/njs_vm.c	Wed Apr 10 17:46:29 2019 +0300
+++ b/njs/njs_vm.c	Wed Apr 10 17:46:29 2019 +0300
@@ -391,6 +391,23 @@ njs_vmcode_function(njs_vm_t *vm, njs_va
 
 
 njs_ret_t
+njs_vmcode_this(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
+{
+    njs_frame_t        *frame;
+    njs_value_t        *value;
+    njs_vmcode_this_t  *code;
+
+    frame = (njs_frame_t *) vm->active_frame;
+    code = (njs_vmcode_this_t *) vm->current;
+
+    value = njs_vmcode_operand(vm, code->dst);
+    *value = frame->native.arguments[0];
+
+    return sizeof(njs_vmcode_this_t);
+}
+
+
+njs_ret_t
 njs_vmcode_arguments(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2)
 {
     nxt_int_t               ret;
diff -r f582672967ad -r 070b635928a9 njs/njs_vm.h
--- a/njs/njs_vm.h	Wed Apr 10 17:46:29 2019 +0300
+++ b/njs/njs_vm.h	Wed Apr 10 17:46:29 2019 +0300
@@ -638,6 +638,12 @@ typedef struct {
 
 
 typedef struct {
+     njs_vmcode_t              code;
+     njs_index_t               dst;
+} njs_vmcode_this_t;
+
+
+typedef struct {
     njs_vmcode_t               code;
     njs_index_t                dst;
 } njs_vmcode_arguments_t;
@@ -1141,6 +1147,8 @@ njs_ret_t njs_vmcode_array(njs_vm_t *vm,
     njs_value_t *inlvd2);
 njs_ret_t njs_vmcode_function(njs_vm_t *vm, njs_value_t *inlvd1,
     njs_value_t *invld2);
+njs_ret_t njs_vmcode_this(njs_vm_t *vm, njs_value_t *inlvd1,
+    njs_value_t *invld2);
 njs_ret_t njs_vmcode_arguments(njs_vm_t *vm, njs_value_t *inlvd1,
     njs_value_t *invld2);
 njs_ret_t njs_vmcode_regexp(njs_vm_t *vm, njs_value_t *inlvd1,


More information about the nginx-devel mailing list