file = njs_str_value("runtime");
- ret = njs_parser_init(vm, &parser, NULL, &file, str.start,
+ ret = njs_parser_init(vm, &parser, NULL, 0, &file, str.start,
str.start + str.length);
if (njs_slow_path(ret != NJS_OK)) {
goto done;
njs_parser_scope_t *scope;
njs_vmcode_variable_t *variable;
- var = njs_variable_reference(vm, node);
+ var = njs_variable_reference(vm, generator->mem_pool, node);
if (njs_slow_path(var == NULL)) {
ret = njs_generate_global_reference(vm, generator, node, 1);
if (njs_slow_path(ret != NJS_OK)) {
njs_parser_scope_t *scope;
njs_vmcode_variable_t *variable;
- var = njs_variable_reference(vm, node);
+ var = njs_variable_reference(vm, generator->mem_pool, node);
if (retvar != NULL) {
*retvar = var;
lvalue = foreach->left;
expr = node->right;
- var = njs_variable_reference(vm, lvalue);
+ var = njs_variable_reference(vm, generator->mem_pool, lvalue);
if (var != NULL) {
ctx->index_next_value = lvalue->index;
right = node->right;
if (right != NULL && right->token_type == NJS_TOKEN_NAME) {
- var = njs_variable_reference(vm, right);
+ var = njs_variable_reference(vm, generator->mem_pool, right);
if (njs_slow_path(var == NULL)) {
goto statement;
}
njs_variable_t *var;
njs_vmcode_prop_set_t *prop_set;
- var = njs_variable_reference(vm, node_dst);
+ var = njs_variable_reference(vm, generator->mem_pool, node_dst);
if (var == NULL) {
njs_generate_code(generator, njs_vmcode_prop_set_t, prop_set,
NJS_VMCODE_PROPERTY_ATOM_SET, node_src);
njs_function_lambda_t *lambda;
njs_vmcode_function_t *function;
- var = njs_variable_reference(vm, node->left);
+ var = njs_variable_reference(vm, generator->mem_pool, node->left);
if (njs_slow_path(var == NULL)) {
ret = njs_generate_reference_error(vm, generator, node->left);
if (njs_slow_path(ret != NJS_OK)) {
njs_function_t *function;
njs_function_lambda_t *lambda;
- var = njs_variable_reference(vm, node);
+ var = njs_variable_reference(vm, generator->mem_pool, node);
if (njs_slow_path(var == NULL)) {
ret = njs_generate_reference_error(vm, generator, node);
if (njs_slow_path(ret != NJS_OK)) {
njs_function_lambda_t *lambda, njs_parser_node_t *node,
const njs_str_t *name)
{
+ size_t size;
njs_int_t ret;
njs_uint_t depth;
+ njs_index_t *closures;
njs_vm_code_t *code;
njs_generator_t generator;
}
lambda->start = generator.code_start;
- lambda->closures = generator.closures->start;
lambda->nclosures = generator.closures->items;
lambda->nlocal = node->scope->items;
+ if (lambda->nclosures != 0) {
+ size = lambda->nclosures * sizeof(njs_index_t);
+
+ closures = njs_mp_alloc(vm->mem_pool, size);
+ if (njs_slow_path(closures == NULL)) {
+ njs_memory_error(vm);
+ return NJS_ERROR;
+ }
+
+ memcpy(closures, generator.closures->start, size);
+ lambda->closures = closures;
+ }
+
return NJS_OK;
}
generator->lines = code->lines;
}
- generator->closures = njs_arr_create(vm->mem_pool, 4, sizeof(njs_index_t));
+ generator->closures = njs_arr_create(generator->mem_pool, 4,
+ sizeof(njs_index_t));
if (njs_slow_path(generator->closures == NULL)) {
return NULL;
}
if (node->token_type == NJS_TOKEN_CATCH) {
/* A "try/catch" case. */
- var = njs_variable_reference(vm, node->left);
+ var = njs_variable_reference(vm, generator->mem_pool, node->left);
if (njs_slow_path(var == NULL)) {
return NJS_ERROR;
}
if (node->left != NULL) {
/* A try/catch/finally case. */
- var = njs_variable_reference(vm, node->left->left);
+ var = njs_variable_reference(vm, generator->mem_pool,
+ node->left->left);
if (njs_slow_path(var == NULL)) {
return NJS_ERROR;
}
lvalue = node->left;
- var = njs_variable_reference(vm, lvalue);
+ var = njs_variable_reference(vm, generator->mem_pool, lvalue);
if (njs_slow_path(var == NULL)) {
return NJS_ERROR;
}
njs_int_t
njs_parser_init(njs_vm_t *vm, njs_parser_t *parser, njs_parser_scope_t *scope,
- njs_str_t *file, u_char *start, u_char *end)
+ njs_bool_t persistent_global, njs_str_t *file, u_char *start, u_char *end)
{
njs_int_t ret;
njs_lexer_t *lexer;
njs_memzero(parser, sizeof(njs_parser_t));
parser->scope = scope;
+ parser->persistent_scope = scope;
+ parser->persistent_global = persistent_global;
parser->mem_pool = njs_mp_fast_create(2 * njs_pagesize(), 128, 512, 16);
if (njs_slow_path(parser->mem_pool == NULL)) {
void
njs_parser_destroy(njs_parser_t *parser)
{
- njs_parser_scope_t *scope;
+ njs_variable_t *var;
+ njs_rbtree_node_t *node;
+ njs_parser_scope_t *scope;
+ njs_variable_node_t *var_node;
for (scope = parser->scope; scope != NULL; scope = scope->parent) {
scope->top = NULL;
}
+ if (parser->persistent_scope != NULL) {
+ node = njs_rbtree_min(&parser->persistent_scope->variables);
+
+ while (njs_rbtree_is_there_successor(
+ &parser->persistent_scope->variables, node))
+ {
+ var_node = (njs_variable_node_t *) node;
+ var = var_node->variable;
+
+ if (var->original != parser->persistent_scope) {
+ var->original = NULL;
+ }
+
+ node = njs_rbtree_node_successor(
+ &parser->persistent_scope->variables, node);
+ }
+
+ njs_rbtree_init(&parser->persistent_scope->references,
+ njs_parser_scope_rbtree_compare);
+ parser->persistent_scope->closures = NULL;
+ parser->persistent_scope->declarations = NULL;
+ }
+
if (parser->mem_pool != NULL) {
njs_mp_destroy(parser->mem_pool);
parser->mem_pool = NULL;
njs_variable_t *var;
njs_parser_scope_t *scope, *parent;
- scope = njs_mp_zalloc(parser->vm->mem_pool, sizeof(njs_parser_scope_t));
+ if (parser->scope == NULL && parser->persistent_global) {
+ scope = njs_mp_zalloc(parser->vm->mem_pool,
+ sizeof(njs_parser_scope_t));
+
+ } else {
+ scope = njs_mp_zalloc(parser->mem_pool, sizeof(njs_parser_scope_t));
+ }
if (njs_slow_path(scope == NULL)) {
return NJS_ERROR;
}
scope->parent = parent;
parser->scope = scope;
+ if (parent == NULL && parser->persistent_global) {
+ parser->persistent_scope = scope;
+ }
+
if (type == NJS_SCOPE_FUNCTION || type == NJS_SCOPE_GLOBAL) {
if (init_this) {
/* Add this as first variable. */
return NJS_OK;
}
- rb_parse_node = njs_mp_alloc(parser->vm->mem_pool,
+ rb_parse_node = njs_mp_alloc(parser->mem_pool,
sizeof(njs_parser_rbtree_node_t));
if (njs_slow_path(rb_parse_node == NULL)) {
return NJS_ERROR;
njs_parser_node_t *node;
njs_parser_node_t *target;
njs_parser_scope_t *scope;
+ njs_parser_scope_t *persistent_scope;
njs_rbtree_t labels;
njs_variable_type_t var_type;
njs_int_t ret;
uint8_t allow_in;
uint8_t module;
+ uint8_t persistent_global;
njs_str_t file;
uint32_t line;
intptr_t njs_parser_scope_rbtree_compare(njs_rbtree_node_t *node1,
njs_rbtree_node_t *node2);
njs_int_t njs_parser_init(njs_vm_t *vm, njs_parser_t *parser,
- njs_parser_scope_t *scope, njs_str_t *file, u_char *start, u_char *end);
+ njs_parser_scope_t *scope, njs_bool_t persistent_global, njs_str_t *file,
+ u_char *start, u_char *end);
void njs_parser_destroy(njs_parser_t *parser);
njs_int_t njs_parser(njs_vm_t *vm, njs_parser_t *parser);
njs_parser_scope_t *scope);
static njs_parser_scope_t *njs_variable_scope_find(njs_parser_t *parser,
njs_parser_scope_t *scope, uintptr_t atom_id, njs_variable_type_t type);
-static njs_variable_t *njs_variable_alloc(njs_vm_t *vm, uintptr_t atom_id,
- njs_variable_type_t type);
+static njs_variable_t *njs_variable_alloc(njs_vm_t *vm, njs_mp_t *mem_pool,
+ uintptr_t atom_id, njs_variable_type_t type);
njs_variable_t *
njs_variable_scope_function_add(njs_parser_t *parser, njs_parser_scope_t *scope)
{
if (scope->declarations == NULL) {
- scope->declarations = njs_arr_create(parser->vm->mem_pool, 1,
+ scope->declarations = njs_arr_create(parser->mem_pool, 1,
sizeof(njs_declaration_t));
if (njs_slow_path(scope->declarations == NULL)) {
return NULL;
goto failed;
}
- if (var->original->type == NJS_SCOPE_BLOCK) {
+ if (var->original_type == NJS_SCOPE_BLOCK) {
if (type == NJS_VARIABLE_FUNCTION
|| var->type == NJS_VARIABLE_FUNCTION)
{
- if (var->original == root) {
+ if (var->original != NULL && var->original == root) {
goto failed;
}
}
njs_parser_scope_t *original, uintptr_t atom_id,
njs_variable_type_t type, njs_index_t index)
{
+ njs_mp_t *mem_pool;
njs_variable_t *var;
njs_rbtree_node_t *node;
njs_parser_scope_t *root;
return ((njs_variable_node_t *) node)->variable;
}
- var = njs_variable_alloc(parser->vm, atom_id, type);
+ mem_pool = (scope == parser->persistent_scope) ? parser->vm->mem_pool
+ : parser->mem_pool;
+
+ var = njs_variable_alloc(parser->vm, mem_pool, atom_id, type);
if (njs_slow_path(var == NULL)) {
goto memory_error;
}
var->scope = scope;
var->index = index;
var->original = original;
+ var->original_type = original->type;
if (index == NJS_INDEX_NONE) {
root = njs_function_scope(scope);
root->items++;
}
- var_node_new = njs_variable_node_alloc(parser->vm, var, atom_id);
+ var_node_new = njs_variable_node_alloc(mem_pool, var, atom_id);
if (njs_slow_path(var_node_new == NULL)) {
goto memory_error;
}
static njs_index_t
-njs_variable_closure(njs_vm_t *vm, njs_variable_t *var,
+njs_variable_closure(njs_vm_t *vm, njs_mp_t *mem_pool, njs_variable_t *var,
njs_parser_scope_t *scope)
{
njs_index_t index, prev_index, *idx;
if (parse_node == NULL) {
/* Create new reference for closure. */
- parse_node = njs_mp_alloc(vm->mem_pool,
+ parse_node = njs_mp_alloc(mem_pool,
sizeof(njs_parser_rbtree_node_t));
if (njs_slow_path(parse_node == NULL)) {
return NJS_INDEX_ERROR;
njs_variable_t *
-njs_variable_reference(njs_vm_t *vm, njs_parser_node_t *node)
+njs_variable_reference(njs_vm_t *vm, njs_mp_t *mem_pool,
+ njs_parser_node_t *node)
{
njs_bool_t closure;
njs_rbtree_node_t *rb_node;
ref->variable->closure = closure;
- node->index = njs_variable_closure(vm, ref->variable, scope);
+ node->index = njs_variable_closure(vm, mem_pool, ref->variable, scope);
if (njs_slow_path(node->index == NJS_INDEX_ERROR)) {
return NULL;
}
static njs_variable_t *
-njs_variable_alloc(njs_vm_t *vm, uintptr_t atom_id, njs_variable_type_t type)
+njs_variable_alloc(njs_vm_t *vm, njs_mp_t *mem_pool, uintptr_t atom_id,
+ njs_variable_type_t type)
{
njs_variable_t *var;
- var = njs_mp_zalloc(vm->mem_pool, sizeof(njs_variable_t));
+ var = njs_mp_zalloc(mem_pool, sizeof(njs_variable_t));
if (njs_slow_path(var == NULL)) {
njs_memory_error(vm);
return NULL;
uint8_t self;
uint8_t init;
uint8_t closure;
+ njs_scope_t original_type:8;
njs_parser_scope_t *scope;
njs_parser_scope_t *original;
njs_int_t njs_label_add(njs_parser_t *parser, uintptr_t atom_id);
njs_bool_t njs_label_find(njs_parser_t *parser, uintptr_t atom_id);
njs_int_t njs_label_remove(njs_parser_t *parser, uintptr_t atom_id);
-njs_variable_t *njs_variable_reference(njs_vm_t *vm, njs_parser_node_t *node);
+njs_variable_t *njs_variable_reference(njs_vm_t *vm, njs_mp_t *mem_pool,
+ njs_parser_node_t *node);
njs_variable_t *njs_variable_scope_add(njs_parser_t *parser,
njs_parser_scope_t *scope, njs_parser_scope_t *original,
uintptr_t atom_id, njs_variable_type_t type, njs_index_t index);
njs_inline njs_variable_node_t *
-njs_variable_node_alloc(njs_vm_t *vm, njs_variable_t *var, uintptr_t key)
+njs_variable_node_alloc(njs_mp_t *mem_pool, njs_variable_t *var, uintptr_t key)
{
njs_variable_node_t *node;
- node = njs_mp_zalloc(vm->mem_pool, sizeof(njs_variable_node_t));
+ node = njs_mp_zalloc(mem_pool, sizeof(njs_variable_node_t));
if (njs_fast_path(node != NULL)) {
node->key = key;
global_items = (vm->global_scope != NULL) ? vm->global_scope->items : 0;
- ret = njs_parser_init(vm, &parser, vm->global_scope, &vm->options.file,
- *start, end);
+ ret = njs_parser_init(vm, &parser, vm->global_scope, 1,
+ &vm->options.file, *start, end);
if (njs_slow_path(ret != NJS_OK)) {
return NJS_ERROR;
}
return NULL;
}
- ret = njs_parser_init(vm, &parser, NULL, &module->name, *start, end);
+ ret = njs_parser_init(vm, &parser, NULL, 0, &module->name, *start, end);
if (njs_slow_path(ret != NJS_OK)) {
return NULL;
}
"sum(2, 4);"),
njs_str("6") },
+ { njs_str("(new Function('a',"
+ " 'return function(b) { return function(c) {"
+ " return a + b + c; }; };'))(1)(2)(3)"),
+ njs_str("6") },
+
{ njs_str("var sum = new Function('a, b', 'c', 'return a + b + c');"
"sum(2, 4, 4);"),
njs_str("10") },