From: Dmitry Volyntsev Date: Wed, 10 Apr 2019 14:46:29 +0000 (+0300) Subject: This object as a variable. X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/static/gitweb.js?a=commitdiff_plain;h=d58cbc30192361fc02d5444d2f990643a23e20e1;p=njs.git 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. --- diff --git a/njs/njs_disassembler.c b/njs/njs_disassembler.c index 55a7bcbf..f3f9f837 100644 --- a/njs/njs_disassembler.c +++ b/njs/njs_disassembler.c @@ -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 --git a/njs/njs_generator.c b/njs/njs_generator.c index f1143323..35beb580 100644 --- a/njs/njs_generator.c +++ b/njs/njs_generator.c @@ -427,6 +427,7 @@ njs_generator(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) 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 *vm, njs_generator_t *generator, 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 *vm, njs_generator_t *generator, 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 --git a/njs/njs_lexer.h b/njs/njs_lexer.h index 62712ac8..95758747 100644 --- a/njs/njs_lexer.h +++ b/njs/njs_lexer.h @@ -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 --git a/njs/njs_parser.h b/njs/njs_parser.h index 95fb681a..d2cfff5f 100644 --- a/njs/njs_parser.h +++ b/njs/njs_parser.h @@ -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 --git a/njs/njs_parser_terminal.c b/njs/njs_parser_terminal.c index 55461902..1e552f90 100644 --- a/njs/njs_parser_terminal.c +++ b/njs/njs_parser_terminal.c @@ -215,14 +215,38 @@ njs_parser_reference(njs_vm_t *vm, njs_parser_t *parser, njs_token_t token, 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 --git a/njs/njs_variable.h b/njs/njs_variable.h index 12d38b92..468890f9 100644 --- a/njs/njs_variable.h +++ b/njs/njs_variable.h @@ -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 --git a/njs/njs_vm.c b/njs/njs_vm.c index ff2c0fe3..7c630461 100644 --- a/njs/njs_vm.c +++ b/njs/njs_vm.c @@ -390,6 +390,23 @@ njs_vmcode_function(njs_vm_t *vm, njs_value_t *invld1, njs_value_t *invld2) } +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) { diff --git a/njs/njs_vm.h b/njs/njs_vm.h index 565620e4..2fdc5a4d 100644 --- a/njs/njs_vm.h +++ b/njs/njs_vm.h @@ -637,6 +637,12 @@ typedef struct { } njs_vmcode_object_t; +typedef struct { + njs_vmcode_t code; + njs_index_t dst; +} njs_vmcode_this_t; + + typedef struct { njs_vmcode_t code; njs_index_t dst; @@ -1141,6 +1147,8 @@ njs_ret_t njs_vmcode_array(njs_vm_t *vm, njs_value_t *inlvd1, 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,