From: Dmitry Volyntsev Date: Wed, 4 Mar 2026 04:40:57 +0000 (-0800) Subject: Parser: isolate optional preserve wrapper details. X-Git-Tag: 0.9.7~18 X-Git-Url: http://www.kaiwu.me/postgresql/commit/static/gitweb.js?a=commitdiff_plain;h=f569076f9783c789f8eae7ca0e6e9d73c845ccca;p=njs.git Parser: isolate optional preserve wrapper details. Introduce NJS_TOKEN_OPTIONAL_PRESERVE for optional-chain preserve nodes instead of reusing OBJECT_VALUE, so OBJECT_VALUE remains strictly an object/array literal structure token. Route optional-preserve, object-value, and optional method-preserve access through dedicated helper functions with narrow assertions, removing direct u.object/left/right access from general parser and generator paths. No behavior change. --- diff --git a/src/njs_generator.c b/src/njs_generator.c index 12ccc527..6caea0d5 100644 --- a/src/njs_generator.c +++ b/src/njs_generator.c @@ -124,9 +124,40 @@ njs_generate_is_property_call_source(njs_parser_node_t *node) } +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; } @@ -138,9 +169,33 @@ njs_generate_optional_method_call_property(njs_parser_node_t *node) } +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; } @@ -148,6 +203,8 @@ njs_generate_optional_chain_preserve(njs_parser_node_t *node) 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; } @@ -787,7 +844,8 @@ njs_generate(njs_vm_t *vm, njs_generator_t *generator, njs_parser_node_t *node) 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: @@ -3465,8 +3523,7 @@ njs_generate_assignment_end(njs_vm_t *vm, njs_generator_t *generator, 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)) @@ -4186,10 +4243,12 @@ njs_generate_optional_method_call(njs_vm_t *vm, njs_parser_node_t *node) { 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; } @@ -4198,8 +4257,6 @@ njs_generate_optional_method_call(njs_vm_t *vm, njs_parser_node_t *node) 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; @@ -4225,7 +4282,7 @@ njs_generate_optional_chain(njs_vm_t *vm, njs_generator_t *generator, 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; @@ -4266,10 +4323,10 @@ njs_generate_optional_chain_after(njs_vm_t *vm, njs_generator_t *generator, 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; @@ -4305,7 +4362,7 @@ njs_generate_optional_chain_end(njs_vm_t *vm, njs_generator_t *generator, 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; } diff --git a/src/njs_lexer.h b/src/njs_lexer.h index 5526be6c..98b8dd87 100644 --- a/src/njs_lexer.h +++ b/src/njs_lexer.h @@ -131,6 +131,7 @@ typedef enum { NJS_TOKEN_OBJECT, NJS_TOKEN_OBJECT_VALUE, + NJS_TOKEN_OPTIONAL_PRESERVE, NJS_TOKEN_PROPERTY, NJS_TOKEN_PROPERTY_REF, NJS_TOKEN_PROPERTY_INIT, diff --git a/src/njs_parser.c b/src/njs_parser.c index 5a56f0cd..9177ac26 100644 --- a/src/njs_parser.c +++ b/src/njs_parser.c @@ -48,6 +48,8 @@ static njs_int_t njs_parser_object_literal(njs_parser_t *parser, 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( @@ -107,6 +109,10 @@ static njs_parser_node_t *njs_parser_optional_chain_receiver( 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( @@ -2700,7 +2706,7 @@ njs_parser_optional_chain_preserve(njs_parser_t *parser, { 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; } @@ -2712,10 +2718,21 @@ njs_parser_optional_chain_preserve(njs_parser_t *parser, } +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; } @@ -2769,7 +2786,7 @@ njs_parser_create_call(njs_parser_t *parser, njs_parser_node_t *node, } func->ctor = ctor; - func->u.object = this_object; + njs_parser_set_call_this(func, this_object); return func; } @@ -2819,6 +2836,27 @@ njs_parser_optional_chain_receiver(njs_parser_node_t *node) } +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) { @@ -2826,13 +2864,34 @@ 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) { @@ -2860,17 +2919,17 @@ njs_parser_optional_chain_method_call(njs_parser_t *parser, 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; } @@ -3180,7 +3239,7 @@ njs_parser_optional_expression_after(njs_parser_t *parser, 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); @@ -8726,6 +8785,27 @@ njs_parser_reference(njs_parser_t *parser, njs_lexer_token_t *token) } +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) @@ -8755,14 +8835,11 @@ njs_parser_object_property(njs_parser_t *parser, njs_parser_node_t *parent, 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); @@ -8804,14 +8881,11 @@ njs_parser_property_accessor(njs_parser_t *parser, njs_parser_node_t *parent, { 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; @@ -9778,6 +9852,7 @@ njs_parser_serialize_node(njs_chb_t *chain, njs_parser_node_t *node) 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);