}
+njs_inline njs_parser_node_t *
+njs_generate_wrapped_node(njs_parser_node_t *node)
+{
+ njs_assert(node->token_type == NJS_TOKEN_OBJECT_VALUE
+ || node->token_type == NJS_TOKEN_OPTIONAL_PRESERVE);
+
+ return node->u.object;
+}
+
+
+njs_inline njs_parser_node_t *
+njs_generate_object_value_parent(njs_parser_node_t *node)
+{
+ njs_assert(node->token_type == NJS_TOKEN_OBJECT_VALUE);
+
+ return njs_generate_wrapped_node(node);
+}
+
+
+njs_inline njs_bool_t
+njs_generate_is_object_literal_value(njs_parser_node_t *node)
+{
+ return node != NULL
+ && node->token_type == NJS_TOKEN_OBJECT_VALUE
+ && njs_generate_object_value_parent(node)->token_type
+ == NJS_TOKEN_OBJECT;
+}
+
+
njs_inline njs_parser_node_t *
njs_generate_optional_method_call_preserve(njs_parser_node_t *node)
{
+ njs_assert(node->token_type == NJS_TOKEN_METHOD_CALL);
+
return node->u.object;
}
}
+njs_inline njs_parser_node_t *
+njs_generate_optional_method_call_base(njs_parser_node_t *node)
+{
+ njs_parser_node_t *preserve;
+
+ preserve = njs_generate_optional_method_call_preserve(node);
+
+ return (preserve != NULL) ? preserve->left : NULL;
+}
+
+
+njs_inline njs_parser_node_t *
+njs_generate_optional_method_call_key(njs_parser_node_t *node)
+{
+ njs_parser_node_t *preserve;
+
+ preserve = njs_generate_optional_method_call_preserve(node);
+
+ return (preserve != NULL) ? preserve->right : NULL;
+}
+
+
njs_inline njs_parser_node_t *
njs_generate_optional_chain_preserve(njs_parser_node_t *node)
{
+ njs_assert(node->token_type == NJS_TOKEN_OPTIONAL_CHAIN);
+
return node->u.object;
}
njs_inline njs_parser_node_t *
njs_generate_function_call_this(njs_parser_node_t *node)
{
+ njs_assert(node->token_type == NJS_TOKEN_FUNCTION_CALL);
+
return node->u.object;
}
return njs_generator_stack_pop(vm, generator, NULL);
case NJS_TOKEN_OBJECT_VALUE:
- node->index = node->u.object->index;
+ case NJS_TOKEN_OPTIONAL_PRESERVE:
+ node->index = njs_generate_wrapped_node(node)->index;
return njs_generator_stack_pop(vm, generator, NULL);
case NJS_TOKEN_OBJECT:
case NJS_TOKEN_PROPERTY_INIT:
if ((object->token_type == NJS_TOKEN_OBJECT
- || (object->token_type == NJS_TOKEN_OBJECT_VALUE
- && object->u.object->token_type == NJS_TOKEN_OBJECT))
+ || njs_generate_is_object_literal_value(object))
&& (expr->token_type == NJS_TOKEN_FUNCTION
|| expr->token_type == NJS_TOKEN_FUNCTION_EXPRESSION
|| expr->token_type == NJS_TOKEN_ASYNC_FUNCTION_EXPRESSION))
{
njs_parser_node_t *preserve;
- if (node == NULL
- || node->token_type != NJS_TOKEN_METHOD_CALL
- || node->u.object == NULL)
- {
+ if (node == NULL || node->token_type != NJS_TOKEN_METHOD_CALL) {
+ return NULL;
+ }
+
+ preserve = njs_generate_optional_method_call_preserve(node);
+ if (preserve == NULL) {
return NULL;
}
return NULL;
}
- preserve = njs_generate_optional_method_call_preserve(node);
-
if (preserve->left == NULL || preserve->right == NULL) {
njs_internal_error(vm, "unexpected optional method call state");
return NULL;
call = njs_generate_optional_method_call(vm, node->right);
if (call != NULL) {
- preserve = njs_generate_optional_method_call_preserve(call)->left;
+ preserve = njs_generate_optional_method_call_base(call);
if (njs_generate_is_property_lvalue(preserve)) {
preserve->hoist = 1;
call = njs_generate_optional_method_call(vm, node->right);
if (call != NULL) {
prop = njs_generate_optional_method_call_property(call);
- prop->left->index = njs_generate_optional_method_call_preserve(call)
- ->left->index;
- prop->right->index = njs_generate_optional_method_call_preserve(call)
- ->right->index;
+ prop->left->index = njs_generate_optional_method_call_base(call)
+ ->index;
+ prop->right->index = njs_generate_optional_method_call_key(call)
+ ->index;
} else if (njs_generate_optional_chain_preserve(node) != NULL) {
njs_generate_optional_chain_preserve(node)->index = node->left->index;
call = njs_generate_optional_method_call(vm, node->right);
if (call != NULL) {
- preserve = njs_generate_optional_method_call_preserve(call)->left;
+ preserve = njs_generate_optional_method_call_base(call);
if (!njs_generate_is_property_lvalue(preserve)) {
preserve = NULL;
}
njs_lexer_token_t *token, njs_queue_link_t *current);
static njs_int_t njs_parser_object_literal_after(njs_parser_t *parser,
njs_lexer_token_t *token, njs_queue_link_t *current);
+static njs_parser_node_t *njs_parser_object_value(njs_parser_t *parser,
+ njs_parser_node_t *parent, uint32_t token_line);
static njs_int_t njs_parser_property_definition_list(njs_parser_t *parser,
njs_lexer_token_t *token, njs_queue_link_t *current);
static njs_int_t njs_parser_property_definition_list_after(
njs_parser_node_t *node);
static njs_parser_node_t *njs_parser_optional_chain_call_this(
njs_parser_node_t *node);
+static void njs_parser_set_call_this(njs_parser_node_t *node,
+ njs_parser_node_t *this_object);
+static void njs_parser_set_optional_method_call_preserve(
+ njs_parser_node_t *node, njs_parser_node_t *preserve);
static njs_parser_node_t *njs_parser_optional_chain_target_property(
njs_parser_node_t *node);
static njs_parser_node_t *njs_parser_optional_chain_method_call(
{
njs_parser_node_t *ref;
- ref = njs_parser_node_new(parser, NJS_TOKEN_OBJECT_VALUE);
+ ref = njs_parser_node_new(parser, NJS_TOKEN_OPTIONAL_PRESERVE);
if (ref == NULL) {
return NULL;
}
}
+static void
+njs_parser_set_optional_chain_preserve(njs_parser_node_t *node,
+ njs_parser_node_t *preserve)
+{
+ njs_assert(node->token_type == NJS_TOKEN_OPTIONAL_CHAIN);
+ njs_assert(preserve->token_type == NJS_TOKEN_OPTIONAL_PRESERVE);
+
+ node->u.object = preserve;
+}
+
+
static njs_parser_node_t *
njs_parser_optional_chain_source(njs_parser_node_t *node)
{
- if (node != NULL && node->token_type == NJS_TOKEN_OBJECT_VALUE) {
+ if (node != NULL && node->token_type == NJS_TOKEN_OPTIONAL_PRESERVE) {
return node->u.object;
}
}
func->ctor = ctor;
- func->u.object = this_object;
+ njs_parser_set_call_this(func, this_object);
return func;
}
}
+static njs_vmcode_t
+njs_parser_optional_chain_receiver_operation(njs_parser_node_t *node)
+{
+ return node->u.operation;
+}
+
+
+static njs_parser_node_t *
+njs_parser_optional_chain_receiver_base(njs_parser_node_t *node)
+{
+ return node->left;
+}
+
+
+static njs_parser_node_t *
+njs_parser_optional_chain_receiver_key(njs_parser_node_t *node)
+{
+ return node->right;
+}
+
+
static njs_parser_node_t *
njs_parser_optional_chain_call_this(njs_parser_node_t *node)
{
receiver = njs_parser_optional_chain_receiver(node);
if (receiver != NULL) {
- return receiver->left;
+ return njs_parser_optional_chain_receiver_base(receiver);
}
return NULL;
}
+static void
+njs_parser_set_call_this(njs_parser_node_t *node,
+ njs_parser_node_t *this_object)
+{
+ njs_assert(node->token_type == NJS_TOKEN_FUNCTION_CALL);
+
+ node->u.object = this_object;
+}
+
+
+static void
+njs_parser_set_optional_method_call_preserve(njs_parser_node_t *node,
+ njs_parser_node_t *preserve)
+{
+ njs_assert(node->token_type == NJS_TOKEN_METHOD_CALL);
+ njs_assert(njs_parser_call_receiver(preserve) != NULL);
+
+ node->u.object = preserve;
+}
+
+
static njs_parser_node_t *
njs_parser_optional_chain_target_property(njs_parser_node_t *node)
{
return NULL;
}
- prop->u.operation = src->u.operation;
+ prop->u.operation = njs_parser_optional_chain_receiver_operation(src);
prop->token_line = token_line;
- prop->left = src->left;
- prop->right = src->right;
+ prop->left = njs_parser_optional_chain_receiver_base(src);
+ prop->right = njs_parser_optional_chain_receiver_key(src);
func = njs_parser_create_call(parser, prop, 0);
if (func == NULL) {
return NULL;
}
- func->u.object = src;
+ njs_parser_set_optional_method_call_preserve(func, src);
return func;
}
return NJS_ERROR;
}
- opt->u.object = ref;
+ njs_parser_set_optional_chain_preserve(opt, ref);
parser->node = ref;
njs_parser_next(parser, njs_parser_optional_chain);
}
+static njs_parser_node_t *
+njs_parser_object_value(njs_parser_t *parser, njs_parser_node_t *parent,
+ uint32_t token_line)
+{
+ njs_parser_node_t *object;
+
+ njs_assert(parent->token_type == NJS_TOKEN_OBJECT
+ || parent->token_type == NJS_TOKEN_ARRAY);
+
+ object = njs_parser_node_new(parser, NJS_TOKEN_OBJECT_VALUE);
+ if (njs_slow_path(object == NULL)) {
+ return NULL;
+ }
+
+ object->token_line = token_line;
+ object->u.object = parent;
+
+ return object;
+}
+
+
static njs_parser_node_t *
njs_parser_argument(njs_parser_t *parser, njs_parser_node_t *expr,
njs_index_t index)
njs_token_type_t type;
njs_parser_node_t *stmt, *assign, *object, *propref;
- object = njs_parser_node_new(parser, NJS_TOKEN_OBJECT_VALUE);
+ object = njs_parser_object_value(parser, parent, value->token_line);
if (njs_slow_path(object == NULL)) {
return NJS_TOKEN_ERROR;
}
- object->token_line = value->token_line;
- object->u.object = parent;
-
type = proto_init ? NJS_TOKEN_PROTO_INIT : NJS_TOKEN_PROPERTY_INIT;
propref = njs_parser_node_new(parser, type);
{
njs_parser_node_t *node, *stmt, *object, *propref;
- object = njs_parser_node_new(parser, NJS_TOKEN_OBJECT_VALUE);
+ object = njs_parser_object_value(parser, parent, value->token_line);
if (njs_slow_path(object == NULL)) {
return NJS_TOKEN_ERROR;
}
- object->token_line = value->token_line;
- object->u.object = parent;
-
propref = njs_parser_node_new(parser, 0);
if (njs_slow_path(propref == NULL)) {
return NJS_ERROR;
njs_token_serialize(NJS_TOKEN_NAME);
njs_token_serialize(NJS_TOKEN_OBJECT);
njs_token_serialize(NJS_TOKEN_OBJECT_VALUE);
+ njs_token_serialize(NJS_TOKEN_OPTIONAL_PRESERVE);
njs_token_serialize(NJS_TOKEN_ARRAY);
njs_token_serialize(NJS_TOKEN_REGEXP);