Skip to content

Instantly share code, notes, and snippets.

@lexborisov
Created September 24, 2021 16:10
Show Gist options
  • Save lexborisov/08dbde3d79f330b082fe1f3049212920 to your computer and use it in GitHub Desktop.
Save lexborisov/08dbde3d79f330b082fe1f3049212920 to your computer and use it in GitHub Desktop.
# HG changeset patch
# User Alexander Borisov <alexander.borisov@nginx.com>
# Date 1632499826 -10800
# Fri Sep 24 19:10:26 2021 +0300
# Node ID 53c99c659d82d35e9b21d56c27954652fe404e51
# Parent 6feba0e602eeaa963aaf878dc6aa84b8ce2a668e
Added default values support for function arguments.
diff -r 6feba0e602ee -r 53c99c659d82 src/njs_disassembler.c
--- a/src/njs_disassembler.c Fri Sep 17 18:29:40 2021 +0000
+++ b/src/njs_disassembler.c Fri Sep 24 19:10:26 2021 +0300
@@ -159,6 +159,9 @@ static njs_code_name_t code_names[] = {
{ NJS_VMCODE_AWAIT, sizeof(njs_vmcode_await_t),
njs_str("AWAIT ") },
+
+ { NJS_VMCODE_DEFAULT_ARG, sizeof(njs_vmcode_default_arg_t),
+ njs_str("DEFAULT ARGUMENT") },
};
diff -r 6feba0e602ee -r 53c99c659d82 src/njs_function.c
--- a/src/njs_function.c Fri Sep 17 18:29:40 2021 +0000
+++ b/src/njs_function.c Fri Sep 24 19:10:26 2021 +0300
@@ -1294,7 +1294,12 @@ njs_function_instance_length(njs_vm_t *v
function = (njs_function_t *) proto;
- njs_set_number(retval, function->args_count);
+ if (function->first_default != 0) {
+ njs_set_number(retval, function->first_default - 1);
+
+ } else {
+ njs_set_number(retval, function->args_count);
+ }
return NJS_OK;
}
diff -r 6feba0e602ee -r 53c99c659d82 src/njs_function.h
--- a/src/njs_function.h Fri Sep 17 18:29:40 2021 +0000
+++ b/src/njs_function.h Fri Sep 24 19:10:26 2021 +0300
@@ -20,6 +20,7 @@ struct njs_function_lambda_s {
njs_index_t self;
uint32_t nargs;
+ uint32_t first_default;
uint8_t ctor; /* 1 bit */
uint8_t rest_parameters; /* 1 bit */
diff -r 6feba0e602ee -r 53c99c659d82 src/njs_generator.c
--- a/src/njs_generator.c Fri Sep 17 18:29:40 2021 +0000
+++ b/src/njs_generator.c Fri Sep 24 19:10:26 2021 +0300
@@ -281,7 +281,9 @@ static njs_int_t njs_generate_function_s
const njs_str_t *name, njs_uint_t depth);
static njs_int_t njs_generate_scope_end(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
-static int64_t njs_generate_lambda_variables(njs_vm_t *vm,
+static njs_int_t njs_generate_lambda_variables(njs_vm_t *vm,
+ njs_generator_t *generator, njs_parser_node_t *node);
+static njs_int_t njs_generate_lambda_variables_end(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
static njs_int_t njs_generate_return_statement(njs_vm_t *vm,
njs_generator_t *generator, njs_parser_node_t *node);
@@ -862,6 +864,11 @@ njs_generate_name(njs_vm_t *vm, njs_gene
NJS_VMCODE_NOT_INITIALIZED, 1, node);
variable->dst = node->index;
}
+
+ } else if (var->argument && var->scope->in_args) {
+ njs_generate_code(generator, njs_vmcode_variable_t, variable,
+ NJS_VMCODE_NOT_INITIALIZED, 1, node);
+ variable->dst = node->index;
}
return njs_generator_stack_pop(vm, generator, NULL);
@@ -1881,7 +1888,7 @@ njs_generate_for_resolve_closure_cb(njs_
njs_variable_t *var;
if (node->token_type == NJS_TOKEN_NAME) {
- var = njs_variable_resolve(vm, node);
+ var = njs_variable_resolve(vm, node, node->scope);
if (njs_fast_path(var != NULL)) {
closure = njs_variable_closure_test(node->scope, var->scope);
@@ -3609,6 +3616,7 @@ njs_generate_function_declaration(njs_vm
function->global = njs_function_scope(var->scope)->type == NJS_SCOPE_GLOBAL;
function->object.shared = 1;
function->args_count = lambda->nargs - lambda->rest_parameters;
+ function->first_default = lambda->first_default;
njs_set_function(&var->value, function);
@@ -3637,6 +3645,8 @@ njs_generate_function_scope(njs_vm_t *vm
node = node->right;
+ node->scope->lambda = lambda;
+
code = njs_generate_scope(vm, &generator, node->scope, name);
if (njs_slow_path(code == NULL)) {
if (!njs_is_error(&vm->retval)) {
@@ -3672,7 +3682,6 @@ njs_generate_scope(njs_vm_t *vm, njs_gen
njs_parser_scope_t *scope, const njs_str_t *name)
{
u_char *p;
- int64_t nargs;
njs_int_t ret;
njs_uint_t index;
njs_vm_code_t *code;
@@ -3688,11 +3697,6 @@ njs_generate_scope(njs_vm_t *vm, njs_gen
generator->code_start = p;
generator->code_end = p;
- nargs = njs_generate_lambda_variables(vm, generator, scope->top);
- if (njs_slow_path(nargs < NJS_OK)) {
- return NULL;
- }
-
if (vm->codes == NULL) {
vm->codes = njs_arr_create(vm->mem_pool, 4, sizeof(njs_vm_code_t));
if (njs_slow_path(vm->codes == NULL)) {
@@ -3727,10 +3731,10 @@ njs_generate_scope(njs_vm_t *vm, njs_gen
scope->closures = generator->closures;
+ njs_generator_next(generator, njs_generate_lambda_variables, scope->top);
+
njs_queue_init(&generator->stack);
- njs_generator_next(generator, njs_generate, scope->top);
-
ret = njs_generator_after(vm, generator,
njs_queue_first(&generator->stack), NULL,
njs_generate_scope_end, NULL, 0);
@@ -3738,6 +3742,13 @@ njs_generate_scope(njs_vm_t *vm, njs_gen
return NULL;
}
+ ret = njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack), scope->top,
+ njs_generate, NULL, 0);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NULL;
+ }
+
do {
ret = generator->state(vm, generator, generator->node);
if (njs_slow_path(ret != NJS_OK)) {
@@ -3767,18 +3778,15 @@ njs_generate_scope_end(njs_vm_t *vm, njs
}
-static int64_t
+static njs_int_t
njs_generate_lambda_variables(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
{
- int64_t nargs;
njs_variable_t *var;
njs_rbtree_node_t *rb_node;
njs_variable_node_t *var_node;
njs_vmcode_arguments_t *arguments;
- nargs = 0;
-
rb_node = njs_rbtree_min(&node->scope->variables);
while (njs_rbtree_is_there_successor(&node->scope->variables, rb_node)) {
@@ -3789,10 +3797,6 @@ njs_generate_lambda_variables(njs_vm_t *
break;
}
- if (var->argument) {
- nargs++;
- }
-
if (var->arguments_object) {
njs_generate_code(generator, njs_vmcode_arguments_t, arguments,
NJS_VMCODE_ARGUMENTS, 1, NULL);
@@ -3802,7 +3806,82 @@ njs_generate_lambda_variables(njs_vm_t *
rb_node = njs_rbtree_node_successor(&node->scope->variables, rb_node);
}
- return nargs;
+ node = node->scope->arguments;
+
+ if (node == NULL) {
+ return njs_generator_stack_pop(vm, generator, NULL);
+ }
+
+ return njs_generate_lambda_variables_end(vm, generator, node);
+}
+
+
+static njs_int_t
+njs_generate_lambda_variables_end(njs_vm_t *vm, njs_generator_t *generator,
+ njs_parser_node_t *node)
+{
+ njs_variable_t *var;
+ njs_vmcode_move_t *move;
+ njs_parser_node_t *left;
+ njs_parser_scope_t *scope;
+ njs_vmcode_default_arg_t *default_arg;
+
+ if (generator->context != NULL) {
+ left = generator->context;
+ scope = left->scope;
+
+ scope->in_args = 0;
+
+ var = njs_variable_reference(vm, left);
+ if (njs_slow_path(var == NULL)) {
+ return NJS_ERROR;
+ }
+
+ var->init = 1;
+
+ njs_generate_code_move(generator, move, var->index, left->right->index,
+ left);
+
+ default_arg = njs_code_ptr(generator, njs_vmcode_default_arg_t,
+ scope->default_arg);
+
+ default_arg->src = var->index;
+ default_arg->offset = njs_code_offset(generator, generator->code_end)
+ - scope->default_arg;
+ } else {
+ scope = node->scope;
+ }
+
+ while (node != NULL) {
+ if (node->right != NULL) {
+ scope->default_arg = njs_code_offset(generator,
+ generator->code_end);
+
+ scope->in_args = 1;
+
+ njs_generate_code(generator, njs_vmcode_default_arg_t, default_arg,
+ NJS_VMCODE_DEFAULT_ARG, 0, node->right);
+
+ njs_generator_next(generator, njs_generate, node->right);
+
+ return njs_generator_after(vm, generator,
+ njs_queue_first(&generator->stack),
+ node->left,
+ njs_generate_lambda_variables_end,
+ node, 0);
+ }
+
+ var = njs_variable_reference(vm, node);
+ if (njs_slow_path(var == NULL)) {
+ return NJS_ERROR;
+ }
+
+ var->init = 1;
+
+ node = node->left;
+ }
+
+ return njs_generator_stack_pop(vm, generator, NULL);
}
diff -r 6feba0e602ee -r 53c99c659d82 src/njs_parser.c
--- a/src/njs_parser.c Fri Sep 17 18:29:40 2021 +0000
+++ b/src/njs_parser.c Fri Sep 24 19:10:26 2021 +0300
@@ -399,6 +399,8 @@ static njs_int_t njs_parser_formal_param
njs_lexer_token_t *token, njs_queue_link_t *current);
static njs_int_t njs_parser_formal_parameters_after(njs_parser_t *parser,
njs_lexer_token_t *token, njs_queue_link_t *current);
+static njs_int_t njs_parser_formal_parameters_def_after(njs_parser_t *parser,
+ njs_lexer_token_t *token, njs_queue_link_t *current);
static njs_int_t njs_parser_arrow_function(njs_parser_t *parser,
njs_lexer_token_t *token, njs_queue_link_t *current);
@@ -4259,7 +4261,9 @@ static njs_int_t
njs_parser_match_arrow_expression(njs_parser_t *parser,
njs_lexer_token_t *token)
{
- njs_bool_t rest_parameters;
+ njs_arr_t *stack;
+ njs_bool_t rest_parameters;
+ njs_token_type_t *type, need;
if (token->type == NJS_TOKEN_ASYNC) {
token = njs_lexer_peek_token(parser->lexer, token, 1);
@@ -4275,6 +4279,7 @@ njs_parser_match_arrow_expression(njs_pa
}
if (njs_lexer_token_is_binding_identifier(token)) {
+ stack = NULL;
goto arrow;
}
@@ -4283,8 +4288,15 @@ njs_parser_match_arrow_expression(njs_pa
return NJS_ERROR;
}
+ stack = njs_arr_create(parser->vm->mem_pool, 32, sizeof(njs_token_type_t));
+ if (njs_slow_path(stack == NULL)) {
+ return NJS_ERROR;
+ }
+
rest_parameters = 0;
+again:
+
while (token->type != NJS_TOKEN_CLOSE_PARENTHESIS) {
if (rest_parameters) {
@@ -4314,11 +4326,75 @@ njs_parser_match_arrow_expression(njs_pa
if (token == NULL) {
return NJS_ERROR;
}
+
+ } else if (token->type == NJS_TOKEN_ASSIGNMENT) {
+ do {
+ token = njs_lexer_peek_token(parser->lexer, token, 0);
+ if (token == NULL) {
+ return NJS_ERROR;
+ }
+
+ switch (token->type) {
+ case NJS_TOKEN_OPEN_BRACE:
+ need = NJS_TOKEN_CLOSE_BRACE;
+ break;
+
+ case NJS_TOKEN_OPEN_BRACKET:
+ need = NJS_TOKEN_CLOSE_BRACKET;
+ break;
+
+ case NJS_TOKEN_OPEN_PARENTHESIS:
+ need = NJS_TOKEN_CLOSE_PARENTHESIS;
+ break;
+
+ case NJS_TOKEN_COMMA:
+ if (njs_arr_is_empty(stack)) {
+ token = njs_lexer_peek_token(parser->lexer, token, 0);
+ if (token == NULL) {
+ return NJS_ERROR;
+ }
+
+ goto again;
+ }
+
+ continue;
+
+ case NJS_TOKEN_CLOSE_PARENTHESIS:
+ if (njs_arr_is_empty(stack)) {
+ goto arrow;
+ }
+
+ /* Fall through. */
+
+ default:
+ if (!njs_arr_is_empty(stack)) {
+ type = njs_arr_last(stack);
+
+ if (*type == token->type) {
+ (void) njs_arr_remove_last(stack);
+ }
+ }
+
+ continue;
+ }
+
+ type = njs_arr_add(stack);
+ if (njs_slow_path(type == NULL)) {
+ return NJS_ERROR;
+ }
+
+ *type = need;
+
+ } while (1);
}
}
arrow:
+ if (stack != NULL) {
+ njs_arr_destroy(stack);
+ }
+
token = njs_lexer_peek_token(parser->lexer, token, 1);
if (token == NULL) {
return NJS_ERROR;
@@ -6921,8 +6997,10 @@ static njs_int_t
njs_parser_formal_parameters(njs_parser_t *parser, njs_lexer_token_t *token,
njs_queue_link_t *current)
{
+ njs_int_t ret;
njs_variable_t *arg;
njs_rbtree_node_t *rb_node;
+ njs_parser_node_t *node, *name;
njs_variable_node_t var_node;
njs_function_lambda_t *lambda;
@@ -6975,24 +7053,70 @@ njs_parser_formal_parameters(njs_parser_
arg->self = 0;
+ node = njs_parser_node_new(parser, NJS_TOKEN_NAME);
+ if (njs_slow_path(node == NULL)) {
+ return NJS_ERROR;
+ }
+
+ ret = njs_parser_variable_reference(parser, parser->scope, node,
+ token->unique_id,
+ NJS_DECLARATION);
+ if (njs_slow_path(ret != NJS_OK)) {
+ return NJS_ERROR;
+ }
+
} else {
- arg = njs_variable_add(parser, parser->scope,
- token->unique_id, NJS_VARIABLE_VAR);
+ node = njs_parser_variable_node(parser, token->unique_id,
+ NJS_VARIABLE_VAR, &arg);
+ if (njs_slow_path(node == NULL)) {
+ return NJS_ERROR;
+ }
}
if (arg == NULL) {
return NJS_ERROR;
}
+ if (parser->scope->arguments != NULL) {
+ name = parser->scope->arguments;
+
+ while (name->left != NULL) {
+ name = name->left;
+ }
+
+ name->left = node;
+
+ } else {
+ parser->scope->arguments = node;
+ }
+
arg->argument = 1;
lambda->nargs++;
- /* Crutch for temporary storage. */
- parser->node = (njs_parser_node_t *) arg;
-
njs_lexer_consume_token(parser->lexer, 1);
+ token = njs_lexer_token(parser->lexer, 0);
+ if (token == NULL) {
+ return NJS_ERROR;
+ }
+
+ if (token->type == NJS_TOKEN_ASSIGNMENT) {
+ njs_lexer_consume_token(parser->lexer, 1);
+
+ njs_parser_next(parser, njs_parser_assignment_expression);
+
+ parser->node = NULL;
+ node->right = parser->target;
+
+ if (lambda->first_default == 0) {
+ lambda->first_default = lambda->nargs;
+ }
+
+ return njs_parser_after(parser, current, node, 0,
+ njs_parser_formal_parameters_def_after);
+ }
+
njs_parser_next(parser, njs_parser_formal_parameters_after);
break;
}
@@ -7030,6 +7154,26 @@ njs_parser_formal_parameters_after(njs_p
}
+static njs_int_t
+njs_parser_formal_parameters_def_after(njs_parser_t *parser,
+ njs_lexer_token_t *token, njs_queue_link_t *current)
+{
+ njs_parser_node_t *node;
+
+ if (parser->ret != NJS_OK) {
+ return njs_parser_failed(parser);
+ }
+
+ node = parser->target;
+ parser->target = node->right;
+ node->right = parser->node;
+
+ njs_parser_next(parser, njs_parser_formal_parameters_after);
+
+ return NJS_OK;
+}
+
+
/*
* 14.2 Arrow Function Definitions
*
diff -r 6feba0e602ee -r 53c99c659d82 src/njs_parser.h
--- a/src/njs_parser.h Fri Sep 17 18:29:40 2021 +0000
+++ b/src/njs_parser.h Fri Sep 24 19:10:26 2021 +0300
@@ -11,6 +11,7 @@
struct njs_parser_scope_s {
njs_parser_node_t *top;
+ njs_parser_node_t *arguments;
njs_parser_scope_t *parent;
njs_rbtree_t variables;
@@ -20,8 +21,12 @@ struct njs_parser_scope_s {
njs_arr_t *closures;
njs_arr_t *declarations;
+ njs_function_lambda_t *lambda;
+ njs_jump_off_t default_arg;
+
uint32_t temp;
uint32_t items;
+ uint32_t nargs;
njs_str_t cwd;
njs_str_t file;
@@ -119,7 +124,8 @@ njs_int_t njs_parser_module_lambda(njs_p
njs_lexer_token_t *token, njs_queue_link_t *current);
njs_bool_t njs_variable_closure_test(njs_parser_scope_t *root,
njs_parser_scope_t *scope);
-njs_variable_t *njs_variable_resolve(njs_vm_t *vm, njs_parser_node_t *node);
+njs_variable_t *njs_variable_resolve(njs_vm_t *vm, njs_parser_node_t *node,
+ njs_parser_scope_t *scope);
njs_index_t njs_variable_index(njs_vm_t *vm, njs_parser_node_t *node);
njs_bool_t njs_parser_has_side_effect(njs_parser_node_t *node);
njs_int_t njs_parser_variable_reference(njs_parser_t *parser,
diff -r 6feba0e602ee -r 53c99c659d82 src/njs_value.h
--- a/src/njs_value.h Fri Sep 17 18:29:40 2021 +0000
+++ b/src/njs_value.h Fri Sep 24 19:10:26 2021 +0300
@@ -268,6 +268,7 @@ struct njs_function_s {
uint8_t args_offset;
uint8_t args_count:4;
+ uint8_t first_default:4;
uint8_t closure_copied:1;
uint8_t native:1;
diff -r 6feba0e602ee -r 53c99c659d82 src/njs_variable.c
--- a/src/njs_variable.c Fri Sep 17 18:29:40 2021 +0000
+++ b/src/njs_variable.c Fri Sep 24 19:10:26 2021 +0300
@@ -406,15 +406,14 @@ njs_variable_closure_test(njs_parser_sco
njs_variable_t *
-njs_variable_resolve(njs_vm_t *vm, njs_parser_node_t *node)
+njs_variable_resolve(njs_vm_t *vm, njs_parser_node_t *node,
+ njs_parser_scope_t *scope)
{
njs_rbtree_node_t *rb_node;
- njs_parser_scope_t *scope;
njs_variable_node_t var_node;
njs_variable_reference_t *ref;
ref = &node->u.reference;
- scope = node->scope;
var_node.key = ref->unique_id;
@@ -529,6 +528,7 @@ njs_variable_t *
njs_variable_reference(njs_vm_t *vm, njs_parser_node_t *node)
{
njs_bool_t closure;
+ njs_variable_t *var;
njs_rbtree_node_t *rb_node;
njs_parser_scope_t *scope;
njs_parser_rbtree_node_t *parse_node, ref_node;
@@ -537,12 +537,28 @@ njs_variable_reference(njs_vm_t *vm, njs
ref = &node->u.reference;
scope = node->scope;
- if (ref->variable == NULL) {
- ref->variable = njs_variable_resolve(vm, node);
+ if (scope->in_args && node->token_type != NJS_TOKEN_THIS
+ && node->token_type != NJS_TOKEN_ARGUMENTS)
+ {
+ var = ref->variable;
+
+ if (var == NULL) {
+ var = njs_variable_resolve(vm, node, scope);
+ if (njs_slow_path(var == NULL)) {
+ goto not_found;
+ }
+
+ if (!var->argument && var->scope == scope) {
+ goto not_found;
+ }
+
+ ref->variable = var;
+ }
+
+ } else if (ref->variable == NULL) {
+ ref->variable = njs_variable_resolve(vm, node, scope);
if (njs_slow_path(ref->variable == NULL)) {
- ref->not_defined = 1;
-
- return NULL;
+ goto not_found;
}
}
@@ -578,6 +594,12 @@ njs_variable_reference(njs_vm_t *vm, njs
}
return ref->variable;
+
+not_found:
+
+ ref->not_defined = 1;
+
+ return NULL;
}
diff -r 6feba0e602ee -r 53c99c659d82 src/njs_vmcode.c
--- a/src/njs_vmcode.c Fri Sep 17 18:29:40 2021 +0000
+++ b/src/njs_vmcode.c Fri Sep 24 19:10:26 2021 +0300
@@ -106,6 +106,7 @@ njs_vmcode_interpreter(njs_vm_t *vm, u_c
njs_vmcode_test_jump_t *test_jump;
njs_vmcode_equal_jump_t *equal;
njs_vmcode_try_return_t *try_return;
+ njs_vmcode_default_arg_t *default_arg;
njs_vmcode_method_frame_t *method_frame;
njs_vmcode_function_copy_t *fcopy;
njs_vmcode_prop_accessor_t *accessor;
@@ -641,6 +642,20 @@ next:
ret = sizeof(njs_vmcode_move_arg_t);
break;
+ case NJS_VMCODE_DEFAULT_ARG:
+ default_arg = (njs_vmcode_default_arg_t *) pc;
+
+ njs_vmcode_operand(vm, default_arg->src, value1);
+
+ if (njs_is_defined(value1)) {
+ ret = default_arg->offset;
+
+ } else {
+ ret = sizeof(njs_vmcode_default_arg_t);
+ }
+
+ break;
+
case NJS_VMCODE_STOP:
njs_vmcode_operand(vm, (njs_index_t) value2, value2);
vm->retval = *value2;
diff -r 6feba0e602ee -r 53c99c659d82 src/njs_vmcode.h
--- a/src/njs_vmcode.h Fri Sep 17 18:29:40 2021 +0000
+++ b/src/njs_vmcode.h Fri Sep 24 19:10:26 2021 +0300
@@ -32,6 +32,7 @@ typedef uint8_t
enum {
NJS_VMCODE_MOVE_ARG = 0,
+ NJS_VMCODE_DEFAULT_ARG,
NJS_VMCODE_STOP,
NJS_VMCODE_JUMP,
NJS_VMCODE_PROPERTY_SET,
@@ -414,6 +415,13 @@ typedef struct {
typedef struct {
njs_vmcode_t code;
+ njs_index_t src;
+ njs_jump_off_t offset;
+} njs_vmcode_default_arg_t;
+
+
+typedef struct {
+ njs_vmcode_t code;
njs_value_t *function;
njs_index_t retval;
} njs_vmcode_function_copy_t;
diff -r 6feba0e602ee -r 53c99c659d82 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Fri Sep 17 18:29:40 2021 +0000
+++ b/src/test/njs_unit_test.c Fri Sep 24 19:10:26 2021 +0300
@@ -20532,6 +20532,77 @@ static njs_unit_test_t njs_test[] =
{ njs_str("let name = 'af', x = {async [name]() {await Promise.resolve(1)}}; x.af"),
njs_str("[object AsyncFunction]") },
+
+ /* Default arguments in functions. */
+
+ { njs_str("function abc(a = 1, b = 2, c = 3) {return a + b + c} abc()"),
+ njs_str("6") },
+
+ { njs_str("function abc(a = 1, b = a + 2, c = b + 3) {return a + b + c} abc()"),
+ njs_str("10") },
+
+ { njs_str("function abc(a = 1, b, c = 3) {return a + b + c} abc(undefined, 10, 5)"),
+ njs_str("16") },
+
+ { njs_str("function abc(a = b, b = 2, c = 3) {return a + b + c} abc()"),
+ njs_str("ReferenceError: cannot access variable before initialization") },
+
+ { njs_str("function abc(a = 1, b, c) {} abc.length"),
+ njs_str("0") },
+
+ { njs_str("function abc(a, b = 2, c) {} abc.length"),
+ njs_str("1") },
+
+ { njs_str("function abc(a, b, c = 3) {} abc.length"),
+ njs_str("2") },
+
+ { njs_str("function abc(a = x) {let x = 1; return a + x} abc()"),
+ njs_str("ReferenceError: \"x\" is not defined") },
+
+ { njs_str("function abc(a = x) {let x = 1; return a + x} abc(1)"),
+ njs_str("2") },
+
+ { njs_str("function abc(a = a) {return a} abc()"),
+ njs_str("ReferenceError: cannot access variable before initialization") },
+
+ { njs_str("function abc(a = a) {return a} abc(1)"),
+ njs_str("1") },
+
+ { njs_str("function abc(a, b = a, c = b) {return a + b + c} abc(1)"),
+ njs_str("3") },
+
+ { njs_str("function abc(a = (() => a)()) {return a} abc()"),
+ njs_str("ReferenceError: cannot access variable before initialization") },
+
+ { njs_str("function abc(a = ((a = 1) => a)()) {return a} abc()"),
+ njs_str("1") },
+
+ { njs_str("let go = function (x = 100, y = 200) {return x + y};"
+ "function abc(a = go(undefined, 10)) {return a} abc()"),
+ njs_str("110") },
+
+ { njs_str("function abc(a = this.x) {return a} abc.call({x: 123})"),
+ njs_str("123") },
+
+ { njs_str("function abc(a, b = arguments[0], c = abc) {return [a, b, c]} abc.call({x: 1}, 1)"),
+ njs_str("1,1,[object Function]") },
+
+ { njs_str("let func = function x(x = 1) {return x}; func()"),
+ njs_str("1") },
+
+ { njs_str("let func = (a = (() => {return 1})(), b = 2) => {return a + b}; func()"),
+ njs_str("3") },
+
+ { njs_str("let func = (a = (async () => 1)()) => {return a}; func()"),
+ njs_str("[object Promise]") },
+
+ { njs_str("let afunc = async () => {let x = await new Promise((r) => r(123)); return x};"
+ "let func = (a = afunc()) => {return a}; func()"),
+ njs_str("[object Promise]") },
+
+ { njs_str("let afunc = async () => {let x = await 1; return x};"
+ "let func = (a = afunc) => {return a}; func()"),
+ njs_str("[object AsyncFunction]") },
};
diff -r 6feba0e602ee -r 53c99c659d82 test/js/async_await_dflt.js
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/js/async_await_dflt.js Fri Sep 24 19:10:26 2021 +0300
@@ -0,0 +1,32 @@
+function pr(x) {
+ return new Promise(resolve => {resolve(x)})
+ .then(v => v).then(v => v);
+}
+
+let stage = [];
+
+async function f() {
+ let sum = 0;
+
+ stage.push(2);
+
+ const a1 = await pr(10);
+
+ stage.push(4);
+
+ const a2 = await pr(20);
+
+ stage.push(5);
+
+ return a1 + a2;
+}
+
+stage.push(1);
+
+function abc(a = f().then(v => {console.log(v, stage.join(", "))})) {
+ return a;
+}
+
+abc().then(v => console.log("end"))
+
+stage.push(3);
diff -r 6feba0e602ee -r 53c99c659d82 test/njs_expect_test.exp
--- a/test/njs_expect_test.exp Fri Sep 17 18:29:40 2021 +0000
+++ b/test/njs_expect_test.exp Fri Sep 24 19:10:26 2021 +0300
@@ -1176,3 +1176,7 @@ njs_run {"./test/js/async_await_try_reso
njs_run {"./test/js/async_await_many_call.js"} \
"\\\['First: SUN MOON','Second: CAT MOUSE','Third: MAN WOMAN']"
+
+njs_run {"./test/js/async_await_dflt.js"} \
+"30 1, 2, 3, 4, 5
+end"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment